@gajae-code/coding-agent 0.3.0 → 0.3.2
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 +32 -0
- package/README.md +1 -1
- package/dist/types/async/job-manager.d.ts +7 -0
- package/dist/types/cli/args.d.ts +3 -1
- package/dist/types/commands/deep-interview.d.ts +3 -0
- package/dist/types/commands/launch.d.ts +6 -0
- package/dist/types/config/keybindings.d.ts +5 -0
- package/dist/types/config/model-profile-activation.d.ts +30 -0
- package/dist/types/config/model-profiles.d.ts +19 -0
- package/dist/types/config/model-registry.d.ts +8 -0
- package/dist/types/config/model-resolver.d.ts +1 -1
- package/dist/types/config/models-config-schema.d.ts +47 -0
- package/dist/types/config/settings-schema.d.ts +14 -4
- package/dist/types/debug/crash-diagnostics.d.ts +45 -0
- package/dist/types/debug/runtime-gauges.d.ts +6 -0
- package/dist/types/deep-interview/render-middleware.d.ts +1 -0
- package/dist/types/eval/py/executor.d.ts +2 -0
- package/dist/types/eval/py/kernel.d.ts +2 -0
- package/dist/types/exec/bash-executor.d.ts +10 -0
- package/dist/types/gjc-runtime/cli-write-receipt.d.ts +24 -0
- package/dist/types/gjc-runtime/deep-interview-runtime.d.ts +1 -0
- package/dist/types/gjc-runtime/state-migrations.d.ts +9 -0
- package/dist/types/gjc-runtime/state-schema.d.ts +317 -0
- package/dist/types/gjc-runtime/state-writer.d.ts +10 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +2 -1
- package/dist/types/gjc-runtime/workflow-command-ref.d.ts +43 -0
- package/dist/types/harness-control-plane/control-endpoint.d.ts +3 -2
- package/dist/types/hooks/skill-state.d.ts +21 -0
- package/dist/types/internal-urls/agent-protocol.d.ts +2 -2
- package/dist/types/internal-urls/artifact-protocol.d.ts +2 -2
- package/dist/types/internal-urls/registry-helpers.d.ts +8 -7
- package/dist/types/internal-urls/types.d.ts +4 -0
- package/dist/types/lsp/index.d.ts +10 -10
- package/dist/types/main.d.ts +10 -1
- package/dist/types/modes/bridge/auth.d.ts +12 -0
- package/dist/types/modes/bridge/bridge-client-bridge.d.ts +9 -0
- package/dist/types/modes/bridge/bridge-mode.d.ts +44 -0
- package/dist/types/modes/bridge/bridge-ui-context.d.ts +88 -0
- package/dist/types/modes/bridge/event-stream.d.ts +8 -0
- package/dist/types/modes/components/custom-editor.d.ts +6 -0
- package/dist/types/modes/components/custom-provider-wizard.d.ts +10 -0
- package/dist/types/modes/components/jobs-overlay-model.d.ts +31 -0
- package/dist/types/modes/components/jobs-overlay.d.ts +30 -0
- package/dist/types/modes/components/model-selector.d.ts +6 -1
- package/dist/types/modes/components/provider-onboarding-selector.d.ts +1 -1
- package/dist/types/modes/components/status-line/types.d.ts +2 -0
- package/dist/types/modes/components/status-line.d.ts +2 -0
- package/dist/types/modes/controllers/input-controller.d.ts +1 -0
- package/dist/types/modes/controllers/selector-controller.d.ts +9 -0
- package/dist/types/modes/index.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +1 -0
- package/dist/types/modes/jobs-observer.d.ts +57 -0
- package/dist/types/modes/rpc/host-tools.d.ts +1 -16
- package/dist/types/modes/rpc/host-uris.d.ts +1 -38
- package/dist/types/modes/shared/agent-wire/command-dispatch.d.ts +20 -0
- package/dist/types/modes/shared/agent-wire/command-validation.d.ts +2 -0
- package/dist/types/modes/shared/agent-wire/event-envelope.d.ts +24 -0
- package/dist/types/modes/shared/agent-wire/handshake.d.ts +46 -0
- package/dist/types/modes/shared/agent-wire/host-tool-bridge.d.ts +16 -0
- package/dist/types/modes/shared/agent-wire/host-uri-bridge.d.ts +17 -0
- package/dist/types/modes/shared/agent-wire/protocol.d.ts +44 -0
- package/dist/types/modes/shared/agent-wire/responses.d.ts +4 -0
- package/dist/types/modes/shared/agent-wire/scopes.d.ts +18 -0
- package/dist/types/modes/shared/agent-wire/ui-request-broker.d.ts +42 -0
- package/dist/types/modes/shared/agent-wire/ui-result.d.ts +27 -0
- package/dist/types/modes/types.d.ts +2 -0
- package/dist/types/sdk.d.ts +3 -1
- package/dist/types/session/agent-session.d.ts +11 -1
- package/dist/types/skill-state/workflow-state-contract.d.ts +1 -2
- package/dist/types/skill-state/workflow-state-version.d.ts +3 -0
- package/dist/types/task/executor.d.ts +1 -0
- package/dist/types/task/id.d.ts +7 -0
- package/dist/types/task/index.d.ts +5 -0
- package/dist/types/task/receipt.d.ts +85 -0
- package/dist/types/task/spawn-gate.d.ts +38 -0
- package/dist/types/task/types.d.ts +143 -11
- package/dist/types/tools/cron.d.ts +6 -0
- package/dist/types/tools/hindsight-recall.d.ts +0 -2
- package/dist/types/tools/hindsight-reflect.d.ts +0 -2
- package/dist/types/tools/hindsight-retain.d.ts +0 -2
- package/dist/types/tools/index.d.ts +6 -4
- package/dist/types/tools/path-utils.d.ts +1 -0
- package/dist/types/tools/subagent.d.ts +15 -0
- package/package.json +7 -7
- package/scripts/build-binary.ts +7 -0
- package/src/async/job-manager.ts +36 -0
- package/src/cli/args.ts +19 -2
- package/src/commands/deep-interview.ts +1 -0
- package/src/commands/harness.ts +289 -19
- package/src/commands/launch.ts +10 -2
- package/src/commands/state.ts +2 -1
- package/src/commands/team.ts +22 -4
- package/src/config/keybindings.ts +6 -0
- package/src/config/model-profile-activation.ts +157 -0
- package/src/config/model-profiles.ts +155 -0
- package/src/config/model-registry.ts +19 -0
- package/src/config/model-resolver.ts +3 -2
- package/src/config/models-config-schema.ts +36 -0
- package/src/config/settings-schema.ts +16 -3
- package/src/dap/client.ts +17 -3
- package/src/debug/crash-diagnostics.ts +223 -0
- package/src/debug/runtime-gauges.ts +20 -0
- package/src/deep-interview/render-middleware.ts +6 -0
- package/src/defaults/gjc/skills/deep-interview/SKILL.md +1 -1
- package/src/defaults/gjc/skills/ralplan/SKILL.md +31 -2
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +39 -3
- package/src/defaults/gjc/skills/ultragoal/ai-slop-cleaner.md +61 -0
- package/src/defaults/gjc-defaults.ts +7 -0
- package/src/eval/py/executor.ts +21 -1
- package/src/eval/py/kernel.ts +15 -0
- package/src/exec/bash-executor.ts +41 -0
- package/src/gjc-runtime/cli-write-receipt.ts +31 -0
- package/src/gjc-runtime/deep-interview-runtime.ts +69 -32
- package/src/gjc-runtime/ralplan-runtime.ts +213 -36
- package/src/gjc-runtime/state-migrations.ts +54 -7
- package/src/gjc-runtime/state-runtime.ts +461 -64
- package/src/gjc-runtime/state-schema.ts +192 -0
- package/src/gjc-runtime/state-writer.ts +32 -1
- package/src/gjc-runtime/team-runtime.ts +177 -105
- package/src/gjc-runtime/ultragoal-runtime.ts +231 -38
- package/src/gjc-runtime/workflow-command-ref.ts +239 -0
- package/src/gjc-runtime/workflow-manifest.generated.json +108 -4
- package/src/gjc-runtime/workflow-manifest.ts +3 -1
- package/src/harness-control-plane/control-endpoint.ts +19 -8
- package/src/harness-control-plane/owner.ts +57 -10
- package/src/harness-control-plane/state-machine.ts +2 -1
- package/src/hooks/skill-state.ts +176 -26
- package/src/internal-urls/agent-protocol.ts +68 -21
- package/src/internal-urls/artifact-protocol.ts +12 -17
- package/src/internal-urls/docs-index.generated.ts +8 -10
- package/src/internal-urls/registry-helpers.ts +19 -16
- package/src/internal-urls/types.ts +4 -0
- package/src/lsp/client.ts +18 -2
- package/src/main.ts +88 -6
- package/src/modes/bridge/auth.ts +41 -0
- package/src/modes/bridge/bridge-client-bridge.ts +47 -0
- package/src/modes/bridge/bridge-mode.ts +520 -0
- package/src/modes/bridge/bridge-ui-context.ts +200 -0
- package/src/modes/bridge/event-stream.ts +70 -0
- package/src/modes/components/custom-editor.ts +101 -0
- package/src/modes/components/custom-provider-wizard.ts +318 -0
- package/src/modes/components/hook-selector.ts +61 -18
- package/src/modes/components/jobs-overlay-model.ts +109 -0
- package/src/modes/components/jobs-overlay.ts +172 -0
- package/src/modes/components/model-selector.ts +108 -18
- package/src/modes/components/provider-onboarding-selector.ts +6 -1
- package/src/modes/components/status-line/presets.ts +7 -5
- package/src/modes/components/status-line/segments.ts +25 -0
- package/src/modes/components/status-line/types.ts +2 -0
- package/src/modes/components/status-line.ts +9 -1
- package/src/modes/controllers/extension-ui-controller.ts +39 -3
- package/src/modes/controllers/input-controller.ts +97 -9
- package/src/modes/controllers/selector-controller.ts +86 -1
- package/src/modes/index.ts +1 -0
- package/src/modes/interactive-mode.ts +27 -0
- package/src/modes/jobs-observer.ts +204 -0
- package/src/modes/rpc/host-tools.ts +1 -186
- package/src/modes/rpc/host-uris.ts +1 -235
- package/src/modes/rpc/rpc-client.ts +25 -10
- package/src/modes/rpc/rpc-mode.ts +12 -381
- package/src/modes/shared/agent-wire/command-dispatch.ts +341 -0
- package/src/modes/shared/agent-wire/command-validation.ts +131 -0
- package/src/modes/shared/agent-wire/event-envelope.ts +108 -0
- package/src/modes/shared/agent-wire/handshake.ts +117 -0
- package/src/modes/shared/agent-wire/host-tool-bridge.ts +194 -0
- package/src/modes/shared/agent-wire/host-uri-bridge.ts +236 -0
- package/src/modes/shared/agent-wire/protocol.ts +96 -0
- package/src/modes/shared/agent-wire/responses.ts +17 -0
- package/src/modes/shared/agent-wire/scopes.ts +89 -0
- package/src/modes/shared/agent-wire/ui-request-broker.ts +150 -0
- package/src/modes/shared/agent-wire/ui-result.ts +48 -0
- package/src/modes/types.ts +2 -0
- package/src/prompts/memories/consolidation.md +1 -1
- package/src/prompts/memories/read-path.md +6 -7
- package/src/prompts/memories/unavailable.md +2 -2
- package/src/prompts/tools/bash.md +1 -1
- package/src/prompts/tools/irc.md +1 -1
- package/src/prompts/tools/read.md +2 -2
- package/src/prompts/tools/recall.md +1 -0
- package/src/prompts/tools/reflect.md +1 -0
- package/src/prompts/tools/retain.md +1 -0
- package/src/prompts/tools/subagent.md +12 -7
- package/src/prompts/tools/task-summary.md +3 -9
- package/src/prompts/tools/task.md +5 -1
- package/src/sdk.ts +5 -1
- package/src/session/agent-session.ts +214 -38
- package/src/skill-state/deep-interview-mutation-guard.ts +23 -4
- package/src/skill-state/workflow-state-contract.ts +7 -4
- package/src/skill-state/workflow-state-version.ts +3 -0
- package/src/slash-commands/builtin-registry.ts +9 -1
- package/src/task/executor.ts +31 -5
- package/src/task/id.ts +33 -0
- package/src/task/index.ts +259 -67
- package/src/task/output-manager.ts +5 -4
- package/src/task/receipt.ts +297 -0
- package/src/task/render.ts +48 -131
- package/src/task/spawn-gate.ts +132 -0
- package/src/task/types.ts +48 -7
- package/src/tools/ask.ts +73 -33
- package/src/tools/ast-edit.ts +1 -0
- package/src/tools/ast-grep.ts +1 -0
- package/src/tools/bash.ts +1 -1
- package/src/tools/cron.ts +48 -0
- package/src/tools/find.ts +4 -1
- package/src/tools/hindsight-recall.ts +0 -2
- package/src/tools/hindsight-reflect.ts +0 -2
- package/src/tools/hindsight-retain.ts +0 -2
- package/src/tools/index.ts +6 -18
- package/src/tools/path-utils.ts +3 -2
- package/src/tools/read.ts +4 -3
- package/src/tools/search.ts +1 -0
- package/src/tools/skill.ts +6 -1
- package/src/tools/subagent.ts +237 -84
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Shared helpers for internal-url protocol handlers that resolve
|
|
3
|
-
*
|
|
2
|
+
* Shared helpers for internal-url protocol handlers that resolve session-scoped
|
|
3
|
+
* artifact IDs.
|
|
4
4
|
*/
|
|
5
|
-
import
|
|
5
|
+
import * as path from "node:path";
|
|
6
|
+
import type { ResolveContext } from "./types";
|
|
7
|
+
|
|
8
|
+
function addDir(dirs: string[], dir: string | null | undefined): void {
|
|
9
|
+
if (!dir) return;
|
|
10
|
+
const normalized = path.resolve(dir);
|
|
11
|
+
if (!dirs.includes(normalized)) dirs.push(normalized);
|
|
12
|
+
}
|
|
6
13
|
|
|
7
14
|
/**
|
|
8
|
-
* Snapshot of artifacts dirs for
|
|
15
|
+
* Snapshot of artifacts dirs explicitly authorized for the calling session.
|
|
9
16
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
17
|
+
* Normal reads are scoped to the caller's artifacts directory. Parent/child
|
|
18
|
+
* agent tree sharing is allowed only when the caller supplies explicit
|
|
19
|
+
* authorized directories at the ResolveContext boundary. This intentionally
|
|
20
|
+
* does not enumerate AgentRegistry.global(); live but unrelated sessions are
|
|
21
|
+
* not an authorization source.
|
|
15
22
|
*/
|
|
16
|
-
export function
|
|
23
|
+
export function authorizedArtifactsDirsFromContext(context?: ResolveContext): string[] {
|
|
17
24
|
const dirs: string[] = [];
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
ref.session?.sessionManager.getArtifactsDir() ?? (ref.sessionFile ? ref.sessionFile.slice(0, -6) : null);
|
|
21
|
-
if (!dir) continue;
|
|
22
|
-
if (!dirs.includes(dir)) dirs.push(dir);
|
|
23
|
-
}
|
|
25
|
+
addDir(dirs, context?.getArtifactsDir?.());
|
|
26
|
+
for (const dir of context?.getAuthorizedArtifactsDirs?.() ?? []) addDir(dirs, dir);
|
|
24
27
|
return dirs;
|
|
25
28
|
}
|
|
@@ -59,6 +59,10 @@ export interface ResolveContext {
|
|
|
59
59
|
cwd?: string;
|
|
60
60
|
/** Settings of the calling session (used by `issue://`/`pr://` for cache TTLs). */
|
|
61
61
|
settings?: unknown;
|
|
62
|
+
/** Artifacts directory of the calling session. */
|
|
63
|
+
getArtifactsDir?: () => string | null;
|
|
64
|
+
/** Additional artifacts directories explicitly authorized for this caller (for parent/child agent trees). */
|
|
65
|
+
getAuthorizedArtifactsDirs?: () => readonly string[];
|
|
62
66
|
/** Caller's abort signal. */
|
|
63
67
|
signal?: AbortSignal;
|
|
64
68
|
}
|
package/src/lsp/client.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { isEnoent, logger, ptree, untilAborted } from "@gajae-code/utils";
|
|
2
|
+
import { formatCrashDiagnosticNotice, writeCrashReport } from "../debug/crash-diagnostics";
|
|
2
3
|
import { ToolAbortError, throwIfAborted } from "../tools/tool-errors";
|
|
3
4
|
import { applyWorkspaceEdit } from "./edits";
|
|
4
5
|
import { getLspmuxCommand, isLspmuxSupported } from "./lspmux";
|
|
@@ -486,7 +487,7 @@ export async function getOrCreateClient(config: ServerConfig, cwd: string, initT
|
|
|
486
487
|
clients.set(key, client);
|
|
487
488
|
|
|
488
489
|
// Register crash recovery - remove client on process exit
|
|
489
|
-
proc.exited.then(() => {
|
|
490
|
+
proc.exited.then(async () => {
|
|
490
491
|
clients.delete(key);
|
|
491
492
|
clientLocks.delete(key);
|
|
492
493
|
client.resolveProjectLoaded();
|
|
@@ -501,9 +502,24 @@ export async function getOrCreateClient(config: ServerConfig, cwd: string, initT
|
|
|
501
502
|
.filter(line => !/^\[\d{2}:\d{2}:\d{2} (?:INF|DBG|VRB)\]/.test(line))
|
|
502
503
|
.join("\n")
|
|
503
504
|
.trim();
|
|
505
|
+
const crashNotice = formatCrashDiagnosticNotice(
|
|
506
|
+
await writeCrashReport(
|
|
507
|
+
{
|
|
508
|
+
kind: "lsp",
|
|
509
|
+
command: [command, ...args],
|
|
510
|
+
exitCode: proc.exitCode,
|
|
511
|
+
stderr,
|
|
512
|
+
protocol: "lsp",
|
|
513
|
+
},
|
|
514
|
+
{ cwd },
|
|
515
|
+
),
|
|
516
|
+
);
|
|
517
|
+
const diagnosticSuffix = crashNotice ? `\n${crashNotice}` : "";
|
|
504
518
|
const code = proc.exitCode;
|
|
505
519
|
const err = new Error(
|
|
506
|
-
stderr
|
|
520
|
+
stderr
|
|
521
|
+
? `LSP server exited (code ${code}): ${stderr}${diagnosticSuffix}`
|
|
522
|
+
: `LSP server exited unexpectedly (code ${code})${diagnosticSuffix}`,
|
|
507
523
|
);
|
|
508
524
|
for (const pending of client.pendingRequests.values()) {
|
|
509
525
|
pending.reject(err);
|
package/src/main.ts
CHANGED
|
@@ -26,13 +26,14 @@ import { buildInitialMessage } from "./cli/initial-message";
|
|
|
26
26
|
import { runListModelsCommand } from "./cli/list-models";
|
|
27
27
|
import { selectSession } from "./cli/session-picker";
|
|
28
28
|
import { findConfigFile } from "./config";
|
|
29
|
+
import { activateModelProfile } from "./config/model-profile-activation";
|
|
29
30
|
import { ModelRegistry, ModelsConfigFile } from "./config/model-registry";
|
|
30
31
|
import { resolveCliModel, resolveModelRoleValue, resolveModelScope, type ScopedModel } from "./config/model-resolver";
|
|
31
32
|
import { getDefault, type SettingPath, Settings, settings } from "./config/settings";
|
|
32
33
|
import { initializeWithSettings } from "./discovery";
|
|
33
34
|
import { exportFromFile } from "./export/html";
|
|
34
35
|
import type { ExtensionUIContext } from "./extensibility/extensions/types";
|
|
35
|
-
import { InteractiveMode, runAcpMode, runPrintMode, runRpcMode } from "./modes";
|
|
36
|
+
import { InteractiveMode, runAcpMode, runBridgeMode, runPrintMode, runRpcMode } from "./modes";
|
|
36
37
|
import { initTheme, stopThemeWatcher } from "./modes/theme/theme";
|
|
37
38
|
import type { SubmittedUserInput } from "./modes/types";
|
|
38
39
|
import type { MCPManager } from "./runtime-mcp";
|
|
@@ -194,11 +195,59 @@ export interface AcpSessionFactoryOptions {
|
|
|
194
195
|
sessionDir?: string;
|
|
195
196
|
authStorage: AuthStorage;
|
|
196
197
|
modelRegistry: ModelRegistry;
|
|
197
|
-
parsedArgs: Pick<Args, "apiKey">;
|
|
198
|
+
parsedArgs: Pick<Args, "apiKey" | "default" | "model" | "mpreset" | "thinking">;
|
|
198
199
|
rawArgs: string[];
|
|
199
200
|
createSession: (options: CreateAgentSessionOptions) => Promise<CreateAgentSessionResult>;
|
|
200
201
|
}
|
|
201
202
|
|
|
203
|
+
export async function applyStartupModelProfiles(args: {
|
|
204
|
+
session: AgentSession;
|
|
205
|
+
settings: Settings;
|
|
206
|
+
modelRegistry: ModelRegistry;
|
|
207
|
+
parsedArgs: Pick<Args, "default" | "model" | "mpreset" | "thinking">;
|
|
208
|
+
startupModel?: CreateAgentSessionOptions["model"];
|
|
209
|
+
startupThinkingLevel?: CreateAgentSessionOptions["thinkingLevel"];
|
|
210
|
+
}): Promise<void> {
|
|
211
|
+
const applyProfile = async (profileName: string, persistDefault: boolean): Promise<void> => {
|
|
212
|
+
await activateModelProfile(
|
|
213
|
+
{ session: args.session, modelRegistry: args.modelRegistry, settings: args.settings, profileName },
|
|
214
|
+
{ persistDefault },
|
|
215
|
+
);
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
// Capture the explicitly-selected startup model BEFORE profile activation can
|
|
219
|
+
// override it. startupModel covers the eager path; session.model covers the
|
|
220
|
+
// deferred `--model <pattern>` path resolved inside createAgentSession.
|
|
221
|
+
const explicitModel = args.parsedArgs.model ? (args.startupModel ?? args.session.model) : undefined;
|
|
222
|
+
|
|
223
|
+
const defaultProfile = args.settings.get("modelProfile.default");
|
|
224
|
+
if (defaultProfile) {
|
|
225
|
+
await applyProfile(defaultProfile, false);
|
|
226
|
+
}
|
|
227
|
+
if (args.parsedArgs.mpreset) {
|
|
228
|
+
await applyProfile(args.parsedArgs.mpreset, args.parsedArgs.default === true);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Explicit CLI --model/--thinking must win over any activated profile.
|
|
232
|
+
if (explicitModel) {
|
|
233
|
+
await args.session.setModelTemporary(explicitModel, args.startupThinkingLevel ?? args.parsedArgs.thinking);
|
|
234
|
+
} else if (args.parsedArgs.thinking && args.session.model) {
|
|
235
|
+
await args.session.setModelTemporary(args.session.model, args.parsedArgs.thinking);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export async function applyStartupModelProfilesOrExit(
|
|
240
|
+
args: Parameters<typeof applyStartupModelProfiles>[0],
|
|
241
|
+
): Promise<void> {
|
|
242
|
+
try {
|
|
243
|
+
await applyStartupModelProfiles(args);
|
|
244
|
+
} catch (error) {
|
|
245
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
246
|
+
process.stderr.write(`${chalk.red(`Error: ${message}`)}\n`);
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
202
251
|
/**
|
|
203
252
|
* Build the per-`session/new` factory used by ACP mode.
|
|
204
253
|
*
|
|
@@ -225,6 +274,14 @@ export function createAcpSessionFactory(args: AcpSessionFactoryOptions): AcpSess
|
|
|
225
274
|
hasUI: false,
|
|
226
275
|
enableMCP: false,
|
|
227
276
|
});
|
|
277
|
+
await applyStartupModelProfilesOrExit({
|
|
278
|
+
session: nextSession,
|
|
279
|
+
settings: nextSettings,
|
|
280
|
+
modelRegistry: args.modelRegistry,
|
|
281
|
+
parsedArgs: args.parsedArgs,
|
|
282
|
+
startupModel: args.baseOptions.model,
|
|
283
|
+
startupThinkingLevel: args.baseOptions.thinkingLevel,
|
|
284
|
+
});
|
|
228
285
|
if (args.parsedArgs.apiKey && !args.baseOptions.model && nextSession.model) {
|
|
229
286
|
args.authStorage.setRuntimeApiKey(nextSession.model.provider, args.parsedArgs.apiKey);
|
|
230
287
|
}
|
|
@@ -707,21 +764,35 @@ export async function runRootCommand(
|
|
|
707
764
|
process.exit(0);
|
|
708
765
|
}
|
|
709
766
|
|
|
710
|
-
if (
|
|
711
|
-
|
|
767
|
+
if (
|
|
768
|
+
(parsedArgs.mode === "rpc" || parsedArgs.mode === "rpc-ui" || parsedArgs.mode === "bridge") &&
|
|
769
|
+
parsedArgs.fileArgs.length > 0
|
|
770
|
+
) {
|
|
771
|
+
process.stderr.write(`${chalk.red("Error: @file arguments are not supported in RPC or bridge mode")}\n`);
|
|
712
772
|
process.exit(1);
|
|
713
773
|
}
|
|
714
774
|
|
|
715
775
|
const cwd = getProjectDir();
|
|
716
776
|
const settingsInstance = deps.settings ?? (await logger.time("settings:init", Settings.init, { cwd }));
|
|
717
|
-
if (
|
|
777
|
+
if (
|
|
778
|
+
parsedArgs.mode === "rpc" ||
|
|
779
|
+
parsedArgs.mode === "rpc-ui" ||
|
|
780
|
+
parsedArgs.mode === "acp" ||
|
|
781
|
+
parsedArgs.mode === "bridge"
|
|
782
|
+
) {
|
|
718
783
|
applyRpcDefaultSettingOverrides(settingsInstance);
|
|
719
784
|
}
|
|
720
785
|
modelRegistry.applyConfiguredModelBindings(settingsInstance);
|
|
721
786
|
if (parsedArgs.noPty || parsedArgs.mode === "rpc-ui") {
|
|
722
787
|
Bun.env.PI_NO_PTY = "1";
|
|
723
788
|
}
|
|
724
|
-
if (
|
|
789
|
+
if (
|
|
790
|
+
parsedArgs.noTitle ||
|
|
791
|
+
parsedArgs.mode === "rpc" ||
|
|
792
|
+
parsedArgs.mode === "rpc-ui" ||
|
|
793
|
+
parsedArgs.mode === "acp" ||
|
|
794
|
+
parsedArgs.mode === "bridge"
|
|
795
|
+
) {
|
|
725
796
|
Bun.env.PI_NO_TITLE = "1";
|
|
726
797
|
}
|
|
727
798
|
const { pipedInput, fileText, fileImages } = await logger.time("prepareInitialMessage", async () => {
|
|
@@ -864,6 +935,15 @@ export async function runRootCommand(
|
|
|
864
935
|
authStorage.setRuntimeApiKey(session.model.provider, parsedArgs.apiKey);
|
|
865
936
|
}
|
|
866
937
|
|
|
938
|
+
await applyStartupModelProfilesOrExit({
|
|
939
|
+
session,
|
|
940
|
+
settings: settingsInstance,
|
|
941
|
+
modelRegistry,
|
|
942
|
+
parsedArgs,
|
|
943
|
+
startupModel: sessionOptions.model,
|
|
944
|
+
startupThinkingLevel: sessionOptions.thinkingLevel,
|
|
945
|
+
});
|
|
946
|
+
|
|
867
947
|
if (modelFallbackMessage) {
|
|
868
948
|
notifs.push({ kind: "warn", message: modelFallbackMessage });
|
|
869
949
|
}
|
|
@@ -894,6 +974,8 @@ export async function runRootCommand(
|
|
|
894
974
|
|
|
895
975
|
if (mode === "rpc" || mode === "rpc-ui") {
|
|
896
976
|
await runRpcMode(session, mode === "rpc-ui" ? setToolUIContext : undefined);
|
|
977
|
+
} else if (mode === "bridge") {
|
|
978
|
+
await runBridgeMode(session, setToolUIContext);
|
|
897
979
|
} else if (isInteractive) {
|
|
898
980
|
const versionCheckPromise = checkForNewVersion(VERSION).catch(() => undefined);
|
|
899
981
|
const changelogMarkdown = await logger.time("main:getChangelogForDisplay", getChangelogForDisplay, parsedArgs);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as crypto from "node:crypto";
|
|
2
|
+
|
|
3
|
+
export interface BridgeAuthConfig {
|
|
4
|
+
token: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface BridgeBindConfig {
|
|
8
|
+
hostname: string;
|
|
9
|
+
port: number;
|
|
10
|
+
tlsConfigured: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function extractBearerToken(authorization: string | null | undefined): string | undefined {
|
|
14
|
+
if (!authorization) return undefined;
|
|
15
|
+
const trimmed = authorization.trim();
|
|
16
|
+
const match = /^Bearer\s+(.+)$/i.exec(trimmed);
|
|
17
|
+
const token = match?.[1]?.trim();
|
|
18
|
+
return token ? token : undefined;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function isBridgeTokenAuthorized(authorization: string | null | undefined, config: BridgeAuthConfig): boolean {
|
|
22
|
+
const candidate = extractBearerToken(authorization);
|
|
23
|
+
if (candidate === undefined) return false;
|
|
24
|
+
const candidateBytes = Buffer.from(candidate, "utf8");
|
|
25
|
+
const expectedBytes = Buffer.from(config.token, "utf8");
|
|
26
|
+
return candidateBytes.length === expectedBytes.length && crypto.timingSafeEqual(candidateBytes, expectedBytes);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function isLoopbackHost(hostname: string): boolean {
|
|
30
|
+
const normalized = hostname.trim().toLowerCase();
|
|
31
|
+
return normalized === "localhost" || normalized === "127.0.0.1" || normalized === "::1" || normalized === "[::1]";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function assertSafeBridgeBind(config: BridgeBindConfig): void {
|
|
35
|
+
if (!config.tlsConfigured) {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`Refusing to start bridge on ${config.hostname}:${config.port} without TLS configured. ` +
|
|
38
|
+
"Set GJC_BRIDGE_TLS_CERT and GJC_BRIDGE_TLS_KEY.",
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ClientBridge,
|
|
3
|
+
ClientBridgePermissionOption,
|
|
4
|
+
ClientBridgePermissionOutcome,
|
|
5
|
+
ClientBridgePermissionToolCall,
|
|
6
|
+
} from "../../session/client-bridge";
|
|
7
|
+
import type { UiRequestBroker, UiRequestCancelled, UiRequestResolution } from "../shared/agent-wire/ui-request-broker";
|
|
8
|
+
|
|
9
|
+
export interface BridgePermissionRequestPayload {
|
|
10
|
+
kind: "permission";
|
|
11
|
+
toolCall: ClientBridgePermissionToolCall;
|
|
12
|
+
options: ClientBridgePermissionOption[];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type BridgePermissionBroker = UiRequestBroker<BridgePermissionRequestPayload, ClientBridgePermissionOutcome>;
|
|
16
|
+
function isUiRequestCancelled(
|
|
17
|
+
resolution: UiRequestResolution<ClientBridgePermissionOutcome>,
|
|
18
|
+
): resolution is UiRequestCancelled {
|
|
19
|
+
return "status" in resolution && resolution.status === "cancelled";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function toPermissionOutcome(
|
|
23
|
+
resolution: UiRequestResolution<ClientBridgePermissionOutcome>,
|
|
24
|
+
): ClientBridgePermissionOutcome {
|
|
25
|
+
if (isUiRequestCancelled(resolution)) {
|
|
26
|
+
return { outcome: "cancelled" };
|
|
27
|
+
}
|
|
28
|
+
return resolution;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function createBridgeClientBridge(broker: BridgePermissionBroker): ClientBridge {
|
|
32
|
+
return {
|
|
33
|
+
capabilities: { requestPermission: true },
|
|
34
|
+
deferAgentInitiatedTurns: true,
|
|
35
|
+
async requestPermission(toolCall, options, signal) {
|
|
36
|
+
return toPermissionOutcome(
|
|
37
|
+
await broker.request(
|
|
38
|
+
{ kind: "permission", toolCall, options },
|
|
39
|
+
{
|
|
40
|
+
correlationId: toolCall.toolCallId,
|
|
41
|
+
signal,
|
|
42
|
+
},
|
|
43
|
+
),
|
|
44
|
+
);
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|