@shipers-dev/multi 0.39.2 → 0.41.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 +481 -400
- package/dist/loro_wasm_bg-2zffq6w4.wasm +0 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33802,7 +33802,7 @@ function parsePlanBlocks(text) {
|
|
|
33802
33802
|
}
|
|
33803
33803
|
return { actions, errors: errors3 };
|
|
33804
33804
|
}
|
|
33805
|
-
var PLAN_SCHEMA_VERSION =
|
|
33805
|
+
var PLAN_SCHEMA_VERSION = 5, Priority, AssigneeType, IssueStatus, SessionRole, SkillFile, EvalPolicy, PlanActionSchema, PlanEnvelopeSchema, UiBlockSchema, UI_FENCE_RE, FENCE_RE;
|
|
33806
33806
|
var init_plans = __esm(() => {
|
|
33807
33807
|
init_zod();
|
|
33808
33808
|
Priority = exports_external.enum(["low", "medium", "high"]);
|
|
@@ -33810,6 +33810,12 @@ var init_plans = __esm(() => {
|
|
|
33810
33810
|
IssueStatus = exports_external.enum(["todo", "in_progress", "done", "failed", "stopped", "cancelled"]);
|
|
33811
33811
|
SessionRole = exports_external.enum(["implementer", "reviewer", "test-fixer"]);
|
|
33812
33812
|
SkillFile = exports_external.object({ path: exports_external.string().min(1), content: exports_external.string() });
|
|
33813
|
+
EvalPolicy = exports_external.object({
|
|
33814
|
+
evaluator_agent_id: exports_external.string().min(1),
|
|
33815
|
+
threshold: exports_external.number().min(0).max(1),
|
|
33816
|
+
on_fail: exports_external.enum(["retry", "fail", "comment"]).optional(),
|
|
33817
|
+
max_retries: exports_external.number().int().min(0).max(10).optional()
|
|
33818
|
+
});
|
|
33813
33819
|
PlanActionSchema = exports_external.discriminatedUnion("type", [
|
|
33814
33820
|
exports_external.object({
|
|
33815
33821
|
type: exports_external.literal("create"),
|
|
@@ -33820,7 +33826,9 @@ var init_plans = __esm(() => {
|
|
|
33820
33826
|
assignee_type: AssigneeType.optional(),
|
|
33821
33827
|
assignee_id: exports_external.string().optional(),
|
|
33822
33828
|
parent_id: exports_external.string().optional(),
|
|
33823
|
-
blocked_by: exports_external.array(exports_external.string().min(1)).optional()
|
|
33829
|
+
blocked_by: exports_external.array(exports_external.string().min(1)).optional(),
|
|
33830
|
+
await_children: exports_external.boolean().optional(),
|
|
33831
|
+
eval_policy: EvalPolicy.optional()
|
|
33824
33832
|
}),
|
|
33825
33833
|
exports_external.object({
|
|
33826
33834
|
type: exports_external.literal("update"),
|
|
@@ -33831,7 +33839,8 @@ var init_plans = __esm(() => {
|
|
|
33831
33839
|
priority: Priority.optional(),
|
|
33832
33840
|
assignee_type: AssigneeType.optional(),
|
|
33833
33841
|
assignee_id: exports_external.string().optional(),
|
|
33834
|
-
blocked_by: exports_external.array(exports_external.string().min(1)).optional()
|
|
33842
|
+
blocked_by: exports_external.array(exports_external.string().min(1)).optional(),
|
|
33843
|
+
eval_policy: EvalPolicy.nullable().optional()
|
|
33835
33844
|
}),
|
|
33836
33845
|
exports_external.object({
|
|
33837
33846
|
type: exports_external.literal("delegate"),
|
|
@@ -33870,7 +33879,7 @@ var init_plans = __esm(() => {
|
|
|
33870
33879
|
exports_external.object({
|
|
33871
33880
|
type: exports_external.literal("agent.create"),
|
|
33872
33881
|
name: exports_external.string().min(1).max(120),
|
|
33873
|
-
agent_type: exports_external.string().min(1),
|
|
33882
|
+
agent_type: exports_external.string().min(1).optional(),
|
|
33874
33883
|
prompt: exports_external.string().optional(),
|
|
33875
33884
|
skill_ids: exports_external.array(exports_external.string()).optional(),
|
|
33876
33885
|
allowed_tools: exports_external.array(exports_external.string()).optional()
|
|
@@ -33906,6 +33915,13 @@ var init_plans = __esm(() => {
|
|
|
33906
33915
|
agent_id: exports_external.string().min(1),
|
|
33907
33916
|
role: SessionRole,
|
|
33908
33917
|
device_id: exports_external.string().optional()
|
|
33918
|
+
}),
|
|
33919
|
+
exports_external.object({
|
|
33920
|
+
type: exports_external.literal("eval.submit"),
|
|
33921
|
+
id: exports_external.string().min(1).optional(),
|
|
33922
|
+
score: exports_external.number().min(0).max(1),
|
|
33923
|
+
feedback: exports_external.string().min(1).max(8000),
|
|
33924
|
+
scores: exports_external.record(exports_external.string(), exports_external.number().min(0).max(1)).optional()
|
|
33909
33925
|
})
|
|
33910
33926
|
]);
|
|
33911
33927
|
PlanEnvelopeSchema = exports_external.object({
|
|
@@ -34925,7 +34941,7 @@ Agent + skill self-service (use sparingly — only when you genuinely need a new
|
|
|
34925
34941
|
|
|
34926
34942
|
\`\`\`multi-plan
|
|
34927
34943
|
{"actions":[
|
|
34928
|
-
{"type":"agent.create","name":"refactor-bot","
|
|
34944
|
+
{"type":"agent.create","name":"refactor-bot","prompt":"You refactor TS code...","skill_ids":["sk_xxx"],"allowed_tools":["Read","Edit","Bash"]},
|
|
34929
34945
|
{"type":"agent.update","id":"ag_xxx","prompt":"new prompt..."},
|
|
34930
34946
|
{"type":"skill.create","name":"run-tests","description":"Run the test suite","body":"---\\nname: run-tests\\n---\\n\\n# Run tests\\n..."},
|
|
34931
34947
|
{"type":"skill.attach","agent_id":"ag_xxx","skill_id":"sk_yyy"},
|
|
@@ -34950,8 +34966,11 @@ ${agentsBlock}
|
|
|
34950
34966
|
}
|
|
34951
34967
|
async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors = []) {
|
|
34952
34968
|
const lines = [];
|
|
34953
|
-
|
|
34969
|
+
const results = [];
|
|
34970
|
+
for (const e of parseErrors) {
|
|
34954
34971
|
lines.push(`- [err] plan parse: ${e.message}`);
|
|
34972
|
+
results.push({ type: "parse", status: "error", error: e.message });
|
|
34973
|
+
}
|
|
34955
34974
|
let truncated = false;
|
|
34956
34975
|
if (actions.length > PLAN_ACTION_LIMIT) {
|
|
34957
34976
|
truncated = true;
|
|
@@ -34961,8 +34980,10 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
34961
34980
|
if (depth >= PLANNING_DEPTH_LIMIT) {
|
|
34962
34981
|
const blocked3 = actions.filter((a) => a.type !== "update").length;
|
|
34963
34982
|
actions = actions.filter((a) => a.type === "update");
|
|
34964
|
-
if (blocked3)
|
|
34983
|
+
if (blocked3) {
|
|
34965
34984
|
lines.push(`- [warn] ${blocked3} non-update action(s) blocked (planning depth limit ${PLANNING_DEPTH_LIMIT})`);
|
|
34985
|
+
results.push({ type: "note", status: "note", message: `${blocked3} non-update action(s) blocked (planning depth limit ${PLANNING_DEPTH_LIMIT})` });
|
|
34986
|
+
}
|
|
34966
34987
|
}
|
|
34967
34988
|
const SUBCAPS = { "agent.create": 2, "skill.create": 3, "skill.attach": 5, "skill.detach": 5, "agent.update": 5, "session.create": 3 };
|
|
34968
34989
|
const counts = {};
|
|
@@ -34973,6 +34994,7 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
34973
34994
|
counts[a.type] = (counts[a.type] || 0) + 1;
|
|
34974
34995
|
if (counts[a.type] > cap) {
|
|
34975
34996
|
lines.push(`- [warn] ${a.type} sub-cap ${cap} hit, dropping extra`);
|
|
34997
|
+
results.push({ type: a.type, status: "note", message: `${a.type} sub-cap ${cap} hit, dropping extra` });
|
|
34976
34998
|
return false;
|
|
34977
34999
|
}
|
|
34978
35000
|
return true;
|
|
@@ -35013,17 +35035,21 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35013
35035
|
const res = await apiClient.post(mutateUrl, body, { headers });
|
|
35014
35036
|
if (!res.success) {
|
|
35015
35037
|
lines.push(`- [err] create "${a.title}": ${res.error || res.status}`);
|
|
35038
|
+
results.push({ type: "create", status: "error", error: String(res.error || res.status), label: a.title });
|
|
35016
35039
|
continue;
|
|
35017
35040
|
}
|
|
35018
35041
|
const created = res.data;
|
|
35019
35042
|
lines.push(`- [ok] created **${created.key}** - ${created.title}${created.assignee_id ? ` -> @${created.assignee_id}` : ""} (autonomy=${created.autonomy_level || "auto"})`);
|
|
35043
|
+
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
35044
|
} else if (a.type === "update") {
|
|
35021
35045
|
const res = await apiClient.post(mutateUrl, { action: "update", ...a }, { headers });
|
|
35022
35046
|
if (!res.success) {
|
|
35023
35047
|
lines.push(`- [err] update ${a.id}: ${res.error || res.status}`);
|
|
35048
|
+
results.push({ type: "update", status: "error", error: String(res.error || res.status), label: a.id });
|
|
35024
35049
|
continue;
|
|
35025
35050
|
}
|
|
35026
35051
|
lines.push(`- [ok] updated ${res.data.key}`);
|
|
35052
|
+
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
35053
|
if ((a.status === "done" || a.status === "cancelled") && parentTask.working_dir && existsSync11(parentTask.working_dir)) {
|
|
35028
35054
|
const targetKey = res.data?.key;
|
|
35029
35055
|
if (targetKey) {
|
|
@@ -35038,9 +35064,11 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35038
35064
|
const res = await apiClient.post(mutateUrl, { action: "update", id: a.id, assignee_type: "agent", assignee_id: a.assignee_id, status: "todo" }, { headers });
|
|
35039
35065
|
if (!res.success) {
|
|
35040
35066
|
lines.push(`- [err] delegate ${a.id}: ${res.error || res.status}`);
|
|
35067
|
+
results.push({ type: "delegate", status: "error", error: String(res.error || res.status), label: a.id });
|
|
35041
35068
|
continue;
|
|
35042
35069
|
}
|
|
35043
35070
|
lines.push(`- [ok] delegated ${res.data.key} -> ${a.assignee_id}`);
|
|
35071
|
+
results.push({ type: "delegate", status: "ok", issue_id: res.data.id, key: res.data.key, assignee_id: a.assignee_id });
|
|
35044
35072
|
} else if (a.type === "handoff") {
|
|
35045
35073
|
const res = await apiClient.post(mutateUrl, {
|
|
35046
35074
|
action: "handoff",
|
|
@@ -35052,17 +35080,21 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35052
35080
|
}, { headers });
|
|
35053
35081
|
if (!res.success) {
|
|
35054
35082
|
lines.push(`- [err] handoff -> ${a.target_agent_id}: ${res.error || res.status}`);
|
|
35083
|
+
results.push({ type: "handoff", status: "error", error: String(res.error || res.status), label: a.target_agent_id });
|
|
35055
35084
|
continue;
|
|
35056
35085
|
}
|
|
35057
35086
|
const blocked3 = res.data?.blocked ? " (blocked parent)" : "";
|
|
35058
35087
|
lines.push(`- [ok] handoff -> ${a.target_agent_id} via **${res.data?.child_key}**${blocked3} expect=${a.expect ?? "summary"}`);
|
|
35088
|
+
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
35089
|
} else if (a.type === "issue.delete") {
|
|
35060
35090
|
const res = await apiClient.post(mutateUrl, { action: "delete", id: a.id }, { headers });
|
|
35061
35091
|
if (!res.success) {
|
|
35062
35092
|
lines.push(`- [err] issue.delete ${a.id}: ${res.error || res.status}`);
|
|
35093
|
+
results.push({ type: "issue.delete", status: "error", error: String(res.error || res.status), label: a.id });
|
|
35063
35094
|
continue;
|
|
35064
35095
|
}
|
|
35065
35096
|
lines.push(`- [ok] deleted ${res.data?.key || a.id}`);
|
|
35097
|
+
results.push({ type: "issue.delete", status: "ok", key: res.data?.key || a.id, issue_id: res.data?.id || a.id });
|
|
35066
35098
|
} else if (a.type === "issue.delete_where") {
|
|
35067
35099
|
const res = await apiClient.post(mutateUrl, {
|
|
35068
35100
|
action: "delete_where",
|
|
@@ -35073,17 +35105,20 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35073
35105
|
}, { headers });
|
|
35074
35106
|
if (!res.success) {
|
|
35075
35107
|
lines.push(`- [err] issue.delete_where: ${res.error || res.status}`);
|
|
35108
|
+
results.push({ type: "issue.delete_where", status: "error", error: String(res.error || res.status) });
|
|
35076
35109
|
continue;
|
|
35077
35110
|
}
|
|
35078
35111
|
const rows = Array.isArray(res.data?.deleted) ? res.data.deleted : [];
|
|
35079
35112
|
const count3 = res.data?.count ?? rows.length;
|
|
35080
35113
|
if (!count3) {
|
|
35081
35114
|
lines.push(`- [ok] issue.delete_where: 0 matches`);
|
|
35115
|
+
results.push({ type: "issue.delete_where", status: "ok", count: 0, keys: [] });
|
|
35082
35116
|
continue;
|
|
35083
35117
|
}
|
|
35084
35118
|
lines.push(`- [ok] issue.delete_where: deleted ${count3} issue(s)`);
|
|
35085
35119
|
for (const r of rows)
|
|
35086
35120
|
lines.push(` - ${r.key}`);
|
|
35121
|
+
results.push({ type: "issue.delete_where", status: "ok", count: count3, keys: rows.map((r) => r.key) });
|
|
35087
35122
|
} else if (a.type === "issue.list") {
|
|
35088
35123
|
const res = await apiClient.post(queryUrl, {
|
|
35089
35124
|
kind: "list",
|
|
@@ -35094,17 +35129,20 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35094
35129
|
}, { headers });
|
|
35095
35130
|
if (!res.success) {
|
|
35096
35131
|
lines.push(`- [err] issue.list: ${res.error || res.status}`);
|
|
35132
|
+
results.push({ type: "issue.list", status: "error", error: String(res.error || res.status) });
|
|
35097
35133
|
continue;
|
|
35098
35134
|
}
|
|
35099
35135
|
const rows = Array.isArray(res.data) ? res.data : Array.isArray(res.data?.results) ? res.data.results : [];
|
|
35100
35136
|
if (!rows.length) {
|
|
35101
35137
|
lines.push(`- [ok] issue.list: 0 issues`);
|
|
35138
|
+
results.push({ type: "issue.list", status: "ok", count: 0 });
|
|
35102
35139
|
continue;
|
|
35103
35140
|
}
|
|
35104
35141
|
lines.push(`- [ok] issue.list: ${rows.length} issue(s)`);
|
|
35105
35142
|
for (const r of rows) {
|
|
35106
35143
|
lines.push(` - **${r.key}** [${r.status}] ${r.title}${r.assignee_id ? ` (@${r.assignee_id})` : ""}`);
|
|
35107
35144
|
}
|
|
35145
|
+
results.push({ type: "issue.list", status: "ok", count: rows.length });
|
|
35108
35146
|
} else if (a.type === "issue.search") {
|
|
35109
35147
|
const res = await apiClient.post(queryUrl, {
|
|
35110
35148
|
kind: "search",
|
|
@@ -35114,75 +35152,95 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35114
35152
|
}, { headers });
|
|
35115
35153
|
if (!res.success) {
|
|
35116
35154
|
lines.push(`- [err] issue.search "${a.query}": ${res.error || res.status}`);
|
|
35155
|
+
results.push({ type: "issue.search", status: "error", error: String(res.error || res.status), label: a.query });
|
|
35117
35156
|
continue;
|
|
35118
35157
|
}
|
|
35119
35158
|
const rows = Array.isArray(res.data) ? res.data : Array.isArray(res.data?.results) ? res.data.results : [];
|
|
35120
35159
|
if (!rows.length) {
|
|
35121
35160
|
lines.push(`- [ok] issue.search "${a.query}": 0 hits`);
|
|
35161
|
+
results.push({ type: "issue.search", status: "ok", count: 0, query: a.query });
|
|
35122
35162
|
continue;
|
|
35123
35163
|
}
|
|
35124
35164
|
lines.push(`- [ok] issue.search "${a.query}": ${rows.length} hit(s)`);
|
|
35125
35165
|
for (const r of rows) {
|
|
35126
35166
|
lines.push(` - **${r.key}** [${r.status}] ${r.title}`);
|
|
35127
35167
|
}
|
|
35168
|
+
results.push({ type: "issue.search", status: "ok", count: rows.length, query: a.query });
|
|
35128
35169
|
} else if (a.type === "agent.create") {
|
|
35129
35170
|
if (!parentWsId) {
|
|
35130
35171
|
lines.push(`- [err] agent.create "${a.name}": no tenant workspace id`);
|
|
35172
|
+
results.push({ type: "agent.create", status: "error", error: "no tenant workspace id", label: a.name });
|
|
35131
35173
|
continue;
|
|
35132
35174
|
}
|
|
35133
|
-
const res = await apiClient.post(`${apiUrl}/api/workspaces/${parentWsId}/agent_ops/agents/mutate`, { action: "create", name: a.name,
|
|
35175
|
+
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
35176
|
if (!res.success) {
|
|
35135
35177
|
lines.push(`- [err] agent.create "${a.name}": ${res.error || res.status}`);
|
|
35178
|
+
results.push({ type: "agent.create", status: "error", error: String(res.error || res.status), label: a.name });
|
|
35136
35179
|
continue;
|
|
35137
35180
|
}
|
|
35138
35181
|
lines.push(`- [ok] agent.create "${a.name}" -> ${res.data?.agent_id}`);
|
|
35182
|
+
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
35183
|
} else if (a.type === "agent.update") {
|
|
35140
35184
|
if (!parentWsId) {
|
|
35141
35185
|
lines.push(`- [err] agent.update ${a.id}: no tenant workspace id`);
|
|
35186
|
+
results.push({ type: "agent.update", status: "error", error: "no tenant workspace id", label: a.id });
|
|
35142
35187
|
continue;
|
|
35143
35188
|
}
|
|
35144
35189
|
const res = await apiClient.post(`${apiUrl}/api/workspaces/${parentWsId}/agent_ops/agents/mutate`, { action: "update", ...a }, { headers });
|
|
35145
35190
|
if (!res.success) {
|
|
35146
35191
|
lines.push(`- [err] agent.update ${a.id}: ${res.error || res.status}`);
|
|
35192
|
+
results.push({ type: "agent.update", status: "error", error: String(res.error || res.status), label: a.id });
|
|
35147
35193
|
continue;
|
|
35148
35194
|
}
|
|
35149
|
-
|
|
35195
|
+
const changed = ["name", "prompt", "allowed_tools"].filter((k) => a[k] !== undefined);
|
|
35196
|
+
if (res.data?.queued) {
|
|
35150
35197
|
lines.push(`- [pending] agent.update ${a.id} queued`);
|
|
35151
|
-
|
|
35198
|
+
results.push({ type: "agent.update", status: "ok", agent_id: a.id, queued: true, pending_op_id: res.data?.pending_op_id, changed });
|
|
35199
|
+
} else {
|
|
35152
35200
|
lines.push(`- [ok] agent.update ${a.id}`);
|
|
35201
|
+
results.push({ type: "agent.update", status: "ok", agent_id: a.id, queued: false, changed });
|
|
35202
|
+
}
|
|
35153
35203
|
} else if (a.type === "skill.create") {
|
|
35154
35204
|
if (!parentWsId) {
|
|
35155
35205
|
lines.push(`- [err] skill.create "${a.name}": no tenant workspace id`);
|
|
35206
|
+
results.push({ type: "skill.create", status: "error", error: "no tenant workspace id", label: a.name });
|
|
35156
35207
|
continue;
|
|
35157
35208
|
}
|
|
35158
35209
|
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
35210
|
if (!res.success) {
|
|
35160
35211
|
lines.push(`- [err] skill.create "${a.name}": ${res.error || res.status}`);
|
|
35212
|
+
results.push({ type: "skill.create", status: "error", error: String(res.error || res.status), label: a.name });
|
|
35161
35213
|
continue;
|
|
35162
35214
|
}
|
|
35163
35215
|
lines.push(`- [pending] skill.create "${a.name}" queued for human review (op ${res.data?.pending_op_id})`);
|
|
35216
|
+
results.push({ type: "skill.create", status: "ok", pending_op_id: res.data?.pending_op_id, name: a.name, description: a.description });
|
|
35164
35217
|
} else if (a.type === "session.create") {
|
|
35165
35218
|
if (!parentWsId) {
|
|
35166
35219
|
lines.push(`- [err] session.create role=${a.role}: no tenant workspace id`);
|
|
35220
|
+
results.push({ type: "session.create", status: "error", error: "no tenant workspace id" });
|
|
35167
35221
|
continue;
|
|
35168
35222
|
}
|
|
35169
35223
|
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
35224
|
if (!res.success) {
|
|
35171
35225
|
lines.push(`- [err] session.create role=${a.role}: ${res.error || res.status}`);
|
|
35226
|
+
results.push({ type: "session.create", status: "error", error: String(res.error || res.status) });
|
|
35172
35227
|
continue;
|
|
35173
35228
|
}
|
|
35174
35229
|
const sess = res.data?.session;
|
|
35175
35230
|
const reused = res.data?.reused;
|
|
35176
35231
|
lines.push(`- [${reused ? "reuse" : "ok"}] session.${reused ? "reuse" : "create"} ${sess?.id?.slice(0, 8) || "?"} (role=${a.role})`);
|
|
35232
|
+
results.push({ type: "session.create", status: "ok", session_id: sess?.id, role: a.role, agent_id: a.agent_id, reused: !!reused });
|
|
35177
35233
|
} else if (a.type === "eval.submit") {
|
|
35178
35234
|
if (!parentWsId) {
|
|
35179
35235
|
lines.push(`- [err] eval.submit: no tenant workspace id`);
|
|
35236
|
+
results.push({ type: "eval.submit", status: "error", error: "no tenant workspace id" });
|
|
35180
35237
|
continue;
|
|
35181
35238
|
}
|
|
35182
35239
|
const url2 = `${apiUrl}/api/workspaces/${parentWsId}/agent/issues/eval/submit`;
|
|
35183
35240
|
const res = await apiClient.post(url2, { id: a.id, score: a.score, feedback: a.feedback, scores: a.scores }, { headers });
|
|
35184
35241
|
if (!res.success) {
|
|
35185
35242
|
lines.push(`- [err] eval.submit: ${res.error || res.status}`);
|
|
35243
|
+
results.push({ type: "eval.submit", status: "error", error: String(res.error || res.status) });
|
|
35186
35244
|
continue;
|
|
35187
35245
|
}
|
|
35188
35246
|
const verdict = res.data?.verdict;
|
|
@@ -35190,34 +35248,48 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35190
35248
|
const attempt = res.data?.attempt;
|
|
35191
35249
|
const tag3 = verdict === "pass" ? "ok" : "warn";
|
|
35192
35250
|
lines.push(`- [${tag3}] eval.submit verdict=${verdict} score=${a.score.toFixed(2)} attempt=${attempt}${action ? ` action=${action}` : ""}`);
|
|
35251
|
+
results.push({ type: "eval.submit", status: "ok", verdict, score: a.score, attempt, action_taken: action });
|
|
35193
35252
|
} else if (a.type === "skill.attach" || a.type === "skill.detach") {
|
|
35194
35253
|
const action = a.type === "skill.attach" ? "attach_skill" : "detach_skill";
|
|
35195
35254
|
if (!parentWsId) {
|
|
35196
35255
|
lines.push(`- [err] ${a.type}: no tenant workspace id`);
|
|
35256
|
+
results.push({ type: a.type, status: "error", error: "no tenant workspace id" });
|
|
35197
35257
|
continue;
|
|
35198
35258
|
}
|
|
35199
35259
|
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
35260
|
if (!res.success) {
|
|
35201
35261
|
lines.push(`- [err] ${a.type} ${a.skill_id}->${a.agent_id}: ${res.error || res.status}`);
|
|
35262
|
+
results.push({ type: a.type, status: "error", error: String(res.error || res.status), label: `${a.skill_id}->${a.agent_id}` });
|
|
35202
35263
|
continue;
|
|
35203
35264
|
}
|
|
35204
|
-
if (res.data?.queued)
|
|
35265
|
+
if (res.data?.queued) {
|
|
35205
35266
|
lines.push(`- [pending] ${a.type} queued`);
|
|
35206
|
-
|
|
35267
|
+
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 });
|
|
35268
|
+
} else {
|
|
35207
35269
|
lines.push(`- [ok] ${a.type} ${a.skill_id} <-> ${a.agent_id}`);
|
|
35270
|
+
results.push({ type: a.type, status: "ok", agent_id: a.agent_id, skill_id: a.skill_id, queued: false });
|
|
35271
|
+
}
|
|
35208
35272
|
}
|
|
35209
35273
|
} catch (e) {
|
|
35210
35274
|
lines.push(`- [err] ${a.type} failed: ${String(e)}`);
|
|
35275
|
+
results.push({ type: a.type, status: "error", error: String(e) });
|
|
35211
35276
|
}
|
|
35212
35277
|
}
|
|
35213
|
-
if (truncated)
|
|
35278
|
+
if (truncated) {
|
|
35214
35279
|
lines.push(`- [warn] action list truncated at ${PLAN_ACTION_LIMIT}`);
|
|
35280
|
+
results.push({ type: "note", status: "note", message: `Action list truncated at ${PLAN_ACTION_LIMIT}` });
|
|
35281
|
+
}
|
|
35215
35282
|
if (!lines.length)
|
|
35216
35283
|
return "";
|
|
35284
|
+
const json2 = JSON.stringify({ version: 1, actions: results });
|
|
35217
35285
|
return `**Planning actions**
|
|
35218
35286
|
|
|
35219
35287
|
${lines.join(`
|
|
35220
|
-
`)}
|
|
35288
|
+
`)}
|
|
35289
|
+
|
|
35290
|
+
\`\`\`multi-actions
|
|
35291
|
+
${json2}
|
|
35292
|
+
\`\`\``;
|
|
35221
35293
|
}
|
|
35222
35294
|
function stripMd(s) {
|
|
35223
35295
|
return s.replace(/[`*_]/g, "").trim();
|
|
@@ -35822,6 +35894,22 @@ class ChatPeer {
|
|
|
35822
35894
|
getDoc() {
|
|
35823
35895
|
return this.doc;
|
|
35824
35896
|
}
|
|
35897
|
+
findMessage(id3) {
|
|
35898
|
+
for (const m of listMessages(this.doc))
|
|
35899
|
+
if (m.id === id3)
|
|
35900
|
+
return m;
|
|
35901
|
+
return null;
|
|
35902
|
+
}
|
|
35903
|
+
async awaitMessage(id3, timeoutMs = 5000) {
|
|
35904
|
+
const start3 = Date.now();
|
|
35905
|
+
while (Date.now() - start3 < timeoutMs) {
|
|
35906
|
+
const found = this.findMessage(id3);
|
|
35907
|
+
if (found)
|
|
35908
|
+
return found;
|
|
35909
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
35910
|
+
}
|
|
35911
|
+
return null;
|
|
35912
|
+
}
|
|
35825
35913
|
start() {
|
|
35826
35914
|
this.connect();
|
|
35827
35915
|
}
|
|
@@ -35898,8 +35986,9 @@ class ChatPeer {
|
|
|
35898
35986
|
if (before2.has(m.id))
|
|
35899
35987
|
continue;
|
|
35900
35988
|
this.seenIds.add(m.id);
|
|
35901
|
-
if (m.author?.kind === "user" && !m.partial) {
|
|
35902
|
-
|
|
35989
|
+
if (m.author?.kind === "user" && !m.partial && this.opts.onUserMessage) {
|
|
35990
|
+
const cb = this.opts.onUserMessage;
|
|
35991
|
+
Promise.resolve().then(() => cb(m, this)).catch((e) => this.opts.log(`[chat ${this.chatId}] onUserMessage error: ${e.message}`));
|
|
35903
35992
|
}
|
|
35904
35993
|
}
|
|
35905
35994
|
this.dirtySinceWrite++;
|
|
@@ -36046,8 +36135,11 @@ var init_chat_turn = __esm(() => {
|
|
|
36046
36135
|
// src/_impl/chat-plan-actions.ts
|
|
36047
36136
|
async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
36048
36137
|
const lines = [];
|
|
36049
|
-
|
|
36138
|
+
const results = [];
|
|
36139
|
+
for (const e of parseErrors) {
|
|
36050
36140
|
lines.push(`- [err] plan parse: ${e.message}`);
|
|
36141
|
+
results.push({ type: "parse", status: "error", error: e.message });
|
|
36142
|
+
}
|
|
36051
36143
|
let actions = actionsIn;
|
|
36052
36144
|
let truncated = false;
|
|
36053
36145
|
if (actions.length > PLAN_ACTION_LIMIT2) {
|
|
@@ -36062,6 +36154,7 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36062
36154
|
counts[a.type] = (counts[a.type] || 0) + 1;
|
|
36063
36155
|
if (counts[a.type] > cap) {
|
|
36064
36156
|
lines.push(`- [warn] ${a.type} sub-cap ${cap} hit, dropping extra`);
|
|
36157
|
+
results.push({ type: a.type, status: "note", message: `${a.type} sub-cap ${cap} hit, dropping extra` });
|
|
36065
36158
|
return false;
|
|
36066
36159
|
}
|
|
36067
36160
|
return true;
|
|
@@ -36092,6 +36185,7 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36092
36185
|
const project_id = a.project_id || ctx.projectId;
|
|
36093
36186
|
if (!project_id) {
|
|
36094
36187
|
lines.push(`- [err] create "${a.title}": project_id required (chat has no pinned project)`);
|
|
36188
|
+
results.push({ type: "create", status: "error", error: "project_id required (chat has no pinned project)", label: a.title });
|
|
36095
36189
|
tally(false);
|
|
36096
36190
|
continue;
|
|
36097
36191
|
}
|
|
@@ -36108,29 +36202,35 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36108
36202
|
const res = await apiClient.post(mutateUrl, body, { headers });
|
|
36109
36203
|
if (!res.success) {
|
|
36110
36204
|
lines.push(`- [err] create "${a.title}": ${res.error || res.status}`);
|
|
36205
|
+
results.push({ type: "create", status: "error", error: String(res.error || res.status), label: a.title });
|
|
36111
36206
|
tally(false);
|
|
36112
36207
|
continue;
|
|
36113
36208
|
}
|
|
36114
36209
|
const created = res.data;
|
|
36115
36210
|
lines.push(`- [ok] created **${created.key}** - ${created.title}${created.assignee_id ? ` -> @${created.assignee_id}` : ""}`);
|
|
36211
|
+
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
36212
|
tally(true);
|
|
36117
36213
|
} else if (a.type === "update") {
|
|
36118
36214
|
const res = await apiClient.post(mutateUrl, { action: "update", ...a }, { headers });
|
|
36119
36215
|
if (!res.success) {
|
|
36120
36216
|
lines.push(`- [err] update ${a.id}: ${res.error || res.status}`);
|
|
36217
|
+
results.push({ type: "update", status: "error", error: String(res.error || res.status), label: a.id });
|
|
36121
36218
|
tally(false);
|
|
36122
36219
|
continue;
|
|
36123
36220
|
}
|
|
36124
36221
|
lines.push(`- [ok] updated ${res.data.key}`);
|
|
36222
|
+
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
36223
|
tally(true);
|
|
36126
36224
|
} else if (a.type === "delegate") {
|
|
36127
36225
|
const res = await apiClient.post(mutateUrl, { action: "update", id: a.id, assignee_type: "agent", assignee_id: a.assignee_id, status: "todo" }, { headers });
|
|
36128
36226
|
if (!res.success) {
|
|
36129
36227
|
lines.push(`- [err] delegate ${a.id}: ${res.error || res.status}`);
|
|
36228
|
+
results.push({ type: "delegate", status: "error", error: String(res.error || res.status), label: a.id });
|
|
36130
36229
|
tally(false);
|
|
36131
36230
|
continue;
|
|
36132
36231
|
}
|
|
36133
36232
|
lines.push(`- [ok] delegated ${res.data.key} -> ${a.assignee_id}`);
|
|
36233
|
+
results.push({ type: "delegate", status: "ok", issue_id: res.data.id, key: res.data.key, assignee_id: a.assignee_id });
|
|
36134
36234
|
tally(true);
|
|
36135
36235
|
} else if (a.type === "handoff") {
|
|
36136
36236
|
const res = await apiClient.post(mutateUrl, {
|
|
@@ -36143,40 +36243,48 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36143
36243
|
}, { headers });
|
|
36144
36244
|
if (!res.success) {
|
|
36145
36245
|
lines.push(`- [err] handoff -> ${a.target_agent_id}: ${res.error || res.status}`);
|
|
36246
|
+
results.push({ type: "handoff", status: "error", error: String(res.error || res.status), label: a.target_agent_id });
|
|
36146
36247
|
tally(false);
|
|
36147
36248
|
continue;
|
|
36148
36249
|
}
|
|
36149
36250
|
lines.push(`- [ok] handoff -> ${a.target_agent_id} via **${res.data?.child_key}** expect=${a.expect ?? "summary"}`);
|
|
36251
|
+
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
36252
|
tally(true);
|
|
36151
36253
|
} else if (a.type === "issue.comment") {
|
|
36152
36254
|
const res = await apiClient.post(mutateUrl, { action: "comment", id: a.id, body: a.body }, { headers });
|
|
36153
36255
|
if (!res.success) {
|
|
36154
36256
|
lines.push(`- [err] issue.comment ${a.id}: ${res.error || res.status}`);
|
|
36257
|
+
results.push({ type: "issue.comment", status: "error", error: String(res.error || res.status), label: a.id });
|
|
36155
36258
|
tally(false);
|
|
36156
36259
|
continue;
|
|
36157
36260
|
}
|
|
36158
36261
|
const dispatched = res.data?.dispatched;
|
|
36159
36262
|
lines.push(`- [ok] commented on ${a.id}${dispatched ? " -> dispatched agent" : ""}`);
|
|
36263
|
+
results.push({ type: "issue.comment", status: "ok", issue_id: a.id, dispatched: !!dispatched });
|
|
36160
36264
|
tally(true);
|
|
36161
36265
|
} else if (a.type === "issue.delete") {
|
|
36162
36266
|
const res = await apiClient.post(mutateUrl, { action: "delete", id: a.id }, { headers });
|
|
36163
36267
|
if (!res.success) {
|
|
36164
36268
|
lines.push(`- [err] issue.delete ${a.id}: ${res.error || res.status}`);
|
|
36269
|
+
results.push({ type: "issue.delete", status: "error", error: String(res.error || res.status), label: a.id });
|
|
36165
36270
|
tally(false);
|
|
36166
36271
|
continue;
|
|
36167
36272
|
}
|
|
36168
36273
|
lines.push(`- [ok] deleted ${res.data?.key || a.id}`);
|
|
36274
|
+
results.push({ type: "issue.delete", status: "ok", key: res.data?.key || a.id, issue_id: res.data?.id || a.id });
|
|
36169
36275
|
tally(true);
|
|
36170
36276
|
} else if (a.type === "issue.delete_where") {
|
|
36171
36277
|
const project_id = a.project_id || ctx.projectId;
|
|
36172
36278
|
if (!project_id) {
|
|
36173
36279
|
lines.push(`- [err] issue.delete_where: project_id required`);
|
|
36280
|
+
results.push({ type: "issue.delete_where", status: "error", error: "project_id required" });
|
|
36174
36281
|
tally(false);
|
|
36175
36282
|
continue;
|
|
36176
36283
|
}
|
|
36177
36284
|
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
36285
|
if (!res.success) {
|
|
36179
36286
|
lines.push(`- [err] issue.delete_where: ${res.error || res.status}`);
|
|
36287
|
+
results.push({ type: "issue.delete_where", status: "error", error: String(res.error || res.status) });
|
|
36180
36288
|
tally(false);
|
|
36181
36289
|
continue;
|
|
36182
36290
|
}
|
|
@@ -36185,18 +36293,21 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36185
36293
|
lines.push(`- [ok] issue.delete_where: deleted ${count3} issue(s)`);
|
|
36186
36294
|
for (const r of rows)
|
|
36187
36295
|
lines.push(` - ${r.key}`);
|
|
36296
|
+
results.push({ type: "issue.delete_where", status: "ok", count: count3, keys: rows.map((r) => r.key) });
|
|
36188
36297
|
tally(true);
|
|
36189
36298
|
} else if (a.type === "issue.list") {
|
|
36190
36299
|
const project_id = a.project_id || ctx.projectId;
|
|
36191
36300
|
const res = await apiClient.post(queryUrl, { kind: "list", project_id, status: a.status, assignee_id: a.assignee_id, limit: a.limit ?? 20 }, { headers });
|
|
36192
36301
|
if (!res.success) {
|
|
36193
36302
|
lines.push(`- [err] issue.list: ${res.error || res.status}`);
|
|
36303
|
+
results.push({ type: "issue.list", status: "error", error: String(res.error || res.status) });
|
|
36194
36304
|
tally(false);
|
|
36195
36305
|
continue;
|
|
36196
36306
|
}
|
|
36197
36307
|
const rows = Array.isArray(res.data) ? res.data : Array.isArray(res.data?.results) ? res.data.results : [];
|
|
36198
36308
|
if (!rows.length) {
|
|
36199
36309
|
lines.push(`- [ok] issue.list: 0 issues`);
|
|
36310
|
+
results.push({ type: "issue.list", status: "ok", count: 0 });
|
|
36200
36311
|
tally(true);
|
|
36201
36312
|
continue;
|
|
36202
36313
|
}
|
|
@@ -36204,12 +36315,14 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36204
36315
|
for (const r of rows) {
|
|
36205
36316
|
lines.push(` - **${r.key}** [${r.status}] ${r.title}${r.assignee_id ? ` (@${r.assignee_id})` : ""}`);
|
|
36206
36317
|
}
|
|
36318
|
+
results.push({ type: "issue.list", status: "ok", count: rows.length });
|
|
36207
36319
|
tally(true);
|
|
36208
36320
|
} else if (a.type === "issue.search") {
|
|
36209
36321
|
const project_id = a.project_id || ctx.projectId;
|
|
36210
36322
|
const res = await apiClient.post(queryUrl, { kind: "search", project_id, query: a.query, limit: a.limit ?? 10 }, { headers });
|
|
36211
36323
|
if (!res.success) {
|
|
36212
36324
|
lines.push(`- [err] issue.search "${a.query}": ${res.error || res.status}`);
|
|
36325
|
+
results.push({ type: "issue.search", status: "error", error: String(res.error || res.status), label: a.query });
|
|
36213
36326
|
tally(false);
|
|
36214
36327
|
continue;
|
|
36215
36328
|
}
|
|
@@ -36217,12 +36330,12 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36217
36330
|
lines.push(`- [ok] issue.search "${a.query}": ${rows.length} hit(s)`);
|
|
36218
36331
|
for (const r of rows)
|
|
36219
36332
|
lines.push(` - **${r.key}** [${r.status}] ${r.title}`);
|
|
36333
|
+
results.push({ type: "issue.search", status: "ok", count: rows.length, query: a.query });
|
|
36220
36334
|
tally(true);
|
|
36221
36335
|
} else if (a.type === "agent.create") {
|
|
36222
36336
|
const res = await apiClient.post(agentsMutateUrl, {
|
|
36223
36337
|
action: "create",
|
|
36224
36338
|
name: a.name,
|
|
36225
|
-
type: a.agent_type,
|
|
36226
36339
|
prompt: a.prompt,
|
|
36227
36340
|
skill_ids: a.skill_ids,
|
|
36228
36341
|
allowed_tools: a.allowed_tools,
|
|
@@ -36230,19 +36343,24 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36230
36343
|
}, { headers });
|
|
36231
36344
|
if (!res.success) {
|
|
36232
36345
|
lines.push(`- [err] agent.create "${a.name}": ${res.error || res.status}`);
|
|
36346
|
+
results.push({ type: "agent.create", status: "error", error: String(res.error || res.status), label: a.name });
|
|
36233
36347
|
tally(false);
|
|
36234
36348
|
continue;
|
|
36235
36349
|
}
|
|
36236
36350
|
lines.push(`- [ok] agent.create "${a.name}" -> ${res.data?.agent_id}`);
|
|
36351
|
+
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
36352
|
tally(true);
|
|
36238
36353
|
} else if (a.type === "agent.update") {
|
|
36239
36354
|
const res = await apiClient.post(agentsMutateUrl, { action: "update", ...a }, { headers });
|
|
36240
36355
|
if (!res.success) {
|
|
36241
36356
|
lines.push(`- [err] agent.update ${a.id}: ${res.error || res.status}`);
|
|
36357
|
+
results.push({ type: "agent.update", status: "error", error: String(res.error || res.status), label: a.id });
|
|
36242
36358
|
tally(false);
|
|
36243
36359
|
continue;
|
|
36244
36360
|
}
|
|
36361
|
+
const changed = ["name", "prompt", "allowed_tools"].filter((k) => a[k] !== undefined);
|
|
36245
36362
|
lines.push(res.data?.queued ? `- [pending] agent.update ${a.id} queued` : `- [ok] agent.update ${a.id}`);
|
|
36363
|
+
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
36364
|
tally(true);
|
|
36247
36365
|
} else if (a.type === "skill.create") {
|
|
36248
36366
|
const res = await apiClient.post(skillsMutateUrl, {
|
|
@@ -36255,53 +36373,68 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
36255
36373
|
}, { headers });
|
|
36256
36374
|
if (!res.success) {
|
|
36257
36375
|
lines.push(`- [err] skill.create "${a.name}": ${res.error || res.status}`);
|
|
36376
|
+
results.push({ type: "skill.create", status: "error", error: String(res.error || res.status), label: a.name });
|
|
36258
36377
|
tally(false);
|
|
36259
36378
|
continue;
|
|
36260
36379
|
}
|
|
36261
36380
|
const queued = res.data?.pending_op_id;
|
|
36262
36381
|
lines.push(queued ? `- [pending] skill.create "${a.name}" queued for human review (op ${queued})` : `- [ok] skill.create "${a.name}" -> ${res.data?.skill_id}`);
|
|
36382
|
+
results.push({ type: "skill.create", status: "ok", pending_op_id: queued, name: a.name, description: a.description });
|
|
36263
36383
|
tally(true);
|
|
36264
36384
|
} else if (a.type === "skill.attach" || a.type === "skill.detach") {
|
|
36265
36385
|
const action = a.type === "skill.attach" ? "attach_skill" : "detach_skill";
|
|
36266
36386
|
const res = await apiClient.post(agentsMutateUrl, { action, agent_id: a.agent_id, skill_id: a.skill_id }, { headers });
|
|
36267
36387
|
if (!res.success) {
|
|
36268
36388
|
lines.push(`- [err] ${a.type} ${a.skill_id}->${a.agent_id}: ${res.error || res.status}`);
|
|
36389
|
+
results.push({ type: a.type, status: "error", error: String(res.error || res.status), label: `${a.skill_id}->${a.agent_id}` });
|
|
36269
36390
|
tally(false);
|
|
36270
36391
|
continue;
|
|
36271
36392
|
}
|
|
36272
36393
|
lines.push(res.data?.queued ? `- [pending] ${a.type} queued` : `- [ok] ${a.type} ${a.skill_id} <-> ${a.agent_id}`);
|
|
36394
|
+
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
36395
|
tally(true);
|
|
36274
36396
|
} else if (a.type === "session.create") {
|
|
36275
36397
|
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
36398
|
if (!res.success) {
|
|
36277
36399
|
lines.push(`- [err] session.create role=${a.role}: ${res.error || res.status}`);
|
|
36400
|
+
results.push({ type: "session.create", status: "error", error: String(res.error || res.status) });
|
|
36278
36401
|
tally(false);
|
|
36279
36402
|
continue;
|
|
36280
36403
|
}
|
|
36281
36404
|
const sess = res.data?.session;
|
|
36282
36405
|
const reused = res.data?.reused;
|
|
36283
36406
|
lines.push(`- [${reused ? "reuse" : "ok"}] session.${reused ? "reuse" : "create"} ${sess?.id?.slice(0, 8) || "?"} (role=${a.role})`);
|
|
36407
|
+
results.push({ type: "session.create", status: "ok", session_id: sess?.id, role: a.role, agent_id: a.agent_id, reused: !!reused });
|
|
36284
36408
|
tally(true);
|
|
36285
36409
|
} else if (a.type === "eval.submit") {
|
|
36286
36410
|
lines.push(`- [err] eval.submit not allowed in chat (only inside an eval dispatch)`);
|
|
36411
|
+
results.push({ type: "eval.submit", status: "error", error: "eval.submit not allowed in chat" });
|
|
36287
36412
|
tally(false);
|
|
36288
36413
|
}
|
|
36289
36414
|
} catch (e) {
|
|
36290
36415
|
lines.push(`- [err] ${a.type} failed: ${String(e)}`);
|
|
36416
|
+
results.push({ type: a.type, status: "error", error: String(e) });
|
|
36291
36417
|
tally(false);
|
|
36292
36418
|
}
|
|
36293
36419
|
}
|
|
36294
|
-
if (truncated)
|
|
36420
|
+
if (truncated) {
|
|
36295
36421
|
lines.push(`- [warn] action list truncated at ${PLAN_ACTION_LIMIT2}`);
|
|
36296
|
-
|
|
36422
|
+
results.push({ type: "note", status: "note", message: `Action list truncated at ${PLAN_ACTION_LIMIT2}` });
|
|
36423
|
+
}
|
|
36424
|
+
return { ok, fail: fail12, lines, results };
|
|
36297
36425
|
}
|
|
36298
36426
|
function renderChatPlanSummary(res) {
|
|
36299
36427
|
if (!res.lines.length)
|
|
36300
36428
|
return "";
|
|
36429
|
+
const json2 = JSON.stringify({ version: 1, actions: res.results });
|
|
36301
36430
|
return `**Planning actions**
|
|
36302
36431
|
|
|
36303
36432
|
${res.lines.join(`
|
|
36304
|
-
`)}
|
|
36433
|
+
`)}
|
|
36434
|
+
|
|
36435
|
+
\`\`\`multi-actions
|
|
36436
|
+
${json2}
|
|
36437
|
+
\`\`\``;
|
|
36305
36438
|
}
|
|
36306
36439
|
var PLAN_ACTION_LIMIT2 = 10, SUBCAPS;
|
|
36307
36440
|
var init_chat_plan_actions = __esm(() => {
|
|
@@ -36321,391 +36454,327 @@ var init_chat_plan_actions = __esm(() => {
|
|
|
36321
36454
|
// src/_impl/chat-supervisor.ts
|
|
36322
36455
|
var exports_chat_supervisor = {};
|
|
36323
36456
|
__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();
|
|
36457
|
+
runChatTurn: () => runChatTurn
|
|
36458
|
+
});
|
|
36459
|
+
async function runChatTurn(opts) {
|
|
36460
|
+
const { apiUrl, authToken: authToken2, workspaceId, chatId, messageId, log: log4 } = opts;
|
|
36461
|
+
const headers = { authorization: `Bearer ${authToken2}` };
|
|
36462
|
+
const metaR = await fetch(`${apiUrl}/api/workspaces/${workspaceId}/chats/${chatId}`, { headers });
|
|
36463
|
+
if (!metaR.ok) {
|
|
36464
|
+
log4(`[chat ${chatId}] meta fetch failed: ${metaR.status}`);
|
|
36465
|
+
return;
|
|
36351
36466
|
}
|
|
36352
|
-
|
|
36353
|
-
|
|
36467
|
+
const chat2 = await metaR.json();
|
|
36468
|
+
const peer = new ChatPeer({
|
|
36469
|
+
apiUrl,
|
|
36470
|
+
authToken: authToken2,
|
|
36471
|
+
workspaceId,
|
|
36472
|
+
chatId,
|
|
36473
|
+
primaryAgentId: chat2.primary_agent_id,
|
|
36474
|
+
log: log4
|
|
36475
|
+
});
|
|
36476
|
+
peer.start();
|
|
36477
|
+
try {
|
|
36478
|
+
const msg = await peer.awaitMessage(messageId, 7000);
|
|
36479
|
+
if (!msg) {
|
|
36480
|
+
log4(`[chat ${chatId}] message ${messageId} not visible after sync; aborting`);
|
|
36354
36481
|
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
36482
|
}
|
|
36483
|
+
await processUserMessage(chat2, msg, peer, { apiUrl, authToken: authToken2, workspaceId, log: log4 });
|
|
36484
|
+
} finally {
|
|
36485
|
+
peer.close();
|
|
36384
36486
|
}
|
|
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;
|
|
36487
|
+
}
|
|
36488
|
+
async function fetchAgents(apiUrl, workspaceId, authToken2) {
|
|
36489
|
+
const headers = { authorization: `Bearer ${authToken2}` };
|
|
36490
|
+
try {
|
|
36491
|
+
const r = await fetch(`${apiUrl}/api/workspaces/${workspaceId}/agents`, { headers });
|
|
36492
|
+
if (!r.ok)
|
|
36493
|
+
return [];
|
|
36494
|
+
const body = await r.json();
|
|
36495
|
+
const arr = Array.isArray(body) ? body : Array.isArray(body.results) ? body.results : [];
|
|
36496
|
+
return arr.map((a) => ({ id: a.id, name: a.name }));
|
|
36497
|
+
} catch {
|
|
36498
|
+
return [];
|
|
36413
36499
|
}
|
|
36414
|
-
|
|
36415
|
-
|
|
36416
|
-
|
|
36417
|
-
|
|
36418
|
-
|
|
36419
|
-
|
|
36420
|
-
|
|
36421
|
-
|
|
36422
|
-
|
|
36423
|
-
|
|
36424
|
-
|
|
36425
|
-
|
|
36500
|
+
}
|
|
36501
|
+
function resolveAgentFromMention(agents, mentioned) {
|
|
36502
|
+
if (!mentioned)
|
|
36503
|
+
return null;
|
|
36504
|
+
const m = mentioned.toLowerCase();
|
|
36505
|
+
return agents.find((a) => a.name?.toLowerCase() === m || a.id === mentioned) ?? null;
|
|
36506
|
+
}
|
|
36507
|
+
async function resolveCwd(apiUrl, workspaceId, authToken2, chat2) {
|
|
36508
|
+
if (!chat2.project_id || !chat2.device_id)
|
|
36509
|
+
return;
|
|
36510
|
+
const headers = { authorization: `Bearer ${authToken2}` };
|
|
36511
|
+
try {
|
|
36512
|
+
const r = await fetch(`${apiUrl}/api/workspaces/${workspaceId}/projects/${chat2.project_id}/devices`, { headers });
|
|
36513
|
+
if (!r.ok)
|
|
36426
36514
|
return;
|
|
36427
|
-
|
|
36515
|
+
const body = await r.json();
|
|
36516
|
+
const row = body.results.find((d) => d.id === chat2.device_id);
|
|
36517
|
+
return row?.working_dir || undefined;
|
|
36518
|
+
} catch {
|
|
36519
|
+
return;
|
|
36428
36520
|
}
|
|
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 {
|
|
36521
|
+
}
|
|
36522
|
+
async function resolveAgentRuntime(apiUrl, workspaceId, authToken2, chat2, agentId) {
|
|
36523
|
+
if (chat2.runtime)
|
|
36524
|
+
return chat2.runtime;
|
|
36525
|
+
if (!agentId || typeof agentId !== "string")
|
|
36526
|
+
return null;
|
|
36527
|
+
const headers = { authorization: `Bearer ${authToken2}` };
|
|
36528
|
+
try {
|
|
36529
|
+
const r = await fetch(`${apiUrl}/api/workspaces/${workspaceId}/agents/${agentId}`, { headers });
|
|
36530
|
+
if (!r.ok)
|
|
36442
36531
|
return null;
|
|
36443
|
-
|
|
36532
|
+
const body = await r.json();
|
|
36533
|
+
return body.runtime || body.type || null;
|
|
36534
|
+
} catch {
|
|
36535
|
+
return null;
|
|
36444
36536
|
}
|
|
36445
|
-
|
|
36446
|
-
|
|
36447
|
-
|
|
36448
|
-
|
|
36449
|
-
|
|
36450
|
-
|
|
36451
|
-
|
|
36452
|
-
|
|
36453
|
-
|
|
36454
|
-
|
|
36455
|
-
|
|
36537
|
+
}
|
|
36538
|
+
async function processUserMessage(chat2, userMsg, peer, ctx) {
|
|
36539
|
+
const { apiUrl, authToken: authToken2, workspaceId, log: log4 } = ctx;
|
|
36540
|
+
log4(`[chat ${chat2.id}] user: ${userMsg.text.slice(0, 80)}`);
|
|
36541
|
+
const allAgents = await fetchAgents(apiUrl, workspaceId, authToken2);
|
|
36542
|
+
const mentioned = userMsg.mentions?.[0];
|
|
36543
|
+
const mentionAgent = resolveAgentFromMention(allAgents, mentioned);
|
|
36544
|
+
const resolvedAgentId = mentionAgent?.id ?? chat2.primary_agent_id ?? null;
|
|
36545
|
+
const agentAuthorId = resolvedAgentId || mentioned || "agent";
|
|
36546
|
+
const runtime4 = await resolveAgentRuntime(apiUrl, workspaceId, authToken2, chat2, resolvedAgentId);
|
|
36547
|
+
const cwd = await resolveCwd(apiUrl, workspaceId, authToken2, chat2);
|
|
36548
|
+
if (cwd)
|
|
36549
|
+
log4(`[chat ${chat2.id}] cwd=${cwd}`);
|
|
36550
|
+
if (mentionAgent)
|
|
36551
|
+
log4(`[chat ${chat2.id}] mention → ${mentionAgent.name}`);
|
|
36552
|
+
let textContainerId = null;
|
|
36553
|
+
let buffered = "";
|
|
36554
|
+
let lastFlush = Date.now();
|
|
36555
|
+
let agentReplyText = "";
|
|
36556
|
+
const toolMsgByCallId = new Map;
|
|
36557
|
+
const flushText = (force = false) => {
|
|
36558
|
+
const now = Date.now();
|
|
36559
|
+
if (!buffered || textContainerId == null)
|
|
36560
|
+
return;
|
|
36561
|
+
if (force || now - lastFlush > 200) {
|
|
36562
|
+
peer.appendPartialText(textContainerId, buffered);
|
|
36563
|
+
buffered = "";
|
|
36564
|
+
lastFlush = now;
|
|
36456
36565
|
}
|
|
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(`
|
|
36566
|
+
};
|
|
36567
|
+
const closeText = () => {
|
|
36568
|
+
if (textContainerId == null)
|
|
36569
|
+
return;
|
|
36570
|
+
flushText(true);
|
|
36571
|
+
peer.finalizePartialMessage(textContainerId);
|
|
36572
|
+
textContainerId = null;
|
|
36573
|
+
};
|
|
36574
|
+
const agentDisplayName = mentionAgent?.name ?? allAgents.find((a) => a.id === resolvedAgentId)?.name ?? runtime4 ?? undefined;
|
|
36575
|
+
const ensureTextOpen = () => {
|
|
36576
|
+
if (textContainerId == null) {
|
|
36577
|
+
textContainerId = peer.beginPartialAgentMessage(agentAuthorId, agentDisplayName).containerId;
|
|
36578
|
+
}
|
|
36579
|
+
};
|
|
36580
|
+
const summarizeInput = (raw) => {
|
|
36581
|
+
if (!raw || typeof raw !== "object")
|
|
36582
|
+
return;
|
|
36583
|
+
const r = raw;
|
|
36584
|
+
const out = {};
|
|
36585
|
+
if (typeof r.file_path === "string")
|
|
36586
|
+
out.file_path = r.file_path;
|
|
36587
|
+
if (typeof r.path === "string")
|
|
36588
|
+
out.path = r.path;
|
|
36589
|
+
if (typeof r.filename === "string")
|
|
36590
|
+
out.filename = r.filename;
|
|
36591
|
+
if (typeof r.command === "string")
|
|
36592
|
+
out.command = String(r.command).slice(0, 400);
|
|
36593
|
+
if (typeof r.pattern === "string")
|
|
36594
|
+
out.pattern = String(r.pattern).slice(0, 200);
|
|
36595
|
+
if (typeof r.query === "string")
|
|
36596
|
+
out.query = String(r.query).slice(0, 200);
|
|
36597
|
+
if (typeof r.url === "string")
|
|
36598
|
+
out.url = r.url;
|
|
36599
|
+
return Object.keys(out).length ? out : undefined;
|
|
36600
|
+
};
|
|
36601
|
+
const summarizeContent = (raw) => {
|
|
36602
|
+
const bytes = raw?.length ?? 0;
|
|
36603
|
+
const lines = raw ? raw.split(`
|
|
36529
36604
|
`).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" });
|
|
36605
|
+
const trimmed = raw && raw.length > 240 ? raw.slice(0, 240) + "…" : raw || "";
|
|
36606
|
+
return { content: trimmed, bytes, lines };
|
|
36607
|
+
};
|
|
36608
|
+
const mapToolKind = (raw) => {
|
|
36609
|
+
const s = (raw || "").toLowerCase();
|
|
36610
|
+
if (s.includes("edit") || s.includes("modify"))
|
|
36611
|
+
return "edit";
|
|
36612
|
+
if (s.includes("read") || s.includes("view") || s.includes("fetch"))
|
|
36613
|
+
return "read";
|
|
36614
|
+
if (s.includes("write") || s.includes("create"))
|
|
36615
|
+
return "write";
|
|
36616
|
+
if (s.includes("execute") || s.includes("bash") || s.includes("shell") || s.includes("run"))
|
|
36617
|
+
return "bash";
|
|
36618
|
+
if (s.includes("search") || s.includes("grep") || s.includes("find"))
|
|
36619
|
+
return "search";
|
|
36620
|
+
return "other";
|
|
36621
|
+
};
|
|
36622
|
+
const preamble = buildChatPreamble({ projectId: chat2.project_id, agents: allAgents });
|
|
36623
|
+
await new Promise((resolve2) => {
|
|
36624
|
+
handleChatTurn({
|
|
36625
|
+
chatId: chat2.id,
|
|
36626
|
+
prompt: userMsg.text,
|
|
36627
|
+
preferredRuntime: runtime4,
|
|
36628
|
+
cwd,
|
|
36629
|
+
systemPreamble: preamble,
|
|
36630
|
+
log: log4,
|
|
36631
|
+
onChunk: (text) => {
|
|
36632
|
+
ensureTextOpen();
|
|
36633
|
+
buffered += text;
|
|
36634
|
+
agentReplyText += text;
|
|
36635
|
+
flushText();
|
|
36636
|
+
},
|
|
36637
|
+
onToolCall: (ev) => {
|
|
36638
|
+
closeText();
|
|
36639
|
+
const partial2 = ev.status !== "completed" && ev.status !== "failed";
|
|
36640
|
+
const status3 = ev.status || "in_progress";
|
|
36641
|
+
if (ev.id) {
|
|
36642
|
+
const existing = toolMsgByCallId.get(ev.id);
|
|
36643
|
+
if (existing) {
|
|
36644
|
+
peer.patchMessage(existing, {
|
|
36645
|
+
partial: partial2,
|
|
36646
|
+
status: status3,
|
|
36647
|
+
tool: ev.tool,
|
|
36648
|
+
tool_kind: mapToolKind(ev.kind),
|
|
36649
|
+
input: summarizeInput(ev.input)
|
|
36650
|
+
});
|
|
36651
|
+
return;
|
|
36624
36652
|
}
|
|
36625
|
-
this.opts.log(`[chat ${chat2.id}] done: ${stopReason}`);
|
|
36626
|
-
resolve2();
|
|
36627
36653
|
}
|
|
36628
|
-
|
|
36629
|
-
|
|
36630
|
-
|
|
36631
|
-
|
|
36632
|
-
|
|
36633
|
-
|
|
36634
|
-
|
|
36635
|
-
|
|
36636
|
-
|
|
36637
|
-
|
|
36638
|
-
|
|
36639
|
-
|
|
36654
|
+
const id3 = `tc_${ev.id || Math.random().toString(36).slice(2)}`;
|
|
36655
|
+
const containerId = peer.appendStructured({
|
|
36656
|
+
id: id3,
|
|
36657
|
+
author: { kind: "agent", id: agentAuthorId, name: agentDisplayName },
|
|
36658
|
+
kind: "tool_call",
|
|
36659
|
+
text: "",
|
|
36660
|
+
ts: Math.floor(Date.now() / 1000),
|
|
36661
|
+
mentions: [],
|
|
36662
|
+
attachments: [],
|
|
36663
|
+
partial: partial2,
|
|
36664
|
+
tool: ev.tool,
|
|
36665
|
+
tool_kind: mapToolKind(ev.kind),
|
|
36666
|
+
status: status3,
|
|
36667
|
+
input: summarizeInput(ev.input),
|
|
36668
|
+
tool_call_id: ev.id
|
|
36640
36669
|
});
|
|
36641
|
-
|
|
36642
|
-
|
|
36643
|
-
|
|
36644
|
-
|
|
36645
|
-
|
|
36646
|
-
|
|
36647
|
-
|
|
36648
|
-
|
|
36649
|
-
|
|
36650
|
-
|
|
36651
|
-
|
|
36652
|
-
|
|
36670
|
+
if (ev.id)
|
|
36671
|
+
toolMsgByCallId.set(ev.id, containerId);
|
|
36672
|
+
},
|
|
36673
|
+
onToolResult: (ev) => {
|
|
36674
|
+
closeText();
|
|
36675
|
+
const summary5 = summarizeContent(ev.content);
|
|
36676
|
+
peer.appendStructured({
|
|
36677
|
+
id: `tr_${ev.tool_call_id || Math.random().toString(36).slice(2)}_${Date.now()}`,
|
|
36678
|
+
author: { kind: "agent", id: agentAuthorId, name: agentDisplayName },
|
|
36679
|
+
kind: "tool_result",
|
|
36680
|
+
text: `${summary5.lines} lines · ${summary5.bytes} bytes`,
|
|
36681
|
+
ts: Math.floor(Date.now() / 1000),
|
|
36682
|
+
mentions: [],
|
|
36683
|
+
attachments: [],
|
|
36684
|
+
partial: false,
|
|
36685
|
+
tool_call_id: ev.tool_call_id,
|
|
36686
|
+
content: summary5.content
|
|
36687
|
+
});
|
|
36688
|
+
const cid = ev.tool_call_id ? toolMsgByCallId.get(ev.tool_call_id) : undefined;
|
|
36689
|
+
if (cid)
|
|
36690
|
+
peer.patchMessage(cid, { partial: false, status: "completed" });
|
|
36691
|
+
},
|
|
36692
|
+
onDone: (stopReason) => {
|
|
36693
|
+
closeText();
|
|
36694
|
+
for (const cid of toolMsgByCallId.values()) {
|
|
36695
|
+
peer.patchMessage(cid, { partial: false, status: "completed" });
|
|
36653
36696
|
}
|
|
36654
|
-
|
|
36697
|
+
log4(`[chat ${chat2.id}] done: ${stopReason}`);
|
|
36698
|
+
resolve2();
|
|
36655
36699
|
}
|
|
36656
|
-
|
|
36657
|
-
|
|
36658
|
-
|
|
36659
|
-
|
|
36660
|
-
|
|
36661
|
-
|
|
36662
|
-
|
|
36663
|
-
|
|
36664
|
-
|
|
36665
|
-
|
|
36700
|
+
});
|
|
36701
|
+
});
|
|
36702
|
+
try {
|
|
36703
|
+
const { actions, errors: errors3 } = parsePlanBlocks(agentReplyText);
|
|
36704
|
+
if (actions.length || errors3.length) {
|
|
36705
|
+
const res = await executeChatPlanActions(actions, errors3, {
|
|
36706
|
+
apiUrl,
|
|
36707
|
+
wsId: workspaceId,
|
|
36708
|
+
chatId: chat2.id,
|
|
36709
|
+
projectId: chat2.project_id,
|
|
36710
|
+
agentId: resolvedAgentId,
|
|
36711
|
+
log: log4
|
|
36712
|
+
});
|
|
36713
|
+
const summary5 = renderChatPlanSummary(res);
|
|
36714
|
+
if (summary5) {
|
|
36715
|
+
peer.appendStructured({
|
|
36716
|
+
id: `sys_plan_${Date.now()}`,
|
|
36717
|
+
author: { kind: "system", id: "multi-plan", name: "multi" },
|
|
36718
|
+
kind: "text",
|
|
36719
|
+
text: summary5,
|
|
36720
|
+
ts: Math.floor(Date.now() / 1000),
|
|
36721
|
+
mentions: [],
|
|
36722
|
+
attachments: [],
|
|
36723
|
+
partial: false
|
|
36724
|
+
});
|
|
36725
|
+
}
|
|
36726
|
+
log4(`[chat ${chat2.id}] plan exec: ${res.ok} ok, ${res.fail} fail, ${errors3.length} parse-err`);
|
|
36666
36727
|
}
|
|
36728
|
+
const ui = parseUiBlocks(agentReplyText);
|
|
36729
|
+
if (ui.blocks.length)
|
|
36730
|
+
log4(`[chat ${chat2.id}] ui blocks: ${ui.blocks.length}`);
|
|
36731
|
+
if (ui.errors.length)
|
|
36732
|
+
log4(`[chat ${chat2.id}] ui parse err: ${ui.errors.length}`);
|
|
36733
|
+
} catch (e) {
|
|
36734
|
+
log4(`[chat ${chat2.id}] post-turn err: ${e.message}`);
|
|
36667
36735
|
}
|
|
36668
|
-
|
|
36669
|
-
|
|
36670
|
-
|
|
36671
|
-
|
|
36672
|
-
|
|
36736
|
+
if (/^new chat$/i.test(chat2.title) && agentReplyText.trim()) {
|
|
36737
|
+
autoTitle(chat2, userMsg.text, agentReplyText, ctx).catch((e) => log4(`[chat ${chat2.id}] auto-title failed: ${e.message}`));
|
|
36738
|
+
}
|
|
36739
|
+
}
|
|
36740
|
+
async function autoTitle(chat2, userMsg, agentReply, ctx) {
|
|
36741
|
+
const { apiUrl, authToken: authToken2, workspaceId, log: log4 } = ctx;
|
|
36742
|
+
const runtime4 = await resolveAgentRuntime(apiUrl, workspaceId, authToken2, chat2, chat2.primary_agent_id);
|
|
36743
|
+
const trimUser = userMsg.slice(0, 800);
|
|
36744
|
+
const trimAgent = agentReply.slice(0, 1200);
|
|
36745
|
+
const prompt = `Reply with ONLY a 3-6 word title for this conversation. No quotes, no punctuation, no explanation. Capitalize each word.
|
|
36673
36746
|
|
|
36674
36747
|
` + `User: ${trimUser}
|
|
36675
36748
|
|
|
36676
36749
|
Assistant: ${trimAgent}`;
|
|
36677
|
-
|
|
36678
|
-
|
|
36679
|
-
|
|
36680
|
-
|
|
36681
|
-
|
|
36682
|
-
|
|
36683
|
-
|
|
36684
|
-
|
|
36685
|
-
|
|
36686
|
-
|
|
36687
|
-
|
|
36688
|
-
});
|
|
36750
|
+
let collected = "";
|
|
36751
|
+
await new Promise((resolve2) => {
|
|
36752
|
+
handleChatTurn({
|
|
36753
|
+
chatId: `${chat2.id}__title`,
|
|
36754
|
+
prompt,
|
|
36755
|
+
preferredRuntime: runtime4,
|
|
36756
|
+
log: log4,
|
|
36757
|
+
onChunk: (t) => {
|
|
36758
|
+
collected += t;
|
|
36759
|
+
},
|
|
36760
|
+
onDone: () => resolve2()
|
|
36689
36761
|
});
|
|
36690
|
-
|
|
36762
|
+
});
|
|
36763
|
+
const cleaned = collected.split(`
|
|
36691
36764
|
`).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
|
-
}
|
|
36765
|
+
const stripped = cleaned.replace(/^["'`*_#-]+|["'`*_#-]+$/g, "").trim();
|
|
36766
|
+
const final = stripped.split(/\s+/).slice(0, 8).join(" ").slice(0, 60);
|
|
36767
|
+
if (!final || /^new chat$/i.test(final))
|
|
36768
|
+
return;
|
|
36769
|
+
try {
|
|
36770
|
+
const r = await fetch(`${apiUrl}/api/workspaces/${workspaceId}/chats/${chat2.id}`, {
|
|
36771
|
+
method: "PATCH",
|
|
36772
|
+
headers: { authorization: `Bearer ${authToken2}`, "content-type": "application/json" },
|
|
36773
|
+
body: JSON.stringify({ title: final })
|
|
36774
|
+
});
|
|
36775
|
+
if (r.ok)
|
|
36776
|
+
log4(`[chat ${chat2.id}] auto-titled: ${final}`);
|
|
36777
|
+
} catch {}
|
|
36709
36778
|
}
|
|
36710
36779
|
function buildChatPreamble(args2) {
|
|
36711
36780
|
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 +36802,7 @@ Action vocabulary:
|
|
|
36733
36802
|
{"type":"issue.delete_where","status":"todo","limit":50},
|
|
36734
36803
|
{"type":"issue.list","status":"todo","limit":20},
|
|
36735
36804
|
{"type":"issue.search","query":"flaky tests","limit":10},
|
|
36736
|
-
{"type":"agent.create","name":"refactor-bot","
|
|
36805
|
+
{"type":"agent.create","name":"refactor-bot","prompt":"...","allowed_tools":["Read","Edit","Bash"]},
|
|
36737
36806
|
{"type":"agent.update","id":"ag_xxx","prompt":"..."},
|
|
36738
36807
|
{"type":"skill.create","name":"run-tests","description":"...","body":"---\\nname: run-tests\\n---\\n..."},
|
|
36739
36808
|
{"type":"skill.attach","agent_id":"ag_xxx","skill_id":"sk_yyy"},
|
|
@@ -37334,7 +37403,7 @@ import { parseArgs } from "util";
|
|
|
37334
37403
|
// package.json
|
|
37335
37404
|
var package_default = {
|
|
37336
37405
|
name: "@shipers-dev/multi",
|
|
37337
|
-
version: "0.
|
|
37406
|
+
version: "0.41.0",
|
|
37338
37407
|
type: "module",
|
|
37339
37408
|
bin: {
|
|
37340
37409
|
"multi-agent": "./dist/index.js"
|
|
@@ -38765,6 +38834,34 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
|
|
|
38765
38834
|
}
|
|
38766
38835
|
})();
|
|
38767
38836
|
}
|
|
38837
|
+
if (url2.pathname === "/run-chat-turn" && req.method === "POST") {
|
|
38838
|
+
if (req.headers.get("authorization") !== expectedAuth)
|
|
38839
|
+
return new Response("unauthorized", { status: 401 });
|
|
38840
|
+
return (async () => {
|
|
38841
|
+
try {
|
|
38842
|
+
const body = await req.json();
|
|
38843
|
+
if (!body?.chat_id || !body?.message_id) {
|
|
38844
|
+
return Response.json({ error: "chat_id and message_id required" }, { status: 400 });
|
|
38845
|
+
}
|
|
38846
|
+
if (!cfg.workspaceId || !cfg.authToken || !cfg.deviceId) {
|
|
38847
|
+
return Response.json({ error: "daemon not configured" }, { status: 503 });
|
|
38848
|
+
}
|
|
38849
|
+
const { runChatTurn: runChatTurn2 } = await Promise.resolve().then(() => (init_chat_supervisor(), exports_chat_supervisor));
|
|
38850
|
+
runChatTurn2({
|
|
38851
|
+
apiUrl,
|
|
38852
|
+
authToken: cfg.authToken,
|
|
38853
|
+
workspaceId: cfg.workspaceId,
|
|
38854
|
+
deviceId: cfg.deviceId,
|
|
38855
|
+
chatId: body.chat_id,
|
|
38856
|
+
messageId: body.message_id,
|
|
38857
|
+
log: log3
|
|
38858
|
+
}).catch((e) => log3(`[chat ${body.chat_id}] runChatTurn error: ${e.message}`));
|
|
38859
|
+
return Response.json({ accepted: true }, { status: 202 });
|
|
38860
|
+
} catch (e) {
|
|
38861
|
+
return Response.json({ error: String(e) }, { status: 400 });
|
|
38862
|
+
}
|
|
38863
|
+
})();
|
|
38864
|
+
}
|
|
38768
38865
|
if (url2.pathname === "/stop" && req.method === "POST") {
|
|
38769
38866
|
if (req.headers.get("authorization") !== expectedAuth)
|
|
38770
38867
|
return new Response("unauthorized", { status: 401 });
|
|
@@ -38826,19 +38923,6 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
|
|
|
38826
38923
|
catch: () => new DaemonError({ message: "materializeBundle skipped" })
|
|
38827
38924
|
}).pipe(exports_Effect.catchAll(() => exports_Effect.void));
|
|
38828
38925
|
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
38926
|
if (cfg.workspaceId) {
|
|
38843
38927
|
yield* exports_Effect.forkIn(daemonScope)(exports_Effect.tryPromise({
|
|
38844
38928
|
try: () => drainOfflineDispatches(apiUrl, cfg.deviceId, cfg.workspaceId, cfg.dispatchSecret, db2, () => {
|
|
@@ -38928,9 +39012,6 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
|
|
|
38928
39012
|
try {
|
|
38929
39013
|
server.stop();
|
|
38930
39014
|
} catch {}
|
|
38931
|
-
try {
|
|
38932
|
-
chatSup?.close();
|
|
38933
|
-
} catch {}
|
|
38934
39015
|
try {
|
|
38935
39016
|
tunnel?.child?.kill();
|
|
38936
39017
|
} catch {}
|