@shipers-dev/multi 0.15.0 → 0.16.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.
Files changed (2) hide show
  1. package/dist/index.js +59 -27
  2. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -16073,10 +16073,10 @@ var StreamEventInputSchema = exports_external.object({
16073
16073
  });
16074
16074
  // src/worktree.ts
16075
16075
  import { spawn } from "child_process";
16076
- import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2 } from "fs";
16077
- import { join as join3 } from "path";
16076
+ import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, mkdirSync as mkdirSync2, symlinkSync } from "fs";
16077
+ import { dirname as dirname2, join as join3, resolve } from "path";
16078
16078
  async function run(cwd, cmd, args) {
16079
- return await new Promise((resolve) => {
16079
+ return await new Promise((resolve2) => {
16080
16080
  const p = spawn(cmd, args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
16081
16081
  let stdout = "";
16082
16082
  let stderr = "";
@@ -16086,8 +16086,8 @@ async function run(cwd, cmd, args) {
16086
16086
  p.stderr.on("data", (d) => {
16087
16087
  stderr += d.toString();
16088
16088
  });
16089
- p.on("close", (code) => resolve({ code: code ?? 0, stdout: stdout.trim(), stderr: stderr.trim() }));
16090
- p.on("error", (e) => resolve({ code: 1, stdout: "", stderr: String(e) }));
16089
+ p.on("close", (code) => resolve2({ code: code ?? 0, stdout: stdout.trim(), stderr: stderr.trim() }));
16090
+ p.on("error", (e) => resolve2({ code: 1, stdout: "", stderr: String(e) }));
16091
16091
  });
16092
16092
  }
16093
16093
  async function isGitRepo(dir) {
@@ -16144,12 +16144,43 @@ async function ensureWorktree(workingDir, issueKey) {
16144
16144
  if (r.code !== 0) {
16145
16145
  throw new Error(`git worktree add failed: ${r.stderr || r.stdout}`);
16146
16146
  }
16147
+ await linkIgnoredFiles(workingDir, wtPath);
16147
16148
  return { path: wtPath, branch, created: true };
16148
16149
  }
16150
+ async function linkIgnoredFiles(workingDir, wtPath) {
16151
+ const r = await run(workingDir, "git", [
16152
+ "ls-files",
16153
+ "--others",
16154
+ "--ignored",
16155
+ "--exclude-standard",
16156
+ "--directory"
16157
+ ]);
16158
+ if (r.code !== 0)
16159
+ return;
16160
+ const entries = r.stdout.split(`
16161
+ `).map((l) => l.trim()).filter(Boolean);
16162
+ for (const raw of entries) {
16163
+ const rel = raw.endsWith("/") ? raw.slice(0, -1) : raw;
16164
+ if (!rel || rel === ".multi" || rel.startsWith(".multi/"))
16165
+ continue;
16166
+ if (rel === ".git" || rel.startsWith(".git/"))
16167
+ continue;
16168
+ const src = resolve(workingDir, rel);
16169
+ const dst = join3(wtPath, rel);
16170
+ if (existsSync2(dst))
16171
+ continue;
16172
+ try {
16173
+ mkdirSync2(dirname2(dst), { recursive: true });
16174
+ } catch {}
16175
+ try {
16176
+ symlinkSync(src, dst);
16177
+ } catch {}
16178
+ }
16179
+ }
16149
16180
 
16150
16181
  // src/materializer.ts
16151
- import { mkdirSync as mkdirSync3, existsSync as existsSync3, writeFileSync as writeFileSync3, readFileSync as readFileSync3, rmSync, symlinkSync, lstatSync } from "fs";
16152
- import { join as join4, dirname as dirname2 } from "path";
16182
+ import { mkdirSync as mkdirSync3, existsSync as existsSync3, writeFileSync as writeFileSync3, readFileSync as readFileSync3, rmSync, symlinkSync as symlinkSync2, lstatSync } from "fs";
16183
+ import { join as join4, dirname as dirname3 } from "path";
16153
16184
  var HOME2 = process.env.HOME || process.env.USERPROFILE || ".";
16154
16185
  var MULTI_DIR = join4(HOME2, ".multi");
16155
16186
  var MULTI_SKILLS = join4(MULTI_DIR, "skills");
@@ -16207,7 +16238,7 @@ revision=${Date.now()}
16207
16238
  if (f.path === MARKER)
16208
16239
  continue;
16209
16240
  const out = join4(dir, f.path);
16210
- mkdirSync3(dirname2(out), { recursive: true });
16241
+ mkdirSync3(dirname3(out), { recursive: true });
16211
16242
  writeFileSync3(out, f.content);
16212
16243
  }
16213
16244
  mkdirSync3(CLAUDE_SKILLS, { recursive: true });
@@ -16215,7 +16246,7 @@ revision=${Date.now()}
16215
16246
  safeRmManaged(link);
16216
16247
  if (!existsSync3(link)) {
16217
16248
  try {
16218
- symlinkSync(dir, link, "dir");
16249
+ symlinkSync2(dir, link, "dir");
16219
16250
  } catch {}
16220
16251
  }
16221
16252
  }
@@ -16289,11 +16320,11 @@ function lastMaterializedRevision() {
16289
16320
  // src/index.ts
16290
16321
  import { parseArgs } from "util";
16291
16322
  import { mkdirSync as mkdirSync4, existsSync as existsSync4, writeFileSync as writeFileSync4, readFileSync as readFileSync4, appendFileSync as appendFileSync2, unlinkSync, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
16292
- import { join as join5, dirname as dirname3 } from "path";
16323
+ import { join as join5, dirname as dirname4 } from "path";
16293
16324
  // package.json
16294
16325
  var package_default = {
16295
16326
  name: "@shipers-dev/multi",
16296
- version: "0.14.0",
16327
+ version: "0.16.0",
16297
16328
  type: "module",
16298
16329
  bin: {
16299
16330
  "multi-agent": "./dist/index.js"
@@ -16303,7 +16334,8 @@ var package_default = {
16303
16334
  ],
16304
16335
  scripts: {
16305
16336
  dev: "bun run src/index.ts",
16306
- build: "bun build src/index.ts --outdir=dist --target=bun"
16337
+ build: "bun build src/index.ts --outdir=dist --target=bun",
16338
+ prepublishOnly: "bun run build"
16307
16339
  },
16308
16340
  dependencies: {
16309
16341
  "@agentclientprotocol/sdk": "^0.20.0",
@@ -17016,9 +17048,12 @@ async function parseTunnelUrl(stream2) {
17016
17048
  }
17017
17049
  return { url: null, tail: buf };
17018
17050
  }
17051
+ async function patchIssueStatus(apiUrl, issueId, status) {
17052
+ return apiClient.post(`${apiUrl}/api/issues/agent/mutate`, { action: "update", id: issueId, status });
17053
+ }
17019
17054
  async function markStopped(apiUrl, issueId, reason) {
17020
17055
  try {
17021
- await apiClient.patch(`${apiUrl}/api/issues/${issueId}`, { status: "stopped" });
17056
+ await patchIssueStatus(apiUrl, issueId, "stopped");
17022
17057
  } catch {}
17023
17058
  try {
17024
17059
  await apiClient.post(`${apiUrl}/api/issues/${issueId}/comments`, {
@@ -17047,7 +17082,7 @@ async function handleRunTask(apiUrl, deviceId, task, detected, ctx) {
17047
17082
  }
17048
17083
  }
17049
17084
  log(`\u25B6 run_task ${task.key}: ${isFollowup ? "(follow-up) " : ""}${task.title}${workingDir ? ` [cwd: ${workingDir}${worktreeBranch ? ` @${worktreeBranch}` : ""}]` : ""}`);
17050
- await apiClient.patch(`${apiUrl}/api/issues/${issueId}`, { status: "in_progress" });
17085
+ await patchIssueStatus(apiUrl, issueId, "in_progress");
17051
17086
  await postStream(apiUrl, issueId, "progress", { message: `Device ${deviceId} picked up ${isFollowup ? "follow-up" : "task"}` });
17052
17087
  let attachmentRefs = [];
17053
17088
  if (task.from_comment_id) {
@@ -17276,12 +17311,14 @@ _${bits.join(" \xB7 ")}_`);
17276
17311
  }
17277
17312
  }
17278
17313
  };
17279
- let preferType;
17280
- try {
17281
- const a = await apiClient.get(`${apiUrl}/api/agents/${task.agent_id}`);
17282
- if (a.data?.type)
17283
- preferType = a.data.type;
17284
- } catch {}
17314
+ let preferType = task.agent_runtime || undefined;
17315
+ if (!preferType) {
17316
+ try {
17317
+ const a = await apiClient.get(`${apiUrl}/api/agents/${task.agent_id}`);
17318
+ if (a.data?.type)
17319
+ preferType = a.data.type;
17320
+ } catch {}
17321
+ }
17285
17322
  const acpCapable = detected.filter((d) => d.type === "claude-code");
17286
17323
  const useAcp = preferType !== "pi" && acpCapable.length > 0 && process.env.MULTI_LEGACY !== "1";
17287
17324
  const useAcpx = !useAcp && preferType && ["pi", "codex", "openclaw"].includes(preferType) && process.env.MULTI_LEGACY !== "1";
@@ -17354,12 +17391,7 @@ ${body}
17354
17391
  ---
17355
17392
 
17356
17393
  ${userPart}` : userPart;
17357
- let preferredType = "claude-code";
17358
- try {
17359
- const a = await apiClient.get(`${apiUrl}/api/agents/${task.agent_id}`);
17360
- if (a.data?.type)
17361
- preferredType = a.data.type;
17362
- } catch {}
17394
+ let preferredType = preferType || "claude-code";
17363
17395
  const chosen = acpCapable.find((d) => d.type === preferredType) || acpCapable[0];
17364
17396
  const adapterBin = await resolveAcpAdapter(chosen.type, chosen.path);
17365
17397
  if (!adapterBin)
@@ -17792,7 +17824,7 @@ async function resolveAcpAdapter(agentType, detectedPath) {
17792
17824
  const here = new URL(import.meta.url).pathname;
17793
17825
  let dir = here;
17794
17826
  for (let i = 0;i < 8; i++) {
17795
- dir = dirname3(dir);
17827
+ dir = dirname4(dir);
17796
17828
  const bin = join5(dir, "node_modules", ".bin", name);
17797
17829
  if (existsSync4(bin))
17798
17830
  return [bin];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipers-dev/multi",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "multi-agent": "./dist/index.js"
@@ -10,7 +10,8 @@
10
10
  ],
11
11
  "scripts": {
12
12
  "dev": "bun run src/index.ts",
13
- "build": "bun build src/index.ts --outdir=dist --target=bun"
13
+ "build": "bun build src/index.ts --outdir=dist --target=bun",
14
+ "prepublishOnly": "bun run build"
14
15
  },
15
16
  "dependencies": {
16
17
  "@agentclientprotocol/sdk": "^0.20.0",