@renxqoo/renx-code 0.0.4 → 0.0.6

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 (210) hide show
  1. package/README.md +82 -51
  2. package/bin/renx.cjs +16 -0
  3. package/package.json +2 -45
  4. package/src/agent/runtime/runtime.context-usage.test.ts +4 -5
  5. package/src/agent/runtime/runtime.error-handling.test.ts +4 -5
  6. package/src/agent/runtime/runtime.test.ts +7 -4
  7. package/src/agent/runtime/runtime.ts +3 -9
  8. package/src/agent/runtime/runtime.usage-forwarding.test.ts +4 -5
  9. package/src/agent/runtime/source-modules.test.ts +16 -35
  10. package/src/agent/runtime/source-modules.ts +17 -0
  11. package/vendor/agent-root/src/agent/ENTERPRISE_ACCEPTANCE_CHECKLIST.md +95 -0
  12. package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.html +1345 -0
  13. package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.md +1353 -0
  14. package/vendor/agent-root/src/agent/ERROR_CONTRACT.md +60 -0
  15. package/vendor/agent-root/src/agent/TEST_COVERAGE_ANALYSIS.md +278 -0
  16. package/vendor/agent-root/src/agent/__test__/error-contract.test.ts +72 -0
  17. package/vendor/agent-root/src/agent/__test__/types.test.ts +137 -0
  18. package/vendor/agent-root/src/agent/agent/__test__/abort-runtime.test.ts +83 -0
  19. package/vendor/agent-root/src/agent/agent/__test__/callback-safety.test.ts +34 -0
  20. package/vendor/agent-root/src/agent/agent/__test__/compaction.test.ts +323 -0
  21. package/vendor/agent-root/src/agent/agent/__test__/concurrency.test.ts +290 -0
  22. package/vendor/agent-root/src/agent/agent/__test__/error-normalizer.test.ts +377 -0
  23. package/vendor/agent-root/src/agent/agent/__test__/error.test.ts +212 -0
  24. package/vendor/agent-root/src/agent/agent/__test__/fault-injection.test.ts +295 -0
  25. package/vendor/agent-root/src/agent/agent/__test__/index.test.ts +3607 -0
  26. package/vendor/agent-root/src/agent/agent/__test__/logger.test.ts +35 -0
  27. package/vendor/agent-root/src/agent/agent/__test__/message-utils.test.ts +517 -0
  28. package/vendor/agent-root/src/agent/agent/__test__/telemetry.test.ts +97 -0
  29. package/vendor/agent-root/src/agent/agent/__test__/timeout-budget.test.ts +479 -0
  30. package/vendor/agent-root/src/agent/agent/__test__/tool-call-merge.test.ts +80 -0
  31. package/vendor/agent-root/src/agent/agent/__test__/tool-execution-ledger.test.ts +76 -0
  32. package/vendor/agent-root/src/agent/agent/__test__/write-buffer.test.ts +173 -0
  33. package/vendor/agent-root/src/agent/agent/__test__/write-file-session.test.ts +109 -0
  34. package/vendor/agent-root/src/agent/agent/abort-runtime.ts +71 -0
  35. package/vendor/agent-root/src/agent/agent/callback-safety.ts +33 -0
  36. package/vendor/agent-root/src/agent/agent/compaction.ts +291 -0
  37. package/vendor/agent-root/src/agent/agent/concurrency.ts +103 -0
  38. package/vendor/agent-root/src/agent/agent/error-normalizer.ts +190 -0
  39. package/vendor/agent-root/src/agent/agent/error.ts +198 -0
  40. package/vendor/agent-root/src/agent/agent/index.ts +1772 -0
  41. package/vendor/agent-root/src/agent/agent/logger.ts +65 -0
  42. package/vendor/agent-root/src/agent/agent/message-utils.ts +101 -0
  43. package/vendor/agent-root/src/agent/agent/stream-events.ts +61 -0
  44. package/vendor/agent-root/src/agent/agent/telemetry.ts +123 -0
  45. package/vendor/agent-root/src/agent/agent/timeout-budget.ts +227 -0
  46. package/vendor/agent-root/src/agent/agent/tool-call-merge.ts +111 -0
  47. package/vendor/agent-root/src/agent/agent/tool-execution-ledger.ts +164 -0
  48. package/vendor/agent-root/src/agent/agent/write-buffer.ts +188 -0
  49. package/vendor/agent-root/src/agent/agent/write-file-session.ts +238 -0
  50. package/vendor/agent-root/src/agent/app/__test__/agent-app-service.test.ts +1053 -0
  51. package/vendor/agent-root/src/agent/app/__test__/minimal-agent-application.test.ts +158 -0
  52. package/vendor/agent-root/src/agent/app/__test__/sqlite-agent-app-store.test.ts +437 -0
  53. package/vendor/agent-root/src/agent/app/agent-app-service.ts +748 -0
  54. package/vendor/agent-root/src/agent/app/contracts.ts +109 -0
  55. package/vendor/agent-root/src/agent/app/index.ts +5 -0
  56. package/vendor/agent-root/src/agent/app/minimal-agent-application.ts +151 -0
  57. package/vendor/agent-root/src/agent/app/ports.ts +72 -0
  58. package/vendor/agent-root/src/agent/app/sqlite-agent-app-store.ts +1182 -0
  59. package/vendor/agent-root/src/agent/app/sqlite-client.ts +177 -0
  60. package/vendor/agent-root/src/agent/docs/cli-app-layer/00-README.md +36 -0
  61. package/vendor/agent-root/src/agent/docs/cli-app-layer/01-scope-and-goals.md +33 -0
  62. package/vendor/agent-root/src/agent/docs/cli-app-layer/02-architecture-overview.md +40 -0
  63. package/vendor/agent-root/src/agent/docs/cli-app-layer/03-domain-model-and-contracts.md +91 -0
  64. package/vendor/agent-root/src/agent/docs/cli-app-layer/04-ports-and-interfaces.md +116 -0
  65. package/vendor/agent-root/src/agent/docs/cli-app-layer/05-run-orchestration-and-state-machine.md +52 -0
  66. package/vendor/agent-root/src/agent/docs/cli-app-layer/06-cli-commands-and-ux.md +53 -0
  67. package/vendor/agent-root/src/agent/docs/cli-app-layer/07-storage-design-local.md +52 -0
  68. package/vendor/agent-root/src/agent/docs/cli-app-layer/08-error-and-observability.md +40 -0
  69. package/vendor/agent-root/src/agent/docs/cli-app-layer/09-security-and-policy-boundary.md +19 -0
  70. package/vendor/agent-root/src/agent/docs/cli-app-layer/10-test-plan-and-acceptance.md +28 -0
  71. package/vendor/agent-root/src/agent/docs/cli-app-layer/11-implementation-phases.md +26 -0
  72. package/vendor/agent-root/src/agent/docs/cli-app-layer/12-open-questions-and-risks.md +30 -0
  73. package/vendor/agent-root/src/agent/docs/cli-app-layer/13-sqlite-schema-fields-and-rationale.md +567 -0
  74. package/vendor/agent-root/src/agent/docs/cli-app-layer/14-project-flow-mermaid.md +583 -0
  75. package/vendor/agent-root/src/agent/docs/cli-app-layer/15-openclaw-style-project-blueprint.md +972 -0
  76. package/vendor/agent-root/src/agent/error-contract.ts +154 -0
  77. package/vendor/agent-root/src/agent/prompts/system.ts +246 -0
  78. package/vendor/agent-root/src/agent/prompts/system1.ts +208 -0
  79. package/vendor/agent-root/src/agent/storage/__test__/file-history-store.test.ts +98 -0
  80. package/vendor/agent-root/src/agent/storage/file-history-store.ts +313 -0
  81. package/vendor/agent-root/src/agent/storage/file-storage-config.ts +94 -0
  82. package/vendor/agent-root/src/agent/storage/file-system.ts +31 -0
  83. package/vendor/agent-root/src/agent/storage/file-write-service.ts +21 -0
  84. package/vendor/agent-root/src/agent/tool/__test__/base-tool.test.ts +413 -0
  85. package/vendor/agent-root/src/agent/tool/__test__/bash-policy.test.ts +356 -0
  86. package/vendor/agent-root/src/agent/tool/__test__/bash.mocked-coverage.test.ts +375 -0
  87. package/vendor/agent-root/src/agent/tool/__test__/bash.test.ts +372 -0
  88. package/vendor/agent-root/src/agent/tool/__test__/error.test.ts +108 -0
  89. package/vendor/agent-root/src/agent/tool/__test__/file-edit-tool.test.ts +258 -0
  90. package/vendor/agent-root/src/agent/tool/__test__/file-history-tools.test.ts +121 -0
  91. package/vendor/agent-root/src/agent/tool/__test__/file-read-tool.test.ts +210 -0
  92. package/vendor/agent-root/src/agent/tool/__test__/glob.test.ts +139 -0
  93. package/vendor/agent-root/src/agent/tool/__test__/grep.mocked-coverage.test.ts +456 -0
  94. package/vendor/agent-root/src/agent/tool/__test__/grep.test.ts +192 -0
  95. package/vendor/agent-root/src/agent/tool/__test__/lsp.test.ts +300 -0
  96. package/vendor/agent-root/src/agent/tool/__test__/outside-workspace-confirmation.test.ts +214 -0
  97. package/vendor/agent-root/src/agent/tool/__test__/path-security.test.ts +336 -0
  98. package/vendor/agent-root/src/agent/tool/__test__/skill-loader.test.ts +494 -0
  99. package/vendor/agent-root/src/agent/tool/__test__/skill-parser.test.ts +543 -0
  100. package/vendor/agent-root/src/agent/tool/__test__/skill-tool.test.ts +172 -0
  101. package/vendor/agent-root/src/agent/tool/__test__/task-concurrency-and-version.test.ts +116 -0
  102. package/vendor/agent-root/src/agent/tool/__test__/task-create-get-list-update.test.ts +267 -0
  103. package/vendor/agent-root/src/agent/tool/__test__/task-create.test.ts +519 -0
  104. package/vendor/agent-root/src/agent/tool/__test__/task-errors.test.ts +225 -0
  105. package/vendor/agent-root/src/agent/tool/__test__/task-output-blocking.test.ts +223 -0
  106. package/vendor/agent-root/src/agent/tool/__test__/task-output.test.ts +184 -0
  107. package/vendor/agent-root/src/agent/tool/__test__/task-parent-abort.test.ts +287 -0
  108. package/vendor/agent-root/src/agent/tool/__test__/task-real-runner-adapter.test.ts +190 -0
  109. package/vendor/agent-root/src/agent/tool/__test__/task-run-lifecycle.test.ts +352 -0
  110. package/vendor/agent-root/src/agent/tool/__test__/task-store-runner-branches.test.ts +395 -0
  111. package/vendor/agent-root/src/agent/tool/__test__/task-store.test.ts +391 -0
  112. package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config-integration.test.ts +176 -0
  113. package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config.test.ts +68 -0
  114. package/vendor/agent-root/src/agent/tool/__test__/task-tools-core-edges.test.ts +630 -0
  115. package/vendor/agent-root/src/agent/tool/__test__/task-tools-runtime-edges.test.ts +732 -0
  116. package/vendor/agent-root/src/agent/tool/__test__/task-types.test.ts +494 -0
  117. package/vendor/agent-root/src/agent/tool/__test__/task-utils-branches.test.ts +175 -0
  118. package/vendor/agent-root/src/agent/tool/__test__/tool-manager.test.ts +505 -0
  119. package/vendor/agent-root/src/agent/tool/__test__/types.test.ts +55 -0
  120. package/vendor/agent-root/src/agent/tool/__test__/web-fetch.test.ts +244 -0
  121. package/vendor/agent-root/src/agent/tool/__test__/web-search.test.ts +290 -0
  122. package/vendor/agent-root/src/agent/tool/__test__/write-file.test.ts +368 -0
  123. package/vendor/agent-root/src/agent/tool/base-tool.ts +345 -0
  124. package/vendor/agent-root/src/agent/tool/bash-policy.ts +636 -0
  125. package/vendor/agent-root/src/agent/tool/bash.ts +688 -0
  126. package/vendor/agent-root/src/agent/tool/error.ts +131 -0
  127. package/vendor/agent-root/src/agent/tool/file-edit-tool.ts +264 -0
  128. package/vendor/agent-root/src/agent/tool/file-history-list.ts +103 -0
  129. package/vendor/agent-root/src/agent/tool/file-history-restore.ts +149 -0
  130. package/vendor/agent-root/src/agent/tool/file-read-tool.ts +211 -0
  131. package/vendor/agent-root/src/agent/tool/glob.ts +171 -0
  132. package/vendor/agent-root/src/agent/tool/grep.ts +496 -0
  133. package/vendor/agent-root/src/agent/tool/lsp.ts +481 -0
  134. package/vendor/agent-root/src/agent/tool/path-security.ts +117 -0
  135. package/vendor/agent-root/src/agent/tool/search/common.ts +153 -0
  136. package/vendor/agent-root/src/agent/tool/skill/index.ts +13 -0
  137. package/vendor/agent-root/src/agent/tool/skill/loader.ts +229 -0
  138. package/vendor/agent-root/src/agent/tool/skill/parser.ts +124 -0
  139. package/vendor/agent-root/src/agent/tool/skill/types.ts +27 -0
  140. package/vendor/agent-root/src/agent/tool/skill-tool.ts +143 -0
  141. package/vendor/agent-root/src/agent/tool/task-create.ts +186 -0
  142. package/vendor/agent-root/src/agent/tool/task-errors.ts +42 -0
  143. package/vendor/agent-root/src/agent/tool/task-get.ts +116 -0
  144. package/vendor/agent-root/src/agent/tool/task-graph.ts +78 -0
  145. package/vendor/agent-root/src/agent/tool/task-list.ts +141 -0
  146. package/vendor/agent-root/src/agent/tool/task-mock-runner-adapter.ts +232 -0
  147. package/vendor/agent-root/src/agent/tool/task-output.ts +223 -0
  148. package/vendor/agent-root/src/agent/tool/task-parent-abort.ts +115 -0
  149. package/vendor/agent-root/src/agent/tool/task-real-runner-adapter.ts +336 -0
  150. package/vendor/agent-root/src/agent/tool/task-runner-adapter.ts +55 -0
  151. package/vendor/agent-root/src/agent/tool/task-stop.ts +187 -0
  152. package/vendor/agent-root/src/agent/tool/task-store.ts +217 -0
  153. package/vendor/agent-root/src/agent/tool/task-subagent-config.ts +149 -0
  154. package/vendor/agent-root/src/agent/tool/task-types.ts +264 -0
  155. package/vendor/agent-root/src/agent/tool/task-update.ts +315 -0
  156. package/vendor/agent-root/src/agent/tool/task.ts +209 -0
  157. package/vendor/agent-root/src/agent/tool/tool-manager.ts +362 -0
  158. package/vendor/agent-root/src/agent/tool/tool-prompts.ts +242 -0
  159. package/vendor/agent-root/src/agent/tool/types.ts +116 -0
  160. package/vendor/agent-root/src/agent/tool/web-fetch.ts +227 -0
  161. package/vendor/agent-root/src/agent/tool/web-search.ts +208 -0
  162. package/vendor/agent-root/src/agent/tool/write-file.ts +497 -0
  163. package/vendor/agent-root/src/agent/types.ts +232 -0
  164. package/vendor/agent-root/src/agent/utils/__tests__/index.test.ts +18 -0
  165. package/vendor/agent-root/src/agent/utils/__tests__/message-utils.test.ts +610 -0
  166. package/vendor/agent-root/src/agent/utils/__tests__/message.test.ts +223 -0
  167. package/vendor/agent-root/src/agent/utils/__tests__/token.test.ts +42 -0
  168. package/vendor/agent-root/src/agent/utils/index.ts +16 -0
  169. package/vendor/agent-root/src/agent/utils/message.ts +171 -0
  170. package/vendor/agent-root/src/agent/utils/token.ts +28 -0
  171. package/vendor/agent-root/src/config/__tests__/load-config-to-env.test.ts +129 -0
  172. package/vendor/agent-root/src/config/__tests__/loader.test.ts +247 -0
  173. package/vendor/agent-root/src/config/__tests__/runtime.test.ts +88 -0
  174. package/vendor/agent-root/src/config/index.ts +54 -0
  175. package/vendor/agent-root/src/config/loader.ts +431 -0
  176. package/vendor/agent-root/src/config/paths.ts +30 -0
  177. package/vendor/agent-root/src/config/runtime.ts +163 -0
  178. package/vendor/agent-root/src/config/types.ts +70 -0
  179. package/vendor/agent-root/src/logger/index.ts +57 -0
  180. package/vendor/agent-root/src/logger/logger.ts +819 -0
  181. package/vendor/agent-root/src/logger/types.ts +150 -0
  182. package/vendor/agent-root/src/providers/__tests__/errors.test.ts +441 -0
  183. package/vendor/agent-root/src/providers/__tests__/index.test.ts +16 -0
  184. package/vendor/agent-root/src/providers/__tests__/openai-compatible.options.test.ts +318 -0
  185. package/vendor/agent-root/src/providers/__tests__/openai-compatible.test.ts +600 -0
  186. package/vendor/agent-root/src/providers/__tests__/registry.test.ts +449 -0
  187. package/vendor/agent-root/src/providers/__tests__/responses-adapter.test.ts +298 -0
  188. package/vendor/agent-root/src/providers/adapters/__tests__/anthropic.test.ts +354 -0
  189. package/vendor/agent-root/src/providers/adapters/__tests__/kimi.test.ts +58 -0
  190. package/vendor/agent-root/src/providers/adapters/__tests__/standard.test.ts +261 -0
  191. package/vendor/agent-root/src/providers/adapters/anthropic.ts +572 -0
  192. package/vendor/agent-root/src/providers/adapters/base.ts +131 -0
  193. package/vendor/agent-root/src/providers/adapters/kimi.ts +48 -0
  194. package/vendor/agent-root/src/providers/adapters/responses.ts +732 -0
  195. package/vendor/agent-root/src/providers/adapters/standard.ts +120 -0
  196. package/vendor/agent-root/src/providers/http/__tests__/client.timeout.test.ts +313 -0
  197. package/vendor/agent-root/src/providers/http/client.ts +289 -0
  198. package/vendor/agent-root/src/providers/http/stream-parser.ts +109 -0
  199. package/vendor/agent-root/src/providers/index.ts +76 -0
  200. package/vendor/agent-root/src/providers/kimi-headers.ts +177 -0
  201. package/vendor/agent-root/src/providers/openai-compatible.ts +387 -0
  202. package/vendor/agent-root/src/providers/registry/model-config.ts +230 -0
  203. package/vendor/agent-root/src/providers/registry/provider-factory.ts +123 -0
  204. package/vendor/agent-root/src/providers/registry.ts +135 -0
  205. package/vendor/agent-root/src/providers/types/api.ts +284 -0
  206. package/vendor/agent-root/src/providers/types/config.ts +58 -0
  207. package/vendor/agent-root/src/providers/types/errors.ts +323 -0
  208. package/vendor/agent-root/src/providers/types/index.ts +72 -0
  209. package/vendor/agent-root/src/providers/types/provider.ts +45 -0
  210. package/vendor/agent-root/src/providers/types/registry.ts +88 -0
@@ -0,0 +1,352 @@
1
+ import * as os from 'node:os';
2
+ import * as path from 'node:path';
3
+ import { promises as fs } from 'node:fs';
4
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
5
+ import { TaskStore } from '../task-store';
6
+ import { InProcessMockRunnerAdapter } from '../task-runner-adapter';
7
+ import { TaskCreateTool } from '../task-create';
8
+ import { TaskTool } from '../task';
9
+ import { TaskOutputTool } from '../task-output';
10
+ import { TaskStopTool } from '../task-stop';
11
+ import { TaskGetTool } from '../task-get';
12
+ import { PARENT_ABORT_REASON } from '../task-parent-abort';
13
+ import type { AgentRunEntity } from '../task-types';
14
+ import type { SubagentRunnerAdapter } from '../task-runner-adapter';
15
+
16
+ function parseOutput<T>(output: string | undefined): T {
17
+ return JSON.parse(output || '{}') as T;
18
+ }
19
+
20
+ async function waitUntil(
21
+ condition: () => boolean | Promise<boolean>,
22
+ timeoutMs = 1500,
23
+ intervalMs = 20
24
+ ): Promise<void> {
25
+ const start = Date.now();
26
+ while (Date.now() - start < timeoutMs) {
27
+ if (await condition()) {
28
+ return;
29
+ }
30
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
31
+ }
32
+ throw new Error('Timed out waiting for condition');
33
+ }
34
+
35
+ function makeRunningRun(agentId: string, prompt = 'x'): AgentRunEntity {
36
+ const now = Date.now();
37
+ return {
38
+ agentId,
39
+ status: 'running',
40
+ subagentType: 'Plan',
41
+ prompt,
42
+ createdAt: now,
43
+ startedAt: now,
44
+ updatedAt: now,
45
+ metadata: {},
46
+ version: 1,
47
+ };
48
+ }
49
+
50
+ describe('task/task_output/task_stop lifecycle', () => {
51
+ let baseDir: string;
52
+ let store: TaskStore;
53
+ let runner: InProcessMockRunnerAdapter;
54
+ let taskCreate: TaskCreateTool;
55
+ let taskTool: TaskTool;
56
+ let taskOutput: TaskOutputTool;
57
+ let taskStop: TaskStopTool;
58
+ let taskGet: TaskGetTool;
59
+
60
+ beforeEach(async () => {
61
+ baseDir = await fs.mkdtemp(path.join(os.tmpdir(), 'renx-task-run-'));
62
+ store = new TaskStore({ baseDir });
63
+ runner = new InProcessMockRunnerAdapter(store, { completionDelayMs: 80 });
64
+ taskCreate = new TaskCreateTool({ store });
65
+ taskTool = new TaskTool({ store, runner });
66
+ taskOutput = new TaskOutputTool({ store, runner });
67
+ taskStop = new TaskStopTool({ store, runner });
68
+ taskGet = new TaskGetTool({ store });
69
+ });
70
+
71
+ afterEach(async () => {
72
+ await fs.rm(baseDir, { recursive: true, force: true });
73
+ });
74
+
75
+ it('runs foreground task and links completion to planning task', async () => {
76
+ const created = parseOutput<{ task: { id: string } }>(
77
+ (
78
+ await taskCreate.execute({
79
+ namespace: 'run1',
80
+ subject: 'Design auth schema',
81
+ description: 'Design auth schema with entities and indexes.',
82
+ })
83
+ ).output
84
+ ).task;
85
+
86
+ const execution = await taskTool.execute({
87
+ namespace: 'run1',
88
+ subagent_type: 'Plan',
89
+ prompt: 'Create a design for auth schema.',
90
+ linked_task_id: created.id,
91
+ run_in_background: false,
92
+ });
93
+ expect(execution.success).toBe(true);
94
+ const runPayload = parseOutput<{ agent_run: { status: string; agentId: string } }>(
95
+ execution.output
96
+ );
97
+ expect(runPayload.agent_run.status).toBe('completed');
98
+
99
+ const detail = await taskGet.execute({
100
+ namespace: 'run1',
101
+ task_id: created.id,
102
+ });
103
+ const detailPayload = parseOutput<{ task: { status: string; agentId?: string } }>(
104
+ detail.output
105
+ );
106
+ expect(detailPayload.task.status).toBe('completed');
107
+ expect(detailPayload.task.agentId).toBe(runPayload.agent_run.agentId);
108
+ });
109
+
110
+ it('runs background task and output can observe completion', async () => {
111
+ const execution = await taskTool.execute({
112
+ namespace: 'run2',
113
+ subagent_type: 'general-purpose',
114
+ prompt: 'Background run example',
115
+ run_in_background: true,
116
+ });
117
+ expect(execution.success).toBe(true);
118
+
119
+ const payload = parseOutput<{ agent_run: { agentId: string; status: string } }>(
120
+ execution.output
121
+ );
122
+ expect(payload.agent_run.status).toBe('running');
123
+
124
+ const output = await taskOutput.execute({
125
+ namespace: 'run2',
126
+ agent_id: payload.agent_run.agentId,
127
+ timeout_ms: 5000,
128
+ });
129
+ expect(output.success).toBe(true);
130
+ const outPayload = parseOutput<{ agent_run: { status: string }; completed: boolean }>(
131
+ output.output
132
+ );
133
+ expect(outPayload.agent_run.status).toBe('completed');
134
+ expect(outPayload.completed).toBe(true);
135
+ });
136
+
137
+ it('keeps background subagent running after parent tool execution returns normally', async () => {
138
+ const controller = new AbortController();
139
+ const execution = await taskTool.execute(
140
+ {
141
+ namespace: 'run2b',
142
+ subagent_type: 'general-purpose',
143
+ prompt: 'Background run should outlive parent tool return',
144
+ run_in_background: true,
145
+ },
146
+ {
147
+ toolCallId: 'parent-finish-background-keeps-running',
148
+ loopIndex: 1,
149
+ agent: {},
150
+ toolAbortSignal: controller.signal,
151
+ }
152
+ );
153
+ expect(execution.success).toBe(true);
154
+
155
+ const payload = parseOutput<{ agent_run: { agentId: string; status: string } }>(
156
+ execution.output
157
+ );
158
+ expect(payload.agent_run.status).toBe('running');
159
+
160
+ const stateAfterReturn = await store.getState('run2b');
161
+ expect(stateAfterReturn.agentRuns[payload.agent_run.agentId]?.status).toBe('running');
162
+
163
+ await waitUntil(async () => {
164
+ const state = await store.getState('run2b');
165
+ return state.agentRuns[payload.agent_run.agentId]?.status === 'completed';
166
+ });
167
+
168
+ const finalState = await store.getState('run2b');
169
+ expect(controller.signal.aborted).toBe(false);
170
+ expect(finalState.agentRuns[payload.agent_run.agentId]?.status).toBe('completed');
171
+ });
172
+
173
+ it('stops a running background task and cancels linked task', async () => {
174
+ const linked = parseOutput<{ task: { id: string } }>(
175
+ (
176
+ await taskCreate.execute({
177
+ namespace: 'run3',
178
+ subject: 'Long running task',
179
+ description: 'Long running task that will be cancelled by stop.',
180
+ })
181
+ ).output
182
+ ).task;
183
+
184
+ const execution = await taskTool.execute({
185
+ namespace: 'run3',
186
+ subagent_type: 'general-purpose',
187
+ prompt: 'Background run to cancel',
188
+ run_in_background: true,
189
+ linked_task_id: linked.id,
190
+ });
191
+ const runPayload = parseOutput<{ agent_run: { agentId: string } }>(execution.output);
192
+
193
+ const stopped = await taskStop.execute({
194
+ namespace: 'run3',
195
+ agent_id: runPayload.agent_run.agentId,
196
+ reason: 'User cancelled',
197
+ cancel_linked_task: true,
198
+ });
199
+ expect(stopped.success).toBe(true);
200
+ const stopPayload = parseOutput<{
201
+ agent_run: { status: string };
202
+ cancelled_task_ids: string[];
203
+ }>(stopped.output);
204
+ expect(stopPayload.agent_run.status).toBe('cancelled');
205
+ expect(stopPayload.cancelled_task_ids).toContain(linked.id);
206
+
207
+ const detail = await taskGet.execute({
208
+ namespace: 'run3',
209
+ task_id: linked.id,
210
+ });
211
+ const detailPayload = parseOutput<{ task: { status: string } }>(detail.output);
212
+ expect(detailPayload.task.status).toBe('cancelled');
213
+ });
214
+
215
+ it('maps [TASK_FAIL] token to failed run and failed linked task', async () => {
216
+ const linked = parseOutput<{ task: { id: string } }>(
217
+ (
218
+ await taskCreate.execute({
219
+ namespace: 'run4',
220
+ subject: 'Failing task',
221
+ description: 'Task expected to fail in execution stage.',
222
+ })
223
+ ).output
224
+ ).task;
225
+
226
+ const execution = await taskTool.execute({
227
+ namespace: 'run4',
228
+ subagent_type: 'general-purpose',
229
+ prompt: 'Trigger [TASK_FAIL] for test',
230
+ linked_task_id: linked.id,
231
+ run_in_background: false,
232
+ });
233
+ expect(execution.success).toBe(true);
234
+ const runPayload = parseOutput<{ agent_run: { status: string } }>(execution.output);
235
+ expect(runPayload.agent_run.status).toBe('failed');
236
+
237
+ const detail = await taskGet.execute({
238
+ namespace: 'run4',
239
+ task_id: linked.id,
240
+ });
241
+ const detailPayload = parseOutput<{ task: { status: string } }>(detail.output);
242
+ expect(detailPayload.task.status).toBe('failed');
243
+ });
244
+
245
+ it('cascades parent abort to subagent cancel and linked task cancel', async () => {
246
+ const linked = parseOutput<{ task: { id: string } }>(
247
+ (
248
+ await taskCreate.execute({
249
+ namespace: 'run5',
250
+ subject: 'Cascade cancel task',
251
+ description: 'Linked task should cancel when parent aborts tool execution.',
252
+ })
253
+ ).output
254
+ ).task;
255
+
256
+ const controller = new AbortController();
257
+ const chunks: Array<{ type: string; content?: string }> = [];
258
+ const execution = await taskTool.execute(
259
+ {
260
+ namespace: 'run5',
261
+ subagent_type: 'Plan',
262
+ prompt: 'Run that should be cancelled via parent abort',
263
+ run_in_background: true,
264
+ linked_task_id: linked.id,
265
+ },
266
+ {
267
+ toolCallId: 'parent-abort-cascade',
268
+ loopIndex: 1,
269
+ agent: {},
270
+ toolAbortSignal: controller.signal,
271
+ onChunk: async (event) => {
272
+ chunks.push({ type: event.type, content: String(event.content || '') });
273
+ },
274
+ }
275
+ );
276
+
277
+ const agentId = parseOutput<{ agent_run: { agentId: string } }>(execution.output).agent_run
278
+ .agentId;
279
+ controller.abort();
280
+
281
+ await waitUntil(async () => {
282
+ const state = await store.getState('run5');
283
+ return state.agentRuns[agentId]?.status === 'cancelled';
284
+ });
285
+
286
+ const state = await store.getState('run5');
287
+ expect(state.agentRuns[agentId]?.status).toBe('cancelled');
288
+ expect(state.agentRuns[agentId]?.error).toBe(PARENT_ABORT_REASON);
289
+
290
+ const detail = await taskGet.execute({
291
+ namespace: 'run5',
292
+ task_id: linked.id,
293
+ include_history: true,
294
+ });
295
+ const taskPayload = parseOutput<{
296
+ task: { status: string; history: Array<{ actor?: string; reason?: string }> };
297
+ }>(detail.output);
298
+ expect(taskPayload.task.status).toBe('cancelled');
299
+ expect(taskPayload.task.history.some((item) => item.actor === 'task-parent-abort')).toBe(true);
300
+ expect(
301
+ taskPayload.task.history.some(
302
+ (item) => item.actor === 'task-parent-abort' && item.reason === PARENT_ABORT_REASON
303
+ )
304
+ ).toBe(true);
305
+ expect(
306
+ chunks.some(
307
+ (event) =>
308
+ event.type === 'info' && event.content?.includes('subagent cancelled by parent abort')
309
+ )
310
+ ).toBe(true);
311
+ });
312
+
313
+ it('handles already-aborted parent signal and emits stderr chunk when cascade cancel fails', async () => {
314
+ const runner: SubagentRunnerAdapter = {
315
+ start: async () => makeRunningRun('agent-parent-fail'),
316
+ poll: async () => null,
317
+ cancel: async () => {
318
+ throw new Error('boom');
319
+ },
320
+ };
321
+ const taskWithFailingCancel = new TaskTool({ store, runner });
322
+
323
+ const controller = new AbortController();
324
+ controller.abort();
325
+ const chunks: Array<{ type: string; content?: string }> = [];
326
+
327
+ await taskWithFailingCancel.execute(
328
+ {
329
+ namespace: 'run6',
330
+ subagent_type: 'Plan',
331
+ prompt: 'Parent already aborted before execute',
332
+ run_in_background: true,
333
+ },
334
+ {
335
+ toolCallId: 'already-aborted-parent',
336
+ loopIndex: 2,
337
+ agent: {},
338
+ toolAbortSignal: controller.signal,
339
+ onChunk: async (event) => {
340
+ chunks.push({ type: event.type, content: String(event.content || '') });
341
+ },
342
+ }
343
+ );
344
+
345
+ await waitUntil(() =>
346
+ chunks.some(
347
+ (event) =>
348
+ event.type === 'stderr' && event.content?.includes('failed to cascade parent abort: boom')
349
+ )
350
+ );
351
+ });
352
+ });