@dhrxv29/autocodex 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +119 -0
  3. package/dist/app.d.ts +47 -0
  4. package/dist/app.js +174 -0
  5. package/dist/app.js.map +1 -0
  6. package/dist/cli.d.ts +22 -0
  7. package/dist/cli.js +308 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/clock.d.ts +14 -0
  10. package/dist/clock.js +21 -0
  11. package/dist/clock.js.map +1 -0
  12. package/dist/defaults.d.ts +10 -0
  13. package/dist/defaults.js +11 -0
  14. package/dist/defaults.js.map +1 -0
  15. package/dist/facing.d.ts +31 -0
  16. package/dist/facing.js +115 -0
  17. package/dist/facing.js.map +1 -0
  18. package/dist/index.d.ts +17 -0
  19. package/dist/index.js +18 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/launchd.d.ts +57 -0
  22. package/dist/launchd.js +333 -0
  23. package/dist/launchd.js.map +1 -0
  24. package/dist/machine.d.ts +21 -0
  25. package/dist/machine.js +277 -0
  26. package/dist/machine.js.map +1 -0
  27. package/dist/paths.d.ts +20 -0
  28. package/dist/paths.js +58 -0
  29. package/dist/paths.js.map +1 -0
  30. package/dist/provider.d.ts +20 -0
  31. package/dist/provider.js +2 -0
  32. package/dist/provider.js.map +1 -0
  33. package/dist/providers/app-server.d.ts +102 -0
  34. package/dist/providers/app-server.js +474 -0
  35. package/dist/providers/app-server.js.map +1 -0
  36. package/dist/providers/codex.d.ts +44 -0
  37. package/dist/providers/codex.js +260 -0
  38. package/dist/providers/codex.js.map +1 -0
  39. package/dist/scheduler.d.ts +25 -0
  40. package/dist/scheduler.js +59 -0
  41. package/dist/scheduler.js.map +1 -0
  42. package/dist/schema.d.ts +5 -0
  43. package/dist/schema.js +41 -0
  44. package/dist/schema.js.map +1 -0
  45. package/dist/store.d.ts +15 -0
  46. package/dist/store.js +146 -0
  47. package/dist/store.js.map +1 -0
  48. package/dist/tracker.d.ts +33 -0
  49. package/dist/tracker.js +98 -0
  50. package/dist/tracker.js.map +1 -0
  51. package/dist/tui.d.ts +25 -0
  52. package/dist/tui.js +89 -0
  53. package/dist/tui.js.map +1 -0
  54. package/dist/types.d.ts +84 -0
  55. package/dist/types.js +48 -0
  56. package/dist/types.js.map +1 -0
  57. package/dist/view.d.ts +68 -0
  58. package/dist/view.js +139 -0
  59. package/dist/view.js.map +1 -0
  60. package/package.json +57 -0
@@ -0,0 +1,260 @@
1
+ import { CodexAppServerClient, StdioAppServerTransport, defaultAppServerSpawn, } from "./app-server.js";
2
+ import { AutocodexError, SameSessionRequiredError } from "../types.js";
3
+ const USAGE_LIMIT_INFO = new Set([
4
+ "usage_limit_exceeded",
5
+ "UsageLimitExceeded",
6
+ "USAGE_LIMIT_EXCEEDED",
7
+ ]);
8
+ const RATE_LIMIT_INFO = new Set([
9
+ "rate_limit_exceeded",
10
+ "RateLimitExceeded",
11
+ "rateLimitExceeded",
12
+ "RATE_LIMIT_EXCEEDED",
13
+ ]);
14
+ const WAITABLE_REACHED = new Set([
15
+ "rate_limit_reached",
16
+ "RateLimitReached",
17
+ null,
18
+ undefined,
19
+ ]);
20
+ const NON_WAITABLE_REACHED = new Set([
21
+ "workspace_owner_credits_depleted",
22
+ "workspace_member_credits_depleted",
23
+ "workspace_owner_usage_limit_reached",
24
+ "workspace_member_usage_limit_reached",
25
+ "WorkspaceOwnerCreditsDepleted",
26
+ "WorkspaceMemberCreditsDepleted",
27
+ "WorkspaceOwnerUsageLimitReached",
28
+ "WorkspaceMemberUsageLimitReached",
29
+ ]);
30
+ const UNIX_NUMBER_RE = /^[+-]?\d+(?:\.\d+)?$/;
31
+ const RFC3339_RE = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/;
32
+ export function isRecord(value) {
33
+ return typeof value === "object" && value !== null && !Array.isArray(value);
34
+ }
35
+ /**
36
+ * Absolute Unix seconds only.
37
+ * Accepts finite numbers, numeric strings, and RFC3339 instants.
38
+ * Never Date.parse of display banners ("Try again at 3:51 PM").
39
+ */
40
+ export function asFiniteUnix(value) {
41
+ if (typeof value === "number" && Number.isFinite(value)) {
42
+ return unixFromNumber(value);
43
+ }
44
+ if (typeof value === "string") {
45
+ const trimmed = value.trim();
46
+ if (trimmed === "") {
47
+ return null;
48
+ }
49
+ if (UNIX_NUMBER_RE.test(trimmed)) {
50
+ return unixFromNumber(Number(trimmed));
51
+ }
52
+ if (RFC3339_RE.test(trimmed)) {
53
+ const ms = Date.parse(trimmed);
54
+ if (!Number.isNaN(ms)) {
55
+ return unixFromNumber(ms / 1000);
56
+ }
57
+ }
58
+ }
59
+ return null;
60
+ }
61
+ function unixFromNumber(value) {
62
+ if (!Number.isFinite(value)) {
63
+ return null;
64
+ }
65
+ const seconds = value >= 1e12 ? value / 1000 : value;
66
+ const unix = Math.trunc(seconds);
67
+ if (unix <= 0) {
68
+ return null;
69
+ }
70
+ return unix;
71
+ }
72
+ function firstString(...values) {
73
+ for (const value of values) {
74
+ if (typeof value === "string" && value.trim() !== "") {
75
+ return value.trim();
76
+ }
77
+ }
78
+ return undefined;
79
+ }
80
+ /**
81
+ * Resume target is Codex `thread.id`.
82
+ * Never silently use `thread.sessionId` (fork-root / live session-tree root).
83
+ */
84
+ export function pickSessionId(value, hint) {
85
+ if (typeof hint === "string" && hint.trim() !== "") {
86
+ return hint.trim();
87
+ }
88
+ if (!isRecord(value)) {
89
+ return undefined;
90
+ }
91
+ const thread = isRecord(value.thread) ? value.thread : undefined;
92
+ const threadId = firstString(thread?.id, value.threadId, value.thread_id);
93
+ if (threadId) {
94
+ return threadId;
95
+ }
96
+ if (thread) {
97
+ return undefined;
98
+ }
99
+ return firstString(value.sessionId, value.session_id);
100
+ }
101
+ function windowReset(window) {
102
+ if (!isRecord(window)) {
103
+ return null;
104
+ }
105
+ return asFiniteUnix(window.resetsAt ?? window.resets_at ?? window.reset_at);
106
+ }
107
+ function snapshotReset(snapshot) {
108
+ if (!isRecord(snapshot)) {
109
+ return null;
110
+ }
111
+ return (windowReset(snapshot.primary) ??
112
+ windowReset(snapshot.secondary) ??
113
+ asFiniteUnix(snapshot.resetsAt ?? snapshot.resets_at));
114
+ }
115
+ function reachedType(value) {
116
+ if (!isRecord(value)) {
117
+ return undefined;
118
+ }
119
+ const raw = value.rateLimitReachedType ??
120
+ value.rate_limit_reached_type ??
121
+ (isRecord(value.rateLimits) ? value.rateLimits.rateLimitReachedType : undefined);
122
+ return typeof raw === "string" ? raw : undefined;
123
+ }
124
+ /**
125
+ * Parse official Codex app-server / protocol payloads.
126
+ * Does not scrape terminals and does not read $CODEX_HOME auth files.
127
+ */
128
+ export function detectCodexUsageLimit(event, hintSessionId) {
129
+ if (!isRecord(event)) {
130
+ return null;
131
+ }
132
+ const payload = isRecord(event.result)
133
+ ? event.result
134
+ : isRecord(event.params)
135
+ ? event.params
136
+ : event;
137
+ const error = isRecord(payload.error) ? payload.error : isRecord(event.error) ? event.error : undefined;
138
+ const info = error
139
+ ? (error.codexErrorInfo ?? error.codex_error_info ?? error.type)
140
+ : payload.type;
141
+ const sessionId = pickSessionId(payload, hintSessionId) ?? pickSessionId(event, hintSessionId);
142
+ const reached = reachedType(payload) ?? reachedType(event);
143
+ if (reached && NON_WAITABLE_REACHED.has(reached)) {
144
+ return null;
145
+ }
146
+ let kind = null;
147
+ if (typeof info === "string" && USAGE_LIMIT_INFO.has(info)) {
148
+ kind = "usage_limit";
149
+ }
150
+ else if (typeof info === "string" && RATE_LIMIT_INFO.has(info)) {
151
+ kind = "rate_limit";
152
+ }
153
+ else if (reached && WAITABLE_REACHED.has(reached)) {
154
+ const ordinary = payload.ordinaryUsageAllowed ?? event.ordinaryUsageAllowed;
155
+ if (ordinary === false || reached === "rate_limit_reached" || reached === "RateLimitReached") {
156
+ kind = "usage_limit";
157
+ }
158
+ }
159
+ else if (payload.ordinaryUsageAllowed === false) {
160
+ kind = "usage_limit";
161
+ }
162
+ const resetAtUnix = asFiniteUnix(payload.resetsAt ?? payload.resets_at ?? error?.resetsAt ?? error?.resets_at) ??
163
+ snapshotReset(payload.rateLimits ?? payload.rate_limits) ??
164
+ snapshotReset(isRecord(payload.rateLimitsByLimitId) ? payload.rateLimitsByLimitId.codex : undefined) ??
165
+ snapshotReset(error?.rate_limits ?? error?.rateLimits);
166
+ if (!sessionId || resetAtUnix === null || kind === null) {
167
+ return null;
168
+ }
169
+ let source = "usage_limit_error";
170
+ if (error && kind) {
171
+ source = "app_server_turn";
172
+ }
173
+ else if (payload.rateLimits || payload.ordinaryUsageAllowed !== undefined) {
174
+ source = "account_rate_limits";
175
+ }
176
+ return { sessionId, resetAtUnix, kind, source };
177
+ }
178
+ /**
179
+ * Live Codex adapter: parse official events, then `thread/resume` + `turn/start`
180
+ * on the official app-server JSON-RPC (stdio by default).
181
+ */
182
+ export class CodexProvider {
183
+ name = "codex";
184
+ client;
185
+ connecting;
186
+ connect;
187
+ constructor(options = {}) {
188
+ if (options.client) {
189
+ this.client = options.client;
190
+ }
191
+ this.connect =
192
+ options.connect ??
193
+ (async () => {
194
+ const transport = StdioAppServerTransport.spawn(options.spawn ?? defaultAppServerSpawn());
195
+ return new CodexAppServerClient(transport);
196
+ });
197
+ }
198
+ detectUsageLimit(event, hintSessionId) {
199
+ return detectCodexUsageLimit(event, hintSessionId);
200
+ }
201
+ async readAccountRateLimits() {
202
+ const client = await this.ensureClient();
203
+ return client.rateLimitsRead();
204
+ }
205
+ async resumeSession(sessionId) {
206
+ const expected = sessionId.trim();
207
+ if (!expected) {
208
+ throw new AutocodexError("sessionId is required");
209
+ }
210
+ if (expected === "--last" || expected === "last") {
211
+ throw new AutocodexError("Refusing resume --last. Autocodex only resumes an explicit thread.id.");
212
+ }
213
+ const client = await this.ensureClient();
214
+ const resumed = await client.threadResume(expected);
215
+ if (resumed.threadId !== expected) {
216
+ throw new SameSessionRequiredError(expected, resumed.threadId);
217
+ }
218
+ return { sessionId: expected };
219
+ }
220
+ async sendContinuation(sessionId, prompt) {
221
+ const expected = sessionId.trim();
222
+ if (!expected) {
223
+ throw new AutocodexError("sessionId is required");
224
+ }
225
+ const client = await this.ensureClient();
226
+ if (!client.isThreadLoaded(expected)) {
227
+ const resumed = await client.threadResume(expected);
228
+ if (resumed.threadId !== expected) {
229
+ throw new SameSessionRequiredError(expected, resumed.threadId);
230
+ }
231
+ }
232
+ await client.turnStart(expected, prompt);
233
+ }
234
+ async close() {
235
+ const client = this.client;
236
+ this.client = undefined;
237
+ this.connecting = undefined;
238
+ client?.close();
239
+ }
240
+ async ensureClient() {
241
+ if (this.client?.isInitialized) {
242
+ return this.client;
243
+ }
244
+ if (!this.connecting) {
245
+ this.connecting = (async () => {
246
+ const client = this.client ?? (await this.connect());
247
+ this.client = client;
248
+ if (!client.isInitialized) {
249
+ await client.handshake();
250
+ }
251
+ return client;
252
+ })().catch((error) => {
253
+ this.connecting = undefined;
254
+ throw error;
255
+ });
256
+ }
257
+ return this.connecting;
258
+ }
259
+ }
260
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/providers/codex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { AutoCodex, StepResult } from "./app.js";
2
+ import type { SessionRecord } from "./types.js";
3
+ /**
4
+ * One drive of the machine: optional account rate-limit ingest, tick waiting
5
+ * sessions that have reached an absolute reset timestamp, then resume + continue
6
+ * once. Safe after process restart / launchd KeepAlive wake.
7
+ */
8
+ export declare function runOnce(app: AutoCodex): Promise<StepResult>;
9
+ export interface DaemonLoopOptions {
10
+ pollSeconds?: number;
11
+ sleep?: (seconds: number) => Promise<void>;
12
+ shouldContinue?: () => boolean;
13
+ onCycle?: (result: StepResult) => void;
14
+ }
15
+ /**
16
+ * How long the daemon should sleep before the next `step`.
17
+ * Absolute `reset_at_unix` is the source of truth; this cap is only so sleep/wake
18
+ * is noticed without NSWorkspaceDidWake (launchd KeepAlive + poll).
19
+ */
20
+ export declare function secondsUntilNextWork(sessions: SessionRecord[], nowUnix: number, pollSeconds?: number): number;
21
+ /**
22
+ * Long-running driver used by `autocodex daemon` and the macOS KeepAlive agent.
23
+ * Reloads happen by opening SQLite on each process start; each cycle calls `step()`.
24
+ */
25
+ export declare function runDaemon(app: AutoCodex, options?: DaemonLoopOptions): Promise<void>;
@@ -0,0 +1,59 @@
1
+ import { DEFAULT_DAEMON_POLL_SECONDS } from "./defaults.js";
2
+ /**
3
+ * One drive of the machine: optional account rate-limit ingest, tick waiting
4
+ * sessions that have reached an absolute reset timestamp, then resume + continue
5
+ * once. Safe after process restart / launchd KeepAlive wake.
6
+ */
7
+ export async function runOnce(app) {
8
+ return app.step();
9
+ }
10
+ function defaultSleep(seconds) {
11
+ return new Promise((resolve) => {
12
+ setTimeout(resolve, Math.max(0, seconds) * 1000);
13
+ });
14
+ }
15
+ /**
16
+ * How long the daemon should sleep before the next `step`.
17
+ * Absolute `reset_at_unix` is the source of truth; this cap is only so sleep/wake
18
+ * is noticed without NSWorkspaceDidWake (launchd KeepAlive + poll).
19
+ */
20
+ export function secondsUntilNextWork(sessions, nowUnix, pollSeconds = DEFAULT_DAEMON_POLL_SECONDS) {
21
+ const poll = Number.isFinite(pollSeconds) && pollSeconds > 0 ? pollSeconds : DEFAULT_DAEMON_POLL_SECONDS;
22
+ const needsRetry = sessions.some((session) => session.phase === "available" ||
23
+ session.phase === "resuming" ||
24
+ session.phase === "continuing");
25
+ if (needsRetry) {
26
+ return Math.min(poll, 5);
27
+ }
28
+ let until = poll;
29
+ for (const session of sessions) {
30
+ if (session.phase !== "waiting" || session.resetAtUnix === null) {
31
+ continue;
32
+ }
33
+ const delta = session.resetAtUnix - nowUnix;
34
+ if (delta <= 0) {
35
+ return 0;
36
+ }
37
+ until = Math.min(until, delta);
38
+ }
39
+ return Math.max(1, Math.min(until, poll));
40
+ }
41
+ /**
42
+ * Long-running driver used by `autocodex daemon` and the macOS KeepAlive agent.
43
+ * Reloads happen by opening SQLite on each process start; each cycle calls `step()`.
44
+ */
45
+ export async function runDaemon(app, options = {}) {
46
+ const pollSeconds = options.pollSeconds ?? DEFAULT_DAEMON_POLL_SECONDS;
47
+ const sleep = options.sleep ?? defaultSleep;
48
+ const shouldContinue = options.shouldContinue ?? (() => true);
49
+ while (shouldContinue()) {
50
+ const result = await app.step();
51
+ options.onCycle?.(result);
52
+ if (!shouldContinue()) {
53
+ break;
54
+ }
55
+ const wait = secondsUntilNextWork(app.sessions(), app.nowUnix(), pollSeconds);
56
+ await sleep(wait);
57
+ }
58
+ }
59
+ //# sourceMappingURL=scheduler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scheduler.js","sourceRoot":"","sources":["../src/scheduler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAG5D;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,GAAc;IAC1C,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AASD,SAAS,YAAY,CAAC,OAAe;IACnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAClC,QAAyB,EACzB,OAAe,EACf,WAAW,GAAG,2BAA2B;IAEzC,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,2BAA2B,CAAC;IACzG,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAC9B,CAAC,OAAO,EAAE,EAAE,CACV,OAAO,CAAC,KAAK,KAAK,WAAW;QAC7B,OAAO,CAAC,KAAK,KAAK,UAAU;QAC5B,OAAO,CAAC,KAAK,KAAK,YAAY,CACjC,CAAC;IACF,IAAI,UAAU,EAAE,CAAC;QACf,OAAO,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC3B,CAAC;IAED,IAAI,KAAK,GAAG,IAAI,CAAC;IACjB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,WAAW,KAAK,IAAI,EAAE,CAAC;YAChE,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,GAAG,OAAO,CAAC;QAC5C,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YACf,OAAO,CAAC,CAAC;QACX,CAAC;QACD,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAc,EAAE,UAA6B,EAAE;IAC7E,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,2BAA2B,CAAC;IACvE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,YAAY,CAAC;IAC5C,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IAE9D,OAAO,cAAc,EAAE,EAAE,CAAC;QACxB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAChC,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,CAAC;QAC1B,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;YACtB,MAAM;QACR,CAAC;QACD,MAAM,IAAI,GAAG,oBAAoB,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,GAAG,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;QAC9E,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;AACH,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare const SCHEMA_VERSION = 1;
2
+ export declare const MIGRATIONS: readonly {
3
+ version: number;
4
+ sql: string;
5
+ }[];
package/dist/schema.js ADDED
@@ -0,0 +1,41 @@
1
+ export const SCHEMA_VERSION = 1;
2
+ export const MIGRATIONS = [
3
+ {
4
+ version: 1,
5
+ sql: `
6
+ CREATE TABLE IF NOT EXISTS schema_migrations (
7
+ version INTEGER PRIMARY KEY,
8
+ applied_at_unix INTEGER NOT NULL
9
+ );
10
+
11
+ CREATE TABLE IF NOT EXISTS daemon (
12
+ id INTEGER PRIMARY KEY CHECK (id = 1),
13
+ enabled INTEGER NOT NULL DEFAULT 0,
14
+ updated_at_unix INTEGER NOT NULL
15
+ );
16
+
17
+ CREATE TABLE IF NOT EXISTS sessions (
18
+ session_id TEXT PRIMARY KEY,
19
+ cwd TEXT,
20
+ phase TEXT NOT NULL,
21
+ reset_at_unix INTEGER,
22
+ limit_kind TEXT,
23
+ continuation_prompt TEXT NOT NULL,
24
+ continuation_sent INTEGER NOT NULL DEFAULT 0,
25
+ resume_attempt_id TEXT,
26
+ last_error TEXT,
27
+ created_at_unix INTEGER NOT NULL,
28
+ updated_at_unix INTEGER NOT NULL
29
+ );
30
+
31
+ CREATE TABLE IF NOT EXISTS events (
32
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
33
+ session_id TEXT,
34
+ at_unix INTEGER NOT NULL,
35
+ kind TEXT NOT NULL,
36
+ message TEXT NOT NULL
37
+ );
38
+ `,
39
+ },
40
+ ];
41
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC;AAEhC,MAAM,CAAC,MAAM,UAAU,GAAgD;IACrE;QACE,OAAO,EAAE,CAAC;QACV,GAAG,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCR;KACE;CACF,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { DaemonRecord, LogEvent, SessionRecord } from "./types.js";
2
+ export declare class SqliteStore {
3
+ private readonly db;
4
+ constructor(filename: string);
5
+ close(): void;
6
+ private migrate;
7
+ getDaemon(): DaemonRecord;
8
+ setDaemon(enabled: boolean, nowUnix: number): void;
9
+ listSessions(): SessionRecord[];
10
+ getSession(sessionId: string): SessionRecord | undefined;
11
+ putSession(session: SessionRecord): void;
12
+ replaceSessions(sessions: SessionRecord[]): void;
13
+ appendEvent(event: Omit<LogEvent, "id">): void;
14
+ listEvents(limit?: number, sessionId?: string): LogEvent[];
15
+ }
package/dist/store.js ADDED
@@ -0,0 +1,146 @@
1
+ import { mkdirSync } from "node:fs";
2
+ import { dirname } from "node:path";
3
+ import { DatabaseSync } from "node:sqlite";
4
+ import { MIGRATIONS, SCHEMA_VERSION } from "./schema.js";
5
+ function asBool(value) {
6
+ return Number(value) === 1;
7
+ }
8
+ function rowToSession(row) {
9
+ return {
10
+ sessionId: String(row.session_id),
11
+ cwd: row.cwd === null || row.cwd === undefined ? null : String(row.cwd),
12
+ phase: String(row.phase),
13
+ resetAtUnix: row.reset_at_unix === null || row.reset_at_unix === undefined
14
+ ? null
15
+ : Number(row.reset_at_unix),
16
+ limitKind: row.limit_kind === null || row.limit_kind === undefined
17
+ ? null
18
+ : String(row.limit_kind),
19
+ continuationPrompt: String(row.continuation_prompt),
20
+ continuationSent: asBool(row.continuation_sent),
21
+ resumeAttemptId: row.resume_attempt_id === null || row.resume_attempt_id === undefined
22
+ ? null
23
+ : String(row.resume_attempt_id),
24
+ lastError: row.last_error === null || row.last_error === undefined ? null : String(row.last_error),
25
+ createdAtUnix: Number(row.created_at_unix),
26
+ updatedAtUnix: Number(row.updated_at_unix),
27
+ };
28
+ }
29
+ export class SqliteStore {
30
+ db;
31
+ constructor(filename) {
32
+ if (filename !== ":memory:") {
33
+ mkdirSync(dirname(filename), { recursive: true });
34
+ }
35
+ this.db = new DatabaseSync(filename);
36
+ this.db.exec("PRAGMA foreign_keys = ON;");
37
+ this.migrate();
38
+ }
39
+ close() {
40
+ this.db.close();
41
+ }
42
+ migrate() {
43
+ this.db.exec(`
44
+ CREATE TABLE IF NOT EXISTS schema_migrations (
45
+ version INTEGER PRIMARY KEY,
46
+ applied_at_unix INTEGER NOT NULL
47
+ );`);
48
+ const applied = new Set(this.db
49
+ .prepare("SELECT version FROM schema_migrations")
50
+ .all()
51
+ .map((row) => Number(row.version)));
52
+ const now = Math.floor(Date.now() / 1000);
53
+ for (const migration of MIGRATIONS) {
54
+ if (applied.has(migration.version)) {
55
+ continue;
56
+ }
57
+ this.db.exec(migration.sql);
58
+ this.db
59
+ .prepare("INSERT INTO schema_migrations (version, applied_at_unix) VALUES (?, ?)")
60
+ .run(migration.version, now);
61
+ }
62
+ this.db
63
+ .prepare("INSERT OR IGNORE INTO daemon (id, enabled, updated_at_unix) VALUES (1, 0, ?)")
64
+ .run(now);
65
+ if (SCHEMA_VERSION < 1) {
66
+ throw new Error("invalid schema version");
67
+ }
68
+ }
69
+ getDaemon() {
70
+ const row = this.db
71
+ .prepare("SELECT enabled, updated_at_unix FROM daemon WHERE id = 1")
72
+ .get();
73
+ return { enabled: asBool(row.enabled), updatedAtUnix: Number(row.updated_at_unix) };
74
+ }
75
+ setDaemon(enabled, nowUnix) {
76
+ this.db
77
+ .prepare("UPDATE daemon SET enabled = ?, updated_at_unix = ? WHERE id = 1")
78
+ .run(enabled ? 1 : 0, nowUnix);
79
+ }
80
+ listSessions() {
81
+ return this.db
82
+ .prepare("SELECT * FROM sessions ORDER BY updated_at_unix DESC")
83
+ .all()
84
+ .map((row) => rowToSession(row));
85
+ }
86
+ getSession(sessionId) {
87
+ const row = this.db
88
+ .prepare("SELECT * FROM sessions WHERE session_id = ?")
89
+ .get(sessionId);
90
+ return row ? rowToSession(row) : undefined;
91
+ }
92
+ putSession(session) {
93
+ this.db
94
+ .prepare(`INSERT INTO sessions (
95
+ session_id, cwd, phase, reset_at_unix, limit_kind, continuation_prompt,
96
+ continuation_sent, resume_attempt_id, last_error, created_at_unix, updated_at_unix
97
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
98
+ ON CONFLICT(session_id) DO UPDATE SET
99
+ cwd = excluded.cwd,
100
+ phase = excluded.phase,
101
+ reset_at_unix = excluded.reset_at_unix,
102
+ limit_kind = excluded.limit_kind,
103
+ continuation_prompt = excluded.continuation_prompt,
104
+ continuation_sent = excluded.continuation_sent,
105
+ resume_attempt_id = excluded.resume_attempt_id,
106
+ last_error = excluded.last_error,
107
+ updated_at_unix = excluded.updated_at_unix`)
108
+ .run(session.sessionId, session.cwd, session.phase, session.resetAtUnix, session.limitKind, session.continuationPrompt, session.continuationSent ? 1 : 0, session.resumeAttemptId, session.lastError, session.createdAtUnix, session.updatedAtUnix);
109
+ }
110
+ replaceSessions(sessions) {
111
+ this.db.exec("BEGIN");
112
+ try {
113
+ this.db.exec("DELETE FROM sessions");
114
+ for (const session of sessions) {
115
+ this.putSession(session);
116
+ }
117
+ this.db.exec("COMMIT");
118
+ }
119
+ catch (error) {
120
+ this.db.exec("ROLLBACK");
121
+ throw error;
122
+ }
123
+ }
124
+ appendEvent(event) {
125
+ this.db
126
+ .prepare("INSERT INTO events (session_id, at_unix, kind, message) VALUES (?, ?, ?, ?)")
127
+ .run(event.sessionId, event.atUnix, event.kind, event.message);
128
+ }
129
+ listEvents(limit = 50, sessionId) {
130
+ const rows = sessionId
131
+ ? this.db
132
+ .prepare("SELECT * FROM events WHERE session_id = ? ORDER BY id DESC LIMIT ?")
133
+ .all(sessionId, limit)
134
+ : this.db.prepare("SELECT * FROM events ORDER BY id DESC LIMIT ?").all(limit);
135
+ return rows.map((row) => ({
136
+ id: Number(row.id),
137
+ sessionId: row.session_id === null || row.session_id === undefined
138
+ ? null
139
+ : String(row.session_id),
140
+ atUnix: Number(row.at_unix),
141
+ kind: String(row.kind),
142
+ message: String(row.message),
143
+ }));
144
+ }
145
+ }
146
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { AutoCodex } from "./app.js";
2
+ import { installLaunchAgent, type LaunchdHost } from "./launchd.js";
3
+ import { type HelperView, type TrackerScreen, type TuiSnapshot } from "./view.js";
4
+ export interface TrackerOptions {
5
+ app: AutoCodex;
6
+ dataDir: string;
7
+ launchd?: LaunchdHost;
8
+ shouldInstall?: boolean;
9
+ install?: typeof installLaunchAgent;
10
+ }
11
+ export declare class TrackerSession {
12
+ draft: string;
13
+ screen: TrackerScreen;
14
+ inputError: string | null;
15
+ helper: HelperView;
16
+ private readonly app;
17
+ private readonly dataDir;
18
+ private readonly launchd?;
19
+ private readonly shouldInstall;
20
+ private readonly install;
21
+ constructor(options: TrackerOptions);
22
+ get needsInProcessDrive(): boolean;
23
+ hasSessions(): boolean;
24
+ type(text: string): void;
25
+ backspace(): void;
26
+ setDraft(text: string): void;
27
+ submitDraft(): boolean;
28
+ startAddAnother(): void;
29
+ cancelAsk(): void;
30
+ retryBackground(): void;
31
+ snapshot(): TuiSnapshot;
32
+ private syncBackground;
33
+ }