@openacme/tasks 0.4.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.
- package/LICENSE +21 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/ports.d.ts +116 -0
- package/dist/ports.d.ts.map +1 -0
- package/dist/ports.js +43 -0
- package/dist/ports.js.map +1 -0
- package/dist/prompt-render.d.ts +19 -0
- package/dist/prompt-render.d.ts.map +1 -0
- package/dist/prompt-render.js +204 -0
- package/dist/prompt-render.js.map +1 -0
- package/dist/recurrence.d.ts +21 -0
- package/dist/recurrence.d.ts.map +1 -0
- package/dist/recurrence.js +117 -0
- package/dist/recurrence.js.map +1 -0
- package/dist/store.d.ts +156 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +849 -0
- package/dist/store.js.map +1 -0
- package/dist/types.d.ts +115 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +75 -0
- package/dist/types.js.map +1 -0
- package/package.json +50 -0
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File-backed task store. One markdown file per task at
|
|
3
|
+
* `<tasksDir>/<id>.md` — YAML frontmatter for structured fields, body
|
|
4
|
+
* for the agent-readable description and accumulated notes.
|
|
5
|
+
*
|
|
6
|
+
* Concurrency: per-task in-process async mutex serializes
|
|
7
|
+
* read-modify-write of a single id. Each operation only acquires one
|
|
8
|
+
* mutex at a time — fan-out paths (`unblockDependents`, `delete --force`)
|
|
9
|
+
* iterate sequentially without holding multiple locks, so there's no
|
|
10
|
+
* deadlock surface.
|
|
11
|
+
*
|
|
12
|
+
* The store enforces:
|
|
13
|
+
* - cycle-free `depends_on` graph (DFS on write).
|
|
14
|
+
* - status auto-transition between `open` and `blocked` based on deps.
|
|
15
|
+
* - at most one `in_progress` per `session_id`.
|
|
16
|
+
* - inputs validated against the frontmatter schema at the write
|
|
17
|
+
* boundary so a bad input can't land malformed YAML on disk.
|
|
18
|
+
*
|
|
19
|
+
* Status state machine (legal transitions only — anything else is a bug):
|
|
20
|
+
*
|
|
21
|
+
* open ─────► in_progress (assignee claims via update; requires deps satisfied)
|
|
22
|
+
* open ─────► blocked (auto, when deps regress)
|
|
23
|
+
* open ─────► done/canceled (terminal)
|
|
24
|
+
*
|
|
25
|
+
* in_progress ──► blocked (via TaskStore.park, by scheduler on
|
|
26
|
+
* timeout/error or watchdog)
|
|
27
|
+
* in_progress ──► done/canceled (terminal; assignee or human)
|
|
28
|
+
*
|
|
29
|
+
* blocked ──► open (auto, when deps satisfy via unblockDependents)
|
|
30
|
+
* blocked ──► done/canceled (terminal; bypasses in_progress)
|
|
31
|
+
*
|
|
32
|
+
* done ────► open (ONLY for recurring tasks — self-reset
|
|
33
|
+
* to next fire. Non-recurring done is
|
|
34
|
+
* terminal.)
|
|
35
|
+
* canceled ──► (nothing) (kill switch; never resets, even for recurring)
|
|
36
|
+
*
|
|
37
|
+
* Adding a new status: extend `TASK_STATUSES`, then audit `computeAutoStatus`,
|
|
38
|
+
* the closing branches in `update()`, the recurring self-reset, scheduler's
|
|
39
|
+
* `park` / `watchdogPark`, `hasAnyActive`, and prompt rendering.
|
|
40
|
+
*/
|
|
41
|
+
import { type Task, type TaskCreate, type TaskListFilter, type TaskUpdate } from "./types.js";
|
|
42
|
+
import type { Comment, CommentInput, CommentListOptions, CommentStorePort, EventStorePort, TaskEvent } from "./ports.js";
|
|
43
|
+
export declare class TaskStoreError extends Error {
|
|
44
|
+
readonly code: string;
|
|
45
|
+
constructor(code: string, message: string);
|
|
46
|
+
}
|
|
47
|
+
export type OnChangeFn = () => void;
|
|
48
|
+
export interface TaskStoreOptions {
|
|
49
|
+
/** Optional: discussion thread store. If absent, comment methods no-op. */
|
|
50
|
+
commentStore?: CommentStorePort;
|
|
51
|
+
/** Optional: event log store. If absent, no events emitted. */
|
|
52
|
+
eventStore?: EventStorePort;
|
|
53
|
+
/** Optional: session existence check. When provided, create/update
|
|
54
|
+
* reject task bindings to a session id the check returns false for —
|
|
55
|
+
* prevents agents from hallucinating session uuids that would become
|
|
56
|
+
* scheduler zombies. */
|
|
57
|
+
validateSession?: (id: string) => boolean;
|
|
58
|
+
}
|
|
59
|
+
export declare class TaskStore {
|
|
60
|
+
readonly tasksDir: string;
|
|
61
|
+
private readonly inFlight;
|
|
62
|
+
private onChange;
|
|
63
|
+
private readonly commentStore;
|
|
64
|
+
private readonly eventStore;
|
|
65
|
+
private readonly validateSession;
|
|
66
|
+
constructor(tasksDir: string, options?: TaskStoreOptions);
|
|
67
|
+
setOnChange(fn: OnChangeFn | null): void;
|
|
68
|
+
filePath(id: string): string;
|
|
69
|
+
get(id: string): Task | null;
|
|
70
|
+
list(filter?: TaskListFilter): Task[];
|
|
71
|
+
byAssignee(agentId: string): Task[];
|
|
72
|
+
byCreator(agentId: string): Task[];
|
|
73
|
+
byParent(parentId: string): Task[];
|
|
74
|
+
dependentsOf(id: string): Task[];
|
|
75
|
+
/** Tasks bound to `sessionId` in queue order (deps + start_at + created_at). */
|
|
76
|
+
queueFor(sessionId: string, now?: Date): Task[];
|
|
77
|
+
/** Top of `queueFor` excluding already in_progress / done / canceled. */
|
|
78
|
+
nextEligibleFor(sessionId: string, now?: Date): Task | null;
|
|
79
|
+
create(input: TaskCreate): Promise<Task>;
|
|
80
|
+
update(id: string, patch: TaskUpdate, opts?: {
|
|
81
|
+
actor?: string | null;
|
|
82
|
+
}): Promise<Task>;
|
|
83
|
+
delete(id: string, opts?: {
|
|
84
|
+
force?: boolean;
|
|
85
|
+
actor?: string | null;
|
|
86
|
+
}): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Restart sweep: any task `in_progress` whose `updated_at` is older
|
|
89
|
+
* than the staleness threshold is reset to `open`. Returns the ids
|
|
90
|
+
* that were reset.
|
|
91
|
+
*/
|
|
92
|
+
/**
|
|
93
|
+
* Park a task: flip to `blocked` with a future `start_at` and append
|
|
94
|
+
* a `system:scheduler` comment explaining why. The scheduler uses this
|
|
95
|
+
* for both failure attribution (`parkInProgress`) and watchdog stalls
|
|
96
|
+
* (`watchdogPark`). Single helper means the "blocked + back-off +
|
|
97
|
+
* system note" pattern lives in one place.
|
|
98
|
+
*/
|
|
99
|
+
park(input: {
|
|
100
|
+
id: string;
|
|
101
|
+
retryAt: Date;
|
|
102
|
+
reason: string;
|
|
103
|
+
}): Promise<void>;
|
|
104
|
+
sweepStale(now?: Date): Promise<string[]>;
|
|
105
|
+
/**
|
|
106
|
+
* System-prompt block for an agent. `sessionExistsFn` lets the caller
|
|
107
|
+
* treat tasks bound to a deleted session as if they were unbound.
|
|
108
|
+
*/
|
|
109
|
+
renderForPrompt(agentId: string, currentSessionId: string, sessionExistsFn: (sid: string) => boolean, now?: Date): string;
|
|
110
|
+
private latestNonSystemComment;
|
|
111
|
+
private assertDepsExist;
|
|
112
|
+
private assertNoCycle;
|
|
113
|
+
private writeFile;
|
|
114
|
+
private withMutex;
|
|
115
|
+
private fireOnChange;
|
|
116
|
+
private emitEvent;
|
|
117
|
+
/**
|
|
118
|
+
* Append a comment to the task's discussion thread. Authorship gates
|
|
119
|
+
* (assignee-only for `kind: "result"`, system-only for `kind: "system"`)
|
|
120
|
+
* live in the tool layer; the store accepts whatever it's given so
|
|
121
|
+
* automation paths can write system entries directly.
|
|
122
|
+
*/
|
|
123
|
+
addComment(input: CommentInput): Promise<Comment | null>;
|
|
124
|
+
listComments(taskId: string, opts?: CommentListOptions): Comment[];
|
|
125
|
+
latestResult(taskId: string): Comment | null;
|
|
126
|
+
commentCounts(taskIds: string[]): Map<string, number>;
|
|
127
|
+
/**
|
|
128
|
+
* Tasks this session is "involved with" — bound to the session, plus
|
|
129
|
+
* the agent's assigned/created tasks that have no session yet (those
|
|
130
|
+
* land here when they get a fresh session). Plus tasks the agent
|
|
131
|
+
* created and assigned to OTHERS — without this, the agent loses
|
|
132
|
+
* the event feed for delegated work the moment its assignee picks
|
|
133
|
+
* it up and the task gets bound to a different session.
|
|
134
|
+
*/
|
|
135
|
+
involvedTaskIds(sessionId: string, agentId: string): string[];
|
|
136
|
+
/**
|
|
137
|
+
* Fetch recent events for the given session's involvement set, since
|
|
138
|
+
* `sinceTs` (unix seconds). Empty array if no event store wired.
|
|
139
|
+
* `excludeActor` filters out events caused by that actor — used by
|
|
140
|
+
* the mid-turn injection path so the cursor and the rendered set
|
|
141
|
+
* always match (otherwise self-events get re-shown on every step).
|
|
142
|
+
*/
|
|
143
|
+
recentEventsForSession(sessionId: string, agentId: string, sinceTs: number, opts?: {
|
|
144
|
+
limit?: number;
|
|
145
|
+
excludeActor?: string;
|
|
146
|
+
}): TaskEvent[];
|
|
147
|
+
/**
|
|
148
|
+
* Format the events feed as a markdown section for the system prompt.
|
|
149
|
+
* Returns "" when there are no events to render.
|
|
150
|
+
*/
|
|
151
|
+
renderRecentActivity(sessionId: string, agentId: string, sinceTs: number, now?: Date, opts?: {
|
|
152
|
+
limit?: number;
|
|
153
|
+
excludeActor?: string;
|
|
154
|
+
}): string;
|
|
155
|
+
}
|
|
156
|
+
//# sourceMappingURL=store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|