@renxqoo/renx-code 0.0.8 → 0.0.10
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 +114 -40
- package/bin/renx.cjs +79 -42
- package/bin/renx.exe +0 -0
- package/package.json +10 -28
- package/src/App.tsx +0 -297
- package/src/agent/runtime/event-format.ts +0 -258
- package/src/agent/runtime/model-types.ts +0 -13
- package/src/agent/runtime/runtime.context-usage.test.ts +0 -192
- package/src/agent/runtime/runtime.error-handling.test.ts +0 -235
- package/src/agent/runtime/runtime.simple.test.ts +0 -16
- package/src/agent/runtime/runtime.test.ts +0 -296
- package/src/agent/runtime/runtime.ts +0 -875
- package/src/agent/runtime/runtime.usage-forwarding.test.ts +0 -228
- package/src/agent/runtime/source-modules.test.ts +0 -38
- package/src/agent/runtime/source-modules.ts +0 -370
- package/src/agent/runtime/tool-call-buffer.test.ts +0 -65
- package/src/agent/runtime/tool-call-buffer.ts +0 -60
- package/src/agent/runtime/tool-confirmation.test.ts +0 -56
- package/src/agent/runtime/tool-confirmation.ts +0 -15
- package/src/agent/runtime/types.ts +0 -99
- package/src/commands/slash-commands.test.ts +0 -216
- package/src/commands/slash-commands.ts +0 -64
- package/src/components/chat/assistant-reply.test.tsx +0 -47
- package/src/components/chat/assistant-reply.tsx +0 -136
- package/src/components/chat/assistant-segment.test.ts +0 -99
- package/src/components/chat/assistant-segment.tsx +0 -125
- package/src/components/chat/assistant-tool-group.tsx +0 -900
- package/src/components/chat/code-block.test.tsx +0 -206
- package/src/components/chat/code-block.tsx +0 -313
- package/src/components/chat/prompt-card.tsx +0 -81
- package/src/components/chat/segment-groups.test.ts +0 -52
- package/src/components/chat/segment-groups.ts +0 -106
- package/src/components/chat/turn-item.tsx +0 -39
- package/src/components/conversation-panel.tsx +0 -43
- package/src/components/file-mention-menu.tsx +0 -77
- package/src/components/file-picker-dialog.tsx +0 -206
- package/src/components/footer-hints.tsx +0 -75
- package/src/components/model-picker-dialog.tsx +0 -248
- package/src/components/prompt.tsx +0 -233
- package/src/components/slash-command-menu.tsx +0 -65
- package/src/components/tool-confirm-dialog-content.test.ts +0 -103
- package/src/components/tool-confirm-dialog-content.ts +0 -186
- package/src/components/tool-confirm-dialog.tsx +0 -187
- package/src/components/tool-display-config.ts +0 -119
- package/src/context-usage-regressions.test.ts +0 -26
- package/src/files/attachment-capabilities.test.ts +0 -30
- package/src/files/attachment-capabilities.ts +0 -50
- package/src/files/attachment-content.ts +0 -153
- package/src/files/file-mention-query.test.ts +0 -34
- package/src/files/file-mention-query.ts +0 -32
- package/src/files/prompt-display.ts +0 -13
- package/src/files/types.ts +0 -5
- package/src/files/workspace-files.ts +0 -61
- package/src/hooks/agent-event-handlers.test.ts +0 -207
- package/src/hooks/agent-event-handlers.ts +0 -196
- package/src/hooks/chat-local-replies.fixed.test.ts +0 -119
- package/src/hooks/chat-local-replies.test.ts +0 -153
- package/src/hooks/chat-local-replies.ts +0 -63
- package/src/hooks/turn-updater.test.ts +0 -70
- package/src/hooks/turn-updater.ts +0 -166
- package/src/hooks/use-agent-chat.context.test.ts +0 -10
- package/src/hooks/use-agent-chat.status.test.ts +0 -14
- package/src/hooks/use-agent-chat.test.ts +0 -80
- package/src/hooks/use-agent-chat.ts +0 -621
- package/src/hooks/use-file-mention-menu.ts +0 -196
- package/src/hooks/use-file-picker.ts +0 -185
- package/src/hooks/use-model-picker.ts +0 -196
- package/src/hooks/use-slash-command-menu.ts +0 -154
- package/src/index.tsx +0 -55
- package/src/runtime/clipboard.test.ts +0 -43
- package/src/runtime/clipboard.ts +0 -89
- package/src/runtime/exit.test.ts +0 -177
- package/src/runtime/exit.ts +0 -98
- package/src/runtime/runtime-support.test.ts +0 -31
- package/src/runtime/terminal-theme.test.ts +0 -55
- package/src/runtime/terminal-theme.ts +0 -196
- package/src/types/chat.ts +0 -32
- package/src/types/message-content.ts +0 -48
- package/src/ui/open-code-theme.ts +0 -176
- package/src/ui/opencode-markdown.ts +0 -211
- package/src/ui/theme.simple.test.ts +0 -52
- package/src/ui/theme.test.ts +0 -151
- package/src/ui/theme.ts +0 -152
- package/src/utils/time.test.ts +0 -144
- package/src/utils/time.ts +0 -7
- package/tsconfig.json +0 -30
- package/vendor/agent-root/src/agent/ENTERPRISE_ACCEPTANCE_CHECKLIST.md +0 -95
- package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.html +0 -1345
- package/vendor/agent-root/src/agent/ENTERPRISE_REALTIME.md +0 -1353
- package/vendor/agent-root/src/agent/ERROR_CONTRACT.md +0 -60
- package/vendor/agent-root/src/agent/TEST_COVERAGE_ANALYSIS.md +0 -278
- package/vendor/agent-root/src/agent/__test__/error-contract.test.ts +0 -72
- package/vendor/agent-root/src/agent/__test__/types.test.ts +0 -137
- package/vendor/agent-root/src/agent/agent/__test__/abort-runtime.test.ts +0 -83
- package/vendor/agent-root/src/agent/agent/__test__/callback-safety.test.ts +0 -34
- package/vendor/agent-root/src/agent/agent/__test__/compaction.test.ts +0 -323
- package/vendor/agent-root/src/agent/agent/__test__/concurrency.test.ts +0 -290
- package/vendor/agent-root/src/agent/agent/__test__/error-normalizer.test.ts +0 -377
- package/vendor/agent-root/src/agent/agent/__test__/error.test.ts +0 -212
- package/vendor/agent-root/src/agent/agent/__test__/fault-injection.test.ts +0 -295
- package/vendor/agent-root/src/agent/agent/__test__/index.test.ts +0 -3607
- package/vendor/agent-root/src/agent/agent/__test__/logger.test.ts +0 -35
- package/vendor/agent-root/src/agent/agent/__test__/message-utils.test.ts +0 -517
- package/vendor/agent-root/src/agent/agent/__test__/telemetry.test.ts +0 -97
- package/vendor/agent-root/src/agent/agent/__test__/timeout-budget.test.ts +0 -479
- package/vendor/agent-root/src/agent/agent/__test__/tool-call-merge.test.ts +0 -80
- package/vendor/agent-root/src/agent/agent/__test__/tool-execution-ledger.test.ts +0 -76
- package/vendor/agent-root/src/agent/agent/__test__/write-buffer.test.ts +0 -173
- package/vendor/agent-root/src/agent/agent/__test__/write-file-session.test.ts +0 -109
- package/vendor/agent-root/src/agent/agent/abort-runtime.ts +0 -71
- package/vendor/agent-root/src/agent/agent/callback-safety.ts +0 -33
- package/vendor/agent-root/src/agent/agent/compaction.ts +0 -291
- package/vendor/agent-root/src/agent/agent/concurrency.ts +0 -103
- package/vendor/agent-root/src/agent/agent/error-normalizer.ts +0 -190
- package/vendor/agent-root/src/agent/agent/error.ts +0 -198
- package/vendor/agent-root/src/agent/agent/index.ts +0 -1772
- package/vendor/agent-root/src/agent/agent/logger.ts +0 -65
- package/vendor/agent-root/src/agent/agent/message-utils.ts +0 -101
- package/vendor/agent-root/src/agent/agent/stream-events.ts +0 -61
- package/vendor/agent-root/src/agent/agent/telemetry.ts +0 -123
- package/vendor/agent-root/src/agent/agent/timeout-budget.ts +0 -227
- package/vendor/agent-root/src/agent/agent/tool-call-merge.ts +0 -111
- package/vendor/agent-root/src/agent/agent/tool-execution-ledger.ts +0 -164
- package/vendor/agent-root/src/agent/agent/write-buffer.ts +0 -188
- package/vendor/agent-root/src/agent/agent/write-file-session.ts +0 -238
- package/vendor/agent-root/src/agent/app/__test__/agent-app-service.test.ts +0 -1053
- package/vendor/agent-root/src/agent/app/__test__/minimal-agent-application.test.ts +0 -158
- package/vendor/agent-root/src/agent/app/__test__/sqlite-agent-app-store.test.ts +0 -437
- package/vendor/agent-root/src/agent/app/agent-app-service.ts +0 -748
- package/vendor/agent-root/src/agent/app/contracts.ts +0 -109
- package/vendor/agent-root/src/agent/app/index.ts +0 -5
- package/vendor/agent-root/src/agent/app/minimal-agent-application.ts +0 -151
- package/vendor/agent-root/src/agent/app/ports.ts +0 -72
- package/vendor/agent-root/src/agent/app/sqlite-agent-app-store.ts +0 -1182
- package/vendor/agent-root/src/agent/app/sqlite-client.ts +0 -177
- package/vendor/agent-root/src/agent/docs/cli-app-layer/00-README.md +0 -36
- package/vendor/agent-root/src/agent/docs/cli-app-layer/01-scope-and-goals.md +0 -33
- package/vendor/agent-root/src/agent/docs/cli-app-layer/02-architecture-overview.md +0 -40
- package/vendor/agent-root/src/agent/docs/cli-app-layer/03-domain-model-and-contracts.md +0 -91
- package/vendor/agent-root/src/agent/docs/cli-app-layer/04-ports-and-interfaces.md +0 -116
- package/vendor/agent-root/src/agent/docs/cli-app-layer/05-run-orchestration-and-state-machine.md +0 -52
- package/vendor/agent-root/src/agent/docs/cli-app-layer/06-cli-commands-and-ux.md +0 -53
- package/vendor/agent-root/src/agent/docs/cli-app-layer/07-storage-design-local.md +0 -52
- package/vendor/agent-root/src/agent/docs/cli-app-layer/08-error-and-observability.md +0 -40
- package/vendor/agent-root/src/agent/docs/cli-app-layer/09-security-and-policy-boundary.md +0 -19
- package/vendor/agent-root/src/agent/docs/cli-app-layer/10-test-plan-and-acceptance.md +0 -28
- package/vendor/agent-root/src/agent/docs/cli-app-layer/11-implementation-phases.md +0 -26
- package/vendor/agent-root/src/agent/docs/cli-app-layer/12-open-questions-and-risks.md +0 -30
- package/vendor/agent-root/src/agent/docs/cli-app-layer/13-sqlite-schema-fields-and-rationale.md +0 -567
- package/vendor/agent-root/src/agent/docs/cli-app-layer/14-project-flow-mermaid.md +0 -583
- package/vendor/agent-root/src/agent/docs/cli-app-layer/15-openclaw-style-project-blueprint.md +0 -972
- package/vendor/agent-root/src/agent/error-contract.ts +0 -154
- package/vendor/agent-root/src/agent/prompts/system.ts +0 -246
- package/vendor/agent-root/src/agent/prompts/system1.ts +0 -208
- package/vendor/agent-root/src/agent/storage/__test__/file-history-store.test.ts +0 -98
- package/vendor/agent-root/src/agent/storage/file-history-store.ts +0 -313
- package/vendor/agent-root/src/agent/storage/file-storage-config.ts +0 -94
- package/vendor/agent-root/src/agent/storage/file-system.ts +0 -31
- package/vendor/agent-root/src/agent/storage/file-write-service.ts +0 -21
- package/vendor/agent-root/src/agent/tool/__test__/base-tool.test.ts +0 -413
- package/vendor/agent-root/src/agent/tool/__test__/bash-policy.test.ts +0 -356
- package/vendor/agent-root/src/agent/tool/__test__/bash.mocked-coverage.test.ts +0 -375
- package/vendor/agent-root/src/agent/tool/__test__/bash.test.ts +0 -372
- package/vendor/agent-root/src/agent/tool/__test__/error.test.ts +0 -108
- package/vendor/agent-root/src/agent/tool/__test__/file-edit-tool.test.ts +0 -258
- package/vendor/agent-root/src/agent/tool/__test__/file-history-tools.test.ts +0 -121
- package/vendor/agent-root/src/agent/tool/__test__/file-read-tool.test.ts +0 -210
- package/vendor/agent-root/src/agent/tool/__test__/glob.test.ts +0 -139
- package/vendor/agent-root/src/agent/tool/__test__/grep.mocked-coverage.test.ts +0 -456
- package/vendor/agent-root/src/agent/tool/__test__/grep.test.ts +0 -192
- package/vendor/agent-root/src/agent/tool/__test__/lsp.test.ts +0 -300
- package/vendor/agent-root/src/agent/tool/__test__/outside-workspace-confirmation.test.ts +0 -214
- package/vendor/agent-root/src/agent/tool/__test__/path-security.test.ts +0 -336
- package/vendor/agent-root/src/agent/tool/__test__/skill-loader.test.ts +0 -494
- package/vendor/agent-root/src/agent/tool/__test__/skill-parser.test.ts +0 -543
- package/vendor/agent-root/src/agent/tool/__test__/skill-tool.test.ts +0 -172
- package/vendor/agent-root/src/agent/tool/__test__/task-concurrency-and-version.test.ts +0 -116
- package/vendor/agent-root/src/agent/tool/__test__/task-create-get-list-update.test.ts +0 -267
- package/vendor/agent-root/src/agent/tool/__test__/task-create.test.ts +0 -519
- package/vendor/agent-root/src/agent/tool/__test__/task-errors.test.ts +0 -225
- package/vendor/agent-root/src/agent/tool/__test__/task-output-blocking.test.ts +0 -223
- package/vendor/agent-root/src/agent/tool/__test__/task-output.test.ts +0 -184
- package/vendor/agent-root/src/agent/tool/__test__/task-parent-abort.test.ts +0 -287
- package/vendor/agent-root/src/agent/tool/__test__/task-real-runner-adapter.test.ts +0 -190
- package/vendor/agent-root/src/agent/tool/__test__/task-run-lifecycle.test.ts +0 -352
- package/vendor/agent-root/src/agent/tool/__test__/task-store-runner-branches.test.ts +0 -395
- package/vendor/agent-root/src/agent/tool/__test__/task-store.test.ts +0 -391
- package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config-integration.test.ts +0 -176
- package/vendor/agent-root/src/agent/tool/__test__/task-subagent-config.test.ts +0 -68
- package/vendor/agent-root/src/agent/tool/__test__/task-tools-core-edges.test.ts +0 -630
- package/vendor/agent-root/src/agent/tool/__test__/task-tools-runtime-edges.test.ts +0 -732
- package/vendor/agent-root/src/agent/tool/__test__/task-types.test.ts +0 -494
- package/vendor/agent-root/src/agent/tool/__test__/task-utils-branches.test.ts +0 -175
- package/vendor/agent-root/src/agent/tool/__test__/tool-manager.test.ts +0 -505
- package/vendor/agent-root/src/agent/tool/__test__/types.test.ts +0 -55
- package/vendor/agent-root/src/agent/tool/__test__/web-fetch.test.ts +0 -244
- package/vendor/agent-root/src/agent/tool/__test__/web-search.test.ts +0 -290
- package/vendor/agent-root/src/agent/tool/__test__/write-file.test.ts +0 -368
- package/vendor/agent-root/src/agent/tool/base-tool.ts +0 -345
- package/vendor/agent-root/src/agent/tool/bash-policy.ts +0 -636
- package/vendor/agent-root/src/agent/tool/bash.ts +0 -688
- package/vendor/agent-root/src/agent/tool/error.ts +0 -131
- package/vendor/agent-root/src/agent/tool/file-edit-tool.ts +0 -264
- package/vendor/agent-root/src/agent/tool/file-history-list.ts +0 -103
- package/vendor/agent-root/src/agent/tool/file-history-restore.ts +0 -149
- package/vendor/agent-root/src/agent/tool/file-read-tool.ts +0 -211
- package/vendor/agent-root/src/agent/tool/glob.ts +0 -171
- package/vendor/agent-root/src/agent/tool/grep.ts +0 -496
- package/vendor/agent-root/src/agent/tool/lsp.ts +0 -481
- package/vendor/agent-root/src/agent/tool/path-security.ts +0 -117
- package/vendor/agent-root/src/agent/tool/search/common.ts +0 -153
- package/vendor/agent-root/src/agent/tool/skill/index.ts +0 -13
- package/vendor/agent-root/src/agent/tool/skill/loader.ts +0 -229
- package/vendor/agent-root/src/agent/tool/skill/parser.ts +0 -124
- package/vendor/agent-root/src/agent/tool/skill/types.ts +0 -27
- package/vendor/agent-root/src/agent/tool/skill-tool.ts +0 -143
- package/vendor/agent-root/src/agent/tool/task-create.ts +0 -186
- package/vendor/agent-root/src/agent/tool/task-errors.ts +0 -42
- package/vendor/agent-root/src/agent/tool/task-get.ts +0 -116
- package/vendor/agent-root/src/agent/tool/task-graph.ts +0 -78
- package/vendor/agent-root/src/agent/tool/task-list.ts +0 -141
- package/vendor/agent-root/src/agent/tool/task-mock-runner-adapter.ts +0 -232
- package/vendor/agent-root/src/agent/tool/task-output.ts +0 -223
- package/vendor/agent-root/src/agent/tool/task-parent-abort.ts +0 -115
- package/vendor/agent-root/src/agent/tool/task-real-runner-adapter.ts +0 -336
- package/vendor/agent-root/src/agent/tool/task-runner-adapter.ts +0 -55
- package/vendor/agent-root/src/agent/tool/task-stop.ts +0 -187
- package/vendor/agent-root/src/agent/tool/task-store.ts +0 -217
- package/vendor/agent-root/src/agent/tool/task-subagent-config.ts +0 -149
- package/vendor/agent-root/src/agent/tool/task-types.ts +0 -264
- package/vendor/agent-root/src/agent/tool/task-update.ts +0 -315
- package/vendor/agent-root/src/agent/tool/task.ts +0 -209
- package/vendor/agent-root/src/agent/tool/tool-manager.ts +0 -361
- package/vendor/agent-root/src/agent/tool/tool-prompts.ts +0 -242
- package/vendor/agent-root/src/agent/tool/types.ts +0 -116
- package/vendor/agent-root/src/agent/tool/web-fetch.ts +0 -227
- package/vendor/agent-root/src/agent/tool/web-search.ts +0 -208
- package/vendor/agent-root/src/agent/tool/write-file.ts +0 -497
- package/vendor/agent-root/src/agent/types.ts +0 -232
- package/vendor/agent-root/src/agent/utils/__tests__/index.test.ts +0 -18
- package/vendor/agent-root/src/agent/utils/__tests__/message-utils.test.ts +0 -610
- package/vendor/agent-root/src/agent/utils/__tests__/message.test.ts +0 -223
- package/vendor/agent-root/src/agent/utils/__tests__/token.test.ts +0 -42
- package/vendor/agent-root/src/agent/utils/index.ts +0 -16
- package/vendor/agent-root/src/agent/utils/message.ts +0 -171
- package/vendor/agent-root/src/agent/utils/token.ts +0 -28
- package/vendor/agent-root/src/config/__tests__/load-config-to-env.test.ts +0 -238
- package/vendor/agent-root/src/config/__tests__/loader.test.ts +0 -361
- package/vendor/agent-root/src/config/__tests__/runtime.test.ts +0 -88
- package/vendor/agent-root/src/config/index.ts +0 -55
- package/vendor/agent-root/src/config/loader.ts +0 -494
- package/vendor/agent-root/src/config/paths.ts +0 -30
- package/vendor/agent-root/src/config/runtime.ts +0 -163
- package/vendor/agent-root/src/config/types.ts +0 -96
- package/vendor/agent-root/src/logger/index.ts +0 -57
- package/vendor/agent-root/src/logger/logger.ts +0 -819
- package/vendor/agent-root/src/logger/types.ts +0 -150
- package/vendor/agent-root/src/providers/__tests__/errors.test.ts +0 -441
- package/vendor/agent-root/src/providers/__tests__/index.test.ts +0 -16
- package/vendor/agent-root/src/providers/__tests__/openai-compatible.options.test.ts +0 -318
- package/vendor/agent-root/src/providers/__tests__/openai-compatible.test.ts +0 -600
- package/vendor/agent-root/src/providers/__tests__/registry.test.ts +0 -523
- package/vendor/agent-root/src/providers/__tests__/responses-adapter.test.ts +0 -298
- package/vendor/agent-root/src/providers/adapters/__tests__/anthropic.test.ts +0 -354
- package/vendor/agent-root/src/providers/adapters/__tests__/kimi.test.ts +0 -58
- package/vendor/agent-root/src/providers/adapters/__tests__/standard.test.ts +0 -261
- package/vendor/agent-root/src/providers/adapters/anthropic.ts +0 -572
- package/vendor/agent-root/src/providers/adapters/base.ts +0 -131
- package/vendor/agent-root/src/providers/adapters/kimi.ts +0 -48
- package/vendor/agent-root/src/providers/adapters/responses.ts +0 -732
- package/vendor/agent-root/src/providers/adapters/standard.ts +0 -120
- package/vendor/agent-root/src/providers/http/__tests__/client.timeout.test.ts +0 -313
- package/vendor/agent-root/src/providers/http/client.ts +0 -289
- package/vendor/agent-root/src/providers/http/stream-parser.ts +0 -109
- package/vendor/agent-root/src/providers/index.ts +0 -76
- package/vendor/agent-root/src/providers/kimi-headers.ts +0 -177
- package/vendor/agent-root/src/providers/openai-compatible.ts +0 -387
- package/vendor/agent-root/src/providers/registry/model-config.ts +0 -477
- package/vendor/agent-root/src/providers/registry/provider-factory.ts +0 -127
- package/vendor/agent-root/src/providers/registry.ts +0 -135
- package/vendor/agent-root/src/providers/types/api.ts +0 -284
- package/vendor/agent-root/src/providers/types/config.ts +0 -58
- package/vendor/agent-root/src/providers/types/errors.ts +0 -323
- package/vendor/agent-root/src/providers/types/index.ts +0 -72
- package/vendor/agent-root/src/providers/types/provider.ts +0 -45
- package/vendor/agent-root/src/providers/types/registry.ts +0 -68
|
@@ -1,391 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import * as fs from 'node:fs/promises';
|
|
3
|
-
import * as os from 'node:os';
|
|
4
|
-
import * as path from 'node:path';
|
|
5
|
-
import { TaskStore, getTaskStore } from '../task-store';
|
|
6
|
-
import { createEmptyNamespaceState } from '../task-types';
|
|
7
|
-
|
|
8
|
-
describe('TaskStore', () => {
|
|
9
|
-
let tempDir: string;
|
|
10
|
-
let store: TaskStore;
|
|
11
|
-
|
|
12
|
-
beforeEach(async () => {
|
|
13
|
-
tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'task-store-test-'));
|
|
14
|
-
store = new TaskStore({ baseDir: tempDir });
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
afterEach(async () => {
|
|
18
|
-
await fs.rm(tempDir, { recursive: true, force: true });
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
describe('constructor', () => {
|
|
22
|
-
it('creates store with default options', () => {
|
|
23
|
-
const store = new TaskStore();
|
|
24
|
-
expect(store).toBeDefined();
|
|
25
|
-
expect(store.baseDir).toContain('.renx');
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('creates store with custom baseDir', () => {
|
|
29
|
-
const store = new TaskStore({ baseDir: '/custom/path' });
|
|
30
|
-
// On Windows, path.resolve converts /custom/path to D:\custom\path
|
|
31
|
-
expect(path.isAbsolute(store.baseDir)).toBe(true);
|
|
32
|
-
expect(store.baseDir).toContain('custom');
|
|
33
|
-
expect(store.baseDir).toContain('path');
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it('creates store with custom now function', () => {
|
|
37
|
-
const mockNow = vi.fn().mockReturnValue(1234567890);
|
|
38
|
-
const store = new TaskStore({ now: mockNow });
|
|
39
|
-
expect(store).toBeDefined();
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
describe('normalizeNamespace', () => {
|
|
44
|
-
it('returns default for undefined', () => {
|
|
45
|
-
expect(store.normalizeNamespace(undefined)).toBe('default');
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
it('returns default for empty string', () => {
|
|
49
|
-
expect(store.normalizeNamespace('')).toBe('default');
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('returns default for whitespace-only string', () => {
|
|
53
|
-
expect(store.normalizeNamespace(' ')).toBe('default');
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
it('returns trimmed namespace', () => {
|
|
57
|
-
expect(store.normalizeNamespace(' test ')).toBe('test');
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('accepts valid namespace characters', () => {
|
|
61
|
-
expect(store.normalizeNamespace('test-namespace')).toBe('test-namespace');
|
|
62
|
-
expect(store.normalizeNamespace('test_namespace')).toBe('test_namespace');
|
|
63
|
-
expect(store.normalizeNamespace('test.namespace')).toBe('test.namespace');
|
|
64
|
-
expect(store.normalizeNamespace('test123')).toBe('test123');
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('throws for invalid namespace characters', () => {
|
|
68
|
-
expect(() => store.normalizeNamespace('test namespace')).toThrow('TASK_INVALID_NAMESPACE');
|
|
69
|
-
expect(() => store.normalizeNamespace('test@namespace')).toThrow('TASK_INVALID_NAMESPACE');
|
|
70
|
-
expect(() => store.normalizeNamespace('test#namespace')).toThrow('TASK_INVALID_NAMESPACE');
|
|
71
|
-
expect(() => store.normalizeNamespace('test/namespace')).toThrow('TASK_INVALID_NAMESPACE');
|
|
72
|
-
expect(() => store.normalizeNamespace('test\\namespace')).toThrow('TASK_INVALID_NAMESPACE');
|
|
73
|
-
});
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
describe('getNamespaceFilePath', () => {
|
|
77
|
-
it('returns correct file path', () => {
|
|
78
|
-
const filePath = store.getNamespaceFilePath('test-namespace');
|
|
79
|
-
expect(filePath).toBe(path.join(tempDir, 'test-namespace.json'));
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('handles default namespace', () => {
|
|
83
|
-
const filePath = store.getNamespaceFilePath('default');
|
|
84
|
-
expect(filePath).toBe(path.join(tempDir, 'default.json'));
|
|
85
|
-
});
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
describe('getState', () => {
|
|
89
|
-
it('returns empty state for new namespace', async () => {
|
|
90
|
-
const state = await store.getState('test-namespace');
|
|
91
|
-
|
|
92
|
-
expect(state.namespace).toBe('test-namespace');
|
|
93
|
-
expect(state.tasks).toEqual({});
|
|
94
|
-
expect(state.agentRuns).toEqual({});
|
|
95
|
-
expect(state.graph.adjacency).toEqual({});
|
|
96
|
-
expect(state.graph.reverse).toEqual({});
|
|
97
|
-
expect(state.schemaVersion).toBe(1);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('returns default namespace state', async () => {
|
|
101
|
-
const state = await store.getState();
|
|
102
|
-
|
|
103
|
-
expect(state.namespace).toBe('default');
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it('returns cached state', async () => {
|
|
107
|
-
// First call creates the state
|
|
108
|
-
const state1 = await store.getState('test-namespace');
|
|
109
|
-
|
|
110
|
-
// Second call should return cached state
|
|
111
|
-
const state2 = await store.getState('test-namespace');
|
|
112
|
-
|
|
113
|
-
expect(state1).toEqual(state2);
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it('returns state from file', async () => {
|
|
117
|
-
// Create a state file manually
|
|
118
|
-
const state = createEmptyNamespaceState('test-namespace');
|
|
119
|
-
state.tasks = {
|
|
120
|
-
task_1: {
|
|
121
|
-
id: 'task_1',
|
|
122
|
-
subject: 'Test Task',
|
|
123
|
-
description: 'Test description',
|
|
124
|
-
activeForm: 'Testing',
|
|
125
|
-
status: 'pending',
|
|
126
|
-
priority: 'normal',
|
|
127
|
-
owner: null,
|
|
128
|
-
blockedBy: [],
|
|
129
|
-
blocks: [],
|
|
130
|
-
progress: 0,
|
|
131
|
-
checkpoints: [],
|
|
132
|
-
retryConfig: { maxRetries: 3, retryDelayMs: 5000, backoffMultiplier: 2, retryOn: [] },
|
|
133
|
-
retryCount: 0,
|
|
134
|
-
tags: [],
|
|
135
|
-
metadata: {},
|
|
136
|
-
history: [],
|
|
137
|
-
createdAt: Date.now(),
|
|
138
|
-
updatedAt: Date.now(),
|
|
139
|
-
version: 1,
|
|
140
|
-
},
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
const filePath = store.getNamespaceFilePath('test-namespace');
|
|
144
|
-
await fs.writeFile(filePath, JSON.stringify(state, null, 2));
|
|
145
|
-
|
|
146
|
-
const loadedState = await store.getState('test-namespace');
|
|
147
|
-
|
|
148
|
-
expect(loadedState.tasks).toHaveProperty('task_1');
|
|
149
|
-
expect(loadedState.tasks.task_1.subject).toBe('Test Task');
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it('handles corrupted state file', async () => {
|
|
153
|
-
const filePath = store.getNamespaceFilePath('test-namespace');
|
|
154
|
-
await fs.writeFile(filePath, 'invalid json');
|
|
155
|
-
|
|
156
|
-
await expect(store.getState('test-namespace')).rejects.toThrow('TASK_STORE_IO_ERROR');
|
|
157
|
-
});
|
|
158
|
-
|
|
159
|
-
it('handles state file with missing fields', async () => {
|
|
160
|
-
const filePath = store.getNamespaceFilePath('test-namespace');
|
|
161
|
-
await fs.writeFile(filePath, JSON.stringify({ namespace: 'test-namespace' }));
|
|
162
|
-
|
|
163
|
-
const state = await store.getState('test-namespace');
|
|
164
|
-
|
|
165
|
-
expect(state.namespace).toBe('test-namespace');
|
|
166
|
-
expect(state.tasks).toEqual({});
|
|
167
|
-
expect(state.agentRuns).toEqual({});
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
describe('updateState', () => {
|
|
172
|
-
it('updates state and returns result', async () => {
|
|
173
|
-
const { state, result } = await store.updateState('test-namespace', (state) => {
|
|
174
|
-
state.tasks.task_1 = {
|
|
175
|
-
id: 'task_1',
|
|
176
|
-
subject: 'Test Task',
|
|
177
|
-
description: 'Test description',
|
|
178
|
-
activeForm: 'Testing',
|
|
179
|
-
status: 'pending',
|
|
180
|
-
priority: 'normal',
|
|
181
|
-
owner: null,
|
|
182
|
-
blockedBy: [],
|
|
183
|
-
blocks: [],
|
|
184
|
-
progress: 0,
|
|
185
|
-
checkpoints: [],
|
|
186
|
-
retryConfig: { maxRetries: 3, retryDelayMs: 5000, backoffMultiplier: 2, retryOn: [] },
|
|
187
|
-
retryCount: 0,
|
|
188
|
-
tags: [],
|
|
189
|
-
metadata: {},
|
|
190
|
-
history: [],
|
|
191
|
-
createdAt: Date.now(),
|
|
192
|
-
updatedAt: Date.now(),
|
|
193
|
-
version: 1,
|
|
194
|
-
};
|
|
195
|
-
return 'created';
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
expect(result).toBe('created');
|
|
199
|
-
expect(state.tasks).toHaveProperty('task_1');
|
|
200
|
-
expect(state.tasks.task_1.subject).toBe('Test Task');
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('persists state to file', async () => {
|
|
204
|
-
await store.updateState('test-namespace', (state) => {
|
|
205
|
-
state.tasks.task_1 = {
|
|
206
|
-
id: 'task_1',
|
|
207
|
-
subject: 'Test Task',
|
|
208
|
-
description: 'Test description',
|
|
209
|
-
activeForm: 'Testing',
|
|
210
|
-
status: 'pending',
|
|
211
|
-
priority: 'normal',
|
|
212
|
-
owner: null,
|
|
213
|
-
blockedBy: [],
|
|
214
|
-
blocks: [],
|
|
215
|
-
progress: 0,
|
|
216
|
-
checkpoints: [],
|
|
217
|
-
retryConfig: { maxRetries: 3, retryDelayMs: 5000, backoffMultiplier: 2, retryOn: [] },
|
|
218
|
-
retryCount: 0,
|
|
219
|
-
tags: [],
|
|
220
|
-
metadata: {},
|
|
221
|
-
history: [],
|
|
222
|
-
createdAt: Date.now(),
|
|
223
|
-
updatedAt: Date.now(),
|
|
224
|
-
version: 1,
|
|
225
|
-
};
|
|
226
|
-
return 'created';
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
const filePath = store.getNamespaceFilePath('test-namespace');
|
|
230
|
-
const fileContent = await fs.readFile(filePath, 'utf8');
|
|
231
|
-
const parsed = JSON.parse(fileContent);
|
|
232
|
-
|
|
233
|
-
expect(parsed.tasks).toHaveProperty('task_1');
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it('handles async updater', async () => {
|
|
237
|
-
const { state, result } = await store.updateState('test-namespace', async (state) => {
|
|
238
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
239
|
-
state.tasks.task_1 = {
|
|
240
|
-
id: 'task_1',
|
|
241
|
-
subject: 'Test Task',
|
|
242
|
-
description: 'Test description',
|
|
243
|
-
activeForm: 'Testing',
|
|
244
|
-
status: 'pending',
|
|
245
|
-
priority: 'normal',
|
|
246
|
-
owner: null,
|
|
247
|
-
blockedBy: [],
|
|
248
|
-
blocks: [],
|
|
249
|
-
progress: 0,
|
|
250
|
-
checkpoints: [],
|
|
251
|
-
retryConfig: { maxRetries: 3, retryDelayMs: 5000, backoffMultiplier: 2, retryOn: [] },
|
|
252
|
-
retryCount: 0,
|
|
253
|
-
tags: [],
|
|
254
|
-
metadata: {},
|
|
255
|
-
history: [],
|
|
256
|
-
createdAt: Date.now(),
|
|
257
|
-
updatedAt: Date.now(),
|
|
258
|
-
version: 1,
|
|
259
|
-
};
|
|
260
|
-
return 'async-created';
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
expect(result).toBe('async-created');
|
|
264
|
-
expect(state.tasks).toHaveProperty('task_1');
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
it('handles updater errors', async () => {
|
|
268
|
-
await expect(
|
|
269
|
-
store.updateState('test-namespace', () => {
|
|
270
|
-
throw new Error('Updater error');
|
|
271
|
-
})
|
|
272
|
-
).rejects.toThrow('Updater error');
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
it('releases lock on error', async () => {
|
|
276
|
-
// First update fails
|
|
277
|
-
await expect(
|
|
278
|
-
store.updateState('test-namespace', () => {
|
|
279
|
-
throw new Error('First error');
|
|
280
|
-
})
|
|
281
|
-
).rejects.toThrow('First error');
|
|
282
|
-
|
|
283
|
-
// Second update should succeed (lock was released)
|
|
284
|
-
const { result } = await store.updateState('test-namespace', () => {
|
|
285
|
-
return 'success';
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
expect(result).toBe('success');
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
it('handles concurrent updates', async () => {
|
|
292
|
-
const results: string[] = [];
|
|
293
|
-
|
|
294
|
-
const update1 = store.updateState('test-namespace', async (_state) => {
|
|
295
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
296
|
-
results.push('update1');
|
|
297
|
-
return 'result1';
|
|
298
|
-
});
|
|
299
|
-
|
|
300
|
-
const update2 = store.updateState('test-namespace', async (_state) => {
|
|
301
|
-
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
302
|
-
results.push('update2');
|
|
303
|
-
return 'result2';
|
|
304
|
-
});
|
|
305
|
-
|
|
306
|
-
const [result1, result2] = await Promise.all([update1, update2]);
|
|
307
|
-
|
|
308
|
-
expect(result1.result).toBe('result1');
|
|
309
|
-
expect(result2.result).toBe('result2');
|
|
310
|
-
// Both updates should have completed
|
|
311
|
-
expect(results).toHaveLength(2);
|
|
312
|
-
expect(results).toContain('update1');
|
|
313
|
-
expect(results).toContain('update2');
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
it('uses custom now function', async () => {
|
|
317
|
-
const mockNow = vi.fn().mockReturnValue(1234567890);
|
|
318
|
-
const store = new TaskStore({ baseDir: tempDir, now: mockNow });
|
|
319
|
-
|
|
320
|
-
await store.updateState('test-namespace', (_state) => {
|
|
321
|
-
return 'result';
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
expect(mockNow).toHaveBeenCalled();
|
|
325
|
-
});
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
describe('file operations', () => {
|
|
329
|
-
it('creates base directory on first access', async () => {
|
|
330
|
-
const newDir = path.join(tempDir, 'new-dir');
|
|
331
|
-
const store = new TaskStore({ baseDir: newDir });
|
|
332
|
-
|
|
333
|
-
await store.getState('test-namespace');
|
|
334
|
-
|
|
335
|
-
const stats = await fs.stat(newDir);
|
|
336
|
-
expect(stats.isDirectory()).toBe(true);
|
|
337
|
-
});
|
|
338
|
-
|
|
339
|
-
it('handles permission errors on directory creation', async () => {
|
|
340
|
-
// Skip on Windows as chmod doesn't work the same way
|
|
341
|
-
if (process.platform === 'win32') {
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
const restrictedDir = path.join(tempDir, 'restricted');
|
|
345
|
-
await fs.mkdir(restrictedDir, { recursive: true });
|
|
346
|
-
await fs.chmod(restrictedDir, 0o000);
|
|
347
|
-
|
|
348
|
-
try {
|
|
349
|
-
const store = new TaskStore({ baseDir: path.join(restrictedDir, 'subdir') });
|
|
350
|
-
await expect(store.getState('test-namespace')).rejects.toThrow();
|
|
351
|
-
} finally {
|
|
352
|
-
await fs.chmod(restrictedDir, 0o755);
|
|
353
|
-
}
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
it('handles permission errors on file write', async () => {
|
|
357
|
-
const filePath = store.getNamespaceFilePath('test-namespace');
|
|
358
|
-
await fs.writeFile(filePath, '{}');
|
|
359
|
-
await fs.chmod(filePath, 0o000);
|
|
360
|
-
|
|
361
|
-
try {
|
|
362
|
-
await expect(store.updateState('test-namespace', () => 'result')).rejects.toThrow();
|
|
363
|
-
} finally {
|
|
364
|
-
await fs.chmod(filePath, 0o644);
|
|
365
|
-
}
|
|
366
|
-
});
|
|
367
|
-
});
|
|
368
|
-
});
|
|
369
|
-
|
|
370
|
-
describe('getTaskStore', () => {
|
|
371
|
-
it('returns same store for same baseDir', () => {
|
|
372
|
-
const store1 = getTaskStore({ baseDir: '/tmp/test' });
|
|
373
|
-
const store2 = getTaskStore({ baseDir: '/tmp/test' });
|
|
374
|
-
|
|
375
|
-
expect(store1).toBe(store2);
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
it('returns different store for different baseDir', () => {
|
|
379
|
-
const store1 = getTaskStore({ baseDir: '/tmp/test1' });
|
|
380
|
-
const store2 = getTaskStore({ baseDir: '/tmp/test2' });
|
|
381
|
-
|
|
382
|
-
expect(store1).not.toBe(store2);
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
it('returns same store for equivalent baseDir', () => {
|
|
386
|
-
const store1 = getTaskStore({ baseDir: '/tmp/test' });
|
|
387
|
-
const store2 = getTaskStore({ baseDir: '/tmp/test/' });
|
|
388
|
-
|
|
389
|
-
expect(store1).toBe(store2);
|
|
390
|
-
});
|
|
391
|
-
});
|
|
@@ -1,176 +0,0 @@
|
|
|
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 { TaskTool } from '../task';
|
|
6
|
-
import { TaskStore } from '../task-store';
|
|
7
|
-
import type { SubagentRunnerAdapter } from '../task-runner-adapter';
|
|
8
|
-
import type { AgentRunEntity } from '../task-types';
|
|
9
|
-
|
|
10
|
-
function parseOutput<T>(output: string | undefined): T {
|
|
11
|
-
return JSON.parse(output || '{}') as T;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function makeRun(agentId: string): AgentRunEntity {
|
|
15
|
-
const now = Date.now();
|
|
16
|
-
return {
|
|
17
|
-
agentId,
|
|
18
|
-
status: 'running',
|
|
19
|
-
subagentType: 'Plan',
|
|
20
|
-
prompt: 'p',
|
|
21
|
-
createdAt: now,
|
|
22
|
-
startedAt: now,
|
|
23
|
-
updatedAt: now,
|
|
24
|
-
metadata: {},
|
|
25
|
-
version: 1,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
describe('task subagent config integration', () => {
|
|
30
|
-
let baseDir: string;
|
|
31
|
-
let store: TaskStore;
|
|
32
|
-
|
|
33
|
-
beforeEach(async () => {
|
|
34
|
-
baseDir = await fs.mkdtemp(path.join(os.tmpdir(), 'renx-task-subagent-config-'));
|
|
35
|
-
store = new TaskStore({ baseDir });
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
afterEach(async () => {
|
|
39
|
-
await fs.rm(baseDir, { recursive: true, force: true });
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it('injects default tools and systemPrompt from subagent config', async () => {
|
|
43
|
-
const captured: Array<{ allowedTools?: string[]; systemPrompt?: string }> = [];
|
|
44
|
-
const runner: SubagentRunnerAdapter = {
|
|
45
|
-
start: async (_ns, input) => {
|
|
46
|
-
captured.push({
|
|
47
|
-
allowedTools: input.allowedTools,
|
|
48
|
-
systemPrompt: input.systemPrompt,
|
|
49
|
-
});
|
|
50
|
-
return makeRun('agent-default-config');
|
|
51
|
-
},
|
|
52
|
-
poll: async () => null,
|
|
53
|
-
cancel: async () => null,
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
const tool = new TaskTool({ store, runner });
|
|
57
|
-
const result = await tool.execute({
|
|
58
|
-
namespace: 'ns1',
|
|
59
|
-
subagent_type: 'Plan',
|
|
60
|
-
prompt: 'build plan',
|
|
61
|
-
run_in_background: true,
|
|
62
|
-
});
|
|
63
|
-
expect(result.success).toBe(true);
|
|
64
|
-
const firstCapture = captured[0];
|
|
65
|
-
if (!firstCapture) {
|
|
66
|
-
throw new Error('expected captured task config');
|
|
67
|
-
}
|
|
68
|
-
expect(firstCapture.allowedTools).toContain('glob');
|
|
69
|
-
expect(firstCapture.allowedTools).toContain('grep');
|
|
70
|
-
expect(firstCapture.allowedTools).toContain('file_read');
|
|
71
|
-
expect(firstCapture.systemPrompt).toContain('planning specialist');
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('filters requested allowed_tools through config whitelist', async () => {
|
|
75
|
-
const captured: Array<{ allowedTools?: string[]; systemPrompt?: string }> = [];
|
|
76
|
-
const runner: SubagentRunnerAdapter = {
|
|
77
|
-
start: async (_ns, input) => {
|
|
78
|
-
captured.push({
|
|
79
|
-
allowedTools: input.allowedTools,
|
|
80
|
-
systemPrompt: input.systemPrompt,
|
|
81
|
-
});
|
|
82
|
-
return makeRun('agent-filtered-config');
|
|
83
|
-
},
|
|
84
|
-
poll: async () => null,
|
|
85
|
-
cancel: async () => null,
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
const tool = new TaskTool({ store, runner });
|
|
89
|
-
const result = await tool.execute({
|
|
90
|
-
namespace: 'ns2',
|
|
91
|
-
subagent_type: 'Plan',
|
|
92
|
-
prompt: 'plan with narrowed tools',
|
|
93
|
-
run_in_background: true,
|
|
94
|
-
allowed_tools: ['glob', 'bash', 'write_file'],
|
|
95
|
-
});
|
|
96
|
-
expect(result.success).toBe(true);
|
|
97
|
-
const firstCapture = captured[0];
|
|
98
|
-
if (!firstCapture) {
|
|
99
|
-
throw new Error('expected captured task config');
|
|
100
|
-
}
|
|
101
|
-
expect(firstCapture.allowedTools).toEqual(['glob']);
|
|
102
|
-
|
|
103
|
-
const payload = parseOutput<{ agent_run: { agentId: string } }>(result.output);
|
|
104
|
-
expect(payload.agent_run.agentId).toBe('agent-filtered-config');
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
it('injects find-skills defaults (skill + bash) and skill-discovery prompt', async () => {
|
|
108
|
-
const captured: Array<{ allowedTools?: string[]; systemPrompt?: string }> = [];
|
|
109
|
-
const runner: SubagentRunnerAdapter = {
|
|
110
|
-
start: async (_ns, input) => {
|
|
111
|
-
captured.push({
|
|
112
|
-
allowedTools: input.allowedTools,
|
|
113
|
-
systemPrompt: input.systemPrompt,
|
|
114
|
-
});
|
|
115
|
-
return makeRun('agent-find-skills-config');
|
|
116
|
-
},
|
|
117
|
-
poll: async () => null,
|
|
118
|
-
cancel: async () => null,
|
|
119
|
-
};
|
|
120
|
-
|
|
121
|
-
const tool = new TaskTool({ store, runner });
|
|
122
|
-
const result = await tool.execute({
|
|
123
|
-
namespace: 'ns3',
|
|
124
|
-
subagent_type: 'find-skills',
|
|
125
|
-
prompt: 'find and install skill for code review',
|
|
126
|
-
run_in_background: true,
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
expect(result.success).toBe(true);
|
|
130
|
-
const firstCapture = captured[0];
|
|
131
|
-
if (!firstCapture) {
|
|
132
|
-
throw new Error('expected captured task config');
|
|
133
|
-
}
|
|
134
|
-
expect(firstCapture.allowedTools).toEqual(['skill', 'bash']);
|
|
135
|
-
expect(firstCapture.systemPrompt).toContain('Skill Discovery and Installation Specialist');
|
|
136
|
-
expect(firstCapture.systemPrompt).toContain('Check local skills first');
|
|
137
|
-
expect(firstCapture.systemPrompt).toContain('load the **`find-skills`** skill');
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('injects Restore defaults and absolute-path rollback prompt', async () => {
|
|
141
|
-
const captured: Array<{ allowedTools?: string[]; systemPrompt?: string }> = [];
|
|
142
|
-
const runner: SubagentRunnerAdapter = {
|
|
143
|
-
start: async (_ns, input) => {
|
|
144
|
-
captured.push({
|
|
145
|
-
allowedTools: input.allowedTools,
|
|
146
|
-
systemPrompt: input.systemPrompt,
|
|
147
|
-
});
|
|
148
|
-
return makeRun('agent-restore-config');
|
|
149
|
-
},
|
|
150
|
-
poll: async () => null,
|
|
151
|
-
cancel: async () => null,
|
|
152
|
-
};
|
|
153
|
-
|
|
154
|
-
const tool = new TaskTool({ store, runner });
|
|
155
|
-
const result = await tool.execute({
|
|
156
|
-
namespace: 'ns4',
|
|
157
|
-
subagent_type: 'Restore',
|
|
158
|
-
prompt: 'restore D:\\work\\coding-agent-v2\\src\\renx\\tool\\write-file.ts',
|
|
159
|
-
run_in_background: true,
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
expect(result.success).toBe(true);
|
|
163
|
-
const firstCapture = captured[0];
|
|
164
|
-
if (!firstCapture) {
|
|
165
|
-
throw new Error('expected captured task config');
|
|
166
|
-
}
|
|
167
|
-
expect(firstCapture.allowedTools).toEqual([
|
|
168
|
-
'glob',
|
|
169
|
-
'file_read',
|
|
170
|
-
'file_history_list',
|
|
171
|
-
'file_history_restore',
|
|
172
|
-
]);
|
|
173
|
-
expect(firstCapture.systemPrompt).toContain('absolute file paths');
|
|
174
|
-
expect(firstCapture.systemPrompt).toContain('Do not use file_edit or write_file');
|
|
175
|
-
});
|
|
176
|
-
});
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
2
|
-
import { getTaskSubagentConfig, resolveTaskSubagentTools } from '../task-subagent-config';
|
|
3
|
-
import type { SubagentType } from '../task-types';
|
|
4
|
-
|
|
5
|
-
const ALL_TYPES: SubagentType[] = [
|
|
6
|
-
'Bash',
|
|
7
|
-
'general-purpose',
|
|
8
|
-
'Explore',
|
|
9
|
-
'Restore',
|
|
10
|
-
'Plan',
|
|
11
|
-
'research-agent',
|
|
12
|
-
'find-skills',
|
|
13
|
-
];
|
|
14
|
-
|
|
15
|
-
describe('task-subagent-config', () => {
|
|
16
|
-
it('returns config for every supported subagent type', () => {
|
|
17
|
-
for (const type of ALL_TYPES) {
|
|
18
|
-
const config = getTaskSubagentConfig(type);
|
|
19
|
-
expect(config.tools.length).toBeGreaterThan(0);
|
|
20
|
-
expect(config.systemPrompt.length).toBeGreaterThan(0);
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('returns cloned tool arrays to avoid accidental shared mutation', () => {
|
|
25
|
-
const first = getTaskSubagentConfig('Plan');
|
|
26
|
-
const second = getTaskSubagentConfig('Plan');
|
|
27
|
-
first.tools.push('unexpected_tool');
|
|
28
|
-
expect(second.tools).not.toContain('unexpected_tool');
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('uses defaults when requested tools are empty or undefined', () => {
|
|
32
|
-
const defaults = getTaskSubagentConfig('general-purpose').tools;
|
|
33
|
-
expect(resolveTaskSubagentTools('general-purpose')).toEqual(defaults);
|
|
34
|
-
expect(resolveTaskSubagentTools('general-purpose', [])).toEqual(defaults);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('narrows requested tools by config whitelist and falls back to defaults', () => {
|
|
38
|
-
expect(resolveTaskSubagentTools('Plan', ['glob', 'bash'])).toEqual(['glob']);
|
|
39
|
-
|
|
40
|
-
const defaults = getTaskSubagentConfig('Plan').tools;
|
|
41
|
-
expect(resolveTaskSubagentTools('Plan', ['bash', 'write_file'])).toEqual(defaults);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
it('defines find-skills as local-first skill workflow with bash fallback', () => {
|
|
45
|
-
const config = getTaskSubagentConfig('find-skills');
|
|
46
|
-
|
|
47
|
-
expect(config.tools).toEqual(['skill', 'bash']);
|
|
48
|
-
expect(config.systemPrompt).toContain('Check local skills first');
|
|
49
|
-
expect(config.systemPrompt).toContain('load the **`find-skills`** skill');
|
|
50
|
-
expect(config.systemPrompt).toContain('Use `bash` only for the required installation command');
|
|
51
|
-
expect(config.systemPrompt).toContain('retry using the `skill` tool');
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
it('defines Restore as a narrow rollback workflow using explicit file paths', () => {
|
|
55
|
-
const config = getTaskSubagentConfig('Restore');
|
|
56
|
-
|
|
57
|
-
expect(config.tools).toEqual([
|
|
58
|
-
'glob',
|
|
59
|
-
'file_read',
|
|
60
|
-
'file_history_list',
|
|
61
|
-
'file_history_restore',
|
|
62
|
-
]);
|
|
63
|
-
expect(config.systemPrompt).toContain('file restoration specialist');
|
|
64
|
-
expect(config.systemPrompt).toContain('Prefer exact absolute file paths');
|
|
65
|
-
expect(config.systemPrompt).toContain('Do not use file_edit or write_file');
|
|
66
|
-
expect(config.systemPrompt).toContain('file_history_restore');
|
|
67
|
-
});
|
|
68
|
-
});
|