@gajae-code/coding-agent 0.12.5 → 0.12.6
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 +4 -1
- package/dist/types/eval/backend.d.ts +2 -2
- package/dist/types/exec/bash-executor.d.ts +10 -8
- package/dist/types/extensibility/extensions/runner.d.ts +9 -7
- package/dist/types/gjc-runtime/launch-tmux.d.ts +22 -3
- package/dist/types/gjc-runtime/psmux-detect.d.ts +3 -0
- package/dist/types/gjc-runtime/team-launch.d.ts +3 -1
- package/dist/types/gjc-runtime/team-runtime.d.ts +14 -2
- package/dist/types/gjc-runtime/team-store.d.ts +0 -4
- package/dist/types/gjc-runtime/team-workers.d.ts +5 -0
- package/dist/types/gjc-runtime/tmux-common.d.ts +1 -0
- package/dist/types/gjc-runtime/tmux-provider-context.d.ts +57 -0
- package/dist/types/gjc-runtime/tmux-sessions.d.ts +8 -1
- package/dist/types/gjc-runtime/ultragoal-change-set.d.ts +3 -0
- package/dist/types/gjc-runtime/ultragoal-review-source.d.ts +83 -0
- package/dist/types/gjc-runtime/ultragoal-runtime.d.ts +57 -4
- package/dist/types/internal-urls/registry-helpers.d.ts +18 -0
- package/dist/types/modes/components/gjc-bundle-settings.d.ts +1 -0
- package/dist/types/modes/components/plugin-settings.d.ts +2 -0
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/sdk/broker/broker.d.ts +18 -0
- package/dist/types/sdk/broker/lifecycle-ledger.d.ts +13 -0
- package/dist/types/sdk/broker/lifecycle.d.ts +1 -0
- package/dist/types/sdk/bus/chat-daemon-control.d.ts +4 -3
- package/dist/types/sdk/bus/index.d.ts +4 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +4 -2
- package/dist/types/sdk/bus/telegram-daemon.d.ts +25 -3
- package/dist/types/sdk/bus/topic-registry.d.ts +63 -3
- package/dist/types/sdk/host/host.d.ts +23 -2
- package/dist/types/sdk/host/reverse-leases.d.ts +7 -4
- package/dist/types/session/agent-session.d.ts +5 -4
- package/dist/types/session/artifacts.d.ts +8 -5
- package/dist/types/session/attempt-record-store.d.ts +19 -0
- package/dist/types/session/client-bridge.d.ts +14 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +5 -2
- package/dist/types/session/messages.d.ts +4 -1
- package/dist/types/session/session-manager.d.ts +6 -4
- package/dist/types/session/session-storage.d.ts +8 -0
- package/dist/types/session/streaming-output.d.ts +32 -0
- package/dist/types/task/receipt.d.ts +2 -0
- package/dist/types/task/types.d.ts +178 -0
- package/dist/types/tools/bash.d.ts +1 -1
- package/dist/types/tools/fetch.d.ts +3 -0
- package/dist/types/tools/output-meta.d.ts +37 -5
- package/dist/types/tools/tool-result.d.ts +1 -0
- package/dist/types/utils/artifact-id.d.ts +2 -0
- package/package.json +8 -8
- package/scripts/capture-sticky-viewport-showcase.ts +131 -5
- package/scripts/verify-gjc-sdk-canonicalization.ts +128 -183
- package/scripts/verify-sticky-viewport-showcase.ts +620 -93
- package/src/config/model-profiles.ts +8 -0
- package/src/config/settings-schema.ts +17 -3
- package/src/cursor.ts +20 -13
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +5 -2
- package/src/eval/backend.ts +2 -2
- package/src/exec/bash-executor.ts +425 -151
- package/src/extensibility/extensions/runner.ts +80 -6
- package/src/extensibility/extensions/wrapper.ts +22 -15
- package/src/extensibility/runtime-skill-discovery.ts +4 -6
- package/src/gjc-runtime/launch-tmux.ts +309 -293
- package/src/gjc-runtime/managed-owner-supervisor.ts +6 -2
- package/src/gjc-runtime/psmux-detect.ts +52 -6
- package/src/gjc-runtime/team-launch.ts +50 -2
- package/src/gjc-runtime/team-runtime.ts +716 -251
- package/src/gjc-runtime/team-store.ts +25 -7
- package/src/gjc-runtime/team-workers.ts +161 -1
- package/src/gjc-runtime/tmux-common.ts +16 -4
- package/src/gjc-runtime/tmux-gc.ts +37 -5
- package/src/gjc-runtime/tmux-owner-isolation.ts +2 -0
- package/src/gjc-runtime/tmux-provider-context.ts +451 -0
- package/src/gjc-runtime/tmux-sessions.ts +409 -156
- package/src/gjc-runtime/ultragoal-change-set.ts +90 -44
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +7 -0
- package/src/gjc-runtime/ultragoal-review-source.ts +378 -0
- package/src/gjc-runtime/ultragoal-runtime.ts +640 -159
- package/src/gjc-runtime/workflow-manifest.generated.json +40 -1
- package/src/gjc-runtime/workflow-manifest.ts +12 -0
- package/src/internal-urls/agent-protocol.ts +98 -38
- package/src/internal-urls/artifact-protocol.ts +28 -17
- package/src/internal-urls/docs-index.generated.ts +5 -5
- package/src/internal-urls/local-protocol.ts +39 -18
- package/src/internal-urls/registry-helpers.ts +62 -0
- package/src/modes/acp/acp-agent.ts +51 -13
- package/src/modes/acp/acp-client-bridge.ts +154 -11
- package/src/modes/components/gjc-bundle-settings.ts +2 -0
- package/src/modes/components/plugin-settings.ts +5 -0
- package/src/modes/components/settings-selector.ts +4 -0
- package/src/modes/controllers/selector-controller.ts +1 -0
- package/src/prompts/tools/bash.md +2 -2
- package/src/prompts/tools/monitor.md +4 -4
- package/src/sdk/acp/adapter.ts +200 -9
- package/src/sdk/broker/broker.ts +93 -10
- package/src/sdk/broker/lifecycle-ledger.ts +227 -11
- package/src/sdk/broker/lifecycle.ts +691 -92
- package/src/sdk/bus/chat-daemon-control.ts +32 -6
- package/src/sdk/bus/index.ts +347 -14
- package/src/sdk/bus/telegram-daemon-contract.ts +4 -2
- package/src/sdk/bus/telegram-daemon.ts +283 -44
- package/src/sdk/bus/topic-registry.ts +133 -10
- package/src/sdk/host/host.ts +187 -9
- package/src/sdk/host/reverse-leases.ts +249 -42
- package/src/sdk/session.ts +7 -6
- package/src/session/agent-session.ts +930 -354
- package/src/session/artifacts.ts +211 -74
- package/src/session/attempt-record-store.ts +106 -0
- package/src/session/client-bridge.ts +15 -0
- package/src/session/internal/managed-session-scope.ts +252 -67
- package/src/session/internal/managed-session-storage.ts +105 -5
- package/src/session/messages.ts +32 -7
- package/src/session/session-manager.ts +19 -21
- package/src/session/session-storage.ts +146 -24
- package/src/session/streaming-output.ts +198 -40
- package/src/task/index.ts +45 -0
- package/src/task/provider-retry-status.ts +4 -1
- package/src/task/receipt.ts +4 -0
- package/src/task/render.ts +30 -0
- package/src/task/types.ts +34 -0
- package/src/tools/bash.ts +818 -239
- package/src/tools/eval.ts +99 -4
- package/src/tools/fetch.ts +77 -15
- package/src/tools/find.ts +7 -3
- package/src/tools/monitor.ts +7 -1
- package/src/tools/output-meta.ts +706 -116
- package/src/tools/search.ts +9 -4
- package/src/tools/tool-result.ts +1 -0
- package/src/utils/artifact-id.ts +6 -0
|
@@ -92,6 +92,10 @@ function lifecycleRoot(): {
|
|
|
92
92
|
function commandDigest(command: readonly string[]): string {
|
|
93
93
|
return crypto.createHash("sha256").update(JSON.stringify(command)).digest("hex");
|
|
94
94
|
}
|
|
95
|
+
async function managedOwnerProcessProvenance(pid: number): Promise<string | null> {
|
|
96
|
+
if (process.platform === "linux") return await readLinuxProcStartTime(pid);
|
|
97
|
+
return Process.fromPid(pid)?.incarnation ?? null;
|
|
98
|
+
}
|
|
95
99
|
|
|
96
100
|
async function writeDurableExclusive(file: string, value: object): Promise<void> {
|
|
97
101
|
const handle = await fs.open(file, "wx", 0o600);
|
|
@@ -132,7 +136,7 @@ export async function runManagedOwnerSupervisor(): Promise<void> {
|
|
|
132
136
|
};
|
|
133
137
|
process.removeAllListeners("SIGTERM");
|
|
134
138
|
process.on("SIGTERM", captureEarlySigterm);
|
|
135
|
-
const supervisorStartTime = await
|
|
139
|
+
const supervisorStartTime = await managedOwnerProcessProvenance(process.pid);
|
|
136
140
|
if (!supervisorStartTime) throw new Error("managed_owner_supervisor_start_time_unavailable");
|
|
137
141
|
await fs.mkdir(root, { recursive: true, mode: 0o700 });
|
|
138
142
|
const childToken = crypto.randomUUID();
|
|
@@ -157,7 +161,7 @@ export async function runManagedOwnerSupervisor(): Promise<void> {
|
|
|
157
161
|
stderr: "inherit",
|
|
158
162
|
env: { ...process.env, [MANAGED_OWNER_CHILD_TOKEN_ENV]: childToken },
|
|
159
163
|
});
|
|
160
|
-
const childStartTime = await
|
|
164
|
+
const childStartTime = await managedOwnerProcessProvenance(child.pid);
|
|
161
165
|
if (!childStartTime) throw new Error("managed_owner_child_start_time_unavailable");
|
|
162
166
|
const childProcess = Process.fromPid(child.pid);
|
|
163
167
|
if (!childProcess) throw new Error("managed_owner_child_reference_unavailable");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import * as fs from "node:fs";
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -62,8 +63,32 @@ export type ExecutableIdentityResolver = (path: string) => string | null;
|
|
|
62
63
|
const DEFAULT_EXECUTABLE_IDENTITY_RESOLVER: ExecutableIdentityResolver = executablePath => {
|
|
63
64
|
try {
|
|
64
65
|
const realPath = fs.realpathSync.native(executablePath);
|
|
65
|
-
const
|
|
66
|
-
|
|
66
|
+
const fd = fs.openSync(realPath, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW);
|
|
67
|
+
try {
|
|
68
|
+
const before = fs.fstatSync(fd, { bigint: true });
|
|
69
|
+
if (!before.isFile() || before.dev === 0n || before.ino === 0n) return null;
|
|
70
|
+
const bytes = fs.readFileSync(fd);
|
|
71
|
+
const after = fs.fstatSync(fd, { bigint: true });
|
|
72
|
+
const named = fs.lstatSync(realPath, { bigint: true });
|
|
73
|
+
if (
|
|
74
|
+
!named.isFile() ||
|
|
75
|
+
named.isSymbolicLink() ||
|
|
76
|
+
after.dev !== before.dev ||
|
|
77
|
+
after.ino !== before.ino ||
|
|
78
|
+
after.size !== before.size ||
|
|
79
|
+
after.mtimeNs !== before.mtimeNs ||
|
|
80
|
+
after.ctimeNs !== before.ctimeNs ||
|
|
81
|
+
named.dev !== before.dev ||
|
|
82
|
+
named.ino !== before.ino ||
|
|
83
|
+
named.size !== before.size ||
|
|
84
|
+
named.mtimeNs !== before.mtimeNs ||
|
|
85
|
+
named.ctimeNs !== before.ctimeNs
|
|
86
|
+
)
|
|
87
|
+
return null;
|
|
88
|
+
return `${before.dev}:${before.ino}:${before.size}:${before.mtimeNs}:${before.ctimeNs}:${createHash("sha256").update(bytes).digest("hex")}`;
|
|
89
|
+
} finally {
|
|
90
|
+
fs.closeSync(fd);
|
|
91
|
+
}
|
|
67
92
|
} catch {
|
|
68
93
|
return null;
|
|
69
94
|
}
|
|
@@ -152,6 +177,14 @@ function isNamedPsmuxCommand(command: string): boolean {
|
|
|
152
177
|
function resolveBinaryPath(candidate: string): string | null {
|
|
153
178
|
return activeBinaryResolver(candidate);
|
|
154
179
|
}
|
|
180
|
+
/** Resolve through the same identity-aware seams used by Windows alias detection. */
|
|
181
|
+
export function resolveGjcTmuxExecutablePath(command: string): string | null {
|
|
182
|
+
return resolveBinaryPath(command);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
export function resolveGjcTmuxExecutableIdentity(executablePath: string): string | null {
|
|
186
|
+
return activeExecutableIdentityResolver(executablePath);
|
|
187
|
+
}
|
|
155
188
|
|
|
156
189
|
function detectPsmuxForCommand(command: string, runner: PsmuxSpawnRunner): boolean {
|
|
157
190
|
const resolved = resolveBinaryPath(command);
|
|
@@ -291,11 +324,24 @@ export function resolveGjcTmuxBinary(options: ResolveGjcTmuxBinaryOptions = {}):
|
|
|
291
324
|
return { command: explicit, isPsmux, viaExplicitOverride: true };
|
|
292
325
|
}
|
|
293
326
|
if (platform === "win32") {
|
|
327
|
+
const candidates: Array<{ command: string; identity: string }> = [];
|
|
294
328
|
for (const candidate of PSMUX_BINARY_NAMES) {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
329
|
+
const executablePath = resolveBinaryPath(candidate);
|
|
330
|
+
if (!executablePath) continue;
|
|
331
|
+
const isPsmuxAlias = candidate !== "tmux" || detectPsmuxForCommand(candidate, runner);
|
|
332
|
+
if (!isPsmuxAlias) continue;
|
|
333
|
+
const identity = activeExecutableIdentityResolver(executablePath);
|
|
334
|
+
if (!identity)
|
|
335
|
+
throw new Error(`gjc_tmux_provider_ambiguous: Windows ${candidate} executable identity is unavailable`);
|
|
336
|
+
candidates.push({ command: candidate, identity });
|
|
337
|
+
}
|
|
338
|
+
if (candidates.length > 0) {
|
|
339
|
+
const identities = new Set(candidates.map(candidate => candidate.identity));
|
|
340
|
+
if (identities.size !== 1)
|
|
341
|
+
throw new Error("gjc_tmux_provider_ambiguous: Windows psmux aliases resolve to different executables");
|
|
342
|
+
// The order is the canonical provider spelling, then its compatibility
|
|
343
|
+
// aliases. Identity equality above makes PATH-order alias selection safe.
|
|
344
|
+
return { command: candidates[0]!.command, isPsmux: true, viaExplicitOverride: false };
|
|
299
345
|
}
|
|
300
346
|
}
|
|
301
347
|
const tmuxPath = resolveBinaryPath("tmux");
|
|
@@ -2,6 +2,11 @@ import * as fs from "node:fs/promises";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { SPAWN_PROVENANCE_ENV } from "../sdk/bus/config";
|
|
4
4
|
import { resolveSessionIdFromSources } from "./session-resolution";
|
|
5
|
+
import {
|
|
6
|
+
GJC_COORDINATOR_SESSION_ID_ENV,
|
|
7
|
+
GJC_TMUX_OWNER_GENERATION_ENV,
|
|
8
|
+
GJC_TMUX_OWNER_STATE_DIR_ENV,
|
|
9
|
+
} from "./session-state-sidecar";
|
|
5
10
|
import type {
|
|
6
11
|
GjcTeamConfig,
|
|
7
12
|
GjcTeamSnapshot,
|
|
@@ -13,6 +18,12 @@ import type {
|
|
|
13
18
|
GjcTeamWorktreeMode,
|
|
14
19
|
} from "./team-runtime";
|
|
15
20
|
import { createInitialGjcTeamWorkerMemoryGuardLedger, workerMemoryGuardLedgerPath } from "./team-worker-memory-guard";
|
|
21
|
+
import {
|
|
22
|
+
bindGjcTmuxProviderAuthority,
|
|
23
|
+
type ProviderAuthority,
|
|
24
|
+
readGjcTmuxProviderAuthoritySync,
|
|
25
|
+
resolveGjcTmuxProviderContext,
|
|
26
|
+
} from "./tmux-provider-context";
|
|
16
27
|
|
|
17
28
|
/** Launch-specific option wiring kept separate from runtime dispatch. */
|
|
18
29
|
export function withTeamLaunchTransport(
|
|
@@ -97,6 +108,7 @@ export function buildWorkerCommand(
|
|
|
97
108
|
interface GjcTmuxBinary {
|
|
98
109
|
command: string;
|
|
99
110
|
isPsmux: boolean;
|
|
111
|
+
viaExplicitOverride: boolean;
|
|
100
112
|
}
|
|
101
113
|
|
|
102
114
|
interface GjcTmuxLeaderContext {
|
|
@@ -115,7 +127,11 @@ export interface GjcTeamLaunchRuntime {
|
|
|
115
127
|
teamDir(stateRoot: string, teamName: string): string;
|
|
116
128
|
resolveDefaultWorktreeMode(mode?: GjcTeamWorktreeMode): GjcTeamWorktreeMode;
|
|
117
129
|
resolveTmuxBinary(input: { env: NodeJS.ProcessEnv; platform: NodeJS.Platform }): GjcTmuxBinary;
|
|
118
|
-
readTmuxLeaderContext(
|
|
130
|
+
readTmuxLeaderContext(
|
|
131
|
+
tmuxCommand: string,
|
|
132
|
+
env: NodeJS.ProcessEnv,
|
|
133
|
+
authority: ProviderAuthority,
|
|
134
|
+
): GjcTmuxLeaderContext;
|
|
119
135
|
buildWorkers(workerCount: number, agentType: string, stateRoot: string): GjcTeamWorker[];
|
|
120
136
|
buildInitialTasks(task: string, workers: GjcTeamWorker[]): GjcTeamTask[];
|
|
121
137
|
ensureWorkerWorktree(
|
|
@@ -217,9 +233,32 @@ export async function startGjcTeamLaunch(
|
|
|
217
233
|
const platform = options.platform ?? process.platform;
|
|
218
234
|
const tmuxBinary = runtime.resolveTmuxBinary({ env, platform });
|
|
219
235
|
const tmuxCommand = tmuxBinary.command;
|
|
236
|
+
const tmuxProviderGeneration =
|
|
237
|
+
tmuxBinary.isPsmux && platform === "win32" ? env[GJC_TMUX_OWNER_GENERATION_ENV]?.trim() : undefined;
|
|
238
|
+
const tmuxProvider = resolveGjcTmuxProviderContext({ binary: tmuxBinary, env, platform });
|
|
239
|
+
if (tmuxProvider.binary.command !== tmuxCommand) throw new Error("gjc_team_tmux_provider_command_mismatch");
|
|
240
|
+
const launchSessionId =
|
|
241
|
+
env[GJC_COORDINATOR_SESSION_ID_ENV]?.trim() || env.GJC_SESSION_ID?.trim() || gjcSessionId?.trim();
|
|
242
|
+
const launchStateDir = env[GJC_TMUX_OWNER_STATE_DIR_ENV]?.trim();
|
|
243
|
+
const tmuxAuthority =
|
|
244
|
+
tmuxBinary.isPsmux && platform === "win32" && !options.dryRun
|
|
245
|
+
? launchSessionId && launchStateDir && tmuxProviderGeneration
|
|
246
|
+
? readGjcTmuxProviderAuthoritySync({
|
|
247
|
+
stateDir: launchStateDir,
|
|
248
|
+
sessionId: launchSessionId,
|
|
249
|
+
generation: tmuxProviderGeneration,
|
|
250
|
+
})
|
|
251
|
+
: (() => {
|
|
252
|
+
throw new Error("gjc_team_tmux_provider_authority_unavailable");
|
|
253
|
+
})()
|
|
254
|
+
: bindGjcTmuxProviderAuthority(tmuxProvider, {
|
|
255
|
+
stateDir: stateRoot,
|
|
256
|
+
sessionId: teamName,
|
|
257
|
+
generation: "native-tmux",
|
|
258
|
+
});
|
|
220
259
|
const tmuxContext = options.dryRun
|
|
221
260
|
? { sessionName: "dry-run", windowIndex: "0", leaderPaneId: "%dry-run-leader", target: "dry-run:0" }
|
|
222
|
-
: runtime.readTmuxLeaderContext(tmuxCommand, env);
|
|
261
|
+
: runtime.readTmuxLeaderContext(tmuxCommand, env, tmuxAuthority);
|
|
223
262
|
const initialWorkers = runtime.buildWorkers(options.workerCount, options.agentType, stateRoot);
|
|
224
263
|
const initialTasks = runtime.buildInitialTasks(options.task, initialWorkers);
|
|
225
264
|
const workers: GjcTeamWorker[] = [];
|
|
@@ -267,9 +306,17 @@ export async function startGjcTeamLaunch(
|
|
|
267
306
|
...(gjcSessionId ? { gjc_session_id: gjcSessionId } : {}),
|
|
268
307
|
worker_cli_plan: workerCliPlan,
|
|
269
308
|
tmux_command: tmuxCommand,
|
|
309
|
+
platform,
|
|
270
310
|
tmux_session: tmuxContext.sessionName,
|
|
271
311
|
tmux_session_name: tmuxContext.sessionName,
|
|
272
312
|
tmux_target: tmuxContext.target,
|
|
313
|
+
...(tmuxProviderGeneration
|
|
314
|
+
? {
|
|
315
|
+
tmux_provider_generation: tmuxProviderGeneration,
|
|
316
|
+
tmux_provider_state_dir: launchStateDir!,
|
|
317
|
+
tmux_provider_session_id: launchSessionId!,
|
|
318
|
+
}
|
|
319
|
+
: {}),
|
|
273
320
|
workspace_mode: worktreeMode.enabled ? "worktree" : "direct",
|
|
274
321
|
dry_run: options.dryRun ?? false,
|
|
275
322
|
leader: {
|
|
@@ -296,6 +343,7 @@ export async function startGjcTeamLaunch(
|
|
|
296
343
|
worker_command: config.worker_command,
|
|
297
344
|
worker_cli_plan: config.worker_cli_plan,
|
|
298
345
|
tmux_command: config.tmux_command,
|
|
346
|
+
tmux_provider_generation: config.tmux_provider_generation,
|
|
299
347
|
leader: config.leader,
|
|
300
348
|
workers: config.workers,
|
|
301
349
|
workspace_mode: config.workspace_mode,
|