@shipers-dev/multi 0.49.0 → 0.51.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 +279 -122
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -33133,25 +33133,146 @@ var init_workspace_mutex = __esm(() => {
33133
33133
  ]);
33134
33134
  });
33135
33135
 
33136
+ // src/_impl/adapter-pidfile.ts
33137
+ import { existsSync as existsSync5, mkdirSync as mkdirSync5, readdirSync as readdirSync2, readFileSync as readFileSync5, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "fs";
33138
+ import { homedir } from "os";
33139
+ import { join as join7 } from "path";
33140
+ import { spawnSync } from "child_process";
33141
+ function ensureDir() {
33142
+ if (!existsSync5(ADAPTERS_DIR))
33143
+ mkdirSync5(ADAPTERS_DIR, { recursive: true });
33144
+ }
33145
+ function pidfilePath(pid) {
33146
+ return join7(ADAPTERS_DIR, `${pid}.json`);
33147
+ }
33148
+ function writeAdapterPidfile(entry) {
33149
+ ensureDir();
33150
+ const full = {
33151
+ ...entry,
33152
+ daemon_pid: entry.daemon_pid ?? process.pid,
33153
+ started_at: Date.now()
33154
+ };
33155
+ const path = pidfilePath(entry.pid);
33156
+ try {
33157
+ writeFileSync5(path, JSON.stringify(full) + `
33158
+ `, "utf8");
33159
+ } catch {}
33160
+ return path;
33161
+ }
33162
+ function removeAdapterPidfile(pid) {
33163
+ try {
33164
+ unlinkSync3(pidfilePath(pid));
33165
+ } catch {}
33166
+ }
33167
+ function inspectPid(pid) {
33168
+ try {
33169
+ const r = spawnSync("ps", ["-o", "ppid=,command=", "-p", String(pid)], { encoding: "utf8" });
33170
+ if (r.status !== 0)
33171
+ return { alive: false, ppid: 0, command: "" };
33172
+ const line = (r.stdout || "").trim();
33173
+ if (!line)
33174
+ return { alive: false, ppid: 0, command: "" };
33175
+ const m = line.match(/^\s*(\d+)\s+(.*)$/);
33176
+ if (!m)
33177
+ return { alive: false, ppid: 0, command: "" };
33178
+ return { alive: true, ppid: parseInt(m[1], 10), command: m[2] };
33179
+ } catch {
33180
+ return { alive: false, ppid: 0, command: "" };
33181
+ }
33182
+ }
33183
+ function tryKill(pid, signal) {
33184
+ try {
33185
+ process.kill(pid, signal);
33186
+ return true;
33187
+ } catch {
33188
+ return false;
33189
+ }
33190
+ }
33191
+ function isPidAlive(pid) {
33192
+ try {
33193
+ process.kill(pid, 0);
33194
+ return true;
33195
+ } catch {
33196
+ return false;
33197
+ }
33198
+ }
33199
+ function reapStaleAdapters(log3 = () => {}) {
33200
+ ensureDir();
33201
+ let entries2 = [];
33202
+ try {
33203
+ entries2 = readdirSync2(ADAPTERS_DIR);
33204
+ } catch {
33205
+ return 0;
33206
+ }
33207
+ let reaped = 0;
33208
+ for (const name of entries2) {
33209
+ if (!name.endsWith(".json"))
33210
+ continue;
33211
+ const path = join7(ADAPTERS_DIR, name);
33212
+ let parsed = null;
33213
+ try {
33214
+ parsed = JSON.parse(readFileSync5(path, "utf8"));
33215
+ } catch {}
33216
+ if (!parsed || typeof parsed.pid !== "number") {
33217
+ try {
33218
+ unlinkSync3(path);
33219
+ } catch {}
33220
+ continue;
33221
+ }
33222
+ const info = inspectPid(parsed.pid);
33223
+ if (!info.alive) {
33224
+ try {
33225
+ unlinkSync3(path);
33226
+ } catch {}
33227
+ continue;
33228
+ }
33229
+ if (parsed.daemon_pid && isPidAlive(parsed.daemon_pid))
33230
+ continue;
33231
+ if (parsed.bin && !info.command.includes(parsed.bin)) {
33232
+ try {
33233
+ unlinkSync3(path);
33234
+ } catch {}
33235
+ continue;
33236
+ }
33237
+ if (info.ppid !== 1)
33238
+ continue;
33239
+ log3(`[reap] killing orphan ${parsed.kind} pid=${parsed.pid} bin=${parsed.bin} session=${parsed.session_id ?? "?"}`);
33240
+ tryKill(parsed.pid, "SIGTERM");
33241
+ setTimeout(() => {
33242
+ if (isPidAlive(parsed.pid))
33243
+ tryKill(parsed.pid, "SIGKILL");
33244
+ }, 1500).unref?.();
33245
+ try {
33246
+ unlinkSync3(path);
33247
+ } catch {}
33248
+ reaped++;
33249
+ }
33250
+ return reaped;
33251
+ }
33252
+ var ADAPTERS_DIR;
33253
+ var init_adapter_pidfile = __esm(() => {
33254
+ ADAPTERS_DIR = join7(homedir(), ".multi", "adapters");
33255
+ });
33256
+
33136
33257
  // src/_impl/acp-runner.ts
33137
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5, existsSync as existsSync5 } from "fs";
33138
- import { dirname as dirname6, join as join7 } from "path";
33258
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6, existsSync as existsSync6 } from "fs";
33259
+ import { dirname as dirname6, join as join8 } from "path";
33139
33260
  function ensureBypassPermissions(cwd) {
33140
33261
  try {
33141
- const dir = join7(cwd, ".claude");
33142
- if (!existsSync5(dir))
33143
- mkdirSync5(dir, { recursive: true });
33144
- const path = join7(dir, "settings.local.json");
33262
+ const dir = join8(cwd, ".claude");
33263
+ if (!existsSync6(dir))
33264
+ mkdirSync6(dir, { recursive: true });
33265
+ const path = join8(dir, "settings.local.json");
33145
33266
  let json2 = {};
33146
- if (existsSync5(path)) {
33267
+ if (existsSync6(path)) {
33147
33268
  try {
33148
- json2 = JSON.parse(readFileSync5(path, "utf8"));
33269
+ json2 = JSON.parse(readFileSync6(path, "utf8"));
33149
33270
  } catch {
33150
33271
  json2 = {};
33151
33272
  }
33152
33273
  }
33153
33274
  json2.permissions = { ...json2.permissions || {}, defaultMode: "bypassPermissions" };
33154
- writeFileSync5(path, JSON.stringify(json2, null, 2) + `
33275
+ writeFileSync6(path, JSON.stringify(json2, null, 2) + `
33155
33276
  `, "utf8");
33156
33277
  } catch {}
33157
33278
  }
@@ -33195,6 +33316,16 @@ async function runAcp(opts) {
33195
33316
  try {
33196
33317
  opts.onSpawn?.(child);
33197
33318
  } catch {}
33319
+ const pidfileBin = argv[0]?.split("/").pop() || "claude-code-acp";
33320
+ if (typeof child.pid === "number") {
33321
+ writeAdapterPidfile({
33322
+ pid: child.pid,
33323
+ bin: pidfileBin,
33324
+ kind: "acp",
33325
+ session_id: opts.sessionId ?? null,
33326
+ issue_id: opts.issueId ?? null
33327
+ });
33328
+ }
33198
33329
  const output = new WritableStream({
33199
33330
  write(chunk2) {
33200
33331
  child.stdin.write(chunk2);
@@ -33224,7 +33355,7 @@ async function runAcp(opts) {
33224
33355
  },
33225
33356
  async readTextFile(params) {
33226
33357
  try {
33227
- const content = readFileSync5(params.path, "utf8");
33358
+ const content = readFileSync6(params.path, "utf8");
33228
33359
  const sliced = typeof params.line === "number" && typeof params.limit === "number" ? content.split(`
33229
33360
  `).slice(params.line, params.line + params.limit).join(`
33230
33361
  `) : content;
@@ -33236,9 +33367,9 @@ async function runAcp(opts) {
33236
33367
  async writeTextFile(params) {
33237
33368
  try {
33238
33369
  const dir = dirname6(params.path);
33239
- if (!existsSync5(dir))
33240
- mkdirSync5(dir, { recursive: true });
33241
- writeFileSync5(params.path, params.content, "utf8");
33370
+ if (!existsSync6(dir))
33371
+ mkdirSync6(dir, { recursive: true });
33372
+ writeFileSync6(params.path, params.content, "utf8");
33242
33373
  return {};
33243
33374
  } catch (e) {
33244
33375
  throw new Error(`writeTextFile failed: ${fmtErr(e)}`);
@@ -33327,6 +33458,8 @@ async function runAcp(opts) {
33327
33458
  try {
33328
33459
  child.kill();
33329
33460
  } catch {}
33461
+ if (typeof child.pid === "number")
33462
+ removeAdapterPidfile(child.pid);
33330
33463
  }
33331
33464
  async function handleSessionUpdate(params, o) {
33332
33465
  const u = params.update;
@@ -33479,11 +33612,12 @@ var init_acp_runner = __esm(() => {
33479
33612
  init_acp();
33480
33613
  init_client();
33481
33614
  init_workspace_mutex();
33615
+ init_adapter_pidfile();
33482
33616
  });
33483
33617
 
33484
33618
  // src/_impl/acpx-runner.ts
33485
33619
  import { appendFileSync as appendFileSync3 } from "fs";
33486
- import { join as join8 } from "path";
33620
+ import { join as join9 } from "path";
33487
33621
  function dlog(msg) {
33488
33622
  try {
33489
33623
  appendFileSync3(LOG_PATH2, `[${new Date().toISOString()}] ${msg}
@@ -33502,6 +33636,9 @@ async function spawnAcpxPrompt(agentType, cwd, sessionName, prompt, collectAssis
33502
33636
  args2.push(prompt);
33503
33637
  dlog(`[acpx] prompt: ${args2.slice(0, 10).join(" ")} ... (prompt len=${prompt.length})`);
33504
33638
  const proc = Bun.spawn(args2, { stdout: "pipe", stderr: "pipe", stdin: "ignore" });
33639
+ if (typeof proc.pid === "number") {
33640
+ writeAdapterPidfile({ pid: proc.pid, bin: "acpx", kind: "acpx", session_id: sessionName ?? null });
33641
+ }
33505
33642
  let stopReason = "end_turn";
33506
33643
  (async () => {
33507
33644
  try {
@@ -33570,6 +33707,8 @@ async function spawnAcpxPrompt(agentType, cwd, sessionName, prompt, collectAssis
33570
33707
  }
33571
33708
  }
33572
33709
  const code = await proc.exited;
33710
+ if (typeof proc.pid === "number")
33711
+ removeAdapterPidfile(proc.pid);
33573
33712
  if (code !== 0 && code !== 130) {
33574
33713
  if (!collectAssistantText)
33575
33714
  await forward({ event_type: "error", payload: { message: `acpx exited with code ${code}` } });
@@ -33605,6 +33744,9 @@ async function runAcpx(opts) {
33605
33744
  try {
33606
33745
  opts.onSpawn?.(proc);
33607
33746
  } catch {}
33747
+ if (typeof proc.pid === "number") {
33748
+ writeAdapterPidfile({ pid: proc.pid, bin: "acpx", kind: "acpx", session_id: opts.sessionName ?? null });
33749
+ }
33608
33750
  let stopReason = "end_turn";
33609
33751
  (async () => {
33610
33752
  try {
@@ -33661,6 +33803,8 @@ async function runAcpx(opts) {
33661
33803
  await opts.onEvent(ev);
33662
33804
  }
33663
33805
  const code = await proc.exited;
33806
+ if (typeof proc.pid === "number")
33807
+ removeAdapterPidfile(proc.pid);
33664
33808
  if (code !== 0 && code !== 130) {
33665
33809
  await opts.onEvent({ event_type: "error", payload: { message: `acpx exited with code ${code}` } });
33666
33810
  }
@@ -33776,8 +33920,9 @@ function extractText2(content) {
33776
33920
  }
33777
33921
  var HOME3, LOG_PATH2;
33778
33922
  var init_acpx_runner = __esm(() => {
33923
+ init_adapter_pidfile();
33779
33924
  HOME3 = process.env.HOME || process.env.USERPROFILE || ".";
33780
- LOG_PATH2 = join8(HOME3, ".multi", "logs", "agent.log");
33925
+ LOG_PATH2 = join9(HOME3, ".multi", "logs", "agent.log");
33781
33926
  });
33782
33927
 
33783
33928
  // ../../node_modules/zod/index.js
@@ -34003,12 +34148,12 @@ function parsePlanBlocks(text) {
34003
34148
  }
34004
34149
  return { actions, errors: errors3 };
34005
34150
  }
34006
- var PLAN_SCHEMA_VERSION = 5, Priority, AssigneeType, IssueStatus, SessionRole, SkillFile, EvalPolicy, PlanActionSchema, PlanEnvelopeSchema, UiBlockSchema, UI_FENCE_RE, FENCE_RE;
34151
+ var PLAN_SCHEMA_VERSION = 6, Priority, AssigneeType, IssueStatus, SessionRole, SkillFile, EvalPolicy, PlanActionSchema, PlanEnvelopeSchema, UiBlockSchema, UI_FENCE_RE, FENCE_RE;
34007
34152
  var init_plans = __esm(() => {
34008
34153
  init_zod();
34009
34154
  Priority = exports_external.enum(["low", "medium", "high"]);
34010
34155
  AssigneeType = exports_external.enum(["human", "agent"]);
34011
- IssueStatus = exports_external.enum(["todo", "in_progress", "done", "failed", "stopped", "cancelled"]);
34156
+ IssueStatus = exports_external.enum(["todo", "in_progress", "blocked", "done", "archived", "failed", "stopped", "cancelled"]);
34012
34157
  SessionRole = exports_external.enum(["implementer", "reviewer", "test-fixer"]);
34013
34158
  SkillFile = exports_external.object({ path: exports_external.string().min(1), content: exports_external.string() });
34014
34159
  EvalPolicy = exports_external.object({
@@ -34220,8 +34365,8 @@ var init_lib = __esm(() => {
34220
34365
 
34221
34366
  // src/_impl/git-enforce.ts
34222
34367
  import { spawn as spawn2 } from "node:child_process";
34223
- import { existsSync as existsSync9 } from "node:fs";
34224
- import { join as join9 } from "node:path";
34368
+ import { existsSync as existsSync10 } from "node:fs";
34369
+ import { join as join10 } from "node:path";
34225
34370
  function run4(cwd, cmd, args2) {
34226
34371
  return new Promise((resolve2) => {
34227
34372
  const p = spawn2(cmd, args2, { cwd, stdio: ["ignore", "pipe", "pipe"] });
@@ -34241,7 +34386,7 @@ function normalizeKey2(issueKey) {
34241
34386
  return issueKey.toLowerCase().replace(/[^a-z0-9\-_\/]/g, "-");
34242
34387
  }
34243
34388
  function worktreePath(baseWorkingDir, issueKey) {
34244
- return join9(baseWorkingDir, ".multi", "worktrees", normalizeKey2(issueKey));
34389
+ return join10(baseWorkingDir, ".multi", "worktrees", normalizeKey2(issueKey));
34245
34390
  }
34246
34391
  function branchFor(issueKey) {
34247
34392
  return `multi/${normalizeKey2(issueKey)}`;
@@ -34260,7 +34405,7 @@ function enforceCommitAndPush(baseWorkingDir, issueKey, mode = "enforce") {
34260
34405
  };
34261
34406
  if (mode === "off")
34262
34407
  return result;
34263
- if (!existsSync9(wt))
34408
+ if (!existsSync10(wt))
34264
34409
  return result;
34265
34410
  if (!(yield* isGitRepo2(wt)))
34266
34411
  return result;
@@ -34348,7 +34493,7 @@ var git = (cwd, args2, op) => exports_Effect.tryPromise({
34348
34493
  try: () => run4(cwd, "git", args2),
34349
34494
  catch: (cause3) => new GitError({ op, message: `git ${args2.join(" ")} threw`, cause: cause3 })
34350
34495
  }), isGitRepo2 = (dir) => exports_Effect.gen(function* () {
34351
- if (!existsSync9(dir))
34496
+ if (!existsSync10(dir))
34352
34497
  return false;
34353
34498
  const r = yield* git(dir, ["rev-parse", "--is-inside-work-tree"], "rev-parse");
34354
34499
  return r.code === 0 && r.stdout === "true";
@@ -34360,14 +34505,14 @@ var init_git_enforce = __esm(() => {
34360
34505
 
34361
34506
  // src/_impl/outbox.ts
34362
34507
  import { Database as Database2 } from "bun:sqlite";
34363
- import { existsSync as existsSync10, mkdirSync as mkdirSync7 } from "fs";
34364
- import { homedir } from "os";
34365
- import { join as join10 } from "path";
34508
+ import { existsSync as existsSync11, mkdirSync as mkdirSync8 } from "fs";
34509
+ import { homedir as homedir2 } from "os";
34510
+ import { join as join11 } from "path";
34366
34511
  function ensureDb() {
34367
34512
  if (db)
34368
34513
  return db;
34369
- if (!existsSync10(MULTI_DIR3))
34370
- mkdirSync7(MULTI_DIR3, { recursive: true });
34514
+ if (!existsSync11(MULTI_DIR3))
34515
+ mkdirSync8(MULTI_DIR3, { recursive: true });
34371
34516
  db = new Database2(TASKS_DB_PATH2);
34372
34517
  db.exec(`
34373
34518
  CREATE TABLE IF NOT EXISTS stream_outbox (
@@ -34500,17 +34645,17 @@ function startOutboxFlusher(apiUrl, wsId) {
34500
34645
  var MULTI_DIR3, TASKS_DB_PATH2, BATCH_SIZE = 100, FLUSH_INTERVAL_MS = 2000, MAX_BACKOFF_MS = 30000, db = null;
34501
34646
  var init_outbox = __esm(() => {
34502
34647
  init_client();
34503
- MULTI_DIR3 = join10(homedir(), ".multi");
34504
- TASKS_DB_PATH2 = join10(MULTI_DIR3, "tasks.db");
34648
+ MULTI_DIR3 = join11(homedir2(), ".multi");
34649
+ TASKS_DB_PATH2 = join11(MULTI_DIR3, "tasks.db");
34505
34650
  });
34506
34651
 
34507
34652
  // src/_impl/run-task.ts
34508
- import { mkdirSync as mkdirSync8, existsSync as existsSync11, writeFileSync as writeFileSync6, readFileSync as readFileSync9, appendFileSync as appendFileSync4, unlinkSync as unlinkSync5, readdirSync as readdirSync2, statSync as statSync2 } from "fs";
34509
- import { join as join11, dirname as dirname9 } from "path";
34653
+ import { mkdirSync as mkdirSync9, existsSync as existsSync12, writeFileSync as writeFileSync7, readFileSync as readFileSync10, appendFileSync as appendFileSync4, unlinkSync as unlinkSync6, readdirSync as readdirSync3, statSync as statSync2 } from "fs";
34654
+ import { join as join12, dirname as dirname9 } from "path";
34510
34655
  function ensureDirs() {
34511
- for (const d of [MULTI_DIR4, join11(MULTI_DIR4, "logs"), SKILLS_DIR2]) {
34512
- if (!existsSync11(d))
34513
- mkdirSync8(d, { recursive: true });
34656
+ for (const d of [MULTI_DIR4, join12(MULTI_DIR4, "logs"), SKILLS_DIR2]) {
34657
+ if (!existsSync12(d))
34658
+ mkdirSync9(d, { recursive: true });
34514
34659
  }
34515
34660
  }
34516
34661
  function log3(msg) {
@@ -34589,7 +34734,7 @@ async function writeTaskMemory(apiUrl, task, text) {
34589
34734
  async function handleRunTask(apiUrl, deviceId, task, detected, ctx) {
34590
34735
  const issueId = task.issue_id;
34591
34736
  const isFollowup = !!task.followup;
34592
- const baseWorkingDir = task.working_dir && existsSync11(task.working_dir) ? task.working_dir : undefined;
34737
+ const baseWorkingDir = task.working_dir && existsSync12(task.working_dir) ? task.working_dir : undefined;
34593
34738
  const tenantWsId = task.tenant_workspace_id ?? null;
34594
34739
  const projectId = task.project_id ?? null;
34595
34740
  const ISSUE_BASE = tenantWsId && projectId ? `${apiUrl}/api/workspaces/${tenantWsId}/projects/${projectId}/issues/${issueId}` : null;
@@ -34656,13 +34801,13 @@ async function handleRunTask(apiUrl, deviceId, task, detected, ctx) {
34656
34801
  await postStream(apiUrl, issueId, "progress", { message: `Device ${deviceId} picked up ${isFollowup ? "follow-up" : "task"}` });
34657
34802
  let attachmentRefs = [];
34658
34803
  if (task.from_comment_id && task.tenant_workspace_id && task.project_id) {
34659
- const baseDir = workingDir || join11(MULTI_DIR4, "tmp", issueId);
34660
- const inDir = join11(baseDir, ".multi-in", task.from_comment_id);
34804
+ const baseDir = workingDir || join12(MULTI_DIR4, "tmp", issueId);
34805
+ const inDir = join12(baseDir, ".multi-in", task.from_comment_id);
34661
34806
  attachmentRefs = await downloadCommentAttachments(apiUrl, task.tenant_workspace_id, task.project_id, issueId, task.from_comment_id, inDir);
34662
34807
  if (attachmentRefs.length)
34663
34808
  log3(` fetched ${attachmentRefs.length} attachment(s) → ${inDir}`);
34664
34809
  }
34665
- const outDir = join11(workingDir || join11(MULTI_DIR4, "tmp", issueId), ".multi-out");
34810
+ const outDir = join12(workingDir || join12(MULTI_DIR4, "tmp", issueId), ".multi-out");
34666
34811
  let liveCommentId;
34667
34812
  let liveBody = "";
34668
34813
  let hadError = false;
@@ -35172,7 +35317,12 @@ async function buildPlanningPreamble(apiUrl, task, _wsId) {
35172
35317
  if (depth >= PLANNING_DEPTH_LIMIT) {
35173
35318
  return `# Planning (sub-task context)
35174
35319
 
35175
- You are acting on a sub-issue spawned by another agent. You MAY emit a \`multi-plan\` block to update your own issue's status (e.g. mark done/failed) but CANNOT create child issues or delegate further.
35320
+ You are acting on a sub-issue spawned by another agent. You MAY emit a \`multi-plan\` block to update your own issue's status (e.g. mark done/blocked/failed) but CANNOT create child issues or delegate further.
35321
+
35322
+ Status guidance:
35323
+ - \`done\` — work is finished; no further human or agent action needed.
35324
+ - \`blocked\` — you need a human decision before continuing (confirmation, choice between approaches, missing info). Do NOT mark \`done\` when waiting on review.
35325
+ - \`failed\` — work could not be completed; explain in your reply.
35176
35326
 
35177
35327
  \`\`\`multi-plan
35178
35328
  {"actions":[{"type":"update","id":"<this issue id>","status":"done"}]}
@@ -35220,6 +35370,8 @@ Issue actions:
35220
35370
  ]}
35221
35371
  \`\`\`
35222
35372
 
35373
+ Status values: \`todo\` | \`in_progress\` | \`blocked\` | \`done\` | \`archived\` | \`failed\`. **Use \`blocked\` (NOT \`done\`) when you are pausing to wait on a human decision** — confirmation, a choice between approaches, or missing context. Marking such an issue \`done\` is wrong: the work isn't finished, you're waiting on review. Use \`archived\` to hide a completed/abandoned issue from default views.
35374
+
35223
35375
  Prefer the bulk \`issue.delete_where\` over \`issue.list\` + per-issue \`issue.delete\` when the user's intent matches a filter ("delete all todo issues", "remove anything assigned to agent X"). It runs in one turn instead of two.
35224
35376
 
35225
35377
  Read actions (\`issue.list\`, \`issue.search\`) return the matched rows in the action summary comment. Use them to look up issue ids/keys before \`update\` / \`delegate\` / \`issue.delete\` ONLY when the per-row filter isn't enough (e.g. you need to inspect titles before acting).
@@ -35338,7 +35490,7 @@ async function executePlanActions(apiUrl, parentTask, actions, ctx, parseErrors
35338
35490
  }
35339
35491
  lines.push(`- [ok] updated ${res.data.key}`);
35340
35492
  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 });
35341
- if ((a.status === "done" || a.status === "cancelled") && parentTask.working_dir && existsSync11(parentTask.working_dir)) {
35493
+ if ((a.status === "done" || a.status === "cancelled") && parentTask.working_dir && existsSync12(parentTask.working_dir)) {
35342
35494
  const targetKey = res.data?.key;
35343
35495
  if (targetKey) {
35344
35496
  const targetIssueId = res.data?.id || a.id;
@@ -35619,26 +35771,26 @@ function statusIcon(status3) {
35619
35771
  }
35620
35772
  }
35621
35773
  async function resolveAcpAdapter(agentType, detectedPath) {
35622
- if (agentType === "pi" && detectedPath && existsSync11(detectedPath)) {
35774
+ if (agentType === "pi" && detectedPath && existsSync12(detectedPath)) {
35623
35775
  return [detectedPath, "--mode", "rpc"];
35624
35776
  }
35625
35777
  const override = process.env.MULTI_ACP_ADAPTER?.trim();
35626
35778
  const adapterNames = override ? [override] : ["claude-code-acp", "claude-agent-acp"];
35627
35779
  for (const name of adapterNames) {
35628
- if (name.startsWith("/") && existsSync11(name))
35780
+ if (name.startsWith("/") && existsSync12(name))
35629
35781
  return [name];
35630
35782
  try {
35631
35783
  const here = new URL(import.meta.url).pathname;
35632
35784
  let dir = here;
35633
35785
  for (let i = 0;i < 8; i++) {
35634
35786
  dir = dirname9(dir);
35635
- const bin = join11(dir, "node_modules", ".bin", name);
35636
- if (existsSync11(bin))
35787
+ const bin = join12(dir, "node_modules", ".bin", name);
35788
+ if (existsSync12(bin))
35637
35789
  return [bin];
35638
35790
  }
35639
35791
  } catch {}
35640
- const global = join11(HOME4, ".bun", "install", "global", "node_modules", ".bin", name);
35641
- if (existsSync11(global))
35792
+ const global = join12(HOME4, ".bun", "install", "global", "node_modules", ".bin", name);
35793
+ if (existsSync12(global))
35642
35794
  return [global];
35643
35795
  }
35644
35796
  return null;
@@ -35647,7 +35799,7 @@ async function postStream(_apiUrl, issueId, event_type, payload) {
35647
35799
  try {
35648
35800
  ensureDirs();
35649
35801
  const date6 = new Date().toISOString().slice(0, 10);
35650
- const path = join11(MULTI_DIR4, "logs", `events-${date6}.ndjson`);
35802
+ const path = join12(MULTI_DIR4, "logs", `events-${date6}.ndjson`);
35651
35803
  appendFileSync4(path, JSON.stringify({ ts: Date.now(), issue_id: issueId, event_type, payload }) + `
35652
35804
  `);
35653
35805
  } catch {}
@@ -35666,7 +35818,7 @@ async function downloadCommentAttachments(apiUrl, wsId, projectId, issueId, comm
35666
35818
  const items = list.data?.results || list.data || [];
35667
35819
  if (!Array.isArray(items) || items.length === 0)
35668
35820
  return [];
35669
- mkdirSync8(destDir, { recursive: true });
35821
+ mkdirSync9(destDir, { recursive: true });
35670
35822
  const token = authTokenHeader();
35671
35823
  const out = [];
35672
35824
  for (const it of items) {
@@ -35675,8 +35827,8 @@ async function downloadCommentAttachments(apiUrl, wsId, projectId, issueId, comm
35675
35827
  continue;
35676
35828
  const buf = new Uint8Array(await res.arrayBuffer());
35677
35829
  const safe = it.filename.replace(/[^A-Za-z0-9._-]/g, "_");
35678
- const p = join11(destDir, safe);
35679
- writeFileSync6(p, buf);
35830
+ const p = join12(destDir, safe);
35831
+ writeFileSync7(p, buf);
35680
35832
  out.push({ filename: it.filename, path: p });
35681
35833
  }
35682
35834
  return out;
@@ -35686,9 +35838,9 @@ async function downloadCommentAttachments(apiUrl, wsId, projectId, issueId, comm
35686
35838
  }
35687
35839
  function authTokenHeader() {
35688
35840
  try {
35689
- if (!existsSync11(CONFIG_PATH2))
35841
+ if (!existsSync12(CONFIG_PATH2))
35690
35842
  return null;
35691
- const raw = JSON.parse(readFileSync9(CONFIG_PATH2, "utf8"));
35843
+ const raw = JSON.parse(readFileSync10(CONFIG_PATH2, "utf8"));
35692
35844
  const token = raw.token ?? raw.authToken;
35693
35845
  return token ? `Bearer ${token}` : null;
35694
35846
  } catch {
@@ -35696,14 +35848,14 @@ function authTokenHeader() {
35696
35848
  }
35697
35849
  }
35698
35850
  async function uploadOutputDir(apiUrl, wsId, projectId, issueId, commentId, dir) {
35699
- if (!existsSync11(dir))
35851
+ if (!existsSync12(dir))
35700
35852
  return 0;
35701
35853
  const files = [];
35702
35854
  const walk = (d, depth = 0) => {
35703
35855
  if (depth > 3)
35704
35856
  return;
35705
- for (const name of readdirSync2(d)) {
35706
- const p = join11(d, name);
35857
+ for (const name of readdirSync3(d)) {
35858
+ const p = join12(d, name);
35707
35859
  try {
35708
35860
  const st = statSync2(p);
35709
35861
  if (st.isDirectory())
@@ -35721,7 +35873,7 @@ async function uploadOutputDir(apiUrl, wsId, projectId, issueId, commentId, dir)
35721
35873
  let uploaded = 0;
35722
35874
  for (const f of files) {
35723
35875
  try {
35724
- const data = readFileSync9(f);
35876
+ const data = readFileSync10(f);
35725
35877
  const form = new FormData;
35726
35878
  const blob = new Blob([data]);
35727
35879
  form.append("file", blob, f.split("/").pop() || "file");
@@ -35736,7 +35888,7 @@ async function uploadOutputDir(apiUrl, wsId, projectId, issueId, commentId, dir)
35736
35888
  if (res.ok) {
35737
35889
  uploaded++;
35738
35890
  try {
35739
- unlinkSync5(f);
35891
+ unlinkSync6(f);
35740
35892
  } catch {}
35741
35893
  }
35742
35894
  } catch (e) {
@@ -36012,10 +36164,10 @@ var init_run_task = __esm(() => {
36012
36164
  init_git_enforce();
36013
36165
  init_outbox();
36014
36166
  HOME4 = process.env.HOME || process.env.USERPROFILE || ".";
36015
- MULTI_DIR4 = join11(HOME4, ".multi");
36016
- CONFIG_PATH2 = join11(MULTI_DIR4, "config.json");
36017
- LOG_PATH3 = join11(MULTI_DIR4, "logs", "agent.log");
36018
- SKILLS_DIR2 = join11(MULTI_DIR4, "skills");
36167
+ MULTI_DIR4 = join12(HOME4, ".multi");
36168
+ CONFIG_PATH2 = join12(MULTI_DIR4, "config.json");
36169
+ LOG_PATH3 = join12(MULTI_DIR4, "logs", "agent.log");
36170
+ SKILLS_DIR2 = join12(MULTI_DIR4, "skills");
36019
36171
  });
36020
36172
 
36021
36173
  // ../lib/chat-doc.ts
@@ -36061,12 +36213,12 @@ function patchMessage(doc2, mapId, patch9) {
36061
36213
  map20.set(k, v);
36062
36214
  }
36063
36215
  }
36064
- function appendText(doc2, mapId, chunk2) {
36216
+ function appendText(doc2, mapId, chunk3) {
36065
36217
  const map20 = doc2.getContainerById(mapId);
36066
36218
  if (!map20)
36067
36219
  return;
36068
36220
  const cur = map20.get("text") ?? "";
36069
- map20.set("text", cur + chunk2);
36221
+ map20.set("text", cur + chunk3);
36070
36222
  }
36071
36223
  function finalizeMessage(doc2, mapId) {
36072
36224
  const map20 = doc2.getContainerById(mapId);
@@ -36107,8 +36259,8 @@ var init_chat_doc = __esm(() => {
36107
36259
  });
36108
36260
 
36109
36261
  // src/_impl/chat-peer.ts
36110
- import { existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync10, writeFileSync as writeFileSync7 } from "fs";
36111
- import { dirname as dirname10, join as join12 } from "path";
36262
+ import { existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "fs";
36263
+ import { dirname as dirname10, join as join13 } from "path";
36112
36264
  import { LoroDoc as LoroDoc2 } from "loro-crdt";
36113
36265
 
36114
36266
  class ChatPeer {
@@ -36125,24 +36277,24 @@ class ChatPeer {
36125
36277
  constructor(opts) {
36126
36278
  this.opts = opts;
36127
36279
  this.chatId = opts.chatId;
36128
- this.snapshotPath = join12(MULTI_DIR, "chats", `${opts.chatId}.loro`);
36280
+ this.snapshotPath = join13(MULTI_DIR, "chats", `${opts.chatId}.loro`);
36129
36281
  this.doc = this.loadFromDisk();
36130
36282
  for (const m of listMessages(this.doc))
36131
36283
  this.seenIds.add(m.id);
36132
36284
  }
36133
36285
  loadFromDisk() {
36134
36286
  try {
36135
- if (existsSync12(this.snapshotPath)) {
36136
- const bytes = readFileSync10(this.snapshotPath);
36287
+ if (existsSync13(this.snapshotPath)) {
36288
+ const bytes = readFileSync11(this.snapshotPath);
36137
36289
  return importSnapshot(new Uint8Array(bytes));
36138
36290
  }
36139
36291
  } catch {}
36140
36292
  return new LoroDoc2;
36141
36293
  }
36142
36294
  persist() {
36143
- if (!existsSync12(dirname10(this.snapshotPath)))
36144
- mkdirSync9(dirname10(this.snapshotPath), { recursive: true });
36145
- writeFileSync7(this.snapshotPath, exportSnapshot(this.doc));
36295
+ if (!existsSync13(dirname10(this.snapshotPath)))
36296
+ mkdirSync10(dirname10(this.snapshotPath), { recursive: true });
36297
+ writeFileSync8(this.snapshotPath, exportSnapshot(this.doc));
36146
36298
  this.dirtySinceWrite = 0;
36147
36299
  }
36148
36300
  appendAndPush(msg) {
@@ -36177,8 +36329,8 @@ class ChatPeer {
36177
36329
  this.flush();
36178
36330
  return { msgId: msg.id, containerId };
36179
36331
  }
36180
- appendPartialText(containerId, chunk2) {
36181
- appendText(this.doc, containerId, chunk2);
36332
+ appendPartialText(containerId, chunk3) {
36333
+ appendText(this.doc, containerId, chunk3);
36182
36334
  this.flush();
36183
36335
  }
36184
36336
  finalizePartialMessage(containerId) {
@@ -37188,6 +37340,7 @@ Action vocabulary:
37188
37340
 
37189
37341
  Rules:
37190
37342
  - Omit the block entirely if no actions are needed. Don't emit empty arrays.
37343
+ - Status values for \`update\`: \`todo\` | \`in_progress\` | \`blocked\` | \`done\` | \`archived\` | \`failed\`. **Use \`blocked\` (NOT \`done\`) when the issue is paused waiting on a human decision** — confirmation, choice, or missing context. Marking such an issue \`done\` misrepresents finished work. Use \`archived\` to hide a completed/abandoned issue from default views.
37191
37344
  - Max 10 actions per turn. Sub-caps: agent.create=2, skill.create=3, agent.update=5, skill.attach/detach=5, session.create=3, issue.comment=5.
37192
37345
  - Chat-initiated agent.create / agent.update / skill.attach are auto-approved (the user is reading this reply right now). skill.create still queues for human review.
37193
37346
  - Use \`issue.comment\` with \`@<agent name>\` mention to dispatch an agent on an existing issue. Plain comments without an @mention are recorded but do not trigger a run. Issues whose autonomy is \`manual\` will not dispatch.
@@ -37962,7 +38115,7 @@ import { parseArgs } from "util";
37962
38115
  // package.json
37963
38116
  var package_default = {
37964
38117
  name: "@shipers-dev/multi",
37965
- version: "0.49.0",
38118
+ version: "0.51.0",
37966
38119
  type: "module",
37967
38120
  bin: {
37968
38121
  "multi-agent": "./dist/index.js"
@@ -38476,7 +38629,7 @@ class Runners extends exports_Effect.Service()("cli/Runners", {
38476
38629
  // src/commands/simple.ts
38477
38630
  init_esm();
38478
38631
  init_paths();
38479
- import { existsSync as existsSync6, readFileSync as readFileSync6 } from "fs";
38632
+ import { existsSync as existsSync7, readFileSync as readFileSync7 } from "fs";
38480
38633
 
38481
38634
  // src/services/Config.ts
38482
38635
  init_esm();
@@ -38571,7 +38724,7 @@ var statusCmd = exports_Effect.fn("statusCmd")(function* () {
38571
38724
  process.exit(1);
38572
38725
  }
38573
38726
  const d = res.data;
38574
- const pid = existsSync6(PID_PATH) ? readFileSync6(PID_PATH, "utf8").trim() : null;
38727
+ const pid = existsSync7(PID_PATH) ? readFileSync7(PID_PATH, "utf8").trim() : null;
38575
38728
  const daemon = pid && isRunning3(Number(pid)) ? `running (pid ${pid})` : "stopped";
38576
38729
  console.log(`
38577
38730
  Device Status
@@ -38586,11 +38739,11 @@ Daemon: ${daemon}
38586
38739
  });
38587
38740
  var stopCmd = exports_Effect.fn("stopCmd")(function* () {
38588
38741
  const fs3 = yield* FileSystem;
38589
- if (!existsSync6(PID_PATH)) {
38742
+ if (!existsSync7(PID_PATH)) {
38590
38743
  console.log("No daemon running.");
38591
38744
  return;
38592
38745
  }
38593
- const pid = Number(readFileSync6(PID_PATH, "utf8").trim());
38746
+ const pid = Number(readFileSync7(PID_PATH, "utf8").trim());
38594
38747
  if (!pid || !isRunning3(pid)) {
38595
38748
  yield* fs3.remove(PID_PATH);
38596
38749
  console.log("Cleaned stale pidfile.");
@@ -38603,11 +38756,11 @@ var stopCmd = exports_Effect.fn("stopCmd")(function* () {
38603
38756
  } catch {}
38604
38757
  });
38605
38758
  var logsCmd = exports_Effect.fn("logsCmd")(function* () {
38606
- if (!existsSync6(LOG_PATH)) {
38759
+ if (!existsSync7(LOG_PATH)) {
38607
38760
  console.log("No logs yet.");
38608
38761
  return;
38609
38762
  }
38610
- const content = readFileSync6(LOG_PATH, "utf8");
38763
+ const content = readFileSync7(LOG_PATH, "utf8");
38611
38764
  console.log(content.split(`
38612
38765
  `).slice(-100).join(`
38613
38766
  `));
@@ -38616,10 +38769,10 @@ var resetCmd = exports_Effect.fn("resetCmd")(function* (issueId) {
38616
38769
  if (!issueId) {
38617
38770
  return yield* exports_Effect.fail(new UsageError({ message: "reset requires --issue <id>" }));
38618
38771
  }
38619
- if (!existsSync6(PORT_PATH)) {
38772
+ if (!existsSync7(PORT_PATH)) {
38620
38773
  return yield* exports_Effect.fail(new DaemonError({ message: "Daemon not running (no port file)." }));
38621
38774
  }
38622
- const port = Number(readFileSync6(PORT_PATH, "utf8").trim());
38775
+ const port = Number(readFileSync7(PORT_PATH, "utf8").trim());
38623
38776
  const config2 = yield* Config4;
38624
38777
  const cfg = yield* config2.load;
38625
38778
  if (!cfg.dispatchSecret) {
@@ -38780,10 +38933,10 @@ var linkCmd = exports_Effect.fn("linkCmd")(function* (apiUrl, agentId) {
38780
38933
  // src/commands/restart.ts
38781
38934
  init_esm();
38782
38935
  init_paths();
38783
- import { existsSync as existsSync8, readFileSync as readFileSync8, unlinkSync as unlinkSync4 } from "fs";
38936
+ import { existsSync as existsSync9, readFileSync as readFileSync9, unlinkSync as unlinkSync5 } from "fs";
38784
38937
 
38785
38938
  // src/_impl/pid-lock.ts
38786
- import { closeSync, existsSync as existsSync7, mkdirSync as mkdirSync6, openSync, readFileSync as readFileSync7, unlinkSync as unlinkSync3, writeSync } from "fs";
38939
+ import { closeSync, existsSync as existsSync8, mkdirSync as mkdirSync7, openSync, readFileSync as readFileSync8, unlinkSync as unlinkSync4, writeSync } from "fs";
38787
38940
  import { dirname as dirname8 } from "path";
38788
38941
  var isAlive = (pid) => {
38789
38942
  if (!Number.isFinite(pid) || pid <= 0)
@@ -38796,7 +38949,7 @@ var isAlive = (pid) => {
38796
38949
  }
38797
38950
  };
38798
38951
  var writeExclusive = (path, pid) => {
38799
- mkdirSync6(dirname8(path), { recursive: true });
38952
+ mkdirSync7(dirname8(path), { recursive: true });
38800
38953
  const fd = openSync(path, "wx");
38801
38954
  try {
38802
38955
  writeSync(fd, String(pid));
@@ -38815,7 +38968,7 @@ var acquirePidLock = (path) => {
38815
38968
  }
38816
38969
  const raw = (() => {
38817
38970
  try {
38818
- return readFileSync7(path, "utf8").trim();
38971
+ return readFileSync8(path, "utf8").trim();
38819
38972
  } catch {
38820
38973
  return "";
38821
38974
  }
@@ -38827,7 +38980,7 @@ var acquirePidLock = (path) => {
38827
38980
  return { ok: false, existingPid };
38828
38981
  }
38829
38982
  try {
38830
- unlinkSync3(path);
38983
+ unlinkSync4(path);
38831
38984
  } catch {}
38832
38985
  try {
38833
38986
  writeExclusive(path, ourPid);
@@ -38837,7 +38990,7 @@ var acquirePidLock = (path) => {
38837
38990
  throw e;
38838
38991
  const racingRaw = (() => {
38839
38992
  try {
38840
- return readFileSync7(path, "utf8").trim();
38993
+ return readFileSync8(path, "utf8").trim();
38841
38994
  } catch {
38842
38995
  return "";
38843
38996
  }
@@ -38848,12 +39001,12 @@ var acquirePidLock = (path) => {
38848
39001
  };
38849
39002
  var releasePidLock = (path) => {
38850
39003
  try {
38851
- if (!existsSync7(path))
39004
+ if (!existsSync8(path))
38852
39005
  return;
38853
- const raw = readFileSync7(path, "utf8").trim();
39006
+ const raw = readFileSync8(path, "utf8").trim();
38854
39007
  if (Number(raw) !== process.pid)
38855
39008
  return;
38856
- unlinkSync3(path);
39009
+ unlinkSync4(path);
38857
39010
  } catch {}
38858
39011
  };
38859
39012
  var killStaleConnects = () => {
@@ -38918,8 +39071,8 @@ var isRunning4 = (pid) => {
38918
39071
  var restartCmd = exports_Effect.fn("restartCmd")(function* (apiUrl) {
38919
39072
  const fs3 = yield* FileSystem;
38920
39073
  yield* (yield* Config4).ensureDirs;
38921
- if (existsSync8(PID_PATH)) {
38922
- const pid = Number(readFileSync8(PID_PATH, "utf8").trim());
39074
+ if (existsSync9(PID_PATH)) {
39075
+ const pid = Number(readFileSync9(PID_PATH, "utf8").trim());
38923
39076
  if (pid && isRunning4(pid)) {
38924
39077
  yield* fs3.writeText(STOP_PATH, "1");
38925
39078
  try {
@@ -38938,13 +39091,13 @@ var restartCmd = exports_Effect.fn("restartCmd")(function* (apiUrl) {
38938
39091
  }
38939
39092
  }
38940
39093
  try {
38941
- if (existsSync8(PID_PATH))
38942
- unlinkSync4(PID_PATH);
39094
+ if (existsSync9(PID_PATH))
39095
+ unlinkSync5(PID_PATH);
38943
39096
  } catch {}
38944
39097
  }
38945
39098
  try {
38946
- if (existsSync8(STOP_PATH))
38947
- unlinkSync4(STOP_PATH);
39099
+ if (existsSync9(STOP_PATH))
39100
+ unlinkSync5(STOP_PATH);
38948
39101
  } catch {}
38949
39102
  const killed = killStaleConnects();
38950
39103
  if (killed.length)
@@ -39040,21 +39193,22 @@ init_client();
39040
39193
  init_detect();
39041
39194
  init_run_task();
39042
39195
  import { Database as Database3 } from "bun:sqlite";
39043
- import { existsSync as existsSync13, mkdirSync as mkdirSync10, writeFileSync as writeFileSync8, unlinkSync as unlinkSync6 } from "fs";
39044
- import { homedir as homedir2 } from "os";
39045
- import { join as join13 } from "path";
39196
+ import { existsSync as existsSync14, mkdirSync as mkdirSync11, writeFileSync as writeFileSync9, unlinkSync as unlinkSync7 } from "fs";
39197
+ import { homedir as homedir3 } from "os";
39198
+ import { join as join14 } from "path";
39199
+ init_adapter_pidfile();
39046
39200
  init_errors();
39047
- var MULTI_DIR5 = join13(homedir2(), ".multi");
39048
- var PID_PATH2 = join13(MULTI_DIR5, "agent.pid");
39049
- var PORT_PATH2 = join13(MULTI_DIR5, "agent.port");
39050
- var STOP_PATH2 = join13(MULTI_DIR5, "stop.flag");
39051
- var TASKS_DB_PATH3 = join13(MULTI_DIR5, "tasks.db");
39201
+ var MULTI_DIR5 = join14(homedir3(), ".multi");
39202
+ var PID_PATH2 = join14(MULTI_DIR5, "agent.pid");
39203
+ var PORT_PATH2 = join14(MULTI_DIR5, "agent.port");
39204
+ var STOP_PATH2 = join14(MULTI_DIR5, "stop.flag");
39205
+ var TASKS_DB_PATH3 = join14(MULTI_DIR5, "tasks.db");
39052
39206
  function ensureDirs2() {
39053
- if (!existsSync13(MULTI_DIR5))
39054
- mkdirSync10(MULTI_DIR5, { recursive: true });
39055
- const logs = join13(MULTI_DIR5, "logs");
39056
- if (!existsSync13(logs))
39057
- mkdirSync10(logs, { recursive: true });
39207
+ if (!existsSync14(MULTI_DIR5))
39208
+ mkdirSync11(MULTI_DIR5, { recursive: true });
39209
+ const logs = join14(MULTI_DIR5, "logs");
39210
+ if (!existsSync14(logs))
39211
+ mkdirSync11(logs, { recursive: true });
39058
39212
  }
39059
39213
  function isLocalApi(url2) {
39060
39214
  try {
@@ -39346,8 +39500,11 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
39346
39500
  if (cfg.authToken)
39347
39501
  setAuthToken(cfg.authToken);
39348
39502
  ensureDirs2();
39349
- if (existsSync13(STOP_PATH2))
39350
- unlinkSync6(STOP_PATH2);
39503
+ if (existsSync14(STOP_PATH2))
39504
+ unlinkSync7(STOP_PATH2);
39505
+ const reaped = reapStaleAdapters((m) => log3(m));
39506
+ if (reaped > 0)
39507
+ log3(`reaped ${reaped} stale adapter${reaped === 1 ? "" : "s"}`);
39351
39508
  const detected = yield* exports_Effect.promise(() => detectAgents());
39352
39509
  const localMode = isLocalApi(apiUrl);
39353
39510
  log3(`daemon device=${cfg.deviceId} pid=${process.pid}`);
@@ -39481,10 +39638,10 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
39481
39638
  });
39482
39639
  log3(`Local server: http://127.0.0.1:${port}`);
39483
39640
  try {
39484
- writeFileSync8(PORT_PATH2, String(port));
39641
+ writeFileSync9(PORT_PATH2, String(port));
39485
39642
  } catch {}
39486
39643
  try {
39487
- writeFileSync8(PID_PATH2, String(process.pid));
39644
+ writeFileSync9(PID_PATH2, String(process.pid));
39488
39645
  } catch {}
39489
39646
  let tunnel;
39490
39647
  if (localMode) {
@@ -39548,7 +39705,7 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
39548
39705
  let probeFailures = 0;
39549
39706
  while (true) {
39550
39707
  yield* exports_Effect.sleep(exports_Duration.seconds(120));
39551
- if (existsSync13(STOP_PATH2)) {
39708
+ if (existsSync14(STOP_PATH2)) {
39552
39709
  yield* exports_Deferred.succeed(stopDeferred, "stop flag");
39553
39710
  return;
39554
39711
  }
@@ -39573,7 +39730,7 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
39573
39730
  yield* exports_Effect.forkIn(daemonScope)(exports_Effect.gen(function* () {
39574
39731
  while (true) {
39575
39732
  yield* exports_Effect.sleep(exports_Duration.seconds(5));
39576
- if (existsSync13(STOP_PATH2)) {
39733
+ if (existsSync14(STOP_PATH2)) {
39577
39734
  yield* exports_Deferred.succeed(stopDeferred, "stop flag");
39578
39735
  return;
39579
39736
  }
@@ -39613,12 +39770,12 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
39613
39770
  yield* exports_Effect.race(exports_Fiber.interruptAll(inFlight), exports_Effect.sleep(exports_Duration.seconds(10)));
39614
39771
  }
39615
39772
  yield* exports_Scope.close(daemonScope, exports_Exit.void).pipe(exports_Effect.catchAll(() => exports_Effect.void));
39616
- if (existsSync13(PID_PATH2))
39617
- unlinkSync6(PID_PATH2);
39618
- if (existsSync13(STOP_PATH2))
39619
- unlinkSync6(STOP_PATH2);
39620
- if (existsSync13(PORT_PATH2))
39621
- unlinkSync6(PORT_PATH2);
39773
+ if (existsSync14(PID_PATH2))
39774
+ unlinkSync7(PID_PATH2);
39775
+ if (existsSync14(STOP_PATH2))
39776
+ unlinkSync7(STOP_PATH2);
39777
+ if (existsSync14(PORT_PATH2))
39778
+ unlinkSync7(PORT_PATH2);
39622
39779
  db2.close();
39623
39780
  log3("disconnected");
39624
39781
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipers-dev/multi",
3
- "version": "0.49.0",
3
+ "version": "0.51.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "multi-agent": "./dist/index.js"