aismemory 0.8.2 → 0.8.4

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 (198) hide show
  1. package/README.md +146 -3
  2. package/dist/__tests__/agent-key-mode.test.js +46 -5
  3. package/dist/__tests__/agent-key-mode.test.js.map +1 -1
  4. package/dist/__tests__/ais-http.test.js +49 -1
  5. package/dist/__tests__/ais-http.test.js.map +1 -1
  6. package/dist/__tests__/auto-enroll-key.test.js +20 -1
  7. package/dist/__tests__/auto-enroll-key.test.js.map +1 -1
  8. package/dist/__tests__/cli-info.test.d.ts +1 -0
  9. package/dist/__tests__/cli-info.test.js +117 -0
  10. package/dist/__tests__/cli-info.test.js.map +1 -0
  11. package/dist/__tests__/client-credential-expiry.test.d.ts +1 -0
  12. package/dist/__tests__/client-credential-expiry.test.js +319 -0
  13. package/dist/__tests__/client-credential-expiry.test.js.map +1 -0
  14. package/dist/__tests__/credential-resolution.test.js +10 -4
  15. package/dist/__tests__/credential-resolution.test.js.map +1 -1
  16. package/dist/__tests__/declared-agent.test.d.ts +1 -0
  17. package/dist/__tests__/declared-agent.test.js +60 -0
  18. package/dist/__tests__/declared-agent.test.js.map +1 -0
  19. package/dist/__tests__/doctor.test.js +21 -2
  20. package/dist/__tests__/doctor.test.js.map +1 -1
  21. package/dist/__tests__/dream-poll.test.d.ts +1 -0
  22. package/dist/__tests__/dream-poll.test.js +130 -0
  23. package/dist/__tests__/dream-poll.test.js.map +1 -0
  24. package/dist/__tests__/enable-key-auth.test.d.ts +1 -0
  25. package/dist/__tests__/enable-key-auth.test.js +180 -0
  26. package/dist/__tests__/enable-key-auth.test.js.map +1 -0
  27. package/dist/__tests__/existing-hashes.test.js +3 -6
  28. package/dist/__tests__/existing-hashes.test.js.map +1 -1
  29. package/dist/__tests__/full-context-view-forwarding.test.js +20 -1
  30. package/dist/__tests__/full-context-view-forwarding.test.js.map +1 -1
  31. package/dist/__tests__/hooks.test.d.ts +1 -0
  32. package/dist/__tests__/hooks.test.js +455 -0
  33. package/dist/__tests__/hooks.test.js.map +1 -0
  34. package/dist/__tests__/hydration.test.js +2 -0
  35. package/dist/__tests__/hydration.test.js.map +1 -1
  36. package/dist/__tests__/install.test.js +28 -1
  37. package/dist/__tests__/install.test.js.map +1 -1
  38. package/dist/__tests__/invite-accept.test.d.ts +1 -0
  39. package/dist/__tests__/invite-accept.test.js +282 -0
  40. package/dist/__tests__/invite-accept.test.js.map +1 -0
  41. package/dist/__tests__/list-all-agents.test.js +17 -15
  42. package/dist/__tests__/list-all-agents.test.js.map +1 -1
  43. package/dist/__tests__/mcp-instructions.test.d.ts +1 -0
  44. package/dist/__tests__/mcp-instructions.test.js +26 -0
  45. package/dist/__tests__/mcp-instructions.test.js.map +1 -0
  46. package/dist/__tests__/mcp-tools.test.js +136 -5
  47. package/dist/__tests__/mcp-tools.test.js.map +1 -1
  48. package/dist/__tests__/memory-export.test.d.ts +1 -0
  49. package/dist/__tests__/memory-export.test.js +78 -0
  50. package/dist/__tests__/memory-export.test.js.map +1 -0
  51. package/dist/__tests__/missing-credential-help.test.d.ts +1 -0
  52. package/dist/__tests__/missing-credential-help.test.js +14 -0
  53. package/dist/__tests__/missing-credential-help.test.js.map +1 -0
  54. package/dist/__tests__/owner-credentials.test.d.ts +1 -0
  55. package/dist/__tests__/owner-credentials.test.js +250 -0
  56. package/dist/__tests__/owner-credentials.test.js.map +1 -0
  57. package/dist/__tests__/owner-keychain-agent-load.test.d.ts +1 -0
  58. package/dist/__tests__/owner-keychain-agent-load.test.js +57 -0
  59. package/dist/__tests__/owner-keychain-agent-load.test.js.map +1 -0
  60. package/dist/__tests__/recall-order-by.test.d.ts +1 -0
  61. package/dist/__tests__/recall-order-by.test.js +115 -0
  62. package/dist/__tests__/recall-order-by.test.js.map +1 -0
  63. package/dist/__tests__/reconnect-survival-e2e.test.js +3 -2
  64. package/dist/__tests__/reconnect-survival-e2e.test.js.map +1 -1
  65. package/dist/__tests__/remember-duplicate-truth.test.js +11 -0
  66. package/dist/__tests__/remember-duplicate-truth.test.js.map +1 -1
  67. package/dist/__tests__/request-timeout.test.js +15 -0
  68. package/dist/__tests__/request-timeout.test.js.map +1 -1
  69. package/dist/__tests__/resolve-agent-preference.test.js +19 -8
  70. package/dist/__tests__/resolve-agent-preference.test.js.map +1 -1
  71. package/dist/__tests__/retry-after.test.js +53 -0
  72. package/dist/__tests__/retry-after.test.js.map +1 -1
  73. package/dist/__tests__/run-pass-mode.test.js +34 -1
  74. package/dist/__tests__/run-pass-mode.test.js.map +1 -1
  75. package/dist/__tests__/session-identity.test.js +63 -0
  76. package/dist/__tests__/session-identity.test.js.map +1 -1
  77. package/dist/__tests__/signin-keychain.test.d.ts +1 -0
  78. package/dist/__tests__/signin-keychain.test.js +79 -0
  79. package/dist/__tests__/signin-keychain.test.js.map +1 -0
  80. package/dist/__tests__/startup-identity.test.d.ts +1 -0
  81. package/dist/__tests__/startup-identity.test.js +213 -0
  82. package/dist/__tests__/startup-identity.test.js.map +1 -0
  83. package/dist/__tests__/sync-auth.test.d.ts +1 -0
  84. package/dist/__tests__/sync-auth.test.js +69 -0
  85. package/dist/__tests__/sync-auth.test.js.map +1 -0
  86. package/dist/__tests__/sync-doc.test.d.ts +1 -0
  87. package/dist/__tests__/sync-doc.test.js +13 -0
  88. package/dist/__tests__/sync-doc.test.js.map +1 -0
  89. package/dist/__tests__/sync-memory-cli.test.js +1 -1
  90. package/dist/__tests__/sync-memory-cli.test.js.map +1 -1
  91. package/dist/__tests__/tool-args.test.js +6 -0
  92. package/dist/__tests__/tool-args.test.js.map +1 -1
  93. package/dist/__tests__/version-check.test.js +16 -1
  94. package/dist/__tests__/version-check.test.js.map +1 -1
  95. package/dist/agent-key-mode.js +24 -24
  96. package/dist/agent-key-mode.js.map +1 -1
  97. package/dist/agent-preference.d.ts +4 -0
  98. package/dist/agent-preference.js +7 -1
  99. package/dist/agent-preference.js.map +1 -1
  100. package/dist/ais-http-error.d.ts +5 -0
  101. package/dist/ais-http-error.js +10 -0
  102. package/dist/ais-http-error.js.map +1 -1
  103. package/dist/ais-http.d.ts +2 -0
  104. package/dist/ais-http.js +41 -6
  105. package/dist/ais-http.js.map +1 -1
  106. package/dist/auto-handoff.js +2 -1
  107. package/dist/auto-handoff.js.map +1 -1
  108. package/dist/cli/doctor.d.ts +8 -0
  109. package/dist/cli/doctor.js +19 -0
  110. package/dist/cli/doctor.js.map +1 -1
  111. package/dist/cli/enable-key-auth.js +39 -18
  112. package/dist/cli/enable-key-auth.js.map +1 -1
  113. package/dist/cli/export-harness.d.ts +13 -0
  114. package/dist/cli/export-harness.js +110 -0
  115. package/dist/cli/export-harness.js.map +1 -0
  116. package/dist/cli/hooks.d.ts +62 -0
  117. package/dist/cli/hooks.js +634 -0
  118. package/dist/cli/hooks.js.map +1 -0
  119. package/dist/cli/install.d.ts +4 -0
  120. package/dist/cli/install.js +44 -5
  121. package/dist/cli/install.js.map +1 -1
  122. package/dist/cli/invite-accept.d.ts +67 -0
  123. package/dist/cli/invite-accept.js +295 -0
  124. package/dist/cli/invite-accept.js.map +1 -0
  125. package/dist/cli/owner-credentials.d.ts +52 -0
  126. package/dist/cli/owner-credentials.js +387 -0
  127. package/dist/cli/owner-credentials.js.map +1 -0
  128. package/dist/cli/sync-memory.js +7 -9
  129. package/dist/cli/sync-memory.js.map +1 -1
  130. package/dist/cli-info.d.ts +18 -0
  131. package/dist/cli-info.js +77 -0
  132. package/dist/cli-info.js.map +1 -0
  133. package/dist/credential-expiry.d.ts +10 -0
  134. package/dist/credential-expiry.js +41 -0
  135. package/dist/credential-expiry.js.map +1 -0
  136. package/dist/credential-whoami.js +1 -1
  137. package/dist/credential-whoami.js.map +1 -1
  138. package/dist/declared-agent.d.ts +20 -0
  139. package/dist/declared-agent.js +40 -0
  140. package/dist/declared-agent.js.map +1 -0
  141. package/dist/device-poll.d.ts +1 -0
  142. package/dist/device-poll.js.map +1 -1
  143. package/dist/dream-poll.d.ts +19 -0
  144. package/dist/dream-poll.js +93 -0
  145. package/dist/dream-poll.js.map +1 -0
  146. package/dist/env-agent.d.ts +6 -1
  147. package/dist/env-agent.js +18 -5
  148. package/dist/env-agent.js.map +1 -1
  149. package/dist/hydration.js +2 -1
  150. package/dist/hydration.js.map +1 -1
  151. package/dist/index.d.ts +1 -0
  152. package/dist/index.js +145 -18
  153. package/dist/index.js.map +1 -1
  154. package/dist/key-auth.d.ts +13 -3
  155. package/dist/key-auth.js +27 -5
  156. package/dist/key-auth.js.map +1 -1
  157. package/dist/mcp/tools.js +55 -25
  158. package/dist/mcp/tools.js.map +1 -1
  159. package/dist/mcp-instructions.d.ts +6 -0
  160. package/dist/mcp-instructions.js +7 -0
  161. package/dist/mcp-instructions.js.map +1 -0
  162. package/dist/memory-export.d.ts +30 -0
  163. package/dist/memory-export.js +116 -0
  164. package/dist/memory-export.js.map +1 -0
  165. package/dist/pipeline/bulk-store.d.ts +2 -5
  166. package/dist/pipeline/bulk-store.js +2 -4
  167. package/dist/pipeline/bulk-store.js.map +1 -1
  168. package/dist/pipeline/existing-hashes.d.ts +2 -5
  169. package/dist/pipeline/existing-hashes.js +1 -2
  170. package/dist/pipeline/existing-hashes.js.map +1 -1
  171. package/dist/pipeline/sync-auth.d.ts +12 -0
  172. package/dist/pipeline/sync-auth.js +64 -0
  173. package/dist/pipeline/sync-auth.js.map +1 -0
  174. package/dist/refresh.js +2 -1
  175. package/dist/refresh.js.map +1 -1
  176. package/dist/request-timeout.d.ts +4 -4
  177. package/dist/request-timeout.js +15 -6
  178. package/dist/request-timeout.js.map +1 -1
  179. package/dist/run-pass-mode.js +48 -15
  180. package/dist/run-pass-mode.js.map +1 -1
  181. package/dist/session-identity.js +14 -12
  182. package/dist/session-identity.js.map +1 -1
  183. package/dist/signin-keychain.d.ts +54 -0
  184. package/dist/signin-keychain.js +200 -0
  185. package/dist/signin-keychain.js.map +1 -0
  186. package/dist/startup-identity.d.ts +71 -0
  187. package/dist/startup-identity.js +213 -0
  188. package/dist/startup-identity.js.map +1 -0
  189. package/dist/tool-args.d.ts +10 -0
  190. package/dist/tool-args.js +39 -0
  191. package/dist/tool-args.js.map +1 -1
  192. package/dist/types.d.ts +8 -0
  193. package/dist/version-check.d.ts +8 -0
  194. package/dist/version-check.js +21 -1
  195. package/dist/version-check.js.map +1 -1
  196. package/dist/workspace-key-mode.js +54 -33
  197. package/dist/workspace-key-mode.js.map +1 -1
  198. package/package.json +1 -1
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Owner terminal sign-in credentials in the OS keychain (CORBOT-51CAC5E8).
3
+ *
4
+ * After device-flow approval, renewal + access tokens live only in the
5
+ * keychain — never as bearer secrets on disk under ~/.aismemory.
6
+ * Design: docs/superpowers/specs/2026-09-28-idprog-terminal-signin.md §4.2
7
+ */
8
+ import { spawnSync } from 'node:child_process';
9
+ import { isCredsStale } from './auth-staleness.js';
10
+ export const SIGNIN_RENEWAL_SERVICE = 'ai.agentsandswarms.aismemory.signin';
11
+ export const SIGNIN_ACCESS_SERVICE = 'ai.agentsandswarms.aismemory.access';
12
+ let backendOverride = null;
13
+ /** Test hook — production uses the platform backend. */
14
+ export function setSigninKeychainBackendForTests(next) {
15
+ backendOverride = next;
16
+ }
17
+ function decodeJwtClaims(token) {
18
+ const parts = token.split('.');
19
+ if (parts.length !== 3)
20
+ throw new Error('Malformed JWT');
21
+ const json = Buffer.from(parts[1], 'base64url').toString('utf-8');
22
+ return JSON.parse(json);
23
+ }
24
+ export function signinKeychainAccount(aisUrl, tenantId, userId) {
25
+ const host = new URL(aisUrl).host;
26
+ return `${host}:${tenantId}:${userId}`;
27
+ }
28
+ function spawnSecurityInteractive(securityBin, scriptLine) {
29
+ const result = spawnSync(securityBin, ['-i'], {
30
+ input: `${scriptLine}\n`,
31
+ encoding: 'utf-8',
32
+ });
33
+ if (result.status !== 0) {
34
+ const detail = (result.stderr ?? result.stdout ?? '').trim().slice(0, 200);
35
+ throw new Error(`keychain write failed (${result.status ?? 'unknown'}): ${detail}`);
36
+ }
37
+ }
38
+ function linuxSecretToolAvailable() {
39
+ const lookup = spawnSync('which', ['secret-tool'], { encoding: 'utf-8' });
40
+ if (lookup.status !== 0)
41
+ return false;
42
+ const probe = spawnSync('secret-tool', ['lookup', '--help'], { encoding: 'utf-8' });
43
+ return probe.status === 0 || probe.status === 1;
44
+ }
45
+ function createPlatformBackend() {
46
+ if (process.platform === 'darwin') {
47
+ return {
48
+ isAvailable: () => {
49
+ const probe = spawnSync('security', ['help'], { encoding: 'utf-8' });
50
+ return probe.status === 0;
51
+ },
52
+ read: (service, account) => {
53
+ const result = spawnSync('security', ['find-generic-password', '-s', service, '-a', account, '-w'], { encoding: 'utf-8' });
54
+ if (result.status !== 0)
55
+ return null;
56
+ const secret = result.stdout?.trim();
57
+ return secret ? secret : null;
58
+ },
59
+ write: (service, account, secret) => {
60
+ const escapedAccount = account.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
61
+ const escapedService = service.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
62
+ const escapedSecret = secret.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
63
+ spawnSecurityInteractive('security', `add-generic-password -U -s "${escapedService}" -a "${escapedAccount}" -w "${escapedSecret}"`);
64
+ },
65
+ };
66
+ }
67
+ if (process.platform === 'linux' && linuxSecretToolAvailable()) {
68
+ return {
69
+ isAvailable: () => linuxSecretToolAvailable(),
70
+ read: (service, account) => {
71
+ const result = spawnSync('secret-tool', ['lookup', 'service', service, 'account', account], { encoding: 'utf-8' });
72
+ if (result.status !== 0)
73
+ return null;
74
+ const secret = result.stdout?.trim();
75
+ return secret ? secret : null;
76
+ },
77
+ write: (service, account, secret) => {
78
+ const result = spawnSync('secret-tool', ['store', '--label', service, 'service', service, 'account', account], { input: secret, encoding: 'utf-8' });
79
+ if (result.status !== 0) {
80
+ const detail = (result.stderr ?? result.stdout ?? '').trim().slice(0, 200);
81
+ throw new Error(`secret-tool store failed (${result.status ?? 'unknown'}): ${detail}`);
82
+ }
83
+ },
84
+ };
85
+ }
86
+ return {
87
+ isAvailable: () => false,
88
+ read: () => null,
89
+ write: () => {
90
+ throw new Error('No OS keychain available on this platform');
91
+ },
92
+ };
93
+ }
94
+ function backend() {
95
+ return backendOverride ?? createPlatformBackend();
96
+ }
97
+ export function isSigninKeychainAvailable() {
98
+ return backend().isAvailable();
99
+ }
100
+ export function saveOwnerSignInToKeychain(input) {
101
+ const claims = decodeJwtClaims(input.accessToken);
102
+ const userId = claims.user_id ?? claims.sub;
103
+ const tenantId = claims.tenant_id;
104
+ if (!userId || !tenantId) {
105
+ throw new Error('Access token missing user_id or tenant_id for keychain account');
106
+ }
107
+ const account = signinKeychainAccount(input.aisUrl, tenantId, userId);
108
+ const renewal = {
109
+ refresh_token: input.refreshToken,
110
+ ...(claims.sid ? { sid: claims.sid } : {}),
111
+ };
112
+ const access = {
113
+ access_token: input.accessToken,
114
+ expires_at: input.expiresAt,
115
+ };
116
+ const store = backend();
117
+ store.write(SIGNIN_RENEWAL_SERVICE, account, JSON.stringify(renewal));
118
+ store.write(SIGNIN_ACCESS_SERVICE, account, JSON.stringify(access));
119
+ }
120
+ export function loadOwnerSignInAccessForPreference(aisUrl, pref) {
121
+ const userId = pref.ownerUserId;
122
+ if (!userId)
123
+ return null;
124
+ const store = backend();
125
+ if (!store.isAvailable())
126
+ return null;
127
+ const account = signinKeychainAccount(aisUrl, pref.tenantId, userId);
128
+ const raw = store.read(SIGNIN_ACCESS_SERVICE, account);
129
+ if (!raw)
130
+ return null;
131
+ try {
132
+ const parsed = JSON.parse(raw);
133
+ if (typeof parsed.access_token !== 'string' || typeof parsed.expires_at !== 'string')
134
+ return null;
135
+ return parsed;
136
+ }
137
+ catch {
138
+ return null;
139
+ }
140
+ }
141
+ export function loadOwnerSignInRenewalForAccount(aisUrl, tenantId, userId) {
142
+ const store = backend();
143
+ if (!store.isAvailable())
144
+ return null;
145
+ const account = signinKeychainAccount(aisUrl, tenantId, userId);
146
+ const raw = store.read(SIGNIN_RENEWAL_SERVICE, account);
147
+ if (!raw)
148
+ return null;
149
+ try {
150
+ const parsed = JSON.parse(raw);
151
+ if (typeof parsed.refresh_token !== 'string')
152
+ return null;
153
+ return parsed;
154
+ }
155
+ catch {
156
+ return null;
157
+ }
158
+ }
159
+ /** Decode owner user id from a bearer without verifying the signature (local cache only). */
160
+ export function ownerUserIdFromAccessToken(accessToken) {
161
+ try {
162
+ const claims = decodeJwtClaims(accessToken);
163
+ return claims.user_id ?? claims.sub ?? null;
164
+ }
165
+ catch {
166
+ return null;
167
+ }
168
+ }
169
+ /** Shown when preference marks an owner keychain session but access is missing (CORBOT-EBCB2D2B). */
170
+ export const OWNER_KEYCHAIN_SIGNED_OUT = 'Signed out on this device (no AIS access token in the OS keychain). Complete AIS sign-in again before calling agent_load or other AIS tools.';
171
+ export class OwnerKeychainSignedOutError extends Error {
172
+ constructor(message = OWNER_KEYCHAIN_SIGNED_OUT) {
173
+ super(message);
174
+ this.name = 'OwnerKeychainSignedOutError';
175
+ }
176
+ }
177
+ /**
178
+ * Bearer + ids for an owner terminal sign-in stored in the OS keychain.
179
+ * Returns null when the session is signed out or the access token is stale.
180
+ */
181
+ export function credentialsFromOwnerKeychain(aisUrl, pref, activeAgentId, nowMs = Date.now()) {
182
+ if (!pref.ownerUserId)
183
+ return null;
184
+ const cached = loadOwnerSignInAccessForPreference(aisUrl, pref);
185
+ if (!cached || isCredsStale(cached.expires_at, nowMs))
186
+ return null;
187
+ return {
188
+ token: cached.access_token,
189
+ agentId: activeAgentId ?? pref.agentId,
190
+ tenantId: pref.tenantId,
191
+ expiresAt: cached.expires_at,
192
+ };
193
+ }
194
+ export function requireOwnerKeychainCredentials(aisUrl, pref, activeAgentId) {
195
+ const creds = credentialsFromOwnerKeychain(aisUrl, pref, activeAgentId);
196
+ if (!creds)
197
+ throw new OwnerKeychainSignedOutError();
198
+ return creds;
199
+ }
200
+ //# sourceMappingURL=signin-keychain.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signin-keychain.js","sourceRoot":"","sources":["../src/signin-keychain.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,71 @@
1
+ /** What this process reports about itself at startup and through whoami. */
2
+ export interface StartupIdentity {
3
+ clientVersion: string;
4
+ /** null when no agent is known locally (unbonded, or resolved on first call). */
5
+ agentId: string | null;
6
+ /** Where the credential comes from: an env variable name, a file path, or "none". */
7
+ credentialSource: string;
8
+ }
9
+ /** The auth mode main() selected, with the local facts each mode already holds. */
10
+ export type CredentialSourceInput = {
11
+ kind: 'workspace-key';
12
+ env: Record<string, string | undefined>;
13
+ agentId: string;
14
+ } | {
15
+ kind: 'agent-api-key';
16
+ env: Record<string, string | undefined>;
17
+ agentId: string;
18
+ } | {
19
+ kind: 'run-pass';
20
+ runPassFile: string;
21
+ agentId: string;
22
+ } | {
23
+ kind: 'oauth';
24
+ /** AIS_AGENT_ID chosen for this session, if any. */
25
+ sessionAgentId?: string;
26
+ /** Keys directory when exactly one device key is enrolled, else null. */
27
+ enrolledKeyDir: string | null;
28
+ /** Agent id in a usable saved owner session file, else null. */
29
+ diskAgentId: string | null;
30
+ credentialsFile: string;
31
+ /** Last bonded agent from the preference file, if any. */
32
+ preferredAgentId?: string;
33
+ /** Owner session tokens live in the OS keychain (CORBOT-51CAC5E8). */
34
+ keychainOwnerSession?: boolean;
35
+ };
36
+ /** Resolve version, agent and credential source from what main() already loaded. */
37
+ export declare function describeStartupIdentity(clientVersion: string, input: CredentialSourceInput): StartupIdentity;
38
+ /** One stderr line, e.g. `aismemory 0.8.3: agent <id> via env AIS_API_KEY`. */
39
+ export declare function formatStartupIdentityLine(identity: StartupIdentity): string;
40
+ /** Recorded once by main(); read by whoami. null clears it (tests). */
41
+ export declare function setStartupIdentity(next: StartupIdentity | null): void;
42
+ export declare function getStartupIdentity(): StartupIdentity | null;
43
+ /** A server name defined in more than one config scope. */
44
+ export interface ServerNameConflict {
45
+ name: string;
46
+ /** Human-readable scope labels with their file paths, in client precedence order. */
47
+ scopes: string[];
48
+ /** The scope label the client actually runs: the first of `scopes`. */
49
+ winner: string;
50
+ /** Credential env variable NAMES the winning entry sets (values never read out). */
51
+ winnerCredentialEnv: string[];
52
+ /** Losing scopes that set credential env, as "<scope> sets <NAMES>". */
53
+ ignoredCredentialEnv: string[];
54
+ }
55
+ export declare function setServerNameConflicts(next: ServerNameConflict[]): void;
56
+ export declare function getServerNameConflicts(): ServerNameConflict[];
57
+ /**
58
+ * Find server names the launching client defines in more than one scope.
59
+ *
60
+ * The server cannot learn the name its client gave it, so the candidates are
61
+ * `aismemory` plus any name whose entry runs this package. Scopes read are
62
+ * Claude Code's: local (`~/.claude.json` projects[cwd]), project
63
+ * (`<cwd>/.mcp.json`) and user (`~/.claude.json` top level), in that
64
+ * precedence order. Missing or invalid files are skipped.
65
+ */
66
+ export declare function findDuplicateServerNames(opts: {
67
+ home: string;
68
+ cwd: string;
69
+ }): ServerNameConflict[];
70
+ /** The stderr / doctor text for one conflict. Names scopes only, never env or headers. */
71
+ export declare function formatDuplicateServerWarning(conflict: ServerNameConflict): string;
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Startup identity report (CORBOT-5D16CF2A).
3
+ *
4
+ * Two failure shapes looked identical to a user: an older aismemory install
5
+ * answering instead of the current one (different bond-prompt text, different
6
+ * tool list), and two MCP config entries with the same server name, where the
7
+ * client keeps one and the one holding the credentials is silently dropped.
8
+ * At startup the server now writes one stderr line naming its version, the
9
+ * agent it will act as and where that credential comes from, and warns when
10
+ * the launching client's config defines this server's name more than once.
11
+ *
12
+ * Everything here is local and read-only: no network call, no write. Only
13
+ * env variable NAMES and file PATHS are ever reported — never a key, token,
14
+ * header or env value.
15
+ */
16
+ import { readFileSync, realpathSync } from 'node:fs';
17
+ import { join } from 'node:path';
18
+ /** Resolve version, agent and credential source from what main() already loaded. */
19
+ export function describeStartupIdentity(clientVersion, input) {
20
+ switch (input.kind) {
21
+ case 'workspace-key':
22
+ // Mirrors loadWorkspaceKeyConfig's choice of variable.
23
+ return {
24
+ clientVersion,
25
+ agentId: input.agentId,
26
+ credentialSource: `env ${input.env['AIS_WORKSPACE_KEY'] !== undefined ? 'AIS_WORKSPACE_KEY' : 'AIS_API_KEY'}`,
27
+ };
28
+ case 'agent-api-key':
29
+ // Mirrors loadAgentApiKeyConfig's choice of variable.
30
+ return {
31
+ clientVersion,
32
+ agentId: input.agentId,
33
+ credentialSource: `env ${input.env['AIS_API_KEY'] !== undefined ? 'AIS_API_KEY' : 'AIS_AGENT_API_KEY'}`,
34
+ };
35
+ case 'run-pass':
36
+ return { clientVersion, agentId: input.agentId, credentialSource: `run-pass file ${input.runPassFile}` };
37
+ case 'oauth':
38
+ if (input.keychainOwnerSession) {
39
+ return {
40
+ clientVersion,
41
+ agentId: input.sessionAgentId ?? input.preferredAgentId ?? input.diskAgentId ?? null,
42
+ credentialSource: 'OS keychain owner sign-in',
43
+ };
44
+ }
45
+ // An enrolled device key owns the live session even when a disk bearer exists (F4).
46
+ if (input.enrolledKeyDir !== null) {
47
+ return {
48
+ clientVersion,
49
+ agentId: input.sessionAgentId ?? input.preferredAgentId ?? null,
50
+ credentialSource: `device key file in ${input.enrolledKeyDir}`,
51
+ };
52
+ }
53
+ if (input.diskAgentId !== null) {
54
+ return {
55
+ clientVersion,
56
+ agentId: input.sessionAgentId ?? input.diskAgentId,
57
+ credentialSource: `owner session file ${input.credentialsFile}`,
58
+ };
59
+ }
60
+ return { clientVersion, agentId: input.sessionAgentId ?? null, credentialSource: 'none' };
61
+ }
62
+ }
63
+ /** One stderr line, e.g. `aismemory 0.8.3: agent <id> via env AIS_API_KEY`. */
64
+ export function formatStartupIdentityLine(identity) {
65
+ return `aismemory ${identity.clientVersion}: agent ${identity.agentId ?? 'none (unbonded)'} via ${identity.credentialSource}`;
66
+ }
67
+ let startupIdentity = null;
68
+ /** Recorded once by main(); read by whoami. null clears it (tests). */
69
+ export function setStartupIdentity(next) {
70
+ startupIdentity = next;
71
+ }
72
+ export function getStartupIdentity() {
73
+ return startupIdentity;
74
+ }
75
+ let serverNameConflicts = [];
76
+ export function setServerNameConflicts(next) {
77
+ serverNameConflicts = next;
78
+ }
79
+ export function getServerNameConflicts() {
80
+ return serverNameConflicts;
81
+ }
82
+ /** The name this package documents in every install snippet. */
83
+ const DEFAULT_SERVER_NAME = 'aismemory';
84
+ /** Env variables that select an aismemory credential. Only their names are reported. */
85
+ const CREDENTIAL_ENV_NAMES = [
86
+ 'AIS_WORKSPACE_KEY',
87
+ 'AIS_API_KEY',
88
+ 'AIS_AGENT_API_KEY',
89
+ 'AIS_RUN_PASS_FILE',
90
+ 'AIS_CREDENTIALS_FILE',
91
+ ];
92
+ /** Names of credential env variables a server entry sets, without reading their values. */
93
+ function credentialEnvNames(entry) {
94
+ if (!isRecord(entry))
95
+ return [];
96
+ const env = entry['env'];
97
+ if (!isRecord(env))
98
+ return [];
99
+ return CREDENTIAL_ENV_NAMES.filter((name) => Object.hasOwn(env, name));
100
+ }
101
+ function isRecord(value) {
102
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
103
+ }
104
+ /** Parse a JSON file; null when missing, unreadable or invalid. */
105
+ function readJsonFile(path) {
106
+ try {
107
+ return JSON.parse(readFileSync(path, 'utf8'));
108
+ }
109
+ catch {
110
+ return null;
111
+ }
112
+ }
113
+ /** The mcpServers map under `container`, or an empty map when absent or malformed. */
114
+ function serversOf(container) {
115
+ if (!isRecord(container))
116
+ return {};
117
+ const servers = container['mcpServers'];
118
+ return isRecord(servers) ? servers : {};
119
+ }
120
+ /** Matches `aismemory`, `aismemory@0.8.0`, `/usr/local/bin/aismemory`. */
121
+ const PACKAGE_TOKEN = /(^|[\\/])aismemory(@[^\\/\s]*)?$/;
122
+ /** Matches a direct node launch of this package's entrypoint. */
123
+ const PACKAGE_ENTRYPOINT = /(aismemory|agentmemory)[\\/]dist[\\/]index\.js$/;
124
+ /** True when a server entry's command or args launch this package. */
125
+ function runsThisPackage(entry) {
126
+ if (!isRecord(entry))
127
+ return false;
128
+ const parts = [];
129
+ if (typeof entry['command'] === 'string')
130
+ parts.push(entry['command']);
131
+ const args = entry['args'];
132
+ if (Array.isArray(args)) {
133
+ for (const arg of args)
134
+ if (typeof arg === 'string')
135
+ parts.push(arg);
136
+ }
137
+ return parts
138
+ .flatMap((part) => part.split(/\s+/))
139
+ .some((token) => PACKAGE_TOKEN.test(token) || PACKAGE_ENTRYPOINT.test(token));
140
+ }
141
+ /**
142
+ * Find server names the launching client defines in more than one scope.
143
+ *
144
+ * The server cannot learn the name its client gave it, so the candidates are
145
+ * `aismemory` plus any name whose entry runs this package. Scopes read are
146
+ * Claude Code's: local (`~/.claude.json` projects[cwd]), project
147
+ * (`<cwd>/.mcp.json`) and user (`~/.claude.json` top level), in that
148
+ * precedence order. Missing or invalid files are skipped.
149
+ */
150
+ export function findDuplicateServerNames(opts) {
151
+ let cwd = opts.cwd;
152
+ try {
153
+ cwd = realpathSync(opts.cwd);
154
+ }
155
+ catch {
156
+ // Keep the supplied path for missing or unreadable launch directories.
157
+ }
158
+ const userFile = join(opts.home, '.claude.json');
159
+ const projectFile = join(cwd, '.mcp.json');
160
+ const userConfig = readJsonFile(userFile);
161
+ const projects = isRecord(userConfig) ? userConfig['projects'] : undefined;
162
+ const projectKey = isRecord(projects)
163
+ ? Object.hasOwn(projects, cwd) ? cwd : Object.hasOwn(projects, opts.cwd) ? opts.cwd : null
164
+ : null;
165
+ const projectScope = projectKey === null || !isRecord(projects) ? undefined : projects[projectKey];
166
+ const scopes = [
167
+ {
168
+ kind: 'local',
169
+ label: `local (${userFile} projects[${projectKey ?? cwd}])`,
170
+ servers: serversOf(projectScope),
171
+ },
172
+ { kind: 'project', label: `project (${projectFile})`, servers: serversOf(readJsonFile(projectFile)) },
173
+ { kind: 'user', label: `user (${userFile})`, servers: serversOf(userConfig) },
174
+ ];
175
+ const candidates = new Set([DEFAULT_SERVER_NAME]);
176
+ for (const scope of scopes) {
177
+ for (const [name, entry] of Object.entries(scope.servers)) {
178
+ if (runsThisPackage(entry))
179
+ candidates.add(name);
180
+ }
181
+ }
182
+ const conflicts = [];
183
+ for (const name of candidates) {
184
+ const defining = scopes.filter((scope) => Object.hasOwn(scope.servers, name) && isRecord(scope.servers[name]));
185
+ if (defining.length < 2)
186
+ continue;
187
+ const [winner, ...losers] = defining;
188
+ conflicts.push({
189
+ name,
190
+ scopes: defining.map((scope) => scope.label),
191
+ winner: winner.label,
192
+ winnerCredentialEnv: credentialEnvNames(winner.servers[name]),
193
+ ignoredCredentialEnv: losers
194
+ .map((scope) => ({ label: scope.label, names: credentialEnvNames(scope.servers[name]) }))
195
+ .filter((loser) => loser.names.length > 0)
196
+ .map((loser) => `${loser.label} sets ${loser.names.join(', ')}`),
197
+ });
198
+ }
199
+ return conflicts;
200
+ }
201
+ /** The stderr / doctor text for one conflict. Names scopes only, never env or headers. */
202
+ export function formatDuplicateServerWarning(conflict) {
203
+ const winnerCredential = conflict.winnerCredentialEnv.length > 0
204
+ ? `the winner sets credential env ${conflict.winnerCredentialEnv.join(', ')}`
205
+ : 'the winner has no credential env';
206
+ const ignored = conflict.ignoredCredentialEnv.length > 0
207
+ ? ` Ignored: ${conflict.ignoredCredentialEnv.join('; ')}.`
208
+ : '';
209
+ return (`MCP server name "${conflict.name}" is defined in ${conflict.scopes.length} config scopes: ` +
210
+ `${conflict.scopes.join(', ')}. The ${conflict.winner} entry wins (precedence: local > project > user); ` +
211
+ `${winnerCredential}.${ignored} Remove or rename the duplicates.`);
212
+ }
213
+ //# sourceMappingURL=startup-identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"startup-identity.js","sourceRoot":"","sources":["../src/startup-identity.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,7 @@ export declare const rememberArgsSchema: z.ZodObject<{
19
19
  }>>>;
20
20
  importance: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
21
21
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
22
+ supersedes: z.ZodOptional<z.ZodString>;
22
23
  }, z.core.$strip>;
23
24
  export declare const recallArgsSchema: z.ZodObject<{
24
25
  principalAgentId: z.ZodOptional<z.ZodString>;
@@ -33,6 +34,9 @@ export declare const recallArgsSchema: z.ZodObject<{
33
34
  task: "task";
34
35
  }>>;
35
36
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
37
+ orderBy: z.ZodOptional<z.ZodEnum<{
38
+ newest: "newest";
39
+ }>>;
36
40
  }, z.core.$strip>;
37
41
  export declare const handoffArgsSchema: z.ZodObject<{
38
42
  summary: z.ZodOptional<z.ZodString>;
@@ -56,6 +60,9 @@ export declare const emptyArgsSchema: z.ZodObject<{}, z.core.$strict>;
56
60
  */
57
61
  export declare const FULL_CONTEXT_MIN_MAX_TOKENS = 500;
58
62
  export declare const FULL_CONTEXT_MAX_MAX_TOKENS = 20000;
63
+ /** Mirrors the server's context-window bounds (full-context.ts MIN/MAX_CONTEXT_WINDOW). */
64
+ export declare const FULL_CONTEXT_MIN_WINDOW = 1000;
65
+ export declare const FULL_CONTEXT_MAX_WINDOW = 10000000;
59
66
  export declare const fullContextArgsSchema: z.ZodObject<{
60
67
  principalAgentId: z.ZodOptional<z.ZodString>;
61
68
  memoriesLimit: z.ZodOptional<z.ZodNumber>;
@@ -65,6 +72,7 @@ export declare const fullContextArgsSchema: z.ZodObject<{
65
72
  bootstrap: "bootstrap";
66
73
  }>>;
67
74
  maxTokens: z.ZodOptional<z.ZodNumber>;
75
+ contextWindowSize: z.ZodOptional<z.ZodNumber>;
68
76
  }, z.core.$strict>;
69
77
  export declare const INBOX_MAX_BODY_CHARS = 8000;
70
78
  export declare const INBOX_MAX_TASK_ID_CHARS = 128;
@@ -155,6 +163,8 @@ export declare function parseHandoffArgs(raw: unknown): HandoffArgs;
155
163
  export declare function parseAgentLoadArgs(raw: unknown): AgentLoadArgs;
156
164
  export declare function parseEmptyToolArgs(raw: unknown): Record<string, never>;
157
165
  export declare function parseFullContextArgs(raw: unknown): FullContextArgs;
166
+ /** Query string (with leading `?`, or empty) for the full-context endpoint; shared by every dispatcher. */
167
+ export declare function buildFullContextQuery(args: FullContextArgs): string;
158
168
  export declare function parseInboxSendArgs(raw: unknown): InboxSendArgs;
159
169
  export declare function parseInboxReadArgs(raw: unknown): InboxReadArgs;
160
170
  export declare function parseGoalCreateArgs(raw: unknown): GoalCreateArgs;
package/dist/tool-args.js CHANGED
@@ -23,6 +23,14 @@ export const rememberArgsSchema = z.object({
23
23
  type: memoryTypeSchema.optional().default('context'),
24
24
  importance: z.number().min(0).max(1).optional().default(0.5),
25
25
  tags: tagsArgSchema.optional(),
26
+ /**
27
+ * Id of an older memory of this agent that this one replaces
28
+ * (CORBOT-FC8D0DCC). The server keeps it but leaves it out of recall.
29
+ */
30
+ supersedes: z
31
+ .string({ message: 'supersedes must be a memory id' })
32
+ .regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i, 'supersedes must be a memory id (UUID)')
33
+ .optional(),
26
34
  });
27
35
  /**
28
36
  * Optional delegated-read principal (CORBOT-3785D10D).
@@ -44,6 +52,11 @@ export const recallArgsSchema = z.object({
44
52
  type: memoryTypeSchema.optional(),
45
53
  /** Only memories carrying every one of these tags. */
46
54
  tags: tagsArgSchema.optional(),
55
+ /**
56
+ * Newest-first list instead of a ranked search (CORBOT-B1770E61). The only
57
+ * value AIS accepts is `newest`; it also needs `type` or `tags`.
58
+ */
59
+ orderBy: z.enum(['newest'], { message: "orderBy must be 'newest'" }).optional(),
47
60
  });
48
61
  export const handoffArgsSchema = z.object({
49
62
  summary: z
@@ -83,6 +96,9 @@ export const emptyArgsSchema = z.object({}).strict();
83
96
  */
84
97
  export const FULL_CONTEXT_MIN_MAX_TOKENS = 500;
85
98
  export const FULL_CONTEXT_MAX_MAX_TOKENS = 20_000;
99
+ /** Mirrors the server's context-window bounds (full-context.ts MIN/MAX_CONTEXT_WINDOW). */
100
+ export const FULL_CONTEXT_MIN_WINDOW = 1000;
101
+ export const FULL_CONTEXT_MAX_WINDOW = 10_000_000;
86
102
  export const fullContextArgsSchema = z
87
103
  .object({
88
104
  principalAgentId: principalAgentIdSchema.optional(),
@@ -96,6 +112,13 @@ export const fullContextArgsSchema = z
96
112
  .min(FULL_CONTEXT_MIN_MAX_TOKENS)
97
113
  .max(FULL_CONTEXT_MAX_MAX_TOKENS)
98
114
  .optional(),
115
+ /** Caller's model context window in tokens; scales the skills budget. */
116
+ contextWindowSize: z
117
+ .number()
118
+ .int()
119
+ .min(FULL_CONTEXT_MIN_WINDOW)
120
+ .max(FULL_CONTEXT_MAX_WINDOW)
121
+ .optional(),
99
122
  })
100
123
  .strict();
101
124
  // ── Agent inbox (CORBOT-7115B8AE) ───────────────────────────────────────
@@ -241,6 +264,22 @@ export function parseEmptyToolArgs(raw) {
241
264
  export function parseFullContextArgs(raw) {
242
265
  return parseOrThrow(fullContextArgsSchema, raw);
243
266
  }
267
+ /** Query string (with leading `?`, or empty) for the full-context endpoint; shared by every dispatcher. */
268
+ export function buildFullContextQuery(args) {
269
+ const params = new URLSearchParams();
270
+ if (args.principalAgentId !== undefined)
271
+ params.set('principalAgentId', args.principalAgentId);
272
+ if (args.memoriesLimit !== undefined)
273
+ params.set('memoriesLimit', String(args.memoriesLimit));
274
+ if (args.view !== undefined)
275
+ params.set('view', args.view);
276
+ if (args.maxTokens !== undefined)
277
+ params.set('maxTokens', String(args.maxTokens));
278
+ if (args.contextWindowSize !== undefined)
279
+ params.set('contextWindowSize', String(args.contextWindowSize));
280
+ const qs = params.toString();
281
+ return qs ? `?${qs}` : '';
282
+ }
244
283
  export function parseInboxSendArgs(raw) {
245
284
  return parseOrThrow(inboxSendArgsSchema, raw);
246
285
  }