klaus-agent 0.3.0 → 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/README.md +44 -7
- package/README.zh-CN.md +43 -6
- package/dist/compaction/compaction.d.ts +3 -1
- package/dist/compaction/compaction.js +34 -0
- package/dist/compaction/compaction.js.map +1 -1
- package/dist/compaction/types.d.ts +2 -0
- package/dist/core/agent-loop.js +4 -1
- package/dist/core/agent-loop.js.map +1 -1
- package/dist/core/agent.d.ts +6 -0
- package/dist/core/agent.js +24 -7
- package/dist/core/agent.js.map +1 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/task-graph/result-injection.d.ts +8 -0
- package/dist/task-graph/result-injection.js +26 -0
- package/dist/task-graph/result-injection.js.map +1 -0
- package/dist/task-graph/task-graph.d.ts +38 -0
- package/dist/task-graph/task-graph.js +241 -0
- package/dist/task-graph/task-graph.js.map +1 -0
- package/dist/task-graph/tools.d.ts +3 -0
- package/dist/task-graph/tools.js +106 -0
- package/dist/task-graph/tools.js.map +1 -0
- package/dist/task-graph/types.d.ts +44 -0
- package/dist/task-graph/types.js +9 -0
- package/dist/task-graph/types.js.map +1 -0
- package/package.json +1 -1
- package/src/compaction/compaction.ts +43 -1
- package/src/compaction/types.ts +3 -0
- package/src/core/agent-loop.ts +5 -1
- package/src/core/agent.ts +29 -6
- package/src/index.ts +16 -1
- package/src/task-graph/result-injection.ts +29 -0
- package/src/task-graph/task-graph.ts +270 -0
- package/src/task-graph/tools.ts +109 -0
- package/src/task-graph/types.ts +52 -0
package/dist/index.js
CHANGED
|
@@ -27,6 +27,7 @@ export function createAgent(config) {
|
|
|
27
27
|
wire: config.wire,
|
|
28
28
|
backgroundTasks: config.backgroundTasks,
|
|
29
29
|
planning: config.planning,
|
|
30
|
+
taskGraph: config.taskGraph,
|
|
30
31
|
});
|
|
31
32
|
}
|
|
32
33
|
// Re-export classes
|
|
@@ -50,7 +51,7 @@ export { ExtensionRunner } from "./extensions/runner.js";
|
|
|
50
51
|
export { discoverSkills } from "./skills/discovery.js";
|
|
51
52
|
export { loadSkill, renderSkillTemplate } from "./skills/loader.js";
|
|
52
53
|
export { MCPAdapter } from "./tools/mcp-adapter.js";
|
|
53
|
-
export { estimateTokens, shouldCompact, findCutPoint } from "./compaction/compaction.js";
|
|
54
|
+
export { estimateTokens, shouldCompact, findCutPoint, microCompact } from "./compaction/compaction.js";
|
|
54
55
|
export { calculateCost } from "./providers/shared.js";
|
|
55
56
|
export { LLMSummarizer } from "./compaction/summarizer.js";
|
|
56
57
|
export { Wire } from "./wire/wire.js";
|
|
@@ -59,5 +60,9 @@ export { createBackgroundTaskTools } from "./background/tools.js";
|
|
|
59
60
|
export { PlanningManager } from "./planning/planning-manager.js";
|
|
60
61
|
export { createPlanningTools } from "./planning/tools.js";
|
|
61
62
|
export { PlanningNagProvider } from "./planning/nag-injection.js";
|
|
63
|
+
export { TaskGraph } from "./task-graph/task-graph.js";
|
|
64
|
+
export { createTaskGraphTools } from "./task-graph/tools.js";
|
|
65
|
+
export { TaskResultInjectionProvider } from "./task-graph/result-injection.js";
|
|
62
66
|
export { PLANNING_TOOL_NAMES } from "./planning/types.js";
|
|
67
|
+
export { TASK_GRAPH_TOOL_NAMES } from "./task-graph/types.js";
|
|
63
68
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qBAAqB;AAErB,OAAO,EAAE,KAAK,EAA2C,MAAM,iBAAiB,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAoB,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { DynamicInjectionProvider, DynamicInjection } from "../injection/types.js";
|
|
2
|
+
import type { AgentMessage } from "../types.js";
|
|
3
|
+
import type { TaskGraph } from "./task-graph.js";
|
|
4
|
+
export declare class TaskResultInjectionProvider implements DynamicInjectionProvider {
|
|
5
|
+
private _graph;
|
|
6
|
+
constructor(_graph: TaskGraph);
|
|
7
|
+
getInjections(_history: AgentMessage[]): Promise<DynamicInjection[]>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Auto-inject completed background task results before each LLM call
|
|
2
|
+
export class TaskResultInjectionProvider {
|
|
3
|
+
_graph;
|
|
4
|
+
constructor(_graph) {
|
|
5
|
+
this._graph = _graph;
|
|
6
|
+
}
|
|
7
|
+
async getInjections(_history) {
|
|
8
|
+
const completed = this._graph.drainCompleted();
|
|
9
|
+
if (completed.length === 0)
|
|
10
|
+
return [];
|
|
11
|
+
const lines = completed.map((c) => {
|
|
12
|
+
const status = c.status === "completed" ? "completed" : "FAILED";
|
|
13
|
+
const unblocked = c.unblockedTasks.length > 0
|
|
14
|
+
? ` → unblocked: ${c.unblockedTasks.join(", ")}`
|
|
15
|
+
: "";
|
|
16
|
+
return `[task:${c.taskId}] ${c.subject} — ${status}: ${c.result}${unblocked}`;
|
|
17
|
+
});
|
|
18
|
+
return [
|
|
19
|
+
{
|
|
20
|
+
type: "task-results",
|
|
21
|
+
content: `<background-results>\n${lines.join("\n")}\n</background-results>`,
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=result-injection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"result-injection.js","sourceRoot":"","sources":["../../src/task-graph/result-injection.ts"],"names":[],"mappings":"AAAA,qEAAqE;AAMrE,MAAM,OAAO,2BAA2B;IAClB;IAApB,YAAoB,MAAiB;QAAjB,WAAM,GAAN,MAAM,CAAW;IAAG,CAAC;IAEzC,KAAK,CAAC,aAAa,CAAC,QAAwB;QAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAC/C,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAEtC,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAChC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;YACjE,MAAM,SAAS,GAAG,CAAC,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC;gBAC3C,CAAC,CAAC,iBAAiB,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBAChD,CAAC,CAAC,EAAE,CAAC;YACP,OAAO,SAAS,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,MAAM,MAAM,KAAK,CAAC,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QAChF,CAAC,CAAC,CAAC;QAEH,OAAO;YACL;gBACE,IAAI,EAAE,cAAc;gBACpB,OAAO,EAAE,yBAAyB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB;aAC5E;SACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { TaskNode, TaskStatus, TaskGraphConfig, CompletedTaskResult } from "./types.js";
|
|
2
|
+
export declare class TaskGraph {
|
|
3
|
+
private _tasks;
|
|
4
|
+
private _config;
|
|
5
|
+
private _completedQueue;
|
|
6
|
+
private _backgroundAborts;
|
|
7
|
+
constructor(config?: TaskGraphConfig);
|
|
8
|
+
get(id: string): TaskNode | undefined;
|
|
9
|
+
listAll(): TaskNode[];
|
|
10
|
+
/** Tasks that are pending with no unfinished blockers. */
|
|
11
|
+
listReady(): TaskNode[];
|
|
12
|
+
/** Tasks waiting on unfinished blockers. */
|
|
13
|
+
listBlocked(): TaskNode[];
|
|
14
|
+
create(subject: string, description?: string): TaskNode;
|
|
15
|
+
/** Add a dependency: `taskId` is blocked by `blockedById`. */
|
|
16
|
+
addDependency(taskId: string, blockedById: string): void;
|
|
17
|
+
update(taskId: string, fields: {
|
|
18
|
+
status?: TaskStatus;
|
|
19
|
+
owner?: string;
|
|
20
|
+
result?: string;
|
|
21
|
+
}): TaskNode;
|
|
22
|
+
/**
|
|
23
|
+
* Run an async function in the background for a task.
|
|
24
|
+
* Auto-updates task status to in_progress/completed/failed.
|
|
25
|
+
*/
|
|
26
|
+
runBackground(taskId: string, fn: (signal: AbortSignal) => Promise<string>): void;
|
|
27
|
+
abortBackground(taskId: string): boolean;
|
|
28
|
+
drainCompleted(): CompletedTaskResult[];
|
|
29
|
+
render(): string;
|
|
30
|
+
dispose(): void;
|
|
31
|
+
private _require;
|
|
32
|
+
/** Remove completedId from all tasks' blockedBy. Returns IDs of newly unblocked tasks. */
|
|
33
|
+
private _clearDependency;
|
|
34
|
+
/** Check if `taskId` is transitively blocked by `targetId`. */
|
|
35
|
+
private _isTransitivelyBlockedBy;
|
|
36
|
+
private _persist;
|
|
37
|
+
private _loadFromDisk;
|
|
38
|
+
}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// Task graph — dependency-aware DAG with background execution and auto-unlock
|
|
2
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, renameSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { generateId } from "../utils/id.js";
|
|
5
|
+
export class TaskGraph {
|
|
6
|
+
_tasks = new Map();
|
|
7
|
+
_config;
|
|
8
|
+
_completedQueue = [];
|
|
9
|
+
_backgroundAborts = new Map();
|
|
10
|
+
constructor(config = {}) {
|
|
11
|
+
this._config = config;
|
|
12
|
+
if (config.persistDir) {
|
|
13
|
+
mkdirSync(config.persistDir, { recursive: true });
|
|
14
|
+
this._loadFromDisk();
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
get(id) {
|
|
18
|
+
const task = this._tasks.get(id);
|
|
19
|
+
return task ? { ...task } : undefined;
|
|
20
|
+
}
|
|
21
|
+
listAll() {
|
|
22
|
+
return [...this._tasks.values()];
|
|
23
|
+
}
|
|
24
|
+
/** Tasks that are pending with no unfinished blockers. */
|
|
25
|
+
listReady() {
|
|
26
|
+
return this.listAll().filter((t) => t.status === "pending" && t.blockedBy.length === 0);
|
|
27
|
+
}
|
|
28
|
+
/** Tasks waiting on unfinished blockers. */
|
|
29
|
+
listBlocked() {
|
|
30
|
+
return this.listAll().filter((t) => t.status === "pending" && t.blockedBy.length > 0);
|
|
31
|
+
}
|
|
32
|
+
create(subject, description = "") {
|
|
33
|
+
const max = this._config.maxTasks ?? 100;
|
|
34
|
+
if (this._tasks.size >= max) {
|
|
35
|
+
throw new Error(`Task limit reached: ${max}.`);
|
|
36
|
+
}
|
|
37
|
+
const node = {
|
|
38
|
+
id: generateId(),
|
|
39
|
+
subject,
|
|
40
|
+
description,
|
|
41
|
+
status: "pending",
|
|
42
|
+
blockedBy: [],
|
|
43
|
+
blocks: [],
|
|
44
|
+
owner: "",
|
|
45
|
+
createdAt: Date.now(),
|
|
46
|
+
updatedAt: Date.now(),
|
|
47
|
+
};
|
|
48
|
+
this._tasks.set(node.id, node);
|
|
49
|
+
this._persist();
|
|
50
|
+
return { ...node };
|
|
51
|
+
}
|
|
52
|
+
/** Add a dependency: `taskId` is blocked by `blockedById`. */
|
|
53
|
+
addDependency(taskId, blockedById) {
|
|
54
|
+
const task = this._require(taskId);
|
|
55
|
+
const blocker = this._require(blockedById);
|
|
56
|
+
if (task.blockedBy.includes(blockedById))
|
|
57
|
+
return;
|
|
58
|
+
// Cycle detection: if blocker is (transitively) blocked by task, adding this edge creates a cycle
|
|
59
|
+
if (this._isTransitivelyBlockedBy(blockedById, taskId)) {
|
|
60
|
+
throw new Error(`Adding dependency ${blockedById} → ${taskId} would create a cycle.`);
|
|
61
|
+
}
|
|
62
|
+
task.blockedBy.push(blockedById);
|
|
63
|
+
blocker.blocks.push(taskId);
|
|
64
|
+
task.updatedAt = Date.now();
|
|
65
|
+
blocker.updatedAt = Date.now();
|
|
66
|
+
this._persist();
|
|
67
|
+
}
|
|
68
|
+
update(taskId, fields) {
|
|
69
|
+
const task = this._require(taskId);
|
|
70
|
+
if (fields.status !== undefined && fields.status !== task.status) {
|
|
71
|
+
if (fields.status === "in_progress" && task.blockedBy.length > 0) {
|
|
72
|
+
throw new Error(`Task ${taskId} is blocked by: ${task.blockedBy.join(", ")}`);
|
|
73
|
+
}
|
|
74
|
+
task.status = fields.status;
|
|
75
|
+
if (fields.status === "completed" || fields.status === "failed") {
|
|
76
|
+
task.result = fields.result ?? task.result;
|
|
77
|
+
const unblocked = this._clearDependency(taskId);
|
|
78
|
+
this._completedQueue.push({
|
|
79
|
+
taskId,
|
|
80
|
+
subject: task.subject,
|
|
81
|
+
result: task.result ?? "",
|
|
82
|
+
status: fields.status,
|
|
83
|
+
unblockedTasks: unblocked,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
if (fields.owner !== undefined)
|
|
88
|
+
task.owner = fields.owner;
|
|
89
|
+
// result is already set inside the completion branch above; only apply here for non-completion updates
|
|
90
|
+
if (fields.result !== undefined && task.status !== "completed" && task.status !== "failed") {
|
|
91
|
+
task.result = fields.result;
|
|
92
|
+
}
|
|
93
|
+
task.updatedAt = Date.now();
|
|
94
|
+
this._persist();
|
|
95
|
+
return { ...task };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Run an async function in the background for a task.
|
|
99
|
+
* Auto-updates task status to in_progress/completed/failed.
|
|
100
|
+
*/
|
|
101
|
+
runBackground(taskId, fn) {
|
|
102
|
+
const task = this._require(taskId);
|
|
103
|
+
if (task.blockedBy.length > 0) {
|
|
104
|
+
throw new Error(`Task ${taskId} is blocked by: ${task.blockedBy.join(", ")}`);
|
|
105
|
+
}
|
|
106
|
+
const ac = new AbortController();
|
|
107
|
+
const bgId = generateId();
|
|
108
|
+
task.status = "in_progress";
|
|
109
|
+
task.backgroundId = bgId;
|
|
110
|
+
task.updatedAt = Date.now();
|
|
111
|
+
this._backgroundAborts.set(bgId, ac);
|
|
112
|
+
this._persist();
|
|
113
|
+
fn(ac.signal).then((result) => {
|
|
114
|
+
this._backgroundAborts.delete(bgId);
|
|
115
|
+
try {
|
|
116
|
+
this.update(taskId, { status: "completed", result });
|
|
117
|
+
}
|
|
118
|
+
catch { /* task may have been removed */ }
|
|
119
|
+
}, (err) => {
|
|
120
|
+
this._backgroundAborts.delete(bgId);
|
|
121
|
+
try {
|
|
122
|
+
this.update(taskId, {
|
|
123
|
+
status: "failed",
|
|
124
|
+
result: err instanceof Error ? err.message : String(err),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
catch { /* task may have been removed */ }
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
abortBackground(taskId) {
|
|
131
|
+
const task = this._tasks.get(taskId);
|
|
132
|
+
if (!task?.backgroundId)
|
|
133
|
+
return false;
|
|
134
|
+
const ac = this._backgroundAborts.get(task.backgroundId);
|
|
135
|
+
if (!ac)
|
|
136
|
+
return false;
|
|
137
|
+
ac.abort();
|
|
138
|
+
return true;
|
|
139
|
+
}
|
|
140
|
+
drainCompleted() {
|
|
141
|
+
const results = [...this._completedQueue];
|
|
142
|
+
this._completedQueue = [];
|
|
143
|
+
return results;
|
|
144
|
+
}
|
|
145
|
+
render() {
|
|
146
|
+
const tasks = this.listAll();
|
|
147
|
+
if (tasks.length === 0)
|
|
148
|
+
return "No tasks.";
|
|
149
|
+
const lines = tasks.map((t) => {
|
|
150
|
+
const icon = t.status === "completed" ? "[x]"
|
|
151
|
+
: t.status === "failed" ? "[!]"
|
|
152
|
+
: t.status === "in_progress" ? "[>]"
|
|
153
|
+
: t.blockedBy.length > 0 ? "[~]"
|
|
154
|
+
: "[ ]";
|
|
155
|
+
const deps = t.blockedBy.length > 0 ? ` (blocked by: ${t.blockedBy.join(", ")})` : "";
|
|
156
|
+
return `${icon} ${t.id}: ${t.subject}${deps}`;
|
|
157
|
+
});
|
|
158
|
+
const done = tasks.filter((t) => t.status === "completed").length;
|
|
159
|
+
const ready = tasks.filter((t) => t.status === "pending" && t.blockedBy.length === 0).length;
|
|
160
|
+
return `Tasks: ${done}/${tasks.length} done, ${ready} ready\n${lines.join("\n")}`;
|
|
161
|
+
}
|
|
162
|
+
dispose() {
|
|
163
|
+
for (const ac of this._backgroundAborts.values()) {
|
|
164
|
+
ac.abort();
|
|
165
|
+
}
|
|
166
|
+
this._backgroundAborts.clear();
|
|
167
|
+
}
|
|
168
|
+
_require(id) {
|
|
169
|
+
const task = this._tasks.get(id);
|
|
170
|
+
if (!task)
|
|
171
|
+
throw new Error(`Task not found: ${id}`);
|
|
172
|
+
return task;
|
|
173
|
+
}
|
|
174
|
+
/** Remove completedId from all tasks' blockedBy. Returns IDs of newly unblocked tasks. */
|
|
175
|
+
_clearDependency(completedId) {
|
|
176
|
+
const completed = this._tasks.get(completedId);
|
|
177
|
+
if (!completed)
|
|
178
|
+
return [];
|
|
179
|
+
const unblocked = [];
|
|
180
|
+
for (const dependentId of completed.blocks) {
|
|
181
|
+
const task = this._tasks.get(dependentId);
|
|
182
|
+
if (!task)
|
|
183
|
+
continue;
|
|
184
|
+
const idx = task.blockedBy.indexOf(completedId);
|
|
185
|
+
if (idx !== -1) {
|
|
186
|
+
task.blockedBy.splice(idx, 1);
|
|
187
|
+
if (task.blockedBy.length === 0 && task.status === "pending") {
|
|
188
|
+
unblocked.push(task.id);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return unblocked;
|
|
193
|
+
}
|
|
194
|
+
/** Check if `taskId` is transitively blocked by `targetId`. */
|
|
195
|
+
_isTransitivelyBlockedBy(taskId, targetId) {
|
|
196
|
+
const visited = new Set();
|
|
197
|
+
const stack = [taskId];
|
|
198
|
+
while (stack.length > 0) {
|
|
199
|
+
const current = stack.pop();
|
|
200
|
+
if (current === targetId)
|
|
201
|
+
return true;
|
|
202
|
+
if (visited.has(current))
|
|
203
|
+
continue;
|
|
204
|
+
visited.add(current);
|
|
205
|
+
const node = this._tasks.get(current);
|
|
206
|
+
if (node)
|
|
207
|
+
stack.push(...node.blockedBy);
|
|
208
|
+
}
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
_persist() {
|
|
212
|
+
if (!this._config.persistDir)
|
|
213
|
+
return;
|
|
214
|
+
const data = JSON.stringify([...this._tasks.values()], null, 2);
|
|
215
|
+
const target = join(this._config.persistDir, "tasks.json");
|
|
216
|
+
const tmp = target + ".tmp";
|
|
217
|
+
writeFileSync(tmp, data, "utf-8");
|
|
218
|
+
renameSync(tmp, target);
|
|
219
|
+
}
|
|
220
|
+
_loadFromDisk() {
|
|
221
|
+
if (!this._config.persistDir)
|
|
222
|
+
return;
|
|
223
|
+
const filePath = join(this._config.persistDir, "tasks.json");
|
|
224
|
+
if (!existsSync(filePath))
|
|
225
|
+
return;
|
|
226
|
+
try {
|
|
227
|
+
const raw = JSON.parse(readFileSync(filePath, "utf-8"));
|
|
228
|
+
if (!Array.isArray(raw))
|
|
229
|
+
return;
|
|
230
|
+
for (const entry of raw) {
|
|
231
|
+
if (entry && typeof entry === "object" && typeof entry.id === "string" && typeof entry.subject === "string") {
|
|
232
|
+
this._tasks.set(entry.id, entry);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
// Corrupted file — start fresh
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
//# sourceMappingURL=task-graph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"task-graph.js","sourceRoot":"","sources":["../../src/task-graph/task-graph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Task graph tools — CRUD + dependency management + background execution
|
|
2
|
+
import { Type } from "@sinclair/typebox";
|
|
3
|
+
import { TASK_GRAPH_TOOL_NAMES } from "./types.js";
|
|
4
|
+
export function createTaskGraphTools(graph) {
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
name: TASK_GRAPH_TOOL_NAMES.create,
|
|
8
|
+
label: "Create Task",
|
|
9
|
+
description: "Create a new task in the task graph. Tasks start as pending. " +
|
|
10
|
+
"Use task_depend to set up dependency ordering.",
|
|
11
|
+
parameters: Type.Object({
|
|
12
|
+
subject: Type.String({ description: "Short title for the task." }),
|
|
13
|
+
description: Type.Optional(Type.String({ description: "Detailed description." })),
|
|
14
|
+
}),
|
|
15
|
+
async execute(_id, params) {
|
|
16
|
+
const task = graph.create(params.subject, params.description);
|
|
17
|
+
return text(`Created task ${task.id}: ${task.subject}\n\n${graph.render()}`);
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: TASK_GRAPH_TOOL_NAMES.depend,
|
|
22
|
+
label: "Add Task Dependency",
|
|
23
|
+
description: "Add a dependency: task_id cannot start until blocked_by_id completes. " +
|
|
24
|
+
"Rejects if this would create a cycle.",
|
|
25
|
+
parameters: Type.Object({
|
|
26
|
+
task_id: Type.String({ description: "Task that is blocked." }),
|
|
27
|
+
blocked_by_id: Type.String({ description: "Task that must complete first." }),
|
|
28
|
+
}),
|
|
29
|
+
async execute(_id, params) {
|
|
30
|
+
graph.addDependency(params.task_id, params.blocked_by_id);
|
|
31
|
+
return text(`Dependency added: ${params.task_id} blocked by ${params.blocked_by_id}\n\n${graph.render()}`);
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
name: TASK_GRAPH_TOOL_NAMES.update,
|
|
36
|
+
label: "Update Task",
|
|
37
|
+
description: "Update a task's status, owner, or result. " +
|
|
38
|
+
"Setting status to 'completed' auto-unblocks dependent tasks. " +
|
|
39
|
+
"Cannot start a task that has unfinished blockers.",
|
|
40
|
+
parameters: Type.Object({
|
|
41
|
+
task_id: Type.String({ description: "Task ID." }),
|
|
42
|
+
status: Type.Optional(Type.Union([Type.Literal("pending"), Type.Literal("in_progress"), Type.Literal("completed"), Type.Literal("failed")], { description: "New status." })),
|
|
43
|
+
owner: Type.Optional(Type.String({ description: "Assign to an agent or user." })),
|
|
44
|
+
result: Type.Optional(Type.String({ description: "Result summary." })),
|
|
45
|
+
}),
|
|
46
|
+
async execute(_id, params) {
|
|
47
|
+
const task = graph.update(params.task_id, {
|
|
48
|
+
status: params.status,
|
|
49
|
+
owner: params.owner,
|
|
50
|
+
result: params.result,
|
|
51
|
+
});
|
|
52
|
+
return text(`Updated task ${task.id}\n\n${graph.render()}`);
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: TASK_GRAPH_TOOL_NAMES.list,
|
|
57
|
+
label: "List Tasks",
|
|
58
|
+
description: "List all tasks with their status, dependencies, and progress.",
|
|
59
|
+
parameters: Type.Object({
|
|
60
|
+
filter: Type.Optional(Type.Union([Type.Literal("all"), Type.Literal("ready"), Type.Literal("blocked"), Type.Literal("in_progress"), Type.Literal("completed")], { description: "Filter tasks by category. Default: all." })),
|
|
61
|
+
}),
|
|
62
|
+
async execute(_id, params) {
|
|
63
|
+
let tasks;
|
|
64
|
+
switch (params.filter) {
|
|
65
|
+
case "ready":
|
|
66
|
+
tasks = graph.listReady();
|
|
67
|
+
break;
|
|
68
|
+
case "blocked":
|
|
69
|
+
tasks = graph.listBlocked();
|
|
70
|
+
break;
|
|
71
|
+
case "in_progress":
|
|
72
|
+
tasks = graph.listAll().filter((t) => t.status === "in_progress");
|
|
73
|
+
break;
|
|
74
|
+
case "completed":
|
|
75
|
+
tasks = graph.listAll().filter((t) => t.status === "completed");
|
|
76
|
+
break;
|
|
77
|
+
default: tasks = graph.listAll();
|
|
78
|
+
}
|
|
79
|
+
if (tasks.length === 0)
|
|
80
|
+
return text(`No tasks matching filter: ${params.filter ?? "all"}`);
|
|
81
|
+
if (!params.filter || params.filter === "all")
|
|
82
|
+
return text(graph.render());
|
|
83
|
+
const lines = tasks.map((t) => `${t.id}: ${t.subject} [${t.status}]`);
|
|
84
|
+
return text(`${params.filter}: ${tasks.length} task(s)\n${lines.join("\n")}`);
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
name: TASK_GRAPH_TOOL_NAMES.get,
|
|
89
|
+
label: "Get Task",
|
|
90
|
+
description: "Get detailed information about a specific task.",
|
|
91
|
+
parameters: Type.Object({
|
|
92
|
+
task_id: Type.String({ description: "Task ID." }),
|
|
93
|
+
}),
|
|
94
|
+
async execute(_id, params) {
|
|
95
|
+
const task = graph.get(params.task_id);
|
|
96
|
+
if (!task)
|
|
97
|
+
return text(`Task not found: ${params.task_id}`);
|
|
98
|
+
return text(JSON.stringify(task, null, 2));
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
];
|
|
102
|
+
}
|
|
103
|
+
function text(t) {
|
|
104
|
+
return { content: [{ type: "text", text: t }] };
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tools.js","sourceRoot":"","sources":["../../src/task-graph/tools.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export declare const TASK_GRAPH_TOOL_NAMES: {
|
|
2
|
+
readonly create: "task_create";
|
|
3
|
+
readonly depend: "task_depend";
|
|
4
|
+
readonly update: "task_update";
|
|
5
|
+
readonly list: "task_list";
|
|
6
|
+
readonly get: "task_get";
|
|
7
|
+
};
|
|
8
|
+
export type TaskStatus = "pending" | "in_progress" | "completed" | "failed";
|
|
9
|
+
export interface TaskNode {
|
|
10
|
+
id: string;
|
|
11
|
+
subject: string;
|
|
12
|
+
description: string;
|
|
13
|
+
status: TaskStatus;
|
|
14
|
+
/** IDs of tasks that must complete before this one can start. */
|
|
15
|
+
blockedBy: string[];
|
|
16
|
+
/** IDs of tasks that this task blocks (reverse edges, maintained automatically). */
|
|
17
|
+
blocks: string[];
|
|
18
|
+
/** Agent or user assigned to this task. */
|
|
19
|
+
owner: string;
|
|
20
|
+
/** Result summary after completion/failure. */
|
|
21
|
+
result?: string;
|
|
22
|
+
/** Background execution handle ID, if running in background. */
|
|
23
|
+
backgroundId?: string;
|
|
24
|
+
createdAt: number;
|
|
25
|
+
updatedAt: number;
|
|
26
|
+
}
|
|
27
|
+
export interface TaskGraphConfig {
|
|
28
|
+
/** Directory for persisting task graph to disk. If omitted, in-memory only. */
|
|
29
|
+
persistDir?: string;
|
|
30
|
+
/** Maximum number of tasks. Default: 100. */
|
|
31
|
+
maxTasks?: number;
|
|
32
|
+
/**
|
|
33
|
+
* Auto-inject completed background task results before each LLM call.
|
|
34
|
+
* Default: true.
|
|
35
|
+
*/
|
|
36
|
+
autoInjectResults?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface CompletedTaskResult {
|
|
39
|
+
taskId: string;
|
|
40
|
+
subject: string;
|
|
41
|
+
result: string;
|
|
42
|
+
status: "completed" | "failed";
|
|
43
|
+
unblockedTasks: string[];
|
|
44
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Task graph types — dependency-aware task DAG with background execution
|
|
2
|
+
export const TASK_GRAPH_TOOL_NAMES = {
|
|
3
|
+
create: "task_create",
|
|
4
|
+
depend: "task_depend",
|
|
5
|
+
update: "task_update",
|
|
6
|
+
list: "task_list",
|
|
7
|
+
get: "task_get",
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/task-graph/types.ts"],"names":[],"mappings":"AAAA,yEAAyE;AAEzE,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,MAAM,EAAE,aAAa;IACrB,MAAM,EAAE,aAAa;IACrB,MAAM,EAAE,aAAa;IACrB,IAAI,EAAE,WAAW;IACjB,GAAG,EAAE,UAAU;CACP,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Compaction logic — token estimation, cut point detection, shouldCompact
|
|
2
2
|
|
|
3
|
-
import type { AgentMessage, Message } from "../types.js";
|
|
3
|
+
import type { AgentMessage, Message, ToolResultMessage, ToolCallBlock } from "../types.js";
|
|
4
4
|
import type { CutPointResult } from "./types.js";
|
|
5
5
|
|
|
6
6
|
const CHARS_PER_TOKEN = 4;
|
|
@@ -97,6 +97,48 @@ export function findCutPoint(
|
|
|
97
97
|
return { firstKeptIndex: cutIndex, isSplitTurn };
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
/** Replace old tool_result content with `[Previous: used {toolName}]`, keeping the most recent N intact. */
|
|
101
|
+
export function microCompact(messages: Message[], keepRecent: number): Message[] {
|
|
102
|
+
const toolResultIndices: number[] = [];
|
|
103
|
+
for (let i = 0; i < messages.length; i++) {
|
|
104
|
+
if (messages[i].role === "tool_result") {
|
|
105
|
+
toolResultIndices.push(i);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (toolResultIndices.length <= keepRecent) return messages;
|
|
110
|
+
|
|
111
|
+
const toReplace = toolResultIndices.slice(0, -keepRecent);
|
|
112
|
+
const result = [...messages];
|
|
113
|
+
|
|
114
|
+
for (const idx of toReplace) {
|
|
115
|
+
const msg = result[idx] as ToolResultMessage;
|
|
116
|
+
|
|
117
|
+
let toolName = "tool";
|
|
118
|
+
for (let j = idx - 1; j >= 0; j--) {
|
|
119
|
+
const prev = result[j];
|
|
120
|
+
if (prev.role === "assistant") {
|
|
121
|
+
const call = prev.content.find(
|
|
122
|
+
(b): b is ToolCallBlock => b.type === "tool_call" && b.id === msg.toolCallId,
|
|
123
|
+
);
|
|
124
|
+
if (call) {
|
|
125
|
+
toolName = call.name;
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
result[idx] = {
|
|
132
|
+
role: "tool_result",
|
|
133
|
+
toolCallId: msg.toolCallId,
|
|
134
|
+
content: `[Previous: used ${toolName}]`,
|
|
135
|
+
...(msg.isError && { isError: msg.isError }),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
|
|
100
142
|
export function messagesToText(messages: AgentMessage[]): string {
|
|
101
143
|
const parts: string[] = [];
|
|
102
144
|
for (const msg of messages) {
|
package/src/compaction/types.ts
CHANGED
|
@@ -6,6 +6,9 @@ export interface CompactionConfig {
|
|
|
6
6
|
keepRecentTokens?: number;
|
|
7
7
|
maxContextTokens?: number;
|
|
8
8
|
customSummarizer?: CompactionSummarizer;
|
|
9
|
+
|
|
10
|
+
/** Number of recent tool results to keep intact during micro compaction. Default: 3. */
|
|
11
|
+
keepRecentToolResults?: number;
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
export interface CompactionSummarizer {
|