@agimon-ai/po-task 0.0.0-alpha.4 → 0.0.0-alpha.41

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 (70) hide show
  1. package/LICENSE +149 -21
  2. package/README.md +12 -2
  3. package/dist/apiContracts.cjs +1 -0
  4. package/dist/apiContracts.cjs.map +1 -1
  5. package/dist/apiContracts.mjs +1 -0
  6. package/dist/apiContracts.mjs.map +1 -1
  7. package/dist/{delegation-Dsqf7fUM.mjs → delegation-CLcleXHi.mjs} +3 -2
  8. package/dist/{delegation-Dsqf7fUM.mjs.map → delegation-CLcleXHi.mjs.map} +1 -1
  9. package/dist/{delegation-frvEXhIz.cjs → delegation-DRp6iZid.cjs} +3 -2
  10. package/dist/{delegation-frvEXhIz.cjs.map → delegation-DRp6iZid.cjs.map} +1 -1
  11. package/dist/delegationManager.cjs +1 -1
  12. package/dist/delegationManager.d.mts +1 -1
  13. package/dist/delegationManager.mjs +1 -1
  14. package/dist/extensions/mcp.cjs +29 -27
  15. package/dist/extensions/mcp.cjs.map +1 -1
  16. package/dist/extensions/mcp.mjs +29 -27
  17. package/dist/extensions/mcp.mjs.map +1 -1
  18. package/dist/extensions/native.mjs +309 -207
  19. package/dist/extensions/native.mjs.map +1 -1
  20. package/dist/extensions/server.cjs +351 -122
  21. package/dist/extensions/server.cjs.map +1 -1
  22. package/dist/extensions/server.d.mts +2 -2
  23. package/dist/extensions/server.d.mts.map +1 -1
  24. package/dist/extensions/server.mjs +350 -121
  25. package/dist/extensions/server.mjs.map +1 -1
  26. package/dist/extensions/web.mjs +254 -206
  27. package/dist/extensions/web.mjs.map +1 -1
  28. package/dist/{index-DlmXKyhQ.d.mts → index-CdJx5tdI.d.mts} +2 -2
  29. package/dist/{index-DlmXKyhQ.d.mts.map → index-CdJx5tdI.d.mts.map} +1 -1
  30. package/dist/{index-B1JPJdpZ.d.mts → index-DrE00rrP.d.mts} +3 -3
  31. package/dist/{index-B1JPJdpZ.d.mts.map → index-DrE00rrP.d.mts.map} +1 -1
  32. package/dist/{index-B9QNwUBr.d.mts → index-Dyan0ai0.d.mts} +3 -3
  33. package/dist/{index-B9QNwUBr.d.mts.map → index-Dyan0ai0.d.mts.map} +1 -1
  34. package/dist/{index-qQGWsPum.d.mts → index-S77ZvGc-.d.mts} +2 -2
  35. package/dist/{index-qQGWsPum.d.mts.map → index-S77ZvGc-.d.mts.map} +1 -1
  36. package/dist/{index-CUWCvh-E.d.mts → index-nx0ueNkm.d.mts} +2 -2
  37. package/dist/{index-CUWCvh-E.d.mts.map → index-nx0ueNkm.d.mts.map} +1 -1
  38. package/dist/index.cjs +1 -1
  39. package/dist/index.d.mts +8 -8
  40. package/dist/index.mjs +1 -1
  41. package/dist/{logSinkTelemetry-BhbKdn-x.mjs → logSinkTelemetry-3GMazFYa.mjs} +2 -2
  42. package/dist/logSinkTelemetry-3GMazFYa.mjs.map +1 -0
  43. package/dist/{logSinkTelemetry-BGb8WQBz.cjs → logSinkTelemetry-DhzIQMsV.cjs} +3 -3
  44. package/dist/logSinkTelemetry-DhzIQMsV.cjs.map +1 -0
  45. package/dist/logSinkTelemetry.cjs +1 -1
  46. package/dist/logSinkTelemetry.d.mts +1 -1
  47. package/dist/logSinkTelemetry.mjs +1 -1
  48. package/dist/storeInvariants.d.mts +1 -1
  49. package/dist/storeReconcile.d.mts +1 -1
  50. package/dist/storeReducer.d.mts +1 -1
  51. package/dist/storeTaskGraph.d.mts +1 -1
  52. package/dist/storeTaskStore.d.mts +1 -1
  53. package/dist/storeTypes.d.mts +1 -1
  54. package/dist/{task-4HeGAS8o.d.mts → task--hlnpS7L.d.mts} +2 -2
  55. package/dist/{task-4HeGAS8o.d.mts.map → task--hlnpS7L.d.mts.map} +1 -1
  56. package/dist/task-CXF9VULl.cjs.map +1 -1
  57. package/dist/{task-DJpTteeJ.d.mts → task-DdTKZNtU.d.mts} +3 -1
  58. package/dist/task-DdTKZNtU.d.mts.map +1 -0
  59. package/dist/task-giCbpKzV.mjs.map +1 -1
  60. package/dist/{taskGraph-D0zFHF2p.d.mts → taskGraph-CB8ffMCz.d.mts} +2 -2
  61. package/dist/{taskGraph-D0zFHF2p.d.mts.map → taskGraph-CB8ffMCz.d.mts.map} +1 -1
  62. package/dist/toolResponseEnvelope.d.mts +1 -1
  63. package/dist/toolSchema.d.mts +1 -1
  64. package/llms.txt +11 -0
  65. package/package.json +17 -16
  66. package/src/prompts/codemode-how-to-task/SKILL.md +40 -0
  67. package/src/types/webTasks.ts +1 -0
  68. package/dist/logSinkTelemetry-BGb8WQBz.cjs.map +0 -1
  69. package/dist/logSinkTelemetry-BhbKdn-x.mjs.map +0 -1
  70. package/dist/task-DJpTteeJ.d.mts.map +0 -1
@@ -1,23 +1,24 @@
1
1
  import { f as getDelegationTimeoutMs, h as getStoreTtlMs, p as getMaxTasks } from "../config-BTadoGeF.mjs";
2
2
  import { r as isBlocked } from "../taskGraph-BOQvT0-M.mjs";
3
3
  import { t as TASK_EVENT } from "../telemetry-gEGWTaMI.mjs";
4
- import { n as DelegationManager, t as BACKGROUND_WORK_PROVIDER } from "../delegation-Dsqf7fUM.mjs";
4
+ import { n as DelegationManager, t as BACKGROUND_WORK_PROVIDER } from "../delegation-CLcleXHi.mjs";
5
5
  import { a as buildAssignmentResult, c as formatAssignmentResults, o as buildTextResult, s as buildToolResult } from "../taskResult-edBAAKSH.mjs";
6
6
  import { g as COMMAND_NAME, m as TaskParamsSchema } from "../task-DO0TwZ0z.mjs";
7
7
  import { a as removeLegacyStoreDirectoryAsync, c as resolveSessionKey, d as sweepStoreFilesAsync, l as resolveStorePath, n as hasStorePathOverride } from "../paths-DajceJig.mjs";
8
8
  import { a as isCommittingOp, r as applyTaskMutation } from "../reducer-BEfJFM5L.mjs";
9
9
  import { t as TaskStore } from "../taskStore-BAi54FKL.mjs";
10
- import { n as toFailureReporter, t as createTaskErrorReporter } from "../logSinkTelemetry-BhbKdn-x.mjs";
10
+ import { n as toFailureReporter, t as createTaskErrorReporter } from "../logSinkTelemetry-3GMazFYa.mjs";
11
11
  import { PO_DELEGATION_SERVICE, readPoDelegationService } from "@agimon-ai/po-core/delegation";
12
12
  import path from "node:path";
13
- import { composeServerProviderOverrides, defineServerPlugin } from "@agimon-ai/po-core/serverFacet";
14
- import { composeRootHooks, defineChannel, defineResource, defineRoot, defineServerCommand, defineServerTool } from "@agimon-ai/po-core/extensionFile";
13
+ import { composeServerProviderOverrides, defineServerPlugin, packageResourcePath, readPackageResource } from "@agimon-ai/po-core/serverPlugin";
14
+ import { composeRootHooks, composeRootInjects, defineChannel, defineResource, defineRoot, defineServerCommand, defineServerTool, runCleanups } from "@agimon-ai/po-core/extensionFile";
15
15
  import { PO_BACKGROUND_WORK_SERVICE, readPoBackgroundWorkService } from "@agimon-ai/po-core/backgroundWork";
16
+ import { PO_CODEMODE_SERVICE, readPoCodemode } from "@agimon-ai/po-core/codemode";
16
17
  import { PO_CONTEXT_CONTRIBUTIONS_SERVICE, requirePoContextContributions } from "@agimon-ai/po-core/contextContributions";
17
18
  import { createPoReadinessCoordinator, readPoReadinessCoordinator } from "@agimon-ai/po-core/readiness";
18
19
  import { createHash, randomUUID } from "node:crypto";
19
- import { HOME_ENTITY_LIMIT } from "@agimon-ai/po-core/hubChannel";
20
20
  import { Check } from "typebox/value";
21
+ import { HOME_ENTITY_LIMIT } from "@agimon-ai/po-core/hubChannel";
21
22
  //#region src/services/contextContribution/index.ts
22
23
  const TASK_CONTEXT_CONTRIBUTION_SOURCE = "@agimon-ai/po-task";
23
24
  const TASK_CONTEXT_CONTRIBUTION_ID = "active-tasks";
@@ -77,6 +78,298 @@ function createNodeDelegationPlatform(environment = process.env) {
77
78
  };
78
79
  }
79
80
  //#endregion
81
+ //#region src/services/taskTool/index.ts
82
+ function output(value) {
83
+ if (typeof value === "object" && value !== null && "content" in value) return value;
84
+ return {
85
+ content: [{
86
+ type: "text",
87
+ text: typeof value === "string" ? value : JSON.stringify(value, null, 2)
88
+ }],
89
+ details: value
90
+ };
91
+ }
92
+ function failure(error) {
93
+ return {
94
+ content: [{
95
+ type: "text",
96
+ text: error instanceof Error ? error.message : String(error)
97
+ }],
98
+ isError: true
99
+ };
100
+ }
101
+ async function reducerAction(store, action, params, maxTasks) {
102
+ const { document, value } = await store.mutate((current) => {
103
+ const result = applyTaskMutation(current, action, params, void 0, maxTasks);
104
+ return {
105
+ ...isCommittingOp(result.op) ? { document: result.document } : {},
106
+ value: result
107
+ };
108
+ });
109
+ if (value.op.kind === "error") throw new Error(value.op.message);
110
+ return buildToolResult(action, params, document, value.op);
111
+ }
112
+ async function assignmentBatch(manager, assignments, signal) {
113
+ const result = [];
114
+ for (const [index, assignment] of assignments.entries()) try {
115
+ const outcome = await manager.assign(assignment.id, {
116
+ agent: assignment.agent,
117
+ inlineAgent: assignment.inlineAgent,
118
+ instructions: assignment.instructions,
119
+ relevantFiles: assignment.relevantFiles,
120
+ priorFindings: assignment.priorFindings,
121
+ model: assignment.model,
122
+ ...assignment.context === "fork" || assignment.context === "fresh" ? { context: assignment.context } : {},
123
+ signal
124
+ });
125
+ result.push({
126
+ index,
127
+ id: assignment.id,
128
+ agent: assignment.agent,
129
+ ...outcome
130
+ });
131
+ } catch (error) {
132
+ result.push({
133
+ index,
134
+ id: assignment.id,
135
+ agent: assignment.agent,
136
+ ok: false,
137
+ message: String(error)
138
+ });
139
+ }
140
+ return result;
141
+ }
142
+ /** One task action against the session store, shared by the `task` tool and the `tasks` code-mode namespace. */
143
+ async function runTaskAction(store, manager, maxTasks, rawParams, signal, onUpdate) {
144
+ if (!Check(TaskParamsSchema, rawParams)) return failure("Invalid task parameters.");
145
+ const params = rawParams;
146
+ try {
147
+ if ((params.action === "assign" || params.action === "cancel") && !manager) throw new Error("Delegation is not available on this connection.");
148
+ if (params.action === "assign") {
149
+ if (!params.assignments?.length) throw new Error("assign requires a non-empty assignments[] array");
150
+ onUpdate?.(output(`Delegating ${params.assignments.length} task${params.assignments.length === 1 ? "" : "s"}...`));
151
+ const items = await assignmentBatch(manager, params.assignments, signal);
152
+ const assigned = items.filter((item) => item.ok).map((item) => item.id);
153
+ const text = formatAssignmentResults(items);
154
+ if (assigned.length === 0) throw new Error(text);
155
+ return buildAssignmentResult(params, store.snapshot, text, {
156
+ assigned,
157
+ failed: items.length - assigned.length
158
+ });
159
+ }
160
+ if (params.action === "cancel") {
161
+ const outcome = await manager.cancel(params.id ?? NaN);
162
+ if (!outcome.ok) throw new Error(outcome.message);
163
+ return buildTextResult("cancel", params, store.snapshot, outcome.message);
164
+ }
165
+ return reducerAction(store, params.action, params, maxTasks);
166
+ } catch (error) {
167
+ return failure(error);
168
+ }
169
+ }
170
+ function createHeadlessTaskTool(store, manager, maxTasks) {
171
+ return {
172
+ name: "task",
173
+ label: "Task",
174
+ description: "Maintain a persistent task graph and delegate ready tasks to background agents.",
175
+ parameters: TaskParamsSchema,
176
+ promptSnippet: "Track complex work persistently and delegate ready tasks",
177
+ executionMode: "serial",
178
+ execute: (_toolCallId, rawParams, signal, onUpdate) => runTaskAction(store, manager, maxTasks, rawParams, signal, onUpdate)
179
+ };
180
+ }
181
+ //#endregion
182
+ //#region src/services/taskNamespace/index.ts
183
+ const DECLARATIONS = `type TaskStatus = 'pending' | 'in_progress' | 'completed' | 'failed' | 'deleted';
184
+
185
+ type DelegationState = 'requested' | 'running' | 'completed' | 'failed' | 'cancelled';
186
+
187
+ interface DelegationResult {
188
+ status: string;
189
+ output?: string;
190
+ outputPath?: string;
191
+ sessionFile?: string;
192
+ error?: string;
193
+ durationMs?: number;
194
+ toolCount?: number;
195
+ }
196
+
197
+ interface TaskDelegation {
198
+ requestId: string;
199
+ agent: string;
200
+ identity?: string;
201
+ state: DelegationState;
202
+ sessionId?: string;
203
+ pid?: number;
204
+ runId?: string;
205
+ model?: string;
206
+ startedAt?: string;
207
+ endedAt?: string;
208
+ result?: DelegationResult;
209
+ }
210
+
211
+ interface Task {
212
+ id: number;
213
+ subject: string;
214
+ description?: string;
215
+ activeForm?: string;
216
+ status: TaskStatus;
217
+ blockedBy?: number[];
218
+ owner?: string;
219
+ metadata?: Record<string, unknown>;
220
+ createdAt?: string;
221
+ updatedAt?: string;
222
+ delegation?: TaskDelegation;
223
+ }
224
+
225
+ interface TaskDocument {
226
+ version: number;
227
+ rev: number;
228
+ nextId: number;
229
+ tasks: Task[];
230
+ }
231
+ interface TaskItem {
232
+ /** Existing task id to change. Omit to create; an unknown id fails only that entry. */
233
+ id?: number;
234
+ /** Temporary name so a LATER entry in the same call can list it in blockedBy. Never stored. */
235
+ ref?: string;
236
+ /** Short and imperative. Required when creating. */
237
+ subject?: string;
238
+ /** The durable brief handed to a subagent on assign. */
239
+ description?: string;
240
+ /** Present-continuous label shown while in_progress, such as 'writing tests'. */
241
+ activeForm?: string;
242
+ status?: TaskStatus;
243
+ /** For a NEW entry: task ids or earlier refs. */
244
+ blockedBy?: (number | string)[];
245
+ /** For an entry with an id: dependencies to add or remove. */
246
+ addBlockedBy?: (number | string)[];
247
+ removeBlockedBy?: (number | string)[];
248
+ owner?: string;
249
+ /** Merged into the task; a null value deletes that key. */
250
+ metadata?: Record<string, unknown>;
251
+ }
252
+
253
+ interface TaskAssignment {
254
+ /** A pending, unblocked task. */
255
+ id: number;
256
+ /** Exact name from subagent({ action: 'agents' }). */
257
+ agent: string;
258
+ instructions?: string;
259
+ /** Only files you actually read or located. */
260
+ relevantFiles?: string[];
261
+ /** Only verified facts, not directives. */
262
+ priorFindings?: string;
263
+ model?: string;
264
+ context?: 'fresh' | 'fork';
265
+ }
266
+
267
+ /** What a write returns: the text the task tool would print, and the graph after the write. */
268
+ interface TaskWrite {
269
+ message: string;
270
+ document: TaskDocument;
271
+ /** upsert only: ids that landed and how many entries failed. Nothing landing throws; a partial failure does not. */
272
+ applied?: number[];
273
+ failed?: number;
274
+ }
275
+ declare const tasks: {
276
+ /** The whole task graph, tombstones included. Filter it in the script. */
277
+ snapshot(): Promise<TaskDocument>;
278
+ /**
279
+ * Create or change tasks, applied in array order. Never mark a task completed while tests fail or the
280
+ * work is partial: use failed, or keep it in_progress and add a task for the blocker in the same call.
281
+ * Status flow is pending, in_progress, completed. failed is recoverable and deleted is a tombstone.
282
+ */
283
+ upsert(tasks: TaskItem[]): Promise<TaskWrite>;
284
+ /** Tombstone one task. Refused while it has a running delegation. */
285
+ delete(id: number): Promise<TaskWrite>;
286
+ /** Remove every task. Refused while a delegation is running. */
287
+ clear(): Promise<TaskWrite>;
288
+ /** Hand ready tasks to background subagents. Batch independent tasks in one call. */
289
+ assign(assignments: TaskAssignment[]): Promise<TaskWrite>;
290
+ /** Cancel a task's running delegation. */
291
+ cancel(id: number): Promise<TaskWrite>;
292
+ };`;
293
+ /** The owning session's task graph: `snapshot` reads without locking, the rest write through the same store as the `task` tool. */
294
+ function createTaskNamespace(options) {
295
+ return {
296
+ name: "tasks",
297
+ summary: "The session task graph: tasks.snapshot() reads it, tasks.upsert/delete/clear change it, tasks.assign/cancel hand tasks to background subagents. Use it to track multi-step work.",
298
+ declarations: DECLARATIONS,
299
+ bind(run) {
300
+ if (run.sessionId !== options.sessionId) throw new Error("Tasks namespace belongs to another session.");
301
+ let disposed = false;
302
+ run.onDispose(() => {
303
+ disposed = true;
304
+ });
305
+ const assertAvailable = () => {
306
+ run.signal.throwIfAborted();
307
+ if (disposed) throw new Error("Tasks namespace run is disposed.");
308
+ options.assertAvailable();
309
+ };
310
+ const members = Object.create(null);
311
+ members.snapshot = async () => {
312
+ assertAvailable();
313
+ const storePath = options.store.storePath;
314
+ const errors = [];
315
+ const document = await options.store.readAsync(() => false, (error) => errors.push(error));
316
+ assertAvailable();
317
+ if (options.store.storePath !== storePath) throw new Error("Task store path changed during snapshot.");
318
+ if (errors.length > 0) throw new Error("Task snapshot read failed.", { cause: errors[0] });
319
+ return JSON.parse(JSON.stringify(document));
320
+ };
321
+ const write = async (params) => {
322
+ assertAvailable();
323
+ const started = Date.now();
324
+ const result = await runTaskAction(options.store, options.manager, options.maxTasks, params, run.signal);
325
+ assertAvailable();
326
+ const message = result.content.flatMap((part) => part.type === "text" ? [part.text] : []).join("\n");
327
+ const upsert = result.details?.upsert;
328
+ const failure = result.isError || upsert && upsert.applied.length === 0 && upsert.failed > 0 ? message : void 0;
329
+ run.record?.({
330
+ name: `tasks.${String(params.action)}`,
331
+ tool: "task",
332
+ args: params,
333
+ ok: failure === void 0,
334
+ ms: Date.now() - started,
335
+ ...failure === void 0 ? {} : { error: failure },
336
+ result: {
337
+ content: result.content,
338
+ details: result.details
339
+ }
340
+ });
341
+ if (failure !== void 0) throw new Error(failure);
342
+ return {
343
+ message,
344
+ document: JSON.parse(JSON.stringify(options.store.snapshot)),
345
+ ...upsert ? {
346
+ applied: upsert.applied,
347
+ failed: upsert.failed
348
+ } : {}
349
+ };
350
+ };
351
+ members.upsert = (tasks) => write({
352
+ action: "upsert",
353
+ tasks
354
+ });
355
+ members.delete = (id) => write({
356
+ action: "delete",
357
+ id
358
+ });
359
+ members.clear = () => write({ action: "clear" });
360
+ members.assign = (assignments) => write({
361
+ action: "assign",
362
+ assignments
363
+ });
364
+ members.cancel = (id) => write({
365
+ action: "cancel",
366
+ id
367
+ });
368
+ return members;
369
+ }
370
+ };
371
+ }
372
+ //#endregion
80
373
  //#region src/types/webTasks.ts
81
374
  /** Browser-safe task view published by the cockpit hub channel. */
82
375
  const TASKS_CHANNEL_TYPE = "task_graph";
@@ -90,7 +383,7 @@ function headlineOf(content) {
90
383
  const root = defineRoot(({ host: serverHost, agent: host, signal: pluginSignal }) => {
91
384
  if (!host) throw new Error("Task session requires the headless host.");
92
385
  const execution = host.context;
93
- if (serverHost.context.directEvents === void 0) throw new Error("Task headless facet requires the session direct event bus.");
386
+ if (serverHost.context.directEvents === void 0) throw new Error("Task server plugin requires the session direct event bus.");
94
387
  const directEvents = serverHost.context.directEvents;
95
388
  const reporter = createTaskErrorReporter({
96
389
  cwd: execution.cwd,
@@ -175,6 +468,25 @@ const root = defineRoot(({ host: serverHost, agent: host, signal: pluginSignal }
175
468
  },
176
469
  services: [(serviceContextOwner) => {
177
470
  serviceContext = serviceContextOwner;
471
+ const namespace = createTaskNamespace({
472
+ store,
473
+ manager,
474
+ maxTasks,
475
+ sessionId: execution.sessionId,
476
+ assertAvailable: () => {
477
+ if (!active || disposed || pluginSignal?.aborted) throw new Error("Task session is unavailable.");
478
+ }
479
+ });
480
+ serviceContextOwner.inject([PO_CODEMODE_SERVICE], (context) => {
481
+ const codemode = readPoCodemode(context);
482
+ if (!codemode) return void 0;
483
+ const registration = codemode.register(SOURCE, namespace);
484
+ const restriction = host.registerToolRestriction({ excludedTools: ["task"] });
485
+ return () => {
486
+ restriction.dispose();
487
+ registration.dispose();
488
+ };
489
+ });
178
490
  serviceContextOwner.inject([PO_CONTEXT_CONTRIBUTIONS_SERVICE], (context) => {
179
491
  const registration = requirePoContextContributions(context).register(createTaskContextContribution(() => active && !disposed ? store.snapshot.tasks : []));
180
492
  return () => registration.dispose();
@@ -277,12 +589,14 @@ const root = defineRoot(({ host: serverHost, agent: host, signal: pluginSignal }
277
589
  generation += 1;
278
590
  startupAbort.abort();
279
591
  await Promise.allSettled([startup]);
280
- unwatch?.();
281
- background?.dispose();
282
- manager.dispose();
283
- store.dispose();
284
- await ownedReadiness.dispose();
285
- await reporter.shutdown();
592
+ await runCleanups([
593
+ () => unwatch?.(),
594
+ () => background?.dispose(),
595
+ () => manager.dispose(),
596
+ () => store.dispose(),
597
+ () => ownedReadiness.dispose(),
598
+ () => reporter.shutdown()
599
+ ], "Task cleanup failed.");
286
600
  }
287
601
  };
288
602
  });
@@ -310,6 +624,7 @@ function present(document) {
310
624
  if (task.updatedAt) view.updatedAt = task.updatedAt;
311
625
  if (task.delegation) view.delegation = {
312
626
  ...task.delegation.agent === void 0 ? {} : { agent: task.delegation.agent },
627
+ ...task.delegation.identity === void 0 ? {} : { identity: task.delegation.identity },
313
628
  ...task.delegation.state === void 0 ? {} : { state: task.delegation.state }
314
629
  };
315
630
  return [view];
@@ -429,105 +744,6 @@ function createTasksChannel(options = {}) {
429
744
  //#region src/extensions/(backend)/channel/task-graph.server.ts
430
745
  var task_graph_server_default = defineChannel(createTasksChannel);
431
746
  //#endregion
432
- //#region src/services/taskTool/index.ts
433
- function output(value) {
434
- if (typeof value === "object" && value !== null && "content" in value) return value;
435
- return {
436
- content: [{
437
- type: "text",
438
- text: typeof value === "string" ? value : JSON.stringify(value, null, 2)
439
- }],
440
- details: value
441
- };
442
- }
443
- function failure(error) {
444
- return {
445
- content: [{
446
- type: "text",
447
- text: error instanceof Error ? error.message : String(error)
448
- }],
449
- isError: true
450
- };
451
- }
452
- async function reducerAction(store, action, params, maxTasks) {
453
- const { document, value } = await store.mutate((current) => {
454
- const result = applyTaskMutation(current, action, params, void 0, maxTasks);
455
- return {
456
- ...isCommittingOp(result.op) ? { document: result.document } : {},
457
- value: result
458
- };
459
- });
460
- if (value.op.kind === "error") throw new Error(value.op.message);
461
- return buildToolResult(action, params, document, value.op);
462
- }
463
- async function assignmentBatch(manager, assignments, signal) {
464
- const result = [];
465
- for (const [index, assignment] of assignments.entries()) try {
466
- const outcome = await manager.assign(assignment.id, {
467
- agent: assignment.agent,
468
- inlineAgent: assignment.inlineAgent,
469
- instructions: assignment.instructions,
470
- relevantFiles: assignment.relevantFiles,
471
- priorFindings: assignment.priorFindings,
472
- model: assignment.model,
473
- ...assignment.context === "fork" || assignment.context === "fresh" ? { context: assignment.context } : {},
474
- signal
475
- });
476
- result.push({
477
- index,
478
- id: assignment.id,
479
- agent: assignment.agent,
480
- ...outcome
481
- });
482
- } catch (error) {
483
- result.push({
484
- index,
485
- id: assignment.id,
486
- agent: assignment.agent,
487
- ok: false,
488
- message: String(error)
489
- });
490
- }
491
- return result;
492
- }
493
- function createHeadlessTaskTool(store, manager, maxTasks) {
494
- return {
495
- name: "task",
496
- label: "Task",
497
- description: "Maintain a persistent task graph and delegate ready tasks to background agents.",
498
- parameters: TaskParamsSchema,
499
- promptSnippet: "Track complex work persistently and delegate ready tasks",
500
- executionMode: "serial",
501
- async execute(_toolCallId, rawParams, signal, onUpdate) {
502
- if (!Check(TaskParamsSchema, rawParams)) return failure("Invalid task parameters.");
503
- const params = rawParams;
504
- try {
505
- if ((params.action === "assign" || params.action === "cancel") && !manager) throw new Error("Delegation is not available on this connection.");
506
- if (params.action === "assign") {
507
- if (!params.assignments?.length) throw new Error("assign requires a non-empty assignments[] array");
508
- onUpdate?.(output(`Delegating ${params.assignments.length} task${params.assignments.length === 1 ? "" : "s"}...`));
509
- const items = await assignmentBatch(manager, params.assignments, signal);
510
- const assigned = items.filter((item) => item.ok).map((item) => item.id);
511
- const text = formatAssignmentResults(items);
512
- if (assigned.length === 0) throw new Error(text);
513
- return buildAssignmentResult(params, store.snapshot, text, {
514
- assigned,
515
- failed: items.length - assigned.length
516
- });
517
- }
518
- if (params.action === "cancel") {
519
- const outcome = await manager.cancel(params.id ?? NaN);
520
- if (!outcome.ok) throw new Error(outcome.message);
521
- return buildTextResult("cancel", params, store.snapshot, outcome.message);
522
- }
523
- return reducerAction(store, params.action, params, maxTasks);
524
- } catch (error) {
525
- return failure(error);
526
- }
527
- }
528
- };
529
- }
530
- //#endregion
531
747
  //#region src/extensions/workspaces/sessions/(backend)/command/_lib/tasks.server.ts
532
748
  var tasks_server_default$1 = (context) => ({
533
749
  name: COMMAND_NAME,
@@ -545,12 +761,22 @@ var tasks_server_default$1 = (context) => ({
545
761
  //#region src/extensions/workspaces/sessions/(backend)/command/tasks.server.ts
546
762
  var tasks_server_default = defineServerCommand(tasks_server_default$1);
547
763
  //#endregion
764
+ //#region src/extensions/workspaces/sessions/(backend)/resource/codemode-how-to-task.server.ts
765
+ var codemode_how_to_task_server_default = defineResource({
766
+ name: "codemode-how-to-task",
767
+ description: "Keep a plan that survives compaction and delegate parts of it to background subagents. Use for any multi-step plan, todo list, or delegation.",
768
+ kind: "skill",
769
+ pinned: true,
770
+ path: packageResourcePath(import.meta.url, "src/prompts/codemode-how-to-task/SKILL.md"),
771
+ read: () => readPackageResource(import.meta.url, "src/prompts/codemode-how-to-task/SKILL.md")
772
+ });
773
+ //#endregion
548
774
  //#region src/extensions/workspaces/sessions/(backend)/resource/_lib/task-board.server.ts
549
775
  var task_board_server_default$1 = (context) => ({
550
776
  name: "po/task-board",
551
777
  kind: "context",
552
778
  /**
553
- * The same bounded projection the Pi facet renders: open work only, one line each.
779
+ * The same bounded projection the Pi extension renders: open work only, one line each.
554
780
  * Dumping the whole TaskDocument put every completed task plus the store's own
555
781
  * version/rev/nextId bookkeeping in the prompt, and an idle board still cost a
556
782
  * paragraph. '' is dropped by the prompt composer.
@@ -572,21 +798,24 @@ var task_server_default = defineServerTool(task_server_default$1);
572
798
  //#endregion
573
799
  //#region generated/server.ts
574
800
  const at = (value, context) => typeof value === "function" ? value(context) : value;
801
+ /* v8 ignore next -- generated normalization branch */
802
+ const defined = (values) => values.filter((value) => value !== void 0);
575
803
  const via = (identity, value) => value === void 0 ? void 0 : {
576
804
  ...identity,
577
805
  ...value
578
806
  };
579
- const facet = defineServerPlugin({
807
+ const serverPlugin = defineServerPlugin({
580
808
  name: "@agimon-ai/po-task",
581
809
  providerOverrides: composeServerProviderOverrides(root_server_default),
582
- global: () => ({ get channels() {
583
- return [() => via({ frameType: "task_graph" }, task_graph_server_default())];
810
+ injects: composeRootInjects({ session: [root_server_default] }),
811
+ global: (context) => ({ get channels() {
812
+ return [() => via({ frameType: "task_graph" }, at(task_graph_server_default, context))];
584
813
  } }),
585
- workspace: () => ({ get channels() {
586
- return [() => via({ frameType: "task_graph" }, task_graph_server_default())];
814
+ workspace: (context) => ({ get channels() {
815
+ return defined([context.hosted("global") ? void 0 : () => via({ frameType: "task_graph" }, at(task_graph_server_default, context))]);
587
816
  } }),
588
817
  session: async (context) => {
589
- const scopeSession = await root_server_default(context);
818
+ const scopeSession = await context.scopeRoot("session", root_server_default, context);
590
819
  const contextSession = {
591
820
  ...context,
592
821
  root: scopeSession.value
@@ -594,13 +823,13 @@ const facet = defineServerPlugin({
594
823
  return {
595
824
  ...composeRootHooks(scopeSession),
596
825
  get channels() {
597
- return [() => via({ frameType: "task_graph" }, task_graph_server_default())];
826
+ return defined([context.hosted("global") ? void 0 : () => via({ frameType: "task_graph" }, at(task_graph_server_default, context))]);
598
827
  },
599
828
  get commands() {
600
829
  return [via({ name: "tasks" }, at(tasks_server_default, contextSession))];
601
830
  },
602
831
  get resources() {
603
- return [at(task_board_server_default, contextSession)];
832
+ return [at(codemode_how_to_task_server_default, contextSession), at(task_board_server_default, contextSession)];
604
833
  },
605
834
  get tools() {
606
835
  return [via({ name: "task" }, at(task_server_default, contextSession))];
@@ -613,6 +842,6 @@ const facet = defineServerPlugin({
613
842
  }
614
843
  });
615
844
  //#endregion
616
- export { facet as default, facet };
845
+ export { serverPlugin as default, serverPlugin };
617
846
 
618
847
  //# sourceMappingURL=server.mjs.map