@mrpatronz/nexusflow 1.9.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 (237) hide show
  1. package/README.md +2 -1
  2. package/dist/agent/AcpCliAdapter.d.ts +75 -0
  3. package/dist/agent/AcpCliAdapter.d.ts.map +1 -0
  4. package/dist/agent/AcpCliAdapter.js +292 -0
  5. package/dist/agent/AcpCliAdapter.js.map +1 -0
  6. package/dist/agent/AcpCliAdapter.test.d.ts +2 -0
  7. package/dist/agent/AcpCliAdapter.test.d.ts.map +1 -0
  8. package/dist/agent/AcpCliAdapter.test.js +235 -0
  9. package/dist/agent/AcpCliAdapter.test.js.map +1 -0
  10. package/dist/agent/ClaudeCliAdapter.d.ts +40 -5
  11. package/dist/agent/ClaudeCliAdapter.d.ts.map +1 -1
  12. package/dist/agent/ClaudeCliAdapter.js +212 -15
  13. package/dist/agent/ClaudeCliAdapter.js.map +1 -1
  14. package/dist/agent/ClaudeCliAdapter.test.d.ts +2 -0
  15. package/dist/agent/ClaudeCliAdapter.test.d.ts.map +1 -0
  16. package/dist/agent/ClaudeCliAdapter.test.js +320 -0
  17. package/dist/agent/ClaudeCliAdapter.test.js.map +1 -0
  18. package/dist/agent/CliAdapterBase.d.ts +29 -12
  19. package/dist/agent/CliAdapterBase.d.ts.map +1 -1
  20. package/dist/agent/CliAdapterBase.js +76 -36
  21. package/dist/agent/CliAdapterBase.js.map +1 -1
  22. package/dist/agent/CodexCliAdapter.d.ts +51 -0
  23. package/dist/agent/CodexCliAdapter.d.ts.map +1 -0
  24. package/dist/agent/CodexCliAdapter.js +226 -0
  25. package/dist/agent/CodexCliAdapter.js.map +1 -0
  26. package/dist/agent/CodexCliAdapter.test.d.ts +2 -0
  27. package/dist/agent/CodexCliAdapter.test.d.ts.map +1 -0
  28. package/dist/agent/CodexCliAdapter.test.js +316 -0
  29. package/dist/agent/CodexCliAdapter.test.js.map +1 -0
  30. package/dist/agent/CopilotAcpAdapter.d.ts +7 -0
  31. package/dist/agent/CopilotAcpAdapter.d.ts.map +1 -0
  32. package/dist/agent/CopilotAcpAdapter.js +29 -0
  33. package/dist/agent/CopilotAcpAdapter.js.map +1 -0
  34. package/dist/agent/ProviderRegistry.d.ts +50 -3
  35. package/dist/agent/ProviderRegistry.d.ts.map +1 -1
  36. package/dist/agent/ProviderRegistry.js +43 -8
  37. package/dist/agent/ProviderRegistry.js.map +1 -1
  38. package/dist/agent/ProviderRegistry.test.js +53 -0
  39. package/dist/agent/ProviderRegistry.test.js.map +1 -1
  40. package/dist/agent/adapters.d.ts +16 -0
  41. package/dist/agent/adapters.d.ts.map +1 -1
  42. package/dist/agent/adapters.js +114 -4
  43. package/dist/agent/adapters.js.map +1 -1
  44. package/dist/agent/adapters.test.d.ts +2 -0
  45. package/dist/agent/adapters.test.d.ts.map +1 -0
  46. package/dist/agent/adapters.test.js +71 -0
  47. package/dist/agent/adapters.test.js.map +1 -0
  48. package/dist/agent/cliAvailability.d.ts +86 -0
  49. package/dist/agent/cliAvailability.d.ts.map +1 -0
  50. package/dist/agent/cliAvailability.js +231 -0
  51. package/dist/agent/cliAvailability.js.map +1 -0
  52. package/dist/agent/cliAvailability.test.d.ts +2 -0
  53. package/dist/agent/cliAvailability.test.d.ts.map +1 -0
  54. package/dist/agent/cliAvailability.test.js +192 -0
  55. package/dist/agent/cliAvailability.test.js.map +1 -0
  56. package/dist/agent/session.d.ts +2 -1
  57. package/dist/agent/session.d.ts.map +1 -1
  58. package/dist/agent/session.js +15 -4
  59. package/dist/agent/session.js.map +1 -1
  60. package/dist/agent/session.test.js +29 -8
  61. package/dist/agent/session.test.js.map +1 -1
  62. package/dist/analyzers/detect-deps.d.ts.map +1 -1
  63. package/dist/analyzers/detect-deps.js +16 -19
  64. package/dist/analyzers/detect-deps.js.map +1 -1
  65. package/dist/analyzers/index.d.ts +0 -2
  66. package/dist/analyzers/index.d.ts.map +1 -1
  67. package/dist/analyzers/index.js +6 -9
  68. package/dist/analyzers/index.js.map +1 -1
  69. package/dist/commands/commands.test.js +4 -3
  70. package/dist/commands/commands.test.js.map +1 -1
  71. package/dist/commands/create.d.ts.map +1 -1
  72. package/dist/commands/create.js.map +1 -1
  73. package/dist/commands/knowledge.d.ts +10 -0
  74. package/dist/commands/knowledge.d.ts.map +1 -1
  75. package/dist/commands/knowledge.js +27 -1
  76. package/dist/commands/knowledge.js.map +1 -1
  77. package/dist/commands/knowledge.test.d.ts +2 -0
  78. package/dist/commands/knowledge.test.d.ts.map +1 -0
  79. package/dist/commands/knowledge.test.js +77 -0
  80. package/dist/commands/knowledge.test.js.map +1 -0
  81. package/dist/commands/refresh.d.ts +2 -4
  82. package/dist/commands/refresh.d.ts.map +1 -1
  83. package/dist/commands/refresh.js +4 -20
  84. package/dist/commands/refresh.js.map +1 -1
  85. package/dist/core/adapters/registry.d.ts.map +1 -1
  86. package/dist/core/adapters/registry.js +8 -3
  87. package/dist/core/adapters/registry.js.map +1 -1
  88. package/dist/core/adapters/storage.test.js +5 -24
  89. package/dist/core/adapters/storage.test.js.map +1 -1
  90. package/dist/core/analysis-cache.d.ts +15 -8
  91. package/dist/core/analysis-cache.d.ts.map +1 -1
  92. package/dist/core/analysis-cache.js +61 -10
  93. package/dist/core/analysis-cache.js.map +1 -1
  94. package/dist/core/analysis-cache.test.js +17 -4
  95. package/dist/core/analysis-cache.test.js.map +1 -1
  96. package/dist/core/config.d.ts.map +1 -1
  97. package/dist/core/config.js +5 -4
  98. package/dist/core/config.js.map +1 -1
  99. package/dist/core/doctor.d.ts.map +1 -1
  100. package/dist/core/doctor.js +9 -5
  101. package/dist/core/doctor.js.map +1 -1
  102. package/dist/core/knowledge.d.ts +14 -4
  103. package/dist/core/knowledge.d.ts.map +1 -1
  104. package/dist/core/knowledge.js +64 -14
  105. package/dist/core/knowledge.js.map +1 -1
  106. package/dist/core/knowledge.test.js +54 -2
  107. package/dist/core/knowledge.test.js.map +1 -1
  108. package/dist/core/locks.d.ts +43 -0
  109. package/dist/core/locks.d.ts.map +1 -0
  110. package/dist/core/locks.js +102 -0
  111. package/dist/core/locks.js.map +1 -0
  112. package/dist/core/locks.test.d.ts +2 -0
  113. package/dist/core/locks.test.d.ts.map +1 -0
  114. package/dist/core/locks.test.js +95 -0
  115. package/dist/core/locks.test.js.map +1 -0
  116. package/dist/core/ports/storage.d.ts +3 -3
  117. package/dist/core/ports/storage.d.ts.map +1 -1
  118. package/dist/core/refresh.d.ts +12 -13
  119. package/dist/core/refresh.d.ts.map +1 -1
  120. package/dist/core/refresh.js +14 -11
  121. package/dist/core/refresh.js.map +1 -1
  122. package/dist/core/refresh.test.js +17 -11
  123. package/dist/core/refresh.test.js.map +1 -1
  124. package/dist/core/scheduler.d.ts.map +1 -1
  125. package/dist/core/scheduler.js +2 -65
  126. package/dist/core/scheduler.js.map +1 -1
  127. package/dist/core/sync.js +3 -3
  128. package/dist/core/sync.js.map +1 -1
  129. package/dist/core/worktree.js +2 -2
  130. package/dist/core/worktree.js.map +1 -1
  131. package/dist/core/worktree.test.js +2 -2
  132. package/dist/core/worktree.test.js.map +1 -1
  133. package/dist/generators/base.d.ts +31 -2
  134. package/dist/generators/base.d.ts.map +1 -1
  135. package/dist/generators/base.js +174 -238
  136. package/dist/generators/base.js.map +1 -1
  137. package/dist/generators/base.test.js +231 -24
  138. package/dist/generators/base.test.js.map +1 -1
  139. package/dist/generators/claude.d.ts +19 -5
  140. package/dist/generators/claude.d.ts.map +1 -1
  141. package/dist/generators/claude.js +33 -11
  142. package/dist/generators/claude.js.map +1 -1
  143. package/dist/generators/index.d.ts +10 -9
  144. package/dist/generators/index.d.ts.map +1 -1
  145. package/dist/generators/index.js +103 -118
  146. package/dist/generators/index.js.map +1 -1
  147. package/dist/generators/plan-generator.d.ts.map +1 -1
  148. package/dist/generators/plan-generator.js +217 -193
  149. package/dist/generators/plan-generator.js.map +1 -1
  150. package/dist/generators/plan-generator.test.d.ts +2 -0
  151. package/dist/generators/plan-generator.test.d.ts.map +1 -0
  152. package/dist/generators/plan-generator.test.js +217 -0
  153. package/dist/generators/plan-generator.test.js.map +1 -0
  154. package/dist/gui/assets/DashboardPage-BeAHHUtn.js +1 -0
  155. package/dist/gui/assets/GettingStartedPage-CFAyG0ar.js +1 -0
  156. package/dist/gui/assets/ProjectsPage-C0SmbBqW.js +1 -0
  157. package/dist/gui/assets/{ScaffoldRepoInline-DRipQsos.js → ScaffoldRepoInline-lfFwOnQu.js} +1 -1
  158. package/dist/gui/assets/SettingsPage-DIBk9fu8.js +1 -0
  159. package/dist/gui/assets/StartWorkPage-CWC5OujI.js +1 -0
  160. package/dist/gui/assets/{StrategiesPage-6LWOnKdk.js → StrategiesPage-Dcq10WZS.js} +2 -2
  161. package/dist/gui/assets/WorkspacesPage-BqOx6Gbe.js +6 -0
  162. package/dist/gui/assets/index-B5IYXvr6.css +2 -0
  163. package/dist/gui/assets/{index-CyYbQwRf.js → index-BCfJkb0T.js} +7 -7
  164. package/dist/gui/index.html +2 -2
  165. package/dist/index.js +2 -4
  166. package/dist/index.js.map +1 -1
  167. package/dist/mcp/tools.d.ts.map +1 -1
  168. package/dist/mcp/tools.js +11 -15
  169. package/dist/mcp/tools.js.map +1 -1
  170. package/dist/resources/workflows/plan-implement-review.md +8 -0
  171. package/dist/resources/workflows/research-verify.md +6 -0
  172. package/dist/resources/workflows/solo-developer.md +3 -0
  173. package/dist/server.d.ts +13 -0
  174. package/dist/server.d.ts.map +1 -1
  175. package/dist/server.js +154 -23
  176. package/dist/server.js.map +1 -1
  177. package/dist/server.test.js +147 -3
  178. package/dist/server.test.js.map +1 -1
  179. package/dist/types.d.ts +0 -24
  180. package/dist/types.d.ts.map +1 -1
  181. package/dist/utils/prompts.js +2 -2
  182. package/dist/utils/prompts.js.map +1 -1
  183. package/dist/utils/resources.d.ts +28 -0
  184. package/dist/utils/resources.d.ts.map +1 -0
  185. package/dist/utils/resources.js +54 -0
  186. package/dist/utils/resources.js.map +1 -0
  187. package/dist/utils/session-finder.d.ts +3 -0
  188. package/dist/utils/session-finder.d.ts.map +1 -1
  189. package/dist/utils/session-finder.js +54 -10
  190. package/dist/utils/session-finder.js.map +1 -1
  191. package/dist/utils/session-finder.test.js +61 -2
  192. package/dist/utils/session-finder.test.js.map +1 -1
  193. package/dist/utils/workflow-advisor.d.ts.map +1 -1
  194. package/dist/utils/workflow-advisor.js +17 -27
  195. package/dist/utils/workflow-advisor.js.map +1 -1
  196. package/dist/utils/workflows.d.ts.map +1 -1
  197. package/dist/utils/workflows.js +6 -2
  198. package/dist/utils/workflows.js.map +1 -1
  199. package/package.json +8 -4
  200. package/resources/workflows/plan-implement-review.md +8 -0
  201. package/resources/workflows/research-verify.md +6 -0
  202. package/resources/workflows/solo-developer.md +3 -0
  203. package/dist/analyzers/detect-apis.d.ts +0 -19
  204. package/dist/analyzers/detect-apis.d.ts.map +0 -1
  205. package/dist/analyzers/detect-apis.js +0 -250
  206. package/dist/analyzers/detect-apis.js.map +0 -1
  207. package/dist/analyzers/messaging-analyzer.d.ts +0 -17
  208. package/dist/analyzers/messaging-analyzer.d.ts.map +0 -1
  209. package/dist/analyzers/messaging-analyzer.js +0 -229
  210. package/dist/analyzers/messaging-analyzer.js.map +0 -1
  211. package/dist/core/adapters/vault-storage.d.ts +0 -16
  212. package/dist/core/adapters/vault-storage.d.ts.map +0 -1
  213. package/dist/core/adapters/vault-storage.js +0 -77
  214. package/dist/core/adapters/vault-storage.js.map +0 -1
  215. package/dist/core/graph.d.ts +0 -35
  216. package/dist/core/graph.d.ts.map +0 -1
  217. package/dist/core/graph.js +0 -281
  218. package/dist/core/graph.js.map +0 -1
  219. package/dist/generators/diff-context.d.ts +0 -6
  220. package/dist/generators/diff-context.d.ts.map +0 -1
  221. package/dist/generators/diff-context.js +0 -70
  222. package/dist/generators/diff-context.js.map +0 -1
  223. package/dist/generators/map-generator.d.ts +0 -15
  224. package/dist/generators/map-generator.d.ts.map +0 -1
  225. package/dist/generators/map-generator.js +0 -514
  226. package/dist/generators/map-generator.js.map +0 -1
  227. package/dist/generators/map-generator.test.d.ts +0 -2
  228. package/dist/generators/map-generator.test.d.ts.map +0 -1
  229. package/dist/generators/map-generator.test.js +0 -147
  230. package/dist/generators/map-generator.test.js.map +0 -1
  231. package/dist/gui/assets/DashboardPage-C3NH97y2.js +0 -1
  232. package/dist/gui/assets/GettingStartedPage-og-Kv7Sm.js +0 -1
  233. package/dist/gui/assets/ProjectsPage-COqqadEr.js +0 -1
  234. package/dist/gui/assets/SettingsPage-CpU3V9oU.js +0 -1
  235. package/dist/gui/assets/StartWorkPage-DIND0hJy.js +0 -1
  236. package/dist/gui/assets/WorkspacesPage-BUqgOhuy.js +0 -6
  237. package/dist/gui/assets/index-CsA2SueF.css +0 -2
@@ -0,0 +1,7 @@
1
+ import { AcpCliAdapter, type AcpTransportFactory } from './AcpCliAdapter.js';
2
+ /** Copilot ACP starts with a read/search-only tool surface. */
3
+ export declare function buildCopilotAcpArgs(): string[];
4
+ export declare class CopilotAcpAdapter extends AcpCliAdapter {
5
+ constructor(transportFactory?: AcpTransportFactory);
6
+ }
7
+ //# sourceMappingURL=CopilotAcpAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CopilotAcpAdapter.d.ts","sourceRoot":"","sources":["../../src/agent/CopilotAcpAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAI7E,+DAA+D;AAC/D,wBAAgB,mBAAmB,IAAI,MAAM,EAAE,CAW9C;AAED,qBAAa,iBAAkB,SAAQ,aAAa;gBACtC,gBAAgB,CAAC,EAAE,mBAAmB;CAUnD"}
@@ -0,0 +1,29 @@
1
+ import { AcpCliAdapter } from './AcpCliAdapter.js';
2
+ import { findExecutable } from './cliAvailability.js';
3
+ import { isValidSessionUuid } from './session.js';
4
+ /** Copilot ACP starts with a read/search-only tool surface. */
5
+ export function buildCopilotAcpArgs() {
6
+ return [
7
+ '--acp',
8
+ '--stdio',
9
+ '--available-tools=view,glob,grep',
10
+ '--disable-builtin-mcps',
11
+ '--no-ask-user',
12
+ '--no-auto-update',
13
+ '--no-remote',
14
+ '--no-remote-export',
15
+ ];
16
+ }
17
+ export class CopilotAcpAdapter extends AcpCliAdapter {
18
+ constructor(transportFactory) {
19
+ super({
20
+ executable: findExecutable('copilot') ?? 'copilot',
21
+ args: buildCopilotAcpArgs(),
22
+ label: 'GitHub Copilot CLI',
23
+ loginCommand: 'copilot login',
24
+ validateSessionId: isValidSessionUuid,
25
+ transportFactory,
26
+ });
27
+ }
28
+ }
29
+ //# sourceMappingURL=CopilotAcpAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CopilotAcpAdapter.js","sourceRoot":"","sources":["../../src/agent/CopilotAcpAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAA4B,MAAM,oBAAoB,CAAC;AAC7E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,+DAA+D;AAC/D,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL,OAAO;QACP,SAAS;QACT,kCAAkC;QAClC,wBAAwB;QACxB,eAAe;QACf,kBAAkB;QAClB,aAAa;QACb,oBAAoB;KACrB,CAAC;AACJ,CAAC;AAED,MAAM,OAAO,iBAAkB,SAAQ,aAAa;IAClD,YAAY,gBAAsC;QAChD,KAAK,CAAC;YACJ,UAAU,EAAE,cAAc,CAAC,SAAS,CAAC,IAAI,SAAS;YAClD,IAAI,EAAE,mBAAmB,EAAE;YAC3B,KAAK,EAAE,oBAAoB;YAC3B,YAAY,EAAE,eAAe;YAC7B,iBAAiB,EAAE,kBAAkB;YACrC,gBAAgB;SACjB,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -5,26 +5,73 @@ export interface ProviderStatus {
5
5
  isConfigured: boolean;
6
6
  message?: string;
7
7
  icon?: string;
8
+ accessLabel?: string;
9
+ setupIssue?: ProviderSetupIssue;
10
+ recoveryCommand?: string;
11
+ recoveryLabel?: string;
12
+ executionProfiles?: readonly ProviderExecutionProfile[];
13
+ defaultExecutionProfile?: AgentExecutionProfile;
14
+ capabilities: ProviderCapabilities;
8
15
  }
16
+ export type AgentExecutionProfile = 'review' | 'workspace-write';
17
+ export interface ProviderExecutionProfile {
18
+ id: AgentExecutionProfile;
19
+ label: string;
20
+ description: string;
21
+ }
22
+ export type ProviderSetupIssue = 'missing-cli' | 'signed-out' | 'probe-failed';
23
+ export interface ProviderSetupHelp {
24
+ setupIssue: ProviderSetupIssue;
25
+ recoveryCommand: string;
26
+ recoveryLabel: string;
27
+ }
28
+ export interface ProviderCapabilities {
29
+ transport: 'native-api' | 'cli-print' | 'acp';
30
+ sessionIdentity: 'none' | 'client-assigned' | 'provider-assigned';
31
+ workspaceAccess: 'read-only' | 'workspace-write' | 'harness-managed';
32
+ sessionIdFormat?: 'uuid' | 'opaque';
33
+ }
34
+ export type AgentEvent = 'data' | 'close' | 'error' | 'system' | 'idle' | 'session';
9
35
  export interface AgentHarness {
10
36
  start(cwd: string, session?: AgentSession): Promise<void>;
11
- send(data: string): Promise<void>;
37
+ send(data: string, executionProfile?: AgentExecutionProfile): Promise<void>;
12
38
  stop(): void;
13
- on(event: 'data' | 'close' | 'error' | 'system' | 'idle', listener: (...args: any[]) => void): this;
39
+ on(event: AgentEvent, listener: (...args: any[]) => void): this;
40
+ /**
41
+ * Detaches a listener, so a caller that attaches per operation on a long-lived
42
+ * harness can clean up rather than accumulating listener sets. Satisfied for
43
+ * free by EventEmitter, which every adapter extends.
44
+ *
45
+ * Nothing in this package calls it today — the caller it was added for was the
46
+ * workflow engine — but it belongs on the interface: `on` without `off` makes
47
+ * any repeated use of a harness a leak.
48
+ */
49
+ off(event: AgentEvent, listener: (...args: any[]) => void): this;
14
50
  }
15
51
  export interface ProviderAdapter {
16
52
  id: string;
17
53
  name: string;
18
54
  icon?: string;
55
+ accessLabel?: string;
56
+ capabilities: ProviderCapabilities;
57
+ executionProfiles?: readonly ProviderExecutionProfile[];
58
+ defaultExecutionProfile?: AgentExecutionProfile;
19
59
  isConfigured(): boolean;
20
60
  getStatusMessage(): string | undefined;
61
+ getSetupHelp?(): ProviderSetupHelp | undefined;
62
+ invalidateStatus?(): void;
21
63
  createInstance(): AgentHarness;
22
64
  }
23
65
  declare class ProviderRegistryImpl {
24
66
  private providers;
67
+ private lastRefreshCompletedAt;
25
68
  register(provider: ProviderAdapter): void;
26
69
  getProvider(id: string): ProviderAdapter | undefined;
27
- getAllStatus(): ProviderStatus[];
70
+ /** Resolve an untyped renderer value against provider-owned profiles. */
71
+ resolveExecutionProfile(provider: ProviderAdapter, requested: unknown): AgentExecutionProfile | undefined | null;
72
+ getAllStatus(options?: {
73
+ refreshProviderId?: string;
74
+ }): ProviderStatus[];
28
75
  }
29
76
  export declare const ProviderRegistry: ProviderRegistryImpl;
30
77
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"ProviderRegistry.d.ts","sourceRoot":"","sources":["../../src/agent/ProviderRegistry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAClC,IAAI,IAAI,IAAI,CAAC;IACb,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,IAAI,CAAC;CACrG;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,IAAI,OAAO,CAAC;IACxB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAAC;IACvC,cAAc,IAAI,YAAY,CAAC;CAChC;AAED,cAAM,oBAAoB;IACxB,OAAO,CAAC,SAAS,CAA2C;IAE5D,QAAQ,CAAC,QAAQ,EAAE,eAAe;IAIlC,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAIpD,YAAY,IAAI,cAAc,EAAE;CASjC;AAED,eAAO,MAAM,gBAAgB,sBAA6B,CAAC"}
1
+ {"version":3,"file":"ProviderRegistry.d.ts","sourceRoot":"","sources":["../../src/agent/ProviderRegistry.ts"],"names":[],"mappings":"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"}
@@ -1,19 +1,54 @@
1
1
  class ProviderRegistryImpl {
2
2
  providers = new Map();
3
+ lastRefreshCompletedAt = new Map();
3
4
  register(provider) {
4
5
  this.providers.set(provider.id, provider);
5
6
  }
6
7
  getProvider(id) {
7
8
  return this.providers.get(id);
8
9
  }
9
- getAllStatus() {
10
- return Array.from(this.providers.values()).map(p => ({
11
- id: p.id,
12
- name: p.name,
13
- icon: p.icon,
14
- isConfigured: p.isConfigured(),
15
- message: p.getStatusMessage()
16
- }));
10
+ /** Resolve an untyped renderer value against provider-owned profiles. */
11
+ resolveExecutionProfile(provider, requested) {
12
+ const profiles = provider.executionProfiles;
13
+ if (!profiles?.length)
14
+ return requested === undefined ? undefined : null;
15
+ if (requested !== 'review' && requested !== 'workspace-write')
16
+ return null;
17
+ return profiles.some(profile => profile.id === requested) ? requested : null;
18
+ }
19
+ getAllStatus(options = {}) {
20
+ const providers = Array.from(this.providers.values());
21
+ const refreshProvider = options.refreshProviderId
22
+ ? this.providers.get(options.refreshProviderId)
23
+ : undefined;
24
+ const lastRefresh = options.refreshProviderId
25
+ ? this.lastRefreshCompletedAt.get(options.refreshProviderId) ?? 0
26
+ : 0;
27
+ const shouldRefresh = Boolean(refreshProvider?.invalidateStatus
28
+ && Date.now() - lastRefresh >= 1_000);
29
+ if (shouldRefresh)
30
+ refreshProvider?.invalidateStatus?.();
31
+ const statuses = providers.map(provider => {
32
+ const setup = provider.getSetupHelp?.();
33
+ return {
34
+ id: provider.id,
35
+ name: provider.name,
36
+ icon: provider.icon,
37
+ accessLabel: provider.accessLabel,
38
+ capabilities: provider.capabilities,
39
+ executionProfiles: provider.executionProfiles,
40
+ defaultExecutionProfile: provider.defaultExecutionProfile,
41
+ isConfigured: provider.isConfigured(),
42
+ message: provider.getStatusMessage(),
43
+ ...setup,
44
+ };
45
+ });
46
+ // Timestamp after all synchronous probes finish so requests queued during
47
+ // a slow refresh reuse its result instead of immediately spawning again.
48
+ if (shouldRefresh && options.refreshProviderId) {
49
+ this.lastRefreshCompletedAt.set(options.refreshProviderId, Date.now());
50
+ }
51
+ return statuses;
17
52
  }
18
53
  }
19
54
  export const ProviderRegistry = new ProviderRegistryImpl();
@@ -1 +1 @@
1
- {"version":3,"file":"ProviderRegistry.js","sourceRoot":"","sources":["../../src/agent/ProviderRegistry.ts"],"names":[],"mappings":"AA0BA,MAAM,oBAAoB;IAChB,SAAS,GAAiC,IAAI,GAAG,EAAE,CAAC;IAE5D,QAAQ,CAAC,QAAyB;QAChC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,WAAW,CAAC,EAAU;QACpB,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,YAAY;QACV,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACnD,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE;YAC9B,OAAO,EAAE,CAAC,CAAC,gBAAgB,EAAE;SAC9B,CAAC,CAAC,CAAC;IACN,CAAC;CACF;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,EAAE,CAAC"}
1
+ {"version":3,"file":"ProviderRegistry.js","sourceRoot":"","sources":["../../src/agent/ProviderRegistry.ts"],"names":[],"mappings":"AA0EA,MAAM,oBAAoB;IAChB,SAAS,GAAiC,IAAI,GAAG,EAAE,CAAC;IACpD,sBAAsB,GAAwB,IAAI,GAAG,EAAE,CAAC;IAEhE,QAAQ,CAAC,QAAyB;QAChC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,WAAW,CAAC,EAAU;QACpB,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,yEAAyE;IACzE,uBAAuB,CAAC,QAAyB,EAAE,SAAkB;QACnE,MAAM,QAAQ,GAAG,QAAQ,CAAC,iBAAiB,CAAC;QAC5C,IAAI,CAAC,QAAQ,EAAE,MAAM;YAAE,OAAO,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;QACzE,IAAI,SAAS,KAAK,QAAQ,IAAI,SAAS,KAAK,iBAAiB;YAAE,OAAO,IAAI,CAAC;QAC3E,OAAO,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/E,CAAC;IAED,YAAY,CAAC,UAA0C,EAAE;QACvD,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;QACtD,MAAM,eAAe,GAAG,OAAO,CAAC,iBAAiB;YAC/C,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC;YAC/C,CAAC,CAAC,SAAS,CAAC;QACd,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB;YAC3C,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,CAAC,IAAI,CAAC;YACjE,CAAC,CAAC,CAAC,CAAC;QACN,MAAM,aAAa,GAAG,OAAO,CAC3B,eAAe,EAAE,gBAAgB;eAC9B,IAAI,CAAC,GAAG,EAAE,GAAG,WAAW,IAAI,KAAK,CACrC,CAAC;QACF,IAAI,aAAa;YAAE,eAAe,EAAE,gBAAgB,EAAE,EAAE,CAAC;QAEzD,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;YACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,YAAY,EAAE,EAAE,CAAC;YACxC,OAAO;gBACL,EAAE,EAAE,QAAQ,CAAC,EAAE;gBACf,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,WAAW,EAAE,QAAQ,CAAC,WAAW;gBACjC,YAAY,EAAE,QAAQ,CAAC,YAAY;gBACnC,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;gBAC7C,uBAAuB,EAAE,QAAQ,CAAC,uBAAuB;gBACzD,YAAY,EAAE,QAAQ,CAAC,YAAY,EAAE;gBACrC,OAAO,EAAE,QAAQ,CAAC,gBAAgB,EAAE;gBACpC,GAAG,KAAK;aACT,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,0EAA0E;QAC1E,yEAAyE;QACzE,IAAI,aAAa,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAAC;YAC/C,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QACzE,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,oBAAoB,EAAE,CAAC"}
@@ -8,6 +8,7 @@ class MockAgentHarness {
8
8
  async send(data) { }
9
9
  stop() { }
10
10
  on(event, listener) { return this; }
11
+ off(event, listener) { return this; }
11
12
  }
12
13
  // The registry is a shared singleton without a reset method, so each test
13
14
  // registers its own uniquely-named provider to stay order-independent.
@@ -15,6 +16,7 @@ function makeProvider(id, overrides = {}) {
15
16
  return {
16
17
  id,
17
18
  name: 'Mock',
19
+ capabilities: { transport: 'native-api', sessionIdentity: 'none', workspaceAccess: 'read-only' },
18
20
  isConfigured: () => true,
19
21
  getStatusMessage: () => undefined,
20
22
  createInstance: () => new MockAgentHarness(),
@@ -40,6 +42,7 @@ describe('ProviderRegistry', () => {
40
42
  expect(unconfiguredStatus).toBeDefined();
41
43
  expect(unconfiguredStatus?.isConfigured).toBe(false);
42
44
  expect(unconfiguredStatus?.message).toBe('Missing API Key');
45
+ expect(unconfiguredStatus?.capabilities.workspaceAccess).toBe('read-only');
43
46
  });
44
47
  it('should create an instance correctly', () => {
45
48
  ProviderRegistry.register(makeProvider('mock-instance'));
@@ -53,5 +56,55 @@ describe('ProviderRegistry', () => {
53
56
  expect(instance.started).toBe(true);
54
57
  }
55
58
  });
59
+ it('exposes closed setup recovery metadata and invalidates cached status on refresh', () => {
60
+ let configured = false;
61
+ let invalidations = 0;
62
+ ProviderRegistry.register(makeProvider('mock-refreshable', {
63
+ isConfigured: () => configured,
64
+ getStatusMessage: () => configured ? undefined : 'Sign in.',
65
+ getSetupHelp: () => configured ? undefined : {
66
+ setupIssue: 'signed-out',
67
+ recoveryCommand: 'mock auth login',
68
+ recoveryLabel: 'Copy sign-in command',
69
+ },
70
+ invalidateStatus: () => {
71
+ invalidations += 1;
72
+ configured = true;
73
+ },
74
+ }));
75
+ expect(ProviderRegistry.getAllStatus().find(status => status.id === 'mock-refreshable'))
76
+ .toMatchObject({ isConfigured: false, setupIssue: 'signed-out' });
77
+ expect(ProviderRegistry.getAllStatus({ refreshProviderId: 'mock-refreshable' }).find(status => status.id === 'mock-refreshable'))
78
+ .toMatchObject({ isConfigured: true });
79
+ ProviderRegistry.getAllStatus({ refreshProviderId: 'mock-refreshable' });
80
+ expect(invalidations).toBe(1);
81
+ });
82
+ it('exposes provider-owned execution profiles and validates turn authorization', () => {
83
+ const provider = makeProvider('mock-profiled', {
84
+ executionProfiles: [
85
+ { id: 'review', label: 'Review only', description: 'Read-only.' },
86
+ { id: 'workspace-write', label: 'Edit workspace', description: 'Workspace edits.' },
87
+ ],
88
+ defaultExecutionProfile: 'review',
89
+ });
90
+ ProviderRegistry.register(provider);
91
+ expect(ProviderRegistry.getAllStatus().find(status => status.id === 'mock-profiled'))
92
+ .toMatchObject({
93
+ defaultExecutionProfile: 'review',
94
+ executionProfiles: [
95
+ { id: 'review', label: 'Review only' },
96
+ { id: 'workspace-write', label: 'Edit workspace' },
97
+ ],
98
+ });
99
+ expect(ProviderRegistry.resolveExecutionProfile(provider, 'review')).toBe('review');
100
+ expect(ProviderRegistry.resolveExecutionProfile(provider, 'workspace-write')).toBe('workspace-write');
101
+ expect(ProviderRegistry.resolveExecutionProfile(provider, undefined)).toBeNull();
102
+ expect(ProviderRegistry.resolveExecutionProfile(provider, 'danger-full-access')).toBeNull();
103
+ });
104
+ it('keeps legacy providers profile-free', () => {
105
+ const provider = makeProvider('mock-legacy-profile');
106
+ expect(ProviderRegistry.resolveExecutionProfile(provider, undefined)).toBeUndefined();
107
+ expect(ProviderRegistry.resolveExecutionProfile(provider, 'review')).toBeNull();
108
+ });
56
109
  });
57
110
  //# sourceMappingURL=ProviderRegistry.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ProviderRegistry.test.js","sourceRoot":"","sources":["../../src/agent/ProviderRegistry.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ProviderRegistry.test.js","sourceRoot":"","sources":["../../src/agent/ProviderRegistry.test.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,19 @@
1
1
  import { ProviderRegistry } from './ProviderRegistry.js';
2
+ /**
3
+ * Wraps a synchronous detector in a short-lived cache.
4
+ *
5
+ * `isConfigured()` and `getStatusMessage()` are separate calls on the same
6
+ * provider, so listing statuses ran every detector twice. CLI detectors walk
7
+ * PATH and may spawn a bounded provider-owned status command, so duplicate
8
+ * probes materially slow the request.
9
+ *
10
+ * A few seconds is the right window: long enough to collapse the duplicate calls
11
+ * within one request, short enough that installing a CLI or signing in is
12
+ * noticed almost immediately rather than needing a restart.
13
+ */
14
+ export type CachedStatusReader<T> = (() => T) & {
15
+ invalidate(): void;
16
+ };
17
+ export declare function cachedStatus<T>(detect: () => T, ttlMs?: number): CachedStatusReader<T>;
2
18
  export { ProviderRegistry };
3
19
  //# sourceMappingURL=adapters.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../../src/agent/adapters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAoDzD,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../../src/agent/adapters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAA0B,MAAM,uBAAuB,CAAC;AAiDjF;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,kBAAkB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG;IAAE,UAAU,IAAI,IAAI,CAAA;CAAE,CAAC;AAEvE,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,SAAQ,GAAG,kBAAkB,CAAC,CAAC,CAAC,CAuBrF;AAqGD,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -1,13 +1,18 @@
1
1
  import { ProviderRegistry } from './ProviderRegistry.js';
2
+ import { detectAntigravityCliStatus, detectClaudeCliStatus, detectCodexCliStatus, detectCopilotCliStatus, } from './cliAvailability.js';
2
3
  import { NativeClaudeAgent } from './NativeClaudeAgent.js';
3
4
  import { NativeAgent } from './NativeAgent.js';
4
5
  import { NativeGoogleAgent } from './NativeGoogleAgent.js';
5
6
  import { ClaudeCliAdapter } from './ClaudeCliAdapter.js';
6
7
  import { AntigravityCliAdapter } from './AntigravityCliAdapter.js';
8
+ import { CodexCliAdapter } from './CodexCliAdapter.js';
9
+ import { CopilotAcpAdapter } from './CopilotAcpAdapter.js';
7
10
  ProviderRegistry.register({
8
11
  id: 'claude-native',
9
12
  name: 'Claude',
10
13
  icon: 'Bot',
14
+ accessLabel: 'Read-only tools',
15
+ capabilities: { transport: 'native-api', sessionIdentity: 'none', workspaceAccess: 'read-only' },
11
16
  isConfigured: () => !!process.env.ANTHROPIC_API_KEY,
12
17
  getStatusMessage: () => process.env.ANTHROPIC_API_KEY ? undefined : 'Anthropic API key is not configured in ANTHROPIC_API_KEY.',
13
18
  createInstance: () => new NativeClaudeAgent()
@@ -16,6 +21,8 @@ ProviderRegistry.register({
16
21
  id: 'openai-native',
17
22
  name: 'OpenAI',
18
23
  icon: 'Sparkles',
24
+ accessLabel: 'Read-only tools',
25
+ capabilities: { transport: 'native-api', sessionIdentity: 'none', workspaceAccess: 'read-only' },
19
26
  isConfigured: () => !!process.env.OPENAI_API_KEY,
20
27
  getStatusMessage: () => process.env.OPENAI_API_KEY ? undefined : 'OpenAI API key is not configured in OPENAI_API_KEY.',
21
28
  createInstance: () => new NativeAgent()
@@ -24,25 +31,128 @@ ProviderRegistry.register({
24
31
  id: 'google-native',
25
32
  name: 'Google Gemini',
26
33
  icon: 'Sparkles',
34
+ accessLabel: 'Read-only tools',
35
+ capabilities: { transport: 'native-api', sessionIdentity: 'none', workspaceAccess: 'read-only' },
27
36
  isConfigured: () => !!process.env.GEMINI_API_KEY,
28
37
  getStatusMessage: () => process.env.GEMINI_API_KEY ? undefined : 'Google API key is not configured in GEMINI_API_KEY.',
29
38
  createInstance: () => new NativeGoogleAgent()
30
39
  });
40
+ export function cachedStatus(detect, ttlMs = 5_000) {
41
+ // Freshness is tracked with a flag, not by testing the value: keying on
42
+ // `value === undefined` would make a detector that legitimately returns
43
+ // undefined re-run on every read, which is the case this exists to avoid.
44
+ let cached = null;
45
+ let readAt = 0;
46
+ const read = (() => {
47
+ const now = Date.now();
48
+ if (!cached || now - readAt >= ttlMs) {
49
+ const value = detect();
50
+ // Age the cache from completion. A detector that consumes its whole
51
+ // timeout must still be reused by the other fields in this status read.
52
+ cached = { value };
53
+ readAt = Date.now();
54
+ }
55
+ return cached.value;
56
+ });
57
+ read.invalidate = () => {
58
+ cached = null;
59
+ readAt = 0;
60
+ };
61
+ return read;
62
+ }
63
+ function setupHelp(status) {
64
+ if (!status.setupIssue || !status.recoveryCommand || !status.recoveryLabel)
65
+ return undefined;
66
+ return {
67
+ setupIssue: status.setupIssue,
68
+ recoveryCommand: status.recoveryCommand,
69
+ recoveryLabel: status.recoveryLabel,
70
+ };
71
+ }
72
+ // The CLI providers need no API key, but "installed" is not the same as "usable":
73
+ // a CLI can be on PATH and still have no credentials a spawned process can use.
74
+ // Reporting that up front beats letting the first turn fail with whatever the CLI
75
+ // happened to print.
76
+ const claudeCliStatus = cachedStatus(() => detectClaudeCliStatus());
77
+ const antigravityCliStatus = cachedStatus(() => detectAntigravityCliStatus());
78
+ const codexCliStatus = cachedStatus(() => detectCodexCliStatus());
79
+ const copilotCliStatus = cachedStatus(() => detectCopilotCliStatus());
31
80
  ProviderRegistry.register({
32
81
  id: 'claude-cli',
33
82
  name: 'Claude Code (Local CLI)',
34
83
  icon: 'Terminal',
35
- isConfigured: () => true, // Assume the CLI is installed for now
36
- getStatusMessage: () => undefined, // No API key required!
84
+ accessLabel: 'Harness-managed access',
85
+ executionProfiles: [
86
+ { id: 'review', label: 'Review only', description: 'Reads and plans; no source edits.' },
87
+ {
88
+ id: 'workspace-write',
89
+ label: 'Edit workspace',
90
+ description: 'Auto-accepts in-workspace file edits and common filesystem actions; other approval-requiring commands are unavailable in embedded chat.',
91
+ },
92
+ ],
93
+ defaultExecutionProfile: 'review',
94
+ capabilities: {
95
+ transport: 'cli-print',
96
+ sessionIdentity: 'client-assigned',
97
+ workspaceAccess: 'harness-managed',
98
+ sessionIdFormat: 'uuid',
99
+ },
100
+ isConfigured: () => claudeCliStatus().usable,
101
+ getStatusMessage: () => claudeCliStatus().message,
102
+ getSetupHelp: () => setupHelp(claudeCliStatus()),
103
+ invalidateStatus: () => claudeCliStatus.invalidate(),
37
104
  createInstance: () => new ClaudeCliAdapter()
38
105
  });
39
106
  ProviderRegistry.register({
40
107
  id: 'antigravity-cli',
41
108
  name: 'Antigravity (Local CLI)',
42
109
  icon: 'Terminal',
43
- isConfigured: () => true, // Assume the CLI is installed for now
44
- getStatusMessage: () => undefined, // No API key required!
110
+ accessLabel: 'Harness-managed access',
111
+ capabilities: { transport: 'cli-print', sessionIdentity: 'none', workspaceAccess: 'harness-managed' },
112
+ isConfigured: () => antigravityCliStatus().usable,
113
+ getStatusMessage: () => antigravityCliStatus().message,
45
114
  createInstance: () => new AntigravityCliAdapter()
46
115
  });
116
+ ProviderRegistry.register({
117
+ id: 'codex-cli',
118
+ name: 'Codex (Local CLI)',
119
+ icon: 'Terminal',
120
+ accessLabel: 'Workspace write',
121
+ executionProfiles: [
122
+ { id: 'review', label: 'Review only', description: 'Read-only sandbox; escalation is denied.' },
123
+ {
124
+ id: 'workspace-write',
125
+ label: 'Edit workspace',
126
+ description: 'Workspace-write sandbox; command network and escalation outside the sandbox are denied.',
127
+ },
128
+ ],
129
+ defaultExecutionProfile: 'review',
130
+ capabilities: {
131
+ transport: 'cli-print',
132
+ sessionIdentity: 'provider-assigned',
133
+ workspaceAccess: 'workspace-write',
134
+ sessionIdFormat: 'uuid',
135
+ },
136
+ isConfigured: () => codexCliStatus().usable,
137
+ getStatusMessage: () => codexCliStatus().message,
138
+ getSetupHelp: () => setupHelp(codexCliStatus()),
139
+ invalidateStatus: () => codexCliStatus.invalidate(),
140
+ createInstance: () => new CodexCliAdapter()
141
+ });
142
+ ProviderRegistry.register({
143
+ id: 'copilot-cli',
144
+ name: 'GitHub Copilot (Local CLI)',
145
+ icon: 'Terminal',
146
+ accessLabel: 'Read-only workspace tools',
147
+ capabilities: {
148
+ transport: 'acp',
149
+ sessionIdentity: 'provider-assigned',
150
+ workspaceAccess: 'read-only',
151
+ sessionIdFormat: 'uuid',
152
+ },
153
+ isConfigured: () => copilotCliStatus().usable,
154
+ getStatusMessage: () => copilotCliStatus().message,
155
+ createInstance: () => new CopilotAcpAdapter()
156
+ });
47
157
  export { ProviderRegistry };
48
158
  //# sourceMappingURL=adapters.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"adapters.js","sourceRoot":"","sources":["../../src/agent/adapters.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,gBAAgB,CAAC,QAAQ,CAAC;IACxB,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,KAAK;IACX,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB;IACnD,gBAAgB,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,2DAA2D;IAC/H,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,iBAAiB,EAAE;CAC9C,CAAC,CAAC;AAEH,gBAAgB,CAAC,QAAQ,CAAC;IACxB,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,UAAU;IAChB,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc;IAChD,gBAAgB,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,qDAAqD;IACtH,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,WAAW,EAAE;CACxC,CAAC,CAAC;AAEH,gBAAgB,CAAC,QAAQ,CAAC;IACxB,EAAE,EAAE,eAAe;IACnB,IAAI,EAAE,eAAe;IACrB,IAAI,EAAE,UAAU;IAChB,YAAY,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc;IAChD,gBAAgB,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,qDAAqD;IACtH,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,iBAAiB,EAAE;CAC9C,CAAC,CAAC;AAEH,gBAAgB,CAAC,QAAQ,CAAC;IACxB,EAAE,EAAE,YAAY;IAChB,IAAI,EAAE,yBAAyB;IAC/B,IAAI,EAAE,UAAU;IAChB,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,sCAAsC;IAChE,gBAAgB,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,uBAAuB;IAC1D,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,gBAAgB,EAAE;CAC7C,CAAC,CAAC;AAEH,gBAAgB,CAAC,QAAQ,CAAC;IACxB,EAAE,EAAE,iBAAiB;IACrB,IAAI,EAAE,yBAAyB;IAC/B,IAAI,EAAE,UAAU;IAChB,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,EAAE,sCAAsC;IAChE,gBAAgB,EAAE,GAAG,EAAE,CAAC,SAAS,EAAE,uBAAuB;IAC1D,cAAc,EAAE,GAAG,EAAE,CAAC,IAAI,qBAAqB,EAAE;CAClD,CAAC,CAAC;AAEH,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
1
+ {"version":3,"file":"adapters.js","sourceRoot":"","sources":["../../src/agent/adapters.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=adapters.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.test.d.ts","sourceRoot":"","sources":["../../src/agent/adapters.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,71 @@
1
+ import { describe, it, expect, vi, afterEach } from 'vitest';
2
+ import { cachedStatus } from './adapters.js';
3
+ describe('cachedStatus', () => {
4
+ afterEach(() => {
5
+ vi.useRealTimers();
6
+ });
7
+ it('detects once for repeated reads inside the window', () => {
8
+ // isConfigured() and getStatusMessage() are separate calls on the same
9
+ // provider, so listing statuses ran every detector twice — and each walks
10
+ // PATH with a statSync per directory per PATHEXT entry, then reads a
11
+ // credentials file.
12
+ const detect = vi.fn(() => ({ usable: true }));
13
+ const read = cachedStatus(detect);
14
+ read();
15
+ read();
16
+ read();
17
+ expect(detect).toHaveBeenCalledTimes(1);
18
+ });
19
+ it('returns the same value each time it is cached', () => {
20
+ const detect = vi.fn(() => ({ usable: false, message: 'not signed in' }));
21
+ const read = cachedStatus(detect);
22
+ expect(read()).toEqual({ usable: false, message: 'not signed in' });
23
+ expect(read()).toEqual({ usable: false, message: 'not signed in' });
24
+ });
25
+ it('re-detects once the window has passed, so an install is noticed', () => {
26
+ // A permanent cache would need a restart to see a newly installed CLI.
27
+ vi.useFakeTimers();
28
+ const detect = vi.fn(() => ({ usable: false }));
29
+ const read = cachedStatus(detect, 5_000);
30
+ read();
31
+ vi.advanceTimersByTime(4_999);
32
+ read();
33
+ expect(detect).toHaveBeenCalledTimes(1);
34
+ vi.advanceTimersByTime(1);
35
+ read();
36
+ expect(detect).toHaveBeenCalledTimes(2);
37
+ });
38
+ it('caches an undefined result too', () => {
39
+ // Freshness is a flag, not a test of the value: keying on
40
+ // `value === undefined` would make a detector that legitimately returns
41
+ // undefined re-run on every read, defeating the whole point.
42
+ const detect = vi.fn(() => undefined);
43
+ const read = cachedStatus(detect);
44
+ read();
45
+ read();
46
+ expect(detect).toHaveBeenCalledTimes(1);
47
+ });
48
+ it('re-detects immediately after an explicit invalidation', () => {
49
+ const detect = vi.fn()
50
+ .mockReturnValueOnce({ usable: false })
51
+ .mockReturnValueOnce({ usable: true });
52
+ const read = cachedStatus(detect);
53
+ expect(read()).toEqual({ usable: false });
54
+ read.invalidate();
55
+ expect(read()).toEqual({ usable: true });
56
+ expect(detect).toHaveBeenCalledTimes(2);
57
+ });
58
+ it('ages the cache from completion of a slow detector', () => {
59
+ vi.useFakeTimers();
60
+ const detect = vi.fn(() => {
61
+ vi.advanceTimersByTime(5_000);
62
+ return { usable: false };
63
+ });
64
+ const read = cachedStatus(detect, 5_000);
65
+ read();
66
+ read();
67
+ read();
68
+ expect(detect).toHaveBeenCalledTimes(1);
69
+ });
70
+ });
71
+ //# sourceMappingURL=adapters.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapters.test.js","sourceRoot":"","sources":["../../src/agent/adapters.test.ts"],"names":[],"mappings":"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"}