@gajae-code/coding-agent 0.5.1 → 0.5.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.
- package/CHANGELOG.md +31 -0
- package/README.md +1 -1
- package/dist/types/async/job-manager.d.ts +6 -0
- package/dist/types/cli/setup-cli.d.ts +8 -1
- package/dist/types/commands/setup.d.ts +7 -0
- package/dist/types/config/file-lock.d.ts +24 -2
- package/dist/types/config/model-registry.d.ts +4 -0
- package/dist/types/config/models-config-schema.d.ts +5 -0
- package/dist/types/config/settings-schema.d.ts +62 -0
- package/dist/types/dap/client.d.ts +2 -1
- package/dist/types/edit/read-file.d.ts +6 -0
- package/dist/types/eval/js/context-manager.d.ts +3 -0
- package/dist/types/eval/js/executor.d.ts +1 -0
- package/dist/types/exec/bash-executor.d.ts +2 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +64 -2
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +7 -1
- package/dist/types/gjc-runtime/ultragoal-guard.d.ts +10 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +29 -0
- package/dist/types/lsp/types.d.ts +2 -0
- package/dist/types/modes/bridge/bridge-mode.d.ts +1 -0
- package/dist/types/modes/components/model-selector.d.ts +2 -0
- package/dist/types/modes/components/oauth-selector.d.ts +1 -0
- package/dist/types/modes/components/provider-onboarding-selector.d.ts +1 -1
- package/dist/types/modes/components/runtime-mcp-add-wizard.d.ts +1 -0
- package/dist/types/modes/components/tool-execution.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -1
- package/dist/types/modes/rpc/rpc-mode.d.ts +56 -1
- package/dist/types/modes/shared/agent-wire/unattended-session.d.ts +10 -0
- package/dist/types/modes/theme/defaults/index.d.ts +302 -0
- package/dist/types/modes/theme/theme.d.ts +1 -0
- package/dist/types/modes/types.d.ts +1 -1
- package/dist/types/runtime/process-lifecycle.d.ts +108 -0
- package/dist/types/runtime-mcp/transports/stdio.d.ts +1 -0
- package/dist/types/runtime-mcp/types.d.ts +2 -0
- package/dist/types/session/agent-session.d.ts +17 -1
- package/dist/types/session/artifacts.d.ts +4 -1
- package/dist/types/session/history-storage.d.ts +2 -2
- package/dist/types/session/session-manager.d.ts +10 -1
- package/dist/types/session/streaming-output.d.ts +5 -0
- package/dist/types/setup/credential-import.d.ts +79 -0
- package/dist/types/slash-commands/helpers/fast-status-report.d.ts +76 -0
- package/dist/types/task/executor.d.ts +1 -0
- package/dist/types/task/render.d.ts +1 -1
- package/dist/types/tools/bash.d.ts +1 -0
- package/dist/types/tools/browser/tab-supervisor.d.ts +9 -0
- package/dist/types/tools/sqlite-reader.d.ts +2 -1
- package/dist/types/tools/subagent-render.d.ts +7 -1
- package/dist/types/tools/subagent.d.ts +21 -0
- package/dist/types/tools/ultragoal-ask-guard.d.ts +5 -0
- package/dist/types/web/search/index.d.ts +4 -4
- package/dist/types/web/search/provider.d.ts +16 -20
- package/dist/types/web/search/providers/base.d.ts +2 -1
- package/dist/types/web/search/providers/openai-compatible.d.ts +9 -0
- package/dist/types/web/search/types.d.ts +14 -2
- package/package.json +7 -7
- package/scripts/build-binary.ts +7 -0
- package/src/async/job-manager.ts +153 -39
- package/src/cli/args.ts +2 -0
- package/src/cli/fast-help.ts +2 -0
- package/src/cli/setup-cli.ts +138 -3
- package/src/commands/setup.ts +5 -1
- package/src/commands/ultragoal.ts +3 -1
- package/src/config/file-lock-gc.ts +14 -2
- package/src/config/file-lock.ts +63 -13
- package/src/config/model-profile-activation.ts +15 -3
- package/src/config/model-profiles.ts +15 -15
- package/src/config/model-registry.ts +21 -1
- package/src/config/models-config-schema.ts +1 -0
- package/src/config/settings-schema.ts +62 -0
- package/src/dap/client.ts +105 -64
- package/src/dap/session.ts +44 -7
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +30 -8
- package/src/edit/read-file.ts +19 -1
- package/src/eval/js/context-manager.ts +228 -65
- package/src/eval/js/executor.ts +2 -0
- package/src/eval/js/index.ts +1 -0
- package/src/eval/js/worker-core.ts +10 -6
- package/src/eval/py/executor.ts +68 -19
- package/src/eval/py/kernel.ts +46 -22
- package/src/eval/py/runner.py +68 -14
- package/src/exec/bash-executor.ts +49 -13
- package/src/gjc-runtime/deep-interview-recorder.ts +40 -0
- package/src/gjc-runtime/launch-tmux.ts +3 -4
- package/src/gjc-runtime/ralplan-runtime.ts +174 -12
- package/src/gjc-runtime/state-runtime.ts +2 -1
- package/src/gjc-runtime/state-writer.ts +254 -7
- package/src/gjc-runtime/tmux-gc.ts +88 -38
- package/src/gjc-runtime/tmux-sessions.ts +44 -6
- package/src/gjc-runtime/ultragoal-guard.ts +155 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +1227 -31
- package/src/gjc-runtime/workflow-manifest.generated.json +44 -0
- package/src/gjc-runtime/workflow-manifest.ts +12 -0
- package/src/harness-control-plane/owner.ts +3 -2
- package/src/harness-control-plane/rpc-adapter.ts +1 -1
- package/src/hooks/skill-state.ts +121 -2
- package/src/internal-urls/artifact-protocol.ts +10 -1
- package/src/internal-urls/docs-index.generated.ts +14 -10
- package/src/lsp/client.ts +64 -26
- package/src/lsp/defaults.json +1 -0
- package/src/lsp/index.ts +2 -1
- package/src/lsp/lspmux.ts +33 -9
- package/src/lsp/types.ts +2 -0
- package/src/main.ts +14 -4
- package/src/modes/acp/acp-agent.ts +4 -2
- package/src/modes/bridge/bridge-mode.ts +23 -1
- package/src/modes/components/assistant-message.ts +10 -2
- package/src/modes/components/bash-execution.ts +5 -1
- package/src/modes/components/eval-execution.ts +5 -1
- package/src/modes/components/history-search.ts +5 -2
- package/src/modes/components/model-selector.ts +60 -2
- package/src/modes/components/oauth-selector.ts +5 -0
- package/src/modes/components/provider-onboarding-selector.ts +6 -1
- package/src/modes/components/runtime-mcp-add-wizard.ts +58 -7
- package/src/modes/components/skill-message.ts +24 -16
- package/src/modes/components/tool-execution.ts +6 -0
- package/src/modes/controllers/extension-ui-controller.ts +33 -6
- package/src/modes/controllers/input-controller.ts +5 -0
- package/src/modes/controllers/selector-controller.ts +86 -2
- package/src/modes/interactive-mode.ts +11 -1
- package/src/modes/rpc/rpc-mode.ts +132 -18
- package/src/modes/shared/agent-wire/command-dispatch.ts +5 -2
- package/src/modes/shared/agent-wire/host-tool-bridge.ts +3 -0
- package/src/modes/shared/agent-wire/unattended-session.ts +16 -1
- package/src/modes/theme/defaults/claude-code.json +100 -0
- package/src/modes/theme/defaults/codex.json +100 -0
- package/src/modes/theme/defaults/index.ts +6 -0
- package/src/modes/theme/defaults/opencode.json +102 -0
- package/src/modes/theme/theme.ts +2 -2
- package/src/modes/types.ts +1 -1
- package/src/modes/utils/ui-helpers.ts +5 -2
- package/src/prompts/agents/executor.md +5 -2
- package/src/runtime/process-lifecycle.ts +400 -0
- package/src/runtime-mcp/manager.ts +164 -50
- package/src/runtime-mcp/transports/http.ts +12 -11
- package/src/runtime-mcp/transports/stdio.ts +64 -38
- package/src/runtime-mcp/types.ts +3 -0
- package/src/sdk.ts +39 -1
- package/src/session/agent-session.ts +190 -33
- package/src/session/artifacts.ts +17 -2
- package/src/session/blob-store.ts +36 -2
- package/src/session/history-storage.ts +32 -11
- package/src/session/session-manager.ts +99 -31
- package/src/session/streaming-output.ts +54 -3
- package/src/setup/credential-import.ts +429 -0
- package/src/skill-state/deep-interview-mutation-guard.ts +2 -1
- package/src/slash-commands/builtin-registry.ts +30 -3
- package/src/slash-commands/helpers/fast-status-report.ts +111 -0
- package/src/task/executor.ts +7 -1
- package/src/task/render.ts +18 -7
- package/src/tools/archive-reader.ts +10 -1
- package/src/tools/ask.ts +4 -2
- package/src/tools/bash.ts +11 -4
- package/src/tools/browser/tab-supervisor.ts +22 -0
- package/src/tools/browser.ts +38 -4
- package/src/tools/cron.ts +1 -1
- package/src/tools/read.ts +11 -12
- package/src/tools/sqlite-reader.ts +19 -5
- package/src/tools/subagent-render.ts +119 -29
- package/src/tools/subagent.ts +147 -7
- package/src/tools/ultragoal-ask-guard.ts +39 -0
- package/src/web/search/index.ts +25 -25
- package/src/web/search/provider.ts +178 -87
- package/src/web/search/providers/base.ts +2 -1
- package/src/web/search/providers/openai-compatible.ts +151 -0
- package/src/web/search/types.ts +47 -22
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* Messages are newline-delimited JSON.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { getProjectDir,
|
|
8
|
+
import { getProjectDir, readJsonl, Snowflake } from "@gajae-code/utils";
|
|
9
|
+
import { type OwnedProcess, spawnOwnedProcess } from "../../runtime/process-lifecycle";
|
|
9
10
|
import type {
|
|
10
11
|
JsonRpcError,
|
|
11
12
|
JsonRpcMessage,
|
|
@@ -24,7 +25,7 @@ import { toJsonRpcError } from "../../runtime-mcp/types";
|
|
|
24
25
|
const CLOSE_WAIT_MS = 1_000;
|
|
25
26
|
|
|
26
27
|
export class StdioTransport implements MCPTransport {
|
|
27
|
-
#process:
|
|
28
|
+
#process: OwnedProcess | null = null;
|
|
28
29
|
#pendingRequests = new Map<
|
|
29
30
|
string | number,
|
|
30
31
|
{
|
|
@@ -34,6 +35,8 @@ export class StdioTransport implements MCPTransport {
|
|
|
34
35
|
>();
|
|
35
36
|
#connected = false;
|
|
36
37
|
#readLoop: Promise<void> | null = null;
|
|
38
|
+
#stderrLoop: Promise<void> | null = null;
|
|
39
|
+
#closePromise: Promise<void> | null = null;
|
|
37
40
|
|
|
38
41
|
onClose?: () => void;
|
|
39
42
|
onError?: (error: Error) => void;
|
|
@@ -46,10 +49,17 @@ export class StdioTransport implements MCPTransport {
|
|
|
46
49
|
return this.#connected;
|
|
47
50
|
}
|
|
48
51
|
|
|
52
|
+
get closeBeforeReconnect(): true {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
|
|
49
56
|
/**
|
|
50
57
|
* Start the subprocess and begin reading.
|
|
51
58
|
*/
|
|
52
59
|
async connect(): Promise<void> {
|
|
60
|
+
if (this.#closePromise) {
|
|
61
|
+
throw new Error("Transport is closing");
|
|
62
|
+
}
|
|
53
63
|
if (this.#connected) return;
|
|
54
64
|
|
|
55
65
|
const args = this.config.args ?? [];
|
|
@@ -58,11 +68,12 @@ export class StdioTransport implements MCPTransport {
|
|
|
58
68
|
...this.config.env,
|
|
59
69
|
};
|
|
60
70
|
|
|
61
|
-
this.#process =
|
|
71
|
+
this.#process = spawnOwnedProcess([this.config.command, ...args], {
|
|
62
72
|
cwd: this.config.cwd ?? getProjectDir(),
|
|
63
73
|
env,
|
|
64
74
|
stdin: "pipe",
|
|
65
|
-
|
|
75
|
+
gracefulMs: CLOSE_WAIT_MS,
|
|
76
|
+
name: `mcp-stdio:${this.config.command}`,
|
|
66
77
|
});
|
|
67
78
|
|
|
68
79
|
this.#connected = true;
|
|
@@ -71,13 +82,13 @@ export class StdioTransport implements MCPTransport {
|
|
|
71
82
|
this.#readLoop = this.#startReadLoop();
|
|
72
83
|
|
|
73
84
|
// Log stderr for debugging
|
|
74
|
-
this.#startStderrLoop();
|
|
85
|
+
this.#stderrLoop = this.#startStderrLoop();
|
|
75
86
|
}
|
|
76
87
|
|
|
77
88
|
async #startReadLoop(): Promise<void> {
|
|
78
|
-
if (!this.#process?.stdout) return;
|
|
89
|
+
if (!this.#process?.child.stdout) return;
|
|
79
90
|
try {
|
|
80
|
-
for await (const line of readJsonl(this.#process.stdout)) {
|
|
91
|
+
for await (const line of readJsonl(this.#process.child.stdout)) {
|
|
81
92
|
if (!this.#connected) break;
|
|
82
93
|
try {
|
|
83
94
|
this.#handleMessage(line as JsonRpcMessage);
|
|
@@ -95,9 +106,9 @@ export class StdioTransport implements MCPTransport {
|
|
|
95
106
|
}
|
|
96
107
|
|
|
97
108
|
async #startStderrLoop(): Promise<void> {
|
|
98
|
-
if (!this.#process?.stderr) return;
|
|
109
|
+
if (!this.#process?.child.stderr) return;
|
|
99
110
|
|
|
100
|
-
const reader = this.#process.stderr.getReader();
|
|
111
|
+
const reader = this.#process.child.stderr.getReader();
|
|
101
112
|
const decoder = new TextDecoder();
|
|
102
113
|
|
|
103
114
|
try {
|
|
@@ -168,26 +179,23 @@ export class StdioTransport implements MCPTransport {
|
|
|
168
179
|
}
|
|
169
180
|
}
|
|
170
181
|
|
|
182
|
+
#getStdin(): Bun.FileSink | null {
|
|
183
|
+
const stdin = this.#process?.child.stdin;
|
|
184
|
+
return typeof stdin === "object" && stdin !== null ? stdin : null;
|
|
185
|
+
}
|
|
186
|
+
|
|
171
187
|
#sendResponse(id: string | number, result?: unknown, error?: JsonRpcError): void {
|
|
172
|
-
|
|
188
|
+
const stdin = this.#getStdin();
|
|
189
|
+
if (!this.#connected || !stdin) return;
|
|
173
190
|
const response = error
|
|
174
191
|
? { jsonrpc: "2.0" as const, id, error }
|
|
175
192
|
: { jsonrpc: "2.0" as const, id, result: result ?? {} };
|
|
176
|
-
|
|
177
|
-
|
|
193
|
+
stdin.write(`${JSON.stringify(response)}\n`);
|
|
194
|
+
stdin.flush();
|
|
178
195
|
}
|
|
179
196
|
|
|
180
197
|
#handleClose(): void {
|
|
181
|
-
|
|
182
|
-
this.#connected = false;
|
|
183
|
-
|
|
184
|
-
// Reject all pending requests
|
|
185
|
-
for (const [, pending] of this.#pendingRequests) {
|
|
186
|
-
pending.reject(new Error("Transport closed"));
|
|
187
|
-
}
|
|
188
|
-
this.#pendingRequests.clear();
|
|
189
|
-
|
|
190
|
-
this.onClose?.();
|
|
198
|
+
void this.#closeInternal(true);
|
|
191
199
|
}
|
|
192
200
|
|
|
193
201
|
async request<T = unknown>(
|
|
@@ -195,7 +203,8 @@ export class StdioTransport implements MCPTransport {
|
|
|
195
203
|
params?: Record<string, unknown>,
|
|
196
204
|
options?: MCPRequestOptions,
|
|
197
205
|
): Promise<T> {
|
|
198
|
-
|
|
206
|
+
const stdin = this.#getStdin();
|
|
207
|
+
if (!this.#connected || !stdin) {
|
|
199
208
|
throw new Error("Transport not connected");
|
|
200
209
|
}
|
|
201
210
|
|
|
@@ -261,8 +270,8 @@ export class StdioTransport implements MCPTransport {
|
|
|
261
270
|
const message = `${JSON.stringify(request)}\n`;
|
|
262
271
|
try {
|
|
263
272
|
// Bun's FileSink has write() method directly
|
|
264
|
-
|
|
265
|
-
|
|
273
|
+
stdin.write(message);
|
|
274
|
+
stdin.flush();
|
|
266
275
|
} catch (error: unknown) {
|
|
267
276
|
cleanup();
|
|
268
277
|
reject(error instanceof Error ? error : new Error(String(error)));
|
|
@@ -272,7 +281,8 @@ export class StdioTransport implements MCPTransport {
|
|
|
272
281
|
}
|
|
273
282
|
|
|
274
283
|
async notify(method: string, params?: Record<string, unknown>): Promise<void> {
|
|
275
|
-
|
|
284
|
+
const stdin = this.#getStdin();
|
|
285
|
+
if (!this.#connected || !stdin) {
|
|
276
286
|
throw new Error("Transport not connected");
|
|
277
287
|
}
|
|
278
288
|
|
|
@@ -284,35 +294,51 @@ export class StdioTransport implements MCPTransport {
|
|
|
284
294
|
|
|
285
295
|
const message = `${JSON.stringify(notification)}\n`;
|
|
286
296
|
// Bun's FileSink has write() method directly
|
|
287
|
-
|
|
288
|
-
|
|
297
|
+
stdin.write(message);
|
|
298
|
+
stdin.flush();
|
|
289
299
|
}
|
|
290
300
|
|
|
291
301
|
async close(): Promise<void> {
|
|
292
|
-
|
|
302
|
+
await this.#closeInternal(false);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
#closeInternal(fromReadLoop: boolean): Promise<void> {
|
|
306
|
+
if (this.#closePromise) return this.#closePromise;
|
|
307
|
+
this.#closePromise = this.#finishClose(fromReadLoop).finally(() => {
|
|
308
|
+
this.#closePromise = null;
|
|
309
|
+
});
|
|
310
|
+
return this.#closePromise;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
async #finishClose(fromReadLoop: boolean): Promise<void> {
|
|
314
|
+
const wasConnected = this.#connected;
|
|
293
315
|
this.#connected = false;
|
|
294
316
|
|
|
295
|
-
// Reject pending requests
|
|
296
317
|
for (const [, pending] of this.#pendingRequests) {
|
|
297
318
|
pending.reject(new Error("Transport closed"));
|
|
298
319
|
}
|
|
299
320
|
this.#pendingRequests.clear();
|
|
300
321
|
|
|
301
|
-
|
|
322
|
+
const stdin = this.#getStdin();
|
|
302
323
|
const process = this.#process;
|
|
324
|
+
this.#process = null;
|
|
303
325
|
if (process) {
|
|
304
|
-
|
|
305
|
-
await
|
|
306
|
-
|
|
326
|
+
stdin?.end();
|
|
327
|
+
await process.dispose().catch(() => {});
|
|
328
|
+
await process.awaitExit({ timeoutMs: CLOSE_WAIT_MS }).catch(() => ({ exited: false, code: null }));
|
|
307
329
|
}
|
|
308
330
|
|
|
309
|
-
|
|
310
|
-
if (this.#readLoop) {
|
|
331
|
+
if (!fromReadLoop && this.#readLoop) {
|
|
311
332
|
await this.#readLoop.catch(() => {});
|
|
312
|
-
|
|
333
|
+
}
|
|
334
|
+
this.#readLoop = null;
|
|
335
|
+
|
|
336
|
+
if (this.#stderrLoop) {
|
|
337
|
+
await this.#stderrLoop.catch(() => {});
|
|
338
|
+
this.#stderrLoop = null;
|
|
313
339
|
}
|
|
314
340
|
|
|
315
|
-
this.onClose?.();
|
|
341
|
+
if (wasConnected) this.onClose?.();
|
|
316
342
|
}
|
|
317
343
|
}
|
|
318
344
|
|
package/src/runtime-mcp/types.ts
CHANGED
|
@@ -225,6 +225,9 @@ export interface MCPTransport {
|
|
|
225
225
|
/** Close the transport */
|
|
226
226
|
close(): Promise<void>;
|
|
227
227
|
|
|
228
|
+
/** Whether close must finish before reconnect can safely spawn a replacement. */
|
|
229
|
+
readonly closeBeforeReconnect?: boolean;
|
|
230
|
+
|
|
228
231
|
/** Whether the transport is connected */
|
|
229
232
|
readonly connected: boolean;
|
|
230
233
|
|
package/src/sdk.ts
CHANGED
|
@@ -52,6 +52,7 @@ import { resolveConfigValue } from "./config/resolve-config-value";
|
|
|
52
52
|
import { getEmbeddedDefaultGjcSkills } from "./defaults/gjc-defaults";
|
|
53
53
|
import { BUNDLED_GROK_BUILD_EXTENSION_ID, getBundledGrokBuildExtensionFactory } from "./defaults/gjc-grok-cli";
|
|
54
54
|
import { initializeWithSettings } from "./discovery";
|
|
55
|
+
import { disposeAllVmContexts, disposeVmContextsByOwner } from "./eval/js/context-manager";
|
|
55
56
|
import { disposeAllKernelSessions, disposeKernelSessionsByOwner } from "./eval/py/executor";
|
|
56
57
|
import { TtsrManager } from "./export/ttsr";
|
|
57
58
|
import type { CustomCommandsLoadResult, LoadedCustomCommand } from "./extensibility/custom-commands";
|
|
@@ -115,6 +116,7 @@ import {
|
|
|
115
116
|
FindTool,
|
|
116
117
|
getSearchTools,
|
|
117
118
|
HIDDEN_TOOLS,
|
|
119
|
+
isConfigurableSearchProviderId,
|
|
118
120
|
isSearchProviderPreference,
|
|
119
121
|
type LspStartupServerInfo,
|
|
120
122
|
loadSshTool,
|
|
@@ -124,6 +126,7 @@ import {
|
|
|
124
126
|
SearchTool,
|
|
125
127
|
setPreferredImageProvider,
|
|
126
128
|
setPreferredSearchProvider,
|
|
129
|
+
setSearchFallbackProviders,
|
|
127
130
|
type Tool,
|
|
128
131
|
type ToolSession,
|
|
129
132
|
WebSearchTool,
|
|
@@ -133,6 +136,7 @@ import {
|
|
|
133
136
|
import { ToolContextStore } from "./tools/context";
|
|
134
137
|
import { getImageGenTools } from "./tools/image-gen";
|
|
135
138
|
import { wrapToolWithMetaNotice } from "./tools/output-meta";
|
|
139
|
+
import { guardToolForUltragoalAsk } from "./tools/ultragoal-ask-guard";
|
|
136
140
|
import { EventBus } from "./utils/event-bus";
|
|
137
141
|
import { buildNamedToolChoice, buildNamedToolChoiceResult } from "./utils/tool-choice";
|
|
138
142
|
import { buildWorkspaceTree, type WorkspaceTree } from "./workspace-tree";
|
|
@@ -411,6 +415,7 @@ function getDefaultAgentDir(): string {
|
|
|
411
415
|
*/
|
|
412
416
|
export async function discoverAuthStorage(agentDir: string = getDefaultAgentDir()): Promise<AuthStorage> {
|
|
413
417
|
const brokerConfig = await resolveAuthBrokerConfig();
|
|
418
|
+
const credentialRankingMode = resolveCredentialRankingMode();
|
|
414
419
|
if (brokerConfig) {
|
|
415
420
|
const client = new AuthBrokerClient({ url: brokerConfig.url, token: brokerConfig.token });
|
|
416
421
|
const initialResult = await client.fetchSnapshot();
|
|
@@ -421,6 +426,7 @@ export async function discoverAuthStorage(agentDir: string = getDefaultAgentDir(
|
|
|
421
426
|
const storage = new AuthStorage(store, {
|
|
422
427
|
configValueResolver: resolveConfigValue,
|
|
423
428
|
sourceLabel: `broker ${brokerConfig.url}`,
|
|
429
|
+
credentialRankingMode,
|
|
424
430
|
});
|
|
425
431
|
await storage.reload();
|
|
426
432
|
return storage;
|
|
@@ -429,11 +435,25 @@ export async function discoverAuthStorage(agentDir: string = getDefaultAgentDir(
|
|
|
429
435
|
const storage = await AuthStorage.create(dbPath, {
|
|
430
436
|
configValueResolver: resolveConfigValue,
|
|
431
437
|
sourceLabel: `local ${dbPath}`,
|
|
438
|
+
credentialRankingMode,
|
|
432
439
|
});
|
|
433
440
|
await storage.reload();
|
|
434
441
|
return storage;
|
|
435
442
|
}
|
|
436
443
|
|
|
444
|
+
/**
|
|
445
|
+
* Opt-in multi-account credential ranking mode, read from the
|
|
446
|
+
* `GJC_CREDENTIAL_RANKING_MODE` env var. Unset/unknown → `undefined`, leaving
|
|
447
|
+
* {@link AuthStorage}'s default (`balanced`) untouched. `earliest-reset`
|
|
448
|
+
* switches to earliest-expiry-first selection so soon-to-reset tumbling-window
|
|
449
|
+
* quota is drained before it is lost.
|
|
450
|
+
*/
|
|
451
|
+
function resolveCredentialRankingMode(): "balanced" | "earliest-reset" | undefined {
|
|
452
|
+
const raw = process.env.GJC_CREDENTIAL_RANKING_MODE?.trim();
|
|
453
|
+
if (raw === "balanced" || raw === "earliest-reset") return raw;
|
|
454
|
+
return undefined;
|
|
455
|
+
}
|
|
456
|
+
|
|
437
457
|
/**
|
|
438
458
|
* Discover extensions from cwd.
|
|
439
459
|
*/
|
|
@@ -567,6 +587,14 @@ function registerPythonCleanup(): void {
|
|
|
567
587
|
postmortem.register("python-cleanup", disposeAllKernelSessions);
|
|
568
588
|
}
|
|
569
589
|
|
|
590
|
+
let jsVmCleanupRegistered = false;
|
|
591
|
+
|
|
592
|
+
function registerJsVmCleanup(): void {
|
|
593
|
+
if (jsVmCleanupRegistered) return;
|
|
594
|
+
jsVmCleanupRegistered = true;
|
|
595
|
+
postmortem.register("js-vm-cleanup", disposeAllVmContexts);
|
|
596
|
+
}
|
|
597
|
+
|
|
570
598
|
/**
|
|
571
599
|
* Resolve whether to enable append-only context mode based on the setting and provider.
|
|
572
600
|
*
|
|
@@ -803,6 +831,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
803
831
|
|
|
804
832
|
registerSshCleanup();
|
|
805
833
|
registerPythonCleanup();
|
|
834
|
+
registerJsVmCleanup();
|
|
806
835
|
|
|
807
836
|
// Pin authStorage to modelRegistry.authStorage: ModelRegistry.getApiKey() routes refresh
|
|
808
837
|
// failures through that instance, so any divergent storage handed to the bridge / mcpManager
|
|
@@ -865,6 +894,12 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
865
894
|
if (typeof webSearchProvider === "string" && isSearchProviderPreference(webSearchProvider)) {
|
|
866
895
|
setPreferredSearchProvider(webSearchProvider);
|
|
867
896
|
}
|
|
897
|
+
const webSearchFallback = settings.get("web_search.fallback");
|
|
898
|
+
if (Array.isArray(webSearchFallback)) {
|
|
899
|
+
setSearchFallbackProviders(
|
|
900
|
+
webSearchFallback.filter(value => typeof value === "string" && isConfigurableSearchProviderId(value)),
|
|
901
|
+
);
|
|
902
|
+
}
|
|
868
903
|
|
|
869
904
|
const imageProvider = settings.get("providers.image");
|
|
870
905
|
if (
|
|
@@ -1806,7 +1841,9 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
1806
1841
|
|
|
1807
1842
|
const initialTools = initialToolNames
|
|
1808
1843
|
.map(name => toolRegistry.get(name))
|
|
1809
|
-
.filter((tool): tool is AgentTool => tool !== undefined)
|
|
1844
|
+
.filter((tool): tool is AgentTool => tool !== undefined)
|
|
1845
|
+
// AgentSession tool wrapping is not installed until after Agent construction.
|
|
1846
|
+
.map(tool => guardToolForUltragoalAsk(tool, () => sessionManager.getCwd()));
|
|
1810
1847
|
|
|
1811
1848
|
const openaiWebsocketSetting = settings.get("providers.openaiWebsockets") ?? "off";
|
|
1812
1849
|
const preferOpenAICodexWebsockets =
|
|
@@ -2189,6 +2226,7 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
2189
2226
|
} else {
|
|
2190
2227
|
if (hasRegistered) agentRegistry.unregister(resolvedAgentId);
|
|
2191
2228
|
await disposeKernelSessionsByOwner(evalKernelOwnerId);
|
|
2229
|
+
await disposeVmContextsByOwner(evalKernelOwnerId);
|
|
2192
2230
|
}
|
|
2193
2231
|
} catch (cleanupError) {
|
|
2194
2232
|
logger.warn("Failed to clean up createAgentSession resources after startup error", {
|