pi-harness-runtime 0.9.15 → 0.9.16
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/package.json +1 -1
- package/packages/autonomous-runtime/README.md +48 -0
- package/packages/autonomous-runtime/dist/inbox.d.ts +75 -0
- package/packages/autonomous-runtime/dist/inbox.d.ts.map +1 -0
- package/packages/autonomous-runtime/dist/inbox.js +212 -0
- package/packages/autonomous-runtime/dist/inbox.js.map +1 -0
- package/packages/autonomous-runtime/dist/index.d.ts +17 -0
- package/packages/autonomous-runtime/dist/index.d.ts.map +1 -0
- package/packages/autonomous-runtime/dist/index.js +17 -0
- package/packages/autonomous-runtime/dist/index.js.map +1 -0
- package/packages/autonomous-runtime/dist/lease.d.ts +78 -0
- package/packages/autonomous-runtime/dist/lease.d.ts.map +1 -0
- package/packages/autonomous-runtime/dist/lease.js +273 -0
- package/packages/autonomous-runtime/dist/lease.js.map +1 -0
- package/packages/autonomous-runtime/dist/types.d.ts +160 -0
- package/packages/autonomous-runtime/dist/types.d.ts.map +1 -0
- package/packages/autonomous-runtime/dist/types.js +31 -0
- package/packages/autonomous-runtime/dist/types.js.map +1 -0
- package/packages/autonomous-runtime/dist/worker.d.ts +63 -0
- package/packages/autonomous-runtime/dist/worker.d.ts.map +1 -0
- package/packages/autonomous-runtime/dist/worker.js +133 -0
- package/packages/autonomous-runtime/dist/worker.js.map +1 -0
- package/packages/autonomous-runtime/package.json +34 -0
- package/packages/autonomous-runtime/src/inbox.ts +266 -0
- package/packages/autonomous-runtime/src/index.ts +22 -0
- package/packages/autonomous-runtime/src/lease.ts +318 -0
- package/packages/autonomous-runtime/src/types.ts +257 -0
- package/packages/autonomous-runtime/test/autonomous-runtime.test.ts +194 -0
- package/packages/autonomous-runtime/test/inbox.test.mjs +266 -0
- package/packages/autonomous-runtime/test/inbox.test.ts +80 -0
- package/packages/autonomous-runtime/test/types.test.ts +68 -0
- package/packages/autonomous-runtime/tsconfig.json +22 -0
- package/packages/autonomous-runtime/tsconfig.tsbuildinfo +1 -0
- package/packages/privilege-broker/README.md +45 -0
- package/packages/privilege-broker/config/privileges.yaml.example +172 -0
- package/packages/privilege-broker/dist/approval.d.ts +23 -0
- package/packages/privilege-broker/dist/approval.d.ts.map +1 -0
- package/packages/privilege-broker/dist/approval.js +45 -0
- package/packages/privilege-broker/dist/approval.js.map +1 -0
- package/packages/privilege-broker/dist/audit.d.ts +38 -0
- package/packages/privilege-broker/dist/audit.d.ts.map +1 -0
- package/packages/privilege-broker/dist/audit.js +125 -0
- package/packages/privilege-broker/dist/audit.js.map +1 -0
- package/packages/privilege-broker/dist/executor.d.ts +25 -0
- package/packages/privilege-broker/dist/executor.d.ts.map +1 -0
- package/packages/privilege-broker/dist/executor.js +83 -0
- package/packages/privilege-broker/dist/executor.js.map +1 -0
- package/packages/privilege-broker/dist/index.d.ts +30 -0
- package/packages/privilege-broker/dist/index.d.ts.map +1 -0
- package/packages/privilege-broker/dist/index.js +5 -0
- package/packages/privilege-broker/dist/index.js.map +1 -0
- package/packages/privilege-broker/dist/registry.d.ts +15 -0
- package/packages/privilege-broker/dist/registry.d.ts.map +1 -0
- package/packages/privilege-broker/dist/registry.js +76 -0
- package/packages/privilege-broker/dist/registry.js.map +1 -0
- package/packages/privilege-broker/dist/types.d.ts +77 -0
- package/packages/privilege-broker/dist/types.d.ts.map +1 -0
- package/packages/privilege-broker/dist/types.js +11 -0
- package/packages/privilege-broker/dist/types.js.map +1 -0
- package/packages/privilege-broker/package.json +35 -0
- package/packages/privilege-broker/src/approval.ts +70 -0
- package/packages/privilege-broker/src/audit.ts +142 -0
- package/packages/privilege-broker/src/executor.ts +110 -0
- package/packages/privilege-broker/src/index.ts +46 -0
- package/packages/privilege-broker/src/registry.ts +98 -0
- package/packages/privilege-broker/src/types.ts +105 -0
- package/packages/privilege-broker/tsconfig.json +22 -0
- package/packages/privilege-broker/tsconfig.tsbuildinfo +1 -0
- package/packages/scheduler-adapter/README.md +36 -0
- package/packages/scheduler-adapter/dist/cron.d.ts +21 -0
- package/packages/scheduler-adapter/dist/cron.d.ts.map +1 -0
- package/packages/scheduler-adapter/dist/cron.js +116 -0
- package/packages/scheduler-adapter/dist/cron.js.map +1 -0
- package/packages/scheduler-adapter/dist/index.d.ts +9 -0
- package/packages/scheduler-adapter/dist/index.d.ts.map +1 -0
- package/packages/scheduler-adapter/dist/index.js +8 -0
- package/packages/scheduler-adapter/dist/index.js.map +1 -0
- package/packages/scheduler-adapter/dist/interface.d.ts +61 -0
- package/packages/scheduler-adapter/dist/interface.d.ts.map +1 -0
- package/packages/scheduler-adapter/dist/interface.js +2 -0
- package/packages/scheduler-adapter/dist/interface.js.map +1 -0
- package/packages/scheduler-adapter/dist/internal.d.ts +30 -0
- package/packages/scheduler-adapter/dist/internal.d.ts.map +1 -0
- package/packages/scheduler-adapter/dist/internal.js +82 -0
- package/packages/scheduler-adapter/dist/internal.js.map +1 -0
- package/packages/scheduler-adapter/dist/systemd.d.ts +31 -0
- package/packages/scheduler-adapter/dist/systemd.d.ts.map +1 -0
- package/packages/scheduler-adapter/dist/systemd.js +203 -0
- package/packages/scheduler-adapter/dist/systemd.js.map +1 -0
- package/packages/scheduler-adapter/package.json +32 -0
- package/packages/scheduler-adapter/src/cron.ts +123 -0
- package/packages/scheduler-adapter/src/index.ts +9 -0
- package/packages/scheduler-adapter/src/interface.ts +61 -0
- package/packages/scheduler-adapter/src/internal.ts +99 -0
- package/packages/scheduler-adapter/src/systemd.ts +221 -0
- package/packages/scheduler-adapter/tsconfig.json +22 -0
- package/packages/scheduler-adapter/tsconfig.tsbuildinfo +1 -0
- package/packages/types/dist/ai-providers.d.ts +0 -36
- package/packages/types/dist/ai-providers.d.ts.map +0 -1
- package/packages/types/dist/ai-providers.js +0 -66
- package/packages/types/dist/ai-providers.js.map +0 -1
package/package.json
CHANGED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Autonomous Runtime — RFC-0101
|
|
2
|
+
|
|
3
|
+
Task Inbox, Task Lease, and worker supervision for autonomous post-session execution.
|
|
4
|
+
|
|
5
|
+
## Package
|
|
6
|
+
|
|
7
|
+
`@pi-harness/autonomous-runtime`
|
|
8
|
+
|
|
9
|
+
## Concepts
|
|
10
|
+
|
|
11
|
+
### Task Inbox
|
|
12
|
+
|
|
13
|
+
Durable queue of tasks submitted by the harness master planner. Survives worker crashes, host reboots, and provider quota exhaustion.
|
|
14
|
+
|
|
15
|
+
### Task Lease
|
|
16
|
+
|
|
17
|
+
Atomic exclusive claim on a task. Guarantees **single-execution** under crash recovery. Other workers skip a leased task.
|
|
18
|
+
|
|
19
|
+
### Worker
|
|
20
|
+
|
|
21
|
+
Supervised process that reads from the inbox, claims tasks via leases, executes, and reports results.
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
import { TaskInbox, TaskLeaseManager, WORKER_ROOT } from "@pi-harness/autonomous-runtime";
|
|
27
|
+
|
|
28
|
+
const inbox = new TaskInbox();
|
|
29
|
+
const leaseMgr = new TaskLeaseManager();
|
|
30
|
+
|
|
31
|
+
// Submit a task
|
|
32
|
+
await inbox.submit({
|
|
33
|
+
title: "Fix login bug",
|
|
34
|
+
description: "Users cannot log in with SSO",
|
|
35
|
+
capability: "write",
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Worker: claim and work
|
|
39
|
+
const task = await inbox.claimNext("worker-1", leaseMgr);
|
|
40
|
+
if (task) {
|
|
41
|
+
// ... do work ...
|
|
42
|
+
await inbox.complete(task.id, { success: true });
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Status
|
|
47
|
+
|
|
48
|
+
**Phase 1 done.** Phases 2–10 pending implementation.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { TaskRecord, TaskStatus, TaskEvent } from "./types.js";
|
|
2
|
+
export declare class InboxError extends Error {
|
|
3
|
+
constructor(msg: string);
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Manages the append-only task inbox at `~/.pi/harness/inbox/tasks.jsonl`.
|
|
7
|
+
*
|
|
8
|
+
* Storage layout:
|
|
9
|
+
* ```
|
|
10
|
+
* ~/.pi/harness/inbox/
|
|
11
|
+
* ├── tasks.jsonl # append-only log (one JSON line per task)
|
|
12
|
+
* ├── claimed/ # active leases (one JSON file per task)
|
|
13
|
+
* └── BACKLOG.md # human-friendly authoring surface (optional)
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Operations are:
|
|
17
|
+
* - **append** — append a new task to tasks.jsonl
|
|
18
|
+
* - **list** — read all tasks, filterable by status
|
|
19
|
+
* - **transition** — update a task's status in-place (rewrite)
|
|
20
|
+
* - **get** — read one task by id
|
|
21
|
+
* - **reindex** — compact tasks.jsonl by rewriting it from in-memory state
|
|
22
|
+
*/
|
|
23
|
+
export declare class TaskInbox {
|
|
24
|
+
private readonly tasksPath;
|
|
25
|
+
private readonly inboxDir;
|
|
26
|
+
private _cache;
|
|
27
|
+
constructor(options?: {
|
|
28
|
+
tasksPath?: string;
|
|
29
|
+
inboxDir?: string;
|
|
30
|
+
});
|
|
31
|
+
/** Ensure the inbox directory exists. Call before any write. */
|
|
32
|
+
ensureDir(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Append a new task to tasks.jsonl.
|
|
35
|
+
* The task is validated before writing. Duplicate ids are rejected.
|
|
36
|
+
*
|
|
37
|
+
* @throws {InboxError} if the task id already exists or validation fails
|
|
38
|
+
*/
|
|
39
|
+
append(task: TaskRecord): void;
|
|
40
|
+
/**
|
|
41
|
+
* Read all tasks from tasks.jsonl.
|
|
42
|
+
* Results are sorted by priority ASC then createdAt ASC (oldest first).
|
|
43
|
+
*
|
|
44
|
+
* @param filter Optionally filter by status. If omitted, returns all.
|
|
45
|
+
*/
|
|
46
|
+
list(filter?: {
|
|
47
|
+
status?: TaskStatus | TaskStatus[];
|
|
48
|
+
}): TaskRecord[];
|
|
49
|
+
/** Retrieve a single task by id, or null if not found. */
|
|
50
|
+
get(id: string): TaskRecord | null;
|
|
51
|
+
/**
|
|
52
|
+
* Update a task's status in-place inside tasks.jsonl.
|
|
53
|
+
*
|
|
54
|
+
* Uses read→parse→update→rewrite to avoid corrupting the JSONL file.
|
|
55
|
+
* The rewrite is atomic (write-tmp-then-rename).
|
|
56
|
+
*
|
|
57
|
+
* @param taskId The id of the task to transition
|
|
58
|
+
* @param newStatus The target status
|
|
59
|
+
* @param extra Optional additional fields to merge into the task record
|
|
60
|
+
* @param event Optional TaskEvent to append to the history
|
|
61
|
+
* @throws {InboxError} if the task does not exist
|
|
62
|
+
*/
|
|
63
|
+
transition(taskId: string, newStatus: TaskStatus, extra?: Partial<TaskRecord>, event?: TaskEvent): TaskRecord;
|
|
64
|
+
/** Convenience: mark a task as completed with a result. */
|
|
65
|
+
complete(taskId: string, result: TaskRecord["result"]): TaskRecord;
|
|
66
|
+
/** Convenience: mark a task as failed with a reason. */
|
|
67
|
+
fail(taskId: string, reason: string): TaskRecord;
|
|
68
|
+
/** Rewrite tasks.jsonl from the given task list. */
|
|
69
|
+
private _rewriteAll;
|
|
70
|
+
/** Force a full reindex. Call after manual edits to tasks.jsonl. */
|
|
71
|
+
reindex(): void;
|
|
72
|
+
/** Return counts of tasks grouped by status. */
|
|
73
|
+
stats(): Record<TaskStatus, number>;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=inbox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox.d.ts","sourceRoot":"","sources":["../src/inbox.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAKpE,qBAAa,UAAW,SAAQ,KAAK;IACpC,YAAY,GAAG,EAAE,MAAM,EAGtB;CACD;AAID;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,SAAS;IACrB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,MAAM,CAA6B;IAE3C,YAAY,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,EAGlE;IAED,gEAAgE;IAChE,SAAS,IAAI,IAAI,CAIhB;IAID;;;;;OAKG;IACH,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAc7B;IAID;;;;;OAKG;IACH,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,UAAU,GAAG,UAAU,EAAE,CAAA;KAAE,GAAG,UAAU,EAAE,CAoClE;IAID,0DAA0D;IAC1D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAGjC;IAID;;;;;;;;;;;OAWG;IACH,UAAU,CACT,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,UAAU,EACrB,KAAK,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,EAC3B,KAAK,CAAC,EAAE,SAAS,GACf,UAAU,CAqCZ;IAID,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,QAAQ,CAAC,GAAG,UAAU,CAWjE;IAED,wDAAwD;IACxD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAe/C;IAID,oDAAoD;IACpD,OAAO,CAAC,WAAW;IAUnB,oEAAoE;IACpE,OAAO,IAAI,IAAI,CAKd;IAID,gDAAgD;IAChD,KAAK,IAAI,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,CAOlC;CACD"}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Inbox — RFC-0101 §2
|
|
3
|
+
*
|
|
4
|
+
* Append-only durable store for TaskRecords backed by `tasks.jsonl`.
|
|
5
|
+
* One JSONL line per task — easy to tail, grep, and replay.
|
|
6
|
+
*/
|
|
7
|
+
import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync, } from "node:fs";
|
|
8
|
+
import { getInboxDir, getTasksPath } from "./types.js";
|
|
9
|
+
// ─── Errors ───────────────────────────────────────────────────────────────────
|
|
10
|
+
export class InboxError extends Error {
|
|
11
|
+
constructor(msg) {
|
|
12
|
+
super(`[InboxError] ${msg}`);
|
|
13
|
+
this.name = "InboxError";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
// ─── TaskInbox ────────────────────────────────────────────────────────────────
|
|
17
|
+
/**
|
|
18
|
+
* Manages the append-only task inbox at `~/.pi/harness/inbox/tasks.jsonl`.
|
|
19
|
+
*
|
|
20
|
+
* Storage layout:
|
|
21
|
+
* ```
|
|
22
|
+
* ~/.pi/harness/inbox/
|
|
23
|
+
* ├── tasks.jsonl # append-only log (one JSON line per task)
|
|
24
|
+
* ├── claimed/ # active leases (one JSON file per task)
|
|
25
|
+
* └── BACKLOG.md # human-friendly authoring surface (optional)
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* Operations are:
|
|
29
|
+
* - **append** — append a new task to tasks.jsonl
|
|
30
|
+
* - **list** — read all tasks, filterable by status
|
|
31
|
+
* - **transition** — update a task's status in-place (rewrite)
|
|
32
|
+
* - **get** — read one task by id
|
|
33
|
+
* - **reindex** — compact tasks.jsonl by rewriting it from in-memory state
|
|
34
|
+
*/
|
|
35
|
+
export class TaskInbox {
|
|
36
|
+
tasksPath;
|
|
37
|
+
inboxDir;
|
|
38
|
+
_cache = null;
|
|
39
|
+
constructor(options = {}) {
|
|
40
|
+
this.inboxDir = options.inboxDir ?? getInboxDir();
|
|
41
|
+
this.tasksPath = options.tasksPath ?? getTasksPath();
|
|
42
|
+
}
|
|
43
|
+
/** Ensure the inbox directory exists. Call before any write. */
|
|
44
|
+
ensureDir() {
|
|
45
|
+
if (!existsSync(this.inboxDir)) {
|
|
46
|
+
mkdirSync(this.inboxDir, { recursive: true });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// ─── append ──────────────────────────────────────────────────────────────
|
|
50
|
+
/**
|
|
51
|
+
* Append a new task to tasks.jsonl.
|
|
52
|
+
* The task is validated before writing. Duplicate ids are rejected.
|
|
53
|
+
*
|
|
54
|
+
* @throws {InboxError} if the task id already exists or validation fails
|
|
55
|
+
*/
|
|
56
|
+
append(task) {
|
|
57
|
+
this.ensureDir();
|
|
58
|
+
// Guard against duplicate ids
|
|
59
|
+
const existing = this.list().find((t) => t.id === task.id);
|
|
60
|
+
if (existing) {
|
|
61
|
+
throw new InboxError(`Task ${task.id} already exists in inbox (status=${existing.status})`);
|
|
62
|
+
}
|
|
63
|
+
const line = JSON.stringify(task) + "\n";
|
|
64
|
+
appendFileSync(this.tasksPath, line, "utf8");
|
|
65
|
+
this._cache = null; // invalidate
|
|
66
|
+
}
|
|
67
|
+
// ─── list ─────────────────────────────────────────────────────────────────
|
|
68
|
+
/**
|
|
69
|
+
* Read all tasks from tasks.jsonl.
|
|
70
|
+
* Results are sorted by priority ASC then createdAt ASC (oldest first).
|
|
71
|
+
*
|
|
72
|
+
* @param filter Optionally filter by status. If omitted, returns all.
|
|
73
|
+
*/
|
|
74
|
+
list(filter) {
|
|
75
|
+
if (!existsSync(this.tasksPath)) {
|
|
76
|
+
return [];
|
|
77
|
+
}
|
|
78
|
+
const raw = readFileSync(this.tasksPath, "utf8");
|
|
79
|
+
const tasks = [];
|
|
80
|
+
for (const line of raw.split("\n")) {
|
|
81
|
+
const trimmed = line.trim();
|
|
82
|
+
if (!trimmed)
|
|
83
|
+
continue;
|
|
84
|
+
try {
|
|
85
|
+
const task = JSON.parse(trimmed);
|
|
86
|
+
tasks.push(task);
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Corrupt line — skip but don't fail the whole list
|
|
90
|
+
console.warn(`[TaskInbox] Skipping corrupt line in ${this.tasksPath}`);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Filter by status
|
|
94
|
+
let filtered = tasks;
|
|
95
|
+
if (filter?.status !== undefined) {
|
|
96
|
+
const statuses = Array.isArray(filter.status)
|
|
97
|
+
? filter.status
|
|
98
|
+
: [filter.status];
|
|
99
|
+
filtered = tasks.filter((t) => statuses.includes(t.status));
|
|
100
|
+
}
|
|
101
|
+
// Sort: priority ASC, then createdAt ASC
|
|
102
|
+
filtered.sort((a, b) => {
|
|
103
|
+
if (a.priority !== b.priority)
|
|
104
|
+
return a.priority - b.priority;
|
|
105
|
+
return a.createdAt.localeCompare(b.createdAt);
|
|
106
|
+
});
|
|
107
|
+
return filtered;
|
|
108
|
+
}
|
|
109
|
+
// ─── get ─────────────────────────────────────────────────────────────────
|
|
110
|
+
/** Retrieve a single task by id, or null if not found. */
|
|
111
|
+
get(id) {
|
|
112
|
+
const tasks = this.list();
|
|
113
|
+
return tasks.find((t) => t.id === id) ?? null;
|
|
114
|
+
}
|
|
115
|
+
// ─── transition ──────────────────────────────────────────────────────────
|
|
116
|
+
/**
|
|
117
|
+
* Update a task's status in-place inside tasks.jsonl.
|
|
118
|
+
*
|
|
119
|
+
* Uses read→parse→update→rewrite to avoid corrupting the JSONL file.
|
|
120
|
+
* The rewrite is atomic (write-tmp-then-rename).
|
|
121
|
+
*
|
|
122
|
+
* @param taskId The id of the task to transition
|
|
123
|
+
* @param newStatus The target status
|
|
124
|
+
* @param extra Optional additional fields to merge into the task record
|
|
125
|
+
* @param event Optional TaskEvent to append to the history
|
|
126
|
+
* @throws {InboxError} if the task does not exist
|
|
127
|
+
*/
|
|
128
|
+
transition(taskId, newStatus, extra, event) {
|
|
129
|
+
if (!existsSync(this.tasksPath)) {
|
|
130
|
+
throw new InboxError(`tasks.jsonl does not exist at ${this.tasksPath}`);
|
|
131
|
+
}
|
|
132
|
+
const tasks = this.list();
|
|
133
|
+
const idx = tasks.findIndex((t) => t.id === taskId);
|
|
134
|
+
if (idx === -1) {
|
|
135
|
+
throw new InboxError(`Task ${taskId} not found in inbox`);
|
|
136
|
+
}
|
|
137
|
+
const updated = {
|
|
138
|
+
...tasks[idx],
|
|
139
|
+
...extra,
|
|
140
|
+
status: newStatus,
|
|
141
|
+
updatedAt: new Date().toISOString(),
|
|
142
|
+
history: event
|
|
143
|
+
? [...tasks[idx].history, event]
|
|
144
|
+
: [
|
|
145
|
+
...tasks[idx].history,
|
|
146
|
+
{
|
|
147
|
+
ts: new Date().toISOString(),
|
|
148
|
+
kind: "transitioned",
|
|
149
|
+
payload: { from: tasks[idx].status, to: newStatus },
|
|
150
|
+
},
|
|
151
|
+
],
|
|
152
|
+
};
|
|
153
|
+
// Rewrite tasks.jsonl atomically
|
|
154
|
+
this._rewriteAll([
|
|
155
|
+
...tasks.slice(0, idx),
|
|
156
|
+
updated,
|
|
157
|
+
...tasks.slice(idx + 1),
|
|
158
|
+
]);
|
|
159
|
+
this._cache = null;
|
|
160
|
+
return updated;
|
|
161
|
+
}
|
|
162
|
+
// ─── markDone / markFailed ───────────────────────────────────────────────
|
|
163
|
+
/** Convenience: mark a task as completed with a result. */
|
|
164
|
+
complete(taskId, result) {
|
|
165
|
+
return this.transition(taskId, "completed", { result }, {
|
|
166
|
+
ts: new Date().toISOString(),
|
|
167
|
+
kind: "completed",
|
|
168
|
+
payload: { result },
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
/** Convenience: mark a task as failed with a reason. */
|
|
172
|
+
fail(taskId, reason) {
|
|
173
|
+
const task = this.get(taskId);
|
|
174
|
+
const attempts = (task?.attempts ?? 0) + 1;
|
|
175
|
+
const newStatus = attempts >= (task?.maxAttempts ?? 3) ? "dead_letter" : "retrying";
|
|
176
|
+
return this.transition(taskId, newStatus, { failureReason: reason, attempts }, {
|
|
177
|
+
ts: new Date().toISOString(),
|
|
178
|
+
kind: newStatus === "dead_letter" ? "dead_lettered" : "failed",
|
|
179
|
+
payload: { reason, attempts },
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
// ─── reindex ─────────────────────────────────────────────────────────────
|
|
183
|
+
/** Rewrite tasks.jsonl from the given task list. */
|
|
184
|
+
_rewriteAll(tasks) {
|
|
185
|
+
const tmp = `${this.tasksPath}.tmp`;
|
|
186
|
+
const content = tasks.map((t) => JSON.stringify(t)).join("\n") + "\n";
|
|
187
|
+
writeFileSync(tmp, content, "utf8");
|
|
188
|
+
// Atomic rename (POSIX guarantees atomicity)
|
|
189
|
+
// Bun/Node will use the native rename which is atomic on POSIX
|
|
190
|
+
const { renameSync } = require("node:fs");
|
|
191
|
+
renameSync(tmp, this.tasksPath);
|
|
192
|
+
}
|
|
193
|
+
/** Force a full reindex. Call after manual edits to tasks.jsonl. */
|
|
194
|
+
reindex() {
|
|
195
|
+
if (!existsSync(this.tasksPath))
|
|
196
|
+
return;
|
|
197
|
+
const tasks = this.list(); // reads and validates
|
|
198
|
+
this._rewriteAll(tasks);
|
|
199
|
+
this._cache = null;
|
|
200
|
+
}
|
|
201
|
+
// ─── count ───────────────────────────────────────────────────────────────
|
|
202
|
+
/** Return counts of tasks grouped by status. */
|
|
203
|
+
stats() {
|
|
204
|
+
const tasks = this.list();
|
|
205
|
+
const counts = {};
|
|
206
|
+
for (const t of tasks) {
|
|
207
|
+
counts[t.status] = (counts[t.status] ?? 0) + 1;
|
|
208
|
+
}
|
|
209
|
+
return counts;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=inbox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inbox.js","sourceRoot":"","sources":["../src/inbox.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Autonomous Operations Runtime — Public API
|
|
3
|
+
*
|
|
4
|
+
* Phase 1 exports (RFC-0101 §1-2):
|
|
5
|
+
* - TaskRecord, TaskLease, TaskEvent, TaskStatus, CapabilityName, ApprovalClass types
|
|
6
|
+
* - TaskInbox: append, list, get, transition, complete, fail
|
|
7
|
+
* - LeaseManager: claim, heartbeat, release, reap, recoverOnStartup
|
|
8
|
+
*
|
|
9
|
+
* Phase 2+ exports (added as implemented):
|
|
10
|
+
* - Worker lifecycle (worker.ts)
|
|
11
|
+
* - Privilege broker (privilege-broker package)
|
|
12
|
+
* - Scheduler adapter (scheduler-adapter package)
|
|
13
|
+
*/
|
|
14
|
+
export * from "./types.js";
|
|
15
|
+
export { TaskInbox, InboxError } from "./inbox.js";
|
|
16
|
+
export { LeaseManager, LeaseError, DEFAULT_LEASE_TTL_MS, HEARTBEAT_INTERVAL_MS, HEARTBEAT_EXTENSION_MS, } from "./lease.js";
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EACN,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,GACtB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Autonomous Operations Runtime — Public API
|
|
3
|
+
*
|
|
4
|
+
* Phase 1 exports (RFC-0101 §1-2):
|
|
5
|
+
* - TaskRecord, TaskLease, TaskEvent, TaskStatus, CapabilityName, ApprovalClass types
|
|
6
|
+
* - TaskInbox: append, list, get, transition, complete, fail
|
|
7
|
+
* - LeaseManager: claim, heartbeat, release, reap, recoverOnStartup
|
|
8
|
+
*
|
|
9
|
+
* Phase 2+ exports (added as implemented):
|
|
10
|
+
* - Worker lifecycle (worker.ts)
|
|
11
|
+
* - Privilege broker (privilege-broker package)
|
|
12
|
+
* - Scheduler adapter (scheduler-adapter package)
|
|
13
|
+
*/
|
|
14
|
+
export * from "./types.js";
|
|
15
|
+
export { TaskInbox, InboxError } from "./inbox.js";
|
|
16
|
+
export { LeaseManager, LeaseError, DEFAULT_LEASE_TTL_MS, HEARTBEAT_INTERVAL_MS, HEARTBEAT_EXTENSION_MS, } from "./lease.js";
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EACN,YAAY,EACZ,UAAU,EACV,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,GACtB,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { TaskLease } from "./types.js";
|
|
2
|
+
export declare class LeaseError extends Error {
|
|
3
|
+
constructor(msg: string);
|
|
4
|
+
}
|
|
5
|
+
/** Default lease duration before heartbeat extension is required. */
|
|
6
|
+
export declare const DEFAULT_LEASE_TTL_MS = 30000;
|
|
7
|
+
/** Heartbeat interval sent by the worker. */
|
|
8
|
+
export declare const HEARTBEAT_INTERVAL_MS = 5000;
|
|
9
|
+
/** Default worker heartbeat interval extension. */
|
|
10
|
+
export declare const HEARTBEAT_EXTENSION_MS = 30000;
|
|
11
|
+
export interface LeaseOptions {
|
|
12
|
+
leasesDir?: string;
|
|
13
|
+
/** TTL in ms for new leases. Default: DEFAULT_LEASE_TTL_MS */
|
|
14
|
+
leaseTtlMs?: number;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Manages task leases on disk using atomic write-tmp-then-rename.
|
|
18
|
+
*/
|
|
19
|
+
export declare class LeaseManager {
|
|
20
|
+
private readonly leasesDir;
|
|
21
|
+
private readonly leaseTtlMs;
|
|
22
|
+
constructor(options?: LeaseOptions);
|
|
23
|
+
/** Ensure the claimed/ directory exists. */
|
|
24
|
+
ensureDir(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Atomically claim a task for a worker.
|
|
27
|
+
*
|
|
28
|
+
* Algorithm:
|
|
29
|
+
* 1. Write lease to a temp file in the same directory (same filesystem → fast rename)
|
|
30
|
+
* 2. Attempt atomic rename to `claimed/<taskId>.lease.json`
|
|
31
|
+
* 3. If rename fails (EEXIST) → another worker won → return null
|
|
32
|
+
*
|
|
33
|
+
* @param taskId The task to claim
|
|
34
|
+
* @param workerId The worker claiming it
|
|
35
|
+
* @param attempt Which attempt number (for retry)
|
|
36
|
+
* @returns The TaskLease if won, null if another worker claimed first
|
|
37
|
+
*/
|
|
38
|
+
claim(taskId: string, workerId: string, attempt?: number): TaskLease | null;
|
|
39
|
+
/**
|
|
40
|
+
* Extend a lease's expiry time.
|
|
41
|
+
* Only the worker that holds the lease can extend it.
|
|
42
|
+
*
|
|
43
|
+
* @returns Updated lease, or null if the lease no longer exists
|
|
44
|
+
*/
|
|
45
|
+
heartbeat(taskId: string, workerId: string): TaskLease | null;
|
|
46
|
+
/**
|
|
47
|
+
* Explicitly release a lease (task completed or failed without retry).
|
|
48
|
+
*/
|
|
49
|
+
release(taskId: string, workerId: string): void;
|
|
50
|
+
/** Read a lease by taskId. Returns null if not found. */
|
|
51
|
+
get(taskId: string): TaskLease | null;
|
|
52
|
+
/** Check if a lease has expired (expiresAt is in the past). */
|
|
53
|
+
isExpired(lease: TaskLease): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Scan all leases and return the ones that have expired.
|
|
56
|
+
* Does NOT remove them — call reapAndRelease() to remove atomically.
|
|
57
|
+
*/
|
|
58
|
+
reap(): TaskLease[];
|
|
59
|
+
/**
|
|
60
|
+
* Release all expired leases and return their taskIds.
|
|
61
|
+
* Idempotent — safe to call on every heartbeat interval.
|
|
62
|
+
*/
|
|
63
|
+
reapAndRelease(): string[];
|
|
64
|
+
/**
|
|
65
|
+
* On worker startup, release any leases held by dead workers.
|
|
66
|
+
* A lease is orphaned if its worker has not re-claimed it since startup.
|
|
67
|
+
*
|
|
68
|
+
* Strategy: remove all leases whose expiresAt has passed.
|
|
69
|
+
* Safe because the next claim will succeed (no other worker holds it).
|
|
70
|
+
*/
|
|
71
|
+
recoverOnStartup(): string[];
|
|
72
|
+
/** Return all active (non-expired) leases. */
|
|
73
|
+
listActive(): TaskLease[];
|
|
74
|
+
private _leasePath;
|
|
75
|
+
private _writeLease;
|
|
76
|
+
private _removeLease;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=lease.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lease.d.ts","sourceRoot":"","sources":["../src/lease.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAK5C,qBAAa,UAAW,SAAQ,KAAK;IACpC,YAAY,GAAG,EAAE,MAAM,EAGtB;CACD;AAID,qEAAqE;AACrE,eAAO,MAAM,oBAAoB,QAAS,CAAC;AAE3C,6CAA6C;AAC7C,eAAO,MAAM,qBAAqB,OAAQ,CAAC;AAE3C,mDAAmD;AACnD,eAAO,MAAM,sBAAsB,QAAS,CAAC;AAI7C,MAAM,WAAW,YAAY;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,qBAAa,YAAY;IACxB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IAEpC,YAAY,OAAO,GAAE,YAAiB,EAGrC;IAED,4CAA4C;IAC5C,SAAS,IAAI,IAAI,CAIhB;IAID;;;;;;;;;;;;OAYG;IACH,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAI,GAAG,SAAS,GAAG,IAAI,CA8CrE;IAID;;;;;OAKG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAiB5D;IAID;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAS9C;IAID,yDAAyD;IACzD,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAQpC;IAID,+DAA+D;IAC/D,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAEnC;IAID;;;OAGG;IACH,IAAI,IAAI,SAAS,EAAE,CAwBlB;IAED;;;OAGG;IACH,cAAc,IAAI,MAAM,EAAE,CAYzB;IAID;;;;;;OAMG;IACH,gBAAgB,IAAI,MAAM,EAAE,CAE3B;IAID,8CAA8C;IAC9C,UAAU,IAAI,SAAS,EAAE,CAwBxB;IAID,OAAO,CAAC,UAAU;IAIlB,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,YAAY;CAIpB"}
|