aismemory 0.7.4 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/README.md +211 -11
  2. package/dist/__tests__/agent-archive.test.d.ts +1 -0
  3. package/dist/__tests__/agent-archive.test.js +153 -0
  4. package/dist/__tests__/agent-archive.test.js.map +1 -0
  5. package/dist/__tests__/agent-key-mode.test.js +88 -7
  6. package/dist/__tests__/agent-key-mode.test.js.map +1 -1
  7. package/dist/__tests__/ais-http.test.js +32 -0
  8. package/dist/__tests__/ais-http.test.js.map +1 -1
  9. package/dist/__tests__/credential-isolation.test.js +117 -3
  10. package/dist/__tests__/credential-isolation.test.js.map +1 -1
  11. package/dist/__tests__/credential-resolution.test.js +5 -5
  12. package/dist/__tests__/credential-resolution.test.js.map +1 -1
  13. package/dist/__tests__/device-flow-gate-e2e.test.js +5 -0
  14. package/dist/__tests__/device-flow-gate-e2e.test.js.map +1 -1
  15. package/dist/__tests__/doctor.test.js +144 -79
  16. package/dist/__tests__/doctor.test.js.map +1 -1
  17. package/dist/__tests__/mcp-tools.test.d.ts +1 -0
  18. package/dist/__tests__/mcp-tools.test.js +189 -0
  19. package/dist/__tests__/mcp-tools.test.js.map +1 -0
  20. package/dist/__tests__/memory-pull.test.d.ts +1 -0
  21. package/dist/__tests__/memory-pull.test.js +380 -0
  22. package/dist/__tests__/memory-pull.test.js.map +1 -0
  23. package/dist/__tests__/memory-write-failure.test.js +4 -8
  24. package/dist/__tests__/memory-write-failure.test.js.map +1 -1
  25. package/dist/__tests__/no-registered-keys-disk-bearer-fallback.test.js +4 -7
  26. package/dist/__tests__/no-registered-keys-disk-bearer-fallback.test.js.map +1 -1
  27. package/dist/__tests__/pending-device-flow-e2e.test.d.ts +19 -0
  28. package/dist/__tests__/pending-device-flow-e2e.test.js +159 -0
  29. package/dist/__tests__/pending-device-flow-e2e.test.js.map +1 -0
  30. package/dist/__tests__/pending-device-flow.test.d.ts +15 -0
  31. package/dist/__tests__/pending-device-flow.test.js +108 -0
  32. package/dist/__tests__/pending-device-flow.test.js.map +1 -0
  33. package/dist/__tests__/provisional-register-mcp-remember.test.js +4 -8
  34. package/dist/__tests__/provisional-register-mcp-remember.test.js.map +1 -1
  35. package/dist/__tests__/readme-quickstart-default-ais-url.test.d.ts +1 -0
  36. package/dist/__tests__/readme-quickstart-default-ais-url.test.js +80 -0
  37. package/dist/__tests__/readme-quickstart-default-ais-url.test.js.map +1 -0
  38. package/dist/__tests__/reconnect-survival-e2e.test.js +3 -4
  39. package/dist/__tests__/reconnect-survival-e2e.test.js.map +1 -1
  40. package/dist/__tests__/remember-duplicate-truth.test.d.ts +13 -0
  41. package/dist/__tests__/remember-duplicate-truth.test.js +106 -0
  42. package/dist/__tests__/remember-duplicate-truth.test.js.map +1 -0
  43. package/dist/__tests__/retry-after.test.d.ts +4 -0
  44. package/dist/__tests__/retry-after.test.js +128 -0
  45. package/dist/__tests__/retry-after.test.js.map +1 -0
  46. package/dist/__tests__/startup-credential-warning-e2e.test.d.ts +1 -0
  47. package/dist/__tests__/startup-credential-warning-e2e.test.js +102 -0
  48. package/dist/__tests__/startup-credential-warning-e2e.test.js.map +1 -0
  49. package/dist/__tests__/tool-args.test.js +10 -0
  50. package/dist/__tests__/tool-args.test.js.map +1 -1
  51. package/dist/__tests__/version-check.test.d.ts +1 -0
  52. package/dist/__tests__/version-check.test.js +349 -0
  53. package/dist/__tests__/version-check.test.js.map +1 -0
  54. package/dist/agent-archive.d.ts +36 -0
  55. package/dist/agent-archive.js +69 -0
  56. package/dist/agent-archive.js.map +1 -0
  57. package/dist/agent-key-mode.d.ts +1 -1
  58. package/dist/agent-key-mode.js +56 -19
  59. package/dist/agent-key-mode.js.map +1 -1
  60. package/dist/ais-http-error.d.ts +26 -2
  61. package/dist/ais-http-error.js +52 -4
  62. package/dist/ais-http-error.js.map +1 -1
  63. package/dist/ais-http.js +46 -16
  64. package/dist/ais-http.js.map +1 -1
  65. package/dist/cli/doctor.d.ts +17 -2
  66. package/dist/cli/doctor.js +93 -14
  67. package/dist/cli/doctor.js.map +1 -1
  68. package/dist/cli/pull-memory.d.ts +17 -0
  69. package/dist/cli/pull-memory.js +141 -0
  70. package/dist/cli/pull-memory.js.map +1 -0
  71. package/dist/index.js +135 -398
  72. package/dist/index.js.map +1 -1
  73. package/dist/mcp/tools.d.ts +82 -0
  74. package/dist/mcp/tools.js +453 -0
  75. package/dist/mcp/tools.js.map +1 -0
  76. package/dist/memory-pull.d.ts +114 -0
  77. package/dist/memory-pull.js +171 -0
  78. package/dist/memory-pull.js.map +1 -0
  79. package/dist/pending-device-flow.d.ts +49 -0
  80. package/dist/pending-device-flow.js +96 -0
  81. package/dist/pending-device-flow.js.map +1 -0
  82. package/dist/retry-after.d.ts +26 -0
  83. package/dist/retry-after.js +42 -0
  84. package/dist/retry-after.js.map +1 -0
  85. package/dist/session-identity.d.ts +26 -0
  86. package/dist/session-identity.js +89 -0
  87. package/dist/session-identity.js.map +1 -0
  88. package/dist/telemetry.d.ts +1 -1
  89. package/dist/telemetry.js.map +1 -1
  90. package/dist/tool-args.d.ts +4 -0
  91. package/dist/tool-args.js +16 -0
  92. package/dist/tool-args.js.map +1 -1
  93. package/dist/version-check.d.ts +72 -0
  94. package/dist/version-check.js +237 -0
  95. package/dist/version-check.js.map +1 -0
  96. package/dist/workspace-key-mode.js +22 -6
  97. package/dist/workspace-key-mode.js.map +1 -1
  98. package/package.json +4 -3
  99. package/dist/harness-identity.d.ts +0 -17
  100. package/dist/harness-identity.js +0 -105
  101. package/dist/harness-identity.js.map +0 -1
@@ -0,0 +1,349 @@
1
+ /**
2
+ * Published-version check (CORBOT-7B8A1D16).
3
+ *
4
+ * Covers the five states the lane names: behind, current, ahead,
5
+ * offline/timeout, and switched off — plus the daily cache and the two places
6
+ * a customer reads the notice (the doctor line and the whoami / full_context
7
+ * tool results).
8
+ */
9
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
10
+ import { mkdtempSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
11
+ import { tmpdir } from 'node:os';
12
+ import { join } from 'node:path';
13
+ import { checkForUpdate, classifyVersion, clearUpdateNotice, compareVersions, formatUpdateNotice, getUpdateNotice, isUpdateStatus, isVersionCheckEnabled, startVersionCheck, versionCacheFilePath, REGISTRY_LATEST_URL, } from '../version-check.js';
14
+ import { checkPackageVersion } from '../cli/doctor.js';
15
+ import { createAgentKeyCallToolHandler } from '../mcp/tools.js';
16
+ import { ActivityTracker } from '../auto-handoff.js';
17
+ let home;
18
+ function registryFetch(version, calls) {
19
+ return (async (input) => {
20
+ calls?.push(String(input));
21
+ return Response.json({ name: 'aismemory', version });
22
+ });
23
+ }
24
+ function offlineFetch(message = 'The operation was aborted due to timeout') {
25
+ return (async () => {
26
+ throw new Error(message);
27
+ });
28
+ }
29
+ function asStatus(result) {
30
+ if (!isUpdateStatus(result))
31
+ throw new Error(`expected a version status, got skip: ${result.skipped}`);
32
+ return result;
33
+ }
34
+ beforeEach(() => {
35
+ home = mkdtempSync(join(tmpdir(), 'aismemory-version-check-'));
36
+ clearUpdateNotice();
37
+ });
38
+ afterEach(() => {
39
+ rmSync(home, { recursive: true, force: true });
40
+ clearUpdateNotice();
41
+ });
42
+ describe('compareVersions', () => {
43
+ it('orders release versions by each numeric part', () => {
44
+ expect(compareVersions('0.6.0', '0.7.4')).toBe(-1);
45
+ expect(compareVersions('0.7.4', '0.6.0')).toBe(1);
46
+ expect(compareVersions('0.7.4', '0.7.4')).toBe(0);
47
+ expect(compareVersions('0.10.0', '0.9.9')).toBe(1);
48
+ expect(compareVersions('1.0.0', '0.99.99')).toBe(1);
49
+ });
50
+ it('treats a pre-release as older than the release it leads to', () => {
51
+ expect(compareVersions('1.0.0-rc.1', '1.0.0')).toBe(-1);
52
+ expect(compareVersions('1.0.0', '1.0.0-rc.1')).toBe(1);
53
+ expect(compareVersions('1.0.0-rc.1', '1.0.0-rc.2')).toBe(-1);
54
+ expect(compareVersions('1.0.0-alpha', '1.0.0-beta')).toBe(-1);
55
+ });
56
+ it('ignores a leading v and build metadata', () => {
57
+ expect(compareVersions('v0.7.4', '0.7.4+build.9')).toBe(0);
58
+ });
59
+ });
60
+ describe('classifyVersion', () => {
61
+ it('names the three states', () => {
62
+ expect(classifyVersion('0.6.0', '0.7.4')).toBe('behind');
63
+ expect(classifyVersion('0.7.4', '0.7.4')).toBe('current');
64
+ expect(classifyVersion('0.8.0', '0.7.4')).toBe('ahead');
65
+ });
66
+ });
67
+ describe('checkForUpdate', () => {
68
+ it('reports behind, with a notice naming both versions and both commands', async () => {
69
+ const result = asStatus(await checkForUpdate({
70
+ currentVersion: '0.6.0',
71
+ env: {},
72
+ home,
73
+ fetchImpl: registryFetch('0.7.4'),
74
+ }));
75
+ expect(result.comparison).toBe('behind');
76
+ expect(result.currentVersion).toBe('0.6.0');
77
+ expect(result.latestVersion).toBe('0.7.4');
78
+ expect(result.notice).toContain('you are running version 0.6.0');
79
+ expect(result.notice).toContain('the latest published version is 0.7.4');
80
+ expect(result.notice).toContain('npm install -g aismemory@latest');
81
+ expect(result.notice).toContain('npx -y aismemory@latest');
82
+ });
83
+ it('reports current with no notice', async () => {
84
+ const result = asStatus(await checkForUpdate({
85
+ currentVersion: '0.7.4',
86
+ env: {},
87
+ home,
88
+ fetchImpl: registryFetch('0.7.4'),
89
+ }));
90
+ expect(result.comparison).toBe('current');
91
+ expect(result.notice).toBeUndefined();
92
+ });
93
+ it('reports ahead with no notice when running an unpublished build', async () => {
94
+ const result = asStatus(await checkForUpdate({
95
+ currentVersion: '0.8.0',
96
+ env: {},
97
+ home,
98
+ fetchImpl: registryFetch('0.7.4'),
99
+ }));
100
+ expect(result.comparison).toBe('ahead');
101
+ expect(result.notice).toBeUndefined();
102
+ });
103
+ it('skips without throwing when the registry is unreachable or times out', async () => {
104
+ const result = await checkForUpdate({
105
+ currentVersion: '0.6.0',
106
+ env: {},
107
+ home,
108
+ fetchImpl: offlineFetch(),
109
+ });
110
+ expect(isUpdateStatus(result)).toBe(false);
111
+ expect(result).toMatchObject({ skipped: 'unreachable' });
112
+ });
113
+ it('skips a registry response that carries no version', async () => {
114
+ const result = await checkForUpdate({
115
+ currentVersion: '0.6.0',
116
+ env: {},
117
+ home,
118
+ fetchImpl: (async () => Response.json({ name: 'aismemory' })),
119
+ });
120
+ expect(result).toMatchObject({ skipped: 'unreachable' });
121
+ });
122
+ it('skips a registry error status', async () => {
123
+ const result = await checkForUpdate({
124
+ currentVersion: '0.6.0',
125
+ env: {},
126
+ home,
127
+ fetchImpl: (async () => new Response('nope', { status: 503 })),
128
+ });
129
+ expect(result).toMatchObject({ skipped: 'unreachable' });
130
+ });
131
+ it.each(['off', '0', 'false', 'no', 'OFF'])('does not call the registry when AISMEMORY_VERSION_CHECK=%s', async (value) => {
132
+ const calls = [];
133
+ const result = await checkForUpdate({
134
+ currentVersion: '0.6.0',
135
+ env: { AISMEMORY_VERSION_CHECK: value },
136
+ home,
137
+ fetchImpl: registryFetch('0.7.4', calls),
138
+ });
139
+ expect(result).toMatchObject({ skipped: 'disabled' });
140
+ expect(calls).toEqual([]);
141
+ });
142
+ it('stays enabled for any other value of the switch', () => {
143
+ expect(isVersionCheckEnabled({})).toBe(true);
144
+ expect(isVersionCheckEnabled({ AISMEMORY_VERSION_CHECK: 'on' })).toBe(true);
145
+ expect(isVersionCheckEnabled({ AISMEMORY_VERSION_CHECK: '' })).toBe(true);
146
+ expect(isVersionCheckEnabled({ AISMEMORY_VERSION_CHECK: 'off' })).toBe(false);
147
+ });
148
+ it('asks the registry once a day and serves the cache in between', async () => {
149
+ const calls = [];
150
+ const day = 24 * 60 * 60 * 1000;
151
+ const first = await checkForUpdate({
152
+ currentVersion: '0.6.0',
153
+ env: {},
154
+ home,
155
+ now: () => 1_000_000,
156
+ fetchImpl: registryFetch('0.7.4', calls),
157
+ });
158
+ expect(asStatus(first).latestVersion).toBe('0.7.4');
159
+ expect(calls).toEqual([REGISTRY_LATEST_URL]);
160
+ expect(JSON.parse(readFileSync(versionCacheFilePath(home), 'utf-8'))).toEqual({
161
+ latestVersion: '0.7.4',
162
+ checkedAt: 1_000_000,
163
+ });
164
+ // One hour later: served from cache, no second registry call.
165
+ const cached = await checkForUpdate({
166
+ currentVersion: '0.6.0',
167
+ env: {},
168
+ home,
169
+ now: () => 1_000_000 + 3_600_000,
170
+ fetchImpl: registryFetch('9.9.9', calls),
171
+ });
172
+ expect(asStatus(cached).latestVersion).toBe('0.7.4');
173
+ expect(calls).toHaveLength(1);
174
+ // A day later: the cache has expired and the registry is asked again.
175
+ const refreshed = await checkForUpdate({
176
+ currentVersion: '0.6.0',
177
+ env: {},
178
+ home,
179
+ now: () => 1_000_000 + day + 1,
180
+ fetchImpl: registryFetch('0.8.0', calls),
181
+ });
182
+ expect(asStatus(refreshed).latestVersion).toBe('0.8.0');
183
+ expect(calls).toHaveLength(2);
184
+ });
185
+ it('ignores a corrupt cache file rather than failing', async () => {
186
+ mkdirSync(join(home, '.aismemory'), { recursive: true });
187
+ writeFileSync(versionCacheFilePath(home), 'not json at all');
188
+ const result = asStatus(await checkForUpdate({
189
+ currentVersion: '0.6.0',
190
+ env: {},
191
+ home,
192
+ fetchImpl: registryFetch('0.7.4'),
193
+ }));
194
+ expect(result.latestVersion).toBe('0.7.4');
195
+ });
196
+ });
197
+ describe('startVersionCheck', () => {
198
+ it('publishes the notice and announces it once when behind', async () => {
199
+ const announced = [];
200
+ await startVersionCheck({
201
+ currentVersion: '0.6.0',
202
+ env: {},
203
+ home,
204
+ fetchImpl: registryFetch('0.7.4'),
205
+ onUpdateAvailable: (notice) => { announced.push(notice); },
206
+ });
207
+ expect(announced).toEqual([formatUpdateNotice('0.6.0', '0.7.4')]);
208
+ expect(getUpdateNotice()).toBe(formatUpdateNotice('0.6.0', '0.7.4'));
209
+ });
210
+ it.each([
211
+ ['current', '0.7.4', registryFetch('0.7.4')],
212
+ ['ahead', '0.8.0', registryFetch('0.7.4')],
213
+ ['offline', '0.6.0', offlineFetch()],
214
+ ])('publishes no notice when %s', async (_label, currentVersion, fetchImpl) => {
215
+ await startVersionCheck({ currentVersion, env: {}, home, fetchImpl });
216
+ expect(getUpdateNotice()).toBeNull();
217
+ });
218
+ it('publishes no notice when the check is switched off', async () => {
219
+ await startVersionCheck({
220
+ currentVersion: '0.6.0',
221
+ env: { AISMEMORY_VERSION_CHECK: 'off' },
222
+ home,
223
+ fetchImpl: registryFetch('0.7.4'),
224
+ });
225
+ expect(getUpdateNotice()).toBeNull();
226
+ });
227
+ });
228
+ describe('doctor package-version check', () => {
229
+ const behind = async () => ({
230
+ currentVersion: '0.6.0',
231
+ latestVersion: '0.7.4',
232
+ comparison: 'behind',
233
+ notice: formatUpdateNotice('0.6.0', '0.7.4'),
234
+ });
235
+ it('WARNs with the upgrade command when behind', async () => {
236
+ const check = await checkPackageVersion({ packageVersion: '0.6.0', versionCheck: behind });
237
+ expect(check).toMatchObject({ name: 'Package version', status: 'WARN' });
238
+ expect(check.message).toContain('0.6.0');
239
+ expect(check.message).toContain('0.7.4');
240
+ expect(check.hint).toContain('npm install -g aismemory@latest');
241
+ });
242
+ it('PASSes when current', async () => {
243
+ const check = await checkPackageVersion({
244
+ packageVersion: '0.7.4',
245
+ versionCheck: async () => ({
246
+ currentVersion: '0.7.4', latestVersion: '0.7.4', comparison: 'current',
247
+ }),
248
+ });
249
+ expect(check.status).toBe('PASS');
250
+ expect(check.message).toContain('the latest published version');
251
+ });
252
+ it('PASSes when ahead of the published version', async () => {
253
+ const check = await checkPackageVersion({
254
+ packageVersion: '0.8.0',
255
+ versionCheck: async () => ({
256
+ currentVersion: '0.8.0', latestVersion: '0.7.4', comparison: 'ahead',
257
+ }),
258
+ });
259
+ expect(check.status).toBe('PASS');
260
+ expect(check.message).toContain('ahead of the latest published version');
261
+ });
262
+ it('PASSes and says so when the registry could not be reached', async () => {
263
+ const check = await checkPackageVersion({
264
+ packageVersion: '0.6.0',
265
+ versionCheck: async () => ({ skipped: 'unreachable', detail: 'timed out' }),
266
+ });
267
+ expect(check.status).toBe('PASS');
268
+ expect(check.message).toContain('could not reach the npm registry');
269
+ expect(check.hint).toBeUndefined();
270
+ });
271
+ it('PASSes and says so when the check is switched off', async () => {
272
+ const check = await checkPackageVersion({
273
+ packageVersion: '0.6.0',
274
+ versionCheck: async () => ({ skipped: 'disabled' }),
275
+ });
276
+ expect(check.status).toBe('PASS');
277
+ expect(check.message).toContain('AISMEMORY_VERSION_CHECK');
278
+ });
279
+ it('runs the real check end to end against an injected registry', async () => {
280
+ const check = await checkPackageVersion({
281
+ packageVersion: '0.6.0',
282
+ env: {},
283
+ home,
284
+ fetchImpl: registryFetch('0.7.4'),
285
+ });
286
+ expect(check.status).toBe('WARN');
287
+ expect(check.message).toContain('aismemory update available');
288
+ });
289
+ });
290
+ describe('model context protocol tool results', () => {
291
+ const config = {
292
+ agentId: '11111111-2222-3333-4444-555555555555',
293
+ apiKey: 'synthetic-key',
294
+ tenantId: 'tenant-a',
295
+ };
296
+ function handlerWithFetch(payload) {
297
+ globalThis.fetch = (async () => Response.json(payload));
298
+ return createAgentKeyCallToolHandler({
299
+ aisUrl: 'https://ais.example',
300
+ activityTracker: new ActivityTracker(),
301
+ config,
302
+ getSessionIdentity: () => null,
303
+ });
304
+ }
305
+ const originalFetch = globalThis.fetch;
306
+ afterEach(() => { globalThis.fetch = originalFetch; });
307
+ async function callTool(name) {
308
+ const handler = handlerWithFetch({ success: true, data: { id: config.agentId, name: 'Jaire' } });
309
+ const response = await handler({
310
+ method: 'tools/call',
311
+ params: { name, arguments: {} },
312
+ });
313
+ const first = response.content?.[0];
314
+ if (!first || first.type !== 'text')
315
+ throw new Error('tool returned no text content');
316
+ return JSON.parse(first.text);
317
+ }
318
+ it.each(['whoami', 'full_context'])('carries the notice in the %s result when behind', async (tool) => {
319
+ await startVersionCheck({
320
+ currentVersion: '0.6.0',
321
+ env: {},
322
+ home,
323
+ fetchImpl: registryFetch('0.7.4'),
324
+ });
325
+ const result = await callTool(tool);
326
+ expect(result['aismemoryUpdateAvailable']).toBe(formatUpdateNotice('0.6.0', '0.7.4'));
327
+ });
328
+ it('carries nothing in the whoami result when the version is current', async () => {
329
+ await startVersionCheck({
330
+ currentVersion: '0.7.4',
331
+ env: {},
332
+ home,
333
+ fetchImpl: registryFetch('0.7.4'),
334
+ });
335
+ const result = await callTool('whoami');
336
+ expect(result['aismemoryUpdateAvailable']).toBeUndefined();
337
+ });
338
+ it('leaves other tool results untouched when behind', async () => {
339
+ await startVersionCheck({
340
+ currentVersion: '0.6.0',
341
+ env: {},
342
+ home,
343
+ fetchImpl: registryFetch('0.7.4'),
344
+ });
345
+ const result = await callTool('recall');
346
+ expect(result['aismemoryUpdateAvailable']).toBeUndefined();
347
+ });
348
+ });
349
+ //# sourceMappingURL=version-check.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version-check.test.js","sourceRoot":"","sources":["../../src/__tests__/version-check.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtF,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EACL,cAAc,EACd,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,mBAAmB,GAGpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,6BAA6B,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,IAAI,IAAY,CAAC;AAEjB,SAAS,aAAa,CAAC,OAAe,EAAE,KAAgB;IACtD,OAAO,CAAC,KAAK,EAAE,KAAwB,EAAqB,EAAE;QAC5D,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3B,OAAO,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC;IACvD,CAAC,CAAiB,CAAC;AACrB,CAAC;AAED,SAAS,YAAY,CAAC,OAAO,GAAG,0CAA0C;IACxE,OAAO,CAAC,KAAK,IAAuB,EAAE;QACpC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC,CAAiB,CAAC;AACrB,CAAC;AAED,SAAS,QAAQ,CAAC,MAA0B;IAC1C,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,wCAAwC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IACvG,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,UAAU,CAAC,GAAS,EAAE;IACpB,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,0BAA0B,CAAC,CAAC,CAAC;IAC/D,iBAAiB,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,GAAS,EAAE;IACnB,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,iBAAiB,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,8CAA8C,EAAE,GAAS,EAAE;QAC5D,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4DAA4D,EAAE,GAAS,EAAE;QAC1E,MAAM,CAAC,eAAe,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,CAAC,eAAe,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7D,MAAM,CAAC,eAAe,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAS,EAAE;QACtD,MAAM,CAAC,eAAe,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC/B,EAAE,CAAC,wBAAwB,EAAE,GAAS,EAAE;QACtC,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzD,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1D,MAAM,CAAC,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAmB,EAAE;QACnG,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,cAAc,CAAC;YAC3C,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;SAClC,CAAC,CAAC,CAAC;QAEJ,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,+BAA+B,CAAC,CAAC;QACjE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,uCAAuC,CAAC,CAAC;QACzE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;QACnE,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAmB,EAAE;QAC7D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,cAAc,CAAC;YAC3C,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;SAClC,CAAC,CAAC,CAAC;QAEJ,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAmB,EAAE;QAC7F,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,cAAc,CAAC;YAC3C,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;SAClC,CAAC,CAAC,CAAC;QAEJ,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,EAAE,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sEAAsE,EAAE,KAAK,IAAmB,EAAE;QACnG,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;YAClC,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,SAAS,EAAE,YAAY,EAAE;SAC1B,CAAC,CAAC;QAEH,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAmB,EAAE;QAChF,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;YAClC,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,SAAS,EAAE,CAAC,KAAK,IAAuB,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAiB;SACjG,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+BAA+B,EAAE,KAAK,IAAmB,EAAE;QAC5D,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;YAClC,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,SAAS,EAAE,CAAC,KAAK,IAAuB,EAAE,CAAC,IAAI,QAAQ,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAiB;SAClG,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CACzC,4DAA4D,EAC5D,KAAK,EAAE,KAAK,EAAiB,EAAE;QAC7B,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;YAClC,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE,uBAAuB,EAAE,KAAK,EAAE;YACvC,IAAI;YACJ,SAAS,EAAE,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC;SACzC,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC,CACF,CAAC;IAEF,EAAE,CAAC,iDAAiD,EAAE,GAAS,EAAE;QAC/D,MAAM,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,CAAC,qBAAqB,CAAC,EAAE,uBAAuB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5E,MAAM,CAAC,qBAAqB,CAAC,EAAE,uBAAuB,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1E,MAAM,CAAC,qBAAqB,CAAC,EAAE,uBAAuB,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAmB,EAAE;QAC3F,MAAM,KAAK,GAAa,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QAChC,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC;YACjC,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,GAAG,EAAE,GAAG,EAAE,CAAC,SAAS;YACpB,SAAS,EAAE,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC;SACzC,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpD,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;YAC5E,aAAa,EAAE,OAAO;YACtB,SAAS,EAAE,SAAS;SACrB,CAAC,CAAC;QAEH,8DAA8D;QAC9D,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;YAClC,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,GAAG,EAAE,GAAG,EAAE,CAAC,SAAS,GAAG,SAAS;YAChC,SAAS,EAAE,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC;SACzC,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAE9B,sEAAsE;QACtE,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC;YACrC,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,GAAG,EAAE,GAAG,EAAE,CAAC,SAAS,GAAG,GAAG,GAAG,CAAC;YAC9B,SAAS,EAAE,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC;SACzC,CAAC,CAAC;QACH,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAmB,EAAE;QAC/E,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,aAAa,CAAC,oBAAoB,CAAC,IAAI,CAAC,EAAE,iBAAiB,CAAC,CAAC;QAE7D,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,cAAc,CAAC;YAC3C,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;SAClC,CAAC,CAAC,CAAC;QACJ,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,wDAAwD,EAAE,KAAK,IAAmB,EAAE;QACrF,MAAM,SAAS,GAAa,EAAE,CAAC;QAC/B,MAAM,iBAAiB,CAAC;YACtB,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;YACjC,iBAAiB,EAAE,CAAC,MAAM,EAAQ,EAAE,GAAG,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;SACjE,CAAC,CAAC;QAEH,MAAM,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,IAAI,CAAC;QACN,CAAC,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;QAC5C,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;QAC1C,CAAC,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;KACrC,CAAC,CAAC,6BAA6B,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,SAAS,EAAiB,EAAE;QAC3F,MAAM,iBAAiB,CAAC,EAAE,cAAc,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;QACtE,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAmB,EAAE;QACjF,MAAM,iBAAiB,CAAC;YACtB,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE,uBAAuB,EAAE,KAAK,EAAE;YACvC,IAAI;YACJ,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;SAClC,CAAC,CAAC;QACH,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,8BAA8B,EAAE,GAAG,EAAE;IAC5C,MAAM,MAAM,GAAG,KAAK,IAAiC,EAAE,CAAC,CAAC;QACvD,cAAc,EAAE,OAAO;QACvB,aAAa,EAAE,OAAO;QACtB,UAAU,EAAE,QAAQ;QACpB,MAAM,EAAE,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC;KAC7C,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAmB,EAAE;QACzE,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC,EAAE,cAAc,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC,CAAC;QAC3F,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;QACzE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qBAAqB,EAAE,KAAK,IAAmB,EAAE;QAClD,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC;YACtC,cAAc,EAAE,OAAO;YACvB,YAAY,EAAE,KAAK,IAAiC,EAAE,CAAC,CAAC;gBACtD,cAAc,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,SAAS;aACvE,CAAC;SACH,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAmB,EAAE;QACzE,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC;YACtC,cAAc,EAAE,OAAO;YACvB,YAAY,EAAE,KAAK,IAAiC,EAAE,CAAC,CAAC;gBACtD,cAAc,EAAE,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO;aACrE,CAAC;SACH,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,uCAAuC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAmB,EAAE;QACxF,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC;YACtC,cAAc,EAAE,OAAO;YACvB,YAAY,EAAE,KAAK,IAAiC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;SACzG,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAmB,EAAE;QAChF,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC;YACtC,cAAc,EAAE,OAAO;YACvB,YAAY,EAAE,KAAK,IAAiC,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC;SACjF,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAmB,EAAE;QAC1F,MAAM,KAAK,GAAG,MAAM,mBAAmB,CAAC;YACtC,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;SAClC,CAAC,CAAC;QACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,qCAAqC,EAAE,GAAG,EAAE;IACnD,MAAM,MAAM,GAAG;QACb,OAAO,EAAE,sCAAsC;QAC/C,MAAM,EAAE,eAAe;QACvB,QAAQ,EAAE,UAAU;KACrB,CAAC;IAEF,SAAS,gBAAgB,CAAC,OAAgB;QACxC,UAAU,CAAC,KAAK,GAAG,CAAC,KAAK,IAAuB,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAiB,CAAC;QAC3F,OAAO,6BAA6B,CAAC;YACnC,MAAM,EAAE,qBAAqB;YAC7B,eAAe,EAAE,IAAI,eAAe,EAAE;YACtC,MAAM;YACN,kBAAkB,EAAE,GAAS,EAAE,CAAC,IAAI;SACrC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,aAAa,GAAG,UAAU,CAAC,KAAK,CAAC;IACvC,SAAS,CAAC,GAAS,EAAE,GAAG,UAAU,CAAC,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7D,KAAK,UAAU,QAAQ,CAAC,IAAY;QAClC,MAAM,OAAO,GAAG,gBAAgB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,CAAC;QACjG,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC;YAC7B,MAAM,EAAE,YAAY;YACpB,MAAM,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE;SAChC,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACtF,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;IAC3D,CAAC;IAED,EAAE,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,iDAAiD,EAAE,KAAK,EAAE,IAAI,EAAiB,EAAE;QACnH,MAAM,iBAAiB,CAAC;YACtB,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;SAClC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAmB,EAAE;QAC/F,MAAM,iBAAiB,CAAC;YACtB,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;SAClC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAmB,EAAE;QAC9E,MAAM,iBAAiB,CAAC;YACtB,cAAc,EAAE,OAAO;YACvB,GAAG,EAAE,EAAE;YACP,IAAI;YACJ,SAAS,EAAE,aAAa,CAAC,OAAO,CAAC;SAClC,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACxC,MAAM,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IAC7D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,36 @@
1
+ export declare const AGENT_ARCHIVE_TOOL = "agent_archive";
2
+ export declare const AGENT_DELETE_ALIAS_TOOL = "agent_delete";
3
+ export type AgentArchiveToolName = typeof AGENT_ARCHIVE_TOOL | typeof AGENT_DELETE_ALIAS_TOOL;
4
+ export declare const AGENT_DELETE_ALIAS_NOTE = "agent_delete is a compatibility alias for agent_archive: it archived the agent and deleted nothing.";
5
+ /** Why the key-based modes refuse both tool names. */
6
+ export declare const AGENT_ARCHIVE_KEY_MODE_DETAIL: string;
7
+ export declare const AGENT_ARCHIVE_DESCRIPTION: string;
8
+ export declare const AGENT_DELETE_ALIAS_DESCRIPTION: string;
9
+ export declare const AGENT_ARCHIVE_INPUT_SCHEMA: {
10
+ type: "object";
11
+ properties: {
12
+ agentId: {
13
+ type: string;
14
+ description: string;
15
+ };
16
+ };
17
+ required: string[];
18
+ };
19
+ export interface AgentArchiveResult {
20
+ success: true;
21
+ archived: true;
22
+ agentId: string;
23
+ status: 'archived';
24
+ message: string;
25
+ aliasOf?: typeof AGENT_ARCHIVE_TOOL;
26
+ note?: string;
27
+ }
28
+ /** Sends one PATCH with the session bearer; the entrypoint passes `aisPatch`. */
29
+ export type ArchivePatch = (path: string, body: {
30
+ status: 'archived';
31
+ }) => Promise<unknown>;
32
+ /**
33
+ * Archive `agentId` through the owner's own bearer. A token-rejection body is
34
+ * returned untouched so the caller's re-auth-and-retry path still sees it.
35
+ */
36
+ export declare function archiveAgent(toolName: AgentArchiveToolName, rawArgs: unknown, patch: ArchivePatch): Promise<unknown>;
@@ -0,0 +1,69 @@
1
+ /**
2
+ * `agent_archive` and its `agent_delete` compatibility alias (CORBOT-BA5AADB0).
3
+ *
4
+ * An owner archives their own agent without the console: the tool sends
5
+ * `PATCH /v1/agents/<id> {"status":"archived"}` with the session's own bearer.
6
+ * The server decides who may do that — its bond check lets an owner token
7
+ * reach only agents that owner holds — so this module adds no permission.
8
+ *
9
+ * Archive is not delete: the agent and its memories stay, and the owner can
10
+ * restore it. `agent_delete` used to be the name for this action, so it is
11
+ * kept as an alias that archives and says so, in its description and in its
12
+ * response. Hard delete is not offered here.
13
+ */
14
+ import { z } from 'zod';
15
+ import { isAuthErrorResult } from './auth-staleness.js';
16
+ export const AGENT_ARCHIVE_TOOL = 'agent_archive';
17
+ export const AGENT_DELETE_ALIAS_TOOL = 'agent_delete';
18
+ export const AGENT_DELETE_ALIAS_NOTE = 'agent_delete is a compatibility alias for agent_archive: it archived the agent and deleted nothing.';
19
+ /** Why the key-based modes refuse both tool names. */
20
+ export const AGENT_ARCHIVE_KEY_MODE_DETAIL = 'archiving an agent needs the owner sign-in (run aismemory without AIS_API_KEY or AIS_WORKSPACE_KEY and ' +
21
+ 'approve the sign-in link). A key cannot archive any agent, its own included.';
22
+ export const AGENT_ARCHIVE_DESCRIPTION = 'Archive one of your own agents: its status becomes "archived", it stops appearing as a live agent, ' +
23
+ 'and its memories are kept. Nothing is deleted, and the owner can restore it. ' +
24
+ 'Needs the owner sign-in; the service refuses an agent that belongs to someone else.';
25
+ export const AGENT_DELETE_ALIAS_DESCRIPTION = 'Compatibility alias for agent_archive. It ARCHIVES the agent; it does not delete it. Use agent_archive. ' +
26
+ AGENT_ARCHIVE_DESCRIPTION;
27
+ export const AGENT_ARCHIVE_INPUT_SCHEMA = {
28
+ type: 'object',
29
+ properties: {
30
+ agentId: {
31
+ type: 'string',
32
+ description: 'The id (uuid) of the agent to archive. Required: the tool never guesses which agent you mean.',
33
+ },
34
+ },
35
+ required: ['agentId'],
36
+ };
37
+ const agentArchiveArgsSchema = z
38
+ .object({
39
+ agentId: z
40
+ .string({ message: 'agentId is required' })
41
+ .regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, 'agentId must be a valid agent UUID'),
42
+ })
43
+ .strict();
44
+ /**
45
+ * Archive `agentId` through the owner's own bearer. A token-rejection body is
46
+ * returned untouched so the caller's re-auth-and-retry path still sees it.
47
+ */
48
+ export async function archiveAgent(toolName, rawArgs, patch) {
49
+ const parsed = agentArchiveArgsSchema.safeParse(rawArgs);
50
+ if (!parsed.success) {
51
+ throw new Error(`Invalid arguments: ${parsed.error.issues.map((i) => i.message).join('; ')}`);
52
+ }
53
+ const { agentId } = parsed.data;
54
+ const response = await patch(`/v1/agents/${agentId}`, { status: 'archived' });
55
+ if (isAuthErrorResult(response))
56
+ return response;
57
+ const result = {
58
+ success: true,
59
+ archived: true,
60
+ agentId,
61
+ status: 'archived',
62
+ message: `Agent ${agentId} archived. Nothing was deleted: its memories are kept and the owner can restore it.`,
63
+ };
64
+ if (toolName === AGENT_DELETE_ALIAS_TOOL) {
65
+ return { ...result, aliasOf: AGENT_ARCHIVE_TOOL, note: AGENT_DELETE_ALIAS_NOTE };
66
+ }
67
+ return result;
68
+ }
69
+ //# sourceMappingURL=agent-archive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-archive.js","sourceRoot":"","sources":["../src/agent-archive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAExD,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAClD,MAAM,CAAC,MAAM,uBAAuB,GAAG,cAAc,CAAC;AAItD,MAAM,CAAC,MAAM,uBAAuB,GAClC,qGAAqG,CAAC;AAExG,sDAAsD;AACtD,MAAM,CAAC,MAAM,6BAA6B,GACxC,yGAAyG;IACzG,8EAA8E,CAAC;AAEjF,MAAM,CAAC,MAAM,yBAAyB,GACpC,qGAAqG;IACrG,+EAA+E;IAC/E,qFAAqF,CAAC;AAExF,MAAM,CAAC,MAAM,8BAA8B,GACzC,0GAA0G;IAC1G,yBAAyB,CAAC;AAE5B,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,IAAI,EAAE,QAAiB;IACvB,UAAU,EAAE;QACV,OAAO,EAAE;YACP,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,+FAA+F;SAC7G;KACF;IACD,QAAQ,EAAE,CAAC,SAAS,CAAC;CACtB,CAAC;AAEF,MAAM,sBAAsB,GAAG,CAAC;KAC7B,MAAM,CAAC;IACN,OAAO,EAAE,CAAC;SACP,MAAM,CAAC,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC;SAC1C,KAAK,CAAC,iEAAiE,EAAE,oCAAoC,CAAC;CAClH,CAAC;KACD,MAAM,EAAE,CAAC;AAeZ;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAA8B,EAC9B,OAAgB,EAChB,KAAmB;IAEnB,MAAM,MAAM,GAAG,sBAAsB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IACzD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,IAAI,KAAK,CAAC,sBAAsB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChG,CAAC;IACD,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC;IAChC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,cAAc,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;IAC9E,IAAI,iBAAiB,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC;IAEjD,MAAM,MAAM,GAAuB;QACjC,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,IAAI;QACd,OAAO;QACP,MAAM,EAAE,UAAU;QAClB,OAAO,EAAE,SAAS,OAAO,qFAAqF;KAC/G,CAAC;IACF,IAAI,QAAQ,KAAK,uBAAuB,EAAE,CAAC;QACzC,OAAO,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,uBAAuB,EAAE,CAAC;IACnF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -26,7 +26,7 @@ export declare function aisKeyPatch(aisUrl: string, path: string, apiKey: string
26
26
  export declare const UNKNOWN_TOOL_KEY_MODE: unique symbol;
27
27
  /**
28
28
  * Error for a tool whose server route falls outside the agent-API-key
29
- * allowlist (memory, goals, dream, full-context). Thrown instead of ever
29
+ * allowlist (memory, goals, dream, full-context, handoff). Thrown instead of ever
30
30
  * making the doomed request — the server would 403 it anyway, but failing
31
31
  * fast client-side keeps the error message focused on SCOPE rather than a
32
32
  * generic 403, and avoids burning a round trip on a request known to fail.
@@ -19,10 +19,12 @@
19
19
  * out-of-scope route return an honest error instead of making a request the
20
20
  * server would reject anyway.
21
21
  */
22
- import { AisHttpError } from './ais-http-error.js';
22
+ import { AisHttpError, duplicateMemoryResult } from './ais-http-error.js';
23
23
  import { emitTelemetry } from './telemetry.js';
24
- import { parseEmptyToolArgs, parseRecallArgs, parseFullContextArgs, parseRememberArgs, parseInboxSendArgs, parseInboxReadArgs, parseGoalCreateArgs, parseGoalListArgs, parseGoalUpdateProgressArgs, parseGoalCompleteArgs, parseInboxAckArgs, } from './tool-args.js';
24
+ import { retryAfterOf, shouldHonourRetryAfter, sleepSeconds } from './retry-after.js';
25
+ import { parseEmptyToolArgs, parseRecallArgs, parseFullContextArgs, parseRememberArgs, parseInboxSendArgs, parseInboxReadArgs, parseGoalCreateArgs, parseGoalListArgs, parseGoalUpdateProgressArgs, parseGoalCompleteArgs, parseInboxAckArgs, parseHandoffArgs, } from './tool-args.js';
25
26
  import { readInboxAndMaybeAck } from './inbox-client.js';
27
+ import { AGENT_ARCHIVE_KEY_MODE_DETAIL } from './agent-archive.js';
26
28
  /** Thrown by loadAgentApiKeyConfig when AIS_AGENT_API_KEY is set without AIS_AGENT_ID. */
27
29
  export class AgentApiKeyConfigError extends Error {
28
30
  constructor(message) {
@@ -94,23 +96,32 @@ export async function aisKeyPost(aisUrl, path, apiKey, body, fetchImpl = globalT
94
96
  const data = await readJson(res);
95
97
  if (!res.ok) {
96
98
  emitTelemetry({ event: 'ais.http.failure', path, httpStatus: res.status, error: `HTTP ${res.status}` });
97
- throw new AisHttpError(res.status, path, data);
99
+ throw new AisHttpError(res.status, path, data, retryAfterOf(res));
98
100
  }
99
101
  return data;
100
102
  }
101
103
  export async function aisKeyGet(aisUrl, path, apiKey, fetchImpl = globalThis.fetch) {
102
104
  let res;
103
- try {
104
- res = await fetchImpl(`${aisUrl}${path}`, { headers: { 'x-agent-api-key': apiKey } });
105
- }
106
- catch (err) {
107
- emitTelemetry({ event: 'ais.http.failure', path, error: err instanceof Error ? err.message : String(err) });
108
- throw err;
105
+ for (let attempt = 0;; attempt++) {
106
+ try {
107
+ res = await fetchImpl(`${aisUrl}${path}`, { headers: { 'x-agent-api-key': apiKey } });
108
+ }
109
+ catch (err) {
110
+ emitTelemetry({ event: 'ais.http.failure', path, error: err instanceof Error ? err.message : String(err) });
111
+ throw err;
112
+ }
113
+ // Jaire C9: a read told to wait a few seconds (429/503 Retry-After)
114
+ // waits and tries once more; writes are never retried.
115
+ const retryAfter = retryAfterOf(res);
116
+ if (attempt > 0 || !shouldHonourRetryAfter(retryAfter))
117
+ break;
118
+ emitTelemetry({ event: 'ais.http.retry', path, httpStatus: res.status });
119
+ await sleepSeconds(retryAfter);
109
120
  }
110
121
  const data = await readJson(res);
111
122
  if (!res.ok) {
112
123
  emitTelemetry({ event: 'ais.http.failure', path, httpStatus: res.status, error: `HTTP ${res.status}` });
113
- throw new AisHttpError(res.status, path, data);
124
+ throw new AisHttpError(res.status, path, data, retryAfterOf(res));
114
125
  }
115
126
  return data;
116
127
  }
@@ -130,7 +141,7 @@ export async function aisKeyPatch(aisUrl, path, apiKey, body, fetchImpl = global
130
141
  const data = await readJson(res);
131
142
  if (!res.ok) {
132
143
  emitTelemetry({ event: 'ais.http.failure', path, httpStatus: res.status, error: `HTTP ${res.status}` });
133
- throw new AisHttpError(res.status, path, data);
144
+ throw new AisHttpError(res.status, path, data, retryAfterOf(res));
134
145
  }
135
146
  return data;
136
147
  }
@@ -139,7 +150,7 @@ export async function aisKeyPatch(aisUrl, path, apiKey, body, fetchImpl = global
139
150
  export const UNKNOWN_TOOL_KEY_MODE = Symbol('unknown-tool-key-mode');
140
151
  /**
141
152
  * Error for a tool whose server route falls outside the agent-API-key
142
- * allowlist (memory, goals, dream, full-context). Thrown instead of ever
153
+ * allowlist (memory, goals, dream, full-context, handoff). Thrown instead of ever
143
154
  * making the doomed request — the server would 403 it anyway, but failing
144
155
  * fast client-side keeps the error message focused on SCOPE rather than a
145
156
  * generic 403, and avoids burning a round trip on a request known to fail.
@@ -155,11 +166,22 @@ export async function dispatchToolKeyMode(aisUrl, config, name, rawArgs, fetchIm
155
166
  switch (name) {
156
167
  case 'remember': {
157
168
  const args = parseRememberArgs(rawArgs);
158
- return aisKeyPost(aisUrl, `/v1/agents/${agentId}/memory`, apiKey, {
159
- content: args.content,
160
- type: args.type,
161
- importance: args.importance,
162
- }, fetchImpl);
169
+ try {
170
+ return await aisKeyPost(aisUrl, `/v1/agents/${agentId}/memory`, apiKey, {
171
+ content: args.content,
172
+ type: args.type,
173
+ importance: args.importance,
174
+ ...(args.tags !== undefined && { tags: args.tags }),
175
+ }, fetchImpl);
176
+ }
177
+ catch (err) {
178
+ // CORBOT-F21668B5: a deduplicated write is not a lost write — report
179
+ // what is true instead of an error the agent would retry forever.
180
+ const duplicate = duplicateMemoryResult(err);
181
+ if (duplicate)
182
+ return duplicate;
183
+ throw err;
184
+ }
163
185
  }
164
186
  case 'recall': {
165
187
  const args = parseRecallArgs(rawArgs);
@@ -169,6 +191,8 @@ export async function dispatchToolKeyMode(aisUrl, config, name, rawArgs, fetchIm
169
191
  params.set('limit', String(args.limit));
170
192
  if (args.type !== undefined)
171
193
  params.set('types', args.type);
194
+ if (args.tags !== undefined && args.tags.length > 0)
195
+ params.set('tags', args.tags.join(','));
172
196
  if (args.principalAgentId !== undefined) {
173
197
  params.set('principalAgentId', args.principalAgentId);
174
198
  }
@@ -266,11 +290,24 @@ export async function dispatchToolKeyMode(aisUrl, config, name, rawArgs, fetchIm
266
290
  ...(args.lessonsLearned !== undefined ? { lessonsLearned: args.lessonsLearned } : {}),
267
291
  }, fetchImpl);
268
292
  }
269
- case 'handoff':
270
- throw new OutOfScopeToolError('handoff', "the handoff route is outside the key's allowed scope (memory, goals, dream, full-context).");
293
+ case 'handoff': {
294
+ // CORBOT-E3541A7F: handoff is in the agent key's scope. The route is
295
+ // own-agent only — the service pins the path agent to the key's agent —
296
+ // so the agent id comes from the key, never from the caller's arguments.
297
+ const args = parseHandoffArgs(rawArgs);
298
+ return aisKeyPost(aisUrl, `/v1/agents/${agentId}/handoff`, apiKey, {
299
+ ...(args.summary !== undefined ? { summary: args.summary } : {}),
300
+ ...(args.keyLearnings !== undefined ? { keyLearnings: args.keyLearnings } : {}),
301
+ ...(args.docPath !== undefined ? { docPath: args.docPath } : {}),
302
+ ...(args.docPrUrl !== undefined ? { docPrUrl: args.docPrUrl } : {}),
303
+ }, fetchImpl);
304
+ }
271
305
  case 'agent_load':
272
306
  throw new OutOfScopeToolError('agent_load', 'switching agents requires a tenant-wide agent-listing route, which is outside the ' +
273
307
  "key's allowed scope. The active agent is fixed to AIS_AGENT_ID for the life of this process.");
308
+ case 'agent_archive':
309
+ case 'agent_delete':
310
+ throw new OutOfScopeToolError(name, AGENT_ARCHIVE_KEY_MODE_DETAIL);
274
311
  default:
275
312
  return UNKNOWN_TOOL_KEY_MODE;
276
313
  }