@shipers-dev/multi 0.64.0 → 0.65.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 +196 -10
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -35192,6 +35192,10 @@ _${bits.join(" · ")}_`);
|
|
|
35192
35192
|
const acpCapable = detected.filter((d) => d.type === "claude-code");
|
|
35193
35193
|
const useAcp = preferType !== "pi" && acpCapable.length > 0 && process.env.MULTI_LEGACY !== "1";
|
|
35194
35194
|
const useAcpx = !useAcp && preferType && ["pi", "codex", "openclaw"].includes(preferType) && process.env.MULTI_LEGACY !== "1";
|
|
35195
|
+
let issueHistoryBlock = "";
|
|
35196
|
+
if (tenantWsId && ISSUE_BASE) {
|
|
35197
|
+
issueHistoryBlock = await fetchIssueHistory(apiUrl, tenantWsId, projectId, issueId, log3);
|
|
35198
|
+
}
|
|
35195
35199
|
try {
|
|
35196
35200
|
if (useAcp) {
|
|
35197
35201
|
const issueContext = `## Issue ${task.key}: ${task.title}${task.description ? `
|
|
@@ -35209,6 +35213,20 @@ ${task.description}` : ""}`;
|
|
|
35209
35213
|
${cleanFollowup}`;
|
|
35210
35214
|
} else {
|
|
35211
35215
|
userPart = stripSelfMention(issueContext, preferType);
|
|
35216
|
+
userPart += `
|
|
35217
|
+
|
|
35218
|
+
---
|
|
35219
|
+
|
|
35220
|
+
You have been assigned this issue. Investigate and resolve it. Read the codebase, understand the problem, implement a fix or complete the described work, and use your tools to make progress. When finished, emit a multi-plan action to mark the issue done (or blocked if you need human input).`;
|
|
35221
|
+
}
|
|
35222
|
+
if (issueHistoryBlock) {
|
|
35223
|
+
userPart += `
|
|
35224
|
+
|
|
35225
|
+
---
|
|
35226
|
+
|
|
35227
|
+
## Issue history (prior activity)
|
|
35228
|
+
|
|
35229
|
+
${issueHistoryBlock}`;
|
|
35212
35230
|
}
|
|
35213
35231
|
if (attachmentRefs.length) {
|
|
35214
35232
|
const lines = attachmentRefs.map((a) => `- ${a.filename}: ${a.path}`).join(`
|
|
@@ -35227,6 +35245,7 @@ Note: if (and only if) you produce binary or large artifact outputs (screenshots
|
|
|
35227
35245
|
Respond in the chat. Only if you produce large artifact files (screenshots, data exports, generated source code), write them under ${outDir}. Do not put your answer in a file.`;
|
|
35228
35246
|
}
|
|
35229
35247
|
let preamble = "";
|
|
35248
|
+
let preambleFailed = false;
|
|
35230
35249
|
try {
|
|
35231
35250
|
if (tenantWsId) {
|
|
35232
35251
|
const agentRes = await apiClient.get(`${apiUrl}/api/workspaces/${tenantWsId}/agents/${task.agent_id}`);
|
|
@@ -35256,7 +35275,9 @@ ${body}
|
|
|
35256
35275
|
}
|
|
35257
35276
|
}
|
|
35258
35277
|
} catch (e) {
|
|
35278
|
+
preambleFailed = true;
|
|
35259
35279
|
log3(`preamble fetch failed: ${String(e)}`);
|
|
35280
|
+
await postBoundChatMessage(apiUrl, task, `⚠️ System: agent preamble (prompt + skills) fetch failed — the agent is running without its role definition. Error: ${String(e).slice(0, 200)}`);
|
|
35260
35281
|
}
|
|
35261
35282
|
preamble += await buildPlanningPreamble(apiUrl, task);
|
|
35262
35283
|
const prompt = preamble ? `${preamble}
|
|
@@ -35337,7 +35358,10 @@ ${body}
|
|
|
35337
35358
|
}
|
|
35338
35359
|
}
|
|
35339
35360
|
}
|
|
35340
|
-
} catch {
|
|
35361
|
+
} catch (e) {
|
|
35362
|
+
log3(`preamble fetch failed (acpx): ${String(e)}`);
|
|
35363
|
+
await postBoundChatMessage(apiUrl, task, `⚠️ System: agent preamble fetch failed — running without role definition. Error: ${String(e).slice(0, 200)}`);
|
|
35364
|
+
}
|
|
35341
35365
|
preamble += await buildPlanningPreamble(apiUrl, task);
|
|
35342
35366
|
const issueContext = `## Issue ${task.key}: ${task.title}${task.description ? `
|
|
35343
35367
|
|
|
@@ -35354,6 +35378,20 @@ ${task.description}` : ""}`;
|
|
|
35354
35378
|
${cleanFollowup}`;
|
|
35355
35379
|
} else {
|
|
35356
35380
|
userPart = stripSelfMention(issueContext, preferType);
|
|
35381
|
+
userPart += `
|
|
35382
|
+
|
|
35383
|
+
---
|
|
35384
|
+
|
|
35385
|
+
You have been assigned this issue. Investigate and resolve it. Read the codebase, understand the problem, implement a fix or complete the described work, and use your tools to make progress. When finished, emit a multi-plan action to mark the issue done (or blocked if you need human input).`;
|
|
35386
|
+
}
|
|
35387
|
+
if (issueHistoryBlock) {
|
|
35388
|
+
userPart += `
|
|
35389
|
+
|
|
35390
|
+
---
|
|
35391
|
+
|
|
35392
|
+
## Issue history (prior activity)
|
|
35393
|
+
|
|
35394
|
+
${issueHistoryBlock}`;
|
|
35357
35395
|
}
|
|
35358
35396
|
if (attachmentRefs.length) {
|
|
35359
35397
|
const lines = attachmentRefs.map((a) => `- ${a.filename}: ${a.path}`).join(`
|
|
@@ -35488,6 +35526,52 @@ ${userPart}` : userPart;
|
|
|
35488
35526
|
}
|
|
35489
35527
|
}
|
|
35490
35528
|
}
|
|
35529
|
+
async function fetchIssueHistory(apiUrl, tenantWsId, projectId, issueId, log4) {
|
|
35530
|
+
const MAX_HISTORY_CHARS = 6000;
|
|
35531
|
+
try {
|
|
35532
|
+
const issueBase = `${apiUrl}/api/workspaces/${tenantWsId}/projects/${projectId}/issues/${issueId}`;
|
|
35533
|
+
const res = await apiClient.get(`${issueBase}/activity`);
|
|
35534
|
+
const activities = Array.isArray(res.data?.results) ? res.data.results : Array.isArray(res.data) ? res.data : [];
|
|
35535
|
+
if (!activities.length)
|
|
35536
|
+
return "";
|
|
35537
|
+
const lines = [];
|
|
35538
|
+
const recent = activities.slice(-20).reverse();
|
|
35539
|
+
for (const act of recent) {
|
|
35540
|
+
const action = act.action || "activity";
|
|
35541
|
+
const actor = act.actor_name || act.actor_id || "system";
|
|
35542
|
+
const ts = act.created_at ? new Date(act.created_at * 1000).toISOString().slice(0, 16) : "";
|
|
35543
|
+
let line = `- **${actor}** ${action}`;
|
|
35544
|
+
if (ts)
|
|
35545
|
+
line += ` _${ts}_`;
|
|
35546
|
+
if (act.details) {
|
|
35547
|
+
try {
|
|
35548
|
+
const d = typeof act.details === "string" ? JSON.parse(act.details) : act.details;
|
|
35549
|
+
if (d.message)
|
|
35550
|
+
line += `: ${String(d.message).slice(0, 200)}`;
|
|
35551
|
+
else if (d.title)
|
|
35552
|
+
line += `: ${String(d.title).slice(0, 200)}`;
|
|
35553
|
+
else if (d.from && d.to)
|
|
35554
|
+
line += `: ${d.from} → ${d.to}`;
|
|
35555
|
+
else if (d.text)
|
|
35556
|
+
line += `: ${String(d.text).slice(0, 200)}`;
|
|
35557
|
+
} catch {}
|
|
35558
|
+
}
|
|
35559
|
+
lines.push(line);
|
|
35560
|
+
}
|
|
35561
|
+
const block = lines.join(`
|
|
35562
|
+
`);
|
|
35563
|
+
if (block.length > MAX_HISTORY_CHARS) {
|
|
35564
|
+
log4(` issue history truncated: ${block.length} → ${MAX_HISTORY_CHARS} chars`);
|
|
35565
|
+
return block.slice(0, MAX_HISTORY_CHARS) + `
|
|
35566
|
+
|
|
35567
|
+
_… truncated_`;
|
|
35568
|
+
}
|
|
35569
|
+
return block;
|
|
35570
|
+
} catch (e) {
|
|
35571
|
+
log4(` issue history fetch failed: ${String(e).slice(0, 200)}`);
|
|
35572
|
+
return "";
|
|
35573
|
+
}
|
|
35574
|
+
}
|
|
35491
35575
|
async function buildPlanningPreamble(apiUrl, task, _wsId) {
|
|
35492
35576
|
const depth = typeof task.planning_depth === "number" ? task.planning_depth : 0;
|
|
35493
35577
|
if (depth >= PLANNING_DEPTH_LIMIT) {
|
|
@@ -35686,7 +35770,7 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
|
|
|
35686
35770
|
}
|
|
35687
35771
|
}
|
|
35688
35772
|
} else if (a.type === "delegate") {
|
|
35689
|
-
const res = await apiClient.post(mutateUrl, { action: "update", id: a.id, assignee_type: "agent", assignee_id: a.assignee_id, status: "
|
|
35773
|
+
const res = await apiClient.post(mutateUrl, { action: "update", id: a.id, assignee_type: "agent", assignee_id: a.assignee_id, status: "in_progress" }, { headers });
|
|
35690
35774
|
if (!res.success) {
|
|
35691
35775
|
lines.push(`- [err] delegate ${a.id}: ${res.error || res.status}`);
|
|
35692
35776
|
results.push({ type: "delegate", status: "error", error: String(res.error || res.status), label: a.id });
|
|
@@ -37123,7 +37207,7 @@ async function executeChatPlanActions(actionsIn, parseErrors, ctx) {
|
|
|
37123
37207
|
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 });
|
|
37124
37208
|
tally(true);
|
|
37125
37209
|
} else if (a.type === "delegate") {
|
|
37126
|
-
const res = await apiClient.post(mutateUrl, { action: "update", id: a.id, assignee_type: "agent", assignee_id: a.assignee_id, status: "
|
|
37210
|
+
const res = await apiClient.post(mutateUrl, { action: "update", id: a.id, assignee_type: "agent", assignee_id: a.assignee_id, status: "in_progress" }, { headers });
|
|
37127
37211
|
if (!res.success) {
|
|
37128
37212
|
lines.push(`- [err] delegate ${a.id}: ${res.error || res.status}`);
|
|
37129
37213
|
results.push({ type: "delegate", status: "error", error: String(res.error || res.status), label: a.id });
|
|
@@ -38769,7 +38853,7 @@ import { parseArgs } from "util";
|
|
|
38769
38853
|
// package.json
|
|
38770
38854
|
var package_default = {
|
|
38771
38855
|
name: "@shipers-dev/multi",
|
|
38772
|
-
version: "0.
|
|
38856
|
+
version: "0.65.0",
|
|
38773
38857
|
type: "module",
|
|
38774
38858
|
bin: {
|
|
38775
38859
|
"multi-agent": "./dist/index.js"
|
|
@@ -39850,6 +39934,66 @@ import { homedir as homedir4 } from "os";
|
|
|
39850
39934
|
import { join as join16 } from "path";
|
|
39851
39935
|
init_adapter_pidfile();
|
|
39852
39936
|
init_errors();
|
|
39937
|
+
// package.json
|
|
39938
|
+
var package_default2 = {
|
|
39939
|
+
name: "@shipers-dev/multi",
|
|
39940
|
+
version: "0.65.0",
|
|
39941
|
+
type: "module",
|
|
39942
|
+
bin: {
|
|
39943
|
+
"multi-agent": "./dist/index.js"
|
|
39944
|
+
},
|
|
39945
|
+
files: [
|
|
39946
|
+
"dist"
|
|
39947
|
+
],
|
|
39948
|
+
scripts: {
|
|
39949
|
+
dev: "MULTI_HOME=${MULTI_HOME:-$HOME/.multi-dev} MULTI_API=${MULTI_API:-http://127.0.0.1:8787} bun run src/index.ts connect",
|
|
39950
|
+
build: "bun build src/index.ts --outdir=dist --target=node --sourcemap=none --external undici --external loro-crdt && node scripts/post-build.cjs",
|
|
39951
|
+
prepublishOnly: "bun run build"
|
|
39952
|
+
},
|
|
39953
|
+
dependencies: {
|
|
39954
|
+
"@agentclientprotocol/claude-agent-acp": "^0.31.0",
|
|
39955
|
+
"@agentclientprotocol/sdk": "^0.20.0",
|
|
39956
|
+
"@effect/platform-node": "^0.103.0",
|
|
39957
|
+
effect: "^3.21.2",
|
|
39958
|
+
"loro-crdt": "^1.12.1",
|
|
39959
|
+
undici: "^7.0.0"
|
|
39960
|
+
},
|
|
39961
|
+
devDependencies: {
|
|
39962
|
+
"@multi/lib": "workspace:*"
|
|
39963
|
+
}
|
|
39964
|
+
};
|
|
39965
|
+
|
|
39966
|
+
// src/_impl/daemon-main.ts
|
|
39967
|
+
var CLI_VERSION = package_default2.version;
|
|
39968
|
+
function findBunBinary() {
|
|
39969
|
+
const tryPath = (p) => {
|
|
39970
|
+
try {
|
|
39971
|
+
return existsSync16(p) ? p : null;
|
|
39972
|
+
} catch {
|
|
39973
|
+
return null;
|
|
39974
|
+
}
|
|
39975
|
+
};
|
|
39976
|
+
if (process.execPath && process.execPath.endsWith("/bun")) {
|
|
39977
|
+
const hit = tryPath(process.execPath);
|
|
39978
|
+
if (hit)
|
|
39979
|
+
return hit;
|
|
39980
|
+
}
|
|
39981
|
+
const fromWhich = Bun.which?.("bun");
|
|
39982
|
+
if (fromWhich)
|
|
39983
|
+
return fromWhich;
|
|
39984
|
+
const candidates = [
|
|
39985
|
+
join16(homedir4(), ".bun", "bin", "bun"),
|
|
39986
|
+
"/opt/homebrew/bin/bun",
|
|
39987
|
+
"/usr/local/bin/bun",
|
|
39988
|
+
"/home/linuxbrew/.linuxbrew/bin/bun"
|
|
39989
|
+
];
|
|
39990
|
+
for (const c of candidates) {
|
|
39991
|
+
const hit = tryPath(c);
|
|
39992
|
+
if (hit)
|
|
39993
|
+
return hit;
|
|
39994
|
+
}
|
|
39995
|
+
return null;
|
|
39996
|
+
}
|
|
39853
39997
|
var MULTI_DIR5 = join16(homedir4(), ".multi");
|
|
39854
39998
|
var PID_PATH2 = join16(MULTI_DIR5, "agent.pid");
|
|
39855
39999
|
var PORT_PATH2 = join16(MULTI_DIR5, "agent.port");
|
|
@@ -40220,7 +40364,7 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
|
|
|
40220
40364
|
}
|
|
40221
40365
|
const route = () => {
|
|
40222
40366
|
if (url2.pathname === "/health")
|
|
40223
|
-
return Response.json({ ok: true, device_id: cfg.deviceId });
|
|
40367
|
+
return Response.json({ ok: true, device_id: cfg.deviceId, cli_version: CLI_VERSION });
|
|
40224
40368
|
if (url2.pathname === "/files" && req.method === "GET") {
|
|
40225
40369
|
if (req.headers.get("authorization") !== expectedAuth)
|
|
40226
40370
|
return new Response("unauthorized", { status: 401 });
|
|
@@ -40627,6 +40771,47 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
|
|
|
40627
40771
|
}
|
|
40628
40772
|
})();
|
|
40629
40773
|
}
|
|
40774
|
+
if (url2.pathname === "/upgrade" && req.method === "POST") {
|
|
40775
|
+
if (req.headers.get("authorization") !== expectedAuth)
|
|
40776
|
+
return new Response("unauthorized", { status: 401 });
|
|
40777
|
+
return (async () => {
|
|
40778
|
+
const bunBin = findBunBinary();
|
|
40779
|
+
if (!bunBin) {
|
|
40780
|
+
return Response.json({ error: "bun binary not found; run `bun add -g @shipers-dev/multi` manually" }, { status: 503 });
|
|
40781
|
+
}
|
|
40782
|
+
let body = {};
|
|
40783
|
+
try {
|
|
40784
|
+
body = await req.json();
|
|
40785
|
+
} catch {}
|
|
40786
|
+
const spec = body.target ? `@shipers-dev/multi@${body.target}` : "@shipers-dev/multi";
|
|
40787
|
+
log3(`[upgrade] spawning ${bunBin} add -g ${spec}`);
|
|
40788
|
+
const child = Bun.spawn([bunBin, "add", "-g", spec], {
|
|
40789
|
+
stdout: "pipe",
|
|
40790
|
+
stderr: "pipe",
|
|
40791
|
+
stdin: "ignore"
|
|
40792
|
+
});
|
|
40793
|
+
(async () => {
|
|
40794
|
+
try {
|
|
40795
|
+
const stdoutTxt = await new Response(child.stdout).text();
|
|
40796
|
+
const stderrTxt = await new Response(child.stderr).text();
|
|
40797
|
+
const code = await child.exited;
|
|
40798
|
+
if (stdoutTxt.trim())
|
|
40799
|
+
log3(`[upgrade] stdout: ${stdoutTxt.trim()}`);
|
|
40800
|
+
if (stderrTxt.trim())
|
|
40801
|
+
log3(`[upgrade] stderr: ${stderrTxt.trim()}`);
|
|
40802
|
+
if (code === 0) {
|
|
40803
|
+
log3("[upgrade] success; exiting so service manager respawns with new binary");
|
|
40804
|
+
setTimeout(() => process.exit(0), 500);
|
|
40805
|
+
} else {
|
|
40806
|
+
log3(`[upgrade] failed with exit code ${code}`);
|
|
40807
|
+
}
|
|
40808
|
+
} catch (e) {
|
|
40809
|
+
log3(`[upgrade] error: ${e.message}`);
|
|
40810
|
+
}
|
|
40811
|
+
})();
|
|
40812
|
+
return Response.json({ accepted: true, current_version: CLI_VERSION, target: spec }, { status: 202 });
|
|
40813
|
+
})();
|
|
40814
|
+
}
|
|
40630
40815
|
if (url2.pathname === "/stop" && req.method === "POST") {
|
|
40631
40816
|
if (req.headers.get("authorization") !== expectedAuth)
|
|
40632
40817
|
return new Response("unauthorized", { status: 401 });
|
|
@@ -40742,7 +40927,8 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
|
|
|
40742
40927
|
device_id: cfg.deviceId,
|
|
40743
40928
|
workspace_id: cfg.workspaceId,
|
|
40744
40929
|
api_url: apiUrl,
|
|
40745
|
-
pid: process.pid
|
|
40930
|
+
pid: process.pid,
|
|
40931
|
+
cli_version: CLI_VERSION
|
|
40746
40932
|
}, null, 2));
|
|
40747
40933
|
} catch {}
|
|
40748
40934
|
let tunnel;
|
|
@@ -41157,14 +41343,14 @@ var collectServiceEnv = () => {
|
|
|
41157
41343
|
env.PATH = process.env.PATH;
|
|
41158
41344
|
if (process.env.HOME)
|
|
41159
41345
|
env.HOME = process.env.HOME;
|
|
41160
|
-
if (process.env.MULTI_HOME)
|
|
41161
|
-
env.MULTI_HOME = process.env.MULTI_HOME;
|
|
41162
|
-
if (process.env.MULTI_API)
|
|
41163
|
-
env.MULTI_API = process.env.MULTI_API;
|
|
41164
41346
|
if (process.env.SHELL)
|
|
41165
41347
|
env.SHELL = process.env.SHELL;
|
|
41166
41348
|
if (process.env.LANG)
|
|
41167
41349
|
env.LANG = process.env.LANG;
|
|
41350
|
+
for (const [k, v] of Object.entries(process.env)) {
|
|
41351
|
+
if (k.startsWith("MULTI_") && typeof v === "string" && v.length > 0)
|
|
41352
|
+
env[k] = v;
|
|
41353
|
+
}
|
|
41168
41354
|
return env;
|
|
41169
41355
|
};
|
|
41170
41356
|
var ensureSupported = exports_Effect.fn("service.ensureSupported")(function* () {
|