From 61d34c01bc013350bfc7a8522003b683b176a435 Mon Sep 17 00:00:00 2001 From: notgitika Date: Mon, 27 Jul 2026 13:35:36 -0400 Subject: [PATCH 1/3] feat(memory): add read-only memory commands --- README.md | 12 +- src/components/RouterScreen.test.tsx | 2 + src/core/core.test.ts | 3 +- src/core/index.tsx | 2 + src/core/memory.tsx | 30 +++++ src/handlers/index.tsx | 2 + .../GetMemoryCommand.22c108a1a6908216.json | 18 +++ .../GetMemoryCommand.97c5e1b3cd9fa634.json | 18 +++ .../GetMemoryCommand.ed4e49fb82fa7aa2.json | 6 + .../ListMemoriesCommand.62f80383c4837247.json | 15 +++ .../ListMemoriesCommand.7d2e22c637f6b633.json | 16 +++ .../memory/__fixtures__/get.golden.json | 14 ++ .../__fixtures__/list-page-1.golden.json | 12 ++ .../__fixtures__/list-page-2.golden.json | 11 ++ src/handlers/memory/get/index.tsx | 26 ++++ src/handlers/memory/index.tsx | 13 ++ src/handlers/memory/list/index.tsx | 26 ++++ src/handlers/memory/memory.test.tsx | 121 ++++++++++++++++++ src/handlers/memory/types.tsx | 15 +++ src/handlers/root.test.tsx | 1 + src/handlers/types.tsx | 2 + src/testing/TestCoreClient.tsx | 51 ++++++++ src/testing/index.tsx | 1 + 23 files changed, 414 insertions(+), 3 deletions(-) create mode 100644 src/core/memory.tsx create mode 100644 src/handlers/memory/__fixtures__/GetMemoryCommand.22c108a1a6908216.json create mode 100644 src/handlers/memory/__fixtures__/GetMemoryCommand.97c5e1b3cd9fa634.json create mode 100644 src/handlers/memory/__fixtures__/GetMemoryCommand.ed4e49fb82fa7aa2.json create mode 100644 src/handlers/memory/__fixtures__/ListMemoriesCommand.62f80383c4837247.json create mode 100644 src/handlers/memory/__fixtures__/ListMemoriesCommand.7d2e22c637f6b633.json create mode 100644 src/handlers/memory/__fixtures__/get.golden.json create mode 100644 src/handlers/memory/__fixtures__/list-page-1.golden.json create mode 100644 src/handlers/memory/__fixtures__/list-page-2.golden.json create mode 100644 src/handlers/memory/get/index.tsx create mode 100644 src/handlers/memory/index.tsx create mode 100644 src/handlers/memory/list/index.tsx create mode 100644 src/handlers/memory/memory.test.tsx create mode 100644 src/handlers/memory/types.tsx diff --git a/README.md b/README.md index b2a3be481..87850644f 100644 --- a/README.md +++ b/README.md @@ -64,6 +64,9 @@ agentcore # interactive TUI │ └── endpoint │ ├── get # get a Runtime endpoint by qualifier │ └── list # list a Runtime's endpoints +├── memory # inspect AgentCore Memories +│ ├── get # fetch a Memory by id +│ └── list # list Memories (server-side paginated) └── config # read/write global config values ``` @@ -108,6 +111,11 @@ agentcore runtime version list --id --max-results 20 agentcore runtime endpoint get --id --qualifier DEFAULT agentcore runtime endpoint list --id --max-results 20 +# Inspect AgentCore Memories without project configuration or deployment +agentcore memory get --id +agentcore memory get --id --view without_decryption +agentcore memory list --max-results 20 + # Manage API key credential providers agentcore identity api-key-credential-provider create --name my-provider --api-key agentcore identity api-key-credential-provider get --name my-provider @@ -537,8 +545,8 @@ A Husky pre-commit hook runs Prettier (via lint-staged) on staged files automati - **Cover more AgentCore resources.** The harness surface (CRUD, versions, endpoints, invoke, exec) is fully implemented in both the CLI and the TUI; - the same patterns extend naturally to gateways, memory, browser profiles, - and the other control-plane resources. + the same patterns extend naturally to gateways, Memory mutations and + data-plane operations, browser profiles, and the other AgentCore resources. - **Implement `config`.** The `config` command is currently a stub — it should read/write real global settings (telemetry, log level, ...) through an injected config accessor. diff --git a/src/components/RouterScreen.test.tsx b/src/components/RouterScreen.test.tsx index 0fe9c235c..9db945dd8 100644 --- a/src/components/RouterScreen.test.tsx +++ b/src/components/RouterScreen.test.tsx @@ -17,6 +17,8 @@ describe("menu rendering", () => { expect(frame).toContain("manage agentcore harnesses"); expect(frame).toContain("runtime"); expect(frame).toContain("inspect AgentCore Runtimes"); + expect(frame).toContain("memory"); + expect(frame).toContain("manage AgentCore Memories"); expect(frame).toContain("config"); expect(frame).toContain("read/write global config values"); r.unmount(); diff --git a/src/core/core.test.ts b/src/core/core.test.ts index 2c773710a..d93282e2c 100644 --- a/src/core/core.test.ts +++ b/src/core/core.test.ts @@ -86,7 +86,7 @@ test("data() caches independently of control()", () => { expect(dataBuilt).toBe(1); }); -test("exposes a harness sub-client", () => { +test("exposes feature sub-clients", () => { const core = new CoreClient({ createControlClient: fakeControl, createDataClient: fakeData, @@ -94,6 +94,7 @@ test("exposes a harness sub-client", () => { logger: createSilentLogger(), }); expect(core.harness).toBeDefined(); + expect(core.memory).toBeDefined(); }); test("invokeHarness sends an InvokeHarnessCommand on the data client with the abort signal", async () => { diff --git a/src/core/index.tsx b/src/core/index.tsx index b08d01a49..e3f9a5a6f 100644 --- a/src/core/index.tsx +++ b/src/core/index.tsx @@ -3,6 +3,7 @@ import { BedrockAgentCoreClient } from "@aws-sdk/client-bedrock-agentcore"; import { IAMClient } from "@aws-sdk/client-iam"; import { HarnessClient } from "./harness"; import { IdentityClient } from "./identity"; +import { MemoryClient } from "./memory"; import { RuntimeClient } from "./runtime"; import type { AwsClients, @@ -47,6 +48,7 @@ export class CoreClient implements AwsClients { // Feature-scoped sub-clients. Access as e.g. `coreClient.harness.getHarness(...)`. readonly harness: HarnessClient = new HarnessClient(this); readonly identity: IdentityClient = new IdentityClient(this); + readonly memory: MemoryClient = new MemoryClient(this); readonly runtime: RuntimeClient = new RuntimeClient(this); readonly projectManager: ProjectManager; diff --git a/src/core/memory.tsx b/src/core/memory.tsx new file mode 100644 index 000000000..29f1ed2d9 --- /dev/null +++ b/src/core/memory.tsx @@ -0,0 +1,30 @@ +import { + GetMemoryCommand, + ListMemoriesCommand, + type GetMemoryOutput, + type ListMemoriesOutput, + type MemoryView, +} from "@aws-sdk/client-bedrock-agentcore-control"; +import type { CoreMemoryClient } from "../handlers/memory/types"; +import type { AwsClients, CoreOptions } from "./types"; +import { toClientConfig } from "./utils"; + +export class MemoryClient implements CoreMemoryClient { + constructor(private readonly clients: AwsClients) {} + + async getMemory(id: string, view: MemoryView, options: CoreOptions): Promise { + return this.clients + .control(toClientConfig(options)) + .send(new GetMemoryCommand({ memoryId: id, view })); + } + + async listMemories( + nextToken: string | undefined, + maxResults: number | undefined, + options: CoreOptions, + ): Promise { + return this.clients + .control(toClientConfig(options)) + .send(new ListMemoriesCommand({ nextToken, maxResults })); + } +} diff --git a/src/handlers/index.tsx b/src/handlers/index.tsx index 0d5723486..97289d544 100644 --- a/src/handlers/index.tsx +++ b/src/handlers/index.tsx @@ -1,6 +1,7 @@ import { Router } from "../router"; import { createHarnessHandler } from "./harness/index.tsx"; import { createIdentityHandler } from "./identity/index.tsx"; +import { createMemoryHandler } from "./memory/index.tsx"; import { createRuntimeHandler } from "./runtime/index.tsx"; import { DebugKey, EndpointKey, JsonKey, RegionKey } from "./keys.tsx"; import { createConfigHandler } from "./config/"; @@ -43,6 +44,7 @@ export function createRootHandler(core: Core, config: RootHandlerConfig): Router root.handler(createHarnessHandler(core, io)); root.handler(createIdentityHandler(core, io)); root.handler(createRuntimeHandler(core, io)); + root.handler(createMemoryHandler(core, io)); root.handler(createConfigHandler()); root.handler(createProjectHandler({ projectManager: core.projectManager })); diff --git a/src/handlers/memory/__fixtures__/GetMemoryCommand.22c108a1a6908216.json b/src/handlers/memory/__fixtures__/GetMemoryCommand.22c108a1a6908216.json new file mode 100644 index 000000000..b033e6f7b --- /dev/null +++ b/src/handlers/memory/__fixtures__/GetMemoryCommand.22c108a1a6908216.json @@ -0,0 +1,18 @@ +{ + "memory": { + "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_read_only_fixture-AbCd123456", + "id": "agentcore_cli_memory_read_only_fixture-AbCd123456", + "name": "agentcore_cli_memory_read_only_fixture", + "description": "Stable synthetic fixture for AgentCore CLI Memory read-only tests", + "eventExpiryDuration": 30, + "status": "ACTIVE", + "createdAt": { + "$date": "2026-07-20T12:00:00.000Z" + }, + "updatedAt": { + "$date": "2026-07-21T12:00:00.000Z" + }, + "strategies": [], + "indexedKeys": [] + } +} diff --git a/src/handlers/memory/__fixtures__/GetMemoryCommand.97c5e1b3cd9fa634.json b/src/handlers/memory/__fixtures__/GetMemoryCommand.97c5e1b3cd9fa634.json new file mode 100644 index 000000000..b033e6f7b --- /dev/null +++ b/src/handlers/memory/__fixtures__/GetMemoryCommand.97c5e1b3cd9fa634.json @@ -0,0 +1,18 @@ +{ + "memory": { + "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_read_only_fixture-AbCd123456", + "id": "agentcore_cli_memory_read_only_fixture-AbCd123456", + "name": "agentcore_cli_memory_read_only_fixture", + "description": "Stable synthetic fixture for AgentCore CLI Memory read-only tests", + "eventExpiryDuration": 30, + "status": "ACTIVE", + "createdAt": { + "$date": "2026-07-20T12:00:00.000Z" + }, + "updatedAt": { + "$date": "2026-07-21T12:00:00.000Z" + }, + "strategies": [], + "indexedKeys": [] + } +} diff --git a/src/handlers/memory/__fixtures__/GetMemoryCommand.ed4e49fb82fa7aa2.json b/src/handlers/memory/__fixtures__/GetMemoryCommand.ed4e49fb82fa7aa2.json new file mode 100644 index 000000000..f04ebcf76 --- /dev/null +++ b/src/handlers/memory/__fixtures__/GetMemoryCommand.ed4e49fb82fa7aa2.json @@ -0,0 +1,6 @@ +{ + "$error": { + "name": "ResourceNotFoundException", + "message": "Memory missing_memory-0000000000 was not found" + } +} diff --git a/src/handlers/memory/__fixtures__/ListMemoriesCommand.62f80383c4837247.json b/src/handlers/memory/__fixtures__/ListMemoriesCommand.62f80383c4837247.json new file mode 100644 index 000000000..a773bc51e --- /dev/null +++ b/src/handlers/memory/__fixtures__/ListMemoriesCommand.62f80383c4837247.json @@ -0,0 +1,15 @@ +{ + "memories": [ + { + "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_second-EfGh789012", + "id": "agentcore_cli_memory_second-EfGh789012", + "status": "ACTIVE", + "createdAt": { + "$date": "2026-07-22T12:00:00.000Z" + }, + "updatedAt": { + "$date": "2026-07-22T12:30:00.000Z" + } + } + ] +} diff --git a/src/handlers/memory/__fixtures__/ListMemoriesCommand.7d2e22c637f6b633.json b/src/handlers/memory/__fixtures__/ListMemoriesCommand.7d2e22c637f6b633.json new file mode 100644 index 000000000..6ca71c24b --- /dev/null +++ b/src/handlers/memory/__fixtures__/ListMemoriesCommand.7d2e22c637f6b633.json @@ -0,0 +1,16 @@ +{ + "memories": [ + { + "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_read_only_fixture-AbCd123456", + "id": "agentcore_cli_memory_read_only_fixture-AbCd123456", + "status": "ACTIVE", + "createdAt": { + "$date": "2026-07-20T12:00:00.000Z" + }, + "updatedAt": { + "$date": "2026-07-21T12:00:00.000Z" + } + } + ], + "nextToken": "memory-page-2" +} diff --git a/src/handlers/memory/__fixtures__/get.golden.json b/src/handlers/memory/__fixtures__/get.golden.json new file mode 100644 index 000000000..4a733bd02 --- /dev/null +++ b/src/handlers/memory/__fixtures__/get.golden.json @@ -0,0 +1,14 @@ +{ + "memory": { + "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_read_only_fixture-AbCd123456", + "id": "agentcore_cli_memory_read_only_fixture-AbCd123456", + "name": "agentcore_cli_memory_read_only_fixture", + "description": "Stable synthetic fixture for AgentCore CLI Memory read-only tests", + "eventExpiryDuration": 30, + "status": "ACTIVE", + "createdAt": "2026-07-20T12:00:00.000Z", + "updatedAt": "2026-07-21T12:00:00.000Z", + "strategies": [], + "indexedKeys": [] + } +} diff --git a/src/handlers/memory/__fixtures__/list-page-1.golden.json b/src/handlers/memory/__fixtures__/list-page-1.golden.json new file mode 100644 index 000000000..055e67eda --- /dev/null +++ b/src/handlers/memory/__fixtures__/list-page-1.golden.json @@ -0,0 +1,12 @@ +{ + "memories": [ + { + "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_read_only_fixture-AbCd123456", + "id": "agentcore_cli_memory_read_only_fixture-AbCd123456", + "status": "ACTIVE", + "createdAt": "2026-07-20T12:00:00.000Z", + "updatedAt": "2026-07-21T12:00:00.000Z" + } + ], + "nextToken": "memory-page-2" +} diff --git a/src/handlers/memory/__fixtures__/list-page-2.golden.json b/src/handlers/memory/__fixtures__/list-page-2.golden.json new file mode 100644 index 000000000..f57538015 --- /dev/null +++ b/src/handlers/memory/__fixtures__/list-page-2.golden.json @@ -0,0 +1,11 @@ +{ + "memories": [ + { + "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_second-EfGh789012", + "id": "agentcore_cli_memory_second-EfGh789012", + "status": "ACTIVE", + "createdAt": "2026-07-22T12:00:00.000Z", + "updatedAt": "2026-07-22T12:30:00.000Z" + } + ] +} diff --git a/src/handlers/memory/get/index.tsx b/src/handlers/memory/get/index.tsx new file mode 100644 index 000000000..9c591fc02 --- /dev/null +++ b/src/handlers/memory/get/index.tsx @@ -0,0 +1,26 @@ +import z from "zod"; +import { createHandler, flag } from "../../../router"; +import { JsonRendererKey } from "../../../tui"; +import type { Core } from "../../types"; +import { coreOptsFromCtx } from "../../utils"; + +const MEMORY_VIEWS = ["full", "without_decryption"] as const; + +export const createGetMemoryHandler = (core: Core) => + createHandler({ + name: "get", + description: "get an AgentCore Memory", + flags: [ + flag("id", "the ID of the Memory", z.string().optional()), + flag("view", "response view", z.enum(MEMORY_VIEWS).default("full")), + ], + handle: async (ctx, flags) => { + if (!flags.id) { + throw new TypeError("required option '--id ' not specified"); + } + + ctx + .require(JsonRendererKey) + .renderJson(await core.memory.getMemory(flags.id, flags.view, coreOptsFromCtx(ctx))); + }, + }); diff --git a/src/handlers/memory/index.tsx b/src/handlers/memory/index.tsx new file mode 100644 index 000000000..8f11ca8df --- /dev/null +++ b/src/handlers/memory/index.tsx @@ -0,0 +1,13 @@ +import { Router } from "../../router"; +import type { AppIO } from "../../io"; +import type { Core } from "../types"; +import { createHelpDefault } from "../help"; +import { createGetMemoryHandler } from "./get"; +import { createListMemoriesHandler } from "./list"; + +export function createMemoryHandler(core: Core, io: AppIO): Router { + return new Router("memory", "manage AgentCore Memories") + .default(createHelpDefault(io)) + .handler(createGetMemoryHandler(core)) + .handler(createListMemoriesHandler(core)); +} diff --git a/src/handlers/memory/list/index.tsx b/src/handlers/memory/list/index.tsx new file mode 100644 index 000000000..987306467 --- /dev/null +++ b/src/handlers/memory/list/index.tsx @@ -0,0 +1,26 @@ +import z from "zod"; +import { createHandler, flag } from "../../../router"; +import { JsonRendererKey } from "../../../tui"; +import type { Core } from "../../types"; +import { coreOptsFromCtx } from "../../utils"; + +export const createListMemoriesHandler = (core: Core) => + createHandler({ + name: "list", + description: "list AgentCore Memories", + flags: [ + flag("next-token", "pagination token returned by a previous request", z.string().optional()), + flag("max-results", "maximum number of items to return", z.number().optional()), + ], + handle: async (ctx, flags) => { + ctx + .require(JsonRendererKey) + .renderJson( + await core.memory.listMemories( + flags["next-token"], + flags["max-results"], + coreOptsFromCtx(ctx), + ), + ); + }, + }); diff --git a/src/handlers/memory/memory.test.tsx b/src/handlers/memory/memory.test.tsx new file mode 100644 index 000000000..2216812ca --- /dev/null +++ b/src/handlers/memory/memory.test.tsx @@ -0,0 +1,121 @@ +import { describe, expect, test } from "bun:test"; +import { join } from "node:path"; +import { CoreClient } from "../../core"; +import { + createSilentLogger, + fixtureFactories, + matchGolden, + TestGlobalConfigAccessor, + testIO, +} from "../../testing"; +import { createRootHandler } from "../index"; + +const REGION = "us-west-2"; +const FIXTURES = join(import.meta.dir, "__fixtures__"); + +// These credential-free fixtures are synthetic but use the same SDK send-boundary +// replay path as recorded fixtures, so command-to-SDK translation remains covered. +const FIXTURE_MEMORY_ID = "agentcore_cli_memory_read_only_fixture-AbCd123456"; +const MISSING_MEMORY_ID = "missing_memory-0000000000"; + +function createFixtureCore(): CoreClient { + const { createControlClient, createDataClient, createIamClient } = fixtureFactories(FIXTURES); + + return new CoreClient({ + createControlClient, + createDataClient, + createIamClient, + logger: createSilentLogger(), + }); +} + +async function run(args: string[]): Promise { + const io = testIO(); + const root = createRootHandler(createFixtureCore(), { + io: io.io, + logger: createSilentLogger(), + globalConfigAccessor: new TestGlobalConfigAccessor(), + }); + + await root.route(["node", "agentcore", ...args, "--region", REGION]); + return io.stdout(); +} + +describe("memory command hierarchy", () => { + test("registers the Memory read-only command hierarchy", () => { + const root = createRootHandler(createFixtureCore(), { + io: testIO().io, + logger: createSilentLogger(), + globalConfigAccessor: new TestGlobalConfigAccessor(), + }); + const memory = root.children().find((child) => child.name() === "memory"); + + expect(memory?.flags().map((flag) => flag.name)).not.toContain("interactive"); + expect(memory?.children().map((child) => child.name())).toEqual(["get", "list"]); + }); + + test("prints help for bare `memory` without an SDK call", async () => { + const stdout = await run(["memory"]); + + expect(stdout).toContain("Usage: agentcore memory"); + expect(stdout).toContain("Commands:"); + }); +}); + +describe("memory read-only commands", () => { + test("gets a Memory using the full view by default", async () => { + const stdout = await run(["memory", "get", "--id", FIXTURE_MEMORY_ID]); + + matchGolden(FIXTURES, "get.golden.json", stdout); + expect(JSON.parse(stdout).memory.id).toBe(FIXTURE_MEMORY_ID); + }); + + test("accepts the without_decryption view", async () => { + const stdout = await run([ + "memory", + "get", + "--id", + FIXTURE_MEMORY_ID, + "--view", + "without_decryption", + ]); + + matchGolden(FIXTURES, "get.golden.json", stdout); + }); + + test("paginates Memory list with --max-results and --next-token", async () => { + const firstPage = await run(["memory", "list", "--max-results", "1"]); + matchGolden(FIXTURES, "list-page-1.golden.json", firstPage); + + const first = JSON.parse(firstPage); + expect(first.memories).toHaveLength(1); + expect(first.nextToken).toBe("memory-page-2"); + + const secondPage = await run([ + "memory", + "list", + "--max-results", + "1", + "--next-token", + first.nextToken, + ]); + matchGolden(FIXTURES, "list-page-2.golden.json", secondPage); + expect(JSON.parse(secondPage).memories).toHaveLength(1); + }); + + test("rejects a missing Memory selector for headless get", async () => { + await expect(run(["memory", "get", "--json"])).rejects.toThrow(/--id/); + }); + + test("rejects an unsupported response view", async () => { + await expect( + run(["memory", "get", "--id", FIXTURE_MEMORY_ID, "--view", "summary"]), + ).rejects.toThrow(/Invalid value for option '--view'/); + }); + + test("propagates ResourceNotFoundException from Memory get", async () => { + await expect(run(["memory", "get", "--id", MISSING_MEMORY_ID])).rejects.toMatchObject({ + name: "ResourceNotFoundException", + }); + }); +}); diff --git a/src/handlers/memory/types.tsx b/src/handlers/memory/types.tsx new file mode 100644 index 000000000..9fe75386d --- /dev/null +++ b/src/handlers/memory/types.tsx @@ -0,0 +1,15 @@ +import type { + GetMemoryOutput, + ListMemoriesOutput, + MemoryView, +} from "@aws-sdk/client-bedrock-agentcore-control"; +import type { CoreOptions } from "../../core/types"; + +export interface CoreMemoryClient { + getMemory(id: string, view: MemoryView, options: CoreOptions): Promise; + listMemories( + nextToken: string | undefined, + maxResults: number | undefined, + options: CoreOptions, + ): Promise; +} diff --git a/src/handlers/root.test.tsx b/src/handlers/root.test.tsx index 11f89a1cb..75c521c5f 100644 --- a/src/handlers/root.test.tsx +++ b/src/handlers/root.test.tsx @@ -14,6 +14,7 @@ describe("createRootHandler", () => { "harness", "identity", "runtime", + "memory", "config", "project", ]); diff --git a/src/handlers/types.tsx b/src/handlers/types.tsx index e609c78ec..7c37d2122 100644 --- a/src/handlers/types.tsx +++ b/src/handlers/types.tsx @@ -1,5 +1,6 @@ import type { CoreHarnessClient } from "./harness/types.tsx"; import type { CoreIdentityClient } from "./identity/types.tsx"; +import type { CoreMemoryClient } from "./memory/types.tsx"; import type { CoreRuntimeClient } from "./runtime/types.tsx"; import type { Context } from "../router"; import type { ProjectManager } from "./project/types.ts"; @@ -7,6 +8,7 @@ import type { ProjectManager } from "./project/types.ts"; export interface Core { harness: CoreHarnessClient; identity: CoreIdentityClient; + memory: CoreMemoryClient; runtime: CoreRuntimeClient; projectManager: ProjectManager; } diff --git a/src/testing/TestCoreClient.tsx b/src/testing/TestCoreClient.tsx index 78c5d5898..4cf02bf71 100644 --- a/src/testing/TestCoreClient.tsx +++ b/src/testing/TestCoreClient.tsx @@ -13,13 +13,16 @@ import type { GetHarnessEndpointResponse, GetAgentRuntimeEndpointResponse, GetAgentRuntimeResponse, + GetMemoryOutput, ListApiKeyCredentialProvidersResponse, ListAgentRuntimeEndpointsResponse, ListAgentRuntimesResponse, ListAgentRuntimeVersionsResponse, + ListMemoriesOutput, ListHarnessesResponse, ListHarnessEndpointsResponse, ListHarnessVersionsResponse, + MemoryView, UpdateApiKeyCredentialProviderResponse, UpdateHarnessEndpointRequest, UpdateHarnessEndpointResponse, @@ -41,6 +44,7 @@ import type { CreateApiKeyCredentialProviderInput, UpdateApiKeyCredentialProviderInput, } from "../handlers/identity/types"; +import type { CoreMemoryClient } from "../handlers/memory/types"; import type { CoreRuntimeClient } from "../handlers/runtime/types"; import type { CoreOptions } from "../core/types"; import type { ProjectManager } from "../handlers/project/types"; @@ -91,6 +95,8 @@ const DEFAULT_LIST_API_KEYS_RESPONSE: ListApiKeyCredentialProvidersResponse = { }; const DEFAULT_UPDATE_API_KEY_RESPONSE = {} as UpdateApiKeyCredentialProviderResponse; const DEFAULT_DELETE_API_KEY_RESPONSE = {} as DeleteApiKeyCredentialProviderResponse; +const DEFAULT_GET_MEMORY_RESPONSE = {} as GetMemoryOutput; +const DEFAULT_LIST_MEMORIES_RESPONSE: ListMemoriesOutput = { memories: [] }; const DEFAULT_GET_RUNTIME_RESPONSE = {} as GetAgentRuntimeResponse; const DEFAULT_GET_RUNTIME_ENDPOINT_RESPONSE = {} as GetAgentRuntimeEndpointResponse; const DEFAULT_LIST_RUNTIMES_RESPONSE: ListAgentRuntimesResponse = { agentRuntimes: [] }; @@ -566,6 +572,50 @@ export class TestRuntimeClient implements CoreRuntimeClient { ); } } + +export class TestMemoryClient implements CoreMemoryClient { + readonly calls: RecordedCall[] = []; + + private getResponse: GetMemoryOutput = DEFAULT_GET_MEMORY_RESPONSE; + private listResponses = new Map(); + private error?: Error; + + setGetResponse(response: GetMemoryOutput): this { + this.getResponse = response; + return this; + } + + setListResponse(response: ListMemoriesOutput, forNextToken?: string): this { + this.listResponses.set(forNextToken, response); + return this; + } + + setError(error: Error | undefined): this { + this.error = error; + return this; + } + + async getMemory(id: string, view: MemoryView, options: CoreOptions): Promise { + this.calls.push({ method: "getMemory", args: [id, view, options] }); + if (this.error) throw this.error; + return this.getResponse; + } + + async listMemories( + nextToken: string | undefined, + maxResults: number | undefined, + options: CoreOptions, + ): Promise { + this.calls.push({ method: "listMemories", args: [nextToken, maxResults, options] }); + if (this.error) throw this.error; + return ( + this.listResponses.get(nextToken) ?? + this.listResponses.get(undefined) ?? + DEFAULT_LIST_MEMORIES_RESPONSE + ); + } +} + type TestCoreClientOptions = { logger?: Logger; }; @@ -612,6 +662,7 @@ class TestIdentityClient implements CoreIdentityClient { export class TestCoreClient implements Core { readonly harness = new TestHarnessClient(); readonly identity = new TestIdentityClient(); + readonly memory = new TestMemoryClient(); readonly runtime = new TestRuntimeClient(); readonly projectManager: ProjectManager; diff --git a/src/testing/index.tsx b/src/testing/index.tsx index 56f62a123..f1cca8730 100644 --- a/src/testing/index.tsx +++ b/src/testing/index.tsx @@ -5,6 +5,7 @@ export { tick, waitFor } from "./timing"; export { TestCoreClient, TestHarnessClient, + TestMemoryClient, TestRuntimeClient, type RecordedCall, } from "./TestCoreClient"; From 346e476ef75beb8b63c49097c1428d4becf369f5 Mon Sep 17 00:00:00 2001 From: notgitika Date: Tue, 28 Jul 2026 21:16:41 -0400 Subject: [PATCH 2/3] fix(memory): defer default view resolution --- src/handlers/memory/get/index.tsx | 6 ++++-- src/handlers/memory/memory.test.tsx | 8 ++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/handlers/memory/get/index.tsx b/src/handlers/memory/get/index.tsx index 9c591fc02..73bd28e8a 100644 --- a/src/handlers/memory/get/index.tsx +++ b/src/handlers/memory/get/index.tsx @@ -12,7 +12,7 @@ export const createGetMemoryHandler = (core: Core) => description: "get an AgentCore Memory", flags: [ flag("id", "the ID of the Memory", z.string().optional()), - flag("view", "response view", z.enum(MEMORY_VIEWS).default("full")), + flag("view", "response view", z.enum(MEMORY_VIEWS).optional()), ], handle: async (ctx, flags) => { if (!flags.id) { @@ -21,6 +21,8 @@ export const createGetMemoryHandler = (core: Core) => ctx .require(JsonRendererKey) - .renderJson(await core.memory.getMemory(flags.id, flags.view, coreOptsFromCtx(ctx))); + .renderJson( + await core.memory.getMemory(flags.id, flags.view ?? "full", coreOptsFromCtx(ctx)), + ); }, }); diff --git a/src/handlers/memory/memory.test.tsx b/src/handlers/memory/memory.test.tsx index 2216812ca..b52ef315e 100644 --- a/src/handlers/memory/memory.test.tsx +++ b/src/handlers/memory/memory.test.tsx @@ -9,6 +9,7 @@ import { testIO, } from "../../testing"; import { createRootHandler } from "../index"; +import { createGetMemoryHandler } from "./get"; const REGION = "us-west-2"; const FIXTURES = join(import.meta.dir, "__fixtures__"); @@ -54,6 +55,13 @@ describe("memory command hierarchy", () => { expect(memory?.children().map((child) => child.name())).toEqual(["get", "list"]); }); + test("keeps an omitted get view undefined for empty-flag routing", () => { + const get = createGetMemoryHandler(createFixtureCore()); + const view = get.flags().find((flag) => flag.name === "view"); + + expect(view?.schema.parse(undefined)).toBeUndefined(); + }); + test("prints help for bare `memory` without an SDK call", async () => { const stdout = await run(["memory"]); From 082e68c96dd64a60d04d2828b060c00963ea3a23 Mon Sep 17 00:00:00 2001 From: notgitika Date: Wed, 29 Jul 2026 15:16:12 -0400 Subject: [PATCH 3/3] fix(memory): address read-only PR review feedback - get: throw InputValidationError (modeled exception) instead of a raw TypeError when the required --id flag is omitted, matching current consensus error handling. - fixtures: replace the synthetic Memory fixtures (which RECORD=1 could not regenerate, since the IDs did not exist and recording overwrote the successes with not-found errors) with responses recorded against two persistent fixture Memories in the e2e-test account, matching Runtime and Identity. Assert an opaque list nextToken rather than a hand-authored value. --- .../GetMemoryCommand.22c108a1a6908216.json | 18 ------------------ .../GetMemoryCommand.4f3ba5bd8d8e60e7.json | 17 +++++++++++++++++ .../GetMemoryCommand.8709459f816da117.json | 17 +++++++++++++++++ .../GetMemoryCommand.97c5e1b3cd9fa634.json | 18 ------------------ .../GetMemoryCommand.ed4e49fb82fa7aa2.json | 4 ++-- .../ListMemoriesCommand.202662ec9345611.json | 15 +++++++++++++++ .../ListMemoriesCommand.62f80383c4837247.json | 15 --------------- .../ListMemoriesCommand.7d2e22c637f6b633.json | 16 ++++++++-------- .../memory/__fixtures__/get.golden.json | 15 +++++++-------- .../__fixtures__/list-page-1.golden.json | 14 +++++++------- .../__fixtures__/list-page-2.golden.json | 12 ++++++------ src/handlers/memory/get/index.tsx | 3 ++- src/handlers/memory/memory.test.tsx | 10 ++++++---- 13 files changed, 87 insertions(+), 87 deletions(-) delete mode 100644 src/handlers/memory/__fixtures__/GetMemoryCommand.22c108a1a6908216.json create mode 100644 src/handlers/memory/__fixtures__/GetMemoryCommand.4f3ba5bd8d8e60e7.json create mode 100644 src/handlers/memory/__fixtures__/GetMemoryCommand.8709459f816da117.json delete mode 100644 src/handlers/memory/__fixtures__/GetMemoryCommand.97c5e1b3cd9fa634.json create mode 100644 src/handlers/memory/__fixtures__/ListMemoriesCommand.202662ec9345611.json delete mode 100644 src/handlers/memory/__fixtures__/ListMemoriesCommand.62f80383c4837247.json diff --git a/src/handlers/memory/__fixtures__/GetMemoryCommand.22c108a1a6908216.json b/src/handlers/memory/__fixtures__/GetMemoryCommand.22c108a1a6908216.json deleted file mode 100644 index b033e6f7b..000000000 --- a/src/handlers/memory/__fixtures__/GetMemoryCommand.22c108a1a6908216.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "memory": { - "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_read_only_fixture-AbCd123456", - "id": "agentcore_cli_memory_read_only_fixture-AbCd123456", - "name": "agentcore_cli_memory_read_only_fixture", - "description": "Stable synthetic fixture for AgentCore CLI Memory read-only tests", - "eventExpiryDuration": 30, - "status": "ACTIVE", - "createdAt": { - "$date": "2026-07-20T12:00:00.000Z" - }, - "updatedAt": { - "$date": "2026-07-21T12:00:00.000Z" - }, - "strategies": [], - "indexedKeys": [] - } -} diff --git a/src/handlers/memory/__fixtures__/GetMemoryCommand.4f3ba5bd8d8e60e7.json b/src/handlers/memory/__fixtures__/GetMemoryCommand.4f3ba5bd8d8e60e7.json new file mode 100644 index 000000000..d5490138b --- /dev/null +++ b/src/handlers/memory/__fixtures__/GetMemoryCommand.4f3ba5bd8d8e60e7.json @@ -0,0 +1,17 @@ +{ + "memory": { + "arn": "arn:aws:bedrock-agentcore:us-west-2:685197708687:memory/agentcore_cli_memory_read_only_fixture-QZMh466aPK", + "id": "agentcore_cli_memory_read_only_fixture-QZMh466aPK", + "name": "agentcore_cli_memory_read_only_fixture", + "eventExpiryDuration": 30, + "status": "ACTIVE", + "createdAt": { + "$date": "2026-07-29T19:10:47.336Z" + }, + "updatedAt": { + "$date": "2026-07-29T19:10:52.159Z" + }, + "description": "Stable fixture for AgentCore CLI Memory read-only tests", + "strategies": [] + } +} \ No newline at end of file diff --git a/src/handlers/memory/__fixtures__/GetMemoryCommand.8709459f816da117.json b/src/handlers/memory/__fixtures__/GetMemoryCommand.8709459f816da117.json new file mode 100644 index 000000000..d5490138b --- /dev/null +++ b/src/handlers/memory/__fixtures__/GetMemoryCommand.8709459f816da117.json @@ -0,0 +1,17 @@ +{ + "memory": { + "arn": "arn:aws:bedrock-agentcore:us-west-2:685197708687:memory/agentcore_cli_memory_read_only_fixture-QZMh466aPK", + "id": "agentcore_cli_memory_read_only_fixture-QZMh466aPK", + "name": "agentcore_cli_memory_read_only_fixture", + "eventExpiryDuration": 30, + "status": "ACTIVE", + "createdAt": { + "$date": "2026-07-29T19:10:47.336Z" + }, + "updatedAt": { + "$date": "2026-07-29T19:10:52.159Z" + }, + "description": "Stable fixture for AgentCore CLI Memory read-only tests", + "strategies": [] + } +} \ No newline at end of file diff --git a/src/handlers/memory/__fixtures__/GetMemoryCommand.97c5e1b3cd9fa634.json b/src/handlers/memory/__fixtures__/GetMemoryCommand.97c5e1b3cd9fa634.json deleted file mode 100644 index b033e6f7b..000000000 --- a/src/handlers/memory/__fixtures__/GetMemoryCommand.97c5e1b3cd9fa634.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "memory": { - "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_read_only_fixture-AbCd123456", - "id": "agentcore_cli_memory_read_only_fixture-AbCd123456", - "name": "agentcore_cli_memory_read_only_fixture", - "description": "Stable synthetic fixture for AgentCore CLI Memory read-only tests", - "eventExpiryDuration": 30, - "status": "ACTIVE", - "createdAt": { - "$date": "2026-07-20T12:00:00.000Z" - }, - "updatedAt": { - "$date": "2026-07-21T12:00:00.000Z" - }, - "strategies": [], - "indexedKeys": [] - } -} diff --git a/src/handlers/memory/__fixtures__/GetMemoryCommand.ed4e49fb82fa7aa2.json b/src/handlers/memory/__fixtures__/GetMemoryCommand.ed4e49fb82fa7aa2.json index f04ebcf76..315d208ad 100644 --- a/src/handlers/memory/__fixtures__/GetMemoryCommand.ed4e49fb82fa7aa2.json +++ b/src/handlers/memory/__fixtures__/GetMemoryCommand.ed4e49fb82fa7aa2.json @@ -1,6 +1,6 @@ { "$error": { "name": "ResourceNotFoundException", - "message": "Memory missing_memory-0000000000 was not found" + "message": "Resource not found during GetMemory: Failed to retrieve memory item for ID: missing_memory-0000000000" } -} +} \ No newline at end of file diff --git a/src/handlers/memory/__fixtures__/ListMemoriesCommand.202662ec9345611.json b/src/handlers/memory/__fixtures__/ListMemoriesCommand.202662ec9345611.json new file mode 100644 index 000000000..7b701b2f3 --- /dev/null +++ b/src/handlers/memory/__fixtures__/ListMemoriesCommand.202662ec9345611.json @@ -0,0 +1,15 @@ +{ + "memories": [ + { + "createdAt": { + "$date": "2026-07-29T19:10:49.223Z" + }, + "updatedAt": { + "$date": "2026-07-29T19:10:53.987Z" + }, + "arn": "arn:aws:bedrock-agentcore:us-west-2:685197708687:memory/agentcore_cli_memory_read_only_fixture_second-yYHO1d5zJb", + "id": "agentcore_cli_memory_read_only_fixture_second-yYHO1d5zJb", + "status": "ACTIVE" + } + ] +} \ No newline at end of file diff --git a/src/handlers/memory/__fixtures__/ListMemoriesCommand.62f80383c4837247.json b/src/handlers/memory/__fixtures__/ListMemoriesCommand.62f80383c4837247.json deleted file mode 100644 index a773bc51e..000000000 --- a/src/handlers/memory/__fixtures__/ListMemoriesCommand.62f80383c4837247.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "memories": [ - { - "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_second-EfGh789012", - "id": "agentcore_cli_memory_second-EfGh789012", - "status": "ACTIVE", - "createdAt": { - "$date": "2026-07-22T12:00:00.000Z" - }, - "updatedAt": { - "$date": "2026-07-22T12:30:00.000Z" - } - } - ] -} diff --git a/src/handlers/memory/__fixtures__/ListMemoriesCommand.7d2e22c637f6b633.json b/src/handlers/memory/__fixtures__/ListMemoriesCommand.7d2e22c637f6b633.json index 6ca71c24b..8cc71c30b 100644 --- a/src/handlers/memory/__fixtures__/ListMemoriesCommand.7d2e22c637f6b633.json +++ b/src/handlers/memory/__fixtures__/ListMemoriesCommand.7d2e22c637f6b633.json @@ -1,16 +1,16 @@ { "memories": [ { - "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_read_only_fixture-AbCd123456", - "id": "agentcore_cli_memory_read_only_fixture-AbCd123456", - "status": "ACTIVE", "createdAt": { - "$date": "2026-07-20T12:00:00.000Z" + "$date": "2026-07-29T19:10:47.336Z" }, "updatedAt": { - "$date": "2026-07-21T12:00:00.000Z" - } + "$date": "2026-07-29T19:10:52.159Z" + }, + "arn": "arn:aws:bedrock-agentcore:us-west-2:685197708687:memory/agentcore_cli_memory_read_only_fixture-QZMh466aPK", + "id": "agentcore_cli_memory_read_only_fixture-QZMh466aPK", + "status": "ACTIVE" } ], - "nextToken": "memory-page-2" -} + "nextToken": "AQICAHiUtSe0BW1y/mGNCEkbzUvDO1/kt+MrXlU4kyNsk96TRAFZNu68ZoZRVpTi4J3mdZa1AAAA6zCB6AYJKoZIhvcNAQcGoIHaMIHXAgEAMIHRBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDE5I2hVBPh23XBhEhwIBEICBoyaroKFGBAkZQJ22PGY4hxH+M04e0wtFiBQUCvxcmW0/zbfP9DUozeosJuF6BAY+cNtUzg5w57FGk9+xLt3GotCE9mGKQYsVbzbLKfOpGjQBPgPQ1erPzB/rSH9RL+CII4aCgNo6RQQ39pYscVrjZVT0ZKXUqWSZbV0pGFJtq8OM5ACWTubrr87ShhGFrYzbQO9xhqsgLovhl8/7wgs9OD/bq8g=" +} \ No newline at end of file diff --git a/src/handlers/memory/__fixtures__/get.golden.json b/src/handlers/memory/__fixtures__/get.golden.json index 4a733bd02..00ce4f242 100644 --- a/src/handlers/memory/__fixtures__/get.golden.json +++ b/src/handlers/memory/__fixtures__/get.golden.json @@ -1,14 +1,13 @@ { "memory": { - "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_read_only_fixture-AbCd123456", - "id": "agentcore_cli_memory_read_only_fixture-AbCd123456", + "arn": "arn:aws:bedrock-agentcore:us-west-2:685197708687:memory/agentcore_cli_memory_read_only_fixture-QZMh466aPK", + "id": "agentcore_cli_memory_read_only_fixture-QZMh466aPK", "name": "agentcore_cli_memory_read_only_fixture", - "description": "Stable synthetic fixture for AgentCore CLI Memory read-only tests", "eventExpiryDuration": 30, "status": "ACTIVE", - "createdAt": "2026-07-20T12:00:00.000Z", - "updatedAt": "2026-07-21T12:00:00.000Z", - "strategies": [], - "indexedKeys": [] + "createdAt": "2026-07-29T19:10:47.336Z", + "updatedAt": "2026-07-29T19:10:52.159Z", + "description": "Stable fixture for AgentCore CLI Memory read-only tests", + "strategies": [] } -} +} \ No newline at end of file diff --git a/src/handlers/memory/__fixtures__/list-page-1.golden.json b/src/handlers/memory/__fixtures__/list-page-1.golden.json index 055e67eda..934ddce90 100644 --- a/src/handlers/memory/__fixtures__/list-page-1.golden.json +++ b/src/handlers/memory/__fixtures__/list-page-1.golden.json @@ -1,12 +1,12 @@ { "memories": [ { - "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_read_only_fixture-AbCd123456", - "id": "agentcore_cli_memory_read_only_fixture-AbCd123456", - "status": "ACTIVE", - "createdAt": "2026-07-20T12:00:00.000Z", - "updatedAt": "2026-07-21T12:00:00.000Z" + "createdAt": "2026-07-29T19:10:47.336Z", + "updatedAt": "2026-07-29T19:10:52.159Z", + "arn": "arn:aws:bedrock-agentcore:us-west-2:685197708687:memory/agentcore_cli_memory_read_only_fixture-QZMh466aPK", + "id": "agentcore_cli_memory_read_only_fixture-QZMh466aPK", + "status": "ACTIVE" } ], - "nextToken": "memory-page-2" -} + "nextToken": "AQICAHiUtSe0BW1y/mGNCEkbzUvDO1/kt+MrXlU4kyNsk96TRAFZNu68ZoZRVpTi4J3mdZa1AAAA6zCB6AYJKoZIhvcNAQcGoIHaMIHXAgEAMIHRBgkqhkiG9w0BBwEwHgYJYIZIAWUDBAEuMBEEDE5I2hVBPh23XBhEhwIBEICBoyaroKFGBAkZQJ22PGY4hxH+M04e0wtFiBQUCvxcmW0/zbfP9DUozeosJuF6BAY+cNtUzg5w57FGk9+xLt3GotCE9mGKQYsVbzbLKfOpGjQBPgPQ1erPzB/rSH9RL+CII4aCgNo6RQQ39pYscVrjZVT0ZKXUqWSZbV0pGFJtq8OM5ACWTubrr87ShhGFrYzbQO9xhqsgLovhl8/7wgs9OD/bq8g=" +} \ No newline at end of file diff --git a/src/handlers/memory/__fixtures__/list-page-2.golden.json b/src/handlers/memory/__fixtures__/list-page-2.golden.json index f57538015..34c5d80a8 100644 --- a/src/handlers/memory/__fixtures__/list-page-2.golden.json +++ b/src/handlers/memory/__fixtures__/list-page-2.golden.json @@ -1,11 +1,11 @@ { "memories": [ { - "arn": "arn:aws:bedrock-agentcore:us-west-2:123456789012:memory/agentcore_cli_memory_second-EfGh789012", - "id": "agentcore_cli_memory_second-EfGh789012", - "status": "ACTIVE", - "createdAt": "2026-07-22T12:00:00.000Z", - "updatedAt": "2026-07-22T12:30:00.000Z" + "createdAt": "2026-07-29T19:10:49.223Z", + "updatedAt": "2026-07-29T19:10:53.987Z", + "arn": "arn:aws:bedrock-agentcore:us-west-2:685197708687:memory/agentcore_cli_memory_read_only_fixture_second-yYHO1d5zJb", + "id": "agentcore_cli_memory_read_only_fixture_second-yYHO1d5zJb", + "status": "ACTIVE" } ] -} +} \ No newline at end of file diff --git a/src/handlers/memory/get/index.tsx b/src/handlers/memory/get/index.tsx index 73bd28e8a..bce0109ee 100644 --- a/src/handlers/memory/get/index.tsx +++ b/src/handlers/memory/get/index.tsx @@ -1,4 +1,5 @@ import z from "zod"; +import { InputValidationError } from "../../../errors"; import { createHandler, flag } from "../../../router"; import { JsonRendererKey } from "../../../tui"; import type { Core } from "../../types"; @@ -16,7 +17,7 @@ export const createGetMemoryHandler = (core: Core) => ], handle: async (ctx, flags) => { if (!flags.id) { - throw new TypeError("required option '--id ' not specified"); + throw new InputValidationError("required option '--id ' not specified"); } ctx diff --git a/src/handlers/memory/memory.test.tsx b/src/handlers/memory/memory.test.tsx index b52ef315e..edf086dc2 100644 --- a/src/handlers/memory/memory.test.tsx +++ b/src/handlers/memory/memory.test.tsx @@ -14,9 +14,11 @@ import { createGetMemoryHandler } from "./get"; const REGION = "us-west-2"; const FIXTURES = join(import.meta.dir, "__fixtures__"); -// These credential-free fixtures are synthetic but use the same SDK send-boundary -// replay path as recorded fixtures, so command-to-SDK translation remains covered. -const FIXTURE_MEMORY_ID = "agentcore_cli_memory_read_only_fixture-AbCd123456"; +// The e2e-test account holds two persistent fixture Memories: +// agentcore_cli_memory_read_only_fixture (get) and +// agentcore_cli_memory_read_only_fixture_second (needed for list pagination, >=2). +// Record with AWS_PROFILE=e2e-test RECORD=1 bun test src/handlers/memory/memory.test.tsx. +const FIXTURE_MEMORY_ID = "agentcore_cli_memory_read_only_fixture-QZMh466aPK"; const MISSING_MEMORY_ID = "missing_memory-0000000000"; function createFixtureCore(): CoreClient { @@ -97,7 +99,7 @@ describe("memory read-only commands", () => { const first = JSON.parse(firstPage); expect(first.memories).toHaveLength(1); - expect(first.nextToken).toBe("memory-page-2"); + expect(first.nextToken).toBeString(); const secondPage = await run([ "memory",