Skip to content

Commit a9a683d

Browse files
committed
chore: update CP semantics to expect redesigned namespaces field
1 parent 7586092 commit a9a683d

17 files changed

Lines changed: 219 additions & 92 deletions

File tree

docs/configuration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ Strategy configuration:
244244
"type": "SEMANTIC",
245245
"name": "custom_semantic",
246246
"description": "Custom semantic memory",
247-
"namespaces": ["/users/facts", "/users/preferences"]
247+
"namespaceTemplates": ["/users/facts", "/users/preferences"]
248248
}
249249
```
250250

docs/memory.md

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -196,17 +196,19 @@ Each strategy can have optional configuration:
196196
"type": "SEMANTIC",
197197
"name": "custom_semantic",
198198
"description": "Custom semantic memory",
199-
"namespaces": ["/users/facts", "/users/preferences"]
199+
"namespaceTemplates": ["/users/facts", "/users/preferences"]
200200
}
201201
```
202202

203-
| Field | Required | Description |
204-
| ---------------------- | ------------- | --------------------------------------------------------------------------- |
205-
| `type` | Yes | Strategy type |
206-
| `name` | No | Custom name (defaults to `<memoryName>-<type>`) |
207-
| `description` | No | Strategy description |
208-
| `namespaces` | No | Array of namespace paths for scoping |
209-
| `reflectionNamespaces` | EPISODIC only | Namespaces for cross-episode reflections (must be a prefix of `namespaces`) |
203+
| Field | Required | Description |
204+
| ------------------------------ | ------------- | --------------------------------------------------------------------------------------------- |
205+
| `type` | Yes | Strategy type |
206+
| `name` | No | Custom name (defaults to `<memoryName>-<type>`) |
207+
| `description` | No | Strategy description |
208+
| `namespaceTemplates` | No | Array of namespace templates for scoping |
209+
| `reflectionNamespaceTemplates` | EPISODIC only | Templates for cross-episode reflections (must be a prefix of `namespaceTemplates`) |
210+
| `namespaces` | No | **Deprecated alias for `namespaceTemplates`.** Accepted for backward compatibility. |
211+
| `reflectionNamespaces` | EPISODIC only | **Deprecated alias for `reflectionNamespaceTemplates`.** Accepted for backward compatibility. |
210212

211213
## Event Expiry
212214

src/cli/aws/agentcore-control.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -368,8 +368,8 @@ export interface MemoryDetail {
368368
type: string;
369369
name?: string;
370370
description?: string;
371-
namespaces?: string[];
372-
reflectionNamespaces?: string[];
371+
namespaceTemplates?: string[];
372+
reflectionNamespaceTemplates?: string[];
373373
}[];
374374
tags?: Record<string, string>;
375375
encryptionKeyArn?: string;
@@ -422,13 +422,17 @@ export async function getMemoryDetail(options: GetMemoryOptions): Promise<Memory
422422
if (!s.type) {
423423
throw new Error(`Memory ${options.memoryId} has a strategy with missing required field: type`);
424424
}
425-
const episodicNamespaces = s.configuration?.reflection?.episodicReflectionConfiguration?.namespaces;
425+
// Prefer the new `namespaceTemplates` field; fall back to the deprecated `namespaces` field.
426+
const namespaceTemplates = s.namespaceTemplates ?? s.namespaces;
427+
const reflectionConfig = s.configuration?.reflection?.episodicReflectionConfiguration;
428+
const reflectionTemplates = reflectionConfig?.namespaceTemplates ?? reflectionConfig?.namespaces;
426429
return {
427430
type: s.type,
428431
name: s.name,
429432
description: s.description,
430-
namespaces: s.namespaces,
431-
...(episodicNamespaces && episodicNamespaces.length > 0 && { reflectionNamespaces: episodicNamespaces }),
433+
...(namespaceTemplates && namespaceTemplates.length > 0 && { namespaceTemplates }),
434+
...(reflectionTemplates &&
435+
reflectionTemplates.length > 0 && { reflectionNamespaceTemplates: reflectionTemplates }),
432436
};
433437
}),
434438
};

src/cli/commands/add/__tests__/add-memory.test.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,20 +138,20 @@ describe('add memory command', () => {
138138
const memory = projectSpec.memories.find((m: { name: string }) => m.name === memoryName);
139139

140140
const semantic = memory?.strategies?.find((s: { type: string }) => s.type === 'SEMANTIC');
141-
expect(semantic?.namespaces).toEqual(['/users/{actorId}/facts']);
141+
expect(semantic?.namespaceTemplates).toEqual(['/users/{actorId}/facts']);
142142

143143
const userPref = memory?.strategies?.find((s: { type: string }) => s.type === 'USER_PREFERENCE');
144-
expect(userPref?.namespaces).toEqual(['/users/{actorId}/preferences']);
144+
expect(userPref?.namespaceTemplates).toEqual(['/users/{actorId}/preferences']);
145145

146146
const summarization = memory?.strategies?.find((s: { type: string }) => s.type === 'SUMMARIZATION');
147-
expect(summarization?.namespaces).toEqual(['/summaries/{actorId}/{sessionId}']);
147+
expect(summarization?.namespaceTemplates).toEqual(['/summaries/{actorId}/{sessionId}']);
148148

149149
const episodic = memory?.strategies?.find((s: { type: string }) => s.type === 'EPISODIC');
150-
expect(episodic?.namespaces).toEqual(['/episodes/{actorId}/{sessionId}']);
151-
expect(episodic?.reflectionNamespaces).toEqual(['/episodes/{actorId}']);
150+
expect(episodic?.namespaceTemplates).toEqual(['/episodes/{actorId}/{sessionId}']);
151+
expect(episodic?.reflectionNamespaceTemplates).toEqual(['/episodes/{actorId}']);
152152
});
153153

154-
it('creates memory with EPISODIC strategy including default namespaces and reflectionNamespaces', async () => {
154+
it('creates memory with EPISODIC strategy including default namespaceTemplates and reflectionNamespaceTemplates', async () => {
155155
const memoryName = `epi${Date.now()}`;
156156
const result = await runCLI(
157157
['add', 'memory', '--name', memoryName, '--strategies', 'EPISODIC', '--json'],
@@ -162,8 +162,8 @@ describe('add memory command', () => {
162162
const memory = projectSpec.memories.find((m: { name: string }) => m.name === memoryName);
163163
const episodic = memory?.strategies?.find((s: { type: string }) => s.type === 'EPISODIC');
164164
expect(episodic).toBeTruthy();
165-
expect(episodic?.namespaces).toEqual(['/episodes/{actorId}/{sessionId}']);
166-
expect(episodic?.reflectionNamespaces).toEqual(['/episodes/{actorId}']);
165+
expect(episodic?.namespaceTemplates).toEqual(['/episodes/{actorId}/{sessionId}']);
166+
expect(episodic?.reflectionNamespaceTemplates).toEqual(['/episodes/{actorId}']);
167167
});
168168
});
169169
});

src/cli/commands/create/__tests__/create.test.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,18 +143,18 @@ describe('create command', () => {
143143
const memory = projectSpec.memories[0];
144144

145145
const semantic = memory?.strategies?.find((s: { type: string }) => s.type === 'SEMANTIC');
146-
expect(semantic?.namespaces).toEqual(['/users/{actorId}/facts']);
146+
expect(semantic?.namespaceTemplates).toEqual(['/users/{actorId}/facts']);
147147

148148
const userPref = memory?.strategies?.find((s: { type: string }) => s.type === 'USER_PREFERENCE');
149-
expect(userPref?.namespaces).toEqual(['/users/{actorId}/preferences']);
149+
expect(userPref?.namespaceTemplates).toEqual(['/users/{actorId}/preferences']);
150150

151151
const summarization = memory?.strategies?.find((s: { type: string }) => s.type === 'SUMMARIZATION');
152-
expect(summarization?.namespaces).toEqual(['/summaries/{actorId}/{sessionId}']);
152+
expect(summarization?.namespaceTemplates).toEqual(['/summaries/{actorId}/{sessionId}']);
153153

154154
const episodic = memory?.strategies?.find((s: { type: string }) => s.type === 'EPISODIC');
155155
expect(episodic, 'EPISODIC strategy should exist in longAndShortTerm').toBeTruthy();
156-
expect(episodic?.namespaces).toEqual(['/episodes/{actorId}/{sessionId}']);
157-
expect(episodic?.reflectionNamespaces).toEqual(['/episodes/{actorId}']);
156+
expect(episodic?.namespaceTemplates).toEqual(['/episodes/{actorId}/{sessionId}']);
157+
expect(episodic?.reflectionNamespaceTemplates).toEqual(['/episodes/{actorId}']);
158158
});
159159

160160
it('uses --project-name for project and --name for agent resource', async () => {

src/cli/commands/import/import-memory.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,14 +42,16 @@ function filterInternalNamespaces(namespaces: string[]): string[] {
4242
function toMemorySpec(memory: MemoryDetail, localName: string): Memory {
4343
const strategies: Memory['strategies'] = memory.strategies.map(s => {
4444
const mappedType = mapStrategyType(s.type);
45-
const filteredNamespaces = s.namespaces ? filterInternalNamespaces(s.namespaces) : [];
45+
const filteredTemplates = s.namespaceTemplates ? filterInternalNamespaces(s.namespaceTemplates) : [];
4646
return {
4747
type: mappedType as Memory['strategies'][number]['type'],
4848
...(s.name && { name: s.name }),
4949
...(s.description && { description: s.description }),
50-
...(filteredNamespaces.length > 0 && { namespaces: filteredNamespaces }),
51-
...(s.reflectionNamespaces &&
52-
s.reflectionNamespaces.length > 0 && { reflectionNamespaces: s.reflectionNamespaces }),
50+
...(filteredTemplates.length > 0 && { namespaceTemplates: filteredTemplates }),
51+
...(s.reflectionNamespaceTemplates &&
52+
s.reflectionNamespaceTemplates.length > 0 && {
53+
reflectionNamespaceTemplates: s.reflectionNamespaceTemplates,
54+
}),
5355
};
5456
});
5557

src/cli/operations/agent/generate/__tests__/schema-mapper.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ describe('mapGenerateInputToMemories', () => {
4646
expect(types).toContain('EPISODIC');
4747
});
4848

49-
it('includes default namespaces for strategies', () => {
49+
it('includes default namespace templates for strategies', () => {
5050
const result = mapGenerateInputToMemories('longAndShortTerm', 'Proj');
5151
const semantic = result[0]!.strategies.find(s => s.type === 'SEMANTIC');
52-
expect(semantic?.namespaces).toEqual(['/users/{actorId}/facts']);
52+
expect(semantic?.namespaceTemplates).toEqual(['/users/{actorId}/facts']);
5353
});
5454

5555
it('uses project name in memory name', () => {

src/cli/operations/agent/generate/schema-mapper.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ import type {
99
MemoryStrategyType,
1010
ModelProvider,
1111
} from '../../../../schema';
12-
import { DEFAULT_EPISODIC_REFLECTION_NAMESPACES, DEFAULT_STRATEGY_NAMESPACES } from '../../../../schema';
12+
import {
13+
DEFAULT_EPISODIC_REFLECTION_NAMESPACE_TEMPLATES,
14+
DEFAULT_STRATEGY_NAMESPACE_TEMPLATES,
15+
} from '../../../../schema';
1316
import { GatewayPrimitive } from '../../../primitives/GatewayPrimitive';
1417
import { buildAuthorizerConfigFromJwtConfig } from '../../../primitives/auth-utils';
1518
import {
@@ -69,11 +72,11 @@ export function mapGenerateInputToMemories(memory: MemoryOption, projectName: st
6972
if (memory === 'longAndShortTerm') {
7073
const strategyTypes: MemoryStrategyType[] = ['SEMANTIC', 'USER_PREFERENCE', 'SUMMARIZATION', 'EPISODIC'];
7174
for (const type of strategyTypes) {
72-
const defaultNamespaces = DEFAULT_STRATEGY_NAMESPACES[type];
75+
const defaultTemplates = DEFAULT_STRATEGY_NAMESPACE_TEMPLATES[type];
7376
strategies.push({
7477
type,
75-
...(defaultNamespaces && { namespaces: defaultNamespaces }),
76-
...(type === 'EPISODIC' && { reflectionNamespaces: DEFAULT_EPISODIC_REFLECTION_NAMESPACES }),
78+
...(defaultTemplates && { namespaceTemplates: defaultTemplates }),
79+
...(type === 'EPISODIC' && { reflectionNamespaceTemplates: DEFAULT_EPISODIC_REFLECTION_NAMESPACE_TEMPLATES }),
7780
});
7881
}
7982
}

src/cli/operations/dev/web-ui/api-types.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ export interface ResourceMemory {
145145
/** Memory strategy with namespace patterns */
146146
export interface ResourceMemoryStrategy {
147147
type: string;
148-
/** Namespace patterns, e.g. "/users/{actorId}/facts", "/summaries/{actorId}/{sessionId}" */
149-
namespaces: string[];
148+
/** Namespace templates, e.g. "/users/{actorId}/facts", "/summaries/{actorId}/{sessionId}" */
149+
namespaceTemplates: string[];
150150
}
151151

152152
/** Credential details in the resources response */

src/cli/operations/dev/web-ui/handlers/resources.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ export async function handleResources(ctx: RouteContext, res: ServerResponse, or
112112
name: m.name,
113113
strategies: m.strategies.map(s => ({
114114
type: s.type,
115-
namespaces: s.namespaces ?? [],
115+
namespaceTemplates: s.namespaceTemplates ?? s.namespaces ?? [],
116116
})),
117117
expiryDays: m.eventExpiryDuration,
118118
deploymentStatus: statusByTypeAndName.get(`memory:${m.name}`),

0 commit comments

Comments
 (0)