@gajae-code/coding-agent 0.15.5 → 0.16.0
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 +85 -1
- package/dist/types/async/job-manager.d.ts +83 -0
- package/dist/types/cli/args.d.ts +2 -0
- package/dist/types/cli/auth-gateway-cli.d.ts +17 -0
- package/dist/types/cli/model-presets-cli.d.ts +9 -0
- package/dist/types/cli/root-flags.d.ts +14 -0
- package/dist/types/cli/update-cli.d.ts +15 -0
- package/dist/types/cli.d.ts +7 -0
- package/dist/types/commands/auth-gateway.d.ts +3 -0
- package/dist/types/commands/gc.d.ts +13 -0
- package/dist/types/commands/launch.d.ts +10 -0
- package/dist/types/commands/model-presets.d.ts +21 -0
- package/dist/types/config/autorouting-tier-map.d.ts +120 -0
- package/dist/types/config/file-lock.d.ts +54 -2
- package/dist/types/config/internal/model-preset-registry-test-state.d.ts +4 -0
- package/dist/types/config/internal/model-preset-registry-test-support.d.ts +3 -0
- package/dist/types/config/keybindings.d.ts +3 -2
- package/dist/types/config/model-preset-registry.d.ts +368 -0
- package/dist/types/config/model-profile-activation.d.ts +39 -0
- package/dist/types/config/model-profiles.d.ts +5 -3
- package/dist/types/config/model-registry.d.ts +17 -5
- package/dist/types/config/settings-schema.d.ts +19 -1
- package/dist/types/config/settings.d.ts +2 -0
- package/dist/types/coordinator-mcp/model-preset.d.ts +7 -5
- package/dist/types/coordinator-mcp/projection-scan.d.ts +54 -0
- package/dist/types/crash/record-loader.d.ts +15 -0
- package/dist/types/extensibility/extensions/types.d.ts +2 -5
- package/dist/types/gjc-runtime/empty-delete-gc.d.ts +58 -0
- package/dist/types/gjc-runtime/gc-runtime.d.ts +2 -0
- package/dist/types/gjc-runtime/launch-worktree-reservation.d.ts +21 -0
- package/dist/types/gjc-runtime/managed-owner-supervisor.d.ts +2 -0
- package/dist/types/gjc-runtime/session-state-lock.d.ts +35 -6
- package/dist/types/gjc-runtime/session-state-sidecar.d.ts +72 -1
- package/dist/types/gjc-runtime/tmux-owner-isolation.d.ts +1 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +27 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/main.d.ts +3 -1
- package/dist/types/master-mode/context.d.ts +21 -0
- package/dist/types/master-mode/first-request.d.ts +34 -0
- package/dist/types/master-mode/snapshot.d.ts +32 -0
- package/dist/types/modes/components/frictionless-onboarding-selector.d.ts +10 -0
- package/dist/types/modes/components/jobs-overlay-model.d.ts +4 -2
- package/dist/types/modes/components/oauth-selector.d.ts +1 -0
- package/dist/types/modes/components/status-line/model-name.d.ts +18 -0
- package/dist/types/modes/components/status-line/priority-row.d.ts +34 -0
- package/dist/types/modes/components/status-line/segments.d.ts +10 -0
- package/dist/types/modes/jobs-observer.d.ts +36 -0
- package/dist/types/modes/print-mode.d.ts +17 -0
- package/dist/types/modes/ui-language.d.ts +7 -1
- package/dist/types/sdk/broker/broker.d.ts +80 -1
- package/dist/types/sdk/broker/endpoint-authority.d.ts +24 -0
- package/dist/types/sdk/broker/index.d.ts +3 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +26 -0
- package/dist/types/sdk/broker/master-capability.d.ts +10 -0
- package/dist/types/sdk/broker/session-index.d.ts +40 -11
- package/dist/types/sdk/broker/session-scope.d.ts +72 -0
- package/dist/types/sdk/broker/spawn-authority.d.ts +201 -0
- package/dist/types/sdk/broker/spawn-substrate.d.ts +30 -0
- package/dist/types/sdk/broker/state-version.d.ts +4 -1
- package/dist/types/sdk/broker/worktree-occupancy.d.ts +28 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +3 -0
- package/dist/types/sdk/bus/index.d.ts +6 -0
- package/dist/types/sdk/bus/kind-aware-reconciliation.d.ts +3 -0
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +4 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +1 -1
- package/dist/types/sdk/cli/index.d.ts +1 -0
- package/dist/types/sdk/cli/master-cli.d.ts +63 -0
- package/dist/types/sdk/cli/rows.d.ts +4 -3
- package/dist/types/sdk/cli/session-cli.d.ts +18 -2
- package/dist/types/sdk/client/client.d.ts +3 -2
- package/dist/types/sdk/client/discovery.d.ts +1 -0
- package/dist/types/sdk/host/control/dispatch.d.ts +10 -0
- package/dist/types/sdk/host/control/index.d.ts +1 -1
- package/dist/types/sdk/host/control/operations.d.ts +2 -0
- package/dist/types/sdk/host/control/runtime-gate.d.ts +21 -7
- package/dist/types/sdk/host/host.d.ts +10 -0
- package/dist/types/sdk/host/model-pin.d.ts +7 -2
- package/dist/types/sdk/host/sdk-run-capability.d.ts +1 -0
- package/dist/types/sdk/host/session-runtime.d.ts +67 -1
- package/dist/types/sdk/lifecycle/broker-client.d.ts +6 -0
- package/dist/types/sdk/lifecycle/service.d.ts +15 -3
- package/dist/types/sdk/lifecycle-session.d.ts +2 -0
- package/dist/types/sdk/prompt-deadline-manager.d.ts +11 -1
- package/dist/types/sdk/protocol/adapter-validation.d.ts +2 -0
- package/dist/types/sdk/router/session-router.d.ts +11 -0
- package/dist/types/sdk/session.d.ts +16 -0
- package/dist/types/sdk/startup-capability.d.ts +2 -1
- package/dist/types/session/account-inventory.d.ts +1 -0
- package/dist/types/session/agent-session.d.ts +24 -7
- package/dist/types/session/credential-store-errors.d.ts +1 -0
- package/dist/types/session/fold-coordinator.d.ts +201 -0
- package/dist/types/session/sdk-run-capability-internal.d.ts +7 -0
- package/dist/types/session/sdk-run-capability.d.ts +2 -0
- package/dist/types/session/session-manager.d.ts +65 -0
- package/dist/types/session/yield-queue.d.ts +5 -4
- package/dist/types/setup/frictionless-onboarding.d.ts +1 -0
- package/dist/types/telemetry/control.d.ts +11 -0
- package/dist/types/telemetry/events.d.ts +20 -0
- package/dist/types/telemetry/index.d.ts +3 -0
- package/dist/types/telemetry/transport.d.ts +22 -0
- package/dist/types/tools/bash-interactive.d.ts +23 -0
- package/dist/types/tools/bash.d.ts +4 -0
- package/dist/types/tools/gh.d.ts +8 -0
- package/dist/types/tools/index.d.ts +10 -5
- package/dist/types/web/search/providers/base.d.ts +9 -4
- package/dist/types/web/search/providers/xai.d.ts +2 -1
- package/dist/types/web/search/types.d.ts +14 -0
- package/package.json +10 -7
- package/scripts/generate-hotkeys-docs.ts +4 -0
- package/scripts/generate-sdk-operation-inventory.ts +9 -3
- package/scripts/verify-gjc-sdk-canonicalization.ts +35 -1
- package/src/async/job-manager.ts +671 -39
- package/src/cli/accounts-cli.ts +9 -5
- package/src/cli/args.ts +17 -0
- package/src/cli/auth-broker-cli.ts +40 -12
- package/src/cli/auth-gateway-cli.ts +273 -97
- package/src/cli/config-cli.ts +2 -2
- package/src/cli/fast-help.ts +4 -0
- package/src/cli/model-presets-cli.ts +100 -0
- package/src/cli/root-flags.ts +5 -0
- package/src/cli/update-cli.ts +117 -16
- package/src/cli.ts +6 -2
- package/src/commands/auth-gateway.ts +12 -8
- package/src/commands/gc.ts +19 -0
- package/src/commands/launch.ts +86 -18
- package/src/commands/model-presets.ts +24 -0
- package/src/commands/sdk.ts +113 -21
- package/src/config/autorouting-tier-map.ts +44 -0
- package/src/config/file-lock-gc.ts +9 -4
- package/src/config/file-lock.ts +890 -99
- package/src/config/internal/model-preset-registry-test-state.ts +28 -0
- package/src/config/internal/model-preset-registry-test-support.ts +11 -0
- package/src/config/keybindings.ts +6 -2
- package/src/config/model-preset-registry.ts +2795 -0
- package/src/config/model-profile-activation.ts +115 -28
- package/src/config/model-profile-contract.ts +4 -1
- package/src/config/model-profiles.ts +56 -14
- package/src/config/model-registry.ts +1044 -122
- package/src/config/model-resolver.ts +5 -0
- package/src/config/settings-schema.ts +19 -1
- package/src/config/settings.ts +11 -1
- package/src/coordinator-mcp/model-preset.ts +32 -17
- package/src/coordinator-mcp/projection-scan.ts +592 -0
- package/src/coordinator-mcp/question-state.ts +9 -11
- package/src/coordinator-mcp/server.ts +111 -42
- package/src/coordinator-mcp/session-reaper.ts +9 -3
- package/src/crash/index-store.ts +2 -0
- package/src/crash/record-loader.ts +10 -0
- package/src/extensibility/extensions/loader.ts +0 -1
- package/src/extensibility/extensions/types.ts +2 -3
- package/src/extensibility/gjc-plugins/runtime-adapters.ts +1 -0
- package/src/gjc-runtime/empty-delete-gc.ts +301 -0
- package/src/gjc-runtime/gc-render.ts +29 -0
- package/src/gjc-runtime/gc-runtime.ts +174 -11
- package/src/gjc-runtime/launch-worktree-reservation.ts +242 -0
- package/src/gjc-runtime/managed-owner-supervisor.ts +63 -51
- package/src/gjc-runtime/session-state-lock.ts +1321 -147
- package/src/gjc-runtime/session-state-sidecar.ts +1004 -25
- package/src/gjc-runtime/tmux-owner-isolation-cli.ts +4 -7
- package/src/gjc-runtime/tmux-owner-isolation.ts +2 -2
- package/src/gjc-runtime/tmux-sessions.ts +252 -13
- package/src/hooks/skill-state.ts +6 -0
- package/src/index.ts +1 -0
- package/src/internal-urls/docs-index.generated.ts +14 -13
- package/src/internal-urls/issue-pr-protocol.ts +4 -2
- package/src/lsp/config.ts +4 -3
- package/src/lsp/path-trust.ts +12 -6
- package/src/main.ts +66 -4
- package/src/master-mode/context.ts +50 -0
- package/src/master-mode/first-request.ts +65 -0
- package/src/master-mode/snapshot.ts +205 -0
- package/src/modes/acp/acp-agent.ts +616 -161
- package/src/modes/components/footer.ts +4 -2
- package/src/modes/components/frictionless-onboarding-selector.ts +48 -2
- package/src/modes/components/jobs-overlay-model.ts +99 -16
- package/src/modes/components/model-selector.ts +158 -18
- package/src/modes/components/oauth-selector.ts +6 -1
- package/src/modes/components/settings-selector.ts +1 -0
- package/src/modes/components/status-line/model-name.ts +53 -0
- package/src/modes/components/status-line/priority-row.ts +107 -0
- package/src/modes/components/status-line/segments.ts +29 -10
- package/src/modes/components/tool-status-header.ts +151 -15
- package/src/modes/controllers/extension-ui-controller.ts +1 -1
- package/src/modes/controllers/input-controller.ts +51 -6
- package/src/modes/controllers/selector-controller.ts +191 -96
- package/src/modes/interactive-mode.ts +14 -1
- package/src/modes/jobs-observer.ts +149 -16
- package/src/modes/print-mode.ts +64 -0
- package/src/modes/runtime-init.ts +1 -1
- package/src/modes/ui-language.ts +49 -2
- package/src/modes/utils/injected-user-submission.ts +15 -1
- package/src/prompts/system/master-mode.md +28 -0
- package/src/prompts/tools/bash.md +2 -2
- package/src/prompts/tools/fold-receipt.md +3 -0
- package/src/prompts/tools/job.md +1 -1
- package/src/sdk/acp/adapter.ts +17 -2
- package/src/sdk/broker/broker.ts +1671 -34
- package/src/sdk/broker/endpoint-authority.ts +86 -0
- package/src/sdk/broker/ensure.ts +5 -0
- package/src/sdk/broker/index.ts +3 -0
- package/src/sdk/broker/lifecycle.ts +217 -46
- package/src/sdk/broker/master-capability.ts +232 -0
- package/src/sdk/broker/session-index.ts +121 -17
- package/src/sdk/broker/session-scope.ts +272 -0
- package/src/sdk/broker/spawn-authority.ts +1031 -0
- package/src/sdk/broker/spawn-substrate.ts +548 -0
- package/src/sdk/broker/state-version.ts +26 -14
- package/src/sdk/broker/transport.ts +1 -0
- package/src/sdk/broker/worktree-occupancy.ts +90 -0
- package/src/sdk/bus/chat-daemon-control.ts +5 -2
- package/src/sdk/bus/chat-daemon-runtime.ts +46 -5
- package/src/sdk/bus/index.ts +51 -4
- package/src/sdk/bus/kind-aware-reconciliation.ts +36 -6
- package/src/sdk/bus/prompt-reconciliation.ts +28 -4
- package/src/sdk/bus/slack-conversation.ts +5 -1
- package/src/sdk/bus/telegram-daemon-contract.ts +1 -1
- package/src/sdk/cli/index.ts +1 -0
- package/src/sdk/cli/master-cli.ts +259 -0
- package/src/sdk/cli/rows.ts +11 -8
- package/src/sdk/cli/session-cli.ts +276 -6
- package/src/sdk/client/client.ts +14 -8
- package/src/sdk/client/discovery.ts +3 -1
- package/src/sdk/host/control/dispatch.ts +101 -37
- package/src/sdk/host/control/index.ts +2 -0
- package/src/sdk/host/control/operations.ts +2 -0
- package/src/sdk/host/control/runtime-gate.ts +203 -11
- package/src/sdk/host/host.ts +27 -2
- package/src/sdk/host/model-pin.ts +185 -25
- package/src/sdk/host/sdk-run-capability.ts +1 -0
- package/src/sdk/host/session-runtime.test.ts +581 -43
- package/src/sdk/host/session-runtime.ts +655 -101
- package/src/sdk/lifecycle/broker-client.ts +28 -0
- package/src/sdk/lifecycle/service.ts +279 -20
- package/src/sdk/lifecycle-session.ts +10 -2
- package/src/sdk/prompt-deadline-manager.ts +16 -1
- package/src/sdk/protocol/adapter-validation.ts +27 -0
- package/src/sdk/protocol/operation-inventory.generated.json +53 -2
- package/src/sdk/protocol/operation-registry.ts +17 -4
- package/src/sdk/router/session-router.ts +294 -154
- package/src/sdk/session.ts +440 -167
- package/src/sdk/startup-capability.ts +1 -0
- package/src/session/account-inventory.ts +27 -11
- package/src/session/agent-session.ts +1292 -180
- package/src/session/blob-store.ts +15 -5
- package/src/session/credential-store-errors.ts +2 -0
- package/src/session/fold-coordinator.ts +433 -0
- package/src/session/internal/managed-session-storage.ts +153 -78
- package/src/session/sdk-run-capability-internal.ts +15 -0
- package/src/session/sdk-run-capability.ts +2 -0
- package/src/session/session-manager.ts +342 -28
- package/src/session/yield-queue.ts +24 -10
- package/src/setup/frictionless-onboarding.ts +2 -0
- package/src/setup/provider-presets.json +1 -1
- package/src/slash-commands/helpers/credential-switch.ts +6 -1
- package/src/task/executor.ts +19 -3
- package/src/telemetry/control.ts +26 -0
- package/src/telemetry/events.ts +1268 -0
- package/src/telemetry/index.ts +3 -0
- package/src/telemetry/transport.ts +87 -0
- package/src/tools/bash-interactive.ts +182 -85
- package/src/tools/bash.ts +1028 -109
- package/src/tools/gh.ts +104 -48
- package/src/tools/github-cache.ts +2 -2
- package/src/tools/index.ts +11 -5
- package/src/tools/tool-catalog.generated.ts +1 -1
- package/src/web/search/provider.ts +120 -11
- package/src/web/search/providers/anthropic.ts +89 -17
- package/src/web/search/providers/base.ts +9 -4
- package/src/web/search/providers/gemini.ts +87 -15
- package/src/web/search/providers/openai-compatible.ts +23 -8
- package/src/web/search/providers/xai.ts +98 -12
- package/src/web/search/types.ts +16 -0
|
@@ -201,12 +201,9 @@ export async function runTmuxOwnerIsolationCliFromStdin(): Promise<void> {
|
|
|
201
201
|
const stdin = await readOneBoundedJsonLine();
|
|
202
202
|
const output = stdin === null ? cliFailure("invalid_json_line") : await runTmuxOwnerIsolationCli(stdin);
|
|
203
203
|
process.stdout.write(`${output}\n`);
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
} catch {
|
|
209
|
-
process.exitCode = 1;
|
|
210
|
-
}
|
|
204
|
+
try {
|
|
205
|
+
if (JSON.parse(output).ok === false) process.exitCode = 1;
|
|
206
|
+
} catch {
|
|
207
|
+
process.exitCode = 1;
|
|
211
208
|
}
|
|
212
209
|
}
|
|
@@ -249,7 +249,7 @@ export type TmuxOwnerIsolationExecutionResult = TmuxOwnerIsolationExecutionSucce
|
|
|
249
249
|
/** Synchronous spawn boundary; callers pass argv and scoped stdin unchanged. */
|
|
250
250
|
export interface TmuxOwnerIsolationExecutionDependencies {
|
|
251
251
|
socketKey: string;
|
|
252
|
-
spawn(argv: string[], stdinLine?: string): { exitCode: number | null; stdout?: string };
|
|
252
|
+
spawn(argv: string[], stdinLine?: string): { exitCode: number | null; stdout?: string; stderr?: string };
|
|
253
253
|
probeServer(socketKey: string): TmuxServerProof;
|
|
254
254
|
/** Reads the published owner generation immediately around direct execution. */
|
|
255
255
|
isCurrentGeneration?(): boolean;
|
|
@@ -493,7 +493,7 @@ export function executeTmuxOwnerIsolationPlanSync(
|
|
|
493
493
|
return {
|
|
494
494
|
ok: false,
|
|
495
495
|
code: "scope_bootstrap_failed",
|
|
496
|
-
diagnostic:
|
|
496
|
+
diagnostic: safeDiagnostic(`planned_spawn_failed${result.stderr?.trim() ? `: ${result.stderr}` : ""}`),
|
|
497
497
|
};
|
|
498
498
|
if (execution.mode === "scoped" && !isExactScopedBootstrapSuccessReceipt(result.stdout ?? ""))
|
|
499
499
|
return {
|
|
@@ -7,6 +7,13 @@ import type { Process } from "@gajae-code/natives";
|
|
|
7
7
|
import { nativeProcessBindings } from "@gajae-code/utils/native-process";
|
|
8
8
|
import { managedSecurityFailureClassification } from "../session/internal/managed-session-storage";
|
|
9
9
|
import { readLinuxProcStartTime, readLinuxProcStartTimeSync } from "./linux-proc";
|
|
10
|
+
import {
|
|
11
|
+
MANAGED_OWNER_COMMAND_ENV,
|
|
12
|
+
MANAGED_OWNER_INCARNATION_ENV,
|
|
13
|
+
MANAGED_OWNER_REDACT_COMMAND_ENV,
|
|
14
|
+
MANAGED_OWNER_RUN_ID_ENV,
|
|
15
|
+
MANAGED_OWNER_SUPERVISOR_ARG,
|
|
16
|
+
} from "./managed-owner-supervisor";
|
|
10
17
|
import { resolveGjcTmuxBinary } from "./psmux-detect";
|
|
11
18
|
import { GJC_DIR, GJC_SESSION_PREFIX, tmuxRuntimeSessionPath } from "./session-layout";
|
|
12
19
|
import {
|
|
@@ -70,6 +77,60 @@ import {
|
|
|
70
77
|
} from "./tmux-provider-context";
|
|
71
78
|
import { buildWindowsPowerShellInnerCommand } from "./windows-powershell-command";
|
|
72
79
|
|
|
80
|
+
export interface ManagedTmuxLaunchSpec {
|
|
81
|
+
childSessionId: string;
|
|
82
|
+
cwd: string;
|
|
83
|
+
argv: readonly string[];
|
|
84
|
+
env?: Readonly<Record<string, string>>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface ManagedTmuxLaunchProof {
|
|
88
|
+
name: string;
|
|
89
|
+
nativeSessionId: string;
|
|
90
|
+
serverPid: number;
|
|
91
|
+
serverStartTime: string;
|
|
92
|
+
ownerGeneration: string;
|
|
93
|
+
sessionId: string;
|
|
94
|
+
sessionStateFile: string;
|
|
95
|
+
pid: number;
|
|
96
|
+
providerIdentity: string;
|
|
97
|
+
psmuxIncarnation?: string;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function providerIdentity(
|
|
101
|
+
provider: Pick<ProviderAuthority, "kind" | "command" | "namespace" | "executableIdentity">,
|
|
102
|
+
): string {
|
|
103
|
+
return JSON.stringify([provider.kind, provider.command, provider.namespace, provider.executableIdentity]);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function managedOwnerSupervisorArgv(): string[] {
|
|
107
|
+
const entry = process.argv[1];
|
|
108
|
+
if (!entry || !/\.(?:[cm]?[jt]s)$/.test(entry) || /\.test\.[^.]+$/.test(entry))
|
|
109
|
+
return [process.execPath, MANAGED_OWNER_SUPERVISOR_ARG];
|
|
110
|
+
return [process.execPath, entry, MANAGED_OWNER_SUPERVISOR_ARG];
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function validManagedLaunchSpec(spec: ManagedTmuxLaunchSpec, platform: NodeJS.Platform): boolean {
|
|
114
|
+
const pathModule = platform === "win32" ? path.win32 : path;
|
|
115
|
+
return (
|
|
116
|
+
typeof spec.childSessionId === "string" &&
|
|
117
|
+
spec.childSessionId.length > 0 &&
|
|
118
|
+
!spec.childSessionId.includes("\0") &&
|
|
119
|
+
typeof spec.cwd === "string" &&
|
|
120
|
+
spec.cwd.length > 0 &&
|
|
121
|
+
!spec.cwd.includes("\0") &&
|
|
122
|
+
pathModule.isAbsolute(spec.cwd) &&
|
|
123
|
+
Array.isArray(spec.argv) &&
|
|
124
|
+
spec.argv.length > 0 &&
|
|
125
|
+
spec.argv.every(value => typeof value === "string" && value.length > 0 && !value.includes("\0")) &&
|
|
126
|
+
(spec.env === undefined ||
|
|
127
|
+
Object.entries(spec.env).every(
|
|
128
|
+
([name, value]) =>
|
|
129
|
+
/^[A-Za-z_][A-Za-z0-9_]*$/.test(name) && typeof value === "string" && !value.includes("\0"),
|
|
130
|
+
))
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
73
134
|
export interface GjcTmuxSessionStatus {
|
|
74
135
|
name: string;
|
|
75
136
|
attached: boolean;
|
|
@@ -151,6 +212,8 @@ export interface ForceCloseOwnerDependencies {
|
|
|
151
212
|
listPanePids(sessionName: string, env: NodeJS.ProcessEnv): number[];
|
|
152
213
|
/** Test/runtime seam for an exact owner-exit observer; durable validation remains authoritative. */
|
|
153
214
|
waitForOwnerExitVerdict?(): Promise<OwnerVerdict>;
|
|
215
|
+
/** Broker close pin; production callers use this to reject reused session identity. */
|
|
216
|
+
expectedManagedProof?: ManagedTmuxLaunchProof;
|
|
154
217
|
}
|
|
155
218
|
const GJC_TMUX_PSMUX_INCARNATION_OPTION = "@gjc-psmux-incarnation";
|
|
156
219
|
const effectiveSessionEnvironments = new WeakMap<GjcTmuxSessionStatus, NodeJS.ProcessEnv>();
|
|
@@ -161,6 +224,7 @@ const FORCE_CLOSE_VERDICT_POLL_MS = 50;
|
|
|
161
224
|
|
|
162
225
|
export interface CreateGjcTmuxSessionOptions {
|
|
163
226
|
platform?: NodeJS.Platform;
|
|
227
|
+
launch?: ManagedTmuxLaunchSpec;
|
|
164
228
|
}
|
|
165
229
|
|
|
166
230
|
export type CreateOwnerIsolationTestDependencies = {
|
|
@@ -600,40 +664,66 @@ export function createGjcTmuxSession(
|
|
|
600
664
|
env: NodeJS.ProcessEnv = process.env,
|
|
601
665
|
options: CreateGjcTmuxSessionOptions = {},
|
|
602
666
|
): GjcTmuxSessionStatus {
|
|
667
|
+
const launch = options.launch;
|
|
603
668
|
const platform = options.platform ?? process.platform;
|
|
669
|
+
if (launch && !validManagedLaunchSpec(launch, platform)) throw new Error("gjc_tmux_managed_launch_spec_invalid");
|
|
604
670
|
const provider = resolveGjcTmuxProviderContext({ env, platform });
|
|
605
671
|
const tmuxCommand = provider.command;
|
|
606
|
-
const
|
|
607
|
-
const
|
|
608
|
-
const
|
|
672
|
+
const launchEnvironment = launch ? { ...env, GJC_TMUX_SESSION: launch.childSessionId } : env;
|
|
673
|
+
const sessionName = buildGjcTmuxSessionName(launchEnvironment);
|
|
674
|
+
const cwd = launch?.cwd ?? process.cwd();
|
|
675
|
+
const sessionId = launch?.childSessionId ?? (env[GJC_COORDINATOR_SESSION_ID_ENV]?.trim() || sessionName);
|
|
609
676
|
const stateFile =
|
|
610
|
-
env[GJC_COORDINATOR_SESSION_STATE_FILE_ENV]?.trim() ||
|
|
611
|
-
tmuxRuntimeSessionPath(
|
|
677
|
+
(!launch ? env[GJC_COORDINATOR_SESSION_STATE_FILE_ENV]?.trim() : undefined) ||
|
|
678
|
+
tmuxRuntimeSessionPath(
|
|
679
|
+
cwd,
|
|
680
|
+
launch?.childSessionId ?? (env.GJC_SESSION_ID?.trim() || sessionId),
|
|
681
|
+
buildGjcTmuxSessionSlug(sessionName),
|
|
682
|
+
);
|
|
612
683
|
const stateDir = (platform === "win32" ? path.win32 : path).dirname(stateFile);
|
|
613
684
|
const generation = crypto.randomUUID();
|
|
614
685
|
const authority = bindGjcTmuxProviderAuthority(provider, { stateDir, sessionId, generation });
|
|
615
|
-
const
|
|
686
|
+
const managedEnvironment: Record<string, string> = {
|
|
616
687
|
GJC_TMUX_LAUNCHED: "1",
|
|
617
688
|
[GJC_TMUX_OWNER_GENERATION_ENV]: generation,
|
|
618
689
|
[GJC_TMUX_OWNER_STATE_DIR_ENV]: stateDir,
|
|
619
690
|
[GJC_TMUX_OWNER_SERVER_KEY_ENV]: tmuxCommand,
|
|
620
691
|
[GJC_COORDINATOR_SESSION_ID_ENV]: sessionId,
|
|
621
692
|
[GJC_COORDINATOR_SESSION_STATE_FILE_ENV]: stateFile,
|
|
693
|
+
...(launch
|
|
694
|
+
? {
|
|
695
|
+
[MANAGED_OWNER_RUN_ID_ENV]: crypto.randomUUID(),
|
|
696
|
+
[MANAGED_OWNER_INCARNATION_ENV]: crypto.randomUUID(),
|
|
697
|
+
[MANAGED_OWNER_REDACT_COMMAND_ENV]: "1",
|
|
698
|
+
}
|
|
699
|
+
: {}),
|
|
622
700
|
};
|
|
623
|
-
const
|
|
701
|
+
const childEnvironment: Record<string, string> = { ...(launch?.env ?? {}), ...managedEnvironment };
|
|
702
|
+
const executionEnv = { ...env, ...managedEnvironment };
|
|
624
703
|
const shellQuote = (value: string): string => `'${value.replace(/'/g, `'\\''`)}'`;
|
|
625
704
|
const command =
|
|
626
705
|
platform === "win32"
|
|
627
|
-
? buildWindowsPowerShellInnerCommand({
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
706
|
+
? buildWindowsPowerShellInnerCommand({
|
|
707
|
+
command: launch ? managedOwnerSupervisorArgv() : ["gjc"],
|
|
708
|
+
environment: {
|
|
709
|
+
...childEnvironment,
|
|
710
|
+
...(launch ? { [MANAGED_OWNER_COMMAND_ENV]: JSON.stringify(launch.argv) } : {}),
|
|
711
|
+
},
|
|
712
|
+
})
|
|
713
|
+
: (() => {
|
|
714
|
+
const supervisorEnvironment = launch ? { [MANAGED_OWNER_COMMAND_ENV]: JSON.stringify(launch.argv) } : {};
|
|
715
|
+
const invocation = launch ? managedOwnerSupervisorArgv() : ["gjc"];
|
|
716
|
+
return `exec env ${Object.entries({ ...childEnvironment, ...supervisorEnvironment })
|
|
717
|
+
.map(([name, value]) => `${name}=${shellQuote(value)}`)
|
|
718
|
+
.join(" ")} ${invocation.map(shellQuote).join(" ")}`;
|
|
719
|
+
})();
|
|
631
720
|
const tmuxArgv = [
|
|
632
721
|
tmuxCommand,
|
|
633
722
|
...buildTmuxProviderCommand(provider, "new-session", [
|
|
634
723
|
"-d",
|
|
635
724
|
"-s",
|
|
636
725
|
sessionName,
|
|
726
|
+
...(launch ? ["-c", cwd] : []),
|
|
637
727
|
...(platform === "win32" ? [] : ["-P", "-F", "#{session_id}"]),
|
|
638
728
|
command,
|
|
639
729
|
]),
|
|
@@ -761,7 +851,7 @@ export function createGjcTmuxSession(
|
|
|
761
851
|
env: executionEnv,
|
|
762
852
|
})
|
|
763
853
|
: Bun.spawnSync(argv, { stdout: "pipe", stderr: "pipe", env: executionEnv });
|
|
764
|
-
return { exitCode: result.exitCode, stdout: result.stdout.toString() };
|
|
854
|
+
return { exitCode: result.exitCode, stdout: result.stdout.toString(), stderr: result.stderr.toString() };
|
|
765
855
|
} finally {
|
|
766
856
|
assertGjcTmuxStagedMutationAuthoritySync(authority);
|
|
767
857
|
}
|
|
@@ -862,6 +952,150 @@ export function createGjcTmuxSession(
|
|
|
862
952
|
: statusGjcTmuxSessionByNativeId(nativeSessionId, executionEnv);
|
|
863
953
|
}
|
|
864
954
|
|
|
955
|
+
function cleanupCreatedManagedGjcTmuxSession(
|
|
956
|
+
session: GjcTmuxSessionStatus,
|
|
957
|
+
sessionEnv: NodeJS.ProcessEnv,
|
|
958
|
+
proof: ProvenTmuxSessionIdentity | undefined,
|
|
959
|
+
): void {
|
|
960
|
+
const nativeSessionId = proof?.nativeSessionId ?? session.nativeSessionId;
|
|
961
|
+
if (!nativeSessionId || !session.ownerGeneration)
|
|
962
|
+
throw new Error(`gjc_tmux_managed_launch_cleanup_identity_unavailable:${session.name}`);
|
|
963
|
+
const tmuxCommand = session.providerAuthority?.command ?? resolveGjcTmuxCommand(sessionEnv);
|
|
964
|
+
const server = requireSafeTmuxServerForMutation(tmuxCommand, sessionEnv);
|
|
965
|
+
if (proof && (server.pid !== proof.serverPid || server.startTime !== proof.serverStartTime))
|
|
966
|
+
throw new Error("gjc_tmux_cleanup_target_changed");
|
|
967
|
+
cleanupExactCreatedTmuxSession(
|
|
968
|
+
nativeSessionId,
|
|
969
|
+
session.name,
|
|
970
|
+
tmuxCommand,
|
|
971
|
+
sessionEnv,
|
|
972
|
+
proof?.serverPid ?? server.pid,
|
|
973
|
+
proof?.serverStartTime ?? server.startTime,
|
|
974
|
+
server.pidProven,
|
|
975
|
+
session.providerAuthority,
|
|
976
|
+
session.ownerGeneration,
|
|
977
|
+
proof?.psmuxIncarnation ?? session.psmuxIncarnation,
|
|
978
|
+
);
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
/** Launches one Broker-owned child through the managed owner path and returns only re-proof inputs. */
|
|
982
|
+
export function createManagedGjcTmuxSession(
|
|
983
|
+
spec: ManagedTmuxLaunchSpec,
|
|
984
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
985
|
+
options: Omit<CreateGjcTmuxSessionOptions, "launch"> = {},
|
|
986
|
+
): ManagedTmuxLaunchProof {
|
|
987
|
+
const session = createGjcTmuxSession(env, { ...options, launch: spec });
|
|
988
|
+
const sessionEnv = session.providerAuthority ? environmentForProviderAuthority(env, session.providerAuthority) : env;
|
|
989
|
+
let proof: ProvenTmuxSessionIdentity | undefined;
|
|
990
|
+
try {
|
|
991
|
+
proof = proveGjcTmuxSessionMutationTarget(session.name, sessionEnv);
|
|
992
|
+
const status = statusGjcTmuxSession(session.name, sessionEnv);
|
|
993
|
+
if (
|
|
994
|
+
!status.sessionId ||
|
|
995
|
+
!status.sessionStateFile ||
|
|
996
|
+
!status.ownerGeneration ||
|
|
997
|
+
status.panePids.length !== 1 ||
|
|
998
|
+
proof.nativeSessionId !== status.nativeSessionId
|
|
999
|
+
)
|
|
1000
|
+
throw new Error("gjc_tmux_managed_launch_proof_unavailable");
|
|
1001
|
+
return {
|
|
1002
|
+
name: status.name,
|
|
1003
|
+
nativeSessionId: proof.nativeSessionId,
|
|
1004
|
+
serverPid: proof.serverPid,
|
|
1005
|
+
serverStartTime: proof.serverStartTime,
|
|
1006
|
+
ownerGeneration: status.ownerGeneration,
|
|
1007
|
+
sessionId: status.sessionId,
|
|
1008
|
+
sessionStateFile: status.sessionStateFile,
|
|
1009
|
+
pid: status.panePids[0]!,
|
|
1010
|
+
providerIdentity: providerIdentity(
|
|
1011
|
+
session.providerAuthority ?? resolveGjcTmuxProviderContext({ env, platform: options.platform }),
|
|
1012
|
+
),
|
|
1013
|
+
psmuxIncarnation: proof.psmuxIncarnation,
|
|
1014
|
+
};
|
|
1015
|
+
} catch (proofError) {
|
|
1016
|
+
try {
|
|
1017
|
+
cleanupCreatedManagedGjcTmuxSession(session, sessionEnv, proof);
|
|
1018
|
+
} catch (cleanupError) {
|
|
1019
|
+
throw new AggregateError([proofError, cleanupError], "gjc_tmux_managed_launch_proof_failed_cleanup_failed");
|
|
1020
|
+
}
|
|
1021
|
+
throw proofError;
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
function isManagedSessionGone(error: unknown): boolean {
|
|
1026
|
+
const message = error instanceof Error ? error.message : "";
|
|
1027
|
+
return (
|
|
1028
|
+
message.startsWith("gjc_tmux_session_not_found:") ||
|
|
1029
|
+
message.includes("no server running") ||
|
|
1030
|
+
message.includes("failed to connect to server") ||
|
|
1031
|
+
message.includes("error connecting to")
|
|
1032
|
+
);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
function managedProofAuthority(proof: ManagedTmuxLaunchProof): ProviderAuthority | null | undefined {
|
|
1036
|
+
if (!proof.psmuxIncarnation) return undefined;
|
|
1037
|
+
try {
|
|
1038
|
+
const authority = readGjcTmuxProviderAuthoritySync({
|
|
1039
|
+
stateDir: path.dirname(proof.sessionStateFile),
|
|
1040
|
+
sessionId: proof.sessionId,
|
|
1041
|
+
generation: proof.ownerGeneration,
|
|
1042
|
+
});
|
|
1043
|
+
return authority.kind === "windows-psmux" ? authority : null;
|
|
1044
|
+
} catch {
|
|
1045
|
+
return null;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
|
|
1049
|
+
/** Re-proves every mutable multiplexer identity field before a Broker effect. */
|
|
1050
|
+
export function verifyManagedGjcTmuxSession(
|
|
1051
|
+
expected: ManagedTmuxLaunchProof,
|
|
1052
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
1053
|
+
): "verified" | "mismatch" | "gone" {
|
|
1054
|
+
const authority = managedProofAuthority(expected);
|
|
1055
|
+
if (authority === null) return "mismatch";
|
|
1056
|
+
const sessionEnv = authority ? environmentForProviderAuthority(env, authority) : env;
|
|
1057
|
+
try {
|
|
1058
|
+
const session = statusGjcTmuxSession(expected.name, sessionEnv);
|
|
1059
|
+
const identity = proveGjcTmuxSessionMutationTarget(expected.name, sessionEnv);
|
|
1060
|
+
const currentProvider = authority ?? resolveGjcTmuxProviderContext({ env: sessionEnv });
|
|
1061
|
+
if (
|
|
1062
|
+
session.name !== expected.name ||
|
|
1063
|
+
session.nativeSessionId !== expected.nativeSessionId ||
|
|
1064
|
+
session.sessionId !== expected.sessionId ||
|
|
1065
|
+
session.sessionStateFile !== expected.sessionStateFile ||
|
|
1066
|
+
session.ownerGeneration !== expected.ownerGeneration ||
|
|
1067
|
+
session.panePids.length !== 1 ||
|
|
1068
|
+
session.panePids[0] !== expected.pid ||
|
|
1069
|
+
identity.nativeSessionId !== expected.nativeSessionId ||
|
|
1070
|
+
identity.serverPid !== expected.serverPid ||
|
|
1071
|
+
identity.serverStartTime !== expected.serverStartTime ||
|
|
1072
|
+
identity.psmuxIncarnation !== expected.psmuxIncarnation ||
|
|
1073
|
+
providerIdentity(currentProvider) !== expected.providerIdentity
|
|
1074
|
+
)
|
|
1075
|
+
return "mismatch";
|
|
1076
|
+
return "verified";
|
|
1077
|
+
} catch (error) {
|
|
1078
|
+
return isManagedSessionGone(error) ? "gone" : "mismatch";
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
/** Closes only an identity that passes the same exhaustive verification used for replay and reaping. */
|
|
1083
|
+
export async function forceCloseManagedGjcTmuxSession(
|
|
1084
|
+
expected: ManagedTmuxLaunchProof,
|
|
1085
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
1086
|
+
): Promise<GjcTmuxSessionStatus> {
|
|
1087
|
+
const authority = managedProofAuthority(expected);
|
|
1088
|
+
if (authority === null || verifyManagedGjcTmuxSession(expected, env) !== "verified")
|
|
1089
|
+
throw new Error(`gjc_tmux_owner_changed:${expected.name}`);
|
|
1090
|
+
return await forceCloseGjcTmuxSession(
|
|
1091
|
+
expected.name,
|
|
1092
|
+
authority ? environmentForProviderAuthority(env, authority) : env,
|
|
1093
|
+
expected.sessionId,
|
|
1094
|
+
expected.sessionStateFile,
|
|
1095
|
+
{ expectedManagedProof: expected },
|
|
1096
|
+
);
|
|
1097
|
+
}
|
|
1098
|
+
|
|
865
1099
|
function statusGjcTmuxSessionByNativeId(nativeSessionId: string, env: NodeJS.ProcessEnv): GjcTmuxSessionStatus {
|
|
866
1100
|
const name = runTmux(
|
|
867
1101
|
["display-message", "-p", "-t", normalizeExactTmuxTarget(nativeSessionId, env, "option"), "#{session_name}"],
|
|
@@ -977,6 +1211,8 @@ function cleanupExactCreatedTmuxSession(
|
|
|
977
1211
|
expectedStartTime: string,
|
|
978
1212
|
expectedPidProven?: boolean,
|
|
979
1213
|
provisionalAuthority?: ProviderAuthority,
|
|
1214
|
+
expectedOwnerGeneration?: string,
|
|
1215
|
+
expectedPsmuxIncarnation?: string,
|
|
980
1216
|
): void {
|
|
981
1217
|
const server = requireSafeTmuxServerForMutation(tmuxCommand, env);
|
|
982
1218
|
if (server.pid !== expectedPid || server.startTime !== expectedStartTime)
|
|
@@ -987,8 +1223,9 @@ function cleanupExactCreatedTmuxSession(
|
|
|
987
1223
|
{ pid: expectedPid, pidProven: expectedPidProven ?? server.pidProven },
|
|
988
1224
|
env,
|
|
989
1225
|
`kill-session -t ${tmuxCommandArgument(normalizeExactTmuxTarget(nativeSessionId, env, "session"))}`,
|
|
990
|
-
|
|
1226
|
+
expectedOwnerGeneration,
|
|
991
1227
|
provisionalAuthority,
|
|
1228
|
+
expectedPsmuxIncarnation,
|
|
992
1229
|
);
|
|
993
1230
|
}
|
|
994
1231
|
|
|
@@ -1518,6 +1755,8 @@ export async function forceCloseGjcTmuxSession(
|
|
|
1518
1755
|
expectedStateFile?: string,
|
|
1519
1756
|
deps: Partial<ForceCloseOwnerDependencies> = {},
|
|
1520
1757
|
): Promise<GjcTmuxSessionStatus> {
|
|
1758
|
+
if (deps.expectedManagedProof && verifyManagedGjcTmuxSession(deps.expectedManagedProof, env) !== "verified")
|
|
1759
|
+
throw new Error(`gjc_tmux_owner_changed:${sessionName}`);
|
|
1521
1760
|
const session = statusGjcTmuxSession(sessionName, env);
|
|
1522
1761
|
assertMutationAuthority(session);
|
|
1523
1762
|
const sessionEnv =
|
package/src/hooks/skill-state.ts
CHANGED
|
@@ -3,6 +3,7 @@ import * as path from "node:path";
|
|
|
3
3
|
import { logger } from "@gajae-code/utils";
|
|
4
4
|
import { resolveSkillScopeTrust, type SkillDiscoverySettings } from "../config/skill-settings-defaults";
|
|
5
5
|
import { detectDeepInterviewPlaintextAskLeak } from "../deep-interview/plaintext-gate-guard";
|
|
6
|
+
import { captureRepositoryBinding, publicRepositoryBinding } from "../gjc-runtime/repository-binding";
|
|
6
7
|
import { activeSnapshotPath, modeStatePath as sessionModeStatePath } from "../gjc-runtime/session-layout";
|
|
7
8
|
import { resolveGjcSessionForRead } from "../gjc-runtime/session-resolution";
|
|
8
9
|
import { ModeStateSchema, SkillActiveStateSchema } from "../gjc-runtime/state-schema";
|
|
@@ -421,6 +422,10 @@ async function seedSkillActivationState(
|
|
|
421
422
|
active_skills: [entry],
|
|
422
423
|
...(input.activeSubskills ? { active_subskills: input.activeSubskills } : {}),
|
|
423
424
|
};
|
|
425
|
+
const repositoryBinding =
|
|
426
|
+
skill === "ralplan"
|
|
427
|
+
? publicRepositoryBinding(await captureRepositoryBinding(input.cwd, { displayPath: input.cwd }))
|
|
428
|
+
: undefined;
|
|
424
429
|
const modeState: ModeState = {
|
|
425
430
|
active: true,
|
|
426
431
|
version: WORKFLOW_STATE_VERSION,
|
|
@@ -431,6 +436,7 @@ async function seedSkillActivationState(
|
|
|
431
436
|
session_id: resolvedSessionId,
|
|
432
437
|
...(input.threadId ? { thread_id: input.threadId } : {}),
|
|
433
438
|
...(input.turnId ? { turn_id: input.turnId } : {}),
|
|
439
|
+
...(repositoryBinding ? { repository_binding: repositoryBinding } : {}),
|
|
434
440
|
};
|
|
435
441
|
if (skill === "deep-interview") {
|
|
436
442
|
modeState.threshold = DEFAULT_DEEP_INTERVIEW_AMBIGUITY_THRESHOLD;
|
package/src/index.ts
CHANGED
|
@@ -45,6 +45,7 @@ export * from "./session/session-dump-format";
|
|
|
45
45
|
export * from "./session/session-manager";
|
|
46
46
|
export * from "./task/executor";
|
|
47
47
|
export type * from "./task/types";
|
|
48
|
+
export * from "./telemetry";
|
|
48
49
|
// Tools (detail types and utilities)
|
|
49
50
|
export * from "./tools";
|
|
50
51
|
export * from "./utils/git";
|