@shipers-dev/dayline 0.95.1 → 0.99.1

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 +297 -113
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -18333,17 +18333,37 @@ var init_esm = __esm(() => {
18333
18333
 
18334
18334
  // src/paths.ts
18335
18335
  import { join as join4 } from "path";
18336
- var HOME, MULTI_DIR, CONFIG_PATH, PID_PATH, PORT_PATH, LOG_PATH, SKILLS_DIR, STOP_PATH, TASKS_DB_PATH;
18336
+ function daylineDir() {
18337
+ return process.env.DAYLINE_HOME || join4(HOME, ".dayline");
18338
+ }
18339
+ function hash32(text) {
18340
+ let h = 2166136261;
18341
+ for (let i = 0;i < text.length; i++) {
18342
+ h ^= text.charCodeAt(i);
18343
+ h = Math.imul(h, 16777619) >>> 0;
18344
+ }
18345
+ return h >>> 0;
18346
+ }
18347
+ function daemonPortFor(dir) {
18348
+ if (dir === join4(HOME, ".dayline"))
18349
+ return DEFAULT_DAEMON_PORT;
18350
+ return DERIVED_PORT_BASE + hash32(dir) % DERIVED_PORT_SPAN;
18351
+ }
18352
+ function daemonPort() {
18353
+ return daemonPortFor(daylineDir());
18354
+ }
18355
+ var HOME, DAYLINE_DIR, CONFIG_PATH, PID_PATH, PORT_PATH, LOG_PATH, SKILLS_DIR, STOP_PATH, TASKS_DB_PATH, DEFAULT_DAEMON_PORT = 47832, DERIVED_PORT_BASE = 48000, DERIVED_PORT_SPAN = 1000, DAEMON_PORT;
18337
18356
  var init_paths = __esm(() => {
18338
18357
  HOME = process.env.HOME || process.env.USERPROFILE || ".";
18339
- MULTI_DIR = process.env.MULTI_HOME || join4(HOME, ".multi");
18340
- CONFIG_PATH = join4(MULTI_DIR, "config.json");
18341
- PID_PATH = join4(MULTI_DIR, "agent.pid");
18342
- PORT_PATH = join4(MULTI_DIR, "agent.port");
18343
- LOG_PATH = join4(MULTI_DIR, "logs", "agent.log");
18344
- SKILLS_DIR = join4(MULTI_DIR, "skills");
18345
- STOP_PATH = join4(MULTI_DIR, "stop.flag");
18346
- TASKS_DB_PATH = join4(MULTI_DIR, "tasks.db");
18358
+ DAYLINE_DIR = daylineDir();
18359
+ CONFIG_PATH = join4(DAYLINE_DIR, "config.json");
18360
+ PID_PATH = join4(DAYLINE_DIR, "agent.pid");
18361
+ PORT_PATH = join4(DAYLINE_DIR, "agent.port");
18362
+ LOG_PATH = join4(DAYLINE_DIR, "logs", "agent.log");
18363
+ SKILLS_DIR = join4(DAYLINE_DIR, "skills");
18364
+ STOP_PATH = join4(DAYLINE_DIR, "stop.flag");
18365
+ TASKS_DB_PATH = join4(DAYLINE_DIR, "tasks.db");
18366
+ DAEMON_PORT = daemonPort();
18347
18367
  });
18348
18368
 
18349
18369
  // src/errors.ts
@@ -18579,7 +18599,7 @@ function ensureGitignoreEntry(workingDir, entry) {
18579
18599
  } catch {}
18580
18600
  }
18581
18601
  function indexPath(workingDir) {
18582
- return join5(workingDir, ".multi", "worktrees", "_index.json");
18602
+ return join5(workingDir, ".dayline", "worktrees", "_index.json");
18583
18603
  }
18584
18604
  function readIndex(workingDir) {
18585
18605
  try {
@@ -18620,10 +18640,10 @@ async function ensureWorktree(workingDir, issueKey, issueId, opts) {
18620
18640
  if (!await isGitRepo(workingDir)) {
18621
18641
  return { path: workingDir, branch: "", created: false };
18622
18642
  }
18623
- ensureGitignoreEntry(workingDir, ".multi/");
18643
+ ensureGitignoreEntry(workingDir, ".dayline/");
18624
18644
  const slug = worktreeSlug(opts?.worktreeName ?? issueKey);
18625
18645
  const branch = `multi/${slug}`;
18626
- const wtDir = join5(workingDir, ".multi", "worktrees");
18646
+ const wtDir = join5(workingDir, ".dayline", "worktrees");
18627
18647
  const wtPath = join5(wtDir, slug);
18628
18648
  let baseRef = "HEAD";
18629
18649
  const explicit = opts?.baseBranch || opts?.parentBranch || null;
@@ -18689,7 +18709,9 @@ async function linkIgnoredFiles(workingDir, wtPath) {
18689
18709
  `).map((l) => l.trim()).filter(Boolean);
18690
18710
  for (const raw of entries2) {
18691
18711
  const rel = raw.endsWith("/") ? raw.slice(0, -1) : raw;
18692
- if (!rel || rel === ".multi" || rel.startsWith(".multi/"))
18712
+ if (!rel || rel === ".dayline" || rel.startsWith(".dayline/"))
18713
+ continue;
18714
+ if (rel === ".multi" || rel.startsWith(".multi/"))
18693
18715
  continue;
18694
18716
  if (rel === ".git" || rel.startsWith(".git/"))
18695
18717
  continue;
@@ -18713,7 +18735,7 @@ async function removeWorktree(workingDir, issueKey, opts = {}) {
18713
18735
  }
18714
18736
  const key = worktreeSlug(issueKey);
18715
18737
  const branch = `multi/${key}`;
18716
- const wtPath = join5(workingDir, ".multi", "worktrees", key);
18738
+ const wtPath = join5(workingDir, ".dayline", "worktrees", key);
18717
18739
  if (existsSync3(wtPath)) {
18718
18740
  const dirty = await isDirty(wtPath);
18719
18741
  if (dirty && !opts.force) {
@@ -37790,7 +37812,6 @@ var init_workspace_mutex = __esm(() => {
37790
37812
 
37791
37813
  // src/_impl/adapter-pidfile.ts
37792
37814
  import { existsSync as existsSync5, mkdirSync as mkdirSync5, readdirSync as readdirSync2, readFileSync as readFileSync5, unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "fs";
37793
- import { homedir } from "os";
37794
37815
  import { join as join7 } from "path";
37795
37816
  import { spawnSync } from "child_process";
37796
37817
  function ensureDir() {
@@ -37964,7 +37985,8 @@ function killDaemonChildren(daemonPid, log3 = () => {}) {
37964
37985
  }
37965
37986
  var ADAPTERS_DIR;
37966
37987
  var init_adapter_pidfile = __esm(() => {
37967
- ADAPTERS_DIR = join7(homedir(), ".multi", "adapters");
37988
+ init_paths();
37989
+ ADAPTERS_DIR = join7(daylineDir(), "adapters");
37968
37990
  });
37969
37991
 
37970
37992
  // src/_impl/acp-runner.ts
@@ -38643,11 +38665,11 @@ function extractText2(content) {
38643
38665
  return content.text;
38644
38666
  return "";
38645
38667
  }
38646
- var HOME3, LOG_PATH2;
38668
+ var LOG_PATH2;
38647
38669
  var init_acpx_runner = __esm(() => {
38648
38670
  init_adapter_pidfile();
38649
- HOME3 = process.env.HOME || process.env.USERPROFILE || ".";
38650
- LOG_PATH2 = join9(HOME3, ".multi", "logs", "agent.log");
38671
+ init_paths();
38672
+ LOG_PATH2 = join9(daylineDir(), "logs", "agent.log");
38651
38673
  });
38652
38674
 
38653
38675
  // ../../node_modules/zod/index.js
@@ -39245,7 +39267,7 @@ function normalizeKey(issueKey) {
39245
39267
  return issueKey.toLowerCase().replace(/[^a-z0-9\-_\/]/g, "-");
39246
39268
  }
39247
39269
  function worktreePath(baseWorkingDir, issueKey) {
39248
- return join10(baseWorkingDir, ".multi", "worktrees", normalizeKey(issueKey));
39270
+ return join10(baseWorkingDir, ".dayline", "worktrees", normalizeKey(issueKey));
39249
39271
  }
39250
39272
  function branchFor(issueKey) {
39251
39273
  return `multi/${normalizeKey(issueKey)}`;
@@ -39365,13 +39387,12 @@ var init_git_enforce = __esm(() => {
39365
39387
  // src/_impl/outbox.ts
39366
39388
  import { Database as Database2 } from "bun:sqlite";
39367
39389
  import { existsSync as existsSync11, mkdirSync as mkdirSync8 } from "fs";
39368
- import { homedir as homedir2 } from "os";
39369
39390
  import { join as join11 } from "path";
39370
39391
  function ensureDb() {
39371
39392
  if (db)
39372
39393
  return db;
39373
- if (!existsSync11(MULTI_DIR3))
39374
- mkdirSync8(MULTI_DIR3, { recursive: true });
39394
+ if (!existsSync11(DAYLINE_DIR3))
39395
+ mkdirSync8(DAYLINE_DIR3, { recursive: true });
39375
39396
  db = new Database2(TASKS_DB_PATH2);
39376
39397
  db.exec(`
39377
39398
  CREATE TABLE IF NOT EXISTS stream_outbox (
@@ -39528,11 +39549,12 @@ function startOutboxFlusher(apiUrl, wsId) {
39528
39549
  clearTimeout(timer);
39529
39550
  };
39530
39551
  }
39531
- var MULTI_DIR3, TASKS_DB_PATH2, BATCH_SIZE = 100, FLUSH_INTERVAL_MS = 2000, MAX_BACKOFF_MS = 30000, db = null, kickFlusher = null, PERMANENT_REJECT_REASONS;
39552
+ var DAYLINE_DIR3, TASKS_DB_PATH2, BATCH_SIZE = 100, FLUSH_INTERVAL_MS = 2000, MAX_BACKOFF_MS = 30000, db = null, kickFlusher = null, PERMANENT_REJECT_REASONS;
39532
39553
  var init_outbox = __esm(() => {
39533
39554
  init_client();
39534
- MULTI_DIR3 = join11(homedir2(), ".multi");
39535
- TASKS_DB_PATH2 = join11(MULTI_DIR3, "tasks.db");
39555
+ init_paths();
39556
+ DAYLINE_DIR3 = daylineDir();
39557
+ TASKS_DB_PATH2 = join11(DAYLINE_DIR3, "tasks.db");
39536
39558
  PERMANENT_REJECT_REASONS = new Set(["issue_not_found", "project_not_found", "forbidden", "no_workspace"]);
39537
39559
  });
39538
39560
 
@@ -39540,7 +39562,7 @@ var init_outbox = __esm(() => {
39540
39562
  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";
39541
39563
  import { join as join12, dirname as dirname9 } from "path";
39542
39564
  function ensureDirs() {
39543
- for (const d of [MULTI_DIR4, join12(MULTI_DIR4, "logs"), SKILLS_DIR2]) {
39565
+ for (const d of [DAYLINE_DIR4, join12(DAYLINE_DIR4, "logs"), SKILLS_DIR2]) {
39544
39566
  if (!existsSync12(d))
39545
39567
  mkdirSync9(d, { recursive: true });
39546
39568
  }
@@ -39818,8 +39840,8 @@ async function handleRunTask(apiUrl, deviceId, task, detected, ctx) {
39818
39840
  await postStream(apiUrl, issueId, "progress", { message: `Device ${deviceId} picked up ${isFollowup ? "follow-up" : "task"}` });
39819
39841
  let attachmentRefs = [];
39820
39842
  if (task.from_comment_id && task.tenant_workspace_id && task.project_id) {
39821
- const baseDir = workingDir || join12(MULTI_DIR4, "tmp", issueId);
39822
- const inDir = join12(baseDir, ".multi-in", task.from_comment_id);
39843
+ const baseDir = workingDir || join12(DAYLINE_DIR4, "tmp", issueId);
39844
+ const inDir = join12(baseDir, ".dayline-in", task.from_comment_id);
39823
39845
  try {
39824
39846
  attachmentRefs = await downloadCommentAttachments(apiUrl, task.tenant_workspace_id, task.project_id, issueId, task.from_comment_id, inDir);
39825
39847
  if (attachmentRefs.length)
@@ -39828,7 +39850,7 @@ async function handleRunTask(apiUrl, deviceId, task, detected, ctx) {
39828
39850
  log3(`[from_comment_id] attachment fetch failed — comments table may be gone (Phase 6): ${String(e).slice(0, 200)}`);
39829
39851
  }
39830
39852
  }
39831
- const outDir = join12(workingDir || join12(MULTI_DIR4, "tmp", issueId), ".multi-out");
39853
+ const outDir = join12(workingDir || join12(DAYLINE_DIR4, "tmp", issueId), ".dayline-out");
39832
39854
  let hadError = false;
39833
39855
  let hasAssistantText = false;
39834
39856
  let memorySummary = null;
@@ -40363,7 +40385,7 @@ ${userPart}` : userPart;
40363
40385
  }
40364
40386
  });
40365
40387
  if (files.length > 0)
40366
- log3(` [Phase 4.5] agent wrote ${files.length} file(s) to .multi-out; attachments via chat upload not wired in this path`);
40388
+ log3(` [Phase 4.5] agent wrote ${files.length} file(s) to .dayline-out; attachments via chat upload not wired in this path`);
40367
40389
  }
40368
40390
  if (ctx) {
40369
40391
  const fullText = turn.blocks.filter((b) => b.kind === "text").map((b) => b.text).join(`
@@ -41229,7 +41251,7 @@ async function resolveAcpAdapter(agentType, detectedPath) {
41229
41251
  return [bin];
41230
41252
  }
41231
41253
  } catch {}
41232
- const global = join12(HOME4, ".bun", "install", "global", "node_modules", ".bin", name);
41254
+ const global = join12(HOME3, ".bun", "install", "global", "node_modules", ".bin", name);
41233
41255
  if (existsSync12(global))
41234
41256
  return [global];
41235
41257
  }
@@ -41239,7 +41261,7 @@ async function postStream(_apiUrl, issueId, event_type, payload) {
41239
41261
  try {
41240
41262
  ensureDirs();
41241
41263
  const date6 = new Date().toISOString().slice(0, 10);
41242
- const path = join12(MULTI_DIR4, "logs", `events-${date6}.ndjson`);
41264
+ const path = join12(DAYLINE_DIR4, "logs", `events-${date6}.ndjson`);
41243
41265
  appendFileSync4(path, JSON.stringify({ ts: Date.now(), issue_id: issueId, event_type, payload }) + `
41244
41266
  `);
41245
41267
  } catch {}
@@ -41482,7 +41504,7 @@ function buildArgs(type3, prompt) {
41482
41504
  return [prompt];
41483
41505
  }
41484
41506
  }
41485
- var HOME4, MULTI_DIR4, CONFIG_PATH2, LOG_PATH3, SKILLS_DIR2, conflictAttempts, enforceWorktreeCheckpointE = (apiUrl, issueId, baseWorkingDir, issueKey, mode) => enforceCommitAndPush(baseWorkingDir, issueKey, mode).pipe(exports_Effect.tap((res) => exports_Effect.sync(() => {
41507
+ var HOME3, DAYLINE_DIR4, CONFIG_PATH2, LOG_PATH3, SKILLS_DIR2, conflictAttempts, enforceWorktreeCheckpointE = (apiUrl, issueId, baseWorkingDir, issueKey, mode) => enforceCommitAndPush(baseWorkingDir, issueKey, mode).pipe(exports_Effect.tap((res) => exports_Effect.sync(() => {
41486
41508
  if (!res.ran)
41487
41509
  return;
41488
41510
  if (res.committed) {
@@ -41553,11 +41575,12 @@ var init_run_task = __esm(() => {
41553
41575
  init_esm();
41554
41576
  init_git_enforce();
41555
41577
  init_outbox();
41556
- HOME4 = process.env.HOME || process.env.USERPROFILE || ".";
41557
- MULTI_DIR4 = join12(HOME4, ".multi");
41558
- CONFIG_PATH2 = join12(MULTI_DIR4, "config.json");
41559
- LOG_PATH3 = join12(MULTI_DIR4, "logs", "agent.log");
41560
- SKILLS_DIR2 = join12(MULTI_DIR4, "skills");
41578
+ init_paths();
41579
+ HOME3 = process.env.HOME || process.env.USERPROFILE || ".";
41580
+ DAYLINE_DIR4 = daylineDir();
41581
+ CONFIG_PATH2 = join12(DAYLINE_DIR4, "config.json");
41582
+ LOG_PATH3 = join12(DAYLINE_DIR4, "logs", "agent.log");
41583
+ SKILLS_DIR2 = join12(DAYLINE_DIR4, "skills");
41561
41584
  conflictAttempts = new Map;
41562
41585
  });
41563
41586
 
@@ -42395,7 +42418,6 @@ __export(exports_worktree_create, {
42395
42418
  materialiseWorktree: () => materialiseWorktree,
42396
42419
  removeWorktree: () => removeWorktree2
42397
42420
  });
42398
- import { homedir as homedir3 } from "os";
42399
42421
  import { existsSync as existsSync13, mkdirSync as mkdirSync10, readFileSync as readFileSync11, symlinkSync as symlinkSync3, writeFileSync as writeFileSync8, appendFileSync as appendFileSync5 } from "fs";
42400
42422
  import { dirname as dirname10, join as join14 } from "path";
42401
42423
  function loadOrInitConfig(repoRoot, log4) {
@@ -42518,7 +42540,7 @@ async function materialiseWorktree(opts) {
42518
42540
  const head5 = await run5(["git", "rev-parse", "--abbrev-ref", "HEAD"], repoRoot);
42519
42541
  baseBranch = head5.ok ? head5.stdout : "HEAD";
42520
42542
  }
42521
- const worktreesDir = join14(homedir3(), ".multi", "worktrees");
42543
+ const worktreesDir = join14(daylineDir(), "worktrees");
42522
42544
  const path = join14(worktreesDir, name);
42523
42545
  if (existsSync13(path)) {
42524
42546
  throw new Error(`worktree path already exists: ${path}`);
@@ -42561,6 +42583,7 @@ var CONFIG_FILENAME = "multi.config.jsonc", CONFIG_TEMPLATE = `{
42561
42583
  `, CITY_CODENAMES;
42562
42584
  var init_worktree_create = __esm(() => {
42563
42585
  init_main();
42586
+ init_paths();
42564
42587
  CITY_CODENAMES = [
42565
42588
  "raleigh",
42566
42589
  "yokohama",
@@ -42759,7 +42782,7 @@ class ChatPeer {
42759
42782
  constructor(opts) {
42760
42783
  this.opts = opts;
42761
42784
  this.chatId = opts.chatId;
42762
- this.snapshotPath = join15(MULTI_DIR, "chats", `${opts.chatId}.loro`);
42785
+ this.snapshotPath = join15(daylineDir(), "chats", `${opts.chatId}.loro`);
42763
42786
  this.doc = this.loadFromDisk();
42764
42787
  for (const m of listMessages(this.doc))
42765
42788
  this.seenIds.add(m.id);
@@ -43868,7 +43891,7 @@ async function downloadUserAttachments(opts) {
43868
43891
  const atts = message.attachments || [];
43869
43892
  if (atts.length === 0)
43870
43893
  return [];
43871
- const baseRel = join16(".multi", "attachments", message.id);
43894
+ const baseRel = join16(".dayline", "attachments", message.id);
43872
43895
  const baseAbs = join16(cwd, baseRel);
43873
43896
  if (!existsSync15(baseAbs))
43874
43897
  mkdirSync12(baseAbs, { recursive: true });
@@ -45260,7 +45283,7 @@ import { parseArgs } from "util";
45260
45283
  // package.json
45261
45284
  var package_default = {
45262
45285
  name: "@shipers-dev/dayline",
45263
- version: "0.95.1",
45286
+ version: "0.99.1",
45264
45287
  type: "module",
45265
45288
  bin: {
45266
45289
  dayline: "./dist/index.js"
@@ -45269,7 +45292,7 @@ var package_default = {
45269
45292
  "dist"
45270
45293
  ],
45271
45294
  scripts: {
45272
- dev: "MULTI_HOME=${MULTI_HOME:-$HOME/.multi-dev} MULTI_API=${MULTI_API:-http://127.0.0.1:8787} bun run src/index.ts connect",
45295
+ dev: "DAYLINE_HOME=${DAYLINE_HOME:-$HOME/.dayline-dev} MULTI_API=${MULTI_API:-http://127.0.0.1:8787} bun run src/index.ts connect",
45273
45296
  build: "bun build src/index.ts --outdir=dist --target=node --sourcemap=none --external loro-crdt",
45274
45297
  test: "bun test",
45275
45298
  prepublishOnly: "bun run build",
@@ -45350,7 +45373,7 @@ class Config3 extends exports_Effect.Service()("cli/Config", {
45350
45373
  effect: exports_Effect.gen(function* () {
45351
45374
  const fs2 = yield* FileSystem;
45352
45375
  const ensureDirs = exports_Effect.gen(function* () {
45353
- yield* fs2.mkdirp(MULTI_DIR);
45376
+ yield* fs2.mkdirp(DAYLINE_DIR);
45354
45377
  yield* fs2.mkdirp(dirname2(LOG_PATH));
45355
45378
  yield* fs2.mkdirp(SKILLS_DIR);
45356
45379
  });
@@ -45497,7 +45520,7 @@ CREATE INDEX IF NOT EXISTS idx_tasks_issue ON tasks(issue_id);
45497
45520
  class TasksDb extends exports_Effect.Service()("cli/TasksDb", {
45498
45521
  effect: exports_Effect.gen(function* () {
45499
45522
  const fs3 = yield* FileSystem;
45500
- yield* fs3.mkdirp(MULTI_DIR);
45523
+ yield* fs3.mkdirp(DAYLINE_DIR);
45501
45524
  const db = yield* exports_Effect.try({
45502
45525
  try: () => {
45503
45526
  const d = new Database(TASKS_DB_PATH);
@@ -45570,17 +45593,18 @@ init_esm();
45570
45593
 
45571
45594
  // src/_impl/materializer.ts
45572
45595
  init_client();
45596
+ init_paths();
45573
45597
  import { mkdirSync as mkdirSync4, existsSync as existsSync4, writeFileSync as writeFileSync4, readFileSync as readFileSync4, rmSync as rmSync2, symlinkSync as symlinkSync2, lstatSync } from "fs";
45574
45598
  import { join as join6, dirname as dirname5 } from "path";
45575
45599
  var HOME2 = process.env.HOME || process.env.USERPROFILE || ".";
45576
- var MULTI_DIR2 = join6(HOME2, ".multi");
45577
- var MULTI_SKILLS = join6(MULTI_DIR2, "skills");
45578
- var MULTI_AGENTS = join6(MULTI_DIR2, "agents");
45579
- var STATE_PATH = join6(MULTI_DIR2, "materialized.json");
45600
+ var DAYLINE_DIR2 = daylineDir();
45601
+ var DAYLINE_SKILLS = join6(DAYLINE_DIR2, "skills");
45602
+ var DAYLINE_AGENTS = join6(DAYLINE_DIR2, "agents");
45603
+ var STATE_PATH = join6(DAYLINE_DIR2, "materialized.json");
45580
45604
  var CLAUDE_DIR = join6(HOME2, ".claude");
45581
45605
  var CLAUDE_SKILLS = join6(CLAUDE_DIR, "skills");
45582
45606
  var CLAUDE_AGENTS = join6(CLAUDE_DIR, "agents");
45583
- var MARKER = ".multi-managed";
45607
+ var MARKER = ".dayline-managed";
45584
45608
  function slugify(s) {
45585
45609
  return s.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "unnamed";
45586
45610
  }
@@ -45592,7 +45616,7 @@ function loadState() {
45592
45616
  }
45593
45617
  }
45594
45618
  function saveState(s) {
45595
- mkdirSync4(MULTI_DIR2, { recursive: true });
45619
+ mkdirSync4(DAYLINE_DIR2, { recursive: true });
45596
45620
  writeFileSync4(STATE_PATH, JSON.stringify(s, null, 2));
45597
45621
  }
45598
45622
  function safeRmManaged(path) {
@@ -45616,7 +45640,7 @@ function safeRmManaged(path) {
45616
45640
  } catch {}
45617
45641
  }
45618
45642
  function writeManagedSkill(slug, skill) {
45619
- const dir = join6(MULTI_SKILLS, slug);
45643
+ const dir = join6(DAYLINE_SKILLS, slug);
45620
45644
  mkdirSync4(dir, { recursive: true });
45621
45645
  writeFileSync4(join6(dir, MARKER), `skill_id=${skill.id}
45622
45646
  revision=${Date.now()}
@@ -45693,7 +45717,7 @@ async function materializeBundle(apiUrl, wsId, deviceId, log3) {
45693
45717
  }
45694
45718
  for (const old of prev.skill_slugs) {
45695
45719
  if (!newSkillSlugs.includes(old)) {
45696
- safeRmManaged(join6(MULTI_SKILLS, old));
45720
+ safeRmManaged(join6(DAYLINE_SKILLS, old));
45697
45721
  safeRmManaged(join6(CLAUDE_SKILLS, old));
45698
45722
  }
45699
45723
  }
@@ -45786,7 +45810,7 @@ class Config4 extends exports_Effect.Service()("cli/Config", {
45786
45810
  effect: exports_Effect.gen(function* () {
45787
45811
  const fs3 = yield* FileSystem;
45788
45812
  const ensureDirs = exports_Effect.gen(function* () {
45789
- yield* fs3.mkdirp(MULTI_DIR);
45813
+ yield* fs3.mkdirp(DAYLINE_DIR);
45790
45814
  yield* fs3.mkdirp(dirname7(LOG_PATH));
45791
45815
  yield* fs3.mkdirp(SKILLS_DIR);
45792
45816
  });
@@ -45983,6 +46007,7 @@ class Materializer2 extends exports_Effect.Service()("cli/Materializer", {
45983
46007
  init_errors();
45984
46008
 
45985
46009
  // src/_impl/web-url.ts
46010
+ var DEV_WEB_PORT = 5173;
45986
46011
  function webUrlFor(apiUrl) {
45987
46012
  const override = process.env.MULTI_WEB || process.env.MULTI_WEB_URL;
45988
46013
  if (override)
@@ -45993,8 +46018,11 @@ function webUrlFor(apiUrl) {
45993
46018
  } catch {
45994
46019
  return "https://dayline.ai";
45995
46020
  }
45996
- if (u.hostname === "localhost" || u.hostname === "127.0.0.1" || u.hostname.endsWith(".local")) {
45997
- return u.origin;
46021
+ if (u.hostname === "localhost" || u.hostname === "127.0.0.1") {
46022
+ return `${u.protocol}//localhost:${DEV_WEB_PORT}`;
46023
+ }
46024
+ if (u.hostname.endsWith(".local")) {
46025
+ return `${u.protocol}//${u.hostname}:${DEV_WEB_PORT}`;
45998
46026
  }
45999
46027
  if (u.hostname.startsWith("api.")) {
46000
46028
  return `${u.protocol}//${u.hostname.slice(4)}`;
@@ -46063,7 +46091,16 @@ var setupCmd = exports_Effect.fn("setupCmd")(function* (name, apiUrl) {
46063
46091
  const a = approved.data;
46064
46092
  console.log(`
46065
46093
  ✅ Device paired. ID: ${a.device_id}`);
46066
- yield* config2.save({ deviceId: a.device_id, authToken: a.token, dispatchSecret: a.dispatch_secret, apiUrl });
46094
+ yield* config2.save({
46095
+ deviceId: a.device_id,
46096
+ authToken: a.token,
46097
+ dispatchSecret: a.dispatch_secret,
46098
+ sessionToken: a.session ?? undefined,
46099
+ apiUrl
46100
+ });
46101
+ if (!a.session) {
46102
+ console.log(" (no device session issued — native clients will ask you to pair again)");
46103
+ }
46067
46104
  yield* api2.setAuthToken(a.token);
46068
46105
  const workspaceId = a.workspace_id || undefined;
46069
46106
  if (workspaceId) {
@@ -46106,7 +46143,7 @@ import { existsSync as existsSync9, readFileSync as readFileSync9, unlinkSync as
46106
46143
  init_paths();
46107
46144
  import { closeSync, existsSync as existsSync8, mkdirSync as mkdirSync7, openSync, readFileSync as readFileSync8, unlinkSync as unlinkSync4, writeSync } from "fs";
46108
46145
  import { dirname as dirname8 } from "path";
46109
- var DEFAULT_DAEMON_PORT = 47832;
46146
+ var DEFAULT_DAEMON_PORT2 = DAEMON_PORT;
46110
46147
  var isAlive = (pid) => {
46111
46148
  if (!Number.isFinite(pid) || pid <= 0)
46112
46149
  return false;
@@ -46242,9 +46279,9 @@ var killStaleDaemons = (pidPath = PID_PATH, portPath = PORT_PATH) => {
46242
46279
  const port = (() => {
46243
46280
  try {
46244
46281
  const p = Number(readFileSync8(portPath, "utf8").trim());
46245
- return Number.isFinite(p) && p > 0 ? p : DEFAULT_DAEMON_PORT;
46282
+ return Number.isFinite(p) && p > 0 ? p : DEFAULT_DAEMON_PORT2;
46246
46283
  } catch {
46247
- return DEFAULT_DAEMON_PORT;
46284
+ return DEFAULT_DAEMON_PORT2;
46248
46285
  }
46249
46286
  })();
46250
46287
  const candidates = new Set;
@@ -46419,7 +46456,7 @@ init_detect();
46419
46456
  init_run_task();
46420
46457
  import { Database as Database3 } from "bun:sqlite";
46421
46458
  import { existsSync as existsSync16, mkdirSync as mkdirSync13, writeFileSync as writeFileSync11, unlinkSync as unlinkSync7 } from "fs";
46422
- import { homedir as homedir4 } from "os";
46459
+ import { homedir } from "os";
46423
46460
  import { join as join17 } from "path";
46424
46461
  init_adapter_pidfile();
46425
46462
 
@@ -46461,7 +46498,7 @@ function projectRun(row) {
46461
46498
  if (inline) {
46462
46499
  branch = str(p.base_branch);
46463
46500
  } else if (baseDir && slug) {
46464
- workingDir = join13(baseDir, ".multi", "worktrees", slug);
46501
+ workingDir = join13(baseDir, ".dayline", "worktrees", slug);
46465
46502
  branch = `multi/${slug}`;
46466
46503
  } else if (slug) {
46467
46504
  branch = `multi/${slug}`;
@@ -46573,6 +46610,7 @@ function buildProjectTree(args2) {
46573
46610
  }
46574
46611
 
46575
46612
  // src/_impl/daemon-main.ts
46613
+ init_paths();
46576
46614
  init_errors();
46577
46615
 
46578
46616
  // src/_impl/funnel.ts
@@ -46673,12 +46711,116 @@ function parseChatMessageBody(raw) {
46673
46711
  return { ok: true, value: { chat_id: chatId, text } };
46674
46712
  }
46675
46713
 
46714
+ // src/_impl/api-proxy.ts
46715
+ //! The daemon's forwarder to the worker API.
46716
+ //!
46717
+ //! Native clients (the desktop app) never reach the worker themselves: every
46718
+ //! call they make rides `/api/**` on the local daemon, so the only host the
46719
+ //! app connects to is 127.0.0.1 and exactly one place — here — decides what
46720
+ //! leaves the machine. Split out of daemon-main so the allowlist is readable
46721
+ //! on its own and testable without standing up a server.
46722
+ var API_PROXY_ROUTES = [
46723
+ { method: "GET", path: "/api/auth/me" },
46724
+ { method: "GET", path: "/api/workspaces/:ws/agents" },
46725
+ { method: "GET", path: "/api/workspaces/:ws/devices" },
46726
+ { method: "GET", path: "/api/workspaces/:ws/skills" },
46727
+ { method: "GET", path: "/api/workspaces/:ws/projects" },
46728
+ { method: "GET", path: "/api/workspaces/:ws/projects/:project/chats" },
46729
+ { method: "POST", path: "/api/workspaces/:ws/projects/:project/chats" },
46730
+ { method: "GET", path: "/api/workspaces/:ws/chats/:chat" },
46731
+ { method: "PATCH", path: "/api/workspaces/:ws/chats/:chat" },
46732
+ { method: "DELETE", path: "/api/workspaces/:ws/chats/:chat" },
46733
+ { method: "GET", path: "/api/workspaces/:ws/chats/:chat/snapshot" },
46734
+ { method: "POST", path: "/api/workspaces/:ws/agent/chats/query" },
46735
+ { method: "GET", path: "/api/workspaces/:ws/projects/:project/issues" },
46736
+ { method: "POST", path: "/api/workspaces/:ws/projects/:project/issues" },
46737
+ { method: "GET", path: "/api/workspaces/:ws/projects/:project/issues/:issue" },
46738
+ { method: "PATCH", path: "/api/workspaces/:ws/projects/:project/issues/:issue" },
46739
+ { method: "DELETE", path: "/api/workspaces/:ws/projects/:project/issues/:issue" },
46740
+ { method: "POST", path: "/api/workspaces/:ws/projects/:project/issues/:issue/complete" },
46741
+ { method: "POST", path: "/api/workspaces/:ws/projects/:project/issues/:issue/fail" },
46742
+ { method: "POST", path: "/api/workspaces/:ws/projects/:project/issues/:issue/stop" },
46743
+ { method: "GET", path: "/api/workspaces/:ws/projects/:project/issues/:issue/dispatches" },
46744
+ { method: "GET", path: "/api/workspaces/:ws/projects/:project/issues/:issue/activity" },
46745
+ { method: "GET", path: "/api/workspaces/:ws/projects/:project/devices" },
46746
+ { method: "PATCH", path: "/api/workspaces/:ws/projects/:project/devices/:device" },
46747
+ { method: "POST", path: "/api/workspaces/:ws/projects/:project/devices/:device/prepare-working-dir" },
46748
+ { method: "POST", path: "/api/workspaces/:ws/projects/:project/devices/:device/worktree" },
46749
+ { method: "GET", path: "/api/devices/:device/fs/*" }
46750
+ ];
46751
+ var API_PROXY_MATCHERS = API_PROXY_ROUTES.map(({ method, path }) => ({
46752
+ method,
46753
+ re: new RegExp(`^${path.split("/").map((seg) => seg.startsWith(":") ? "[^/]+" : seg === "*" ? ".+" : seg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")).join("/")}$`)
46754
+ }));
46755
+ function apiProxyAllows(method, pathname) {
46756
+ return API_PROXY_MATCHERS.some((r) => r.method === method && r.re.test(pathname));
46757
+ }
46758
+ var HOP_BY_HOP = new Set([
46759
+ "host",
46760
+ "connection",
46761
+ "keep-alive",
46762
+ "proxy-authenticate",
46763
+ "proxy-authorization",
46764
+ "te",
46765
+ "trailer",
46766
+ "transfer-encoding",
46767
+ "upgrade",
46768
+ "content-length",
46769
+ "authorization",
46770
+ "origin",
46771
+ "referer",
46772
+ "accept-encoding"
46773
+ ]);
46774
+ function makeApiProxy(apiUrl, session) {
46775
+ return async function proxyToApi(req, url2) {
46776
+ const userSession = session();
46777
+ if (!userSession) {
46778
+ return Response.json({
46779
+ ok: false,
46780
+ code: "no_device_session",
46781
+ message: "this device has no user session — re-pair it with `dayline connect`"
46782
+ }, { status: 401 });
46783
+ }
46784
+ const target = new URL(`${apiUrl.replace(/\/+$/, "")}${url2.pathname}`);
46785
+ target.search = url2.search;
46786
+ target.searchParams.delete("token");
46787
+ const headers = new Headers;
46788
+ for (const [k, v] of req.headers) {
46789
+ if (!HOP_BY_HOP.has(k.toLowerCase()))
46790
+ headers.set(k, v);
46791
+ }
46792
+ headers.set("authorization", `Bearer ${userSession}`);
46793
+ const method = req.method.toUpperCase();
46794
+ const body = method === "GET" || method === "HEAD" ? undefined : await req.arrayBuffer();
46795
+ let upstream;
46796
+ try {
46797
+ upstream = await fetch(target.toString(), {
46798
+ method,
46799
+ headers,
46800
+ body,
46801
+ redirect: "manual",
46802
+ signal: AbortSignal.timeout(60000)
46803
+ });
46804
+ } catch (e) {
46805
+ return Response.json({ ok: false, code: "upstream_unreachable", message: String(e?.message || e) }, { status: 502 });
46806
+ }
46807
+ const bytes = await upstream.arrayBuffer();
46808
+ const out = new Headers;
46809
+ for (const name of ["content-type", "cache-control", "etag", "location"]) {
46810
+ const v = upstream.headers.get(name);
46811
+ if (v)
46812
+ out.set(name, v);
46813
+ }
46814
+ return new Response(bytes, { status: upstream.status, headers: out });
46815
+ };
46816
+ }
46817
+
46676
46818
  // src/_impl/daemon-main.ts
46677
46819
  init_lib();
46678
46820
  // package.json
46679
46821
  var package_default2 = {
46680
46822
  name: "@shipers-dev/dayline",
46681
- version: "0.95.1",
46823
+ version: "0.99.1",
46682
46824
  type: "module",
46683
46825
  bin: {
46684
46826
  dayline: "./dist/index.js"
@@ -46687,7 +46829,7 @@ var package_default2 = {
46687
46829
  "dist"
46688
46830
  ],
46689
46831
  scripts: {
46690
- dev: "MULTI_HOME=${MULTI_HOME:-$HOME/.multi-dev} MULTI_API=${MULTI_API:-http://127.0.0.1:8787} bun run src/index.ts connect",
46832
+ dev: "DAYLINE_HOME=${DAYLINE_HOME:-$HOME/.dayline-dev} MULTI_API=${MULTI_API:-http://127.0.0.1:8787} bun run src/index.ts connect",
46691
46833
  build: "bun build src/index.ts --outdir=dist --target=node --sourcemap=none --external loro-crdt",
46692
46834
  test: "bun test",
46693
46835
  prepublishOnly: "bun run build",
@@ -46725,7 +46867,7 @@ function findBunBinary() {
46725
46867
  if (fromWhich)
46726
46868
  return fromWhich;
46727
46869
  const candidates = [
46728
- join17(homedir4(), ".bun", "bin", "bun"),
46870
+ join17(homedir(), ".bun", "bin", "bun"),
46729
46871
  "/opt/homebrew/bin/bun",
46730
46872
  "/usr/local/bin/bun",
46731
46873
  "/home/linuxbrew/.linuxbrew/bin/bun"
@@ -46737,24 +46879,17 @@ function findBunBinary() {
46737
46879
  }
46738
46880
  return null;
46739
46881
  }
46740
- var MULTI_DIR5 = join17(homedir4(), ".multi");
46741
- var PID_PATH2 = join17(MULTI_DIR5, "agent.pid");
46742
- var PORT_PATH2 = join17(MULTI_DIR5, "agent.port");
46743
- var STOP_PATH2 = join17(MULTI_DIR5, "stop.flag");
46744
- var DAEMON_PORT = 47832;
46745
- var TASKS_DB_PATH3 = join17(MULTI_DIR5, "tasks.db");
46746
- var LOCAL_SERVER_DIR = process.env.MULTI_HOME || join17(homedir4(), ".multi");
46747
- var LOCAL_SERVER_PATH = join17(LOCAL_SERVER_DIR, "local-server.json");
46882
+ var LOCAL_SERVER_PATH = join17(DAYLINE_DIR, "local-server.json");
46748
46883
  function ensureDirs2() {
46749
- if (!existsSync16(MULTI_DIR5))
46750
- mkdirSync13(MULTI_DIR5, { recursive: true });
46751
- const logs = join17(MULTI_DIR5, "logs");
46884
+ if (!existsSync16(DAYLINE_DIR))
46885
+ mkdirSync13(DAYLINE_DIR, { recursive: true });
46886
+ const logs = join17(DAYLINE_DIR, "logs");
46752
46887
  if (!existsSync16(logs))
46753
46888
  mkdirSync13(logs, { recursive: true });
46754
46889
  }
46755
46890
  function openTasksDb() {
46756
46891
  ensureDirs2();
46757
- const db2 = new Database3(TASKS_DB_PATH3);
46892
+ const db2 = new Database3(TASKS_DB_PATH);
46758
46893
  const existing = db2.query("PRAGMA table_info(tasks)").all();
46759
46894
  if (existing.length) {
46760
46895
  const have = new Set(existing.map((c) => c.name));
@@ -46919,8 +47054,8 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
46919
47054
  if (cfg.authToken)
46920
47055
  setAuthToken(cfg.authToken);
46921
47056
  ensureDirs2();
46922
- if (existsSync16(STOP_PATH2))
46923
- unlinkSync7(STOP_PATH2);
47057
+ if (existsSync16(STOP_PATH))
47058
+ unlinkSync7(STOP_PATH);
46924
47059
  const reaped = reapStaleAdapters((m) => log3(m));
46925
47060
  if (reaped > 0)
46926
47061
  log3(`reaped ${reaped} stale adapter${reaped === 1 ? "" : "s"}`);
@@ -46943,7 +47078,7 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
46943
47078
  let projectTreeCache = null;
46944
47079
  const corsHeaders = (origin) => ({
46945
47080
  "Access-Control-Allow-Origin": origin || "*",
46946
- "Access-Control-Allow-Methods": "GET, POST, OPTIONS",
47081
+ "Access-Control-Allow-Methods": "GET, POST, PATCH, DELETE, OPTIONS",
46947
47082
  "Access-Control-Allow-Headers": "Authorization, Content-Type",
46948
47083
  "Access-Control-Max-Age": "600",
46949
47084
  Vary: "Origin"
@@ -46959,6 +47094,35 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
46959
47094
  }
46960
47095
  return null;
46961
47096
  };
47097
+ let sessionToken = cfg.sessionToken ?? null;
47098
+ const proxyToApi = makeApiProxy(apiUrl, () => sessionToken);
47099
+ const sessionRoute = async (req) => {
47100
+ if (req.method !== "GET" && req.method !== "DELETE") {
47101
+ return Response.json({ error: "method not allowed" }, { status: 405 });
47102
+ }
47103
+ if (req.method === "DELETE") {
47104
+ sessionToken = null;
47105
+ try {
47106
+ const current = JSON.parse(await Bun.file(CONFIG_PATH).text());
47107
+ delete current.sessionToken;
47108
+ await Bun.write(CONFIG_PATH, JSON.stringify(current, null, 2));
47109
+ } catch (e) {
47110
+ log3(`session: could not persist sign-out: ${e}`);
47111
+ }
47112
+ return Response.json({ signed_in: false });
47113
+ }
47114
+ if (!sessionToken) {
47115
+ return Response.json({ signed_in: false, reason: "no_device_session" });
47116
+ }
47117
+ const me = await proxyToApi(new Request(`http://127.0.0.1/api/auth/me`, { headers: req.headers }), new URL("http://127.0.0.1/api/auth/me"));
47118
+ if (me.status === 401) {
47119
+ return Response.json({ signed_in: false, reason: "session_expired" });
47120
+ }
47121
+ if (!me.ok) {
47122
+ return Response.json({ signed_in: false, reason: "api_unreachable" }, { status: 502 });
47123
+ }
47124
+ return Response.json({ signed_in: true, me: await me.json() });
47125
+ };
46962
47126
  const withCors = (res, origin) => {
46963
47127
  for (const [k, v] of Object.entries(corsHeaders(origin))) {
46964
47128
  res.headers.set(k, v);
@@ -46971,7 +47135,7 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
46971
47135
  probe.stop();
46972
47136
  },
46973
47137
  catch: () => new DaemonError({
46974
- message: `daemon port ${port} is already in use — stop whatever is bound to 127.0.0.1:${port} (if a stale daemon, remove ~/.multi/agent.pid)`
47138
+ message: `daemon port ${port} is already in use — stop whatever is bound to 127.0.0.1:${port} (if a stale daemon, remove ~/.dayline/agent.pid)`
46975
47139
  })
46976
47140
  });
46977
47141
  const server = Bun.serve({
@@ -47005,6 +47169,21 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
47005
47169
  const route = () => {
47006
47170
  if (url2.pathname === "/health")
47007
47171
  return Response.json({ ok: true, device_id: cfg.deviceId, cli_version: CLI_VERSION });
47172
+ if (url2.pathname === "/session") {
47173
+ const denied = requireLocalAuth(req, url2, { allowQueryToken: true });
47174
+ if (denied)
47175
+ return denied;
47176
+ return sessionRoute(req);
47177
+ }
47178
+ if (url2.pathname === "/api" || url2.pathname.startsWith("/api/")) {
47179
+ const denied = requireLocalAuth(req, url2, { allowQueryToken: true });
47180
+ if (denied)
47181
+ return denied;
47182
+ if (!apiProxyAllows(req.method.toUpperCase(), url2.pathname)) {
47183
+ return Response.json({ ok: false, code: "route_not_proxied", message: `${req.method} ${url2.pathname} is not a proxied API route` }, { status: 404 });
47184
+ }
47185
+ return proxyToApi(req, url2);
47186
+ }
47008
47187
  if (url2.pathname === "/files" && req.method === "GET") {
47009
47188
  if (req.headers.get("authorization") !== expectedAuth)
47010
47189
  return new Response("unauthorized", { status: 401 });
@@ -47946,10 +48125,10 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
47946
48125
  });
47947
48126
  log3(`Local server: http://127.0.0.1:${port}`);
47948
48127
  try {
47949
- writeFileSync11(PORT_PATH2, String(port));
48128
+ writeFileSync11(PORT_PATH, String(port));
47950
48129
  } catch {}
47951
48130
  try {
47952
- writeFileSync11(PID_PATH2, String(process.pid));
48131
+ writeFileSync11(PID_PATH, String(process.pid));
47953
48132
  } catch {}
47954
48133
  let funnelUrl = yield* exports_Effect.try({
47955
48134
  try: () => ensureFunnel(port),
@@ -47964,7 +48143,7 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
47964
48143
  yield* exports_Effect.forkIn(daemonScope)(exports_Effect.gen(function* () {
47965
48144
  while (true) {
47966
48145
  yield* exports_Effect.sleep(exports_Duration.seconds(150));
47967
- if (existsSync16(STOP_PATH2)) {
48146
+ if (existsSync16(STOP_PATH)) {
47968
48147
  yield* exports_Deferred.succeed(stopDeferred, "stop flag");
47969
48148
  return;
47970
48149
  }
@@ -47977,8 +48156,8 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
47977
48156
  }
47978
48157
  }).pipe(exports_Effect.catchAllCause((c) => exports_Effect.sync(() => log3(`funnel liveness crash: ${exports_Cause.pretty(c)}`)))));
47979
48158
  try {
47980
- if (!existsSync16(LOCAL_SERVER_DIR))
47981
- mkdirSync13(LOCAL_SERVER_DIR, { recursive: true });
48159
+ if (!existsSync16(DAYLINE_DIR))
48160
+ mkdirSync13(DAYLINE_DIR, { recursive: true });
47982
48161
  writeFileSync11(LOCAL_SERVER_PATH, JSON.stringify({
47983
48162
  url: `http://127.0.0.1:${port}`,
47984
48163
  port,
@@ -48008,7 +48187,7 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
48008
48187
  yield* exports_Effect.forkIn(daemonScope)(exports_Effect.gen(function* () {
48009
48188
  while (true) {
48010
48189
  yield* exports_Effect.sleep(exports_Duration.seconds(5));
48011
- if (existsSync16(STOP_PATH2)) {
48190
+ if (existsSync16(STOP_PATH)) {
48012
48191
  yield* exports_Deferred.succeed(stopDeferred, "stop flag");
48013
48192
  return;
48014
48193
  }
@@ -48051,12 +48230,12 @@ var daemonProgram = ({ cfg, apiUrl }) => exports_Effect.gen(function* () {
48051
48230
  log3(`adapter shutdown sweep failed: ${String(e)}`);
48052
48231
  }
48053
48232
  yield* exports_Scope.close(daemonScope, exports_Exit.void).pipe(exports_Effect.catchAll(() => exports_Effect.void));
48054
- if (existsSync16(PID_PATH2))
48055
- unlinkSync7(PID_PATH2);
48056
- if (existsSync16(STOP_PATH2))
48057
- unlinkSync7(STOP_PATH2);
48058
- if (existsSync16(PORT_PATH2))
48059
- unlinkSync7(PORT_PATH2);
48233
+ if (existsSync16(PID_PATH))
48234
+ unlinkSync7(PID_PATH);
48235
+ if (existsSync16(STOP_PATH))
48236
+ unlinkSync7(STOP_PATH);
48237
+ if (existsSync16(PORT_PATH))
48238
+ unlinkSync7(PORT_PATH);
48060
48239
  if (existsSync16(LOCAL_SERVER_PATH))
48061
48240
  unlinkSync7(LOCAL_SERVER_PATH);
48062
48241
  db2.close();
@@ -48076,14 +48255,14 @@ init_outbox();
48076
48255
 
48077
48256
  // src/_impl/pair-flow.ts
48078
48257
  import { existsSync as existsSync17, mkdirSync as mkdirSync14, writeFileSync as writeFileSync12 } from "fs";
48079
- import { homedir as homedir5 } from "os";
48080
48258
  import { join as join18 } from "path";
48081
- var LOCAL_SERVER_DIR2 = process.env.MULTI_HOME || join18(homedir5(), ".multi");
48082
- var LOCAL_SERVER_PATH2 = join18(LOCAL_SERVER_DIR2, "local-server.json");
48259
+ init_paths();
48260
+ var LOCAL_SERVER_DIR = daylineDir();
48261
+ var LOCAL_SERVER_PATH2 = join18(LOCAL_SERVER_DIR, "local-server.json");
48083
48262
  function writePairingInfo(payload) {
48084
48263
  try {
48085
- if (!existsSync17(LOCAL_SERVER_DIR2))
48086
- mkdirSync14(LOCAL_SERVER_DIR2, { recursive: true });
48264
+ if (!existsSync17(LOCAL_SERVER_DIR))
48265
+ mkdirSync14(LOCAL_SERVER_DIR, { recursive: true });
48087
48266
  writeFileSync12(LOCAL_SERVER_PATH2, JSON.stringify(payload, null, 2));
48088
48267
  } catch {}
48089
48268
  }
@@ -48135,7 +48314,8 @@ async function awaitPairing(apiUrl, deviceName, opts = {}) {
48135
48314
  device_id: j.device_id,
48136
48315
  token: j.token,
48137
48316
  dispatch_secret: j.dispatch_secret ?? null,
48138
- workspace_id: j.workspace_id ?? null
48317
+ workspace_id: j.workspace_id ?? null,
48318
+ session: j.session ?? null
48139
48319
  };
48140
48320
  }
48141
48321
  }
@@ -48154,7 +48334,7 @@ var connectCmd = exports_Effect.fn("connectCmd")(function* () {
48154
48334
  const api2 = yield* Api2;
48155
48335
  yield* config2.ensureDirs;
48156
48336
  let cfg = yield* config2.load;
48157
- if (!cfg.deviceId || !cfg.authToken) {
48337
+ if (!cfg.deviceId || !cfg.authToken || !cfg.sessionToken) {
48158
48338
  const apiUrl = cfg.apiUrl || process.env.MULTI_API || process.env.MULTI_API_URL || "https://api.dayline.ai";
48159
48339
  const name = deviceNameFromEnv();
48160
48340
  const detected = yield* exports_Effect.promise(() => detectAgents());
@@ -48171,10 +48351,14 @@ var connectCmd = exports_Effect.fn("connectCmd")(function* () {
48171
48351
  deviceId: bundle.device_id,
48172
48352
  authToken: bundle.token,
48173
48353
  dispatchSecret: bundle.dispatch_secret ?? undefined,
48174
- workspaceId: bundle.workspace_id ?? undefined
48354
+ workspaceId: bundle.workspace_id ?? undefined,
48355
+ sessionToken: bundle.session ?? undefined
48175
48356
  });
48176
48357
  cfg = yield* config2.load;
48177
48358
  yield* logger.log(`connect: paired device=${cfg.deviceId} workspace=${cfg.workspaceId}`);
48359
+ if (!cfg.sessionToken) {
48360
+ yield* logger.log("connect: this API did not issue a device session — desktop clients will stay signed out");
48361
+ }
48178
48362
  }
48179
48363
  if (!cfg.dispatchSecret) {
48180
48364
  return yield* exports_Effect.fail(new UsageError({ message: "Missing dispatch secret. Re-pair via 'dayline setup'." }));
@@ -48214,14 +48398,14 @@ ${err?.stack ?? ""}`);
48214
48398
  // src/commands/service.ts
48215
48399
  init_esm();
48216
48400
  import { existsSync as existsSync18, readFileSync as readFileSync13 } from "fs";
48217
- import { homedir as homedir6, platform, tmpdir } from "os";
48401
+ import { homedir as homedir2, platform, tmpdir } from "os";
48218
48402
  import { join as join19 } from "path";
48219
48403
  init_errors();
48220
48404
  init_paths();
48221
48405
  var LABEL = "dev.shipers.multi.daemon";
48222
- var HOME5 = homedir6();
48223
- var PLIST_PATH = join19(HOME5, "Library", "LaunchAgents", `${LABEL}.plist`);
48224
- var SYSTEMD_UNIT_PATH = join19(HOME5, ".config", "systemd", "user", "multi-daemon.service");
48406
+ var HOME4 = homedir2();
48407
+ var PLIST_PATH = join19(HOME4, "Library", "LaunchAgents", `${LABEL}.plist`);
48408
+ var SYSTEMD_UNIT_PATH = join19(HOME4, ".config", "systemd", "user", "multi-daemon.service");
48225
48409
  var isMac = () => platform() === "darwin";
48226
48410
  var isLinux = () => platform() === "linux";
48227
48411
  var isRunningPid = (pid) => {
@@ -48259,7 +48443,7 @@ function pickStableBinary(candidates, exists4) {
48259
48443
  return null;
48260
48444
  }
48261
48445
  function stableCandidates(fromWhich) {
48262
- const home = homedir6();
48446
+ const home = homedir2();
48263
48447
  return [
48264
48448
  fromWhich,
48265
48449
  join19(home, ".bun/bin/dayline"),
@@ -48309,7 +48493,7 @@ var buildPlist = (binary, env) => {
48309
48493
  const envEntries = Object.entries(env).map(([k, v]) => ` <key>${k}</key>
48310
48494
  <string>${escapeXml(v)}</string>`).join(`
48311
48495
  `);
48312
- const logDir = join19(MULTI_DIR, "logs");
48496
+ const logDir = join19(DAYLINE_DIR, "logs");
48313
48497
  return `<?xml version="1.0" encoding="UTF-8"?>
48314
48498
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
48315
48499
  <plist version="1.0">
@@ -48326,7 +48510,7 @@ var buildPlist = (binary, env) => {
48326
48510
  <key>KeepAlive</key>
48327
48511
  <true/>
48328
48512
  <key>WorkingDirectory</key>
48329
- <string>${escapeXml(HOME5)}</string>
48513
+ <string>${escapeXml(HOME4)}</string>
48330
48514
  <key>StandardOutPath</key>
48331
48515
  <string>${escapeXml(join19(logDir, "launchd.out.log"))}</string>
48332
48516
  <key>StandardErrorPath</key>
@@ -48354,7 +48538,7 @@ Type=simple
48354
48538
  ExecStart=${binary} connect
48355
48539
  Restart=always
48356
48540
  RestartSec=3
48357
- WorkingDirectory=${HOME5}
48541
+ WorkingDirectory=${HOME4}
48358
48542
  ${envLines}
48359
48543
 
48360
48544
  [Install]
@@ -48388,7 +48572,7 @@ var installMac = exports_Effect.fn("service.installMac")(function* (binary) {
48388
48572
  const fs3 = yield* FileSystem;
48389
48573
  const env = collectServiceEnv();
48390
48574
  const plist = buildPlist(binary, env);
48391
- yield* fs3.mkdirp(join19(MULTI_DIR, "logs"));
48575
+ yield* fs3.mkdirp(join19(DAYLINE_DIR, "logs"));
48392
48576
  yield* fs3.writeText(PLIST_PATH, plist);
48393
48577
  yield* run6("launchctl", ["unload", PLIST_PATH]).pipe(exports_Effect.ignore);
48394
48578
  yield* run6("launchctl", ["load", "-w", PLIST_PATH]);
@@ -48399,7 +48583,7 @@ var installLinux = exports_Effect.fn("service.installLinux")(function* (binary)
48399
48583
  const fs3 = yield* FileSystem;
48400
48584
  const env = collectServiceEnv();
48401
48585
  const unit = buildSystemdUnit(binary, env);
48402
- yield* fs3.mkdirp(join19(MULTI_DIR, "logs"));
48586
+ yield* fs3.mkdirp(join19(DAYLINE_DIR, "logs"));
48403
48587
  yield* fs3.writeText(SYSTEMD_UNIT_PATH, unit);
48404
48588
  yield* run6("systemctl", ["--user", "daemon-reload"]);
48405
48589
  yield* run6("systemctl", ["--user", "enable", "--now", "multi-daemon.service"]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shipers-dev/dayline",
3
- "version": "0.95.1",
3
+ "version": "0.99.1",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "dayline": "./dist/index.js"
@@ -9,7 +9,7 @@
9
9
  "dist"
10
10
  ],
11
11
  "scripts": {
12
- "dev": "MULTI_HOME=${MULTI_HOME:-$HOME/.multi-dev} MULTI_API=${MULTI_API:-http://127.0.0.1:8787} bun run src/index.ts connect",
12
+ "dev": "DAYLINE_HOME=${DAYLINE_HOME:-$HOME/.dayline-dev} MULTI_API=${MULTI_API:-http://127.0.0.1:8787} bun run src/index.ts connect",
13
13
  "build": "bun build src/index.ts --outdir=dist --target=node --sourcemap=none --external loro-crdt",
14
14
  "test": "bun test",
15
15
  "prepublishOnly": "bun run build",