@claudexor/daemon 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,322 @@
1
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
2
+ import { dirname, join } from "node:path";
3
+ import { SCHEMA_VERSION, Session as SessionSchema, Thread as ThreadSchema, ThreadTurn as ThreadTurnSchema, } from "@claudexor/schema";
4
+ import { newId, nowIso, redactSecrets } from "@claudexor/util";
5
+ /**
6
+ * Thread routing invariant: a sticky primary harness must be a member of a
7
+ * NON-EMPTY eligible pool (an empty pool = engine auto-pool, so it constrains
8
+ * nothing). Returns the primary, or null when it falls outside the pool — so a
9
+ * thread is never stored claiming a primary the engine would drop. Applied at
10
+ * both create and update (the only writers of these two fields).
11
+ */
12
+ function coercePrimaryToPool(primary, pool) {
13
+ if (primary && pool.length > 0 && !pool.includes(primary))
14
+ return null;
15
+ return primary;
16
+ }
17
+ /**
18
+ * Durable thread/session registry (chat/session-first SSOT). The Thread is
19
+ * the Claudexor-owned conversation; Sessions are re-hostable pointers to each
20
+ * harness's native CLI session. Persisted as one JSON file with atomic writes
21
+ * (temp + rename), mirroring the daemon job registry's durability contract.
22
+ */
23
+ export class ThreadStore {
24
+ path;
25
+ state = { threads: [], sessions: [], turns: [] };
26
+ constructor(path) {
27
+ this.path = path;
28
+ this.load();
29
+ }
30
+ load() {
31
+ if (!existsSync(this.path))
32
+ return;
33
+ let raw;
34
+ try {
35
+ raw = JSON.parse(readFileSync(this.path, "utf8"));
36
+ }
37
+ catch {
38
+ // A corrupt store must not brick the daemon; threads are recoverable
39
+ // from run artifacts, so start empty rather than crash-looping.
40
+ this.state = { threads: [], sessions: [], turns: [] };
41
+ return;
42
+ }
43
+ // Per-record leniency: ONE invalid record must not wipe the whole history.
44
+ // A record stamped by a different schema_version is forward-migrated first
45
+ // (additive fields are covered by zod defaults); only a genuinely
46
+ // unparseable record is dropped — and then the original file is backed up
47
+ // and the loss is logged, so a schema change never SILENTLY erases history.
48
+ let dropped = 0;
49
+ const keep = (items, schema) => (items ?? []).flatMap((item) => {
50
+ let parsed = schema.safeParse(item);
51
+ if (!parsed.success && item && typeof item === "object") {
52
+ // Forward-migrate: bump schema_version AND coerce retired enum values
53
+ // (Thread.state "blocked" -> "active", ThreadTurnKind "orchestrate"
54
+ // -> "followup", SessionResumeKind "resume_latest"/"rehost" -> the
55
+ // values the daemon actually stamps) so an old record is migrated,
56
+ // not dropped.
57
+ const rec = item;
58
+ const migrated = { ...rec, schema_version: SCHEMA_VERSION };
59
+ if (migrated["state"] === "blocked")
60
+ migrated["state"] = "active";
61
+ if (migrated["kind"] === "orchestrate")
62
+ migrated["kind"] = "followup";
63
+ if (migrated["resume_kind"] === "resume_latest")
64
+ migrated["resume_kind"] = "resume_by_id";
65
+ if (migrated["resume_kind"] === "rehost") {
66
+ // "rehost" meant "continued on a DIFFERENT harness — native resume
67
+ // impossible". resumeMap keys on state==="live" + native id, so the
68
+ // state must flip to "rebound" too or a stale live rehost record
69
+ // would still resume natively despite its own retirement semantics.
70
+ migrated["resume_kind"] = "none";
71
+ migrated["state"] = "rebound";
72
+ }
73
+ parsed = schema.safeParse(migrated);
74
+ }
75
+ if (parsed.success && parsed.data !== undefined)
76
+ return [parsed.data];
77
+ dropped++;
78
+ return [];
79
+ });
80
+ this.state = {
81
+ threads: keep(raw.threads, ThreadSchema),
82
+ sessions: keep(raw.sessions, SessionSchema),
83
+ turns: keep(raw.turns, ThreadTurnSchema),
84
+ };
85
+ if (dropped > 0) {
86
+ try {
87
+ writeFileSync(`${this.path}.bak`, JSON.stringify(raw, null, 2), { mode: 0o600 });
88
+ console.error(`[claudexor] threads store: ${dropped} record(s) unparseable after migration; original backed up to ${this.path}.bak`);
89
+ }
90
+ catch {
91
+ /* best-effort backup */
92
+ }
93
+ }
94
+ }
95
+ persist() {
96
+ mkdirSync(dirname(this.path), { recursive: true, mode: 0o700 });
97
+ const tmp = join(dirname(this.path), `.threads-${process.pid}.tmp`);
98
+ writeFileSync(tmp, JSON.stringify(this.state, null, 2), { mode: 0o600 });
99
+ renameSync(tmp, this.path);
100
+ }
101
+ createThread(input) {
102
+ const now = nowIso();
103
+ // Same invariant as updateThread: a sticky primary must be a member of a
104
+ // non-empty eligible pool. Enforce it at CREATE too (the create request carries
105
+ // primary + pool independently) so a thread is never born incoherent.
106
+ const eligible = input.eligibleHarnesses ?? [];
107
+ const primary = coercePrimaryToPool(input.primaryHarness ?? null, eligible);
108
+ const thread = ThreadSchema.parse({
109
+ schema_version: SCHEMA_VERSION,
110
+ id: newId("th"),
111
+ created_at: now,
112
+ updated_at: now,
113
+ repo: input.repoRoot ? { root: input.repoRoot, base_ref: "HEAD" } : null,
114
+ title: input.title ?? null,
115
+ // Default mode follows the scope: a no-project thread can only Ask
116
+ // (read-only), so it must NOT default to agent (which would 400 on the
117
+ // first turn for lack of a project root). A project thread defaults to agent.
118
+ mode: input.mode ?? (input.repoRoot ? "agent" : "ask"),
119
+ // An isolated workspace needs a git project for its worktree; a no-project
120
+ // thread is always in_place (review #6 — never persist a doomed config).
121
+ workspace: { mode: input.repoRoot ? input.workspace ?? "in_place" : "in_place", worktree_path: null, base_sha: null },
122
+ auth_preference: input.authPreference ?? "auto",
123
+ primary_harness: primary,
124
+ eligible_harnesses: eligible,
125
+ });
126
+ this.state.threads.push(thread);
127
+ this.persist();
128
+ return thread;
129
+ }
130
+ /** Rename and/or open/close (archive) a thread. */
131
+ updateThread(id, patch) {
132
+ const thread = this.getThread(id);
133
+ if (!thread)
134
+ throw Object.assign(new Error(`no such thread: ${id}`), { status: 404 });
135
+ if (patch.title !== undefined)
136
+ thread.title = patch.title;
137
+ if (patch.state !== undefined)
138
+ thread.state = patch.state;
139
+ if (patch.primaryHarness !== undefined)
140
+ thread.primary_harness = patch.primaryHarness;
141
+ if (patch.eligibleHarnesses !== undefined)
142
+ thread.eligible_harnesses = patch.eligibleHarnesses;
143
+ // Invariant (thread.ts contract): a sticky primary must be a member of a non-empty
144
+ // eligible pool. If a PATCH leaves the primary outside the pool — e.g. the user
145
+ // removed the primary harness from the pool — clear it to null (Auto) rather than
146
+ // persist an incoherent state that the UI would show as "X answers in chat" while
147
+ // the engine silently drops X. (An empty pool = auto, so it imposes no constraint.)
148
+ thread.primary_harness = coercePrimaryToPool(thread.primary_harness, thread.eligible_harnesses);
149
+ thread.updated_at = nowIso();
150
+ this.persist();
151
+ return thread;
152
+ }
153
+ /** Persist the resolved isolated worktree path + base sha for a thread. */
154
+ setThreadWorktree(id, worktreePath, baseSha) {
155
+ const thread = this.getThread(id);
156
+ if (!thread)
157
+ return;
158
+ thread.workspace = { ...thread.workspace, worktree_path: worktreePath, base_sha: baseSha };
159
+ thread.updated_at = nowIso();
160
+ this.persist();
161
+ }
162
+ listThreads() {
163
+ return [...this.state.threads].sort((a, b) => (a.updated_at < b.updated_at ? 1 : -1));
164
+ }
165
+ getThread(id) {
166
+ return this.state.threads.find((t) => t.id === id);
167
+ }
168
+ turnsFor(threadId) {
169
+ return this.state.turns.filter((t) => t.thread_id === threadId);
170
+ }
171
+ getTurn(turnId) {
172
+ return this.state.turns.find((t) => t.id === turnId);
173
+ }
174
+ /**
175
+ * Fail-loud prologue for the daemon runner: control-api validates thread/turn
176
+ * ids at the HTTP boundary, but a direct socket caller can pass bogus ids —
177
+ * a silent unbind would orphan the run from its conversation. A typed throw
178
+ * settles the job `failed` instead. Returns the normalized ids.
179
+ */
180
+ assertKnownIds(rawThreadId, rawTurnId) {
181
+ const threadId = typeof rawThreadId === "string" && rawThreadId ? rawThreadId : undefined;
182
+ const turnId = typeof rawTurnId === "string" && rawTurnId ? rawTurnId : undefined;
183
+ if (threadId && !this.getThread(threadId)) {
184
+ throw Object.assign(new Error(`no such thread: ${threadId}`), { code: "unknown_thread" });
185
+ }
186
+ if (turnId) {
187
+ const turn = this.getTurn(turnId);
188
+ if (!turn) {
189
+ throw Object.assign(new Error(`no such turn: ${turnId}`), { code: "unknown_turn" });
190
+ }
191
+ // A turn is bound to ONE conversation: a foreign turnId would resolve
192
+ // workspace/session context from one thread while advancing another
193
+ // thread's lineage. A turn also never rides without its thread id.
194
+ if (!threadId) {
195
+ throw Object.assign(new Error(`turnId ${turnId} requires its threadId`), { code: "unbound_turn" });
196
+ }
197
+ if (turn.thread_id !== threadId) {
198
+ throw Object.assign(new Error(`turn ${turnId} belongs to thread ${turn.thread_id}, not ${threadId}`), { code: "foreign_turn" });
199
+ }
200
+ }
201
+ return { threadId, turnId };
202
+ }
203
+ sessionsForThread(threadId) {
204
+ return this.state.sessions.filter((s) => s.thread_id === threadId);
205
+ }
206
+ /** Native resume map for a thread: harnessId -> native session id (live sessions only). */
207
+ resumeMap(threadId) {
208
+ const map = {};
209
+ for (const s of this.sessionsForThread(threadId)) {
210
+ if (s.state === "live" && s.native_session_id)
211
+ map[s.harness_id] = s.native_session_id;
212
+ }
213
+ return map;
214
+ }
215
+ /**
216
+ * Create a turn BEFORE its run is enqueued (run_id is bound later via
217
+ * `bindTurnRun`). This is the single-writer entry point: the control API and
218
+ * the daemon runner both create here, so a run is recorded on its thread
219
+ * exactly once — there is no second "POST /runs with threadId silently skips
220
+ * the turn" path. `parentRunId` is captured here (head at creation time), so
221
+ * concurrent turns cannot both claim the same stale head.
222
+ */
223
+ createTurn(threadId, prompt, input = {}) {
224
+ const thread = this.getThread(threadId);
225
+ if (!thread)
226
+ throw Object.assign(new Error(`no such thread: ${threadId}`), { status: 404 });
227
+ // Count TURNS, not run_ids: run_ids is only filled at bindTurnRun (which lags
228
+ // the runner), so a second turn created before the first binds would also see
229
+ // an empty run_ids and wrongly claim "initial" (review #5).
230
+ const existingTurns = this.state.turns.filter((t) => t.thread_id === threadId).length;
231
+ const kind = input.kind ?? (existingTurns === 0 ? "initial" : "followup");
232
+ const turn = ThreadTurnSchema.parse({
233
+ id: newId("tn"),
234
+ thread_id: threadId,
235
+ run_id: null,
236
+ parent_run_id: input.parentRunId !== undefined ? input.parentRunId : thread.head_run_id,
237
+ plan_run_id: input.planRunId ?? null,
238
+ kind,
239
+ // The durable conversation store is read back into UIs: redact at the
240
+ // persist boundary exactly like jobs.json / events.jsonl do.
241
+ prompt: redactSecrets(prompt),
242
+ attachments: input.attachments ?? [],
243
+ created_at: nowIso(),
244
+ });
245
+ this.state.turns.push(turn);
246
+ // First prompt names the thread (no LLM): cheap, honest, editable via rename.
247
+ if (!thread.title)
248
+ thread.title = turn.prompt.split("\n")[0].slice(0, 60);
249
+ thread.updated_at = nowIso();
250
+ this.persist();
251
+ return turn;
252
+ }
253
+ /** Bind a started run to its turn and advance the thread head (runner-owned). */
254
+ bindTurnRun(turnId, runId) {
255
+ const turn = this.state.turns.find((t) => t.id === turnId);
256
+ if (!turn)
257
+ return;
258
+ turn.run_id = runId;
259
+ // A binding run supersedes any recorded refusal (the retry path): the
260
+ // turn is no longer an orphan, so the stale error must not linger.
261
+ turn.enqueue_error = null;
262
+ const thread = this.getThread(turn.thread_id);
263
+ if (thread) {
264
+ if (!thread.run_ids.includes(runId))
265
+ thread.run_ids.push(runId);
266
+ thread.head_run_id = runId;
267
+ thread.updated_at = nowIso();
268
+ }
269
+ this.persist();
270
+ }
271
+ /**
272
+ * Persist the reason a turn's run could NOT be enqueued/started (trust
273
+ * refusal, preflight validation, enqueue throw). Only meaningful for a
274
+ * RUNLESS turn: once a run is bound the turn's honesty lives on the run's
275
+ * own terminal artifacts, so a late failure report is ignored. `code` is
276
+ * the typed throw's machine code (e.g. trust_full_access_required) that
277
+ * surfaces key remedies on; `retryable=false` marks refusals with NO
278
+ * recorded job to replay (the enqueue itself threw) so surfaces offer
279
+ * "send a new message" instead of a doomed Retry.
280
+ */
281
+ setTurnEnqueueError(turnId, message, code = null, retryable = true) {
282
+ const turn = this.state.turns.find((t) => t.id === turnId);
283
+ if (!turn || turn.run_id)
284
+ return;
285
+ turn.enqueue_error = { message: redactSecrets(message), code, retryable, failed_at: nowIso() };
286
+ const thread = this.getThread(turn.thread_id);
287
+ if (thread)
288
+ thread.updated_at = nowIso();
289
+ this.persist();
290
+ }
291
+ /** Record/refresh the native CLI session a harness emitted for this thread. */
292
+ recordSession(threadId, harnessId, nativeSessionId, observedModel) {
293
+ const existing = this.state.sessions.find((s) => s.thread_id === threadId && s.harness_id === harnessId);
294
+ const now = nowIso();
295
+ if (existing) {
296
+ existing.native_session_id = nativeSessionId;
297
+ existing.state = "live";
298
+ existing.resume_kind = "resume_by_id";
299
+ if (observedModel)
300
+ existing.last_observed_model = observedModel;
301
+ existing.updated_at = now;
302
+ }
303
+ else {
304
+ this.state.sessions.push(SessionSchema.parse({
305
+ id: newId("se"),
306
+ thread_id: threadId,
307
+ harness_id: harnessId,
308
+ native_session_id: nativeSessionId,
309
+ last_observed_model: observedModel ?? null,
310
+ resume_kind: "resume_by_id",
311
+ state: "live",
312
+ created_at: now,
313
+ updated_at: now,
314
+ }));
315
+ }
316
+ const thread = this.getThread(threadId);
317
+ if (thread)
318
+ thread.updated_at = now;
319
+ this.persist();
320
+ }
321
+ }
322
+ //# sourceMappingURL=threads.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"threads.js","sourceRoot":"","sources":["../src/threads.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACzF,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EACL,cAAc,EACd,OAAO,IAAI,aAAa,EACxB,MAAM,IAAI,YAAY,EACtB,UAAU,IAAI,gBAAgB,GAC/B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAsC/D;;;;;;GAMG;AACH,SAAS,mBAAmB,CAAC,OAAsB,EAAE,IAAc;IACjE,IAAI,OAAO,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACvE,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,WAAW;IAGO;IAFrB,KAAK,GAAqB,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;IAE3E,YAA6B,IAAY;QAAZ,SAAI,GAAJ,IAAI,CAAQ;QACvC,IAAI,CAAC,IAAI,EAAE,CAAC;IACd,CAAC;IAEO,IAAI;QACV,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO;QACnC,IAAI,GAA8B,CAAC;QACnC,IAAI,CAAC;YACH,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAA8B,CAAC;QACjF,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;YACrE,gEAAgE;YAChE,IAAI,CAAC,KAAK,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;YACtD,OAAO;QACT,CAAC;QACD,2EAA2E;QAC3E,2EAA2E;QAC3E,kEAAkE;QAClE,0EAA0E;QAC1E,4EAA4E;QAC5E,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,MAAM,IAAI,GAAG,CAAI,KAA4B,EAAE,MAAiE,EAAO,EAAE,CACvH,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YAC7B,IAAI,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACxD,sEAAsE;gBACtE,oEAAoE;gBACpE,mEAAmE;gBACnE,mEAAmE;gBACnE,eAAe;gBACf,MAAM,GAAG,GAAG,IAA+B,CAAC;gBAC5C,MAAM,QAAQ,GAA4B,EAAE,GAAG,GAAG,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC;gBACrF,IAAI,QAAQ,CAAC,OAAO,CAAC,KAAK,SAAS;oBAAE,QAAQ,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC;gBAClE,IAAI,QAAQ,CAAC,MAAM,CAAC,KAAK,aAAa;oBAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,UAAU,CAAC;gBACtE,IAAI,QAAQ,CAAC,aAAa,CAAC,KAAK,eAAe;oBAAE,QAAQ,CAAC,aAAa,CAAC,GAAG,cAAc,CAAC;gBAC1F,IAAI,QAAQ,CAAC,aAAa,CAAC,KAAK,QAAQ,EAAE,CAAC;oBACzC,mEAAmE;oBACnE,oEAAoE;oBACpE,iEAAiE;oBACjE,oEAAoE;oBACpE,QAAQ,CAAC,aAAa,CAAC,GAAG,MAAM,CAAC;oBACjC,QAAQ,CAAC,OAAO,CAAC,GAAG,SAAS,CAAC;gBAChC,CAAC;gBACD,MAAM,GAAG,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YACtC,CAAC;YACD,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS;gBAAE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACtE,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;QACL,IAAI,CAAC,KAAK,GAAG;YACX,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,YAAY,CAAC;YACxC,QAAQ,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC;YAC3C,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,gBAAgB,CAAC;SACzC,CAAC;QACF,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAChB,IAAI,CAAC;gBACH,aAAa,CAAC,GAAG,IAAI,CAAC,IAAI,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;gBACjF,OAAO,CAAC,KAAK,CACX,8BAA8B,OAAO,iEAAiE,IAAI,CAAC,IAAI,MAAM,CACtH,CAAC;YACJ,CAAC;YAAC,MAAM,CAAC;gBACP,wBAAwB;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAEO,OAAO;QACb,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAChE,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,YAAY,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC;QACpE,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACzE,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,YAAY,CAAC,KAAwB;QACnC,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;QACrB,yEAAyE;QACzE,gFAAgF;QAChF,sEAAsE;QACtE,MAAM,QAAQ,GAAG,KAAK,CAAC,iBAAiB,IAAI,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,cAAc,IAAI,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC5E,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC;YAChC,cAAc,EAAE,cAAc;YAC9B,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC;YACf,UAAU,EAAE,GAAG;YACf,UAAU,EAAE,GAAG;YACf,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,IAAI;YACxE,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,IAAI;YAC1B,mEAAmE;YACnE,uEAAuE;YACvE,8EAA8E;YAC9E,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;YACtD,2EAA2E;YAC3E,yEAAyE;YACzE,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,IAAI,UAAU,CAAC,CAAC,CAAC,UAAU,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;YACrH,eAAe,EAAE,KAAK,CAAC,cAAc,IAAI,MAAM;YAC/C,eAAe,EAAE,OAAO;YACxB,kBAAkB,EAAE,QAAQ;SAC7B,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChC,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,mDAAmD;IACnD,YAAY,CAAC,EAAU,EAAE,KAAwB;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM;YAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,EAAE,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QACtF,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1D,IAAI,KAAK,CAAC,KAAK,KAAK,SAAS;YAAE,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;QAC1D,IAAI,KAAK,CAAC,cAAc,KAAK,SAAS;YAAE,MAAM,CAAC,eAAe,GAAG,KAAK,CAAC,cAAc,CAAC;QACtF,IAAI,KAAK,CAAC,iBAAiB,KAAK,SAAS;YAAE,MAAM,CAAC,kBAAkB,GAAG,KAAK,CAAC,iBAAiB,CAAC;QAC/F,mFAAmF;QACnF,gFAAgF;QAChF,kFAAkF;QAClF,kFAAkF;QAClF,oFAAoF;QACpF,MAAM,CAAC,eAAe,GAAG,mBAAmB,CAAC,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAChG,MAAM,CAAC,UAAU,GAAG,MAAM,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,2EAA2E;IAC3E,iBAAiB,CAAC,EAAU,EAAE,YAAoB,EAAE,OAAe;QACjE,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,CAAC,SAAS,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QAC3F,MAAM,CAAC,UAAU,GAAG,MAAM,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,WAAW;QACT,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACxF,CAAC;IAED,SAAS,CAAC,EAAU;QAClB,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,QAAQ,CAAC,QAAgB;QACvB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IACvD,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,WAAoB,EAAE,SAAkB;QACrD,MAAM,QAAQ,GAAG,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1F,MAAM,MAAM,GAAG,OAAO,SAAS,KAAK,QAAQ,IAAI,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;QAClF,IAAI,QAAQ,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1C,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,QAAQ,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAClC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAiB,MAAM,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;YACtF,CAAC;YACD,sEAAsE;YACtE,oEAAoE;YACpE,mEAAmE;YACnE,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,UAAU,MAAM,wBAAwB,CAAC,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;YACrG,CAAC;YACD,IAAI,IAAI,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;gBAChC,MAAM,MAAM,CAAC,MAAM,CACjB,IAAI,KAAK,CAAC,QAAQ,MAAM,sBAAsB,IAAI,CAAC,SAAS,SAAS,QAAQ,EAAE,CAAC,EAChF,EAAE,IAAI,EAAE,cAAc,EAAE,CACzB,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC9B,CAAC;IAED,iBAAiB,CAAC,QAAgB;QAChC,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC;IACrE,CAAC;IAED,2FAA2F;IAC3F,SAAS,CAAC,QAAgB;QACxB,MAAM,GAAG,GAA2B,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;YACjD,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,CAAC,iBAAiB;gBAAE,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,iBAAiB,CAAC;QACzF,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;;;;OAOG;IACH,UAAU,CAAC,QAAgB,EAAE,MAAc,EAAE,QAAyB,EAAE;QACtE,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM;YAAE,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5F,8EAA8E;QAC9E,8EAA8E;QAC9E,4DAA4D;QAC5D,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;QACtF,MAAM,IAAI,GAAuB,KAAK,CAAC,IAAI,IAAI,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QAC9F,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC;YAClC,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC;YACf,SAAS,EAAE,QAAQ;YACnB,MAAM,EAAE,IAAI;YACZ,aAAa,EAAE,KAAK,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW;YACvF,WAAW,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI;YACpC,IAAI;YACJ,sEAAsE;YACtE,6DAA6D;YAC7D,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC;YAC7B,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,EAAE;YACpC,UAAU,EAAE,MAAM,EAAE;SACrB,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5B,8EAA8E;QAC9E,IAAI,CAAC,MAAM,CAAC,KAAK;YAAE,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC1E,MAAM,CAAC,UAAU,GAAG,MAAM,EAAE,CAAC;QAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;IAED,iFAAiF;IACjF,WAAW,CAAC,MAAc,EAAE,KAAa;QACvC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI;YAAE,OAAO;QAClB,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;QACpB,sEAAsE;QACtE,mEAAmE;QACnE,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAChE,MAAM,CAAC,WAAW,GAAG,KAAK,CAAC;YAC3B,MAAM,CAAC,UAAU,GAAG,MAAM,EAAE,CAAC;QAC/B,CAAC;QACD,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED;;;;;;;;;OASG;IACH,mBAAmB,CAAC,MAAc,EAAE,OAAe,EAAE,OAAsB,IAAI,EAAE,SAAS,GAAG,IAAI;QAC/F,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM;YAAE,OAAO;QACjC,IAAI,CAAC,aAAa,GAAG,EAAE,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,CAAC;QAC/F,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,MAAM;YAAE,MAAM,CAAC,UAAU,GAAG,MAAM,EAAE,CAAC;QACzC,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAGD,+EAA+E;IAC/E,aAAa,CAAC,QAAgB,EAAE,SAAiB,EAAE,eAAuB,EAAE,aAA6B;QACvG,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC;QACzG,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;QACrB,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,iBAAiB,GAAG,eAAe,CAAC;YAC7C,QAAQ,CAAC,KAAK,GAAG,MAAM,CAAC;YACxB,QAAQ,CAAC,WAAW,GAAG,cAAc,CAAC;YACtC,IAAI,aAAa;gBAAE,QAAQ,CAAC,mBAAmB,GAAG,aAAa,CAAC;YAChE,QAAQ,CAAC,UAAU,GAAG,GAAG,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CACtB,aAAa,CAAC,KAAK,CAAC;gBAClB,EAAE,EAAE,KAAK,CAAC,IAAI,CAAC;gBACf,SAAS,EAAE,QAAQ;gBACnB,UAAU,EAAE,SAAS;gBACrB,iBAAiB,EAAE,eAAe;gBAClC,mBAAmB,EAAE,aAAa,IAAI,IAAI;gBAC1C,WAAW,EAAE,cAAc;gBAC3B,KAAK,EAAE,MAAM;gBACb,UAAU,EAAE,GAAG;gBACf,UAAU,EAAE,GAAG;aAChB,CAAC,CACH,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,MAAM;YAAE,MAAM,CAAC,UAAU,GAAG,GAAG,CAAC;QACpC,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;CAEF"}
@@ -0,0 +1,11 @@
1
+ export declare function daemonDir(): string;
2
+ export declare function defaultSocketPath(): string;
3
+ export declare function logPath(): string;
4
+ /** Read or generate a per-user local auth token (0600). */
5
+ export declare function ensureToken(): string;
6
+ export declare function readToken(): string | null;
7
+ /** Rotate the local auth token: a fresh random token replaces the
8
+ * old one (0600). Existing daemon sessions keep their in-memory token, so
9
+ * rotation takes effect on the next daemon start — the CLI surface says so. */
10
+ export declare function rotateToken(): string;
11
+ //# sourceMappingURL=token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAKA,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED,wBAAgB,OAAO,IAAI,MAAM,CAEhC;AAED,2DAA2D;AAC3D,wBAAgB,WAAW,IAAI,MAAM,CAkBpC;AAED,wBAAgB,SAAS,IAAI,MAAM,GAAG,IAAI,CAOzC;AAED;;+EAE+E;AAC/E,wBAAgB,WAAW,IAAI,MAAM,CAYpC"}
package/dist/token.js ADDED
@@ -0,0 +1,63 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { chmodSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { join } from "node:path";
4
+ import { userConfigDir } from "@claudexor/util";
5
+ export function daemonDir() {
6
+ return join(userConfigDir(), "daemon");
7
+ }
8
+ export function defaultSocketPath() {
9
+ return process.env.CLAUDEXOR_DAEMON_SOCK || join(daemonDir(), "claudexord.sock");
10
+ }
11
+ export function logPath() {
12
+ return join(daemonDir(), "claudexord.log");
13
+ }
14
+ /** Read or generate a per-user local auth token (0600). */
15
+ export function ensureToken() {
16
+ const dir = daemonDir();
17
+ mkdirSync(dir, { recursive: true });
18
+ const path = join(dir, "token");
19
+ try {
20
+ const existing = readFileSync(path, "utf8").trim();
21
+ if (existing)
22
+ return existing;
23
+ }
24
+ catch {
25
+ /* generate below */
26
+ }
27
+ const token = randomUUID();
28
+ writeFileSync(path, token + "\n", { mode: 0o600 });
29
+ try {
30
+ chmodSync(path, 0o600);
31
+ }
32
+ catch {
33
+ /* best-effort */
34
+ }
35
+ return token;
36
+ }
37
+ export function readToken() {
38
+ try {
39
+ const t = readFileSync(join(daemonDir(), "token"), "utf8").trim();
40
+ return t || null;
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ }
46
+ /** Rotate the local auth token: a fresh random token replaces the
47
+ * old one (0600). Existing daemon sessions keep their in-memory token, so
48
+ * rotation takes effect on the next daemon start — the CLI surface says so. */
49
+ export function rotateToken() {
50
+ const dir = daemonDir();
51
+ mkdirSync(dir, { recursive: true });
52
+ const path = join(dir, "token");
53
+ const token = randomUUID();
54
+ writeFileSync(path, token + "\n", { mode: 0o600 });
55
+ try {
56
+ chmodSync(path, 0o600);
57
+ }
58
+ catch {
59
+ /* best-effort */
60
+ }
61
+ return token;
62
+ }
63
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../src/token.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,UAAU,SAAS;IACvB,OAAO,IAAI,CAAC,aAAa,EAAE,EAAE,QAAQ,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,OAAO,OAAO,CAAC,GAAG,CAAC,qBAAqB,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE,iBAAiB,CAAC,CAAC;AACnF,CAAC;AAED,MAAM,UAAU,OAAO;IACrB,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,gBAAgB,CAAC,CAAC;AAC7C,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,WAAW;IACzB,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAChC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QACnD,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,oBAAoB;IACtB,CAAC;IACD,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;IAC3B,aAAa,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACnD,IAAI,CAAC;QACH,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;QAClE,OAAO,CAAC,IAAI,IAAI,CAAC;IACnB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;+EAE+E;AAC/E,MAAM,UAAU,WAAW;IACzB,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;IAC3B,aAAa,CAAC,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACnD,IAAI,CAAC;QACH,SAAS,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,iBAAiB;IACnB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@claudexor/daemon",
3
+ "version": "1.0.0",
4
+ "license": "MIT",
5
+ "description": "Optional local daemon: Unix-socket JSON-RPC, token auth, task queue. Runner injected (no second scheduler).",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "dependencies": {
19
+ "@claudexor/event-log": "1.0.0",
20
+ "@claudexor/schema": "1.0.0",
21
+ "@claudexor/util": "1.0.0"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "git+https://github.com/razzant/claudexor.git",
26
+ "directory": "packages/daemon"
27
+ },
28
+ "homepage": "https://github.com/razzant/claudexor#readme",
29
+ "bugs": {
30
+ "url": "https://github.com/razzant/claudexor/issues"
31
+ },
32
+ "engines": {
33
+ "node": ">=20.19"
34
+ },
35
+ "publishConfig": {
36
+ "access": "public"
37
+ },
38
+ "scripts": {
39
+ "build": "tsc",
40
+ "typecheck": "tsc --noEmit"
41
+ }
42
+ }