@namzu/cli 1.0.1 → 2.1.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.
Files changed (211) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +0 -2
  3. package/dist/cli.js.map +1 -1
  4. package/dist/integrations/providers/index.d.ts +0 -3
  5. package/dist/integrations/providers/index.d.ts.map +1 -1
  6. package/dist/integrations/providers/index.js +0 -5
  7. package/dist/integrations/providers/index.js.map +1 -1
  8. package/dist/tui/App.d.ts.map +1 -1
  9. package/dist/tui/App.js +8 -0
  10. package/dist/tui/App.js.map +1 -1
  11. package/dist/tui/agent.d.ts +10 -0
  12. package/dist/tui/agent.d.ts.map +1 -1
  13. package/dist/tui/agent.js +10 -0
  14. package/dist/tui/agent.js.map +1 -1
  15. package/dist/tui/slashCommands.d.ts +46 -0
  16. package/dist/tui/slashCommands.d.ts.map +1 -1
  17. package/dist/tui/slashCommands.js +96 -0
  18. package/dist/tui/slashCommands.js.map +1 -1
  19. package/package.json +11 -6
  20. package/dist/__tests__/environment-reaches-the-turn.test.d.ts +0 -17
  21. package/dist/__tests__/environment-reaches-the-turn.test.d.ts.map +0 -1
  22. package/dist/__tests__/environment-reaches-the-turn.test.js +0 -128
  23. package/dist/__tests__/environment-reaches-the-turn.test.js.map +0 -1
  24. package/dist/__tests__/headless-trust-gate.test.d.ts +0 -23
  25. package/dist/__tests__/headless-trust-gate.test.d.ts.map +0 -1
  26. package/dist/__tests__/headless-trust-gate.test.js +0 -227
  27. package/dist/__tests__/headless-trust-gate.test.js.map +0 -1
  28. package/dist/__tests__/mcp-servers-reach-the-session.test.d.ts +0 -17
  29. package/dist/__tests__/mcp-servers-reach-the-session.test.d.ts.map +0 -1
  30. package/dist/__tests__/mcp-servers-reach-the-session.test.js +0 -171
  31. package/dist/__tests__/mcp-servers-reach-the-session.test.js.map +0 -1
  32. package/dist/__tests__/permission-rules-reach-the-turn.test.d.ts +0 -31
  33. package/dist/__tests__/permission-rules-reach-the-turn.test.d.ts.map +0 -1
  34. package/dist/__tests__/permission-rules-reach-the-turn.test.js +0 -132
  35. package/dist/__tests__/permission-rules-reach-the-turn.test.js.map +0 -1
  36. package/dist/__tests__/project-instructions-reach-the-turn.test.d.ts +0 -24
  37. package/dist/__tests__/project-instructions-reach-the-turn.test.d.ts.map +0 -1
  38. package/dist/__tests__/project-instructions-reach-the-turn.test.js +0 -153
  39. package/dist/__tests__/project-instructions-reach-the-turn.test.js.map +0 -1
  40. package/dist/cli.test.d.ts +0 -2
  41. package/dist/cli.test.d.ts.map +0 -1
  42. package/dist/cli.test.js +0 -100
  43. package/dist/cli.test.js.map +0 -1
  44. package/dist/commands/__tests__/eval.test.d.ts +0 -2
  45. package/dist/commands/__tests__/eval.test.d.ts.map +0 -1
  46. package/dist/commands/__tests__/eval.test.js +0 -165
  47. package/dist/commands/__tests__/eval.test.js.map +0 -1
  48. package/dist/commands/__tests__/passthrough-help.test.d.ts +0 -2
  49. package/dist/commands/__tests__/passthrough-help.test.d.ts.map +0 -1
  50. package/dist/commands/__tests__/passthrough-help.test.js +0 -96
  51. package/dist/commands/__tests__/passthrough-help.test.js.map +0 -1
  52. package/dist/commands/__tests__/resume.test.d.ts +0 -15
  53. package/dist/commands/__tests__/resume.test.d.ts.map +0 -1
  54. package/dist/commands/__tests__/resume.test.js +0 -116
  55. package/dist/commands/__tests__/resume.test.js.map +0 -1
  56. package/dist/commands/__tests__/run-exit-code.test.d.ts +0 -2
  57. package/dist/commands/__tests__/run-exit-code.test.d.ts.map +0 -1
  58. package/dist/commands/__tests__/run-exit-code.test.js +0 -100
  59. package/dist/commands/__tests__/run-exit-code.test.js.map +0 -1
  60. package/dist/commands/__tests__/run-flags.test.d.ts +0 -11
  61. package/dist/commands/__tests__/run-flags.test.d.ts.map +0 -1
  62. package/dist/commands/__tests__/run-flags.test.js +0 -238
  63. package/dist/commands/__tests__/run-flags.test.js.map +0 -1
  64. package/dist/commands/__tests__/run-stream-flags.test.d.ts +0 -2
  65. package/dist/commands/__tests__/run-stream-flags.test.d.ts.map +0 -1
  66. package/dist/commands/__tests__/run-stream-flags.test.js +0 -295
  67. package/dist/commands/__tests__/run-stream-flags.test.js.map +0 -1
  68. package/dist/commands/doctor.test.d.ts +0 -2
  69. package/dist/commands/doctor.test.d.ts.map +0 -1
  70. package/dist/commands/doctor.test.js +0 -82
  71. package/dist/commands/doctor.test.js.map +0 -1
  72. package/dist/commands/providers.d.ts +0 -17
  73. package/dist/commands/providers.d.ts.map +0 -1
  74. package/dist/commands/providers.js +0 -274
  75. package/dist/commands/providers.js.map +0 -1
  76. package/dist/config/load.test.d.ts +0 -2
  77. package/dist/config/load.test.d.ts.map +0 -1
  78. package/dist/config/load.test.js +0 -57
  79. package/dist/config/load.test.js.map +0 -1
  80. package/dist/context/__tests__/environment.test.d.ts +0 -10
  81. package/dist/context/__tests__/environment.test.d.ts.map +0 -1
  82. package/dist/context/__tests__/environment.test.js +0 -84
  83. package/dist/context/__tests__/environment.test.js.map +0 -1
  84. package/dist/context/__tests__/project.test.d.ts +0 -12
  85. package/dist/context/__tests__/project.test.d.ts.map +0 -1
  86. package/dist/context/__tests__/project.test.js +0 -201
  87. package/dist/context/__tests__/project.test.js.map +0 -1
  88. package/dist/doctor/checks/credentials.test.d.ts +0 -10
  89. package/dist/doctor/checks/credentials.test.d.ts.map +0 -1
  90. package/dist/doctor/checks/credentials.test.js +0 -47
  91. package/dist/doctor/checks/credentials.test.js.map +0 -1
  92. package/dist/doctor/checks/sandbox.test.d.ts +0 -2
  93. package/dist/doctor/checks/sandbox.test.d.ts.map +0 -1
  94. package/dist/doctor/checks/sandbox.test.js +0 -59
  95. package/dist/doctor/checks/sandbox.test.js.map +0 -1
  96. package/dist/doctor/registry.test.d.ts +0 -7
  97. package/dist/doctor/registry.test.d.ts.map +0 -1
  98. package/dist/doctor/registry.test.js +0 -379
  99. package/dist/doctor/registry.test.js.map +0 -1
  100. package/dist/integrations/mcp/__tests__/connect.test.d.ts +0 -11
  101. package/dist/integrations/mcp/__tests__/connect.test.d.ts.map +0 -1
  102. package/dist/integrations/mcp/__tests__/connect.test.js +0 -231
  103. package/dist/integrations/mcp/__tests__/connect.test.js.map +0 -1
  104. package/dist/integrations/providers/discover.test.d.ts +0 -2
  105. package/dist/integrations/providers/discover.test.d.ts.map +0 -1
  106. package/dist/integrations/providers/discover.test.js +0 -93
  107. package/dist/integrations/providers/discover.test.js.map +0 -1
  108. package/dist/integrations/providers/keychain.test.d.ts +0 -2
  109. package/dist/integrations/providers/keychain.test.d.ts.map +0 -1
  110. package/dist/integrations/providers/keychain.test.js +0 -21
  111. package/dist/integrations/providers/keychain.test.js.map +0 -1
  112. package/dist/integrations/providers/mask.d.ts +0 -7
  113. package/dist/integrations/providers/mask.d.ts.map +0 -1
  114. package/dist/integrations/providers/mask.js +0 -14
  115. package/dist/integrations/providers/mask.js.map +0 -1
  116. package/dist/integrations/providers/mask.test.d.ts +0 -2
  117. package/dist/integrations/providers/mask.test.d.ts.map +0 -1
  118. package/dist/integrations/providers/mask.test.js +0 -20
  119. package/dist/integrations/providers/mask.test.js.map +0 -1
  120. package/dist/integrations/providers/oauth.test.d.ts +0 -2
  121. package/dist/integrations/providers/oauth.test.d.ts.map +0 -1
  122. package/dist/integrations/providers/oauth.test.js +0 -86
  123. package/dist/integrations/providers/oauth.test.js.map +0 -1
  124. package/dist/integrations/providers/preferences.test.d.ts +0 -2
  125. package/dist/integrations/providers/preferences.test.d.ts.map +0 -1
  126. package/dist/integrations/providers/preferences.test.js +0 -76
  127. package/dist/integrations/providers/preferences.test.js.map +0 -1
  128. package/dist/integrations/providers/schema.d.ts +0 -73
  129. package/dist/integrations/providers/schema.d.ts.map +0 -1
  130. package/dist/integrations/providers/schema.js +0 -70
  131. package/dist/integrations/providers/schema.js.map +0 -1
  132. package/dist/integrations/providers/schema.test.d.ts +0 -2
  133. package/dist/integrations/providers/schema.test.d.ts.map +0 -1
  134. package/dist/integrations/providers/schema.test.js +0 -43
  135. package/dist/integrations/providers/schema.test.js.map +0 -1
  136. package/dist/integrations/providers/store.d.ts +0 -32
  137. package/dist/integrations/providers/store.d.ts.map +0 -1
  138. package/dist/integrations/providers/store.js +0 -133
  139. package/dist/integrations/providers/store.js.map +0 -1
  140. package/dist/integrations/providers/store.test.d.ts +0 -2
  141. package/dist/integrations/providers/store.test.d.ts.map +0 -1
  142. package/dist/integrations/providers/store.test.js +0 -135
  143. package/dist/integrations/providers/store.test.js.map +0 -1
  144. package/dist/integrations/sessions/__tests__/archived-workspace.test.d.ts +0 -21
  145. package/dist/integrations/sessions/__tests__/archived-workspace.test.d.ts.map +0 -1
  146. package/dist/integrations/sessions/__tests__/archived-workspace.test.js +0 -62
  147. package/dist/integrations/sessions/__tests__/archived-workspace.test.js.map +0 -1
  148. package/dist/integrations/subagents/__tests__/delegation-trace.test.d.ts +0 -2
  149. package/dist/integrations/subagents/__tests__/delegation-trace.test.d.ts.map +0 -1
  150. package/dist/integrations/subagents/__tests__/delegation-trace.test.js +0 -114
  151. package/dist/integrations/subagents/__tests__/delegation-trace.test.js.map +0 -1
  152. package/dist/integrations/trust/store.test.d.ts +0 -2
  153. package/dist/integrations/trust/store.test.d.ts.map +0 -1
  154. package/dist/integrations/trust/store.test.js +0 -50
  155. package/dist/integrations/trust/store.test.js.map +0 -1
  156. package/dist/memory/store.test.d.ts +0 -2
  157. package/dist/memory/store.test.d.ts.map +0 -1
  158. package/dist/memory/store.test.js +0 -63
  159. package/dist/memory/store.test.js.map +0 -1
  160. package/dist/output/formatter.test.d.ts +0 -2
  161. package/dist/output/formatter.test.d.ts.map +0 -1
  162. package/dist/output/formatter.test.js +0 -88
  163. package/dist/output/formatter.test.js.map +0 -1
  164. package/dist/output/rendered-payload.test.d.ts +0 -2
  165. package/dist/output/rendered-payload.test.d.ts.map +0 -1
  166. package/dist/output/rendered-payload.test.js +0 -61
  167. package/dist/output/rendered-payload.test.js.map +0 -1
  168. package/dist/permissions/__tests__/mode.test.d.ts +0 -10
  169. package/dist/permissions/__tests__/mode.test.d.ts.map +0 -1
  170. package/dist/permissions/__tests__/mode.test.js +0 -115
  171. package/dist/permissions/__tests__/mode.test.js.map +0 -1
  172. package/dist/permissions/__tests__/rules.test.d.ts +0 -10
  173. package/dist/permissions/__tests__/rules.test.d.ts.map +0 -1
  174. package/dist/permissions/__tests__/rules.test.js +0 -196
  175. package/dist/permissions/__tests__/rules.test.js.map +0 -1
  176. package/dist/skills/store.test.d.ts +0 -2
  177. package/dist/skills/store.test.d.ts.map +0 -1
  178. package/dist/skills/store.test.js +0 -80
  179. package/dist/skills/store.test.js.map +0 -1
  180. package/dist/tui/__tests__/context-gauge.test.d.ts +0 -2
  181. package/dist/tui/__tests__/context-gauge.test.d.ts.map +0 -1
  182. package/dist/tui/__tests__/context-gauge.test.js +0 -83
  183. package/dist/tui/__tests__/context-gauge.test.js.map +0 -1
  184. package/dist/tui/__tests__/deferred-tool-discovery.test.d.ts +0 -24
  185. package/dist/tui/__tests__/deferred-tool-discovery.test.d.ts.map +0 -1
  186. package/dist/tui/__tests__/deferred-tool-discovery.test.js +0 -111
  187. package/dist/tui/__tests__/deferred-tool-discovery.test.js.map +0 -1
  188. package/dist/tui/__tests__/to-agent-event.test.d.ts +0 -2
  189. package/dist/tui/__tests__/to-agent-event.test.d.ts.map +0 -1
  190. package/dist/tui/__tests__/to-agent-event.test.js +0 -230
  191. package/dist/tui/__tests__/to-agent-event.test.js.map +0 -1
  192. package/dist/tui/__tests__/working-directory.test.d.ts +0 -13
  193. package/dist/tui/__tests__/working-directory.test.d.ts.map +0 -1
  194. package/dist/tui/__tests__/working-directory.test.js +0 -109
  195. package/dist/tui/__tests__/working-directory.test.js.map +0 -1
  196. package/dist/tui/agent.test.d.ts +0 -2
  197. package/dist/tui/agent.test.d.ts.map +0 -1
  198. package/dist/tui/agent.test.js +0 -225
  199. package/dist/tui/agent.test.js.map +0 -1
  200. package/dist/tui/markdownParser.test.d.ts +0 -2
  201. package/dist/tui/markdownParser.test.d.ts.map +0 -1
  202. package/dist/tui/markdownParser.test.js +0 -90
  203. package/dist/tui/markdownParser.test.js.map +0 -1
  204. package/dist/tui/mentions.test.d.ts +0 -2
  205. package/dist/tui/mentions.test.d.ts.map +0 -1
  206. package/dist/tui/mentions.test.js +0 -35
  207. package/dist/tui/mentions.test.js.map +0 -1
  208. package/dist/tui/slashCommands.test.d.ts +0 -2
  209. package/dist/tui/slashCommands.test.d.ts.map +0 -1
  210. package/dist/tui/slashCommands.test.js +0 -114
  211. package/dist/tui/slashCommands.test.js.map +0 -1
@@ -1,43 +0,0 @@
1
- import { describe, expect, it } from 'vitest';
2
- import { PROVIDER_TYPES, ProfileValidationError, isProviderType, validateProfile, } from './schema.js';
3
- describe('isProviderType', () => {
4
- it('accepts every shipped type', () => {
5
- for (const t of PROVIDER_TYPES)
6
- expect(isProviderType(t)).toBe(true);
7
- });
8
- it('rejects unknown types', () => {
9
- expect(isProviderType('gemini')).toBe(false);
10
- expect(isProviderType(undefined)).toBe(false);
11
- expect(isProviderType(42)).toBe(false);
12
- });
13
- });
14
- describe('validateProfile', () => {
15
- it('passes a minimal anthropic profile', () => {
16
- const p = validateProfile({ name: 'work', type: 'anthropic' });
17
- expect(p.name).toBe('work');
18
- expect(p.type).toBe('anthropic');
19
- });
20
- it('rejects missing name', () => {
21
- expect(() => validateProfile({ type: 'anthropic' })).toThrow(ProfileValidationError);
22
- });
23
- it('rejects unknown type with a helpful message', () => {
24
- expect(() => validateProfile({ name: 'x', type: 'gpt-5-pro' })).toThrowError(/must be one of/);
25
- });
26
- it('rejects non-boolean default', () => {
27
- expect(() => validateProfile({ name: 'x', type: 'openai', default: 'yes' })).toThrow(ProfileValidationError);
28
- });
29
- it('requires baseUrl when type=http', () => {
30
- expect(() => validateProfile({ name: 'h', type: 'http' })).toThrowError(/baseUrl is required/);
31
- const ok = validateProfile({ name: 'h', type: 'http', baseUrl: 'https://example.com' });
32
- expect(ok.type).toBe('http');
33
- });
34
- it('rejects non-string model', () => {
35
- expect(() => validateProfile({ name: 'x', type: 'openai', model: 42 })).toThrow(ProfileValidationError);
36
- });
37
- it('rejects non-object inputs', () => {
38
- expect(() => validateProfile(null)).toThrow(ProfileValidationError);
39
- expect(() => validateProfile('string')).toThrow(ProfileValidationError);
40
- expect(() => validateProfile([])).toThrow(ProfileValidationError);
41
- });
42
- });
43
- //# sourceMappingURL=schema.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.test.js","sourceRoot":"","sources":["../../../src/integrations/providers/schema.test.ts"],"names":[],"mappings":"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"}
@@ -1,32 +0,0 @@
1
- /**
2
- * `~/.namzu/providers.json` store.
3
- *
4
- * - Reads return `[]` (not error) when the file is missing — first-run UX.
5
- * - Writes are atomic: temp file + rename. Mode 0600 enforced on every write.
6
- * - `resolveApiKey(profile, env)` cascades `NAMZU_<NAME>_API_KEY` (per-
7
- * profile override) → per-type vendor default (`OPENAI_API_KEY` etc.)
8
- * → profile.apiKey on-disk → null.
9
- * - Uniqueness invariants enforced on write: no duplicate `name`; at most
10
- * one profile with `default: true`.
11
- */
12
- import { type ProviderProfile } from './schema.js';
13
- export declare class ProvidersStoreError extends Error {
14
- constructor(message: string);
15
- }
16
- export interface StoreLocation {
17
- readonly path: string;
18
- }
19
- export declare function providersPath(home?: string): string;
20
- export declare function readProfiles(home?: string): ProviderProfile[];
21
- export declare function writeProfiles(profiles: readonly ProviderProfile[], home?: string): void;
22
- export declare function assertInvariants(profiles: readonly ProviderProfile[]): void;
23
- /**
24
- * Resolve the live API key for a profile, honoring overrides:
25
- * 1. `NAMZU_<UPPERCASE_NAME>_API_KEY` (per-profile override)
26
- * 2. Per-type vendor default (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, etc.)
27
- * 3. `profile.apiKey` (on-disk)
28
- * 4. `null` (no key — caller decides whether that's fatal)
29
- */
30
- export declare function resolveApiKey(profile: ProviderProfile, env?: NodeJS.ProcessEnv): string | null;
31
- export declare function findDefault(profiles: readonly ProviderProfile[]): ProviderProfile | null;
32
- //# sourceMappingURL=store.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/integrations/providers/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAOH,OAAO,EAGN,KAAK,eAAe,EAIpB,MAAM,aAAa,CAAA;AAKpB,qBAAa,mBAAoB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI3B;AAED,MAAM,WAAW,aAAa;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACrB;AAED,wBAAgB,aAAa,CAAC,IAAI,GAAE,MAAkB,GAAG,MAAM,CAE9D;AAED,wBAAgB,YAAY,CAAC,IAAI,GAAE,MAAkB,GAAG,eAAe,EAAE,CA2CxE;AAED,wBAAgB,aAAa,CAC5B,QAAQ,EAAE,SAAS,eAAe,EAAE,EACpC,IAAI,GAAE,MAAkB,GACtB,IAAI,CAmBN;AAED,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,GAAG,IAAI,CAa3E;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAC5B,OAAO,EAAE,eAAe,EACxB,GAAG,GAAE,MAAM,CAAC,UAAwB,GAClC,MAAM,GAAG,IAAI,CAWf;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,GAAG,eAAe,GAAG,IAAI,CAExF"}
@@ -1,133 +0,0 @@
1
- /**
2
- * `~/.namzu/providers.json` store.
3
- *
4
- * - Reads return `[]` (not error) when the file is missing — first-run UX.
5
- * - Writes are atomic: temp file + rename. Mode 0600 enforced on every write.
6
- * - `resolveApiKey(profile, env)` cascades `NAMZU_<NAME>_API_KEY` (per-
7
- * profile override) → per-type vendor default (`OPENAI_API_KEY` etc.)
8
- * → profile.apiKey on-disk → null.
9
- * - Uniqueness invariants enforced on write: no duplicate `name`; at most
10
- * one profile with `default: true`.
11
- */
12
- import { randomBytes } from 'node:crypto';
13
- import { chmodSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
14
- import { homedir } from 'node:os';
15
- import { dirname, join } from 'node:path';
16
- import { PROVIDERS_FILE_VERSION, ProfileValidationError, TYPE_ENV_FALLBACK, validateProfile, } from './schema.js';
17
- const FILE_MODE = 0o600;
18
- const DIR_MODE = 0o700;
19
- export class ProvidersStoreError extends Error {
20
- constructor(message) {
21
- super(message);
22
- this.name = 'ProvidersStoreError';
23
- }
24
- }
25
- export function providersPath(home = homedir()) {
26
- return join(home, '.namzu', 'providers.json');
27
- }
28
- export function readProfiles(home = homedir()) {
29
- const path = providersPath(home);
30
- let raw;
31
- try {
32
- raw = readFileSync(path, 'utf8');
33
- }
34
- catch (err) {
35
- if (err.code === 'ENOENT')
36
- return [];
37
- throw new ProvidersStoreError(`could not read ${path}: ${err instanceof Error ? err.message : String(err)}`);
38
- }
39
- let parsed;
40
- try {
41
- parsed = JSON.parse(raw);
42
- }
43
- catch (err) {
44
- throw new ProvidersStoreError(`${path} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`);
45
- }
46
- if (typeof parsed !== 'object' || parsed === null) {
47
- throw new ProvidersStoreError(`${path} top-level must be an object`);
48
- }
49
- const file = parsed;
50
- if (file.version !== PROVIDERS_FILE_VERSION) {
51
- throw new ProvidersStoreError(`${path} has unsupported version ${String(file.version)}; expected ${PROVIDERS_FILE_VERSION}. Upgrade @namzu/cli, or back up the file and re-create your profiles with \`namzu providers add\`.`);
52
- }
53
- if (!Array.isArray(file.profiles)) {
54
- throw new ProvidersStoreError(`${path}.profiles must be an array`);
55
- }
56
- const validated = [];
57
- for (const entry of file.profiles) {
58
- try {
59
- validated.push(validateProfile(entry));
60
- }
61
- catch (err) {
62
- if (err instanceof ProfileValidationError) {
63
- throw new ProvidersStoreError(`${path}: invalid profile — ${err.message}`);
64
- }
65
- throw err;
66
- }
67
- }
68
- return validated;
69
- }
70
- export function writeProfiles(profiles, home = homedir()) {
71
- assertInvariants(profiles);
72
- const path = providersPath(home);
73
- const dir = dirname(path);
74
- mkdirSync(dir, { recursive: true, mode: DIR_MODE });
75
- const payload = { version: PROVIDERS_FILE_VERSION, profiles: [...profiles] };
76
- const body = `${JSON.stringify(payload, null, 2)}\n`;
77
- // PID alone is not enough — two concurrent writes in the same process
78
- // (Promise.all on `providers add` from a script, for example) would
79
- // collide on the temp file and one mutation could be lost. Append a
80
- // random suffix so each writer has its own temp path; the final
81
- // `renameSync` is atomic per-rename so the last successful rename
82
- // wins (caller's responsibility to serialize semantically distinct
83
- // mutations — see assertInvariants for the in-memory check).
84
- const tmp = `${path}.tmp.${process.pid}.${randomBytes(4).toString('hex')}`;
85
- writeFileSync(tmp, body, { mode: FILE_MODE });
86
- // Ensure mode even when umask interfered.
87
- chmodSync(tmp, FILE_MODE);
88
- renameSync(tmp, path);
89
- }
90
- export function assertInvariants(profiles) {
91
- const seen = new Set();
92
- let defaults = 0;
93
- for (const p of profiles) {
94
- if (seen.has(p.name)) {
95
- throw new ProvidersStoreError(`duplicate profile name: ${p.name}`);
96
- }
97
- seen.add(p.name);
98
- if (p.default === true)
99
- defaults += 1;
100
- }
101
- if (defaults > 1) {
102
- throw new ProvidersStoreError(`at most one profile may have default: true (got ${defaults})`);
103
- }
104
- }
105
- /**
106
- * Resolve the live API key for a profile, honoring overrides:
107
- * 1. `NAMZU_<UPPERCASE_NAME>_API_KEY` (per-profile override)
108
- * 2. Per-type vendor default (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, etc.)
109
- * 3. `profile.apiKey` (on-disk)
110
- * 4. `null` (no key — caller decides whether that's fatal)
111
- */
112
- export function resolveApiKey(profile, env = process.env) {
113
- const namedEnv = env[`NAMZU_${nameToEnv(profile.name)}_API_KEY`];
114
- if (namedEnv && namedEnv.length > 0)
115
- return namedEnv;
116
- const fallbackName = TYPE_ENV_FALLBACK[profile.type];
117
- if (fallbackName) {
118
- const v = env[fallbackName];
119
- if (v && v.length > 0)
120
- return v;
121
- }
122
- const onDisk = profile.apiKey;
123
- if (onDisk && onDisk.length > 0)
124
- return onDisk;
125
- return null;
126
- }
127
- export function findDefault(profiles) {
128
- return profiles.find((p) => p.default === true) ?? null;
129
- }
130
- function nameToEnv(name) {
131
- return name.toUpperCase().replace(/[^A-Z0-9]/g, '_');
132
- }
133
- //# sourceMappingURL=store.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/integrations/providers/store.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=store.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"store.test.d.ts","sourceRoot":"","sources":["../../../src/integrations/providers/store.test.ts"],"names":[],"mappings":""}
@@ -1,135 +0,0 @@
1
- import { mkdirSync, mkdtempSync, readFileSync, statSync, writeFileSync } from 'node:fs';
2
- import { tmpdir } from 'node:os';
3
- import { join } from 'node:path';
4
- import { describe, expect, it } from 'vitest';
5
- import { ProvidersStoreError, assertInvariants, findDefault, providersPath, readProfiles, resolveApiKey, writeProfiles, } from './store.js';
6
- /**
7
- * POSIX file modes do not exist on Windows: `chmod` is a no-op there and
8
- * `fs.stat().mode` reports a fixed value, so these cases assert a
9
- * permission the platform cannot enforce. Skipping keeps the suite
10
- * meaningful on Windows instead of permanently red — the behavior itself
11
- * is still covered on Linux and macOS, where it actually matters.
12
- */
13
- const IS_WINDOWS = process.platform === 'win32';
14
- function tmpHome() {
15
- return mkdtempSync(join(tmpdir(), 'namzu-providers-'));
16
- }
17
- const anthropic = (over = {}) => ({
18
- name: 'a',
19
- type: 'anthropic',
20
- apiKey: 'sk-ant-deadbeef',
21
- ...over,
22
- });
23
- const openai = (over = {}) => ({
24
- name: 'o',
25
- type: 'openai',
26
- apiKey: 'sk-openai-cafebabe',
27
- ...over,
28
- });
29
- describe('readProfiles', () => {
30
- it('returns an empty array when the file is missing', () => {
31
- expect(readProfiles(tmpHome())).toEqual([]);
32
- });
33
- it('throws ProvidersStoreError on malformed JSON', () => {
34
- const home = tmpHome();
35
- mkdirSync(join(home, '.namzu'));
36
- writeFileSync(join(home, '.namzu', 'providers.json'), '{not json}');
37
- expect(() => readProfiles(home)).toThrow(ProvidersStoreError);
38
- });
39
- it('throws on wrong version', () => {
40
- const home = tmpHome();
41
- mkdirSync(join(home, '.namzu'));
42
- writeFileSync(join(home, '.namzu', 'providers.json'), JSON.stringify({ version: 99, profiles: [] }));
43
- expect(() => readProfiles(home)).toThrowError(/unsupported version/);
44
- });
45
- });
46
- describe('writeProfiles', () => {
47
- it('round-trips a profile through disk', () => {
48
- const home = tmpHome();
49
- writeProfiles([anthropic()], home);
50
- expect(readProfiles(home)).toEqual([anthropic()]);
51
- });
52
- it.skipIf(IS_WINDOWS)('enforces mode 0600 on the file and 0700 on the directory', () => {
53
- const home = tmpHome();
54
- writeProfiles([anthropic()], home);
55
- const fileStat = statSync(providersPath(home));
56
- const dirStat = statSync(join(home, '.namzu'));
57
- expect(fileStat.mode & 0o777).toBe(0o600);
58
- expect(dirStat.mode & 0o777).toBe(0o700);
59
- });
60
- it('writes valid JSON that includes the version header', () => {
61
- const home = tmpHome();
62
- writeProfiles([anthropic()], home);
63
- const raw = readFileSync(providersPath(home), 'utf8');
64
- const parsed = JSON.parse(raw);
65
- expect(parsed.version).toBe(1);
66
- expect(Array.isArray(parsed.profiles)).toBe(true);
67
- });
68
- it('rejects duplicate names', () => {
69
- expect(() => writeProfiles([anthropic(), anthropic()], tmpHome())).toThrowError(/duplicate profile name/);
70
- });
71
- it('rejects more than one default', () => {
72
- expect(() => writeProfiles([anthropic({ default: true }), openai({ name: 'o', default: true })], tmpHome())).toThrowError(/at most one/);
73
- });
74
- });
75
- describe('concurrent writes', () => {
76
- it('two simultaneous writeProfiles calls do not collide on the temp file', async () => {
77
- const home = tmpHome();
78
- // Fire two writes in parallel. Each carries a different profile set
79
- // so we can tell which one won the final rename — the important
80
- // guarantee is that NEITHER throws (no temp-path collision) and
81
- // the final on-disk state is exactly one of the two valid inputs
82
- // (no half-written, no merged garbage).
83
- const a = anthropic({ name: 'one' });
84
- const b = openai({ name: 'two' });
85
- await Promise.all([
86
- Promise.resolve().then(() => writeProfiles([a], home)),
87
- Promise.resolve().then(() => writeProfiles([b], home)),
88
- ]);
89
- const final = readProfiles(home);
90
- expect(final.length).toBe(1);
91
- expect(['one', 'two']).toContain(final[0]?.name);
92
- });
93
- });
94
- describe('assertInvariants', () => {
95
- it('passes for an empty store', () => {
96
- expect(() => assertInvariants([])).not.toThrow();
97
- });
98
- it('passes for a single profile with default=true', () => {
99
- expect(() => assertInvariants([anthropic({ default: true })])).not.toThrow();
100
- });
101
- });
102
- describe('resolveApiKey', () => {
103
- it('returns null when no key is anywhere', () => {
104
- const p = { name: 'x', type: 'anthropic' };
105
- expect(resolveApiKey(p, {})).toBeNull();
106
- });
107
- it('reads from profile.apiKey when no env override', () => {
108
- expect(resolveApiKey(anthropic(), {})).toBe('sk-ant-deadbeef');
109
- });
110
- it('per-type env (ANTHROPIC_API_KEY) wins over file', () => {
111
- expect(resolveApiKey(anthropic(), { ANTHROPIC_API_KEY: 'env-key' })).toBe('env-key');
112
- });
113
- it('per-profile env (NAMZU_<NAME>_API_KEY) wins over per-type', () => {
114
- expect(resolveApiKey(anthropic({ name: 'work' }), {
115
- ANTHROPIC_API_KEY: 'type-key',
116
- NAMZU_WORK_API_KEY: 'profile-key',
117
- })).toBe('profile-key');
118
- });
119
- it('normalizes profile names with non-alphanumerics in env lookup', () => {
120
- expect(resolveApiKey(anthropic({ name: 'work-1' }), { NAMZU_WORK_1_API_KEY: 'normalized' })).toBe('normalized');
121
- });
122
- it('returns null for ollama (no api-key concept) when nothing is set', () => {
123
- expect(resolveApiKey({ name: 'local', type: 'ollama' }, {})).toBeNull();
124
- });
125
- });
126
- describe('findDefault', () => {
127
- it('returns the profile with default=true', () => {
128
- const list = [anthropic(), openai({ default: true })];
129
- expect(findDefault(list)?.name).toBe('o');
130
- });
131
- it('returns null when nothing is marked default', () => {
132
- expect(findDefault([anthropic(), openai()])).toBeNull();
133
- });
134
- });
135
- //# sourceMappingURL=store.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"store.test.js","sourceRoot":"","sources":["../../../src/integrations/providers/store.test.ts"],"names":[],"mappings":"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"}
@@ -1,21 +0,0 @@
1
- /**
2
- * A closed workspace takes no new conversation from the CLI either.
3
- *
4
- * The kernel gained a workspace-closed gate and it was applied to the SDK's own
5
- * ingress paths. `startConversation` calls `createSession` on the store
6
- * DIRECTLY, and a store deliberately holds no view of workspace status, so the
7
- * invariant did not reach here.
8
- *
9
- * Whether that mattered turned on one question a grep cannot answer: does the
10
- * CLI ever reach a project it did not just create? It does. `openSessions`
11
- * reads the project id back out of `.namzu/cli.json` and creates a new project
12
- * only when the pointer is missing or stale — so every run after the first
13
- * attaches to a project that already existed and may since have been closed.
14
- *
15
- * That is why this test archives a project created by an EARLIER `openSessions`
16
- * and then reopens the same directory. A test that archived a project it made
17
- * itself, in one call, would pass against the first-run case the gate can never
18
- * fire on.
19
- */
20
- export {};
21
- //# sourceMappingURL=archived-workspace.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"archived-workspace.test.d.ts","sourceRoot":"","sources":["../../../../src/integrations/sessions/__tests__/archived-workspace.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG"}
@@ -1,62 +0,0 @@
1
- /**
2
- * A closed workspace takes no new conversation from the CLI either.
3
- *
4
- * The kernel gained a workspace-closed gate and it was applied to the SDK's own
5
- * ingress paths. `startConversation` calls `createSession` on the store
6
- * DIRECTLY, and a store deliberately holds no view of workspace status, so the
7
- * invariant did not reach here.
8
- *
9
- * Whether that mattered turned on one question a grep cannot answer: does the
10
- * CLI ever reach a project it did not just create? It does. `openSessions`
11
- * reads the project id back out of `.namzu/cli.json` and creates a new project
12
- * only when the pointer is missing or stale — so every run after the first
13
- * attaches to a project that already existed and may since have been closed.
14
- *
15
- * That is why this test archives a project created by an EARLIER `openSessions`
16
- * and then reopens the same directory. A test that archived a project it made
17
- * itself, in one call, would pass against the first-run case the gate can never
18
- * fire on.
19
- */
20
- import { mkdtempSync, rmSync } from 'node:fs';
21
- import { tmpdir } from 'node:os';
22
- import { join } from 'node:path';
23
- import { afterEach, beforeEach, describe, expect, it } from 'vitest';
24
- import { ProjectManager, UNKNOWN_TENANT_ID } from '@namzu/sdk';
25
- import { openSessions, startConversation } from '../store.js';
26
- let cwd;
27
- beforeEach(() => {
28
- cwd = mkdtempSync(join(tmpdir(), 'namzu-archived-'));
29
- });
30
- afterEach(() => {
31
- rmSync(cwd, { recursive: true, force: true });
32
- });
33
- describe('a workspace its owner has closed', () => {
34
- it('refuses a new conversation, instead of quietly accepting work', async () => {
35
- // First run: creates the project and writes the pointer.
36
- const first = await openSessions(cwd);
37
- await new ProjectManager({ store: first.store }).archive(first.projectId, UNKNOWN_TENANT_ID);
38
- // A later run in the same directory reaches the SAME project through the
39
- // pointer — the case that exists only from the second run onward.
40
- const later = await openSessions(cwd);
41
- expect(later.projectId, 'the pointer has to be what makes this reachable').toBe(first.projectId);
42
- await expect(startConversation(later)).rejects.toThrow(/archiv|closed/i);
43
- });
44
- it('still starts a conversation in an open one', async () => {
45
- // The other half. A gate nothing can get past has broken the product,
46
- // and this is the assertion that would catch a `requireOpenProject` call
47
- // wired to the wrong project id.
48
- const sessions = await openSessions(cwd);
49
- const id = await startConversation(sessions);
50
- expect(typeof id).toBe('string');
51
- expect(id.length).toBeGreaterThan(0);
52
- });
53
- it('names the workspace in the refusal', async () => {
54
- // A refusal that does not say which workspace sends the reader nowhere:
55
- // the whole point is that an owner closed this one on purpose.
56
- const first = await openSessions(cwd);
57
- await new ProjectManager({ store: first.store }).archive(first.projectId, UNKNOWN_TENANT_ID);
58
- const later = await openSessions(cwd);
59
- await expect(startConversation(later)).rejects.toThrow(new RegExp(later.projectId));
60
- });
61
- });
62
- //# sourceMappingURL=archived-workspace.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"archived-workspace.test.js","sourceRoot":"","sources":["../../../../src/integrations/sessions/__tests__/archived-workspace.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAEpE,OAAO,EAAE,cAAc,EAAiB,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAE7E,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAE7D,IAAI,GAAW,CAAA;AAEf,UAAU,CAAC,GAAG,EAAE;IACf,GAAG,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,iBAAiB,CAAC,CAAC,CAAA;AACrD,CAAC,CAAC,CAAA;AAEF,SAAS,CAAC,GAAG,EAAE;IACd,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AAC9C,CAAC,CAAC,CAAA;AAEF,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IACjD,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC9E,yDAAyD;QACzD,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAA;QACrC,MAAM,IAAI,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,CACvD,KAAK,CAAC,SAAS,EACf,iBAA6B,CAC7B,CAAA;QAED,yEAAyE;QACzE,kEAAkE;QAClE,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAA;QACrC,MAAM,CAAC,KAAK,CAAC,SAAS,EAAE,iDAAiD,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;QAEhG,MAAM,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAA;IACzE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC3D,sEAAsE;QACtE,yEAAyE;QACzE,iCAAiC;QACjC,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAA;QAExC,MAAM,EAAE,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAA;QAE5C,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;QAChC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAA;IACrC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QACnD,wEAAwE;QACxE,+DAA+D;QAC/D,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAA;QACrC,MAAM,IAAI,cAAc,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,CACvD,KAAK,CAAC,SAAS,EACf,iBAA6B,CAC7B,CAAA;QAED,MAAM,KAAK,GAAG,MAAM,YAAY,CAAC,GAAG,CAAC,CAAA;QAErC,MAAM,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAA;IACpF,CAAC,CAAC,CAAA;AACH,CAAC,CAAC,CAAA"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=delegation-trace.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"delegation-trace.test.d.ts","sourceRoot":"","sources":["../../../../src/integrations/subagents/__tests__/delegation-trace.test.ts"],"names":[],"mappings":""}
@@ -1,114 +0,0 @@
1
- import { afterEach, describe, expect, it, vi } from 'vitest';
2
- import { AgentRegistry, LocalTaskGateway, } from '@namzu/sdk';
3
- import { createSubagentRuntime } from '../runtime.js';
4
- /**
5
- * A delegated run belongs inside the turn that asked for it.
6
- *
7
- * The kernel supports this end to end — the executing tool's span reaches
8
- * `createTask`, survives `configOverrides`, is stamped onto the child config
9
- * after the host's `configBuilder` runs, and becomes the child run's trace
10
- * parent. Every hop was built and tested. The `Agent` tool simply did not pass
11
- * the first one, so a sub-agent opened its own ROOT trace and the delegation
12
- * structure — the one thing a delegation trace exists to record — was absent.
13
- *
14
- * The gateway is constructed inside the runtime, so the spy goes on its
15
- * prototype: this drives the real tool through the real wiring rather than
16
- * re-deriving what the tool ought to do. A unit test on the span helper would
17
- * have passed throughout the defect.
18
- */
19
- const fakeSpan = { __brand: 'span' };
20
- function toolContext(parentSpan) {
21
- return { runId: 'run_test', ...(parentSpan ? { parentSpan } : {}) };
22
- }
23
- async function buildAgentTool(extra = {}) {
24
- const created = [];
25
- const registered = [];
26
- vi.spyOn(AgentRegistry.prototype, 'register').mockImplementation((def) => {
27
- for (const d of Array.isArray(def) ? def : [def])
28
- registered.push(d);
29
- });
30
- vi.spyOn(LocalTaskGateway.prototype, 'createTask').mockImplementation(async (options) => {
31
- created.push(options);
32
- return { taskId: 'tsk_1' };
33
- });
34
- vi.spyOn(LocalTaskGateway.prototype, 'waitForTask').mockResolvedValue({
35
- state: 'completed',
36
- result: { status: 'completed', result: 'done' },
37
- });
38
- const runtime = await createSubagentRuntime({
39
- cwd: '/tmp',
40
- model: 'test-model',
41
- buildProvider: () => ({}),
42
- buildTools: () => ({}),
43
- ...extra,
44
- });
45
- return { agentTool: runtime.agentTool, created, registered };
46
- }
47
- afterEach(() => {
48
- vi.restoreAllMocks();
49
- });
50
- describe('the Agent tool parents a delegated run to the turn that asked for it', () => {
51
- it('passes the executing tool span through to the child run', async () => {
52
- const { agentTool, created } = await buildAgentTool();
53
- await agentTool.execute({ description: 'audit', prompt: 'do a thing' }, toolContext(fakeSpan));
54
- expect(created).toHaveLength(1);
55
- expect(created[0]?.parentSpan).toBe(fakeSpan);
56
- });
57
- it('omits the key entirely when the turn supplied no span', async () => {
58
- // Not the same as passing `undefined`: the kernel branches on the
59
- // property's presence, and a top-level run with no parent is correct
60
- // to start its own root. Refusing to invent one is the other half of
61
- // the fix, not an edge case.
62
- const { agentTool, created } = await buildAgentTool();
63
- await agentTool.execute({ description: 'audit', prompt: 'do a thing' }, toolContext());
64
- expect(created[0]).not.toHaveProperty('parentSpan');
65
- });
66
- it('parents a dynamically defined specialist too', async () => {
67
- // The `role` branch registers a fresh agent before delegating, and it
68
- // is a second path to the same `createTask`. One of two paths carrying
69
- // a signal is how this class of defect survives a green suite.
70
- const { agentTool, created } = await buildAgentTool();
71
- await agentTool.execute({ description: 'audit', prompt: 'do a thing', role: 'You are an auditor' }, toolContext(fakeSpan));
72
- expect(created[0]?.parentSpan).toBe(fakeSpan);
73
- });
74
- });
75
- /**
76
- * The project's standing instructions bind a specialist the model invents at
77
- * call time, not only the pre-registered general-purpose sub-agent.
78
- *
79
- * `role` is a SECOND registration path to the same definition builder, and one
80
- * of two paths carrying a signal is how this class of defect survives a green
81
- * suite: the delegation everyone tests would honour the project's rules and
82
- * the one the model actually reaches for — a named specialist — would not.
83
- */
84
- describe('a sub-agent is bound by the project it works in', () => {
85
- const INSTRUCTIONS = '## Project instructions\n\nNever use a default export.';
86
- it('gives the general-purpose sub-agent the block', async () => {
87
- const { registered } = await buildAgentTool({ projectInstructions: INSTRUCTIONS });
88
- const general = registered.find((d) => d.info.id === 'general-purpose');
89
- const config = (await general?.configBuilder?.({}));
90
- expect(config?.systemPrompt).toContain('Never use a default export.');
91
- });
92
- it('gives a specialist defined at call time the same block', async () => {
93
- const { agentTool, registered } = await buildAgentTool({ projectInstructions: INSTRUCTIONS });
94
- await agentTool.execute({ description: 'audit', prompt: 'do a thing', role: 'You are a security auditor' }, toolContext());
95
- const specialist = registered.find((d) => d.info.id.startsWith('dyn-'));
96
- if (!specialist?.configBuilder) {
97
- throw new Error('no dynamic specialist was registered — this test proves nothing');
98
- }
99
- const prompt = String((await specialist.configBuilder({})).systemPrompt ?? '');
100
- expect(prompt).toContain('You are a security auditor');
101
- expect(prompt).toContain('Never fabricate.');
102
- expect(prompt).toContain('Never use a default export.');
103
- // Order is the containment: a persona and a project file are both text
104
- // the model can influence, and both sit after the guardrails.
105
- expect(prompt.indexOf('Never fabricate.')).toBeLessThan(prompt.indexOf('Never use a default export.'));
106
- });
107
- it('adds nothing when the project declares none', async () => {
108
- const { registered } = await buildAgentTool();
109
- const general = registered.find((d) => d.info.id === 'general-purpose');
110
- const config = (await general?.configBuilder?.({}));
111
- expect(config?.systemPrompt).not.toContain('Project instructions');
112
- });
113
- });
114
- //# sourceMappingURL=delegation-trace.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"delegation-trace.test.js","sourceRoot":"","sources":["../../../../src/integrations/subagents/__tests__/delegation-trace.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=store.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"store.test.d.ts","sourceRoot":"","sources":["../../../src/integrations/trust/store.test.ts"],"names":[],"mappings":""}