aismemory 0.6.0 → 0.6.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/README.md +16 -0
- package/dist/__tests__/agent-load-persistence.test.d.ts +1 -0
- package/dist/__tests__/agent-load-persistence.test.js +69 -0
- package/dist/__tests__/agent-load-persistence.test.js.map +1 -0
- package/dist/__tests__/doctor.test.d.ts +1 -0
- package/dist/__tests__/doctor.test.js +248 -0
- package/dist/__tests__/doctor.test.js.map +1 -0
- package/dist/__tests__/pipeline-ingestion.test.js +18 -4
- package/dist/__tests__/pipeline-ingestion.test.js.map +1 -1
- package/dist/__tests__/provisional-token-reauth.test.d.ts +1 -0
- package/dist/__tests__/provisional-token-reauth.test.js +156 -0
- package/dist/__tests__/provisional-token-reauth.test.js.map +1 -0
- package/dist/cli/doctor.d.ts +57 -0
- package/dist/cli/doctor.js +332 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/index.js +25 -15
- package/dist/index.js.map +1 -1
- package/dist/prompt-resource.js +1 -1
- package/dist/prompt-resource.js.map +1 -1
- package/package.json +13 -5
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { type OAuthCredentials } from '../oauth-credentials.js';
|
|
3
|
+
export type CheckStatus = 'PASS' | 'WARN' | 'FAIL';
|
|
4
|
+
export interface CheckResult {
|
|
5
|
+
name: string;
|
|
6
|
+
status: CheckStatus;
|
|
7
|
+
message: string;
|
|
8
|
+
hint?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface DoctorReport {
|
|
11
|
+
aisUrl: string;
|
|
12
|
+
checks: CheckResult[];
|
|
13
|
+
problemCount: number;
|
|
14
|
+
verdict: 'pass' | 'problems';
|
|
15
|
+
exitCode: 0 | 1;
|
|
16
|
+
}
|
|
17
|
+
export declare function checkNodeVersion(nodeVersion?: string, minMajor?: number): CheckResult;
|
|
18
|
+
export interface DnsLookupFn {
|
|
19
|
+
(hostname: string): Promise<{
|
|
20
|
+
address: string;
|
|
21
|
+
family: number;
|
|
22
|
+
}>;
|
|
23
|
+
}
|
|
24
|
+
export declare function checkDnsResolution(host: string, lookup?: DnsLookupFn): Promise<CheckResult>;
|
|
25
|
+
export interface TlsProbeFn {
|
|
26
|
+
(host: string, port: number, timeoutMs: number): Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
export declare function checkTlsReachability(host: string, probe?: TlsProbeFn, port?: number, timeoutMs?: number): Promise<CheckResult>;
|
|
29
|
+
export type FetchFn = typeof fetch;
|
|
30
|
+
export interface RestHealthResult extends CheckResult {
|
|
31
|
+
/** The `Date` response header, if present — reused by the clock-skew check. */
|
|
32
|
+
dateHeader?: string;
|
|
33
|
+
}
|
|
34
|
+
export declare function checkRestHealth(baseUrl: string, fetchImpl?: FetchFn): Promise<RestHealthResult>;
|
|
35
|
+
export declare function checkMcpEndpoint(baseUrl: string, fetchImpl?: FetchFn): Promise<CheckResult>;
|
|
36
|
+
export interface CredentialsCheckDeps {
|
|
37
|
+
load?: (home?: string) => OAuthCredentials | null;
|
|
38
|
+
now?: () => number;
|
|
39
|
+
fetchImpl?: FetchFn;
|
|
40
|
+
home?: string;
|
|
41
|
+
}
|
|
42
|
+
export declare function checkCredentials(baseUrl: string, deps?: CredentialsCheckDeps): Promise<CheckResult>;
|
|
43
|
+
export declare function checkProxyEnv(env?: NodeJS.ProcessEnv): CheckResult;
|
|
44
|
+
export declare function checkClockSkew(dateHeader: string | undefined, now?: () => number, warnThresholdMs?: number): CheckResult;
|
|
45
|
+
export interface DoctorOptions {
|
|
46
|
+
aisUrl?: string;
|
|
47
|
+
env?: NodeJS.ProcessEnv;
|
|
48
|
+
nodeVersion?: string;
|
|
49
|
+
now?: () => number;
|
|
50
|
+
fetchImpl?: FetchFn;
|
|
51
|
+
dnsLookup?: DnsLookupFn;
|
|
52
|
+
tlsProbe?: TlsProbeFn;
|
|
53
|
+
loadCreds?: (home?: string) => OAuthCredentials | null;
|
|
54
|
+
home?: string;
|
|
55
|
+
}
|
|
56
|
+
export declare function runDoctor(options?: DoctorOptions): Promise<DoctorReport>;
|
|
57
|
+
export declare function main(argv?: string[]): Promise<void>;
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* `aismemory doctor` — read-only self-diagnosis for "it doesn't work" reports.
|
|
4
|
+
*
|
|
5
|
+
* A new user whose MCP client can't reach AIS has no way to tell whether the
|
|
6
|
+
* problem is DNS, a corporate proxy, an unbonded agent, an expired token, or
|
|
7
|
+
* clock skew. This command runs a fixed set of read-only checks against the
|
|
8
|
+
* local environment and the AIS host and prints a PASS/WARN/FAIL report with
|
|
9
|
+
* a one-line remediation hint per problem — no writes to the API, no agent
|
|
10
|
+
* creation.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* npx aismemory doctor
|
|
14
|
+
* npx aismemory doctor --json
|
|
15
|
+
* AIS_URL=https://other.example.com npx aismemory doctor
|
|
16
|
+
*
|
|
17
|
+
* Exit codes:
|
|
18
|
+
* 0 — no FAIL checks (WARNs are still reported but don't fail the command)
|
|
19
|
+
* 1 — at least one FAIL check
|
|
20
|
+
*/
|
|
21
|
+
import { lookup as dnsLookupDefault } from 'node:dns/promises';
|
|
22
|
+
import { connect as tlsConnectDefault } from 'node:tls';
|
|
23
|
+
import { loadOAuthCredentials, credentialsFilePath } from '../oauth-credentials.js';
|
|
24
|
+
import { isCredsStale } from '../auth-staleness.js';
|
|
25
|
+
/** Minimum Node major version this package requires (per @modelcontextprotocol/sdk engines). */
|
|
26
|
+
const MIN_NODE_MAJOR = 18;
|
|
27
|
+
const PROXY_ENV_KEYS = ['HTTPS_PROXY', 'https_proxy', 'HTTP_PROXY', 'http_proxy', 'NO_PROXY', 'no_proxy'];
|
|
28
|
+
const CLOCK_SKEW_WARN_MS = 5 * 60 * 1000;
|
|
29
|
+
function errMsg(err) {
|
|
30
|
+
return err instanceof Error ? err.message : String(err);
|
|
31
|
+
}
|
|
32
|
+
// ── Individual checks ────────────────────────────────────
|
|
33
|
+
export function checkNodeVersion(nodeVersion = process.version, minMajor = MIN_NODE_MAJOR) {
|
|
34
|
+
const match = /^v?(\d+)\./.exec(nodeVersion);
|
|
35
|
+
const major = match ? Number(match[1]) : NaN;
|
|
36
|
+
if (Number.isNaN(major)) {
|
|
37
|
+
return {
|
|
38
|
+
name: 'Node version',
|
|
39
|
+
status: 'WARN',
|
|
40
|
+
message: `Could not parse Node version string "${nodeVersion}".`,
|
|
41
|
+
hint: `aismemory requires Node >= ${minMajor}.`,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
if (major < minMajor) {
|
|
45
|
+
return {
|
|
46
|
+
name: 'Node version',
|
|
47
|
+
status: 'FAIL',
|
|
48
|
+
message: `Node ${nodeVersion} is below the required minimum (>= ${minMajor}).`,
|
|
49
|
+
hint: `Upgrade Node (e.g. via nvm: "nvm install ${minMajor}") and retry.`,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
return {
|
|
53
|
+
name: 'Node version',
|
|
54
|
+
status: 'PASS',
|
|
55
|
+
message: `Node ${nodeVersion} meets the minimum requirement (>= ${minMajor}).`,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export async function checkDnsResolution(host, lookup = dnsLookupDefault) {
|
|
59
|
+
try {
|
|
60
|
+
const { address } = await lookup(host);
|
|
61
|
+
return {
|
|
62
|
+
name: 'DNS resolution',
|
|
63
|
+
status: 'PASS',
|
|
64
|
+
message: `${host} resolves to ${address}.`,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch (err) {
|
|
68
|
+
return {
|
|
69
|
+
name: 'DNS resolution',
|
|
70
|
+
status: 'FAIL',
|
|
71
|
+
message: `Could not resolve DNS for ${host}: ${errMsg(err)}.`,
|
|
72
|
+
hint: 'Check your internet connection and DNS settings (or /etc/resolv.conf).',
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function defaultTlsProbe(host, port, timeoutMs) {
|
|
77
|
+
return new Promise((resolve, reject) => {
|
|
78
|
+
let settled = false;
|
|
79
|
+
const socket = tlsConnectDefault({ host, port, servername: host, timeout: timeoutMs }, () => {
|
|
80
|
+
if (settled)
|
|
81
|
+
return;
|
|
82
|
+
settled = true;
|
|
83
|
+
socket.end();
|
|
84
|
+
resolve();
|
|
85
|
+
});
|
|
86
|
+
socket.on('error', (err) => {
|
|
87
|
+
if (settled)
|
|
88
|
+
return;
|
|
89
|
+
settled = true;
|
|
90
|
+
reject(err);
|
|
91
|
+
});
|
|
92
|
+
socket.on('timeout', () => {
|
|
93
|
+
if (settled)
|
|
94
|
+
return;
|
|
95
|
+
settled = true;
|
|
96
|
+
socket.destroy();
|
|
97
|
+
reject(new Error(`connection to ${host}:${port} timed out after ${timeoutMs}ms`));
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
export async function checkTlsReachability(host, probe = defaultTlsProbe, port = 443, timeoutMs = 5000) {
|
|
102
|
+
try {
|
|
103
|
+
await probe(host, port, timeoutMs);
|
|
104
|
+
return {
|
|
105
|
+
name: 'TLS reachability',
|
|
106
|
+
status: 'PASS',
|
|
107
|
+
message: `${host}:${port} accepts TLS connections.`,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
catch (err) {
|
|
111
|
+
return {
|
|
112
|
+
name: 'TLS reachability',
|
|
113
|
+
status: 'FAIL',
|
|
114
|
+
message: `Could not open a TLS connection to ${host}:${port}: ${errMsg(err)}.`,
|
|
115
|
+
hint: 'A firewall, VPN, or corporate proxy may be blocking outbound HTTPS. See the proxy check below.',
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
export async function checkRestHealth(baseUrl, fetchImpl = fetch) {
|
|
120
|
+
const url = `${baseUrl}/livez`;
|
|
121
|
+
try {
|
|
122
|
+
const res = await fetchImpl(url);
|
|
123
|
+
const dateHeader = res.headers.get('date') ?? undefined;
|
|
124
|
+
if (res.ok) {
|
|
125
|
+
return {
|
|
126
|
+
name: 'REST API health',
|
|
127
|
+
status: 'PASS',
|
|
128
|
+
message: `${url} responded HTTP ${res.status} (alive).`,
|
|
129
|
+
dateHeader,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
name: 'REST API health',
|
|
134
|
+
status: 'WARN',
|
|
135
|
+
message: `${url} responded HTTP ${res.status} — server reachable but reporting a problem.`,
|
|
136
|
+
hint: 'The AIS backend may be degraded. Check again shortly.',
|
|
137
|
+
dateHeader,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
return {
|
|
142
|
+
name: 'REST API health',
|
|
143
|
+
status: 'FAIL',
|
|
144
|
+
message: `Could not reach ${url}: ${errMsg(err)}.`,
|
|
145
|
+
hint: 'Check network connectivity — see the DNS/TLS checks above.',
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
export async function checkMcpEndpoint(baseUrl, fetchImpl = fetch) {
|
|
150
|
+
const url = `${baseUrl}/mcp`;
|
|
151
|
+
try {
|
|
152
|
+
const res = await fetchImpl(url);
|
|
153
|
+
// Any resolved HTTP response (even 401 "auth required") proves the MCP
|
|
154
|
+
// endpoint is reachable — only a network-level failure means "down".
|
|
155
|
+
const authNote = res.status === 401 || res.status === 403 ? ' (auth required, as expected without a key)' : '';
|
|
156
|
+
return {
|
|
157
|
+
name: 'MCP HTTP endpoint',
|
|
158
|
+
status: 'PASS',
|
|
159
|
+
message: `${url} responded HTTP ${res.status}${authNote}.`,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
return {
|
|
164
|
+
name: 'MCP HTTP endpoint',
|
|
165
|
+
status: 'FAIL',
|
|
166
|
+
message: `Could not reach ${url}: ${errMsg(err)}.`,
|
|
167
|
+
hint: 'Check network connectivity — see the DNS/TLS checks above.',
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
export async function checkCredentials(baseUrl, deps = {}) {
|
|
172
|
+
const load = deps.load ?? loadOAuthCredentials;
|
|
173
|
+
const now = deps.now ?? Date.now;
|
|
174
|
+
const fetchImpl = deps.fetchImpl ?? fetch;
|
|
175
|
+
const home = deps.home;
|
|
176
|
+
const path = credentialsFilePath(home);
|
|
177
|
+
const creds = load(home);
|
|
178
|
+
if (!creds) {
|
|
179
|
+
return {
|
|
180
|
+
name: 'Credentials',
|
|
181
|
+
status: 'WARN',
|
|
182
|
+
message: `No credentials found at ${path} — this device has not bonded to an agent yet.`,
|
|
183
|
+
hint: 'Run any aismemory tool from your MCP client once and follow the printed bond URL/code (takes ~30s).',
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
if (isCredsStale(creds.expiresAt, now())) {
|
|
187
|
+
return {
|
|
188
|
+
name: 'Credentials',
|
|
189
|
+
status: 'WARN',
|
|
190
|
+
message: `Credentials at ${path} are expired or expiring within 5 minutes (expiresAt: ${creds.expiresAt}).`,
|
|
191
|
+
hint: 'No action needed — the next tool call re-authenticates automatically (silently if a device key is enrolled).',
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
try {
|
|
195
|
+
const res = await fetchImpl(`${baseUrl}/v1/agents/${creds.agentId}`, {
|
|
196
|
+
headers: { Authorization: `Bearer ${creds.token}` },
|
|
197
|
+
});
|
|
198
|
+
if (res.ok) {
|
|
199
|
+
return {
|
|
200
|
+
name: 'Credentials',
|
|
201
|
+
status: 'PASS',
|
|
202
|
+
message: `Bonded as agent ${creds.agentId}; AIS accepted the saved token.`,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
name: 'Credentials',
|
|
207
|
+
status: 'WARN',
|
|
208
|
+
message: `Saved credentials found, but AIS returned HTTP ${res.status} for agent ${creds.agentId}.`,
|
|
209
|
+
hint: 'The token may be revoked or the agent archived. Re-run any aismemory tool to trigger re-authentication.',
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
catch (err) {
|
|
213
|
+
return {
|
|
214
|
+
name: 'Credentials',
|
|
215
|
+
status: 'FAIL',
|
|
216
|
+
message: `Could not verify saved credentials with AIS: ${errMsg(err)}.`,
|
|
217
|
+
hint: 'Check network connectivity — see the REST API health check above.',
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
export function checkProxyEnv(env = process.env) {
|
|
222
|
+
const set = PROXY_ENV_KEYS.filter((key) => Boolean(env[key]));
|
|
223
|
+
if (set.length === 0) {
|
|
224
|
+
return {
|
|
225
|
+
name: 'Proxy environment',
|
|
226
|
+
status: 'PASS',
|
|
227
|
+
message: 'No HTTP(S)_PROXY / NO_PROXY environment variables set.',
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
name: 'Proxy environment',
|
|
232
|
+
status: 'WARN',
|
|
233
|
+
message: `Proxy environment variable(s) detected: ${set.join(', ')}.`,
|
|
234
|
+
hint: 'A corporate proxy can block or MITM TLS to ais.agentsandswarms.ai. If aismemory only fails on this network, ask IT to allowlist the host or trust the proxy CA.',
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
export function checkClockSkew(dateHeader, now = Date.now, warnThresholdMs = CLOCK_SKEW_WARN_MS) {
|
|
238
|
+
if (!dateHeader) {
|
|
239
|
+
return {
|
|
240
|
+
name: 'Clock skew',
|
|
241
|
+
status: 'WARN',
|
|
242
|
+
message: 'No server Date header available to compare (REST API health check did not return one).',
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
const remoteMs = Date.parse(dateHeader);
|
|
246
|
+
if (Number.isNaN(remoteMs)) {
|
|
247
|
+
return {
|
|
248
|
+
name: 'Clock skew',
|
|
249
|
+
status: 'WARN',
|
|
250
|
+
message: `Could not parse the server Date header: "${dateHeader}".`,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
const skewMs = Math.abs(now() - remoteMs);
|
|
254
|
+
const skewMinutes = (skewMs / 60000).toFixed(1);
|
|
255
|
+
if (skewMs > warnThresholdMs) {
|
|
256
|
+
return {
|
|
257
|
+
name: 'Clock skew',
|
|
258
|
+
status: 'WARN',
|
|
259
|
+
message: `Local clock differs from the AIS server by ~${skewMinutes} minutes.`,
|
|
260
|
+
hint: 'Large clock skew can invalidate OAuth tokens. Sync your system clock (e.g. enable automatic time/NTP).',
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
return {
|
|
264
|
+
name: 'Clock skew',
|
|
265
|
+
status: 'PASS',
|
|
266
|
+
message: `Local clock is within ${skewMinutes} min of the AIS server.`,
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
export async function runDoctor(options = {}) {
|
|
270
|
+
const env = options.env ?? process.env;
|
|
271
|
+
const aisUrl = options.aisUrl ?? env['AIS_URL'] ?? 'https://ais.agentsandswarms.ai';
|
|
272
|
+
const host = new URL(aisUrl).hostname;
|
|
273
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
274
|
+
const now = options.now ?? Date.now;
|
|
275
|
+
const checks = [];
|
|
276
|
+
checks.push(checkNodeVersion(options.nodeVersion));
|
|
277
|
+
checks.push(await checkDnsResolution(host, options.dnsLookup));
|
|
278
|
+
checks.push(await checkTlsReachability(host, options.tlsProbe));
|
|
279
|
+
const health = await checkRestHealth(aisUrl, fetchImpl);
|
|
280
|
+
checks.push(health);
|
|
281
|
+
checks.push(await checkMcpEndpoint(aisUrl, fetchImpl));
|
|
282
|
+
checks.push(await checkCredentials(aisUrl, {
|
|
283
|
+
fetchImpl,
|
|
284
|
+
load: options.loadCreds,
|
|
285
|
+
home: options.home,
|
|
286
|
+
now,
|
|
287
|
+
}));
|
|
288
|
+
checks.push(checkProxyEnv(env));
|
|
289
|
+
checks.push(checkClockSkew(health.dateHeader, now));
|
|
290
|
+
const problemCount = checks.filter((c) => c.status !== 'PASS').length;
|
|
291
|
+
const hasFail = checks.some((c) => c.status === 'FAIL');
|
|
292
|
+
return {
|
|
293
|
+
aisUrl,
|
|
294
|
+
checks,
|
|
295
|
+
problemCount,
|
|
296
|
+
verdict: problemCount === 0 ? 'pass' : 'problems',
|
|
297
|
+
exitCode: hasFail ? 1 : 0,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
// ── CLI formatting + entrypoint ──────────────────────────
|
|
301
|
+
function formatText(report) {
|
|
302
|
+
const lines = [];
|
|
303
|
+
lines.push(`aismemory doctor — ${report.aisUrl}`);
|
|
304
|
+
lines.push('');
|
|
305
|
+
for (const c of report.checks) {
|
|
306
|
+
lines.push(`[${c.status}] ${c.name}: ${c.message}`);
|
|
307
|
+
if (c.hint && c.status !== 'PASS') {
|
|
308
|
+
lines.push(` hint: ${c.hint}`);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
lines.push('');
|
|
312
|
+
lines.push(report.problemCount === 0
|
|
313
|
+
? 'doctor: all checks passed'
|
|
314
|
+
: `doctor: ${report.problemCount} problem(s) found`);
|
|
315
|
+
return lines.join('\n');
|
|
316
|
+
}
|
|
317
|
+
export async function main(argv = process.argv.slice(2)) {
|
|
318
|
+
const json = argv.includes('--json');
|
|
319
|
+
const report = await runDoctor();
|
|
320
|
+
if (json) {
|
|
321
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
process.stdout.write(`${formatText(report)}\n`);
|
|
325
|
+
}
|
|
326
|
+
process.exit(report.exitCode);
|
|
327
|
+
}
|
|
328
|
+
main().catch((err) => {
|
|
329
|
+
process.stderr.write(`[aismemory doctor] Fatal: ${errMsg(err)}\n`);
|
|
330
|
+
process.exit(1);
|
|
331
|
+
});
|
|
332
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -224,31 +224,31 @@ class BondPendingError extends Error {
|
|
|
224
224
|
userCode;
|
|
225
225
|
bondPending = true;
|
|
226
226
|
constructor(verificationUri, userCode) {
|
|
227
|
-
super(`Memory bond required.\n\n` +
|
|
227
|
+
super(`Memory bond required — ask your human to approve now.\n\n` +
|
|
228
228
|
`Visit: ${verificationUri}\n` +
|
|
229
229
|
`Code: ${userCode}\n\n` +
|
|
230
|
-
`Enter your email and tap Approve, then retry this tool. Takes about 30 seconds
|
|
230
|
+
`Enter your email and tap Approve, then retry this tool. Takes about 30 seconds.\n` +
|
|
231
|
+
`Heads up: this code expires in 30 minutes, and unclaimed agents (and their memories) are archived after 7 days.`);
|
|
231
232
|
this.verificationUri = verificationUri;
|
|
232
233
|
this.userCode = userCode;
|
|
233
234
|
this.name = 'BondPendingError';
|
|
234
235
|
}
|
|
235
236
|
}
|
|
236
|
-
async function startDeviceFlow() {
|
|
237
|
+
async function startDeviceFlow(priorProvisionalToken) {
|
|
237
238
|
emitTelemetry({ event: 'auth.device_flow.start' });
|
|
238
239
|
stderr('Starting authentication...');
|
|
239
|
-
const authRes = (await aisPost('/v1/oauth/device/authorize', {
|
|
240
|
-
name: `agent-${homedir().split('/').pop() ?? 'user'}`,
|
|
241
|
-
}));
|
|
240
|
+
const authRes = (await aisPost('/v1/oauth/device/authorize', { name: `agent-${homedir().split('/').pop() ?? 'user'}` }, priorProvisionalToken));
|
|
242
241
|
if (!authRes.success || !authRes.data) {
|
|
243
242
|
throw new Error(`Authentication failed: ${authRes.error?.message ?? 'Unknown error'}`);
|
|
244
243
|
}
|
|
245
|
-
const { device_code, user_code, verification_uri_complete, interval, agent_id, provisional_tenant_id } = authRes.data;
|
|
244
|
+
const { device_code, user_code, verification_uri_complete, interval, agent_id, provisional_tenant_id, provisional_token } = authRes.data;
|
|
246
245
|
stderr('');
|
|
247
246
|
stderr('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
248
247
|
stderr(' aismemory — memory bond required');
|
|
249
248
|
stderr('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
250
249
|
stderr(` Bond URL : ${verification_uri_complete}`);
|
|
251
250
|
stderr(` Code : ${user_code}`);
|
|
251
|
+
stderr(' Code expires in 30 min; unclaimed agents are archived after 7 days.');
|
|
252
252
|
stderr('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
253
253
|
const flow = {
|
|
254
254
|
device_code,
|
|
@@ -256,6 +256,7 @@ async function startDeviceFlow() {
|
|
|
256
256
|
verification_uri_complete,
|
|
257
257
|
agent_id,
|
|
258
258
|
provisional_tenant_id,
|
|
259
|
+
provisional_token,
|
|
259
260
|
// poll is assigned below after flowRef is captured so pollForToken holds
|
|
260
261
|
// a reference to the live flow object for URL updates on auto-restart.
|
|
261
262
|
dead: false,
|
|
@@ -276,7 +277,7 @@ async function startDeviceFlow() {
|
|
|
276
277
|
return flow;
|
|
277
278
|
}
|
|
278
279
|
async function pollForToken(device_code, interval, agent_id, provisional_tenant_id,
|
|
279
|
-
/** Mutable ref so auto-restart can update the surfaced URL in ActiveDeviceFlow */
|
|
280
|
+
/** Mutable ref so auto-restart can update the surfaced URL and provisional token in ActiveDeviceFlow */
|
|
280
281
|
flowRef) {
|
|
281
282
|
const pollIntervalMs = Math.max(interval, 5) * 1000;
|
|
282
283
|
const handle = {
|
|
@@ -307,9 +308,7 @@ flowRef) {
|
|
|
307
308
|
}
|
|
308
309
|
},
|
|
309
310
|
startNewFlow: async () => {
|
|
310
|
-
const authRes = (await aisPost('/v1/oauth/device/authorize', {
|
|
311
|
-
name: `agent-${homedir().split('/').pop() ?? 'user'}`,
|
|
312
|
-
}));
|
|
311
|
+
const authRes = (await aisPost('/v1/oauth/device/authorize', { name: `agent-${homedir().split('/').pop() ?? 'user'}` }, flowRef?.provisional_token));
|
|
313
312
|
if (!authRes.success || !authRes.data) {
|
|
314
313
|
throw new Error(`Re-authorization failed: ${authRes.error?.message ?? 'Unknown error'}`);
|
|
315
314
|
}
|
|
@@ -319,10 +318,13 @@ flowRef) {
|
|
|
319
318
|
user_code: authRes.data.user_code,
|
|
320
319
|
};
|
|
321
320
|
// Update the mutable ref so the caller (ensureCredentials) can surface
|
|
322
|
-
// the new URL to the human without restarting the MCP process
|
|
321
|
+
// the new URL to the human without restarting the MCP process, and so
|
|
322
|
+
// a THIRD expiry in the same flow re-sends the latest provisional
|
|
323
|
+
// token rather than a stale, already-superseded one.
|
|
323
324
|
if (flowRef) {
|
|
324
325
|
flowRef.verification_uri_complete = newHandle.verification_uri_complete;
|
|
325
326
|
flowRef.user_code = newHandle.user_code;
|
|
327
|
+
flowRef.provisional_token = authRes.data.provisional_token;
|
|
326
328
|
}
|
|
327
329
|
stderr('');
|
|
328
330
|
stderr('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');
|
|
@@ -404,7 +406,7 @@ const tools = [
|
|
|
404
406
|
},
|
|
405
407
|
{
|
|
406
408
|
name: 'dream',
|
|
407
|
-
description: 'Trigger a memory consolidation dream cycle — promotes important memories and archives old ones.',
|
|
409
|
+
description: 'Trigger a memory consolidation dream cycle — promotes important memories and archives old ones. Promotion only scans the session tier; active-tier memories move via context-clear or handoff, not dream.',
|
|
408
410
|
inputSchema: { type: 'object', properties: {} },
|
|
409
411
|
},
|
|
410
412
|
{
|
|
@@ -523,6 +525,10 @@ async function main() {
|
|
|
523
525
|
await import('./cli/sync-memory.js');
|
|
524
526
|
return; // sync-memory.ts calls process.exit() on failure
|
|
525
527
|
}
|
|
528
|
+
if (process.argv[2] === 'doctor') {
|
|
529
|
+
await import('./cli/doctor.js');
|
|
530
|
+
return; // doctor.ts calls process.exit() itself
|
|
531
|
+
}
|
|
526
532
|
// Agent API key auth mode (CORBOT-B1D3244C) — unattended machines. Checked
|
|
527
533
|
// before any device-flow / OAuth-credential / DID-key-auth setup below so
|
|
528
534
|
// this mode NEVER falls back to those paths (that fallback is what used to
|
|
@@ -609,7 +615,7 @@ async function main() {
|
|
|
609
615
|
stderr(`Key auth failed: ${err instanceof Error ? err.message : String(err)}. Falling back to device flow.`);
|
|
610
616
|
}
|
|
611
617
|
if (!activeFlow || activeFlow.dead) {
|
|
612
|
-
activeFlow = await startDeviceFlow();
|
|
618
|
+
activeFlow = await startDeviceFlow(activeFlow?.provisional_token);
|
|
613
619
|
}
|
|
614
620
|
const sentinel = Symbol('bond-pending');
|
|
615
621
|
// poll is always set by startDeviceFlow before it returns; this guard
|
|
@@ -630,7 +636,7 @@ async function main() {
|
|
|
630
636
|
// Always say WHY the old flow died: a silent discard here hid three
|
|
631
637
|
// weeks of broken cold-start bonding (CORBOT-9CE03C6E).
|
|
632
638
|
stderr(`Device flow discarded (${err instanceof Error ? err.message : String(err)}); starting a fresh one.`);
|
|
633
|
-
activeFlow = await startDeviceFlow();
|
|
639
|
+
activeFlow = await startDeviceFlow(activeFlow.provisional_token);
|
|
634
640
|
throw new BondPendingError(activeFlow.verification_uri_complete, activeFlow.user_code);
|
|
635
641
|
}
|
|
636
642
|
if (got === sentinel) {
|
|
@@ -766,8 +772,12 @@ async function main() {
|
|
|
766
772
|
const target = await resolveAgentForLoad(token, query);
|
|
767
773
|
agentId = target.id;
|
|
768
774
|
// Persist the switch so subsequent tool calls use the new agent.
|
|
775
|
+
// saveCredentials() MUST be called here so that a process restart
|
|
776
|
+
// (silent MCP reconnect) restores the switched agent from disk
|
|
777
|
+
// instead of silently reverting to the default (CORBOT-497C7FA3).
|
|
769
778
|
if (creds) {
|
|
770
779
|
creds = { ...creds, agentId };
|
|
780
|
+
saveCredentials(creds);
|
|
771
781
|
}
|
|
772
782
|
agentContext = await hydrateIdentity(AIS_URL, agentId, token);
|
|
773
783
|
applyMemoryRefresh(agentId, token);
|