squadrant 0.13.2 → 0.13.4
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/dist/index.js +77 -14
- package/dist/index.js.map +1 -1
- package/dist/squadrantd.js +70 -7
- package/dist/squadrantd.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2569,7 +2569,12 @@ async function runCrewSpawn(input, config, deps) {
|
|
|
2569
2569
|
task: input.task,
|
|
2570
2570
|
name
|
|
2571
2571
|
});
|
|
2572
|
-
|
|
2572
|
+
let hooksInstalled = false;
|
|
2573
|
+
try {
|
|
2574
|
+
deps.writeSettingsLocal(spawnCwd);
|
|
2575
|
+
hooksInstalled = true;
|
|
2576
|
+
} catch {
|
|
2577
|
+
}
|
|
2573
2578
|
const cliCommand2 = agent.buildCommand({
|
|
2574
2579
|
prompt: input.task,
|
|
2575
2580
|
workdir: spawnCwd,
|
|
@@ -2593,7 +2598,7 @@ ${buildCompletionProtocol(rec.id, input.project)}`, preLaunchScreen);
|
|
|
2593
2598
|
if (!claudeResult.delivered) {
|
|
2594
2599
|
process.stderr.write(`\u26A0\uFE0F First turn not delivered for crew '${name}' \u2014 use 'squadrant crew send ${input.project} ${name}' to re-send the task.
|
|
2595
2600
|
`);
|
|
2596
|
-
} else {
|
|
2601
|
+
} else if (!hooksInstalled) {
|
|
2597
2602
|
await deps.emitEvent?.(input.project, { type: "task.first-turn.confirmed", id: rec.id });
|
|
2598
2603
|
}
|
|
2599
2604
|
return { ...pane2, title: title2 };
|
|
@@ -2900,7 +2905,28 @@ function parseDraftFromScreen(screen) {
|
|
|
2900
2905
|
}
|
|
2901
2906
|
return "";
|
|
2902
2907
|
}
|
|
2903
|
-
function
|
|
2908
|
+
function hasCCInputBox(screen) {
|
|
2909
|
+
if (!screen)
|
|
2910
|
+
return false;
|
|
2911
|
+
const lines = screen.split(/\r?\n/);
|
|
2912
|
+
const HR_RE = /^\s*─{10,}\s*$/;
|
|
2913
|
+
let bottomHR = -1;
|
|
2914
|
+
let topHR = -1;
|
|
2915
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
2916
|
+
if (HR_RE.test(lines[i])) {
|
|
2917
|
+
if (bottomHR === -1)
|
|
2918
|
+
bottomHR = i;
|
|
2919
|
+
else {
|
|
2920
|
+
topHR = i;
|
|
2921
|
+
break;
|
|
2922
|
+
}
|
|
2923
|
+
}
|
|
2924
|
+
}
|
|
2925
|
+
if (topHR === -1)
|
|
2926
|
+
return false;
|
|
2927
|
+
return lines.slice(topHR + 1, bottomHR).some((l) => /[>❯]/.test(l));
|
|
2928
|
+
}
|
|
2929
|
+
function readInputBoxRaw(screen, opts) {
|
|
2904
2930
|
if (!screen)
|
|
2905
2931
|
return null;
|
|
2906
2932
|
const lines = screen.split(/\r?\n/);
|
|
@@ -2926,7 +2952,8 @@ function readInputBoxRaw(screen) {
|
|
|
2926
2952
|
s = s.replace(/\s*[▌█▔▎▏]+\s*$/, "");
|
|
2927
2953
|
parts.push(s);
|
|
2928
2954
|
}
|
|
2929
|
-
|
|
2955
|
+
const joined = parts.join("");
|
|
2956
|
+
return opts?.trim === false ? joined : joined.replace(/\s+$/, "");
|
|
2930
2957
|
}
|
|
2931
2958
|
function classifyStartupSurface(screen) {
|
|
2932
2959
|
if (CC_WORKING_RE.test(screen))
|
|
@@ -2947,6 +2974,19 @@ function classifySendOutcome(payload, postBox) {
|
|
|
2947
2974
|
return "stuck";
|
|
2948
2975
|
return "unknown";
|
|
2949
2976
|
}
|
|
2977
|
+
function classifyDraftLiveness(before, after) {
|
|
2978
|
+
if (before === null || after === null)
|
|
2979
|
+
return "inconclusive";
|
|
2980
|
+
if (after === "")
|
|
2981
|
+
return "no-draft";
|
|
2982
|
+
if (before.length > 0) {
|
|
2983
|
+
const segs = [...new Intl.Segmenter().segment(before)];
|
|
2984
|
+
const expected = segs.slice(0, -1).map((s) => s.segment).join("").replace(/\s+$/, "");
|
|
2985
|
+
if (after === expected)
|
|
2986
|
+
return "real-draft";
|
|
2987
|
+
}
|
|
2988
|
+
return "inconclusive";
|
|
2989
|
+
}
|
|
2950
2990
|
function createCmuxDriver() {
|
|
2951
2991
|
return {
|
|
2952
2992
|
name: "cmux",
|
|
@@ -3144,18 +3184,38 @@ function createCmuxDriver() {
|
|
|
3144
3184
|
if (!opts?.probe)
|
|
3145
3185
|
throw new DeferDelivery(draft);
|
|
3146
3186
|
const before = readInputBoxRaw(screen);
|
|
3187
|
+
const rawBefore = readInputBoxRaw(screen, { trim: false });
|
|
3147
3188
|
await cmux(["send-key", "--workspace", ws, "--surface", sf, "backspace"]);
|
|
3189
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
3148
3190
|
let afterScreen = "";
|
|
3149
3191
|
try {
|
|
3150
3192
|
afterScreen = await cmux(["read-screen", "--workspace", ws, "--surface", sf]);
|
|
3151
3193
|
} catch {
|
|
3152
3194
|
}
|
|
3153
3195
|
const after = readInputBoxRaw(afterScreen);
|
|
3154
|
-
|
|
3155
|
-
|
|
3196
|
+
const rawAfter = readInputBoxRaw(afterScreen, { trim: false });
|
|
3197
|
+
const liveness = classifyDraftLiveness(before, after);
|
|
3198
|
+
if (liveness === "real-draft") {
|
|
3199
|
+
const segs = before ? [...new Intl.Segmenter().segment(before)] : [];
|
|
3200
|
+
const lastGrapheme = segs.length > 0 ? segs[segs.length - 1].segment : before.slice(-1);
|
|
3201
|
+
await cmux(["send", "--workspace", ws, "--surface", sf, lastGrapheme]);
|
|
3156
3202
|
throw new DeferDelivery(draft);
|
|
3157
3203
|
}
|
|
3158
|
-
|
|
3204
|
+
if (liveness === "no-draft") {
|
|
3205
|
+
await deliver();
|
|
3206
|
+
return;
|
|
3207
|
+
}
|
|
3208
|
+
if (rawBefore !== null && rawAfter !== null) {
|
|
3209
|
+
if (rawBefore !== rawAfter) {
|
|
3210
|
+
const segs = [...new Intl.Segmenter().segment(rawBefore)];
|
|
3211
|
+
const lastGrapheme = segs.length > 0 ? segs[segs.length - 1].segment : rawBefore.slice(-1);
|
|
3212
|
+
await cmux(["send", "--workspace", ws, "--surface", sf, lastGrapheme]);
|
|
3213
|
+
throw new DeferDelivery(draft);
|
|
3214
|
+
}
|
|
3215
|
+
await deliver();
|
|
3216
|
+
return;
|
|
3217
|
+
}
|
|
3218
|
+
throw new DeferDelivery(draft);
|
|
3159
3219
|
},
|
|
3160
3220
|
async listSurfaces(workspaceId) {
|
|
3161
3221
|
let output;
|
|
@@ -4033,7 +4093,7 @@ async function confirmedSendToPane(runtime, pane, message) {
|
|
|
4033
4093
|
sawDraft = true;
|
|
4034
4094
|
if (draft === "" && sawDraft)
|
|
4035
4095
|
return { delivered: true };
|
|
4036
|
-
if (draft === null && afterScreen !== preSendScreen)
|
|
4096
|
+
if (draft === null && afterScreen !== preSendScreen && sawDraft)
|
|
4037
4097
|
return { delivered: true };
|
|
4038
4098
|
const settled = await settleInputBox(runtime, pane);
|
|
4039
4099
|
if (settled)
|
|
@@ -4053,8 +4113,8 @@ async function sendFirstTurnWhenReady(runtime, pane, task, preLaunchScreen, acce
|
|
|
4053
4113
|
let stable = false;
|
|
4054
4114
|
for (let i = 0; i < maxPolls && !stable; i++) {
|
|
4055
4115
|
const screen = await runtime.readPaneScreen(pane) ?? "";
|
|
4056
|
-
const
|
|
4057
|
-
if (screen.length > 0 && screen === previousScreen && screen !== preLaunchScreen &&
|
|
4116
|
+
const ready = acceptanceConfig?.splashMarker ? true : hasCCInputBox(screen) && classifyStartupSurface(screen) === "idle";
|
|
4117
|
+
if (screen.length > 0 && screen === previousScreen && screen !== preLaunchScreen && ready) {
|
|
4058
4118
|
stable = true;
|
|
4059
4119
|
} else {
|
|
4060
4120
|
previousScreen = screen;
|
|
@@ -4092,7 +4152,7 @@ async function sendFirstTurnWhenReady(runtime, pane, task, preLaunchScreen, acce
|
|
|
4092
4152
|
sawDraft = true;
|
|
4093
4153
|
if (draft === "" && sawDraft)
|
|
4094
4154
|
return { delivered: true };
|
|
4095
|
-
if (draft === null && afterScreen !== preSendScreen)
|
|
4155
|
+
if (draft === null && afterScreen !== preSendScreen && sawDraft)
|
|
4096
4156
|
return { delivered: true };
|
|
4097
4157
|
const settled = await settleInputBox(runtime, pane);
|
|
4098
4158
|
if (settled)
|
|
@@ -4117,7 +4177,7 @@ var init_crew_pane = __esm({
|
|
|
4117
4177
|
init_dist2();
|
|
4118
4178
|
SEND_FIRST_TURN_FLOOR_MS = 1500;
|
|
4119
4179
|
POLL_INTERVAL_MS = 750;
|
|
4120
|
-
SEND_FIRST_TURN_TIMEOUT_MS =
|
|
4180
|
+
SEND_FIRST_TURN_TIMEOUT_MS = 9e4;
|
|
4121
4181
|
POST_SEND_CHECK_MS = 750;
|
|
4122
4182
|
SPLASH_MAX_CHECKS = 20;
|
|
4123
4183
|
SPLASH_RESEND_EVERY_N = 4;
|
|
@@ -5833,6 +5893,8 @@ function mapClaudeHookToEvent(event, payload, taskId) {
|
|
|
5833
5893
|
case "SubagentStop":
|
|
5834
5894
|
case "PostToolUse":
|
|
5835
5895
|
return { type: "task.progress", id: taskId, note: event.toLowerCase() };
|
|
5896
|
+
case "UserPromptSubmit":
|
|
5897
|
+
return { type: "task.first-turn.confirmed", id: taskId };
|
|
5836
5898
|
default:
|
|
5837
5899
|
return null;
|
|
5838
5900
|
}
|
|
@@ -5840,7 +5902,7 @@ function mapClaudeHookToEvent(event, payload, taskId) {
|
|
|
5840
5902
|
var EVENTS, claudeInteractive;
|
|
5841
5903
|
var init_claude2 = __esm({
|
|
5842
5904
|
"packages/agents/dist/interactive/claude.js"() {
|
|
5843
|
-
EVENTS = ["Stop", "SubagentStop", "SessionEnd", "PostToolUse", "Notification"];
|
|
5905
|
+
EVENTS = ["Stop", "SubagentStop", "SessionEnd", "PostToolUse", "Notification", "UserPromptSubmit"];
|
|
5844
5906
|
claudeInteractive = {
|
|
5845
5907
|
provider: "claude",
|
|
5846
5908
|
tier: "strong",
|
|
@@ -11028,9 +11090,10 @@ async function sendToSock(req) {
|
|
|
11028
11090
|
function mapHookSub(sub, payload, taskId) {
|
|
11029
11091
|
switch (sub) {
|
|
11030
11092
|
case "session-start":
|
|
11031
|
-
case "prompt-submit":
|
|
11032
11093
|
case "pre-tool-use":
|
|
11033
11094
|
return { type: "task.progress", id: taskId, note: sub };
|
|
11095
|
+
case "prompt-submit":
|
|
11096
|
+
return { type: "task.first-turn.confirmed", id: taskId };
|
|
11034
11097
|
case "stop":
|
|
11035
11098
|
return mapClaudeHookToEvent("Stop", payload, taskId);
|
|
11036
11099
|
case "notification":
|