@shipers-dev/multi 0.39.2 → 0.43.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/dist/index.js +583 -409
- package/package.json +1 -1
- package/dist/fsevents-hj42pnne.node +0 -0
- package/dist/wa-sqlite.node.wasm +0 -0
package/dist/index.js
CHANGED
|
@@ -17109,7 +17109,7 @@ function setWorktreeIndexEntry(workingDir, key, issueId) {
|
|
|
17109
17109
|
idx[key] = issueId;
|
|
17110
17110
|
writeIndex(workingDir, idx);
|
|
17111
17111
|
}
|
|
17112
|
-
async function ensureWorktree(workingDir, issueKey, issueId) {
|
|
17112
|
+
async function ensureWorktree(workingDir, issueKey, issueId, opts) {
|
|
17113
17113
|
if (!await isGitRepo(workingDir)) {
|
|
17114
17114
|
return { path: workingDir, branch: "", created: false };
|
|
17115
17115
|
}
|
|
@@ -17126,8 +17126,19 @@ async function ensureWorktree(workingDir, issueKey, issueId) {
|
|
|
17126
17126
|
try {
|
|
17127
17127
|
mkdirSync3(wtDir, { recursive: true });
|
|
17128
17128
|
} catch {}
|
|
17129
|
+
let baseRef = "HEAD";
|
|
17130
|
+
if (opts?.parentBranch) {
|
|
17131
|
+
const localOk = await branchExists(workingDir, opts.parentBranch);
|
|
17132
|
+
if (localOk) {
|
|
17133
|
+
baseRef = opts.parentBranch;
|
|
17134
|
+
} else {
|
|
17135
|
+
const fetched = await run3(workingDir, "git", ["fetch", "origin", `${opts.parentBranch}:${opts.parentBranch}`]);
|
|
17136
|
+
if (fetched.code === 0)
|
|
17137
|
+
baseRef = opts.parentBranch;
|
|
17138
|
+
}
|
|
17139
|
+
}
|
|
17129
17140
|
const exists4 = await branchExists(workingDir, branch);
|
|
17130
|
-
const args2 = exists4 ? ["worktree", "add", wtPath, branch] : ["worktree", "add", "-b", branch, wtPath,
|
|
17141
|
+
const args2 = exists4 ? ["worktree", "add", wtPath, branch] : ["worktree", "add", "-b", branch, wtPath, baseRef];
|
|
17131
17142
|
const r = await run3(workingDir, "git", args2);
|
|
17132
17143
|
if (r.code !== 0) {
|
|
17133
17144
|
throw new Error(`git worktree add failed: ${r.stderr || r.stdout}`);
|
|
@@ -17219,6 +17230,48 @@ async function removeWorktree(workingDir, issueKey, opts = {}) {
|
|
|
17219
17230
|
removeWorktreeIndexEntry(workingDir, key);
|
|
17220
17231
|
return result;
|
|
17221
17232
|
}
|
|
17233
|
+
async function squashMergeChild(wtPath, childBranch, childKey) {
|
|
17234
|
+
const result = { childKey, branch: childBranch, ok: false, empty: false, conflicts: [], message: "" };
|
|
17235
|
+
await run3(wtPath, "git", ["fetch", "origin", `${childBranch}:${childBranch}`]).catch(() => null);
|
|
17236
|
+
const haveLocal = await branchExists(wtPath, childBranch);
|
|
17237
|
+
if (!haveLocal) {
|
|
17238
|
+
result.message = `branch ${childBranch} not resolvable locally or via origin`;
|
|
17239
|
+
return result;
|
|
17240
|
+
}
|
|
17241
|
+
const ahead = await run3(wtPath, "git", ["rev-list", "--count", `HEAD..${childBranch}`]);
|
|
17242
|
+
if (ahead.code === 0 && Number((ahead.stdout || "0").trim()) === 0) {
|
|
17243
|
+
result.ok = true;
|
|
17244
|
+
result.empty = true;
|
|
17245
|
+
result.message = `${childKey} had no commits ahead of parent — nothing to merge`;
|
|
17246
|
+
return result;
|
|
17247
|
+
}
|
|
17248
|
+
const merge9 = await run3(wtPath, "git", ["merge", "--squash", "--no-commit", childBranch]);
|
|
17249
|
+
const conflicted = await run3(wtPath, "git", ["diff", "--name-only", "--diff-filter=U"]);
|
|
17250
|
+
const conflictPaths = (conflicted.stdout || "").split(`
|
|
17251
|
+
`).map((l) => l.trim()).filter(Boolean);
|
|
17252
|
+
if (merge9.code !== 0 || conflictPaths.length > 0) {
|
|
17253
|
+
result.conflicts = conflictPaths;
|
|
17254
|
+
result.message = `${childKey} had ${conflictPaths.length} conflicting path(s); worktree left dirty for parent to resolve`;
|
|
17255
|
+
return result;
|
|
17256
|
+
}
|
|
17257
|
+
const staged = await run3(wtPath, "git", ["diff", "--cached", "--name-only"]);
|
|
17258
|
+
const stagedFiles = (staged.stdout || "").split(`
|
|
17259
|
+
`).map((l) => l.trim()).filter(Boolean);
|
|
17260
|
+
if (stagedFiles.length === 0) {
|
|
17261
|
+
result.ok = true;
|
|
17262
|
+
result.empty = true;
|
|
17263
|
+
result.message = `${childKey} produced no staged changes — nothing to commit`;
|
|
17264
|
+
return result;
|
|
17265
|
+
}
|
|
17266
|
+
const commit = await run3(wtPath, "git", ["commit", "-m", `squash: ${childKey} (${childBranch})`]);
|
|
17267
|
+
if (commit.code !== 0) {
|
|
17268
|
+
result.message = `${childKey} commit failed: ${commit.stderr || commit.stdout}`;
|
|
17269
|
+
return result;
|
|
17270
|
+
}
|
|
17271
|
+
result.ok = true;
|
|
17272
|
+
result.message = `${childKey} squash-merged (${stagedFiles.length} file${stagedFiles.length === 1 ? "" : "s"})`;
|
|
17273
|
+
return result;
|
|
17274
|
+
}
|
|
17222
17275
|
var init_worktree = () => {};
|
|
17223
17276
|
|
|
17224
17277
|
// ../../node_modules/zod/v4/core/core.js
|
|
@@ -33802,7 +33855,7 @@ function parsePlanBlocks(text) {
|
|
|
33802
33855
|
}
|
|
33803
33856
|
return { actions, errors: errors3 };
|
|
33804
33857
|
}
|
|
33805
|
-
var PLAN_SCHEMA_VERSION =
|
|
33858
|
+
var PLAN_SCHEMA_VERSION = 5, Priority, AssigneeType, IssueStatus, SessionRole, SkillFile, EvalPolicy, PlanActionSchema, PlanEnvelopeSchema, UiBlockSchema, UI_FENCE_RE, FENCE_RE;
|
|
33806
33859
|
var init_plans = __esm(() => {
|
|
33807
33860
|
init_zod();
|
|
33808
33861
|
Priority = exports_external.enum(["low", "medium", "high"]);
|
|
@@ -33810,6 +33863,12 @@ var init_plans = __esm(() => {
|
|
|
33810
33863
|
IssueStatus = exports_external.enum(["todo", "in_progress", "done", "failed", "stopped", "cancelled"]);
|
|
33811
33864
|
SessionRole = exports_external.enum(["implementer", "reviewer", "test-fixer"]);
|
|
33812
33865
|
SkillFile = exports_external.object({ path: exports_external.string().min(1), content: exports_external.string() });
|
|
33866
|
+
EvalPolicy = exports_external.object({
|
|
33867
|
+
evaluator_agent_id: exports_external.string().min(1),
|
|
33868
|
+
threshold: exports_external.number().min(0).max(1),
|
|
33869
|
+
on_fail: exports_external.enum(["retry", "fail", "comment"]).optional(),
|
|
33870
|
+
max_retries: exports_external.number().int().min(0).max(10).optional()
|
|
33871
|
+
});
|
|
33813
33872
|
PlanActionSchema = exports_external.discriminatedUnion("type", [
|
|
33814
33873
|
exports_external.object({
|
|
33815
33874
|
type: exports_external.literal("create"),
|
|
@@ -33820,7 +33879,9 @@ var init_plans = __esm(() => {
|
|
|
33820
33879
|
assignee_type: AssigneeType.optional(),
|
|
33821
33880
|
assignee_id: exports_external.string().optional(),
|
|
33822
33881
|
parent_id: exports_external.string().optional(),
|
|
33823
|
-
blocked_by: exports_external.array(exports_external.string().min(1)).optional()
|
|
33882
|
+
blocked_by: exports_external.array(exports_external.string().min(1)).optional(),
|
|
33883
|
+
await_children: exports_external.boolean().optional(),
|
|
33884
|
+
eval_policy: EvalPolicy.optional()
|
|
33824
33885
|
}),
|
|
33825
33886
|
exports_external.object({
|
|
33826
33887
|
type: exports_external.literal("update"),
|
|
@@ -33831,7 +33892,8 @@ var init_plans = __esm(() => {
|
|
|
33831
33892
|
priority: Priority.optional(),
|
|
33832
33893
|
assignee_type: AssigneeType.optional(),
|
|
33833
33894
|
assignee_id: exports_external.string().optional(),
|
|
33834
|
-
blocked_by: exports_external.array(exports_external.string().min(1)).optional()
|
|
33895
|
+
blocked_by: exports_external.array(exports_external.string().min(1)).optional(),
|
|
33896
|
+
eval_policy: EvalPolicy.nullable().optional()
|
|
33835
33897
|
}),
|
|
33836
33898
|
exports_external.object({
|
|
33837
33899
|
type: exports_external.literal("delegate"),
|
|
@@ -33870,7 +33932,7 @@ var init_plans = __esm(() => {
|
|
|
33870
33932
|
exports_external.object({
|
|
33871
33933
|
type: exports_external.literal("agent.create"),
|
|
33872
33934
|
name: exports_external.string().min(1).max(120),
|
|
33873
|
-
agent_type: exports_external.string().min(1),
|
|
33935
|
+
agent_type: exports_external.string().min(1).optional(),
|
|
33874
33936
|
prompt: exports_external.string().optional(),
|
|
33875
33937
|
skill_ids: exports_external.array(exports_external.string()).optional(),
|
|
33876
33938
|
allowed_tools: exports_external.array(exports_external.string()).optional()
|
|
@@ -33906,6 +33968,13 @@ var init_plans = __esm(() => {
|
|
|
33906
33968
|
agent_id: exports_external.string().min(1),
|
|
33907
33969
|
role: SessionRole,
|
|
33908
33970
|
device_id: exports_external.string().optional()
|
|
33971
|
+
}),
|
|
33972
|
+
exports_external.object({
|
|
33973
|
+
type: exports_external.literal("eval.submit"),
|
|
33974
|
+
id: exports_external.string().min(1).optional(),
|
|
33975
|
+
score: exports_external.number().min(0).max(1),
|
|
33976
|
+
feedback: exports_external.string().min(1).max(8000),
|
|
33977
|
+
scores: exports_external.record(exports_external.string(), exports_external.number().min(0).max(1)).optional()
|
|
33909
33978
|
})
|
|
33910
33979
|
]);
|
|
33911
33980
|
PlanEnvelopeSchema = exports_external.object({
|
|
@@ -34341,7 +34410,7 @@ async function handleRunTask(apiUrl, deviceId, task, detected, ctx) {
|
|
|
34341
34410
|
let worktreeBranch = "";
|
|
34342
34411
|
if (baseWorkingDir) {
|
|
34343
34412
|
try {
|
|
34344
|
-
const wt = await ensureWorktree(baseWorkingDir, task.key || issueId, issueId);
|
|
34413
|
+
const wt = await ensureWorktree(baseWorkingDir, task.key || issueId, issueId, { parentBranch: task.parent_branch ?? undefined });
|
|
34345
34414
|
workingDir = wt.path;
|
|
34346
34415
|
worktreeBranch = wt.branch;
|
|
34347
34416
|
await postStream(apiUrl, issueId, "worktree_created", { path: wt.path, branch: wt.branch, reused: !wt.created });
|
|
@@ -34356,6 +34425,44 @@ async function handleRunTask(apiUrl, deviceId, task, detected, ctx) {
|
|
|
34356
34425
|
await postStream(apiUrl, issueId, "worktree_error", { message: fmtError(e) });
|
|
34357
34426
|
}
|
|
34358
34427
|
}
|
|
34428
|
+
let mergeReportLines = [];
|
|
34429
|
+
let mergeHadConflicts = false;
|
|
34430
|
+
const mergeTargets = Array.isArray(task.merge_targets) ? task.merge_targets : [];
|
|
34431
|
+
if (workingDir && mergeTargets.length) {
|
|
34432
|
+
for (const t of mergeTargets) {
|
|
34433
|
+
if (!t?.branch || !t?.child_key)
|
|
34434
|
+
continue;
|
|
34435
|
+
try {
|
|
34436
|
+
const r = await squashMergeChild(workingDir, String(t.branch), String(t.child_key));
|
|
34437
|
+
if (r.ok && r.empty) {
|
|
34438
|
+
mergeReportLines.push(`- _empty_ ${t.child_key} → no changes`);
|
|
34439
|
+
} else if (r.ok) {
|
|
34440
|
+
mergeReportLines.push(`- ✅ ${t.child_key} squashed into ${worktreeBranch || "(parent)"}`);
|
|
34441
|
+
} else if (r.conflicts.length) {
|
|
34442
|
+
mergeHadConflicts = true;
|
|
34443
|
+
mergeReportLines.push(`- ⚠ ${t.child_key} CONFLICT in: ${r.conflicts.join(", ")}`);
|
|
34444
|
+
} else {
|
|
34445
|
+
mergeReportLines.push(`- ✗ ${t.child_key} ${r.message}`);
|
|
34446
|
+
}
|
|
34447
|
+
await postStream(apiUrl, issueId, "child_merge", {
|
|
34448
|
+
child_key: t.child_key,
|
|
34449
|
+
branch: t.branch,
|
|
34450
|
+
ok: r.ok,
|
|
34451
|
+
empty: r.empty,
|
|
34452
|
+
conflicts: r.conflicts,
|
|
34453
|
+
message: r.message
|
|
34454
|
+
});
|
|
34455
|
+
} catch (e) {
|
|
34456
|
+
mergeReportLines.push(`- ✗ ${t.child_key} merge threw: ${fmtError(e)}`);
|
|
34457
|
+
}
|
|
34458
|
+
}
|
|
34459
|
+
if (mergeReportLines.length) {
|
|
34460
|
+
const header = mergeHadConflicts ? "## ⚠ Squash-merge results — conflicts to resolve in your worktree" : "## Squash-merge results";
|
|
34461
|
+
const block = [header, ...mergeReportLines, "", "---", ""].join(`
|
|
34462
|
+
`);
|
|
34463
|
+
task.followup = block + (task.followup || "");
|
|
34464
|
+
}
|
|
34465
|
+
}
|
|
34359
34466
|
log3(`▶ run_task ${task.key}: ${isFollowup ? "(follow-up) " : ""}${task.title}${workingDir ? ` [cwd: ${workingDir}${worktreeBranch ? ` @${worktreeBranch}` : ""}]` : ""}`);
|
|
34360
34467
|
if (tenantWsId)
|
|
34361
34468
|
await patchIssueStatus(apiUrl, tenantWsId, issueId, "in_progress");
|
|
@@ -34925,7 +35032,7 @@ Agent + skill self-service (use sparingly — only when you genuinely need a new
|
|
|
34925
35032
|
|
|
34926
35033
|
\`\`\`multi-plan
|
|
34927
35034
|
{"actions":[
|
|
34928
|
-
{"type":"agent.create","name":"refactor-bot","
|
|
35035
|
+
{"type":"agent.create","name":"refactor-bot","prompt":"You refactor TS code...","skill_ids":["sk_xxx"],"allowed_tools":["Read","Edit","Bash"]},
|
|
34929
35036
|
{"type":"agent.update","id":"ag_xxx","prompt":"new prompt..."},
|
|
34930
35037
|
{"type":"skill.create","name":"run-tests","description":"Run the test suite","body":"---\\nname: run-tests\\n---\\n\\n# Run tests\\n..."},
|
|
34931
35038
|
{"type":"skill.attach","agent_id":"ag_xxx","skill_id":"sk_yyy"},
|
|
@@ -34950,8 +35057,11 @@ ${agentsBlock}
|
|
|
34950
35057
|
}
|
|
34951
35058
|
async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors = []) {
|
|
34952
35059
|
const lines = [];
|
|
34953
|
-
|
|
35060
|
+
const results = [];
|
|
35061
|
+
for (const e of parseErrors) {
|
|
34954
35062
|
lines.push(`- [err] plan parse: ${e.message}`);
|
|
35063
|
+
results.push({ type: "parse", status: "error", error: e.message });
|
|
35064
|
+
}
|
|
34955
35065
|
let truncated = false;
|
|
34956
35066
|
if (actions.length > PLAN_ACTION_LIMIT) {
|
|
34957
35067
|
truncated = true;
|
|
@@ -34961,8 +35071,10 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
34961
35071
|
if (depth >= PLANNING_DEPTH_LIMIT) {
|
|
34962
35072
|
const blocked3 = actions.filter((a) => a.type !== "update").length;
|
|
34963
35073
|
actions = actions.filter((a) => a.type === "update");
|
|
34964
|
-
if (blocked3)
|
|
35074
|
+
if (blocked3) {
|
|
34965
35075
|
lines.push(`- [warn] ${blocked3} non-update action(s) blocked (planning depth limit ${PLANNING_DEPTH_LIMIT})`);
|
|
35076
|
+
results.push({ type: "note", status: "note", message: `${blocked3} non-update action(s) blocked (planning depth limit ${PLANNING_DEPTH_LIMIT})` });
|
|
35077
|
+
}
|
|
34966
35078
|
}
|
|
34967
35079
|
const SUBCAPS = { "agent.create": 2, "skill.create": 3, "skill.attach": 5, "skill.detach": 5, "agent.update": 5, "session.create": 3 };
|
|
34968
35080
|
const counts = {};
|
|
@@ -34973,6 +35085,7 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
34973
35085
|
counts[a.type] = (counts[a.type] || 0) + 1;
|
|
34974
35086
|
if (counts[a.type] > cap) {
|
|
34975
35087
|
lines.push(`- [warn] ${a.type} sub-cap ${cap} hit, dropping extra`);
|
|
35088
|
+
results.push({ type: a.type, status: "note", message: `${a.type} sub-cap ${cap} hit, dropping extra` });
|
|
34976
35089
|
return false;
|
|
34977
35090
|
}
|
|
34978
35091
|
return true;
|
|
@@ -35008,22 +35121,27 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35008
35121
|
priority: a.priority,
|
|
35009
35122
|
assignee_type: a.assignee_type,
|
|
35010
35123
|
assignee_id: a.assignee_id,
|
|
35011
|
-
parent_id: a.parent_id || parentId
|
|
35124
|
+
parent_id: a.parent_id || parentId,
|
|
35125
|
+
await_children: a.await_children
|
|
35012
35126
|
};
|
|
35013
35127
|
const res = await apiClient.post(mutateUrl, body, { headers });
|
|
35014
35128
|
if (!res.success) {
|
|
35015
35129
|
lines.push(`- [err] create "${a.title}": ${res.error || res.status}`);
|
|
35130
|
+
results.push({ type: "create", status: "error", error: String(res.error || res.status), label: a.title });
|
|
35016
35131
|
continue;
|
|
35017
35132
|
}
|
|
35018
35133
|
const created = res.data;
|
|
35019
35134
|
lines.push(`- [ok] created **${created.key}** - ${created.title}${created.assignee_id ? ` -> @${created.assignee_id}` : ""} (autonomy=${created.autonomy_level || "auto"})`);
|
|
35135
|
+
results.push({ type: "create", status: "ok", issue_id: created.id, key: created.key, title: created.title, assignee_id: created.assignee_id ?? null, assignee_type: created.assignee_type ?? null, priority: created.priority ?? null, autonomy_level: created.autonomy_level || "auto" });
|
|
35020
35136
|
} else if (a.type === "update") {
|
|
35021
35137
|
const res = await apiClient.post(mutateUrl, { action: "update", ...a }, { headers });
|
|
35022
35138
|
if (!res.success) {
|
|
35023
35139
|
lines.push(`- [err] update ${a.id}: ${res.error || res.status}`);
|
|
35140
|
+
results.push({ type: "update", status: "error", error: String(res.error || res.status), label: a.id });
|
|
35024
35141
|
continue;
|
|
35025
35142
|
}
|
|
35026
35143
|
lines.push(`- [ok] updated ${res.data.key}`);
|
|
35144
|
+
results.push({ type: "update", status: "ok", issue_id: res.data.id, key: res.data.key, status_to: a.status ?? null, title_to: a.title ?? null });
|
|
35027
35145
|
if ((a.status === "done" || a.status === "cancelled") && parentTask.working_dir && existsSync11(parentTask.working_dir)) {
|
|
35028
35146
|
const targetKey = res.data?.key;
|
|
35029
35147
|
if (targetKey) {
|
|
@@ -35038,9 +35156,11 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35038
35156
|
const res = await apiClient.post(mutateUrl, { action: "update", id: a.id, assignee_type: "agent", assignee_id: a.assignee_id, status: "todo" }, { headers });
|
|
35039
35157
|
if (!res.success) {
|
|
35040
35158
|
lines.push(`- [err] delegate ${a.id}: ${res.error || res.status}`);
|
|
35159
|
+
results.push({ type: "delegate", status: "error", error: String(res.error || res.status), label: a.id });
|
|
35041
35160
|
continue;
|
|
35042
35161
|
}
|
|
35043
35162
|
lines.push(`- [ok] delegated ${res.data.key} -> ${a.assignee_id}`);
|
|
35163
|
+
results.push({ type: "delegate", status: "ok", issue_id: res.data.id, key: res.data.key, assignee_id: a.assignee_id });
|
|
35044
35164
|
} else if (a.type === "handoff") {
|
|
35045
35165
|
const res = await apiClient.post(mutateUrl, {
|
|
35046
35166
|
action: "handoff",
|
|
@@ -35052,17 +35172,21 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35052
35172
|
}, { headers });
|
|
35053
35173
|
if (!res.success) {
|
|
35054
35174
|
lines.push(`- [err] handoff -> ${a.target_agent_id}: ${res.error || res.status}`);
|
|
35175
|
+
results.push({ type: "handoff", status: "error", error: String(res.error || res.status), label: a.target_agent_id });
|
|
35055
35176
|
continue;
|
|
35056
35177
|
}
|
|
35057
35178
|
const blocked3 = res.data?.blocked ? " (blocked parent)" : "";
|
|
35058
35179
|
lines.push(`- [ok] handoff -> ${a.target_agent_id} via **${res.data?.child_key}**${blocked3} expect=${a.expect ?? "summary"}`);
|
|
35180
|
+
results.push({ type: "handoff", status: "ok", issue_id: res.data?.child_id, key: res.data?.child_key, assignee_id: a.target_agent_id, blocked: !!res.data?.blocked, expect: a.expect ?? "summary" });
|
|
35059
35181
|
} else if (a.type === "issue.delete") {
|
|
35060
35182
|
const res = await apiClient.post(mutateUrl, { action: "delete", id: a.id }, { headers });
|
|
35061
35183
|
if (!res.success) {
|
|
35062
35184
|
lines.push(`- [err] issue.delete ${a.id}: ${res.error || res.status}`);
|
|
35185
|
+
results.push({ type: "issue.delete", status: "error", error: String(res.error || res.status), label: a.id });
|
|
35063
35186
|
continue;
|
|
35064
35187
|
}
|
|
35065
35188
|
lines.push(`- [ok] deleted ${res.data?.key || a.id}`);
|
|
35189
|
+
results.push({ type: "issue.delete", status: "ok", key: res.data?.key || a.id, issue_id: res.data?.id || a.id });
|
|
35066
35190
|
} else if (a.type === "issue.delete_where") {
|
|
35067
35191
|
const res = await apiClient.post(mutateUrl, {
|
|
35068
35192
|
action: "delete_where",
|
|
@@ -35073,17 +35197,20 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35073
35197
|
}, { headers });
|
|
35074
35198
|
if (!res.success) {
|
|
35075
35199
|
lines.push(`- [err] issue.delete_where: ${res.error || res.status}`);
|
|
35200
|
+
results.push({ type: "issue.delete_where", status: "error", error: String(res.error || res.status) });
|
|
35076
35201
|
continue;
|
|
35077
35202
|
}
|
|
35078
35203
|
const rows = Array.isArray(res.data?.deleted) ? res.data.deleted : [];
|
|
35079
35204
|
const count3 = res.data?.count ?? rows.length;
|
|
35080
35205
|
if (!count3) {
|
|
35081
35206
|
lines.push(`- [ok] issue.delete_where: 0 matches`);
|
|
35207
|
+
results.push({ type: "issue.delete_where", status: "ok", count: 0, keys: [] });
|
|
35082
35208
|
continue;
|
|
35083
35209
|
}
|
|
35084
35210
|
lines.push(`- [ok] issue.delete_where: deleted ${count3} issue(s)`);
|
|
35085
35211
|
for (const r of rows)
|
|
35086
35212
|
lines.push(` - ${r.key}`);
|
|
35213
|
+
results.push({ type: "issue.delete_where", status: "ok", count: count3, keys: rows.map((r) => r.key) });
|
|
35087
35214
|
} else if (a.type === "issue.list") {
|
|
35088
35215
|
const res = await apiClient.post(queryUrl, {
|
|
35089
35216
|
kind: "list",
|
|
@@ -35094,17 +35221,20 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35094
35221
|
}, { headers });
|
|
35095
35222
|
if (!res.success) {
|
|
35096
35223
|
lines.push(`- [err] issue.list: ${res.error || res.status}`);
|
|
35224
|
+
results.push({ type: "issue.list", status: "error", error: String(res.error || res.status) });
|
|
35097
35225
|
continue;
|
|
35098
35226
|
}
|
|
35099
35227
|
const rows = Array.isArray(res.data) ? res.data : Array.isArray(res.data?.results) ? res.data.results : [];
|
|
35100
35228
|
if (!rows.length) {
|
|
35101
35229
|
lines.push(`- [ok] issue.list: 0 issues`);
|
|
35230
|
+
results.push({ type: "issue.list", status: "ok", count: 0 });
|
|
35102
35231
|
continue;
|
|
35103
35232
|
}
|
|
35104
35233
|
lines.push(`- [ok] issue.list: ${rows.length} issue(s)`);
|
|
35105
35234
|
for (const r of rows) {
|
|
35106
35235
|
lines.push(` - **${r.key}** [${r.status}] ${r.title}${r.assignee_id ? ` (@${r.assignee_id})` : ""}`);
|
|
35107
35236
|
}
|
|
35237
|
+
results.push({ type: "issue.list", status: "ok", count: rows.length });
|
|
35108
35238
|
} else if (a.type === "issue.search") {
|
|
35109
35239
|
const res = await apiClient.post(queryUrl, {
|
|
35110
35240
|
kind: "search",
|
|
@@ -35114,75 +35244,95 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35114
35244
|
}, { headers });
|
|
35115
35245
|
if (!res.success) {
|
|
35116
35246
|
lines.push(`- [err] issue.search "${a.query}": ${res.error || res.status}`);
|
|
35247
|
+
results.push({ type: "issue.search", status: "error", error: String(res.error || res.status), label: a.query });
|
|
35117
35248
|
continue;
|
|
35118
35249
|
}
|
|
35119
35250
|
const rows = Array.isArray(res.data) ? res.data : Array.isArray(res.data?.results) ? res.data.results : [];
|
|
35120
35251
|
if (!rows.length) {
|
|
35121
35252
|
lines.push(`- [ok] issue.search "${a.query}": 0 hits`);
|
|
35253
|
+
results.push({ type: "issue.search", status: "ok", count: 0, query: a.query });
|
|
35122
35254
|
continue;
|
|
35123
35255
|
}
|
|
35124
35256
|
lines.push(`- [ok] issue.search "${a.query}": ${rows.length} hit(s)`);
|
|
35125
35257
|
for (const r of rows) {
|
|
35126
35258
|
lines.push(` - **${r.key}** [${r.status}] ${r.title}`);
|
|
35127
35259
|
}
|
|
35260
|
+
results.push({ type: "issue.search", status: "ok", count: rows.length, query: a.query });
|
|
35128
35261
|
} else if (a.type === "agent.create") {
|
|
35129
35262
|
if (!parentWsId) {
|
|
35130
35263
|
lines.push(`- [err] agent.create "${a.name}": no tenant workspace id`);
|
|
35264
|
+
results.push({ type: "agent.create", status: "error", error: "no tenant workspace id", label: a.name });
|
|
35131
35265
|
continue;
|
|
35132
35266
|
}
|
|
35133
|
-
const res = await apiClient.post(`${apiUrl}/api/workspaces/${parentWsId}/agent_ops/agents/mutate`, { action: "create", name: a.name,
|
|
35267
|
+
const res = await apiClient.post(`${apiUrl}/api/workspaces/${parentWsId}/agent_ops/agents/mutate`, { action: "create", name: a.name, prompt: a.prompt, skill_ids: a.skill_ids, allowed_tools: a.allowed_tools, capabilities: a.capabilities }, { headers });
|
|
35134
35268
|
if (!res.success) {
|
|
35135
35269
|
lines.push(`- [err] agent.create "${a.name}": ${res.error || res.status}`);
|
|
35270
|
+
results.push({ type: "agent.create", status: "error", error: String(res.error || res.status), label: a.name });
|
|
35136
35271
|
continue;
|
|
35137
35272
|
}
|
|
35138
35273
|
lines.push(`- [ok] agent.create "${a.name}" -> ${res.data?.agent_id}`);
|
|
35274
|
+
results.push({ type: "agent.create", status: "ok", agent_id: res.data?.agent_id, name: a.name, allowed_tools_count: Array.isArray(a.allowed_tools) ? a.allowed_tools.length : 0, approval_status: "approved" });
|
|
35139
35275
|
} else if (a.type === "agent.update") {
|
|
35140
35276
|
if (!parentWsId) {
|
|
35141
35277
|
lines.push(`- [err] agent.update ${a.id}: no tenant workspace id`);
|
|
35278
|
+
results.push({ type: "agent.update", status: "error", error: "no tenant workspace id", label: a.id });
|
|
35142
35279
|
continue;
|
|
35143
35280
|
}
|
|
35144
35281
|
const res = await apiClient.post(`${apiUrl}/api/workspaces/${parentWsId}/agent_ops/agents/mutate`, { action: "update", ...a }, { headers });
|
|
35145
35282
|
if (!res.success) {
|
|
35146
35283
|
lines.push(`- [err] agent.update ${a.id}: ${res.error || res.status}`);
|
|
35284
|
+
results.push({ type: "agent.update", status: "error", error: String(res.error || res.status), label: a.id });
|
|
35147
35285
|
continue;
|
|
35148
35286
|
}
|
|
35149
|
-
|
|
35287
|
+
const changed = ["name", "prompt", "allowed_tools"].filter((k) => a[k] !== undefined);
|
|
35288
|
+
if (res.data?.queued) {
|
|
35150
35289
|
lines.push(`- [pending] agent.update ${a.id} queued`);
|
|
35151
|
-
|
|
35290
|
+
results.push({ type: "agent.update", status: "ok", agent_id: a.id, queued: true, pending_op_id: res.data?.pending_op_id, changed });
|
|
35291
|
+
} else {
|
|
35152
35292
|
lines.push(`- [ok] agent.update ${a.id}`);
|
|
35293
|
+
results.push({ type: "agent.update", status: "ok", agent_id: a.id, queued: false, changed });
|
|
35294
|
+
}
|
|
35153
35295
|
} else if (a.type === "skill.create") {
|
|
35154
35296
|
if (!parentWsId) {
|
|
35155
35297
|
lines.push(`- [err] skill.create "${a.name}": no tenant workspace id`);
|
|
35298
|
+
results.push({ type: "skill.create", status: "error", error: "no tenant workspace id", label: a.name });
|
|
35156
35299
|
continue;
|
|
35157
35300
|
}
|
|
35158
35301
|
const res = await apiClient.post(`${apiUrl}/api/workspaces/${parentWsId}/agent_ops/skills/mutate`, { action: "create", name: a.name, version: a.version, description: a.description, body: a.body, files: a.files }, { headers });
|
|
35159
35302
|
if (!res.success) {
|
|
35160
35303
|
lines.push(`- [err] skill.create "${a.name}": ${res.error || res.status}`);
|
|
35304
|
+
results.push({ type: "skill.create", status: "error", error: String(res.error || res.status), label: a.name });
|
|
35161
35305
|
continue;
|
|
35162
35306
|
}
|
|
35163
35307
|
lines.push(`- [pending] skill.create "${a.name}" queued for human review (op ${res.data?.pending_op_id})`);
|
|
35308
|
+
results.push({ type: "skill.create", status: "ok", pending_op_id: res.data?.pending_op_id, name: a.name, description: a.description });
|
|
35164
35309
|
} else if (a.type === "session.create") {
|
|
35165
35310
|
if (!parentWsId) {
|
|
35166
35311
|
lines.push(`- [err] session.create role=${a.role}: no tenant workspace id`);
|
|
35312
|
+
results.push({ type: "session.create", status: "error", error: "no tenant workspace id" });
|
|
35167
35313
|
continue;
|
|
35168
35314
|
}
|
|
35169
35315
|
const res = await apiClient.post(`${apiUrl}/api/workspaces/${parentWsId}/sessions`, { workspace_id: a.workspace_id, agent_id: a.agent_id, role: a.role, device_id: a.device_id }, { headers });
|
|
35170
35316
|
if (!res.success) {
|
|
35171
35317
|
lines.push(`- [err] session.create role=${a.role}: ${res.error || res.status}`);
|
|
35318
|
+
results.push({ type: "session.create", status: "error", error: String(res.error || res.status) });
|
|
35172
35319
|
continue;
|
|
35173
35320
|
}
|
|
35174
35321
|
const sess = res.data?.session;
|
|
35175
35322
|
const reused = res.data?.reused;
|
|
35176
35323
|
lines.push(`- [${reused ? "reuse" : "ok"}] session.${reused ? "reuse" : "create"} ${sess?.id?.slice(0, 8) || "?"} (role=${a.role})`);
|
|
35324
|
+
results.push({ type: "session.create", status: "ok", session_id: sess?.id, role: a.role, agent_id: a.agent_id, reused: !!reused });
|
|
35177
35325
|
} else if (a.type === "eval.submit") {
|
|
35178
35326
|
if (!parentWsId) {
|
|
35179
35327
|
lines.push(`- [err] eval.submit: no tenant workspace id`);
|
|
35328
|
+
results.push({ type: "eval.submit", status: "error", error: "no tenant workspace id" });
|
|
35180
35329
|
continue;
|
|
35181
35330
|
}
|
|
35182
35331
|
const url2 = `${apiUrl}/api/workspaces/${parentWsId}/agent/issues/eval/submit`;
|
|
35183
35332
|
const res = await apiClient.post(url2, { id: a.id, score: a.score, feedback: a.feedback, scores: a.scores }, { headers });
|
|
35184
35333
|
if (!res.success) {
|
|
35185
35334
|
lines.push(`- [err] eval.submit: ${res.error || res.status}`);
|
|
35335
|
+
results.push({ type: "eval.submit", status: "error", error: String(res.error || res.status) });
|
|
35186
35336
|
continue;
|
|
35187
35337
|
}
|
|
35188
35338
|
const verdict = res.data?.verdict;
|
|
@@ -35190,34 +35340,48 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35190
35340
|
const attempt = res.data?.attempt;
|
|
35191
35341
|
const tag3 = verdict === "pass" ? "ok" : "warn";
|
|
35192
35342
|
lines.push(`- [${tag3}] eval.submit verdict=${verdict} score=${a.score.toFixed(2)} attempt=${attempt}${action ? ` action=${action}` : ""}`);
|
|
35343
|
+
results.push({ type: "eval.submit", status: "ok", verdict, score: a.score, attempt, action_taken: action });
|
|
35193
35344
|
} else if (a.type === "skill.attach" || a.type === "skill.detach") {
|
|
35194
35345
|
const action = a.type === "skill.attach" ? "attach_skill" : "detach_skill";
|
|
35195
35346
|
if (!parentWsId) {
|
|
35196
35347
|
lines.push(`- [err] ${a.type}: no tenant workspace id`);
|
|
35348
|
+
results.push({ type: a.type, status: "error", error: "no tenant workspace id" });
|
|
35197
35349
|
continue;
|
|
35198
35350
|
}
|
|
35199
35351
|
const res = await apiClient.post(`${apiUrl}/api/workspaces/${parentWsId}/agent_ops/agents/mutate`, { action, agent_id: a.agent_id, skill_id: a.skill_id }, { headers });
|
|
35200
35352
|
if (!res.success) {
|
|
35201
35353
|
lines.push(`- [err] ${a.type} ${a.skill_id}->${a.agent_id}: ${res.error || res.status}`);
|
|
35354
|
+
results.push({ type: a.type, status: "error", error: String(res.error || res.status), label: `${a.skill_id}->${a.agent_id}` });
|
|
35202
35355
|
continue;
|
|
35203
35356
|
}
|
|
35204
|
-
if (res.data?.queued)
|
|
35357
|
+
if (res.data?.queued) {
|
|
35205
35358
|
lines.push(`- [pending] ${a.type} queued`);
|
|
35206
|
-
|
|
35359
|
+
results.push({ type: a.type, status: "ok", agent_id: a.agent_id, skill_id: a.skill_id, queued: true, pending_op_id: res.data?.pending_op_id });
|
|
35360
|
+
} else {
|
|
35207
35361
|
lines.push(`- [ok] ${a.type} ${a.skill_id} <-> ${a.agent_id}`);
|
|
35362
|
+
results.push({ type: a.type, status: "ok", agent_id: a.agent_id, skill_id: a.skill_id, queued: false });
|
|
35363
|
+
}
|
|
35208
35364
|
}
|
|
35209
35365
|
} catch (e) {
|
|
35210
35366
|
lines.push(`- [err] ${a.type} failed: ${String(e)}`);
|
|
35367
|
+
results.push({ type: a.type, status: "error", error: String(e) });
|
|
35211
35368
|
}
|
|
35212
35369
|
}
|
|
35213
|
-
if (truncated)
|
|
35370
|
+
if (truncated) {
|
|
35214
35371
|
lines.push(`- [warn] action list truncated at ${PLAN_ACTION_LIMIT}`);
|
|
35372
|
+
results.push({ type: "note", status: "note", message: `Action list truncated at ${PLAN_ACTION_LIMIT}` });
|
|
35373
|
+
}
|
|
35215
35374
|
if (!lines.length)
|
|
35216
35375
|
return "";
|
|
35376
|
+
const json2 = JSON.stringify({ version: 1, actions: results });
|
|
35217
35377
|
return `**Planning actions**
|
|
35218
35378
|
|
|
35219
35379
|
${lines.join(`
|
|
35220
|
-
`)}
|
|
35380
|
+
`)}
|
|
35381
|
+
|
|
35382
|
+
\`\`\`multi-actions
|
|
35383
|
+
${json2}
|
|
35384
|
+
\`\`\``;
|
|
35221
35385
|
}
|
|
35222
35386
|
function stripMd(s) {
|
|
35223
35387
|
return s.replace(/[`*_]/g, "").trim();
|
|
@@ -35822,6 +35986,22 @@ class ChatPeer {
|
|
|
35822
35986
|
getDoc() {
|
|
35823
35987
|
return this.doc;
|
|
35824
35988
|
}
|
|
35989
|
+
findMessage(id3) {
|
|
35990
|
+
for (const m of listMessages(this.doc))
|
|
35991
|
+
if (m.id === id3)
|
|
35992
|
+
return m;
|
|
35993
|
+
return null;
|
|
35994
|
+
}
|
|
35995
|
+
async awaitMessage(id3, timeoutMs = 5000) {
|
|
35996
|
+
const start3 = Date.now();
|
|
35997
|
+
while (Date.now() - start3 < timeoutMs) {
|
|
35998
|
+
const found = this.findMessage(id3);
|
|
35999
|
+
if (found)
|
|
36000
|
+
return found;
|
|
36001
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
36002
|
+
}
|
|
36003
|
+
return null;
|
|
36004
|
+
}
|
|
35825
36005
|
start() {
|
|
35826
36006
|
this.connect();
|
|
35827
36007
|
}
|
|
@@ -35898,8 +36078,9 @@ class ChatPeer {
|
|
|
35898
36078
|
if (before2.has(m.id))
|
|
35899
36079
|
continue;
|
|
35900
36080
|
this.seenIds.add(m.id);
|
|
35901
|
-
if (m.author?.kind === "user" && !m.partial) {
|
|
35902
|
-
|
|
36081
|
+
if (m.author?.kind === "user" && !m.partial && this.opts.onUserMessage) {
|
|
36082
|
+
const cb = this.opts.onUserMessage;
|
|
36083
|
+
Promise.resolve().then(() => cb(m, this)).catch((e) => this.opts.log(`[chat ${this.chatId}] onUserMessage error: ${e.message}`));
|
|
35903
36084
|
}
|
|
35904
36085
|
}
|
|
35905
36086
|
this.dirtySinceWrite++;
|
|
@@ -36046,8 +36227,11 @@ var init_chat_turn = __esm(() => {
|
|
|
36046
36227
|
// src/_impl/chat-plan-actions.ts
|
|
36047
36228
|
async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
36048
36229
|
const lines = [];
|
|
36049
|
-
|
|
36230
|
+
const results = [];
|
|
36231
|
+
for (const e of parseErrors) {
|
|
36050
36232
|
lines.push(`- [err] plan parse: ${e.message}`);
|
|
36233
|
+
results.push({ type: "parse", status: "error", error: e.message });
|
|
36234
|
+
}
|
|
36051
36235
|
let actions = actionsIn;
|
|
36052
36236
|
let truncated = false;
|
|
36053
36237
|
if (actions.length > PLAN_ACTION_LIMIT2) {
|
|
@@ -36062,6 +36246,7 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36062
36246
|
counts[a.type] = (counts[a.type] || 0) + 1;
|
|
36063
36247
|
if (counts[a.type] > cap) {
|
|
36064
36248
|
lines.push(`- [warn] ${a.type} sub-cap ${cap} hit, dropping extra`);
|
|
36249
|
+
results.push({ type: a.type, status: "note", message: `${a.type} sub-cap ${cap} hit, dropping extra` });
|
|
36065
36250
|
return false;
|
|
36066
36251
|
}
|
|
36067
36252
|
return true;
|
|
@@ -36092,6 +36277,7 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36092
36277
|
const project_id = a.project_id || ctx.projectId;
|
|
36093
36278
|
if (!project_id) {
|
|
36094
36279
|
lines.push(`- [err] create "${a.title}": project_id required (chat has no pinned project)`);
|
|
36280
|
+
results.push({ type: "create", status: "error", error: "project_id required (chat has no pinned project)", label: a.title });
|
|
36095
36281
|
tally(false);
|
|
36096
36282
|
continue;
|
|
36097
36283
|
}
|
|
@@ -36103,34 +36289,41 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36103
36289
|
priority: a.priority,
|
|
36104
36290
|
assignee_type: a.assignee_type,
|
|
36105
36291
|
assignee_id: a.assignee_id,
|
|
36106
|
-
parent_id: a.parent_id
|
|
36292
|
+
parent_id: a.parent_id,
|
|
36293
|
+
await_children: a.await_children
|
|
36107
36294
|
};
|
|
36108
36295
|
const res = await apiClient.post(mutateUrl, body, { headers });
|
|
36109
36296
|
if (!res.success) {
|
|
36110
36297
|
lines.push(`- [err] create "${a.title}": ${res.error || res.status}`);
|
|
36298
|
+
results.push({ type: "create", status: "error", error: String(res.error || res.status), label: a.title });
|
|
36111
36299
|
tally(false);
|
|
36112
36300
|
continue;
|
|
36113
36301
|
}
|
|
36114
36302
|
const created = res.data;
|
|
36115
36303
|
lines.push(`- [ok] created **${created.key}** - ${created.title}${created.assignee_id ? ` -> @${created.assignee_id}` : ""}`);
|
|
36304
|
+
results.push({ type: "create", status: "ok", issue_id: created.id, key: created.key, title: created.title, assignee_id: created.assignee_id ?? null, assignee_type: created.assignee_type ?? null, priority: created.priority ?? null, autonomy_level: created.autonomy_level || "auto" });
|
|
36116
36305
|
tally(true);
|
|
36117
36306
|
} else if (a.type === "update") {
|
|
36118
36307
|
const res = await apiClient.post(mutateUrl, { action: "update", ...a }, { headers });
|
|
36119
36308
|
if (!res.success) {
|
|
36120
36309
|
lines.push(`- [err] update ${a.id}: ${res.error || res.status}`);
|
|
36310
|
+
results.push({ type: "update", status: "error", error: String(res.error || res.status), label: a.id });
|
|
36121
36311
|
tally(false);
|
|
36122
36312
|
continue;
|
|
36123
36313
|
}
|
|
36124
36314
|
lines.push(`- [ok] updated ${res.data.key}`);
|
|
36315
|
+
results.push({ type: "update", status: "ok", issue_id: res.data.id, key: res.data.key, status_to: a.status ?? null, title_to: a.title ?? null });
|
|
36125
36316
|
tally(true);
|
|
36126
36317
|
} else if (a.type === "delegate") {
|
|
36127
36318
|
const res = await apiClient.post(mutateUrl, { action: "update", id: a.id, assignee_type: "agent", assignee_id: a.assignee_id, status: "todo" }, { headers });
|
|
36128
36319
|
if (!res.success) {
|
|
36129
36320
|
lines.push(`- [err] delegate ${a.id}: ${res.error || res.status}`);
|
|
36321
|
+
results.push({ type: "delegate", status: "error", error: String(res.error || res.status), label: a.id });
|
|
36130
36322
|
tally(false);
|
|
36131
36323
|
continue;
|
|
36132
36324
|
}
|
|
36133
36325
|
lines.push(`- [ok] delegated ${res.data.key} -> ${a.assignee_id}`);
|
|
36326
|
+
results.push({ type: "delegate", status: "ok", issue_id: res.data.id, key: res.data.key, assignee_id: a.assignee_id });
|
|
36134
36327
|
tally(true);
|
|
36135
36328
|
} else if (a.type === "handoff") {
|
|
36136
36329
|
const res = await apiClient.post(mutateUrl, {
|
|
@@ -36143,40 +36336,48 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36143
36336
|
}, { headers });
|
|
36144
36337
|
if (!res.success) {
|
|
36145
36338
|
lines.push(`- [err] handoff -> ${a.target_agent_id}: ${res.error || res.status}`);
|
|
36339
|
+
results.push({ type: "handoff", status: "error", error: String(res.error || res.status), label: a.target_agent_id });
|
|
36146
36340
|
tally(false);
|
|
36147
36341
|
continue;
|
|
36148
36342
|
}
|
|
36149
36343
|
lines.push(`- [ok] handoff -> ${a.target_agent_id} via **${res.data?.child_key}** expect=${a.expect ?? "summary"}`);
|
|
36344
|
+
results.push({ type: "handoff", status: "ok", issue_id: res.data?.child_id, key: res.data?.child_key, assignee_id: a.target_agent_id, expect: a.expect ?? "summary" });
|
|
36150
36345
|
tally(true);
|
|
36151
36346
|
} else if (a.type === "issue.comment") {
|
|
36152
36347
|
const res = await apiClient.post(mutateUrl, { action: "comment", id: a.id, body: a.body }, { headers });
|
|
36153
36348
|
if (!res.success) {
|
|
36154
36349
|
lines.push(`- [err] issue.comment ${a.id}: ${res.error || res.status}`);
|
|
36350
|
+
results.push({ type: "issue.comment", status: "error", error: String(res.error || res.status), label: a.id });
|
|
36155
36351
|
tally(false);
|
|
36156
36352
|
continue;
|
|
36157
36353
|
}
|
|
36158
36354
|
const dispatched = res.data?.dispatched;
|
|
36159
36355
|
lines.push(`- [ok] commented on ${a.id}${dispatched ? " -> dispatched agent" : ""}`);
|
|
36356
|
+
results.push({ type: "issue.comment", status: "ok", issue_id: a.id, dispatched: !!dispatched });
|
|
36160
36357
|
tally(true);
|
|
36161
36358
|
} else if (a.type === "issue.delete") {
|
|
36162
36359
|
const res = await apiClient.post(mutateUrl, { action: "delete", id: a.id }, { headers });
|
|
36163
36360
|
if (!res.success) {
|
|
36164
36361
|
lines.push(`- [err] issue.delete ${a.id}: ${res.error || res.status}`);
|
|
36362
|
+
results.push({ type: "issue.delete", status: "error", error: String(res.error || res.status), label: a.id });
|
|
36165
36363
|
tally(false);
|
|
36166
36364
|
continue;
|
|
36167
36365
|
}
|
|
36168
36366
|
lines.push(`- [ok] deleted ${res.data?.key || a.id}`);
|
|
36367
|
+
results.push({ type: "issue.delete", status: "ok", key: res.data?.key || a.id, issue_id: res.data?.id || a.id });
|
|
36169
36368
|
tally(true);
|
|
36170
36369
|
} else if (a.type === "issue.delete_where") {
|
|
36171
36370
|
const project_id = a.project_id || ctx.projectId;
|
|
36172
36371
|
if (!project_id) {
|
|
36173
36372
|
lines.push(`- [err] issue.delete_where: project_id required`);
|
|
36373
|
+
results.push({ type: "issue.delete_where", status: "error", error: "project_id required" });
|
|
36174
36374
|
tally(false);
|
|
36175
36375
|
continue;
|
|
36176
36376
|
}
|
|
36177
36377
|
const res = await apiClient.post(mutateUrl, { action: "delete_where", project_id, status: a.status, assignee_id: a.assignee_id, limit: a.limit ?? 50 }, { headers });
|
|
36178
36378
|
if (!res.success) {
|
|
36179
36379
|
lines.push(`- [err] issue.delete_where: ${res.error || res.status}`);
|
|
36380
|
+
results.push({ type: "issue.delete_where", status: "error", error: String(res.error || res.status) });
|
|
36180
36381
|
tally(false);
|
|
36181
36382
|
continue;
|
|
36182
36383
|
}
|
|
@@ -36185,18 +36386,21 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36185
36386
|
lines.push(`- [ok] issue.delete_where: deleted ${count3} issue(s)`);
|
|
36186
36387
|
for (const r of rows)
|
|
36187
36388
|
lines.push(` - ${r.key}`);
|
|
36389
|
+
results.push({ type: "issue.delete_where", status: "ok", count: count3, keys: rows.map((r) => r.key) });
|
|
36188
36390
|
tally(true);
|
|
36189
36391
|
} else if (a.type === "issue.list") {
|
|
36190
36392
|
const project_id = a.project_id || ctx.projectId;
|
|
36191
36393
|
const res = await apiClient.post(queryUrl, { kind: "list", project_id, status: a.status, assignee_id: a.assignee_id, limit: a.limit ?? 20 }, { headers });
|
|
36192
36394
|
if (!res.success) {
|
|
36193
36395
|
lines.push(`- [err] issue.list: ${res.error || res.status}`);
|
|
36396
|
+
results.push({ type: "issue.list", status: "error", error: String(res.error || res.status) });
|
|
36194
36397
|
tally(false);
|
|
36195
36398
|
continue;
|
|
36196
36399
|
}
|
|
36197
36400
|
const rows = Array.isArray(res.data) ? res.data : Array.isArray(res.data?.results) ? res.data.results : [];
|
|
36198
36401
|
if (!rows.length) {
|
|
36199
36402
|
lines.push(`- [ok] issue.list: 0 issues`);
|
|
36403
|
+
results.push({ type: "issue.list", status: "ok", count: 0 });
|
|
36200
36404
|
tally(true);
|
|
36201
36405
|
continue;
|
|
36202
36406
|
}
|
|
@@ -36204,12 +36408,14 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36204
36408
|
for (const r of rows) {
|
|
36205
36409
|
lines.push(` - **${r.key}** [${r.status}] ${r.title}${r.assignee_id ? ` (@${r.assignee_id})` : ""}`);
|
|
36206
36410
|
}
|
|
36411
|
+
results.push({ type: "issue.list", status: "ok", count: rows.length });
|
|
36207
36412
|
tally(true);
|
|
36208
36413
|
} else if (a.type === "issue.search") {
|
|
36209
36414
|
const project_id = a.project_id || ctx.projectId;
|
|
36210
36415
|
const res = await apiClient.post(queryUrl, { kind: "search", project_id, query: a.query, limit: a.limit ?? 10 }, { headers });
|
|
36211
36416
|
if (!res.success) {
|
|
36212
36417
|
lines.push(`- [err] issue.search "${a.query}": ${res.error || res.status}`);
|
|
36418
|
+
results.push({ type: "issue.search", status: "error", error: String(res.error || res.status), label: a.query });
|
|
36213
36419
|
tally(false);
|
|
36214
36420
|
continue;
|
|
36215
36421
|
}
|
|
@@ -36217,12 +36423,12 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36217
36423
|
lines.push(`- [ok] issue.search "${a.query}": ${rows.length} hit(s)`);
|
|
36218
36424
|
for (const r of rows)
|
|
36219
36425
|
lines.push(` - **${r.key}** [${r.status}] ${r.title}`);
|
|
36426
|
+
results.push({ type: "issue.search", status: "ok", count: rows.length, query: a.query });
|
|
36220
36427
|
tally(true);
|
|
36221
36428
|
} else if (a.type === "agent.create") {
|
|
36222
36429
|
const res = await apiClient.post(agentsMutateUrl, {
|
|
36223
36430
|
action: "create",
|
|
36224
36431
|
name: a.name,
|
|
36225
|
-
type: a.agent_type,
|
|
36226
36432
|
prompt: a.prompt,
|
|
36227
36433
|
skill_ids: a.skill_ids,
|
|
36228
36434
|
allowed_tools: a.allowed_tools,
|
|
@@ -36230,19 +36436,24 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36230
36436
|
}, { headers });
|
|
36231
36437
|
if (!res.success) {
|
|
36232
36438
|
lines.push(`- [err] agent.create "${a.name}": ${res.error || res.status}`);
|
|
36439
|
+
results.push({ type: "agent.create", status: "error", error: String(res.error || res.status), label: a.name });
|
|
36233
36440
|
tally(false);
|
|
36234
36441
|
continue;
|
|
36235
36442
|
}
|
|
36236
36443
|
lines.push(`- [ok] agent.create "${a.name}" -> ${res.data?.agent_id}`);
|
|
36444
|
+
results.push({ type: "agent.create", status: "ok", agent_id: res.data?.agent_id, name: a.name, allowed_tools_count: Array.isArray(a.allowed_tools) ? a.allowed_tools.length : 0, approval_status: "approved" });
|
|
36237
36445
|
tally(true);
|
|
36238
36446
|
} else if (a.type === "agent.update") {
|
|
36239
36447
|
const res = await apiClient.post(agentsMutateUrl, { action: "update", ...a }, { headers });
|
|
36240
36448
|
if (!res.success) {
|
|
36241
36449
|
lines.push(`- [err] agent.update ${a.id}: ${res.error || res.status}`);
|
|
36450
|
+
results.push({ type: "agent.update", status: "error", error: String(res.error || res.status), label: a.id });
|
|
36242
36451
|
tally(false);
|
|
36243
36452
|
continue;
|
|
36244
36453
|
}
|
|
36454
|
+
const changed = ["name", "prompt", "allowed_tools"].filter((k) => a[k] !== undefined);
|
|
36245
36455
|
lines.push(res.data?.queued ? `- [pending] agent.update ${a.id} queued` : `- [ok] agent.update ${a.id}`);
|
|
36456
|
+
results.push({ type: "agent.update", status: "ok", agent_id: a.id, queued: !!res.data?.queued, pending_op_id: res.data?.pending_op_id, changed });
|
|
36246
36457
|
tally(true);
|
|
36247
36458
|
} else if (a.type === "skill.create") {
|
|
36248
36459
|
const res = await apiClient.post(skillsMutateUrl, {
|
|
@@ -36255,53 +36466,68 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36255
36466
|
}, { headers });
|
|
36256
36467
|
if (!res.success) {
|
|
36257
36468
|
lines.push(`- [err] skill.create "${a.name}": ${res.error || res.status}`);
|
|
36469
|
+
results.push({ type: "skill.create", status: "error", error: String(res.error || res.status), label: a.name });
|
|
36258
36470
|
tally(false);
|
|
36259
36471
|
continue;
|
|
36260
36472
|
}
|
|
36261
36473
|
const queued = res.data?.pending_op_id;
|
|
36262
36474
|
lines.push(queued ? `- [pending] skill.create "${a.name}" queued for human review (op ${queued})` : `- [ok] skill.create "${a.name}" -> ${res.data?.skill_id}`);
|
|
36475
|
+
results.push({ type: "skill.create", status: "ok", pending_op_id: queued, name: a.name, description: a.description });
|
|
36263
36476
|
tally(true);
|
|
36264
36477
|
} else if (a.type === "skill.attach" || a.type === "skill.detach") {
|
|
36265
36478
|
const action = a.type === "skill.attach" ? "attach_skill" : "detach_skill";
|
|
36266
36479
|
const res = await apiClient.post(agentsMutateUrl, { action, agent_id: a.agent_id, skill_id: a.skill_id }, { headers });
|
|
36267
36480
|
if (!res.success) {
|
|
36268
36481
|
lines.push(`- [err] ${a.type} ${a.skill_id}->${a.agent_id}: ${res.error || res.status}`);
|
|
36482
|
+
results.push({ type: a.type, status: "error", error: String(res.error || res.status), label: `${a.skill_id}->${a.agent_id}` });
|
|
36269
36483
|
tally(false);
|
|
36270
36484
|
continue;
|
|
36271
36485
|
}
|
|
36272
36486
|
lines.push(res.data?.queued ? `- [pending] ${a.type} queued` : `- [ok] ${a.type} ${a.skill_id} <-> ${a.agent_id}`);
|
|
36487
|
+
results.push({ type: a.type, status: "ok", agent_id: a.agent_id, skill_id: a.skill_id, queued: !!res.data?.queued, pending_op_id: res.data?.pending_op_id });
|
|
36273
36488
|
tally(true);
|
|
36274
36489
|
} else if (a.type === "session.create") {
|
|
36275
36490
|
const res = await apiClient.post(sessionsUrl, { workspace_id: a.workspace_id, agent_id: a.agent_id, role: a.role, device_id: a.device_id }, { headers });
|
|
36276
36491
|
if (!res.success) {
|
|
36277
36492
|
lines.push(`- [err] session.create role=${a.role}: ${res.error || res.status}`);
|
|
36493
|
+
results.push({ type: "session.create", status: "error", error: String(res.error || res.status) });
|
|
36278
36494
|
tally(false);
|
|
36279
36495
|
continue;
|
|
36280
36496
|
}
|
|
36281
36497
|
const sess = res.data?.session;
|
|
36282
36498
|
const reused = res.data?.reused;
|
|
36283
36499
|
lines.push(`- [${reused ? "reuse" : "ok"}] session.${reused ? "reuse" : "create"} ${sess?.id?.slice(0, 8) || "?"} (role=${a.role})`);
|
|
36500
|
+
results.push({ type: "session.create", status: "ok", session_id: sess?.id, role: a.role, agent_id: a.agent_id, reused: !!reused });
|
|
36284
36501
|
tally(true);
|
|
36285
36502
|
} else if (a.type === "eval.submit") {
|
|
36286
36503
|
lines.push(`- [err] eval.submit not allowed in chat (only inside an eval dispatch)`);
|
|
36504
|
+
results.push({ type: "eval.submit", status: "error", error: "eval.submit not allowed in chat" });
|
|
36287
36505
|
tally(false);
|
|
36288
36506
|
}
|
|
36289
36507
|
} catch (e) {
|
|
36290
36508
|
lines.push(`- [err] ${a.type} failed: ${String(e)}`);
|
|
36509
|
+
results.push({ type: a.type, status: "error", error: String(e) });
|
|
36291
36510
|
tally(false);
|
|
36292
36511
|
}
|
|
36293
36512
|
}
|
|
36294
|
-
if (truncated)
|
|
36513
|
+
if (truncated) {
|
|
36295
36514
|
lines.push(`- [warn] action list truncated at ${PLAN_ACTION_LIMIT2}`);
|
|
36296
|
-
|
|
36515
|
+
results.push({ type: "note", status: "note", message: `Action list truncated at ${PLAN_ACTION_LIMIT2}` });
|
|
36516
|
+
}
|
|
36517
|
+
return { ok, fail: fail12, lines, results };
|
|
36297
36518
|
}
|
|
36298
36519
|
function renderChatPlanSummary(res) {
|
|
36299
36520
|
if (!res.lines.length)
|
|
36300
36521
|
return "";
|
|
36522
|
+
const json2 = JSON.stringify({ version: 1, actions: res.results });
|
|
36301
36523
|
return `**Planning actions**
|
|
36302
36524
|
|
|
36303
36525
|
${res.lines.join(`
|
|
36304
|
-
`)}
|
|
36526
|
+
`)}
|
|
36527
|
+
|
|
36528
|
+
\`\`\`multi-actions
|
|
36529
|
+
${json2}
|
|
36530
|
+
\`\`\``;
|
|
36305
36531
|
}
|
|
36306
36532
|
var PLAN_ACTION_LIMIT2 = 10, SUBCAPS;
|
|
36307
36533
|
var init_chat_plan_actions = __esm(() => {
|
|
@@ -36321,391 +36547,327 @@ var init_chat_plan_actions = __esm(() => {
|
|
|
36321
36547
|
// src/_impl/chat-supervisor.ts
|
|
36322
36548
|
var exports_chat_supervisor = {};
|
|
36323
36549
|
__export(exports_chat_supervisor, {
|
|
36324
|
-
|
|
36325
|
-
});
|
|
36326
|
-
|
|
36327
|
-
|
|
36328
|
-
|
|
36329
|
-
|
|
36330
|
-
|
|
36331
|
-
|
|
36332
|
-
|
|
36333
|
-
constructor(opts) {
|
|
36334
|
-
this.opts = opts;
|
|
36335
|
-
}
|
|
36336
|
-
start() {
|
|
36337
|
-
this.refresh().catch((e) => this.opts.log(`[chats] refresh err: ${e.message}`));
|
|
36338
|
-
this.timer = setInterval(() => {
|
|
36339
|
-
this.refresh().catch((e) => this.opts.log(`[chats] refresh err: ${e.message}`));
|
|
36340
|
-
}, 30000);
|
|
36341
|
-
}
|
|
36342
|
-
close() {
|
|
36343
|
-
this.closed = true;
|
|
36344
|
-
if (this.timer) {
|
|
36345
|
-
clearInterval(this.timer);
|
|
36346
|
-
this.timer = null;
|
|
36347
|
-
}
|
|
36348
|
-
for (const p of this.peers.values())
|
|
36349
|
-
p.close();
|
|
36350
|
-
this.peers.clear();
|
|
36550
|
+
runChatTurn: () => runChatTurn
|
|
36551
|
+
});
|
|
36552
|
+
async function runChatTurn(opts) {
|
|
36553
|
+
const { apiUrl, authToken: authToken2, workspaceId, chatId, messageId, log: log4 } = opts;
|
|
36554
|
+
const headers = { authorization: `Bearer ${authToken2}` };
|
|
36555
|
+
const metaR = await fetch(`${apiUrl}/api/workspaces/${workspaceId}/chats/${chatId}`, { headers });
|
|
36556
|
+
if (!metaR.ok) {
|
|
36557
|
+
log4(`[chat ${chatId}] meta fetch failed: ${metaR.status}`);
|
|
36558
|
+
return;
|
|
36351
36559
|
}
|
|
36352
|
-
|
|
36353
|
-
|
|
36560
|
+
const chat2 = await metaR.json();
|
|
36561
|
+
const peer = new ChatPeer({
|
|
36562
|
+
apiUrl,
|
|
36563
|
+
authToken: authToken2,
|
|
36564
|
+
workspaceId,
|
|
36565
|
+
chatId,
|
|
36566
|
+
primaryAgentId: chat2.primary_agent_id,
|
|
36567
|
+
log: log4
|
|
36568
|
+
});
|
|
36569
|
+
peer.start();
|
|
36570
|
+
try {
|
|
36571
|
+
const msg = await peer.awaitMessage(messageId, 7000);
|
|
36572
|
+
if (!msg) {
|
|
36573
|
+
log4(`[chat ${chatId}] message ${messageId} not visible after sync; aborting`);
|
|
36354
36574
|
return;
|
|
36355
|
-
const all8 = await this.listAllChats();
|
|
36356
|
-
const mine = all8.filter((c) => c.device_id && c.device_id === this.opts.deviceId);
|
|
36357
|
-
const want = new Set;
|
|
36358
|
-
for (const c of mine) {
|
|
36359
|
-
want.add(c.id);
|
|
36360
|
-
this.chats.set(c.id, c);
|
|
36361
|
-
if (!this.peers.has(c.id)) {
|
|
36362
|
-
const peer = new ChatPeer({
|
|
36363
|
-
apiUrl: this.opts.apiUrl,
|
|
36364
|
-
authToken: this.opts.authToken,
|
|
36365
|
-
workspaceId: this.opts.workspaceId,
|
|
36366
|
-
chatId: c.id,
|
|
36367
|
-
primaryAgentId: c.primary_agent_id,
|
|
36368
|
-
log: this.opts.log,
|
|
36369
|
-
onUserMessage: async (msg, p) => this.onUserMessage(c, msg, p)
|
|
36370
|
-
});
|
|
36371
|
-
peer.start();
|
|
36372
|
-
this.peers.set(c.id, peer);
|
|
36373
|
-
this.opts.log(`[chats] watching ${c.id} (${c.title})`);
|
|
36374
|
-
}
|
|
36375
|
-
}
|
|
36376
|
-
for (const [id3, peer] of this.peers) {
|
|
36377
|
-
if (!want.has(id3)) {
|
|
36378
|
-
peer.close();
|
|
36379
|
-
this.peers.delete(id3);
|
|
36380
|
-
this.chats.delete(id3);
|
|
36381
|
-
this.opts.log(`[chats] released ${id3}`);
|
|
36382
|
-
}
|
|
36383
36575
|
}
|
|
36576
|
+
await processUserMessage(chat2, msg, peer, { apiUrl, authToken: authToken2, workspaceId, log: log4 });
|
|
36577
|
+
} finally {
|
|
36578
|
+
peer.close();
|
|
36384
36579
|
}
|
|
36385
|
-
|
|
36386
|
-
|
|
36387
|
-
|
|
36388
|
-
|
|
36389
|
-
|
|
36390
|
-
|
|
36391
|
-
|
|
36392
|
-
|
|
36393
|
-
|
|
36394
|
-
|
|
36395
|
-
|
|
36396
|
-
|
|
36397
|
-
const pr = await fetch(`${this.opts.apiUrl}/api/workspaces/${this.opts.workspaceId}/devices/me/projects`, { headers });
|
|
36398
|
-
if (pr.ok) {
|
|
36399
|
-
const pbody = await pr.json();
|
|
36400
|
-
for (const pid of pbody.project_ids) {
|
|
36401
|
-
try {
|
|
36402
|
-
const cr = await fetch(`${this.opts.apiUrl}/api/workspaces/${this.opts.workspaceId}/projects/${pid}/chats`, { headers });
|
|
36403
|
-
if (cr.ok) {
|
|
36404
|
-
const cbody = await cr.json();
|
|
36405
|
-
for (const x of cbody.results)
|
|
36406
|
-
out.push(x);
|
|
36407
|
-
}
|
|
36408
|
-
} catch {}
|
|
36409
|
-
}
|
|
36410
|
-
}
|
|
36411
|
-
} catch {}
|
|
36412
|
-
return out;
|
|
36580
|
+
}
|
|
36581
|
+
async function fetchAgents(apiUrl, workspaceId, authToken2) {
|
|
36582
|
+
const headers = { authorization: `Bearer ${authToken2}` };
|
|
36583
|
+
try {
|
|
36584
|
+
const r = await fetch(`${apiUrl}/api/workspaces/${workspaceId}/agents`, { headers });
|
|
36585
|
+
if (!r.ok)
|
|
36586
|
+
return [];
|
|
36587
|
+
const body = await r.json();
|
|
36588
|
+
const arr = Array.isArray(body) ? body : Array.isArray(body.results) ? body.results : [];
|
|
36589
|
+
return arr.map((a) => ({ id: a.id, name: a.name }));
|
|
36590
|
+
} catch {
|
|
36591
|
+
return [];
|
|
36413
36592
|
}
|
|
36414
|
-
|
|
36415
|
-
|
|
36416
|
-
|
|
36417
|
-
|
|
36418
|
-
|
|
36419
|
-
|
|
36420
|
-
|
|
36421
|
-
|
|
36422
|
-
|
|
36423
|
-
|
|
36424
|
-
|
|
36425
|
-
|
|
36593
|
+
}
|
|
36594
|
+
function resolveAgentFromMention(agents, mentioned) {
|
|
36595
|
+
if (!mentioned)
|
|
36596
|
+
return null;
|
|
36597
|
+
const m = mentioned.toLowerCase();
|
|
36598
|
+
return agents.find((a) => a.name?.toLowerCase() === m || a.id === mentioned) ?? null;
|
|
36599
|
+
}
|
|
36600
|
+
async function resolveCwd(apiUrl, workspaceId, authToken2, chat2) {
|
|
36601
|
+
if (!chat2.project_id || !chat2.device_id)
|
|
36602
|
+
return;
|
|
36603
|
+
const headers = { authorization: `Bearer ${authToken2}` };
|
|
36604
|
+
try {
|
|
36605
|
+
const r = await fetch(`${apiUrl}/api/workspaces/${workspaceId}/projects/${chat2.project_id}/devices`, { headers });
|
|
36606
|
+
if (!r.ok)
|
|
36426
36607
|
return;
|
|
36427
|
-
|
|
36608
|
+
const body = await r.json();
|
|
36609
|
+
const row = body.results.find((d) => d.id === chat2.device_id);
|
|
36610
|
+
return row?.working_dir || undefined;
|
|
36611
|
+
} catch {
|
|
36612
|
+
return;
|
|
36428
36613
|
}
|
|
36429
|
-
|
|
36430
|
-
|
|
36431
|
-
|
|
36432
|
-
|
|
36433
|
-
|
|
36434
|
-
|
|
36435
|
-
|
|
36436
|
-
|
|
36437
|
-
|
|
36438
|
-
|
|
36439
|
-
const body = await r.json();
|
|
36440
|
-
return body.runtime || body.type || null;
|
|
36441
|
-
} catch {
|
|
36614
|
+
}
|
|
36615
|
+
async function resolveAgentRuntime(apiUrl, workspaceId, authToken2, chat2, agentId) {
|
|
36616
|
+
if (chat2.runtime)
|
|
36617
|
+
return chat2.runtime;
|
|
36618
|
+
if (!agentId || typeof agentId !== "string")
|
|
36619
|
+
return null;
|
|
36620
|
+
const headers = { authorization: `Bearer ${authToken2}` };
|
|
36621
|
+
try {
|
|
36622
|
+
const r = await fetch(`${apiUrl}/api/workspaces/${workspaceId}/agents/${agentId}`, { headers });
|
|
36623
|
+
if (!r.ok)
|
|
36442
36624
|
return null;
|
|
36443
|
-
|
|
36625
|
+
const body = await r.json();
|
|
36626
|
+
return body.runtime || body.type || null;
|
|
36627
|
+
} catch {
|
|
36628
|
+
return null;
|
|
36444
36629
|
}
|
|
36445
|
-
|
|
36446
|
-
|
|
36447
|
-
|
|
36448
|
-
|
|
36449
|
-
|
|
36450
|
-
|
|
36451
|
-
|
|
36452
|
-
|
|
36453
|
-
|
|
36454
|
-
|
|
36455
|
-
|
|
36630
|
+
}
|
|
36631
|
+
async function processUserMessage(chat2, userMsg, peer, ctx) {
|
|
36632
|
+
const { apiUrl, authToken: authToken2, workspaceId, log: log4 } = ctx;
|
|
36633
|
+
log4(`[chat ${chat2.id}] user: ${userMsg.text.slice(0, 80)}`);
|
|
36634
|
+
const allAgents = await fetchAgents(apiUrl, workspaceId, authToken2);
|
|
36635
|
+
const mentioned = userMsg.mentions?.[0];
|
|
36636
|
+
const mentionAgent = resolveAgentFromMention(allAgents, mentioned);
|
|
36637
|
+
const resolvedAgentId = mentionAgent?.id ?? chat2.primary_agent_id ?? null;
|
|
36638
|
+
const agentAuthorId = resolvedAgentId || mentioned || "agent";
|
|
36639
|
+
const runtime4 = await resolveAgentRuntime(apiUrl, workspaceId, authToken2, chat2, resolvedAgentId);
|
|
36640
|
+
const cwd = await resolveCwd(apiUrl, workspaceId, authToken2, chat2);
|
|
36641
|
+
if (cwd)
|
|
36642
|
+
log4(`[chat ${chat2.id}] cwd=${cwd}`);
|
|
36643
|
+
if (mentionAgent)
|
|
36644
|
+
log4(`[chat ${chat2.id}] mention → ${mentionAgent.name}`);
|
|
36645
|
+
let textContainerId = null;
|
|
36646
|
+
let buffered = "";
|
|
36647
|
+
let lastFlush = Date.now();
|
|
36648
|
+
let agentReplyText = "";
|
|
36649
|
+
const toolMsgByCallId = new Map;
|
|
36650
|
+
const flushText = (force = false) => {
|
|
36651
|
+
const now = Date.now();
|
|
36652
|
+
if (!buffered || textContainerId == null)
|
|
36653
|
+
return;
|
|
36654
|
+
if (force || now - lastFlush > 200) {
|
|
36655
|
+
peer.appendPartialText(textContainerId, buffered);
|
|
36656
|
+
buffered = "";
|
|
36657
|
+
lastFlush = now;
|
|
36456
36658
|
}
|
|
36457
|
-
}
|
|
36458
|
-
|
|
36459
|
-
if (
|
|
36460
|
-
return
|
|
36461
|
-
|
|
36462
|
-
|
|
36463
|
-
|
|
36464
|
-
|
|
36465
|
-
|
|
36466
|
-
|
|
36467
|
-
|
|
36468
|
-
|
|
36469
|
-
|
|
36470
|
-
|
|
36471
|
-
|
|
36472
|
-
|
|
36473
|
-
|
|
36474
|
-
|
|
36475
|
-
|
|
36476
|
-
|
|
36477
|
-
|
|
36478
|
-
|
|
36479
|
-
|
|
36480
|
-
|
|
36481
|
-
|
|
36482
|
-
|
|
36483
|
-
|
|
36484
|
-
|
|
36485
|
-
|
|
36486
|
-
|
|
36487
|
-
|
|
36488
|
-
|
|
36489
|
-
|
|
36490
|
-
|
|
36491
|
-
|
|
36492
|
-
|
|
36493
|
-
|
|
36494
|
-
|
|
36495
|
-
flushText(true);
|
|
36496
|
-
peer.finalizePartialMessage(textContainerId);
|
|
36497
|
-
textContainerId = null;
|
|
36498
|
-
};
|
|
36499
|
-
const agentDisplayName = mentionAgent?.name ?? allAgents.find((a) => a.id === resolvedAgentId)?.name ?? runtime4 ?? undefined;
|
|
36500
|
-
const ensureTextOpen = () => {
|
|
36501
|
-
if (textContainerId == null) {
|
|
36502
|
-
textContainerId = peer.beginPartialAgentMessage(agentAuthorId, agentDisplayName).containerId;
|
|
36503
|
-
}
|
|
36504
|
-
};
|
|
36505
|
-
const summarizeInput = (raw) => {
|
|
36506
|
-
if (!raw || typeof raw !== "object")
|
|
36507
|
-
return;
|
|
36508
|
-
const r = raw;
|
|
36509
|
-
const out = {};
|
|
36510
|
-
if (typeof r.file_path === "string")
|
|
36511
|
-
out.file_path = r.file_path;
|
|
36512
|
-
if (typeof r.path === "string")
|
|
36513
|
-
out.path = r.path;
|
|
36514
|
-
if (typeof r.filename === "string")
|
|
36515
|
-
out.filename = r.filename;
|
|
36516
|
-
if (typeof r.command === "string")
|
|
36517
|
-
out.command = String(r.command).slice(0, 400);
|
|
36518
|
-
if (typeof r.pattern === "string")
|
|
36519
|
-
out.pattern = String(r.pattern).slice(0, 200);
|
|
36520
|
-
if (typeof r.query === "string")
|
|
36521
|
-
out.query = String(r.query).slice(0, 200);
|
|
36522
|
-
if (typeof r.url === "string")
|
|
36523
|
-
out.url = r.url;
|
|
36524
|
-
return Object.keys(out).length ? out : undefined;
|
|
36525
|
-
};
|
|
36526
|
-
const summarizeContent = (raw) => {
|
|
36527
|
-
const bytes = raw?.length ?? 0;
|
|
36528
|
-
const lines = raw ? raw.split(`
|
|
36659
|
+
};
|
|
36660
|
+
const closeText = () => {
|
|
36661
|
+
if (textContainerId == null)
|
|
36662
|
+
return;
|
|
36663
|
+
flushText(true);
|
|
36664
|
+
peer.finalizePartialMessage(textContainerId);
|
|
36665
|
+
textContainerId = null;
|
|
36666
|
+
};
|
|
36667
|
+
const agentDisplayName = mentionAgent?.name ?? allAgents.find((a) => a.id === resolvedAgentId)?.name ?? runtime4 ?? undefined;
|
|
36668
|
+
const ensureTextOpen = () => {
|
|
36669
|
+
if (textContainerId == null) {
|
|
36670
|
+
textContainerId = peer.beginPartialAgentMessage(agentAuthorId, agentDisplayName).containerId;
|
|
36671
|
+
}
|
|
36672
|
+
};
|
|
36673
|
+
const summarizeInput = (raw) => {
|
|
36674
|
+
if (!raw || typeof raw !== "object")
|
|
36675
|
+
return;
|
|
36676
|
+
const r = raw;
|
|
36677
|
+
const out = {};
|
|
36678
|
+
if (typeof r.file_path === "string")
|
|
36679
|
+
out.file_path = r.file_path;
|
|
36680
|
+
if (typeof r.path === "string")
|
|
36681
|
+
out.path = r.path;
|
|
36682
|
+
if (typeof r.filename === "string")
|
|
36683
|
+
out.filename = r.filename;
|
|
36684
|
+
if (typeof r.command === "string")
|
|
36685
|
+
out.command = String(r.command).slice(0, 400);
|
|
36686
|
+
if (typeof r.pattern === "string")
|
|
36687
|
+
out.pattern = String(r.pattern).slice(0, 200);
|
|
36688
|
+
if (typeof r.query === "string")
|
|
36689
|
+
out.query = String(r.query).slice(0, 200);
|
|
36690
|
+
if (typeof r.url === "string")
|
|
36691
|
+
out.url = r.url;
|
|
36692
|
+
return Object.keys(out).length ? out : undefined;
|
|
36693
|
+
};
|
|
36694
|
+
const summarizeContent = (raw) => {
|
|
36695
|
+
const bytes = raw?.length ?? 0;
|
|
36696
|
+
const lines = raw ? raw.split(`
|
|
36529
36697
|
`).length : 0;
|
|
36530
|
-
|
|
36531
|
-
|
|
36532
|
-
|
|
36533
|
-
|
|
36534
|
-
|
|
36535
|
-
|
|
36536
|
-
|
|
36537
|
-
|
|
36538
|
-
|
|
36539
|
-
|
|
36540
|
-
|
|
36541
|
-
|
|
36542
|
-
|
|
36543
|
-
|
|
36544
|
-
|
|
36545
|
-
|
|
36546
|
-
|
|
36547
|
-
|
|
36548
|
-
|
|
36549
|
-
|
|
36550
|
-
|
|
36551
|
-
|
|
36552
|
-
|
|
36553
|
-
|
|
36554
|
-
|
|
36555
|
-
|
|
36556
|
-
|
|
36557
|
-
|
|
36558
|
-
|
|
36559
|
-
|
|
36560
|
-
|
|
36561
|
-
|
|
36562
|
-
|
|
36563
|
-
|
|
36564
|
-
|
|
36565
|
-
|
|
36566
|
-
|
|
36567
|
-
const
|
|
36568
|
-
|
|
36569
|
-
|
|
36570
|
-
|
|
36571
|
-
|
|
36572
|
-
|
|
36573
|
-
|
|
36574
|
-
|
|
36575
|
-
|
|
36576
|
-
|
|
36577
|
-
input: summarizeInput(ev.input)
|
|
36578
|
-
});
|
|
36579
|
-
return;
|
|
36580
|
-
}
|
|
36581
|
-
}
|
|
36582
|
-
const id3 = `tc_${ev.id || Math.random().toString(36).slice(2)}`;
|
|
36583
|
-
const containerId = peer.appendStructured({
|
|
36584
|
-
id: id3,
|
|
36585
|
-
author: { kind: "agent", id: agentAuthorId, name: agentDisplayName },
|
|
36586
|
-
kind: "tool_call",
|
|
36587
|
-
text: "",
|
|
36588
|
-
ts: Math.floor(Date.now() / 1000),
|
|
36589
|
-
mentions: [],
|
|
36590
|
-
attachments: [],
|
|
36591
|
-
partial: partial2,
|
|
36592
|
-
tool: ev.tool,
|
|
36593
|
-
tool_kind: mapToolKind(ev.kind),
|
|
36594
|
-
status: status3,
|
|
36595
|
-
input: summarizeInput(ev.input),
|
|
36596
|
-
tool_call_id: ev.id
|
|
36597
|
-
});
|
|
36598
|
-
if (ev.id)
|
|
36599
|
-
toolMsgByCallId.set(ev.id, containerId);
|
|
36600
|
-
},
|
|
36601
|
-
onToolResult: (ev) => {
|
|
36602
|
-
closeText();
|
|
36603
|
-
const summary5 = summarizeContent(ev.content);
|
|
36604
|
-
peer.appendStructured({
|
|
36605
|
-
id: `tr_${ev.tool_call_id || Math.random().toString(36).slice(2)}_${Date.now()}`,
|
|
36606
|
-
author: { kind: "agent", id: agentAuthorId, name: agentDisplayName },
|
|
36607
|
-
kind: "tool_result",
|
|
36608
|
-
text: `${summary5.lines} lines · ${summary5.bytes} bytes`,
|
|
36609
|
-
ts: Math.floor(Date.now() / 1000),
|
|
36610
|
-
mentions: [],
|
|
36611
|
-
attachments: [],
|
|
36612
|
-
partial: false,
|
|
36613
|
-
tool_call_id: ev.tool_call_id,
|
|
36614
|
-
content: summary5.content
|
|
36615
|
-
});
|
|
36616
|
-
const cid = ev.tool_call_id ? toolMsgByCallId.get(ev.tool_call_id) : undefined;
|
|
36617
|
-
if (cid)
|
|
36618
|
-
peer.patchMessage(cid, { partial: false, status: "completed" });
|
|
36619
|
-
},
|
|
36620
|
-
onDone: (stopReason) => {
|
|
36621
|
-
closeText();
|
|
36622
|
-
for (const cid of toolMsgByCallId.values()) {
|
|
36623
|
-
peer.patchMessage(cid, { partial: false, status: "completed" });
|
|
36698
|
+
const trimmed = raw && raw.length > 240 ? raw.slice(0, 240) + "…" : raw || "";
|
|
36699
|
+
return { content: trimmed, bytes, lines };
|
|
36700
|
+
};
|
|
36701
|
+
const mapToolKind = (raw) => {
|
|
36702
|
+
const s = (raw || "").toLowerCase();
|
|
36703
|
+
if (s.includes("edit") || s.includes("modify"))
|
|
36704
|
+
return "edit";
|
|
36705
|
+
if (s.includes("read") || s.includes("view") || s.includes("fetch"))
|
|
36706
|
+
return "read";
|
|
36707
|
+
if (s.includes("write") || s.includes("create"))
|
|
36708
|
+
return "write";
|
|
36709
|
+
if (s.includes("execute") || s.includes("bash") || s.includes("shell") || s.includes("run"))
|
|
36710
|
+
return "bash";
|
|
36711
|
+
if (s.includes("search") || s.includes("grep") || s.includes("find"))
|
|
36712
|
+
return "search";
|
|
36713
|
+
return "other";
|
|
36714
|
+
};
|
|
36715
|
+
const preamble = buildChatPreamble({ projectId: chat2.project_id, agents: allAgents });
|
|
36716
|
+
await new Promise((resolve2) => {
|
|
36717
|
+
handleChatTurn({
|
|
36718
|
+
chatId: chat2.id,
|
|
36719
|
+
prompt: userMsg.text,
|
|
36720
|
+
preferredRuntime: runtime4,
|
|
36721
|
+
cwd,
|
|
36722
|
+
systemPreamble: preamble,
|
|
36723
|
+
log: log4,
|
|
36724
|
+
onChunk: (text) => {
|
|
36725
|
+
ensureTextOpen();
|
|
36726
|
+
buffered += text;
|
|
36727
|
+
agentReplyText += text;
|
|
36728
|
+
flushText();
|
|
36729
|
+
},
|
|
36730
|
+
onToolCall: (ev) => {
|
|
36731
|
+
closeText();
|
|
36732
|
+
const partial2 = ev.status !== "completed" && ev.status !== "failed";
|
|
36733
|
+
const status3 = ev.status || "in_progress";
|
|
36734
|
+
if (ev.id) {
|
|
36735
|
+
const existing = toolMsgByCallId.get(ev.id);
|
|
36736
|
+
if (existing) {
|
|
36737
|
+
peer.patchMessage(existing, {
|
|
36738
|
+
partial: partial2,
|
|
36739
|
+
status: status3,
|
|
36740
|
+
tool: ev.tool,
|
|
36741
|
+
tool_kind: mapToolKind(ev.kind),
|
|
36742
|
+
input: summarizeInput(ev.input)
|
|
36743
|
+
});
|
|
36744
|
+
return;
|
|
36624
36745
|
}
|
|
36625
|
-
this.opts.log(`[chat ${chat2.id}] done: ${stopReason}`);
|
|
36626
|
-
resolve2();
|
|
36627
36746
|
}
|
|
36628
|
-
|
|
36629
|
-
|
|
36630
|
-
|
|
36631
|
-
|
|
36632
|
-
|
|
36633
|
-
|
|
36634
|
-
|
|
36635
|
-
|
|
36636
|
-
|
|
36637
|
-
|
|
36638
|
-
|
|
36639
|
-
|
|
36747
|
+
const id3 = `tc_${ev.id || Math.random().toString(36).slice(2)}`;
|
|
36748
|
+
const containerId = peer.appendStructured({
|
|
36749
|
+
id: id3,
|
|
36750
|
+
author: { kind: "agent", id: agentAuthorId, name: agentDisplayName },
|
|
36751
|
+
kind: "tool_call",
|
|
36752
|
+
text: "",
|
|
36753
|
+
ts: Math.floor(Date.now() / 1000),
|
|
36754
|
+
mentions: [],
|
|
36755
|
+
attachments: [],
|
|
36756
|
+
partial: partial2,
|
|
36757
|
+
tool: ev.tool,
|
|
36758
|
+
tool_kind: mapToolKind(ev.kind),
|
|
36759
|
+
status: status3,
|
|
36760
|
+
input: summarizeInput(ev.input),
|
|
36761
|
+
tool_call_id: ev.id
|
|
36640
36762
|
});
|
|
36641
|
-
|
|
36642
|
-
|
|
36643
|
-
|
|
36644
|
-
|
|
36645
|
-
|
|
36646
|
-
|
|
36647
|
-
|
|
36648
|
-
|
|
36649
|
-
|
|
36650
|
-
|
|
36651
|
-
|
|
36652
|
-
|
|
36763
|
+
if (ev.id)
|
|
36764
|
+
toolMsgByCallId.set(ev.id, containerId);
|
|
36765
|
+
},
|
|
36766
|
+
onToolResult: (ev) => {
|
|
36767
|
+
closeText();
|
|
36768
|
+
const summary5 = summarizeContent(ev.content);
|
|
36769
|
+
peer.appendStructured({
|
|
36770
|
+
id: `tr_${ev.tool_call_id || Math.random().toString(36).slice(2)}_${Date.now()}`,
|
|
36771
|
+
author: { kind: "agent", id: agentAuthorId, name: agentDisplayName },
|
|
36772
|
+
kind: "tool_result",
|
|
36773
|
+
text: `${summary5.lines} lines · ${summary5.bytes} bytes`,
|
|
36774
|
+
ts: Math.floor(Date.now() / 1000),
|
|
36775
|
+
mentions: [],
|
|
36776
|
+
attachments: [],
|
|
36777
|
+
partial: false,
|
|
36778
|
+
tool_call_id: ev.tool_call_id,
|
|
36779
|
+
content: summary5.content
|
|
36780
|
+
});
|
|
36781
|
+
const cid = ev.tool_call_id ? toolMsgByCallId.get(ev.tool_call_id) : undefined;
|
|
36782
|
+
if (cid)
|
|
36783
|
+
peer.patchMessage(cid, { partial: false, status: "completed" });
|
|
36784
|
+
},
|
|
36785
|
+
onDone: (stopReason) => {
|
|
36786
|
+
closeText();
|
|
36787
|
+
for (const cid of toolMsgByCallId.values()) {
|
|
36788
|
+
peer.patchMessage(cid, { partial: false, status: "completed" });
|
|
36653
36789
|
}
|
|
36654
|
-
|
|
36790
|
+
log4(`[chat ${chat2.id}] done: ${stopReason}`);
|
|
36791
|
+
resolve2();
|
|
36655
36792
|
}
|
|
36656
|
-
|
|
36657
|
-
|
|
36658
|
-
|
|
36659
|
-
|
|
36660
|
-
|
|
36661
|
-
|
|
36662
|
-
|
|
36663
|
-
|
|
36664
|
-
|
|
36665
|
-
|
|
36793
|
+
});
|
|
36794
|
+
});
|
|
36795
|
+
try {
|
|
36796
|
+
const { actions, errors: errors3 } = parsePlanBlocks(agentReplyText);
|
|
36797
|
+
if (actions.length || errors3.length) {
|
|
36798
|
+
const res = await executeChatPlanActions(actions, errors3, {
|
|
36799
|
+
apiUrl,
|
|
36800
|
+
wsId: workspaceId,
|
|
36801
|
+
chatId: chat2.id,
|
|
36802
|
+
projectId: chat2.project_id,
|
|
36803
|
+
agentId: resolvedAgentId,
|
|
36804
|
+
log: log4
|
|
36805
|
+
});
|
|
36806
|
+
const summary5 = renderChatPlanSummary(res);
|
|
36807
|
+
if (summary5) {
|
|
36808
|
+
peer.appendStructured({
|
|
36809
|
+
id: `sys_plan_${Date.now()}`,
|
|
36810
|
+
author: { kind: "system", id: "multi-plan", name: "multi" },
|
|
36811
|
+
kind: "text",
|
|
36812
|
+
text: summary5,
|
|
36813
|
+
ts: Math.floor(Date.now() / 1000),
|
|
36814
|
+
mentions: [],
|
|
36815
|
+
attachments: [],
|
|
36816
|
+
partial: false
|
|
36817
|
+
});
|
|
36818
|
+
}
|
|
36819
|
+
log4(`[chat ${chat2.id}] plan exec: ${res.ok} ok, ${res.fail} fail, ${errors3.length} parse-err`);
|
|
36666
36820
|
}
|
|
36821
|
+
const ui = parseUiBlocks(agentReplyText);
|
|
36822
|
+
if (ui.blocks.length)
|
|
36823
|
+
log4(`[chat ${chat2.id}] ui blocks: ${ui.blocks.length}`);
|
|
36824
|
+
if (ui.errors.length)
|
|
36825
|
+
log4(`[chat ${chat2.id}] ui parse err: ${ui.errors.length}`);
|
|
36826
|
+
} catch (e) {
|
|
36827
|
+
log4(`[chat ${chat2.id}] post-turn err: ${e.message}`);
|
|
36667
36828
|
}
|
|
36668
|
-
|
|
36669
|
-
|
|
36670
|
-
|
|
36671
|
-
|
|
36672
|
-
|
|
36829
|
+
if (/^new chat$/i.test(chat2.title) && agentReplyText.trim()) {
|
|
36830
|
+
autoTitle(chat2, userMsg.text, agentReplyText, ctx).catch((e) => log4(`[chat ${chat2.id}] auto-title failed: ${e.message}`));
|
|
36831
|
+
}
|
|
36832
|
+
}
|
|
36833
|
+
async function autoTitle(chat2, userMsg, agentReply, ctx) {
|
|
36834
|
+
const { apiUrl, authToken: authToken2, workspaceId, log: log4 } = ctx;
|
|
36835
|
+
const runtime4 = await resolveAgentRuntime(apiUrl, workspaceId, authToken2, chat2, chat2.primary_agent_id);
|
|
36836
|
+
const trimUser = userMsg.slice(0, 800);
|
|
36837
|
+
const trimAgent = agentReply.slice(0, 1200);
|
|
36838
|
+
const prompt = `Reply with ONLY a 3-6 word title for this conversation. No quotes, no punctuation, no explanation. Capitalize each word.
|
|
36673
36839
|
|
|
36674
36840
|
` + `User: ${trimUser}
|
|
36675
36841
|
|
|
36676
36842
|
Assistant: ${trimAgent}`;
|
|
36677
|
-
|
|
36678
|
-
|
|
36679
|
-
|
|
36680
|
-
|
|
36681
|
-
|
|
36682
|
-
|
|
36683
|
-
|
|
36684
|
-
|
|
36685
|
-
|
|
36686
|
-
|
|
36687
|
-
|
|
36688
|
-
});
|
|
36843
|
+
let collected = "";
|
|
36844
|
+
await new Promise((resolve2) => {
|
|
36845
|
+
handleChatTurn({
|
|
36846
|
+
chatId: `${chat2.id}__title`,
|
|
36847
|
+
prompt,
|
|
36848
|
+
preferredRuntime: runtime4,
|
|
36849
|
+
log: log4,
|
|
36850
|
+
onChunk: (t) => {
|
|
36851
|
+
collected += t;
|
|
36852
|
+
},
|
|
36853
|
+
onDone: () => resolve2()
|
|
36689
36854
|
});
|
|
36690
|
-
|
|
36855
|
+
});
|
|
36856
|
+
const cleaned = collected.split(`
|
|
36691
36857
|
`).map((s) => s.trim()).filter(Boolean)[0] ?? "";
|
|
36692
|
-
|
|
36693
|
-
|
|
36694
|
-
|
|
36695
|
-
|
|
36696
|
-
|
|
36697
|
-
|
|
36698
|
-
|
|
36699
|
-
|
|
36700
|
-
|
|
36701
|
-
|
|
36702
|
-
|
|
36703
|
-
|
|
36704
|
-
|
|
36705
|
-
if (r.ok)
|
|
36706
|
-
this.opts.log(`[chat ${chat2.id}] auto-titled: ${final}`);
|
|
36707
|
-
} catch {}
|
|
36708
|
-
}
|
|
36858
|
+
const stripped = cleaned.replace(/^["'`*_#-]+|["'`*_#-]+$/g, "").trim();
|
|
36859
|
+
const final = stripped.split(/\s+/).slice(0, 8).join(" ").slice(0, 60);
|
|
36860
|
+
if (!final || /^new chat$/i.test(final))
|
|
36861
|
+
return;
|
|
36862
|
+
try {
|
|
36863
|
+
const r = await fetch(`${apiUrl}/api/workspaces/${workspaceId}/chats/${chat2.id}`, {
|
|
36864
|
+
method: "PATCH",
|
|
36865
|
+
headers: { authorization: `Bearer ${authToken2}`, "content-type": "application/json" },
|
|
36866
|
+
body: JSON.stringify({ title: final })
|
|
36867
|
+
});
|
|
36868
|
+
if (r.ok)
|
|
36869
|
+
log4(`[chat ${chat2.id}] auto-titled: ${final}`);
|
|
36870
|
+
} catch {}
|
|
36709
36871
|
}
|
|
36710
36872
|
function buildChatPreamble(args2) {
|
|
36711
36873
|
const projectLine = args2.projectId ? `Default project: ${args2.projectId} (issue.create / issue.list use it when project_id is omitted).` : `No default project pinned to this chat. issue.create requires explicit project_id; otherwise the host returns [err] and skips.`;
|
|
@@ -36733,7 +36895,7 @@ Action vocabulary:
|
|
|
36733
36895
|
{"type":"issue.delete_where","status":"todo","limit":50},
|
|
36734
36896
|
{"type":"issue.list","status":"todo","limit":20},
|
|
36735
36897
|
{"type":"issue.search","query":"flaky tests","limit":10},
|
|
36736
|
-
{"type":"agent.create","name":"refactor-bot","
|
|
36898
|
+
{"type":"agent.create","name":"refactor-bot","prompt":"...","allowed_tools":["Read","Edit","Bash"]},
|
|
36737
36899
|
{"type":"agent.update","id":"ag_xxx","prompt":"..."},
|
|
36738
36900
|
{"type":"skill.create","name":"run-tests","description":"...","body":"---\\nname: run-tests\\n---\\n..."},
|
|
36739
36901
|
{"type":"skill.attach","agent_id":"ag_xxx","skill_id":"sk_yyy"},
|
|
@@ -37334,7 +37496,7 @@ import { parseArgs } from "util";
|
|
|
37334
37496
|
// package.json
|
|
37335
37497
|
var package_default = {
|
|
37336
37498
|
name: "@shipers-dev/multi",
|
|
37337
|
-
version: "0.
|
|
37499
|
+
version: "0.43.0",
|
|
37338
37500
|
type: "module",
|
|
37339
37501
|
bin: {
|
|
37340
37502
|
"multi-agent": "./dist/index.js"
|
|
@@ -37619,8 +37781,8 @@ init_errors();
|
|
|
37619
37781
|
|
|
37620
37782
|
class Worktree extends exports_Effect.Service()("cli/Worktree", {
|
|
37621
37783
|
succeed: {
|
|
37622
|
-
ensure: (workingDir, issueKey, issueId) => exports_Effect.tryPromise({
|
|
37623
|
-
try: () => ensureWorktree(workingDir, issueKey, issueId),
|
|
37784
|
+
ensure: (workingDir, issueKey, issueId, opts) => exports_Effect.tryPromise({
|
|
37785
|
+
try: () => ensureWorktree(workingDir, issueKey, issueId, opts),
|
|
37624
37786
|
catch: (cause3) => new WorktreeError({ message: `ensureWorktree failed`, cause: cause3 })
|
|
37625
37787
|
}),
|
|
37626
37788
|
isGitRepo: (dir) => exports_Effect.tryPromise({
|
|
@@ -38346,8 +38508,8 @@ init_errors();
|
|
|
38346
38508
|
|
|
38347
38509
|
class Worktree2 extends exports_Effect.Service()("cli/Worktree", {
|
|
38348
38510
|
succeed: {
|
|
38349
|
-
ensure: (workingDir, issueKey, issueId) => exports_Effect.tryPromise({
|
|
38350
|
-
try: () => ensureWorktree(workingDir, issueKey, issueId),
|
|
38511
|
+
ensure: (workingDir, issueKey, issueId, opts) => exports_Effect.tryPromise({
|
|
38512
|
+
try: () => ensureWorktree(workingDir, issueKey, issueId, opts),
|
|
38351
38513
|
catch: (cause3) => new WorktreeError({ message: `ensureWorktree failed`, cause: cause3 })
|
|
38352
38514
|
}),
|
|
38353
38515
|
isGitRepo: (dir) => exports_Effect.tryPromise({
|
|
@@ -38765,6 +38927,34 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
|
|
|
38765
38927
|
}
|
|
38766
38928
|
})();
|
|
38767
38929
|
}
|
|
38930
|
+
if (url2.pathname === "/run-chat-turn" && req.method === "POST") {
|
|
38931
|
+
if (req.headers.get("authorization") !== expectedAuth)
|
|
38932
|
+
return new Response("unauthorized", { status: 401 });
|
|
38933
|
+
return (async () => {
|
|
38934
|
+
try {
|
|
38935
|
+
const body = await req.json();
|
|
38936
|
+
if (!body?.chat_id || !body?.message_id) {
|
|
38937
|
+
return Response.json({ error: "chat_id and message_id required" }, { status: 400 });
|
|
38938
|
+
}
|
|
38939
|
+
if (!cfg.workspaceId || !cfg.authToken || !cfg.deviceId) {
|
|
38940
|
+
return Response.json({ error: "daemon not configured" }, { status: 503 });
|
|
38941
|
+
}
|
|
38942
|
+
const { runChatTurn: runChatTurn2 } = await Promise.resolve().then(() => (init_chat_supervisor(), exports_chat_supervisor));
|
|
38943
|
+
runChatTurn2({
|
|
38944
|
+
apiUrl,
|
|
38945
|
+
authToken: cfg.authToken,
|
|
38946
|
+
workspaceId: cfg.workspaceId,
|
|
38947
|
+
deviceId: cfg.deviceId,
|
|
38948
|
+
chatId: body.chat_id,
|
|
38949
|
+
messageId: body.message_id,
|
|
38950
|
+
log: log3
|
|
38951
|
+
}).catch((e) => log3(`[chat ${body.chat_id}] runChatTurn error: ${e.message}`));
|
|
38952
|
+
return Response.json({ accepted: true }, { status: 202 });
|
|
38953
|
+
} catch (e) {
|
|
38954
|
+
return Response.json({ error: String(e) }, { status: 400 });
|
|
38955
|
+
}
|
|
38956
|
+
})();
|
|
38957
|
+
}
|
|
38768
38958
|
if (url2.pathname === "/stop" && req.method === "POST") {
|
|
38769
38959
|
if (req.headers.get("authorization") !== expectedAuth)
|
|
38770
38960
|
return new Response("unauthorized", { status: 401 });
|
|
@@ -38826,19 +39016,6 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
|
|
|
38826
39016
|
catch: () => new DaemonError({ message: "materializeBundle skipped" })
|
|
38827
39017
|
}).pipe(exports_Effect.catchAll(() => exports_Effect.void));
|
|
38828
39018
|
const schedFiber = yield* exports_Effect.forkIn(daemonScope)(schedulerLoop(state, daemonScope));
|
|
38829
|
-
let chatSup = null;
|
|
38830
|
-
if (cfg.workspaceId && cfg.authToken && cfg.deviceId) {
|
|
38831
|
-
const { ChatSupervisor: ChatSupervisor2 } = yield* exports_Effect.promise(() => Promise.resolve().then(() => (init_chat_supervisor(), exports_chat_supervisor)));
|
|
38832
|
-
chatSup = new ChatSupervisor2({
|
|
38833
|
-
apiUrl,
|
|
38834
|
-
authToken: cfg.authToken,
|
|
38835
|
-
workspaceId: cfg.workspaceId,
|
|
38836
|
-
deviceId: cfg.deviceId,
|
|
38837
|
-
log: log3
|
|
38838
|
-
});
|
|
38839
|
-
chatSup.start();
|
|
38840
|
-
log3(`Chat supervisor started (device=${cfg.deviceId})`);
|
|
38841
|
-
}
|
|
38842
39019
|
if (cfg.workspaceId) {
|
|
38843
39020
|
yield* exports_Effect.forkIn(daemonScope)(exports_Effect.tryPromise({
|
|
38844
39021
|
try: () => drainOfflineDispatches(apiUrl, cfg.deviceId, cfg.workspaceId, cfg.dispatchSecret, db2, () => {
|
|
@@ -38928,9 +39105,6 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
|
|
|
38928
39105
|
try {
|
|
38929
39106
|
server.stop();
|
|
38930
39107
|
} catch {}
|
|
38931
|
-
try {
|
|
38932
|
-
chatSup?.close();
|
|
38933
|
-
} catch {}
|
|
38934
39108
|
try {
|
|
38935
39109
|
tunnel?.child?.kill();
|
|
38936
39110
|
} catch {}
|