@peakflo/agent-harness 0.0.0-stage → 0.2.1-rc.3

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 (85) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +38 -2
  3. package/dist/adapters/acp-adapter.d.ts +177 -0
  4. package/dist/adapters/acp-adapter.js +1732 -0
  5. package/dist/adapters/claude-code-adapter.d.ts +171 -0
  6. package/dist/adapters/claude-code-adapter.js +1918 -0
  7. package/dist/adapters/codex-adapter.d.ts +67 -0
  8. package/dist/adapters/codex-adapter.js +681 -0
  9. package/dist/adapters/codex-app-server-adapter.d.ts +105 -0
  10. package/dist/adapters/codex-app-server-adapter.js +1309 -0
  11. package/dist/adapters/coding-agent-adapter.d.ts +289 -0
  12. package/dist/adapters/coding-agent-adapter.js +31 -0
  13. package/dist/adapters/index.d.ts +17 -0
  14. package/dist/adapters/index.js +35 -0
  15. package/dist/adapters/model-gateway.d.ts +84 -0
  16. package/dist/adapters/model-gateway.js +270 -0
  17. package/dist/adapters/opencode-adapter.d.ts +403 -0
  18. package/dist/adapters/opencode-adapter.js +2710 -0
  19. package/dist/adapters/opencode-config.d.ts +41 -0
  20. package/dist/adapters/opencode-config.js +147 -0
  21. package/dist/adapters/opencode-server-policy.d.ts +82 -0
  22. package/dist/adapters/opencode-server-policy.js +148 -0
  23. package/dist/adapters/pi-adapter.d.ts +168 -0
  24. package/dist/adapters/pi-adapter.js +1468 -0
  25. package/dist/capabilities.d.ts +58 -0
  26. package/dist/capabilities.js +161 -0
  27. package/dist/cli.d.ts +2 -0
  28. package/dist/cli.js +231 -0
  29. package/dist/contract.d.ts +273 -0
  30. package/dist/contract.js +357 -0
  31. package/dist/control-plane.d.ts +178 -0
  32. package/dist/control-plane.js +431 -0
  33. package/dist/credential-store.d.ts +110 -0
  34. package/dist/credential-store.js +181 -0
  35. package/dist/enrol/browser-enrol.d.ts +85 -0
  36. package/dist/enrol/browser-enrol.js +387 -0
  37. package/dist/github-command-guards.d.ts +20 -0
  38. package/dist/github-command-guards.js +330 -0
  39. package/dist/github-proxy-certificates.d.ts +25 -0
  40. package/dist/github-proxy-certificates.js +145 -0
  41. package/dist/github-proxy.d.ts +37 -0
  42. package/dist/github-proxy.js +476 -0
  43. package/dist/github-workspace.d.ts +55 -0
  44. package/dist/github-workspace.js +537 -0
  45. package/dist/harness.d.ts +333 -0
  46. package/dist/harness.js +1414 -0
  47. package/dist/health.d.ts +45 -0
  48. package/dist/health.js +116 -0
  49. package/dist/index.d.ts +53 -0
  50. package/dist/index.js +123 -0
  51. package/dist/model-probe.d.ts +96 -0
  52. package/dist/model-probe.js +195 -0
  53. package/dist/options.d.ts +15 -0
  54. package/dist/options.js +212 -0
  55. package/dist/ports-default.d.ts +212 -0
  56. package/dist/ports-default.js +333 -0
  57. package/dist/ports.d.ts +436 -0
  58. package/dist/ports.js +27 -0
  59. package/dist/runtime/attachments.d.ts +92 -0
  60. package/dist/runtime/attachments.js +377 -0
  61. package/dist/runtime/child-stream-guards.d.ts +45 -0
  62. package/dist/runtime/child-stream-guards.js +111 -0
  63. package/dist/runtime/conversation.d.ts +87 -0
  64. package/dist/runtime/conversation.js +156 -0
  65. package/dist/runtime/lease-renewal.d.ts +169 -0
  66. package/dist/runtime/lease-renewal.js +433 -0
  67. package/dist/runtime/mcp-auth-proxy.d.ts +82 -0
  68. package/dist/runtime/mcp-auth-proxy.js +300 -0
  69. package/dist/runtime/permission-mode.d.ts +116 -0
  70. package/dist/runtime/permission-mode.js +146 -0
  71. package/dist/runtime/projection.d.ts +71 -0
  72. package/dist/runtime/projection.js +211 -0
  73. package/dist/runtime/session-runner.d.ts +520 -0
  74. package/dist/runtime/session-runner.js +2122 -0
  75. package/dist/shared/reasoning-effort.d.ts +11 -0
  76. package/dist/shared/reasoning-effort.js +20 -0
  77. package/dist/store/conversation-store.d.ts +100 -0
  78. package/dist/store/conversation-store.js +305 -0
  79. package/dist/store/sqlite-store.d.ts +120 -0
  80. package/dist/store/sqlite-store.js +346 -0
  81. package/dist/types.d.ts +952 -0
  82. package/dist/types.js +55 -0
  83. package/dist/version.d.ts +32 -0
  84. package/dist/version.js +77 -0
  85. package/package.json +53 -4
@@ -0,0 +1,289 @@
1
+ /**
2
+ * Adapter interface for coding agent backends.
3
+ * Defines common operations that all coding agent implementations must support.
4
+ */
5
+ /**
6
+ * Extracted verbatim from 20x `src/main/adapters/coding-agent-adapter.ts`.
7
+ * CHANGED: imports only — `../../shared/reasoning-effort` ->
8
+ * `../shared/reasoning-effort`. Source formatting (no semicolons) preserved.
9
+ */
10
+ import type { ReasoningEffort } from '../shared/reasoning-effort';
11
+ export declare enum SessionStatusType {
12
+ IDLE = "idle",
13
+ BUSY = "busy",
14
+ RETRY = "retry",
15
+ ERROR = "error",
16
+ WAITING_APPROVAL = "waiting_approval"
17
+ }
18
+ export declare enum MessageRole {
19
+ USER = "user",
20
+ ASSISTANT = "assistant",
21
+ SYSTEM = "system"
22
+ }
23
+ export declare enum MessagePartType {
24
+ TEXT = "text",
25
+ REASONING = "reasoning",
26
+ TOOL = "tool",
27
+ QUESTION = "question",
28
+ IMAGE = "image",
29
+ ERROR = "error",
30
+ TASK_PROGRESS = "task_progress"
31
+ }
32
+ export interface McpServerConfig {
33
+ name?: string;
34
+ type: 'stdio' | 'http' | 'sse';
35
+ command?: string;
36
+ args?: string[];
37
+ env?: Record<string, string>;
38
+ url?: string;
39
+ headers?: Record<string, string>;
40
+ }
41
+ export interface SessionConfig {
42
+ agentId: string;
43
+ taskId: string;
44
+ workspaceDir: string;
45
+ serverUrl?: string;
46
+ model?: string;
47
+ reasoningEffort?: ReasoningEffort;
48
+ systemPrompt?: string;
49
+ tools?: Record<string, boolean>;
50
+ promptAbort?: AbortController;
51
+ mcpServers?: Record<string, McpServerConfig>;
52
+ /** Claude Code auth method: 'subscription' (OAuth/Pro/Max) or 'api_key' (pay-per-use). Defaults to 'subscription'. */
53
+ authMethod?: 'subscription' | 'api_key';
54
+ permissionMode?: 'ask' | 'allow';
55
+ sandboxMode?: 'read-only' | 'workspace-write' | 'danger-full-access';
56
+ apiKeys?: {
57
+ openai?: string;
58
+ anthropic?: string;
59
+ cursor?: string;
60
+ };
61
+ /** Port of the local secret broker HTTP server */
62
+ secretBrokerPort?: number;
63
+ /** Per-session token for authenticating with the secret broker */
64
+ secretSessionToken?: string;
65
+ /** Absolute path to the secret-shell.sh wrapper script */
66
+ secretShellPath?: string;
67
+ /** Decrypted secret env vars to inject directly into the agent process env.
68
+ * Used when the agent runtime doesn't respect $SHELL (e.g. Claude Code). */
69
+ secretEnvVars?: Record<string, string>;
70
+ /** Non-secret values exported into the backend process for this turn. */
71
+ environment?: Record<string, string>;
72
+ /** Published skills made available to this session. */
73
+ skills?: Array<{
74
+ name: string;
75
+ content: string;
76
+ }>;
77
+ /** Whether the OpenCode tillDone runtime plugin should enforce todo completion for this session. */
78
+ tillDone?: boolean;
79
+ }
80
+ export interface SessionStatus {
81
+ type: SessionStatusType;
82
+ message?: string;
83
+ }
84
+ export interface SessionMessage {
85
+ id: string;
86
+ role: MessageRole;
87
+ parts: MessagePart[];
88
+ }
89
+ export interface MessagePart {
90
+ id?: string;
91
+ type: MessagePartType;
92
+ text?: string;
93
+ content?: string;
94
+ role?: 'user' | 'assistant' | 'system';
95
+ tool?: {
96
+ name: string;
97
+ status?: string;
98
+ title?: string;
99
+ description?: string;
100
+ input?: unknown;
101
+ output?: unknown;
102
+ error?: string;
103
+ requestId?: string;
104
+ questions?: unknown;
105
+ todos?: unknown;
106
+ };
107
+ state?: {
108
+ status?: string;
109
+ title?: string;
110
+ input?: unknown;
111
+ output?: unknown;
112
+ error?: string;
113
+ };
114
+ update?: boolean;
115
+ realSessionId?: string;
116
+ receivedAt?: number;
117
+ taskProgress?: {
118
+ taskId: string;
119
+ status: 'started' | 'running' | 'completed' | 'failed' | 'stopped';
120
+ description: string;
121
+ lastToolName?: string;
122
+ summary?: string;
123
+ usage?: {
124
+ total_tokens: number;
125
+ tool_uses: number;
126
+ duration_ms: number;
127
+ };
128
+ };
129
+ }
130
+ export interface MessagePayload {
131
+ content: string;
132
+ partType: string;
133
+ tool?: {
134
+ name: string;
135
+ status?: string;
136
+ title?: string;
137
+ description?: string;
138
+ input?: unknown;
139
+ output?: unknown;
140
+ error?: string;
141
+ };
142
+ }
143
+ /**
144
+ * Common interface for all coding agent backends (OpenCode, Claude Code, etc.)
145
+ */
146
+ export interface CodingAgentAdapter {
147
+ /**
148
+ * Initialize the adapter (e.g., load SDK, validate config)
149
+ */
150
+ initialize(): Promise<void>;
151
+ /**
152
+ * Create a new coding session
153
+ * @returns OpenCode/Claude session ID
154
+ */
155
+ createSession(config: SessionConfig): Promise<string>;
156
+ /**
157
+ * Resume an existing session from a persisted session ID
158
+ * @returns Session messages for replay
159
+ */
160
+ resumeSession(sessionId: string, config: SessionConfig): Promise<SessionMessage[]>;
161
+ /**
162
+ * Send a prompt/message to the session
163
+ */
164
+ sendPrompt(sessionId: string, parts: MessagePart[], config: SessionConfig): Promise<void>;
165
+ /**
166
+ * Deliver a message to a turn that is ALREADY RUNNING, without starting a
167
+ * new one — used for the soft "you have N minutes left" warning near the
168
+ * LONG TURNS hard ceiling.
169
+ *
170
+ * OPTIONAL AND BEST-EFFORT. Not every backend can safely take a second
171
+ * message while one is in flight — a backend whose `sendPrompt` is a single
172
+ * long-lived call per session (OpenCode) would collide with itself. Return
173
+ * `true` when the message reached the running turn, `false` when it could
174
+ * not (the caller still has the transcript note either way).
175
+ */
176
+ steerTurn?(sessionId: string, text: string, config: SessionConfig): Promise<boolean>;
177
+ /**
178
+ * Get current session status
179
+ */
180
+ getStatus(sessionId: string, config: SessionConfig): Promise<SessionStatus>;
181
+ /**
182
+ * Get new messages since last poll
183
+ * @param seenMessageIds Set of message IDs already processed
184
+ * @param seenPartIds Set of part IDs already processed
185
+ * @returns New message parts
186
+ */
187
+ pollMessages(sessionId: string, seenMessageIds: Set<string>, seenPartIds: Set<string>, partContentLengths: Map<string, string>, config: SessionConfig): Promise<MessagePart[]>;
188
+ /**
189
+ * Get all session messages in a standardized format
190
+ * Used for extracting output fields and other post-processing
191
+ * @returns All messages from the session
192
+ */
193
+ getAllMessages?(sessionId: string, config: SessionConfig): Promise<SessionMessage[]>;
194
+ /**
195
+ * Read the session's PERSISTED history from durable storage (e.g. the CLI's
196
+ * on-disk session file) WITHOUT requiring a live/in-memory session or spawning
197
+ * the agent. Used to backfill the durable transcript projection once for
198
+ * sessions that predate write-through. Parts should carry `receivedAt` (real
199
+ * event time) so the projection stores true timestamps.
200
+ * @returns Persisted messages, or [] when unavailable.
201
+ */
202
+ getPersistedMessages?(sessionId: string, config: SessionConfig): Promise<SessionMessage[]>;
203
+ /**
204
+ * Abort ongoing prompt
205
+ */
206
+ abortPrompt(sessionId: string, config: SessionConfig): Promise<void>;
207
+ /**
208
+ * Get tools currently in "running" state.
209
+ * Used by the stuck-tool detector to abort tools that hang without producing
210
+ * data (e.g. cross-workspace file reads that the server silently blocks).
211
+ * Optional — returns empty array if the adapter doesn't support it.
212
+ */
213
+ getRunningTools?(sessionId: string, config: SessionConfig): Promise<Array<{
214
+ partId: string;
215
+ toolName: string;
216
+ startTime?: number;
217
+ input?: Record<string, unknown>;
218
+ }>>;
219
+ /**
220
+ * Destroy/cleanup session
221
+ */
222
+ destroySession(sessionId: string, config: SessionConfig): Promise<void>;
223
+ /**
224
+ * Register an MCP server with the adapter
225
+ */
226
+ registerMcpServer(serverName: string, mcpConfig: {
227
+ type: 'local' | 'remote';
228
+ command?: string[];
229
+ args?: string[];
230
+ url?: string;
231
+ headers?: Record<string, string>;
232
+ environment?: Record<string, string>;
233
+ }, workspaceDir?: string): Promise<void>;
234
+ /**
235
+ * Respond to a pending question (AskUserQuestion tool call).
236
+ * Agent-manager passes structured answers; each adapter delivers them
237
+ * in whatever format its backend expects.
238
+ *
239
+ * @param answers Map of question header/label → selected answer text
240
+ */
241
+ respondToQuestion?(sessionId: string, answers: Record<string, string>, config: SessionConfig, requestId?: string): Promise<boolean | void | {
242
+ handled: boolean;
243
+ resolutionPart?: MessagePart;
244
+ }>;
245
+ /**
246
+ * List available providers and their models from the backend.
247
+ * Returns null if the backend doesn't support provider listing.
248
+ */
249
+ getProviders?(serverUrl?: string, directory?: string): Promise<{
250
+ providers: {
251
+ id: string;
252
+ name: string;
253
+ models: unknown;
254
+ [key: string]: unknown;
255
+ }[];
256
+ default: Record<string, string>;
257
+ } | null>;
258
+ /**
259
+ * Notify the adapter that provider/auth config has changed (e.g. user edited
260
+ * agent settings, AI gateway key was rotated). Adapters that manage a shared
261
+ * backend server (like OpenCode) should push the updated config.
262
+ *
263
+ * Only call this on actual config changes — NOT on every session creation,
264
+ * as some backends (OpenCode) tear down all running sessions on config update.
265
+ */
266
+ notifyConfigChanged?(): Promise<void>;
267
+ /**
268
+ * Check if this adapter's backend is available and healthy
269
+ */
270
+ checkHealth(): Promise<{
271
+ available: boolean;
272
+ reason?: string;
273
+ }>;
274
+ /**
275
+ * Optional callback invoked by the adapter when new data is buffered and
276
+ * ready for consumption. The polling coordinator uses this to trigger an
277
+ * immediate poll cycle instead of waiting for the next 2-second heartbeat,
278
+ * which dramatically reduces perceived latency during active streaming.
279
+ *
280
+ * Set by agent-manager when the session is registered for polling.
281
+ *
282
+ * Lifecycle contract: an IDLE status ends only the current turn. It must not
283
+ * close the adapter session or disable this callback. Push transports and
284
+ * subscriptions must stay open until destroySession() or an explicit abort
285
+ * closes them. This lets late harness events wake an idle session without a
286
+ * continuous polling loop.
287
+ */
288
+ onDataAvailable?: (sessionId: string) => void;
289
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ /**
3
+ * Adapter interface for coding agent backends.
4
+ * Defines common operations that all coding agent implementations must support.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.MessagePartType = exports.MessageRole = exports.SessionStatusType = void 0;
8
+ var SessionStatusType;
9
+ (function (SessionStatusType) {
10
+ SessionStatusType["IDLE"] = "idle";
11
+ SessionStatusType["BUSY"] = "busy";
12
+ SessionStatusType["RETRY"] = "retry";
13
+ SessionStatusType["ERROR"] = "error";
14
+ SessionStatusType["WAITING_APPROVAL"] = "waiting_approval";
15
+ })(SessionStatusType || (exports.SessionStatusType = SessionStatusType = {}));
16
+ var MessageRole;
17
+ (function (MessageRole) {
18
+ MessageRole["USER"] = "user";
19
+ MessageRole["ASSISTANT"] = "assistant";
20
+ MessageRole["SYSTEM"] = "system";
21
+ })(MessageRole || (exports.MessageRole = MessageRole = {}));
22
+ var MessagePartType;
23
+ (function (MessagePartType) {
24
+ MessagePartType["TEXT"] = "text";
25
+ MessagePartType["REASONING"] = "reasoning";
26
+ MessagePartType["TOOL"] = "tool";
27
+ MessagePartType["QUESTION"] = "question";
28
+ MessagePartType["IMAGE"] = "image";
29
+ MessagePartType["ERROR"] = "error";
30
+ MessagePartType["TASK_PROGRESS"] = "task_progress";
31
+ })(MessagePartType || (exports.MessagePartType = MessagePartType = {}));
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Public surface of the coding-agent adapters extracted from the 20x Electron
3
+ * app (`src/main/adapters/`). This barrel is new — it does not exist in 20x,
4
+ * where each adapter is imported by path.
5
+ */
6
+ export { SessionStatusType, MessageRole, MessagePartType } from './coding-agent-adapter';
7
+ export type { CodingAgentAdapter, McpServerConfig, SessionConfig, SessionStatus, SessionMessage, MessagePart, MessagePayload } from './coding-agent-adapter';
8
+ export { OpencodeAdapter } from './opencode-adapter';
9
+ export { PiAdapter } from './pi-adapter';
10
+ export { createOpencodeServerPolicy, backendInstanceId, ephemeralLoopbackPort, SHARED_SERVER_URL, type OpencodeServerPolicy } from './opencode-server-policy';
11
+ export { ClaudeCodeAdapter } from './claude-code-adapter';
12
+ export { CodexAdapter, DEFAULT_CODEX_MODEL } from './codex-adapter';
13
+ export { CodexAppServerAdapter } from './codex-app-server-adapter';
14
+ export { AcpAdapter } from './acp-adapter';
15
+ export type { AcpAgentType } from './acp-adapter';
16
+ export { ENTERPRISE_AI_GATEWAY_PROVIDER_ID, ENTERPRISE_AI_GATEWAY_PROVIDER_NAME, buildEnterpriseAiGatewayProviderConfig, buildPiAiGatewayProviderConfig } from './model-gateway';
17
+ export type { ModelGatewayConfig, ModelGatewayConfigSource, ModelGatewayModel } from './model-gateway';
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ /**
3
+ * Public surface of the coding-agent adapters extracted from the 20x Electron
4
+ * app (`src/main/adapters/`). This barrel is new — it does not exist in 20x,
5
+ * where each adapter is imported by path.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.buildPiAiGatewayProviderConfig = exports.buildEnterpriseAiGatewayProviderConfig = exports.ENTERPRISE_AI_GATEWAY_PROVIDER_NAME = exports.ENTERPRISE_AI_GATEWAY_PROVIDER_ID = exports.AcpAdapter = exports.CodexAppServerAdapter = exports.DEFAULT_CODEX_MODEL = exports.CodexAdapter = exports.ClaudeCodeAdapter = exports.SHARED_SERVER_URL = exports.ephemeralLoopbackPort = exports.backendInstanceId = exports.createOpencodeServerPolicy = exports.PiAdapter = exports.OpencodeAdapter = exports.MessagePartType = exports.MessageRole = exports.SessionStatusType = void 0;
9
+ var coding_agent_adapter_1 = require("./coding-agent-adapter");
10
+ Object.defineProperty(exports, "SessionStatusType", { enumerable: true, get: function () { return coding_agent_adapter_1.SessionStatusType; } });
11
+ Object.defineProperty(exports, "MessageRole", { enumerable: true, get: function () { return coding_agent_adapter_1.MessageRole; } });
12
+ Object.defineProperty(exports, "MessagePartType", { enumerable: true, get: function () { return coding_agent_adapter_1.MessagePartType; } });
13
+ var opencode_adapter_1 = require("./opencode-adapter");
14
+ Object.defineProperty(exports, "OpencodeAdapter", { enumerable: true, get: function () { return opencode_adapter_1.OpencodeAdapter; } });
15
+ var pi_adapter_1 = require("./pi-adapter");
16
+ Object.defineProperty(exports, "PiAdapter", { enumerable: true, get: function () { return pi_adapter_1.PiAdapter; } });
17
+ var opencode_server_policy_1 = require("./opencode-server-policy");
18
+ Object.defineProperty(exports, "createOpencodeServerPolicy", { enumerable: true, get: function () { return opencode_server_policy_1.createOpencodeServerPolicy; } });
19
+ Object.defineProperty(exports, "backendInstanceId", { enumerable: true, get: function () { return opencode_server_policy_1.backendInstanceId; } });
20
+ Object.defineProperty(exports, "ephemeralLoopbackPort", { enumerable: true, get: function () { return opencode_server_policy_1.ephemeralLoopbackPort; } });
21
+ Object.defineProperty(exports, "SHARED_SERVER_URL", { enumerable: true, get: function () { return opencode_server_policy_1.SHARED_SERVER_URL; } });
22
+ var claude_code_adapter_1 = require("./claude-code-adapter");
23
+ Object.defineProperty(exports, "ClaudeCodeAdapter", { enumerable: true, get: function () { return claude_code_adapter_1.ClaudeCodeAdapter; } });
24
+ var codex_adapter_1 = require("./codex-adapter");
25
+ Object.defineProperty(exports, "CodexAdapter", { enumerable: true, get: function () { return codex_adapter_1.CodexAdapter; } });
26
+ Object.defineProperty(exports, "DEFAULT_CODEX_MODEL", { enumerable: true, get: function () { return codex_adapter_1.DEFAULT_CODEX_MODEL; } });
27
+ var codex_app_server_adapter_1 = require("./codex-app-server-adapter");
28
+ Object.defineProperty(exports, "CodexAppServerAdapter", { enumerable: true, get: function () { return codex_app_server_adapter_1.CodexAppServerAdapter; } });
29
+ var acp_adapter_1 = require("./acp-adapter");
30
+ Object.defineProperty(exports, "AcpAdapter", { enumerable: true, get: function () { return acp_adapter_1.AcpAdapter; } });
31
+ var model_gateway_1 = require("./model-gateway");
32
+ Object.defineProperty(exports, "ENTERPRISE_AI_GATEWAY_PROVIDER_ID", { enumerable: true, get: function () { return model_gateway_1.ENTERPRISE_AI_GATEWAY_PROVIDER_ID; } });
33
+ Object.defineProperty(exports, "ENTERPRISE_AI_GATEWAY_PROVIDER_NAME", { enumerable: true, get: function () { return model_gateway_1.ENTERPRISE_AI_GATEWAY_PROVIDER_NAME; } });
34
+ Object.defineProperty(exports, "buildEnterpriseAiGatewayProviderConfig", { enumerable: true, get: function () { return model_gateway_1.buildEnterpriseAiGatewayProviderConfig; } });
35
+ Object.defineProperty(exports, "buildPiAiGatewayProviderConfig", { enumerable: true, get: function () { return model_gateway_1.buildPiAiGatewayProviderConfig; } });
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Model-gateway seam for the extracted coding-agent adapters.
3
+ *
4
+ * In the 20x Electron app the adapters read the enterprise AI gateway
5
+ * credentials directly from SQLite via `src/main/enterprise-ai-gateway.ts`.
6
+ * That module cannot be extracted because it depends on Electron's
7
+ * `safeStorage` for encrypt/decrypt. The harness therefore takes the already
8
+ * decrypted config through an injected `ModelGatewayConfigSource` instead.
9
+ *
10
+ * `ENTERPRISE_AI_GATEWAY_PROVIDER_ID`, `ENTERPRISE_AI_GATEWAY_PROVIDER_NAME`
11
+ * and `buildEnterpriseAiGatewayProviderConfig` are copied verbatim (behaviour
12
+ * identical) from 20x `src/main/enterprise-ai-gateway.ts`; only the formatting
13
+ * follows this package's Prettier config.
14
+ */
15
+ export declare const ENTERPRISE_AI_GATEWAY_PROVIDER_ID = "peakflo";
16
+ export declare const ENTERPRISE_AI_GATEWAY_PROVIDER_NAME = "Peakflo";
17
+ /** Real per-model limits from the gateway. Absent when it did not report them. */
18
+ export interface ModelGatewayLimit {
19
+ context: number;
20
+ output: number;
21
+ }
22
+ export interface ModelGatewayModel {
23
+ id: string;
24
+ name: string;
25
+ limit?: ModelGatewayLimit;
26
+ }
27
+ /**
28
+ * The decrypted enterprise AI gateway config. Structurally identical to
29
+ * `StoredEnterpriseAiGatewayConfig` in 20x.
30
+ */
31
+ export interface ModelGatewayConfig {
32
+ apiKey: string;
33
+ baseUrl: string;
34
+ keyName?: string | null;
35
+ expiresAt?: string | null;
36
+ models?: ModelGatewayModel[];
37
+ }
38
+ /**
39
+ * Injected replacement for `readEnterpriseAiGatewayConfig(db)`.
40
+ * Returns `null` when no gateway is configured, exactly like the original.
41
+ */
42
+ export interface ModelGatewayConfigSource {
43
+ readModelGatewayConfig(): ModelGatewayConfig | null;
44
+ }
45
+ export declare function buildEnterpriseAiGatewayProviderConfig(stored: ModelGatewayConfig): Record<string, unknown>;
46
+ /** Build the provider entry Pi stores under `providers.peakflo`. */
47
+ export declare function buildPiAiGatewayProviderConfig(stored: ModelGatewayConfig): Record<string, unknown>;
48
+ /**
49
+ * The gateway config for the turn that is running right now.
50
+ *
51
+ * Created ONCE and re-pointed per turn, exactly like `SessionTokenInjector`
52
+ * and for the same reason: the adapter is constructed once and holds this
53
+ * reference for the whole process life, so swapping the object would leave it
54
+ * reading a credential from a session that has already ended.
55
+ *
56
+ * `readModelGatewayConfig()` returns `null` when no turn is live, which is the
57
+ * same answer `readEnterpriseAiGatewayConfig(db)` gives in 20x when no gateway
58
+ * is configured. Null means "no gateway provider" — it does NOT mean "fall
59
+ * back to whatever credentials happen to be on this machine".
60
+ */
61
+ export declare class SessionModelGateway implements ModelGatewayConfigSource {
62
+ private config;
63
+ readModelGatewayConfig(): ModelGatewayConfig | null;
64
+ /** Install the gateway for the turn about to run. */
65
+ set(config: ModelGatewayConfig | null): void;
66
+ /**
67
+ * Swap in a re-minted credential without disturbing `baseUrl`/`models` — the
68
+ * LONG TURNS fix's answer to a fixed per-turn LiteLLM key TTL. A no-op when
69
+ * no turn is live (the config was already revoked or never set), which is
70
+ * the correct outcome for a refresh that raced the turn's own end.
71
+ */
72
+ updateApiKey(apiKey: string): void;
73
+ /** Drop the credential the moment the turn ends. */
74
+ revoke(): void;
75
+ }
76
+ /** Exported for tests, which must not inherit another test's catalogue. */
77
+ export declare function __clearGatewayModelCacheForTest(): void;
78
+ export declare function fetchGatewayModels(params: {
79
+ baseUrl: string;
80
+ apiKey: string;
81
+ timeoutMs?: number;
82
+ /** Bypass the cache. Used by a deliberate refresh, never by a turn. */
83
+ force?: boolean;
84
+ }): Promise<ModelGatewayModel[]>;