@gajae-code/coding-agent 0.12.5 → 0.12.7
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 +34 -0
- package/README.md +4 -1
- package/dist/types/async/job-manager.d.ts +36 -1
- 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-runtime.d.ts +21 -4
- 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 +2 -3
- package/dist/types/sdk/bus/index.d.ts +4 -0
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +2 -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/session/agent-session.d.ts +5 -4
- package/dist/types/session/attempt-record-store.d.ts +19 -0
- package/dist/types/session/session-manager.d.ts +1 -0
- package/dist/types/session/session-storage.d.ts +8 -0
- package/dist/types/task/receipt.d.ts +1 -0
- package/dist/types/task/types.d.ts +43 -0
- package/dist/types/tools/subagent.d.ts +15 -0
- package/dist/types/tools/todo-write.d.ts +3 -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/async/job-manager.ts +430 -46
- package/src/config/model-profiles.ts +8 -0
- package/src/config/settings-schema.ts +17 -3
- package/src/defaults/gjc/skills/ultragoal/SKILL.md +2 -0
- 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-runtime.ts +360 -156
- package/src/internal-urls/docs-index.generated.ts +4 -4
- package/src/internal-urls/local-protocol.ts +39 -18
- package/src/modes/acp/acp-agent.ts +27 -13
- 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/monitor.md +4 -4
- 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 +30 -6
- package/src/sdk/bus/index.ts +23 -6
- package/src/sdk/bus/telegram-daemon-contract.ts +2 -2
- package/src/sdk/bus/telegram-daemon.ts +283 -44
- package/src/sdk/bus/topic-registry.ts +133 -10
- package/src/sdk/session.ts +7 -6
- package/src/session/agent-session.ts +752 -339
- package/src/session/attempt-record-store.ts +106 -0
- package/src/session/internal/managed-session-scope.ts +252 -67
- package/src/session/internal/managed-session-storage.ts +1 -0
- package/src/session/session-manager.ts +7 -0
- package/src/session/session-storage.ts +146 -24
- package/src/task/index.ts +230 -19
- package/src/task/provider-retry-status.ts +4 -1
- package/src/task/receipt.ts +2 -0
- package/src/task/types.ts +10 -0
- package/src/tools/monitor.ts +7 -1
- package/src/tools/output-meta.ts +10 -2
- package/src/tools/subagent.ts +97 -75
- package/src/tools/todo-write.ts +47 -0
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
categorizeComputerChangePath,
|
|
3
|
-
|
|
4
|
-
normalizeRepoPath,
|
|
5
|
-
type UltragoalChangeCategory,
|
|
3
|
+
normalizeChangeSetPath,
|
|
6
4
|
type UltragoalChangeSet,
|
|
7
5
|
type UltragoalChangeSetPath,
|
|
8
6
|
type UltragoalChangeStatus,
|
|
@@ -15,12 +13,19 @@ export async function spawnText(
|
|
|
15
13
|
try {
|
|
16
14
|
const proc = Bun.spawn(command, { cwd: options.cwd, stdout: "pipe", stderr: "pipe" });
|
|
17
15
|
const timeout = setTimeout(() => proc.kill(), options.timeoutMs ?? 5000);
|
|
18
|
-
const [
|
|
19
|
-
new Response(proc.stdout).
|
|
20
|
-
new Response(proc.stderr).
|
|
16
|
+
const [stdoutBytes, stderrBytes, exitCode] = await Promise.all([
|
|
17
|
+
new Response(proc.stdout).arrayBuffer(),
|
|
18
|
+
new Response(proc.stderr).arrayBuffer(),
|
|
21
19
|
proc.exited,
|
|
22
20
|
]);
|
|
23
21
|
clearTimeout(timeout);
|
|
22
|
+
let stdout: string;
|
|
23
|
+
try {
|
|
24
|
+
stdout = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(stdoutBytes);
|
|
25
|
+
} catch {
|
|
26
|
+
return { ok: false, stdout: "", stderr: "command stdout was not valid UTF-8" };
|
|
27
|
+
}
|
|
28
|
+
const stderr = new TextDecoder().decode(stderrBytes);
|
|
24
29
|
return { ok: exitCode === 0, stdout, stderr };
|
|
25
30
|
} catch (error) {
|
|
26
31
|
return { ok: false, stdout: "", stderr: error instanceof Error ? error.message : String(error) };
|
|
@@ -55,61 +60,79 @@ export async function resolveGitBase(cwd: string, branch?: string): Promise<stri
|
|
|
55
60
|
}
|
|
56
61
|
if (best) return best.ref;
|
|
57
62
|
}
|
|
58
|
-
|
|
59
|
-
if (mergeBase.ok && mergeBase.stdout.trim()) return mergeBase.stdout.trim();
|
|
60
|
-
return "HEAD~1";
|
|
63
|
+
throw new Error("unable to resolve an authoritative integration base");
|
|
61
64
|
}
|
|
62
65
|
|
|
63
66
|
export function parseGitNameStatus(output: string): UltragoalChangeSetPath[] {
|
|
64
67
|
const rows: UltragoalChangeSetPath[] = [];
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
if (!trimmed) continue;
|
|
68
|
-
const parts = trimmed.split(/\s+/);
|
|
69
|
-
const statusCode = parts[0] ?? "";
|
|
68
|
+
const append = (statusCode: string, pathValue: string | undefined, oldPath: string | undefined): void => {
|
|
69
|
+
if (!pathValue) return;
|
|
70
70
|
let status: UltragoalChangeStatus = "unknown";
|
|
71
71
|
if (statusCode.startsWith("A")) status = "added";
|
|
72
72
|
else if (statusCode.startsWith("M")) status = "modified";
|
|
73
73
|
else if (statusCode.startsWith("D")) status = "deleted";
|
|
74
74
|
else if (statusCode.startsWith("R")) status = "renamed";
|
|
75
75
|
else if (statusCode.startsWith("C")) status = "copied";
|
|
76
|
-
const pathValue = status === "renamed" || status === "copied" ? parts[2] : parts[1];
|
|
77
|
-
if (!pathValue) continue;
|
|
78
|
-
const oldPath = status === "renamed" || status === "copied" ? parts[1] : undefined;
|
|
79
76
|
rows.push({
|
|
80
|
-
path:
|
|
81
|
-
oldPath: oldPath ?
|
|
77
|
+
path: normalizeChangeSetPath(pathValue),
|
|
78
|
+
oldPath: oldPath ? normalizeChangeSetPath(oldPath) : undefined,
|
|
82
79
|
status,
|
|
83
80
|
category: categorizeComputerChangePath(pathValue),
|
|
84
81
|
});
|
|
82
|
+
};
|
|
83
|
+
if (output.includes("\0")) {
|
|
84
|
+
const tokens = output.split("\0");
|
|
85
|
+
let index = 0;
|
|
86
|
+
while (index < tokens.length) {
|
|
87
|
+
const statusCode = tokens[index++] ?? "";
|
|
88
|
+
if (!statusCode) continue;
|
|
89
|
+
if (statusCode.startsWith("R") || statusCode.startsWith("C")) {
|
|
90
|
+
const oldPath = tokens[index++];
|
|
91
|
+
append(statusCode, tokens[index++], oldPath);
|
|
92
|
+
} else {
|
|
93
|
+
append(statusCode, tokens[index++], undefined);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return rows;
|
|
97
|
+
}
|
|
98
|
+
for (const line of output.split("\n")) {
|
|
99
|
+
if (!line.trim()) continue;
|
|
100
|
+
const [rawStatus = "", firstPath, secondPath] = line.split("\t");
|
|
101
|
+
const statusCode = rawStatus.trim();
|
|
102
|
+
append(
|
|
103
|
+
statusCode,
|
|
104
|
+
statusCode.startsWith("R") || statusCode.startsWith("C") ? secondPath : firstPath,
|
|
105
|
+
statusCode.startsWith("R") || statusCode.startsWith("C") ? firstPath : undefined,
|
|
106
|
+
);
|
|
85
107
|
}
|
|
86
108
|
return rows;
|
|
87
109
|
}
|
|
88
110
|
|
|
89
|
-
function
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
111
|
+
export function parseGitUntrackedPaths(output: string): UltragoalChangeSetPath[] {
|
|
112
|
+
const paths = output.includes("\0") ? output.split("\0") : output.split(/\r?\n/);
|
|
113
|
+
return paths
|
|
114
|
+
.filter(pathValue => pathValue.length > 0)
|
|
115
|
+
.map(pathValue => ({
|
|
116
|
+
path: normalizeChangeSetPath(pathValue),
|
|
117
|
+
status: "added" as UltragoalChangeStatus,
|
|
118
|
+
category: categorizeComputerChangePath(pathValue),
|
|
119
|
+
}));
|
|
96
120
|
}
|
|
97
121
|
|
|
98
|
-
function ciDevChangedPathRows(): UltragoalChangeSetPath[] {
|
|
122
|
+
export function ciDevChangedPathRows(): UltragoalChangeSetPath[] {
|
|
99
123
|
const raw = process.env.CI_DEV_CHANGED_PATHS;
|
|
100
124
|
if (!raw) return [];
|
|
101
125
|
return raw
|
|
102
126
|
.split(/\r?\n/)
|
|
103
|
-
.
|
|
104
|
-
.filter(Boolean)
|
|
127
|
+
.filter(row => row.length > 0)
|
|
105
128
|
.map(pathValue => ({
|
|
106
|
-
path:
|
|
129
|
+
path: normalizeChangeSetPath(pathValue),
|
|
107
130
|
status: "unknown" as UltragoalChangeStatus,
|
|
108
|
-
category:
|
|
131
|
+
category: categorizeComputerChangePath(pathValue),
|
|
109
132
|
}));
|
|
110
133
|
}
|
|
111
134
|
|
|
112
|
-
function mergeChangeSetPaths(groups: UltragoalChangeSetPath[][]): UltragoalChangeSetPath[] {
|
|
135
|
+
export function mergeChangeSetPaths(groups: UltragoalChangeSetPath[][]): UltragoalChangeSetPath[] {
|
|
113
136
|
const byKey = new Map<string, UltragoalChangeSetPath>();
|
|
114
137
|
for (const row of groups.flat()) byKey.set(`${row.oldPath ?? ""}\u0000${row.path}`, row);
|
|
115
138
|
return [...byKey.values()];
|
|
@@ -119,36 +142,59 @@ export async function computeCheckpointChangeSet(cwd: string): Promise<Ultragoal
|
|
|
119
142
|
const ciChangedPaths = ciDevChangedPathRows();
|
|
120
143
|
const inGit = await spawnText(["git", "rev-parse", "--is-inside-work-tree"], { cwd, timeoutMs: 3000 });
|
|
121
144
|
if (!inGit.ok || inGit.stdout.trim() !== "true") {
|
|
122
|
-
if (ciChangedPaths.length === 0)
|
|
145
|
+
if (ciChangedPaths.length === 0)
|
|
146
|
+
return { source: "checkpoint-git", paths: [], captureIncomplete: true, trusted: true };
|
|
123
147
|
return { source: "checkpoint-git", paths: ciChangedPaths, trusted: true };
|
|
124
148
|
}
|
|
125
149
|
const baseRef = await resolveGitBase(cwd);
|
|
126
150
|
const base = baseRef;
|
|
127
151
|
const mergeBase = await spawnText(["git", "merge-base", "HEAD", baseRef], { cwd, timeoutMs: 3000 });
|
|
128
|
-
const [committed, unstaged, staged, stat, committedDiff, unstagedDiff, stagedDiff] = await Promise.all([
|
|
129
|
-
spawnText(["git", "diff", "--name-status", `${base}...HEAD`], { cwd, timeoutMs: 5000 }),
|
|
130
|
-
spawnText(["git", "diff", "--name-status"], { cwd, timeoutMs: 5000 }),
|
|
131
|
-
spawnText(["git", "diff", "--cached", "--name-status"], { cwd, timeoutMs: 5000 }),
|
|
152
|
+
const [committed, unstaged, staged, untracked, stat, committedDiff, unstagedDiff, stagedDiff] = await Promise.all([
|
|
153
|
+
spawnText(["git", "diff", "--name-status", "-z", `${base}...HEAD`], { cwd, timeoutMs: 5000 }),
|
|
154
|
+
spawnText(["git", "diff", "--name-status", "-z"], { cwd, timeoutMs: 5000 }),
|
|
155
|
+
spawnText(["git", "diff", "--cached", "--name-status", "-z"], { cwd, timeoutMs: 5000 }),
|
|
156
|
+
spawnText(["git", "ls-files", "--others", "--exclude-standard", "-z"], { cwd, timeoutMs: 5000 }),
|
|
132
157
|
spawnText(["git", "diff", "--stat", `${base}...HEAD`], { cwd, timeoutMs: 5000 }),
|
|
133
158
|
spawnText(["git", "diff", `${base}...HEAD`], { cwd, timeoutMs: 5000 }),
|
|
134
159
|
spawnText(["git", "diff"], { cwd, timeoutMs: 5000 }),
|
|
135
160
|
spawnText(["git", "diff", "--cached"], { cwd, timeoutMs: 5000 }),
|
|
136
161
|
]);
|
|
137
|
-
if (!committed.ok
|
|
138
|
-
|
|
162
|
+
if (!committed.ok || !unstaged.ok || !staged.ok || !untracked.ok) {
|
|
163
|
+
const paths = mergeChangeSetPaths([
|
|
164
|
+
committed.ok ? parseGitNameStatus(committed.stdout) : [],
|
|
165
|
+
unstaged.ok ? parseGitNameStatus(unstaged.stdout) : [],
|
|
166
|
+
staged.ok ? parseGitNameStatus(staged.stdout) : [],
|
|
167
|
+
untracked.ok ? parseGitUntrackedPaths(untracked.stdout) : [],
|
|
168
|
+
ciChangedPaths,
|
|
169
|
+
]);
|
|
170
|
+
return {
|
|
171
|
+
source: "checkpoint-git",
|
|
172
|
+
baseRef,
|
|
173
|
+
mergeBase: mergeBase.ok && mergeBase.stdout.trim() ? mergeBase.stdout.trim() : undefined,
|
|
174
|
+
headRef: "HEAD",
|
|
175
|
+
paths,
|
|
176
|
+
captureIncomplete: true,
|
|
177
|
+
trusted: true,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
const paths = mergeChangeSetPaths([
|
|
139
181
|
parseGitNameStatus(committed.stdout),
|
|
140
182
|
parseGitNameStatus(unstaged.stdout),
|
|
141
183
|
parseGitNameStatus(staged.stdout),
|
|
184
|
+
parseGitUntrackedPaths(untracked.stdout),
|
|
185
|
+
ciChangedPaths,
|
|
142
186
|
]);
|
|
143
|
-
const paths = gitPaths.length > 0 ? gitPaths : ciChangedPaths;
|
|
144
187
|
return {
|
|
145
188
|
source: "checkpoint-git",
|
|
146
189
|
baseRef,
|
|
147
190
|
mergeBase: mergeBase.ok && mergeBase.stdout.trim() ? mergeBase.stdout.trim() : undefined,
|
|
148
191
|
headRef: "HEAD",
|
|
149
192
|
paths,
|
|
150
|
-
rawDiffStat: stat.stdout,
|
|
151
|
-
rawDiff:
|
|
193
|
+
rawDiffStat: stat.ok ? stat.stdout : undefined,
|
|
194
|
+
rawDiff:
|
|
195
|
+
committedDiff.ok && unstagedDiff.ok && stagedDiff.ok
|
|
196
|
+
? [committedDiff.stdout, unstagedDiff.stdout, stagedDiff.stdout].filter(Boolean).join("\n")
|
|
197
|
+
: undefined,
|
|
152
198
|
trusted: true,
|
|
153
199
|
};
|
|
154
200
|
}
|
|
@@ -159,8 +205,8 @@ export function parseUnifiedDiffPaths(diff: string): UltragoalChangeSetPath[] {
|
|
|
159
205
|
if (!line.startsWith("diff --git ")) continue;
|
|
160
206
|
const match = /^diff --git a\/(.+?) b\/(.+)$/.exec(line);
|
|
161
207
|
if (!match) continue;
|
|
162
|
-
const oldPath =
|
|
163
|
-
const newPath =
|
|
208
|
+
const oldPath = normalizeChangeSetPath(match[1]!);
|
|
209
|
+
const newPath = normalizeChangeSetPath(match[2]!);
|
|
164
210
|
paths.push({
|
|
165
211
|
path: newPath,
|
|
166
212
|
oldPath: oldPath === newPath ? undefined : oldPath,
|
|
@@ -338,6 +338,13 @@ export function validateReceiptFreshBase(input: {
|
|
|
338
338
|
message: `Ultragoal ${input.goal.id} receipt ledger event is missing.`,
|
|
339
339
|
goalId: input.goal.id,
|
|
340
340
|
};
|
|
341
|
+
const eventReceipt = event.completionVerification as UltragoalCompletionVerification | undefined;
|
|
342
|
+
if (!eventReceipt || hashStructuredValue(eventReceipt) !== hashStructuredValue(input.receipt))
|
|
343
|
+
return {
|
|
344
|
+
state: "active_stale_receipt",
|
|
345
|
+
message: `Ultragoal ${input.goal.id} receipt does not match its ledger event receipt.`,
|
|
346
|
+
goalId: input.goal.id,
|
|
347
|
+
};
|
|
341
348
|
const generation = computeUltragoalPlanGeneration({
|
|
342
349
|
plan: input.plan,
|
|
343
350
|
ledger: input.ledger,
|