aismemory 0.6.2 → 0.7.1
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.
- package/dist/__tests__/agent-load-persistence.test.js +194 -56
- package/dist/__tests__/agent-load-persistence.test.js.map +1 -1
- package/dist/__tests__/agent-load-session-override-e2e.test.d.ts +1 -0
- package/dist/__tests__/agent-load-session-override-e2e.test.js +214 -0
- package/dist/__tests__/agent-load-session-override-e2e.test.js.map +1 -0
- package/dist/__tests__/agent-preference.test.d.ts +1 -0
- package/dist/__tests__/agent-preference.test.js +173 -0
- package/dist/__tests__/agent-preference.test.js.map +1 -0
- package/dist/__tests__/device-flow-gate-e2e.test.d.ts +1 -0
- package/dist/__tests__/device-flow-gate-e2e.test.js +244 -0
- package/dist/__tests__/device-flow-gate-e2e.test.js.map +1 -0
- package/dist/__tests__/memory-write-failure.test.js +30 -0
- package/dist/__tests__/memory-write-failure.test.js.map +1 -1
- package/dist/__tests__/reconnect-survival-e2e.test.d.ts +1 -0
- package/dist/__tests__/reconnect-survival-e2e.test.js +248 -0
- package/dist/__tests__/reconnect-survival-e2e.test.js.map +1 -0
- package/dist/__tests__/silent-renewal-e2e.test.d.ts +1 -0
- package/dist/__tests__/silent-renewal-e2e.test.js +249 -0
- package/dist/__tests__/silent-renewal-e2e.test.js.map +1 -0
- package/dist/__tests__/split-brain-upgrade-e2e.test.d.ts +1 -0
- package/dist/__tests__/split-brain-upgrade-e2e.test.js +206 -0
- package/dist/__tests__/split-brain-upgrade-e2e.test.js.map +1 -0
- package/dist/__tests__/token-manager.test.d.ts +1 -0
- package/dist/__tests__/token-manager.test.js +403 -0
- package/dist/__tests__/token-manager.test.js.map +1 -0
- package/dist/__tests__/token-rejection-reauth-e2e.test.d.ts +1 -0
- package/dist/__tests__/token-rejection-reauth-e2e.test.js +219 -0
- package/dist/__tests__/token-rejection-reauth-e2e.test.js.map +1 -0
- package/dist/agent-preference.d.ts +59 -0
- package/dist/agent-preference.js +127 -0
- package/dist/agent-preference.js.map +1 -0
- package/dist/index.js +129 -51
- package/dist/index.js.map +1 -1
- package/dist/key-auth.d.ts +8 -0
- package/dist/key-auth.js +13 -0
- package/dist/key-auth.js.map +1 -1
- package/dist/telemetry.d.ts +1 -1
- package/dist/telemetry.js.map +1 -1
- package/dist/token-manager.d.ts +83 -0
- package/dist/token-manager.js +237 -0
- package/dist/token-manager.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,69 +1,207 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Regression test for CORBOT-497C7FA3:
|
|
3
3
|
* agent_load must persist the switched agentId to disk so that process
|
|
4
|
-
* restarts (silent MCP
|
|
5
|
-
*
|
|
4
|
+
* restarts (silent MCP reconnect) restore the correct agent instead of
|
|
5
|
+
* silently reverting to the default.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* Task 7 review fix (2026-08-24): the previous version of this file only
|
|
8
|
+
* round-tripped `saveOAuthCredentials`/`loadOAuthCredentials` directly — it
|
|
9
|
+
* never called into `index.ts`'s real `agent_load` handler, and its
|
|
10
|
+
* docstring claimed `saveCredentials()` is what the handler calls, which
|
|
11
|
+
* stopped being true once auth was routed through the TokenManager
|
|
12
|
+
* (agent_load now calls `saveAgentPreference`, never a credentials
|
|
13
|
+
* function that writes a token). That left the actual restart-persistence
|
|
14
|
+
* regression uncovered on the live code path.
|
|
10
15
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
16
|
+
* This version spawns the real built binary twice against a fake AIS with
|
|
17
|
+
* an enrolled DID key (the "silent MCP reconnect" case the regression is
|
|
18
|
+
* about — no human interaction, no device flow): once to switch agents via
|
|
19
|
+
* `agent_load`, and once more, fresh, to prove the switch survives the
|
|
20
|
+
* restart. It also pins the persisted file's shape: schemaVersion 2,
|
|
21
|
+
* ids only, no `token` key.
|
|
13
22
|
*/
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
23
|
+
import { createServer } from 'node:http';
|
|
24
|
+
import { spawn } from 'node:child_process';
|
|
25
|
+
import { mkdtempSync, mkdirSync, rmSync, existsSync, readFileSync } from 'node:fs';
|
|
16
26
|
import { tmpdir } from 'node:os';
|
|
17
|
-
import { join } from '
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
tenantId: 'tenant-1',
|
|
25
|
-
expiresAt: FUTURE_EXPIRY,
|
|
26
|
-
};
|
|
27
|
+
import { join, resolve } from 'path';
|
|
28
|
+
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
29
|
+
import { generateAndSaveKeypair } from '../key-auth.js';
|
|
30
|
+
function mintJwt() {
|
|
31
|
+
const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64url');
|
|
32
|
+
const payload = Buffer.from(JSON.stringify({ sub: 'user-1', user_id: 'user-1', tenant_id: 'tenant-1' })).toString('base64url');
|
|
33
|
+
return `${header}.${payload}.fakesig`;
|
|
27
34
|
}
|
|
28
35
|
describe('agent_load credential persistence (CORBOT-497C7FA3)', () => {
|
|
29
|
-
let
|
|
30
|
-
|
|
31
|
-
|
|
36
|
+
let fakeAis;
|
|
37
|
+
let port = 0;
|
|
38
|
+
beforeAll(async () => {
|
|
39
|
+
fakeAis = createServer((req, res) => {
|
|
40
|
+
req.on('data', () => { });
|
|
41
|
+
req.on('end', () => {
|
|
42
|
+
if (req.url === '/v1/auth/challenge' && req.method === 'POST') {
|
|
43
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
44
|
+
res.end(JSON.stringify({
|
|
45
|
+
success: true,
|
|
46
|
+
data: { nonce: 'test-nonce', exp: Math.floor(Date.now() / 1000) + 60, hmac: 'test-hmac' },
|
|
47
|
+
}));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
if (req.url === '/v1/auth/did-prove' && req.method === 'POST') {
|
|
51
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
52
|
+
res.end(JSON.stringify({
|
|
53
|
+
success: true,
|
|
54
|
+
data: { bearerToken: mintJwt(), expiresAt: new Date(Date.now() + 7 * 24 * 3600 * 1000).toISOString() },
|
|
55
|
+
}));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if ((req.url === '/v1/agents' || req.url?.startsWith('/v1/agents?')) && req.method === 'GET') {
|
|
59
|
+
// corbot-id deliberately first — the pre-fix bug reverted to
|
|
60
|
+
// "the first active agent" on reconnect, which must NOT be ender-id.
|
|
61
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
62
|
+
res.end(JSON.stringify({
|
|
63
|
+
success: true,
|
|
64
|
+
data: {
|
|
65
|
+
agents: [
|
|
66
|
+
{ id: 'corbot-id', name: 'Corbot', status: 'active' },
|
|
67
|
+
{ id: 'ender-id', name: 'Ender', status: 'active' },
|
|
68
|
+
],
|
|
69
|
+
pagination: { total: 2, page: 1, limit: 100, hasMore: false },
|
|
70
|
+
},
|
|
71
|
+
}));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (req.url === '/v1/agents/corbot-id' && req.method === 'GET') {
|
|
75
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
76
|
+
res.end(JSON.stringify({ success: true, data: { id: 'corbot-id', name: 'Corbot', status: 'active' } }));
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
if (req.url === '/v1/agents/ender-id' && req.method === 'GET') {
|
|
80
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
81
|
+
res.end(JSON.stringify({ success: true, data: { id: 'ender-id', name: 'Ender', status: 'active' } }));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
// /v1/resolve and everything else (hydration / memory refresh /
|
|
85
|
+
// handoff) — generic success.
|
|
86
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
87
|
+
res.end(JSON.stringify({ success: true, data: {} }));
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
await new Promise((r) => {
|
|
91
|
+
fakeAis.listen(0, '127.0.0.1', () => {
|
|
92
|
+
const addr = fakeAis.address();
|
|
93
|
+
if (addr && typeof addr === 'object')
|
|
94
|
+
port = addr.port;
|
|
95
|
+
r();
|
|
96
|
+
});
|
|
97
|
+
});
|
|
32
98
|
});
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
});
|
|
36
|
-
it('credentials file reflects the switched agentId after saveOAuthCredentials', () => {
|
|
37
|
-
// Start with the default (Corbot) agent on disk, as it would be after initial auth.
|
|
38
|
-
saveOAuthCredentials(makeCreds('corbot-id'), tmpHome);
|
|
39
|
-
// Simulate what agent_load now does: update agentId AND persist to disk.
|
|
40
|
-
const switched = { ...makeCreds('corbot-id'), agentId: 'ender-id' };
|
|
41
|
-
saveOAuthCredentials(switched, tmpHome); // the fix ensures this is called
|
|
42
|
-
// A new process (reconnect) loads credentials from disk — must get 'ender-id'.
|
|
43
|
-
const restored = loadOAuthCredentials(tmpHome);
|
|
44
|
-
expect(restored?.agentId).toBe('ender-id');
|
|
45
|
-
});
|
|
46
|
-
it('without persisting, a reload returns the original agentId — documents the pre-fix bug', () => {
|
|
47
|
-
// Start with 'corbot-id' on disk.
|
|
48
|
-
saveOAuthCredentials(makeCreds('corbot-id'), tmpHome);
|
|
49
|
-
// Pre-fix: agent_load only updated the in-memory variable, never called save.
|
|
50
|
-
// Demonstrate what that means: disk still has the old agentId.
|
|
51
|
-
const _inMemoryOnly = { ...makeCreds('corbot-id'), agentId: 'ender-id' };
|
|
52
|
-
// (intentionally NOT calling saveOAuthCredentials here)
|
|
53
|
-
// Reconnect scenario: fresh process reads from disk → wrong agent.
|
|
54
|
-
const restored = loadOAuthCredentials(tmpHome);
|
|
55
|
-
expect(restored?.agentId).toBe('corbot-id'); // bug: silent revert to default
|
|
56
|
-
});
|
|
57
|
-
it('token and tenantId are preserved when only agentId is updated', () => {
|
|
58
|
-
const initial = makeCreds('corbot-id');
|
|
59
|
-
saveOAuthCredentials(initial, tmpHome);
|
|
60
|
-
const switched = { ...initial, agentId: 'ender-id' };
|
|
61
|
-
saveOAuthCredentials(switched, tmpHome);
|
|
62
|
-
const restored = loadOAuthCredentials(tmpHome);
|
|
63
|
-
expect(restored?.agentId).toBe('ender-id');
|
|
64
|
-
expect(restored?.token).toBe(initial.token);
|
|
65
|
-
expect(restored?.tenantId).toBe(initial.tenantId);
|
|
66
|
-
expect(restored?.expiresAt).toBe(initial.expiresAt);
|
|
99
|
+
afterAll(async () => {
|
|
100
|
+
await new Promise((r) => fakeAis?.close(() => r()));
|
|
67
101
|
});
|
|
102
|
+
it('a switch made via agent_load survives a process restart (silent key-auth reconnect)', async () => {
|
|
103
|
+
const distPath = resolve(__dirname, '..', '..', 'dist', 'index.js');
|
|
104
|
+
if (!existsSync(distPath)) {
|
|
105
|
+
throw new Error(`dist/index.js missing — run \`pnpm build\` first (looked at ${distPath})`);
|
|
106
|
+
}
|
|
107
|
+
const fakeHome = mkdtempSync(join(tmpdir(), 'aismem-agent-load-persist-'));
|
|
108
|
+
const aismemDir = join(fakeHome, '.aismemory');
|
|
109
|
+
mkdirSync(aismemDir, { recursive: true });
|
|
110
|
+
await generateAndSaveKeypair({
|
|
111
|
+
userId: 'user-1',
|
|
112
|
+
userDid: 'did:web:test:users:user-1',
|
|
113
|
+
keysDir: join(aismemDir, 'keys'),
|
|
114
|
+
});
|
|
115
|
+
const env = { ...process.env, HOME: fakeHome, AIS_URL: `http://127.0.0.1:${port}` };
|
|
116
|
+
let proc = null;
|
|
117
|
+
try {
|
|
118
|
+
// ── Session 1: cold start, then switch to ender-id via agent_load ──
|
|
119
|
+
proc = spawn('node', [distPath], { env, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
120
|
+
let stdoutBuf = '';
|
|
121
|
+
proc.stdout.on('data', (d) => { stdoutBuf += d.toString(); });
|
|
122
|
+
proc.stderr.on('data', () => { });
|
|
123
|
+
proc.stdin.write(JSON.stringify({
|
|
124
|
+
jsonrpc: '2.0', id: 1, method: 'initialize',
|
|
125
|
+
params: { protocolVersion: '2024-11-05', capabilities: {}, clientInfo: { name: 'agent-load-persist-test', version: '0.0.0' } },
|
|
126
|
+
}) + '\n');
|
|
127
|
+
await waitFor(() => stdoutBuf.includes('"id":1'), 5000, 'initialize (session 1)');
|
|
128
|
+
proc.stdin.write(JSON.stringify({
|
|
129
|
+
jsonrpc: '2.0', id: 2, method: 'tools/call', params: { name: 'whoami', arguments: {} },
|
|
130
|
+
}) + '\n');
|
|
131
|
+
await waitFor(() => stdoutBuf.includes('"id":2'), 15000, 'whoami before switch');
|
|
132
|
+
expect(extractResponseText(stdoutBuf, 2)).toContain('corbot-id');
|
|
133
|
+
proc.stdin.write(JSON.stringify({
|
|
134
|
+
jsonrpc: '2.0', id: 3, method: 'tools/call',
|
|
135
|
+
params: { name: 'agent_load', arguments: { query: 'ender-id' } },
|
|
136
|
+
}) + '\n');
|
|
137
|
+
await waitFor(() => stdoutBuf.includes('"id":3'), 15000, 'agent_load');
|
|
138
|
+
expect(extractResponseText(stdoutBuf, 3)).toContain('ender-id');
|
|
139
|
+
proc.kill();
|
|
140
|
+
proc = null;
|
|
141
|
+
// ── The persisted file: v2 shape, ids only, no token ──
|
|
142
|
+
const credsPath = join(aismemDir, 'credentials.json');
|
|
143
|
+
const raw = readFileSync(credsPath, 'utf-8');
|
|
144
|
+
const savedCreds = JSON.parse(raw);
|
|
145
|
+
expect(savedCreds.schemaVersion).toBe(2);
|
|
146
|
+
expect(savedCreds.agentId).toBe('ender-id');
|
|
147
|
+
expect(savedCreds.tenantId).toBeTypeOf('string');
|
|
148
|
+
expect(Object.prototype.hasOwnProperty.call(savedCreds, 'token')).toBe(false);
|
|
149
|
+
expect(Object.prototype.hasOwnProperty.call(savedCreds, 'expiresAt')).toBe(false);
|
|
150
|
+
// ── Session 2: fresh process, same fake HOME — a silent reconnect. ──
|
|
151
|
+
// Must resolve back to ender-id via loadAgentPreference()'s
|
|
152
|
+
// preferredAgentId, NOT revert to corbot-id (the first active agent).
|
|
153
|
+
proc = spawn('node', [distPath], { env, stdio: ['pipe', 'pipe', 'pipe'] });
|
|
154
|
+
let stdoutBuf2 = '';
|
|
155
|
+
proc.stdout.on('data', (d) => { stdoutBuf2 += d.toString(); });
|
|
156
|
+
proc.stderr.on('data', () => { });
|
|
157
|
+
proc.stdin.write(JSON.stringify({
|
|
158
|
+
jsonrpc: '2.0', id: 1, method: 'initialize',
|
|
159
|
+
params: { protocolVersion: '2024-11-05', capabilities: {}, clientInfo: { name: 'agent-load-persist-test-2', version: '0.0.0' } },
|
|
160
|
+
}) + '\n');
|
|
161
|
+
await waitFor(() => stdoutBuf2.includes('"id":1'), 5000, 'initialize (session 2)');
|
|
162
|
+
proc.stdin.write(JSON.stringify({
|
|
163
|
+
jsonrpc: '2.0', id: 2, method: 'tools/call', params: { name: 'whoami', arguments: {} },
|
|
164
|
+
}) + '\n');
|
|
165
|
+
await waitFor(() => stdoutBuf2.includes('"id":2'), 15000, 'whoami after restart');
|
|
166
|
+
const restartedWhoami = extractResponseText(stdoutBuf2, 2);
|
|
167
|
+
expect(restartedWhoami).toContain('ender-id');
|
|
168
|
+
expect(restartedWhoami).not.toContain('corbot-id');
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
proc?.kill();
|
|
172
|
+
rmSync(fakeHome, { recursive: true, force: true });
|
|
173
|
+
}
|
|
174
|
+
}, 30000);
|
|
68
175
|
});
|
|
176
|
+
function waitFor(predicate, ms, label) {
|
|
177
|
+
return new Promise((resolveOuter, reject) => {
|
|
178
|
+
const start = Date.now();
|
|
179
|
+
const tick = () => {
|
|
180
|
+
if (predicate()) {
|
|
181
|
+
resolveOuter();
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (Date.now() - start > ms) {
|
|
185
|
+
reject(new Error(`timeout waiting for ${label}`));
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
setTimeout(tick, 50);
|
|
189
|
+
};
|
|
190
|
+
tick();
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
function extractResponseText(buf, id) {
|
|
194
|
+
for (const line of buf.split('\n')) {
|
|
195
|
+
if (!line.includes(`"id":${id}`))
|
|
196
|
+
continue;
|
|
197
|
+
try {
|
|
198
|
+
const parsed = JSON.parse(line);
|
|
199
|
+
const text = parsed.result?.content?.[0]?.text;
|
|
200
|
+
if (typeof text === 'string')
|
|
201
|
+
return text;
|
|
202
|
+
}
|
|
203
|
+
catch { /* malformed line; skip */ }
|
|
204
|
+
}
|
|
205
|
+
return '';
|
|
206
|
+
}
|
|
69
207
|
//# sourceMappingURL=agent-load-persistence.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-load-persistence.test.js","sourceRoot":"","sources":["../../src/__tests__/agent-load-persistence.test.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"agent-load-persistence.test.js","sourceRoot":"","sources":["../../src/__tests__/agent-load-persistence.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CRITICAL fix, Task 7 review: on the key-enrolled path, `ensureCredentials`
|
|
3
|
+
* composed its returned Credentials directly from
|
|
4
|
+
* `tokenManager.getCredentials()` on every call. The TokenManager resolves
|
|
5
|
+
* agentId/tenantId ONCE, on its first acquire, and never re-resolves them
|
|
6
|
+
* (by design — see token-manager.ts). That meant an in-session `agent_load`
|
|
7
|
+
* switch — which mutated the outer `creds` variable directly — was
|
|
8
|
+
* clobbered back to the manager's original identity on the very NEXT tool
|
|
9
|
+
* call, not merely after a background renewal: `ensureCredentials` reassigns
|
|
10
|
+
* `creds = mc` unconditionally before returning.
|
|
11
|
+
*
|
|
12
|
+
* Fix: a module-scope `sessionAgentOverride` set by `agent_load`, which
|
|
13
|
+
* `ensureCredentials` composes into the returned Credentials (token/expiresAt
|
|
14
|
+
* from the manager, agentId/tenantId from the override when set) instead of
|
|
15
|
+
* ever letting the manager's cached identity win over a live switch.
|
|
16
|
+
*
|
|
17
|
+
* This test drives the REAL built binary (not a mock of ensureCredentials)
|
|
18
|
+
* against a fake AIS that hands out short-lived tokens, so a background
|
|
19
|
+
* renewal fires mid-test. It proves the switch survives both:
|
|
20
|
+
* 1. the very next tool call after `agent_load`, and
|
|
21
|
+
* 2. a background token renewal that happens after the switch.
|
|
22
|
+
*/
|
|
23
|
+
import { createServer } from 'node:http';
|
|
24
|
+
import { spawn } from 'node:child_process';
|
|
25
|
+
import { mkdtempSync, mkdirSync, rmSync, existsSync } from 'node:fs';
|
|
26
|
+
import { tmpdir } from 'node:os';
|
|
27
|
+
import { join, resolve } from 'path';
|
|
28
|
+
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
29
|
+
import { generateAndSaveKeypair } from '../key-auth.js';
|
|
30
|
+
// Short enough that the TokenManager's 75%-of-TTL renewal fires well inside
|
|
31
|
+
// the test's timeout, long enough to leave room for the intervening tool
|
|
32
|
+
// calls (agent_load + one whoami) before it does. Must clear
|
|
33
|
+
// scheduleRenewal's 30s floor (CORBOT-4F7CAA8E / F7) with margin, so 75% of
|
|
34
|
+
// this TTL is used as-is rather than being clamped up to the floor.
|
|
35
|
+
const SHORT_TTL_MS = 42_000;
|
|
36
|
+
let didProveCalls = 0;
|
|
37
|
+
function mintJwt() {
|
|
38
|
+
const header = Buffer.from(JSON.stringify({ alg: 'HS256', typ: 'JWT' })).toString('base64url');
|
|
39
|
+
const payload = Buffer.from(JSON.stringify({ sub: 'user-1', user_id: 'user-1', tenant_id: 'tenant-1', call: didProveCalls })).toString('base64url');
|
|
40
|
+
return `${header}.${payload}.fakesig-${didProveCalls}`;
|
|
41
|
+
}
|
|
42
|
+
describe('agent_load session override survives the next tool call and a background renewal', () => {
|
|
43
|
+
let fakeAis;
|
|
44
|
+
let port = 0;
|
|
45
|
+
beforeAll(async () => {
|
|
46
|
+
fakeAis = createServer((req, res) => {
|
|
47
|
+
req.on('data', () => { });
|
|
48
|
+
req.on('end', () => {
|
|
49
|
+
if (req.url === '/v1/auth/challenge' && req.method === 'POST') {
|
|
50
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
51
|
+
res.end(JSON.stringify({
|
|
52
|
+
success: true,
|
|
53
|
+
data: { nonce: 'test-nonce', exp: Math.floor(Date.now() / 1000) + 60, hmac: 'test-hmac' },
|
|
54
|
+
}));
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (req.url === '/v1/auth/did-prove' && req.method === 'POST') {
|
|
58
|
+
didProveCalls += 1;
|
|
59
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
60
|
+
res.end(JSON.stringify({
|
|
61
|
+
success: true,
|
|
62
|
+
data: {
|
|
63
|
+
bearerToken: mintJwt(),
|
|
64
|
+
expiresAt: new Date(Date.now() + SHORT_TTL_MS).toISOString(),
|
|
65
|
+
},
|
|
66
|
+
}));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (req.url?.startsWith('/v1/agents') && !req.url?.includes('/v1/agents/agent-') && req.method === 'GET') {
|
|
70
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
71
|
+
res.end(JSON.stringify({
|
|
72
|
+
success: true,
|
|
73
|
+
data: {
|
|
74
|
+
agents: [
|
|
75
|
+
{ id: 'agent-a', name: 'AgentA', status: 'active' },
|
|
76
|
+
{ id: 'agent-b', name: 'AgentB', status: 'active' },
|
|
77
|
+
],
|
|
78
|
+
pagination: { total: 2, page: 1, limit: 100, hasMore: false },
|
|
79
|
+
},
|
|
80
|
+
}));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
if (req.url === '/v1/agents/agent-a' && req.method === 'GET') {
|
|
84
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
85
|
+
res.end(JSON.stringify({ success: true, data: { id: 'agent-a', name: 'AgentA', status: 'active' } }));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
if (req.url === '/v1/agents/agent-b' && req.method === 'GET') {
|
|
89
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
90
|
+
res.end(JSON.stringify({ success: true, data: { id: 'agent-b', name: 'AgentB', status: 'active' } }));
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// /v1/resolve (agent_load's primary lookup) and everything else
|
|
94
|
+
// (hydration / memory refresh / handoff) — generic success. agent_load
|
|
95
|
+
// falls back to its own listAllAgents-based name/id match when
|
|
96
|
+
// /v1/resolve doesn't return a `status`.
|
|
97
|
+
res.writeHead(200, { 'content-type': 'application/json' });
|
|
98
|
+
res.end(JSON.stringify({ success: true, data: {} }));
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
await new Promise((r) => {
|
|
102
|
+
fakeAis.listen(0, '127.0.0.1', () => {
|
|
103
|
+
const addr = fakeAis.address();
|
|
104
|
+
if (addr && typeof addr === 'object')
|
|
105
|
+
port = addr.port;
|
|
106
|
+
r();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
afterAll(async () => {
|
|
111
|
+
await new Promise((r) => fakeAis?.close(() => r()));
|
|
112
|
+
});
|
|
113
|
+
it('keeps the switched agent across the next tool call and a renewal', async () => {
|
|
114
|
+
const distPath = resolve(__dirname, '..', '..', 'dist', 'index.js');
|
|
115
|
+
if (!existsSync(distPath)) {
|
|
116
|
+
throw new Error(`dist/index.js missing — run \`pnpm build\` first (looked at ${distPath})`);
|
|
117
|
+
}
|
|
118
|
+
didProveCalls = 0;
|
|
119
|
+
const fakeHome = mkdtempSync(join(tmpdir(), 'aismem-agent-load-override-'));
|
|
120
|
+
const aismemDir = join(fakeHome, '.aismemory');
|
|
121
|
+
mkdirSync(aismemDir, { recursive: true });
|
|
122
|
+
await generateAndSaveKeypair({
|
|
123
|
+
userId: 'user-1',
|
|
124
|
+
userDid: 'did:web:test:users:user-1',
|
|
125
|
+
keysDir: join(aismemDir, 'keys'),
|
|
126
|
+
});
|
|
127
|
+
let proc = null;
|
|
128
|
+
try {
|
|
129
|
+
proc = spawn('node', [distPath], {
|
|
130
|
+
env: { ...process.env, HOME: fakeHome, AIS_URL: `http://127.0.0.1:${port}` },
|
|
131
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
132
|
+
});
|
|
133
|
+
let stdoutBuf = '';
|
|
134
|
+
proc.stdout.on('data', (d) => { stdoutBuf += d.toString(); });
|
|
135
|
+
proc.stderr.on('data', () => { });
|
|
136
|
+
proc.stdin.write(JSON.stringify({
|
|
137
|
+
jsonrpc: '2.0', id: 1, method: 'initialize',
|
|
138
|
+
params: { protocolVersion: '2024-11-05', capabilities: {}, clientInfo: { name: 'agent-load-override-test', version: '0.0.0' } },
|
|
139
|
+
}) + '\n');
|
|
140
|
+
await waitFor(() => stdoutBuf.includes('"id":1'), 5000, 'initialize response');
|
|
141
|
+
// First whoami: establishes the TokenManager's first acquire, which
|
|
142
|
+
// resolves identity to the first active agent (agent-a — no
|
|
143
|
+
// preference on disk yet).
|
|
144
|
+
proc.stdin.write(JSON.stringify({
|
|
145
|
+
jsonrpc: '2.0', id: 2, method: 'tools/call', params: { name: 'whoami', arguments: {} },
|
|
146
|
+
}) + '\n');
|
|
147
|
+
await waitFor(() => stdoutBuf.includes('"id":2'), 15000, 'first whoami');
|
|
148
|
+
expect(extractResponseText(stdoutBuf, 2)).toContain('agent-a');
|
|
149
|
+
expect(didProveCalls).toBe(1);
|
|
150
|
+
// Switch to agent-b.
|
|
151
|
+
proc.stdin.write(JSON.stringify({
|
|
152
|
+
jsonrpc: '2.0', id: 3, method: 'tools/call',
|
|
153
|
+
params: { name: 'agent_load', arguments: { query: 'agent-b' } },
|
|
154
|
+
}) + '\n');
|
|
155
|
+
await waitFor(() => stdoutBuf.includes('"id":3'), 15000, 'agent_load response');
|
|
156
|
+
expect(extractResponseText(stdoutBuf, 3)).toContain('agent-b');
|
|
157
|
+
// THE critical assertion: the very next tool call after agent_load
|
|
158
|
+
// must dispatch as agent-b, not revert to the manager's original
|
|
159
|
+
// agent-a. No renewal has happened yet (didProveCalls still 1).
|
|
160
|
+
proc.stdin.write(JSON.stringify({
|
|
161
|
+
jsonrpc: '2.0', id: 4, method: 'tools/call', params: { name: 'whoami', arguments: {} },
|
|
162
|
+
}) + '\n');
|
|
163
|
+
await waitFor(() => stdoutBuf.includes('"id":4'), 15000, 'whoami right after switch');
|
|
164
|
+
expect(extractResponseText(stdoutBuf, 4)).toContain('agent-b');
|
|
165
|
+
expect(didProveCalls).toBe(1);
|
|
166
|
+
// Wait for a background renewal to fire (75% of the short TTL, ~31.5s).
|
|
167
|
+
await waitFor(() => didProveCalls >= 2, 40000, 'background renewal');
|
|
168
|
+
// THE second critical assertion: after a renewal — which reuses the
|
|
169
|
+
// manager's cached (agent-a) identity internally — the override must
|
|
170
|
+
// still win. The switch must not have reverted.
|
|
171
|
+
proc.stdin.write(JSON.stringify({
|
|
172
|
+
jsonrpc: '2.0', id: 5, method: 'tools/call', params: { name: 'whoami', arguments: {} },
|
|
173
|
+
}) + '\n');
|
|
174
|
+
await waitFor(() => stdoutBuf.includes('"id":5'), 15000, 'whoami after renewal');
|
|
175
|
+
expect(extractResponseText(stdoutBuf, 5)).toContain('agent-b');
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
proc?.kill();
|
|
179
|
+
rmSync(fakeHome, { recursive: true, force: true });
|
|
180
|
+
}
|
|
181
|
+
}, 60000);
|
|
182
|
+
});
|
|
183
|
+
function waitFor(predicate, ms, label) {
|
|
184
|
+
return new Promise((resolveOuter, reject) => {
|
|
185
|
+
const start = Date.now();
|
|
186
|
+
const tick = () => {
|
|
187
|
+
if (predicate()) {
|
|
188
|
+
resolveOuter();
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
if (Date.now() - start > ms) {
|
|
192
|
+
reject(new Error(`timeout waiting for ${label}`));
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
setTimeout(tick, 50);
|
|
196
|
+
};
|
|
197
|
+
tick();
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
function extractResponseText(buf, id) {
|
|
201
|
+
for (const line of buf.split('\n')) {
|
|
202
|
+
if (!line.includes(`"id":${id}`))
|
|
203
|
+
continue;
|
|
204
|
+
try {
|
|
205
|
+
const parsed = JSON.parse(line);
|
|
206
|
+
const text = parsed.result?.content?.[0]?.text;
|
|
207
|
+
if (typeof text === 'string')
|
|
208
|
+
return text;
|
|
209
|
+
}
|
|
210
|
+
catch { /* malformed line; skip */ }
|
|
211
|
+
}
|
|
212
|
+
return '';
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=agent-load-session-override-e2e.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-load-session-override-e2e.test.js","sourceRoot":"","sources":["../../src/__tests__/agent-load-session-override-e2e.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|