@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.
- package/dist/index.js +297 -113
- 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
|
-
|
|
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
|
-
|
|
18340
|
-
CONFIG_PATH = join4(
|
|
18341
|
-
PID_PATH = join4(
|
|
18342
|
-
PORT_PATH = join4(
|
|
18343
|
-
LOG_PATH = join4(
|
|
18344
|
-
SKILLS_DIR = join4(
|
|
18345
|
-
STOP_PATH = join4(
|
|
18346
|
-
TASKS_DB_PATH = join4(
|
|
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, ".
|
|
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, ".
|
|
18643
|
+
ensureGitignoreEntry(workingDir, ".dayline/");
|
|
18624
18644
|
const slug = worktreeSlug(opts?.worktreeName ?? issueKey);
|
|
18625
18645
|
const branch = `multi/${slug}`;
|
|
18626
|
-
const wtDir = join5(workingDir, ".
|
|
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 === ".
|
|
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, ".
|
|
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
|
-
|
|
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
|
|
38668
|
+
var LOG_PATH2;
|
|
38647
38669
|
var init_acpx_runner = __esm(() => {
|
|
38648
38670
|
init_adapter_pidfile();
|
|
38649
|
-
|
|
38650
|
-
LOG_PATH2 = join9(
|
|
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, ".
|
|
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(
|
|
39374
|
-
mkdirSync8(
|
|
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
|
|
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
|
-
|
|
39535
|
-
|
|
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 [
|
|
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(
|
|
39822
|
-
const inDir = join12(baseDir, ".
|
|
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(
|
|
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 .
|
|
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(
|
|
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(
|
|
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
|
|
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
|
-
|
|
41557
|
-
|
|
41558
|
-
|
|
41559
|
-
|
|
41560
|
-
|
|
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(
|
|
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(
|
|
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(".
|
|
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.
|
|
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: "
|
|
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(
|
|
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(
|
|
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
|
|
45577
|
-
var
|
|
45578
|
-
var
|
|
45579
|
-
var STATE_PATH = join6(
|
|
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 = ".
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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"
|
|
45997
|
-
return u.
|
|
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({
|
|
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
|
|
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 :
|
|
46282
|
+
return Number.isFinite(p) && p > 0 ? p : DEFAULT_DAEMON_PORT2;
|
|
46246
46283
|
} catch {
|
|
46247
|
-
return
|
|
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
|
|
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, ".
|
|
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.
|
|
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: "
|
|
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(
|
|
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
|
|
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(
|
|
46750
|
-
mkdirSync13(
|
|
46751
|
-
const logs = join17(
|
|
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(
|
|
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(
|
|
46923
|
-
unlinkSync7(
|
|
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 ~/.
|
|
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(
|
|
48128
|
+
writeFileSync11(PORT_PATH, String(port));
|
|
47950
48129
|
} catch {}
|
|
47951
48130
|
try {
|
|
47952
|
-
writeFileSync11(
|
|
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(
|
|
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(
|
|
47981
|
-
mkdirSync13(
|
|
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(
|
|
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(
|
|
48055
|
-
unlinkSync7(
|
|
48056
|
-
if (existsSync16(
|
|
48057
|
-
unlinkSync7(
|
|
48058
|
-
if (existsSync16(
|
|
48059
|
-
unlinkSync7(
|
|
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
|
-
|
|
48082
|
-
var
|
|
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(
|
|
48086
|
-
mkdirSync14(
|
|
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
|
|
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
|
|
48223
|
-
var PLIST_PATH = join19(
|
|
48224
|
-
var SYSTEMD_UNIT_PATH = join19(
|
|
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 =
|
|
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(
|
|
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(
|
|
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=${
|
|
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(
|
|
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(
|
|
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.
|
|
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": "
|
|
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",
|