@united-workforce/cli 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -11
- package/dist/.build-fingerprint +1 -0
- package/dist/__tests__/adapter-json-roundtrip.test.js +17 -7
- package/dist/__tests__/adapter-json-roundtrip.test.js.map +1 -1
- package/dist/__tests__/agent-resolution-llm-free.test.d.ts +2 -0
- package/dist/__tests__/agent-resolution-llm-free.test.d.ts.map +1 -0
- package/dist/__tests__/agent-resolution-llm-free.test.js +30 -0
- package/dist/__tests__/agent-resolution-llm-free.test.js.map +1 -0
- package/dist/__tests__/build-step-entry.test.d.ts +2 -0
- package/dist/__tests__/build-step-entry.test.d.ts.map +1 -0
- package/dist/__tests__/build-step-entry.test.js +173 -0
- package/dist/__tests__/build-step-entry.test.js.map +1 -0
- package/dist/__tests__/clear-thread-failed-attempts.test.d.ts +2 -0
- package/dist/__tests__/clear-thread-failed-attempts.test.d.ts.map +1 -0
- package/dist/__tests__/clear-thread-failed-attempts.test.js +93 -0
- package/dist/__tests__/clear-thread-failed-attempts.test.js.map +1 -0
- package/dist/__tests__/concurrency.test.d.ts +2 -0
- package/dist/__tests__/concurrency.test.d.ts.map +1 -0
- package/dist/__tests__/concurrency.test.js +196 -0
- package/dist/__tests__/concurrency.test.js.map +1 -0
- package/dist/__tests__/config.test.js +26 -302
- package/dist/__tests__/config.test.js.map +1 -1
- package/dist/__tests__/current-role.test.js +7 -6
- package/dist/__tests__/current-role.test.js.map +1 -1
- package/dist/__tests__/e2e-mock-agent.test.js +43 -30
- package/dist/__tests__/e2e-mock-agent.test.js.map +1 -1
- package/dist/__tests__/format-text-default.test.d.ts +2 -0
- package/dist/__tests__/format-text-default.test.d.ts.map +1 -0
- package/dist/__tests__/format-text-default.test.js +43 -0
- package/dist/__tests__/format-text-default.test.js.map +1 -0
- package/dist/__tests__/format-text-registry.test.d.ts +2 -0
- package/dist/__tests__/format-text-registry.test.d.ts.map +1 -0
- package/dist/__tests__/format-text-registry.test.js +158 -0
- package/dist/__tests__/format-text-registry.test.js.map +1 -0
- package/dist/__tests__/issue-180-workflow-ref-removed.test.d.ts +2 -0
- package/dist/__tests__/issue-180-workflow-ref-removed.test.d.ts.map +1 -0
- package/dist/__tests__/issue-180-workflow-ref-removed.test.js +40 -0
- package/dist/__tests__/issue-180-workflow-ref-removed.test.js.map +1 -0
- package/dist/__tests__/log-text-renderer.test.d.ts +2 -0
- package/dist/__tests__/log-text-renderer.test.d.ts.map +1 -0
- package/dist/__tests__/log-text-renderer.test.js +265 -0
- package/dist/__tests__/log-text-renderer.test.js.map +1 -0
- package/dist/__tests__/moderator-evaluate.test.js +9 -50
- package/dist/__tests__/moderator-evaluate.test.js.map +1 -1
- package/dist/__tests__/output-mapper-thread-list-startedat.test.d.ts +2 -0
- package/dist/__tests__/output-mapper-thread-list-startedat.test.d.ts.map +1 -0
- package/dist/__tests__/output-mapper-thread-list-startedat.test.js +102 -0
- package/dist/__tests__/output-mapper-thread-list-startedat.test.js.map +1 -0
- package/dist/__tests__/output-mapper-workflow-add.test.d.ts +2 -0
- package/dist/__tests__/output-mapper-workflow-add.test.d.ts.map +1 -0
- package/dist/__tests__/output-mapper-workflow-add.test.js +22 -0
- package/dist/__tests__/output-mapper-workflow-add.test.js.map +1 -0
- package/dist/__tests__/pid-recycling.test.d.ts +2 -0
- package/dist/__tests__/pid-recycling.test.d.ts.map +1 -0
- package/dist/__tests__/pid-recycling.test.js +273 -0
- package/dist/__tests__/pid-recycling.test.js.map +1 -0
- package/dist/__tests__/prompt.test.js +365 -2
- package/dist/__tests__/prompt.test.js.map +1 -1
- package/dist/__tests__/resolve-head-hash.test.js +12 -4
- package/dist/__tests__/resolve-head-hash.test.js.map +1 -1
- package/dist/__tests__/setup-agent-discovery.test.js +21 -30
- package/dist/__tests__/setup-agent-discovery.test.js.map +1 -1
- package/dist/__tests__/setup-complexity.test.js +2 -168
- package/dist/__tests__/setup-complexity.test.js.map +1 -1
- package/dist/__tests__/setup-no-llm.test.d.ts +2 -0
- package/dist/__tests__/setup-no-llm.test.d.ts.map +1 -0
- package/dist/__tests__/setup-no-llm.test.js +52 -0
- package/dist/__tests__/setup-no-llm.test.js.map +1 -0
- package/dist/__tests__/solve-issue-tea-worktree.test.js +27 -28
- package/dist/__tests__/solve-issue-tea-worktree.test.js.map +1 -1
- package/dist/__tests__/step-ask.test.d.ts +2 -0
- package/dist/__tests__/step-ask.test.d.ts.map +1 -0
- package/dist/__tests__/step-ask.test.js +507 -0
- package/dist/__tests__/step-ask.test.js.map +1 -0
- package/dist/__tests__/step-show-json.test.js +1 -0
- package/dist/__tests__/step-show-json.test.js.map +1 -1
- package/dist/__tests__/step-timing.test.js +2 -0
- package/dist/__tests__/step-timing.test.js.map +1 -1
- package/dist/__tests__/store-global-cas.test.js +2 -2
- package/dist/__tests__/store-global-cas.test.js.map +1 -1
- package/dist/__tests__/store-unified-threads.test.js +28 -26
- package/dist/__tests__/store-unified-threads.test.js.map +1 -1
- package/dist/__tests__/thread-cancel-status.test.js +25 -19
- package/dist/__tests__/thread-cancel-status.test.js.map +1 -1
- package/dist/__tests__/thread-cancel-text-renderer.test.d.ts +2 -0
- package/dist/__tests__/thread-cancel-text-renderer.test.d.ts.map +1 -0
- package/dist/__tests__/thread-cancel-text-renderer.test.js +110 -0
- package/dist/__tests__/thread-cancel-text-renderer.test.js.map +1 -0
- package/dist/__tests__/thread-list-filters.test.js +354 -17
- package/dist/__tests__/thread-list-filters.test.js.map +1 -1
- package/dist/__tests__/thread-list-template-ms-date.test.d.ts +2 -0
- package/dist/__tests__/thread-list-template-ms-date.test.d.ts.map +1 -0
- package/dist/__tests__/thread-list-template-ms-date.test.js +102 -0
- package/dist/__tests__/thread-list-template-ms-date.test.js.map +1 -0
- package/dist/__tests__/thread-list-workflow-corrupt.test.d.ts +2 -0
- package/dist/__tests__/thread-list-workflow-corrupt.test.d.ts.map +1 -0
- package/dist/__tests__/thread-list-workflow-corrupt.test.js +157 -0
- package/dist/__tests__/thread-list-workflow-corrupt.test.js.map +1 -0
- package/dist/__tests__/thread-poke.test.d.ts +2 -0
- package/dist/__tests__/thread-poke.test.d.ts.map +1 -0
- package/dist/__tests__/thread-poke.test.js +422 -0
- package/dist/__tests__/thread-poke.test.js.map +1 -0
- package/dist/__tests__/thread-read-xml-tags.test.js +10 -9
- package/dist/__tests__/thread-read-xml-tags.test.js.map +1 -1
- package/dist/__tests__/thread-resume.test.js +21 -15
- package/dist/__tests__/thread-resume.test.js.map +1 -1
- package/dist/__tests__/thread-show-status.test.js +17 -28
- package/dist/__tests__/thread-show-status.test.js.map +1 -1
- package/dist/__tests__/thread-start-cwd-cli.test.js +15 -3
- package/dist/__tests__/thread-start-cwd-cli.test.js.map +1 -1
- package/dist/__tests__/thread-stop-text-renderer.test.d.ts +2 -0
- package/dist/__tests__/thread-stop-text-renderer.test.d.ts.map +1 -0
- package/dist/__tests__/thread-stop-text-renderer.test.js +148 -0
- package/dist/__tests__/thread-stop-text-renderer.test.js.map +1 -0
- package/dist/__tests__/thread-suspend-step.test.js +13 -16
- package/dist/__tests__/thread-suspend-step.test.js.map +1 -1
- package/dist/__tests__/thread-suspended-display.test.js +10 -22
- package/dist/__tests__/thread-suspended-display.test.js.map +1 -1
- package/dist/__tests__/thread-test-helpers.d.ts +7 -0
- package/dist/__tests__/thread-test-helpers.d.ts.map +1 -1
- package/dist/__tests__/thread-test-helpers.js +13 -0
- package/dist/__tests__/thread-test-helpers.js.map +1 -1
- package/dist/__tests__/thread.test.js +15 -13
- package/dist/__tests__/thread.test.js.map +1 -1
- package/dist/__tests__/validate-semantic.test.js +105 -23
- package/dist/__tests__/validate-semantic.test.js.map +1 -1
- package/dist/__tests__/workflow-list-recursive.test.d.ts +2 -0
- package/dist/__tests__/workflow-list-recursive.test.d.ts.map +1 -0
- package/dist/__tests__/workflow-list-recursive.test.js +286 -0
- package/dist/__tests__/workflow-list-recursive.test.js.map +1 -0
- package/dist/__tests__/workflow-resolution.test.js +46 -28
- package/dist/__tests__/workflow-resolution.test.js.map +1 -1
- package/dist/__tests__/workflow-show-resolution.test.d.ts +2 -0
- package/dist/__tests__/workflow-show-resolution.test.d.ts.map +1 -0
- package/dist/__tests__/workflow-show-resolution.test.js +213 -0
- package/dist/__tests__/workflow-show-resolution.test.js.map +1 -0
- package/dist/__tests__/workflow-validate.test.d.ts +2 -0
- package/dist/__tests__/workflow-validate.test.d.ts.map +1 -0
- package/dist/__tests__/workflow-validate.test.js +707 -0
- package/dist/__tests__/workflow-validate.test.js.map +1 -0
- package/dist/__tests__/write-envelope.test.d.ts +2 -0
- package/dist/__tests__/write-envelope.test.d.ts.map +1 -0
- package/dist/__tests__/write-envelope.test.js +201 -0
- package/dist/__tests__/write-envelope.test.js.map +1 -0
- package/dist/background/background.d.ts +22 -1
- package/dist/background/background.d.ts.map +1 -1
- package/dist/background/background.js +83 -6
- package/dist/background/background.js.map +1 -1
- package/dist/background/index.d.ts +1 -1
- package/dist/background/index.d.ts.map +1 -1
- package/dist/background/index.js +1 -1
- package/dist/background/index.js.map +1 -1
- package/dist/background/types.d.ts +1 -0
- package/dist/background/types.d.ts.map +1 -1
- package/dist/cli.js +120 -62
- package/dist/cli.js.map +1 -1
- package/dist/commands/config.d.ts +3 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +17 -31
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/prompt.d.ts.map +1 -1
- package/dist/commands/prompt.js +57 -31
- package/dist/commands/prompt.js.map +1 -1
- package/dist/commands/setup.d.ts +12 -39
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +72 -303
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/step.d.ts +44 -1
- package/dist/commands/step.d.ts.map +1 -1
- package/dist/commands/step.js +255 -11
- package/dist/commands/step.js.map +1 -1
- package/dist/commands/thread.d.ts +16 -3
- package/dist/commands/thread.d.ts.map +1 -1
- package/dist/commands/thread.js +423 -142
- package/dist/commands/thread.js.map +1 -1
- package/dist/commands/workflow.d.ts +9 -1
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +126 -6
- package/dist/commands/workflow.js.map +1 -1
- package/dist/concurrency/concurrency.d.ts +34 -0
- package/dist/concurrency/concurrency.d.ts.map +1 -0
- package/dist/concurrency/concurrency.js +216 -0
- package/dist/concurrency/concurrency.js.map +1 -0
- package/dist/concurrency/index.d.ts +3 -0
- package/dist/concurrency/index.d.ts.map +1 -0
- package/dist/concurrency/index.js +2 -0
- package/dist/concurrency/index.js.map +1 -0
- package/dist/concurrency/types.d.ts +19 -0
- package/dist/concurrency/types.d.ts.map +1 -0
- package/dist/concurrency/types.js +2 -0
- package/dist/concurrency/types.js.map +1 -0
- package/dist/format.d.ts +69 -2
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +198 -1
- package/dist/format.js.map +1 -1
- package/dist/moderator/__tests__/evaluate.test.js +31 -17
- package/dist/moderator/__tests__/evaluate.test.js.map +1 -1
- package/dist/moderator/evaluate.d.ts.map +1 -1
- package/dist/moderator/evaluate.js +4 -16
- package/dist/moderator/evaluate.js.map +1 -1
- package/dist/moderator/index.d.ts +1 -2
- package/dist/moderator/index.d.ts.map +1 -1
- package/dist/moderator/index.js +0 -1
- package/dist/moderator/index.js.map +1 -1
- package/dist/moderator/types.d.ts +6 -10
- package/dist/moderator/types.d.ts.map +1 -1
- package/dist/moderator/types.js +1 -3
- package/dist/moderator/types.js.map +1 -1
- package/dist/output-mappers.d.ts +122 -0
- package/dist/output-mappers.d.ts.map +1 -0
- package/dist/output-mappers.js +134 -0
- package/dist/output-mappers.js.map +1 -0
- package/dist/schemas.d.ts +6 -1
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +34 -5
- package/dist/schemas.js.map +1 -1
- package/dist/store.d.ts +28 -9
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +75 -16
- package/dist/store.js.map +1 -1
- package/dist/text-renderers.d.ts +30 -0
- package/dist/text-renderers.d.ts.map +1 -0
- package/dist/text-renderers.js +251 -0
- package/dist/text-renderers.js.map +1 -0
- package/dist/validate-semantic.d.ts.map +1 -1
- package/dist/validate-semantic.js +95 -61
- package/dist/validate-semantic.js.map +1 -1
- package/dist/validate.d.ts +6 -0
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +24 -0
- package/dist/validate.js.map +1 -1
- package/examples/brainstorm.yaml +130 -0
- package/examples/debate.yaml +169 -0
- package/examples/socratic-questioning.yaml +112 -0
- package/package.json +9 -10
- package/src/__tests__/adapter-json-roundtrip.test.ts +16 -7
- package/src/__tests__/agent-resolution-llm-free.test.ts +39 -0
- package/src/__tests__/build-step-entry.test.ts +203 -0
- package/src/__tests__/clear-thread-failed-attempts.test.ts +122 -0
- package/src/__tests__/concurrency.test.ts +266 -0
- package/src/__tests__/config.test.ts +33 -321
- package/src/__tests__/current-role.test.ts +7 -6
- package/src/__tests__/e2e-mock-agent.test.ts +65 -30
- package/src/__tests__/fixtures/e2e-count.workflow.yaml +1 -0
- package/src/__tests__/fixtures/e2e-linear.workflow.yaml +1 -0
- package/src/__tests__/fixtures/{e2e-mustache.workflow.yaml → e2e-liquid.workflow.yaml} +3 -2
- package/src/__tests__/fixtures/e2e-loop.workflow.yaml +1 -0
- package/src/__tests__/fixtures/e2e-suspend.mock.yaml +2 -2
- package/src/__tests__/fixtures/e2e-suspend.workflow.yaml +6 -10
- package/src/__tests__/format-text-default.test.ts +49 -0
- package/src/__tests__/format-text-registry.test.ts +173 -0
- package/src/__tests__/issue-180-workflow-ref-removed.test.ts +43 -0
- package/src/__tests__/log-text-renderer.test.ts +294 -0
- package/src/__tests__/moderator-evaluate.test.ts +9 -52
- package/src/__tests__/output-mapper-thread-list-startedat.test.ts +124 -0
- package/src/__tests__/output-mapper-workflow-add.test.ts +24 -0
- package/src/__tests__/pid-recycling.test.ts +329 -0
- package/src/__tests__/prompt.test.ts +443 -2
- package/src/__tests__/resolve-head-hash.test.ts +11 -4
- package/src/__tests__/setup-agent-discovery.test.ts +26 -51
- package/src/__tests__/setup-complexity.test.ts +1 -203
- package/src/__tests__/setup-no-llm.test.ts +68 -0
- package/src/__tests__/solve-issue-tea-worktree.test.ts +27 -31
- package/src/__tests__/step-ask.test.ts +677 -0
- package/src/__tests__/step-show-json.test.ts +1 -0
- package/src/__tests__/step-timing.test.ts +2 -0
- package/src/__tests__/store-global-cas.test.ts +2 -2
- package/src/__tests__/store-unified-threads.test.ts +30 -27
- package/src/__tests__/thread-cancel-status.test.ts +27 -20
- package/src/__tests__/thread-cancel-text-renderer.test.ts +125 -0
- package/src/__tests__/thread-list-filters.test.ts +443 -17
- package/src/__tests__/thread-list-template-ms-date.test.ts +110 -0
- package/src/__tests__/thread-list-workflow-corrupt.test.ts +198 -0
- package/src/__tests__/thread-poke.test.ts +554 -0
- package/src/__tests__/thread-read-xml-tags.test.ts +9 -11
- package/src/__tests__/thread-resume.test.ts +20 -15
- package/src/__tests__/thread-show-status.test.ts +17 -29
- package/src/__tests__/thread-start-cwd-cli.test.ts +15 -3
- package/src/__tests__/thread-stop-text-renderer.test.ts +168 -0
- package/src/__tests__/thread-suspend-step.test.ts +13 -16
- package/src/__tests__/thread-suspended-display.test.ts +10 -22
- package/src/__tests__/thread-test-helpers.ts +15 -1
- package/src/__tests__/thread.test.ts +14 -14
- package/src/__tests__/validate-semantic.test.ts +118 -33
- package/src/__tests__/workflow-list-recursive.test.ts +370 -0
- package/src/__tests__/workflow-resolution.test.ts +48 -29
- package/src/__tests__/workflow-show-resolution.test.ts +286 -0
- package/src/__tests__/workflow-validate.test.ts +828 -0
- package/src/__tests__/write-envelope.test.ts +257 -0
- package/src/background/background.ts +88 -6
- package/src/background/index.ts +2 -0
- package/src/background/types.ts +1 -0
- package/src/cli.ts +184 -77
- package/src/commands/config.ts +16 -33
- package/src/commands/prompt.ts +57 -31
- package/src/commands/setup.ts +80 -358
- package/src/commands/step.ts +339 -12
- package/src/commands/thread.ts +511 -171
- package/src/commands/workflow.ts +155 -4
- package/src/concurrency/concurrency.ts +245 -0
- package/src/concurrency/index.ts +10 -0
- package/src/concurrency/types.ts +19 -0
- package/src/format.ts +282 -2
- package/src/moderator/__tests__/evaluate.test.ts +34 -17
- package/src/moderator/evaluate.ts +5 -17
- package/src/moderator/index.ts +1 -6
- package/src/moderator/types.ts +6 -14
- package/src/output-mappers.ts +254 -0
- package/src/schemas.ts +51 -5
- package/src/store.ts +86 -20
- package/src/text-renderers.ts +355 -0
- package/src/validate-semantic.ts +125 -73
- package/src/validate.ts +27 -0
- package/dist/__tests__/setup-validate.test.d.ts +0 -2
- package/dist/__tests__/setup-validate.test.d.ts.map +0 -1
- package/dist/__tests__/setup-validate.test.js +0 -108
- package/dist/__tests__/setup-validate.test.js.map +0 -1
- package/src/__tests__/setup-validate.test.ts +0 -148
- /package/src/__tests__/fixtures/{e2e-mustache.mock.yaml → e2e-liquid.mock.yaml} +0 -0
|
@@ -230,11 +230,11 @@ describe("Global CAS directory", () => {
|
|
|
230
230
|
const { createThreadIndexEntry } = await import("@united-workforce/protocol");
|
|
231
231
|
|
|
232
232
|
setThread(uwf.varStore, threadId, createThreadIndexEntry(headHash));
|
|
233
|
-
completeThread(uwf.varStore, threadId, "
|
|
233
|
+
completeThread(uwf.varStore, threadId, "end");
|
|
234
234
|
|
|
235
235
|
const entry = getThread(uwf.varStore, threadId);
|
|
236
236
|
expect(entry?.head).toBe(headHash);
|
|
237
|
-
expect(entry?.status).toBe("
|
|
237
|
+
expect(entry?.status).toBe("end");
|
|
238
238
|
|
|
239
239
|
const { access } = await import("node:fs/promises");
|
|
240
240
|
await access(join(globalCasDir, "vars"));
|
|
@@ -1,23 +1,17 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import type { CasRef, ThreadId } from "@united-workforce/protocol";
|
|
5
|
-
import { describe, expect, test } from "vitest";
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
6
6
|
import {
|
|
7
7
|
completeThread,
|
|
8
|
-
createUwfStore,
|
|
8
|
+
type createUwfStore,
|
|
9
9
|
getThread,
|
|
10
10
|
loadActiveThreads,
|
|
11
11
|
loadHistoryThreads,
|
|
12
12
|
setThread,
|
|
13
13
|
} from "../store.js";
|
|
14
|
-
|
|
15
|
-
async function makeUwfStore(storageRoot: string) {
|
|
16
|
-
const casDir = join(storageRoot, "cas");
|
|
17
|
-
await mkdir(casDir, { recursive: true });
|
|
18
|
-
process.env.OCAS_HOME = casDir;
|
|
19
|
-
return createUwfStore(storageRoot);
|
|
20
|
-
}
|
|
14
|
+
import { makeUwfStore } from "./thread-test-helpers.js";
|
|
21
15
|
|
|
22
16
|
async function seedThreadHead(
|
|
23
17
|
uwf: Awaited<ReturnType<typeof createUwfStore>>,
|
|
@@ -26,9 +20,25 @@ async function seedThreadHead(
|
|
|
26
20
|
return (await uwf.store.cas.put(uwf.schemas.text, label)) as CasRef;
|
|
27
21
|
}
|
|
28
22
|
|
|
23
|
+
let tmpDir: string;
|
|
24
|
+
let savedOcasHome: string | undefined;
|
|
25
|
+
|
|
26
|
+
beforeEach(async () => {
|
|
27
|
+
savedOcasHome = process.env.OCAS_HOME;
|
|
28
|
+
tmpDir = await mkdtemp(join(tmpdir(), "uwf-store-test-"));
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterEach(async () => {
|
|
32
|
+
if (savedOcasHome === undefined) {
|
|
33
|
+
delete process.env.OCAS_HOME;
|
|
34
|
+
} else {
|
|
35
|
+
process.env.OCAS_HOME = savedOcasHome;
|
|
36
|
+
}
|
|
37
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
38
|
+
});
|
|
39
|
+
|
|
29
40
|
describe("unified thread storage", () => {
|
|
30
41
|
test("loadActiveThreads excludes completed threads", async () => {
|
|
31
|
-
const tmpDir = await mkdtemp(join(tmpdir(), "uwf-active-test-"));
|
|
32
42
|
const uwf = await makeUwfStore(tmpDir);
|
|
33
43
|
|
|
34
44
|
const threadId1 = "01JTEST000000000000ACTIVE1" as ThreadId;
|
|
@@ -46,7 +56,7 @@ describe("unified thread storage", () => {
|
|
|
46
56
|
|
|
47
57
|
setThread(uwf.varStore, threadId2, {
|
|
48
58
|
head: head2,
|
|
49
|
-
status: "
|
|
59
|
+
status: "end",
|
|
50
60
|
suspendedRole: null,
|
|
51
61
|
suspendMessage: null,
|
|
52
62
|
completedAt: Date.now(),
|
|
@@ -59,7 +69,6 @@ describe("unified thread storage", () => {
|
|
|
59
69
|
});
|
|
60
70
|
|
|
61
71
|
test("loadActiveThreads excludes cancelled threads", async () => {
|
|
62
|
-
const tmpDir = await mkdtemp(join(tmpdir(), "uwf-active-test-"));
|
|
63
72
|
const uwf = await makeUwfStore(tmpDir);
|
|
64
73
|
|
|
65
74
|
const threadId1 = "01JTEST000000000000ACTIVE3" as ThreadId;
|
|
@@ -90,7 +99,6 @@ describe("unified thread storage", () => {
|
|
|
90
99
|
});
|
|
91
100
|
|
|
92
101
|
test("loadHistoryThreads only returns completed and cancelled", async () => {
|
|
93
|
-
const tmpDir = await mkdtemp(join(tmpdir(), "uwf-history-test-"));
|
|
94
102
|
const uwf = await makeUwfStore(tmpDir);
|
|
95
103
|
|
|
96
104
|
const threadId1 = "01JTEST000000000000HISTOR1" as ThreadId;
|
|
@@ -110,7 +118,7 @@ describe("unified thread storage", () => {
|
|
|
110
118
|
|
|
111
119
|
setThread(uwf.varStore, threadId2, {
|
|
112
120
|
head: head2,
|
|
113
|
-
status: "
|
|
121
|
+
status: "end",
|
|
114
122
|
suspendedRole: null,
|
|
115
123
|
suspendMessage: null,
|
|
116
124
|
completedAt: Date.now(),
|
|
@@ -132,7 +140,6 @@ describe("unified thread storage", () => {
|
|
|
132
140
|
});
|
|
133
141
|
|
|
134
142
|
test("completeThread marks thread as completed", async () => {
|
|
135
|
-
const tmpDir = await mkdtemp(join(tmpdir(), "uwf-complete-test-"));
|
|
136
143
|
const uwf = await makeUwfStore(tmpDir);
|
|
137
144
|
const threadId = "01JTEST000000000000COMPLE1" as ThreadId;
|
|
138
145
|
const head = await seedThreadHead(uwf, "active-head");
|
|
@@ -145,17 +152,16 @@ describe("unified thread storage", () => {
|
|
|
145
152
|
completedAt: null,
|
|
146
153
|
});
|
|
147
154
|
|
|
148
|
-
completeThread(uwf.varStore, threadId, "
|
|
155
|
+
completeThread(uwf.varStore, threadId, "end");
|
|
149
156
|
|
|
150
157
|
const entry = getThread(uwf.varStore, threadId);
|
|
151
158
|
expect(entry).not.toBeNull();
|
|
152
|
-
expect(entry?.status).toBe("
|
|
159
|
+
expect(entry?.status).toBe("end");
|
|
153
160
|
expect(entry?.completedAt).toBeDefined();
|
|
154
161
|
expect(entry?.completedAt).toBeGreaterThan(0);
|
|
155
162
|
});
|
|
156
163
|
|
|
157
164
|
test("completeThread marks thread as cancelled", async () => {
|
|
158
|
-
const tmpDir = await mkdtemp(join(tmpdir(), "uwf-complete-test-"));
|
|
159
165
|
const uwf = await makeUwfStore(tmpDir);
|
|
160
166
|
const threadId = "01JTEST000000000000COMPLE2" as ThreadId;
|
|
161
167
|
const head = await seedThreadHead(uwf, "active-head");
|
|
@@ -178,7 +184,6 @@ describe("unified thread storage", () => {
|
|
|
178
184
|
});
|
|
179
185
|
|
|
180
186
|
test("completeThread clears suspend metadata", async () => {
|
|
181
|
-
const tmpDir = await mkdtemp(join(tmpdir(), "uwf-complete-test-"));
|
|
182
187
|
const uwf = await makeUwfStore(tmpDir);
|
|
183
188
|
const threadId = "01JTEST000000000000COMPLE3" as ThreadId;
|
|
184
189
|
const head = await seedThreadHead(uwf, "suspended-head");
|
|
@@ -191,29 +196,27 @@ describe("unified thread storage", () => {
|
|
|
191
196
|
completedAt: null,
|
|
192
197
|
});
|
|
193
198
|
|
|
194
|
-
completeThread(uwf.varStore, threadId, "
|
|
199
|
+
completeThread(uwf.varStore, threadId, "end");
|
|
195
200
|
|
|
196
201
|
const entry = getThread(uwf.varStore, threadId);
|
|
197
202
|
expect(entry).not.toBeNull();
|
|
198
|
-
expect(entry?.status).toBe("
|
|
203
|
+
expect(entry?.status).toBe("end");
|
|
199
204
|
expect(entry?.suspendedRole).toBeNull();
|
|
200
205
|
expect(entry?.suspendMessage).toBeNull();
|
|
201
206
|
});
|
|
202
207
|
|
|
203
208
|
test("completeThread handles non-existent thread gracefully", async () => {
|
|
204
|
-
const tmpDir = await mkdtemp(join(tmpdir(), "uwf-complete-test-"));
|
|
205
209
|
const uwf = await makeUwfStore(tmpDir);
|
|
206
210
|
const threadId = "01JTEST000000000000NOEXIST" as ThreadId;
|
|
207
211
|
|
|
208
212
|
// Should not throw
|
|
209
|
-
completeThread(uwf.varStore, threadId, "
|
|
213
|
+
completeThread(uwf.varStore, threadId, "end");
|
|
210
214
|
|
|
211
215
|
const entry = getThread(uwf.varStore, threadId);
|
|
212
216
|
expect(entry).toBeNull();
|
|
213
217
|
});
|
|
214
218
|
|
|
215
219
|
test("status and completedAt tags are persisted and loaded", async () => {
|
|
216
|
-
const tmpDir = await mkdtemp(join(tmpdir(), "uwf-tags-test-"));
|
|
217
220
|
const uwf = await makeUwfStore(tmpDir);
|
|
218
221
|
const threadId = "01JTEST000000000000TAGTEST" as ThreadId;
|
|
219
222
|
const head = await seedThreadHead(uwf, "test-head");
|
|
@@ -221,7 +224,7 @@ describe("unified thread storage", () => {
|
|
|
221
224
|
|
|
222
225
|
setThread(uwf.varStore, threadId, {
|
|
223
226
|
head,
|
|
224
|
-
status: "
|
|
227
|
+
status: "end",
|
|
225
228
|
suspendedRole: null,
|
|
226
229
|
suspendMessage: null,
|
|
227
230
|
completedAt: now,
|
|
@@ -229,7 +232,7 @@ describe("unified thread storage", () => {
|
|
|
229
232
|
|
|
230
233
|
const entry = getThread(uwf.varStore, threadId);
|
|
231
234
|
expect(entry).not.toBeNull();
|
|
232
|
-
expect(entry?.status).toBe("
|
|
235
|
+
expect(entry?.status).toBe("end");
|
|
233
236
|
expect(entry?.completedAt).toBe(now);
|
|
234
237
|
});
|
|
235
238
|
});
|
|
@@ -1,22 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
2
2
|
import { tmpdir } from "node:os";
|
|
3
3
|
import { join } from "node:path";
|
|
4
4
|
import type { CasRef, ThreadId } from "@united-workforce/protocol";
|
|
5
|
-
import { describe, expect, test } from "vitest";
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
6
6
|
import {
|
|
7
7
|
completeThread,
|
|
8
|
-
createUwfStore,
|
|
8
|
+
type createUwfStore,
|
|
9
9
|
getThread,
|
|
10
10
|
loadHistoryThreads,
|
|
11
11
|
setThread,
|
|
12
12
|
} from "../store.js";
|
|
13
|
-
|
|
14
|
-
async function makeUwfStore(storageRoot: string) {
|
|
15
|
-
const casDir = join(storageRoot, "cas");
|
|
16
|
-
await mkdir(casDir, { recursive: true });
|
|
17
|
-
process.env.OCAS_HOME = casDir;
|
|
18
|
-
return createUwfStore(storageRoot);
|
|
19
|
-
}
|
|
13
|
+
import { makeUwfStore } from "./thread-test-helpers.js";
|
|
20
14
|
|
|
21
15
|
async function seedHistoryHead(
|
|
22
16
|
uwf: Awaited<ReturnType<typeof createUwfStore>>,
|
|
@@ -25,9 +19,25 @@ async function seedHistoryHead(
|
|
|
25
19
|
return (await uwf.store.cas.put(uwf.schemas.text, label)) as CasRef;
|
|
26
20
|
}
|
|
27
21
|
|
|
22
|
+
let tmpDir: string;
|
|
23
|
+
let savedOcasHome: string | undefined;
|
|
24
|
+
|
|
25
|
+
beforeEach(async () => {
|
|
26
|
+
savedOcasHome = process.env.OCAS_HOME;
|
|
27
|
+
tmpDir = await mkdtemp(join(tmpdir(), "uwf-cancel-test-"));
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
afterEach(async () => {
|
|
31
|
+
if (savedOcasHome === undefined) {
|
|
32
|
+
delete process.env.OCAS_HOME;
|
|
33
|
+
} else {
|
|
34
|
+
process.env.OCAS_HOME = savedOcasHome;
|
|
35
|
+
}
|
|
36
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
37
|
+
});
|
|
38
|
+
|
|
28
39
|
describe("thread cancel status", () => {
|
|
29
40
|
test("cancelled thread has status 'cancelled'", async () => {
|
|
30
|
-
const tmpDir = await mkdtemp(join(tmpdir(), "uwf-cancel-test-"));
|
|
31
41
|
const threadId = "01JTEST000000000000CANCEL1" as ThreadId;
|
|
32
42
|
const uwf = await makeUwfStore(tmpDir);
|
|
33
43
|
const head = await seedHistoryHead(uwf, "cancelled-head");
|
|
@@ -48,7 +58,6 @@ describe("thread cancel status", () => {
|
|
|
48
58
|
});
|
|
49
59
|
|
|
50
60
|
test("completed thread has status 'completed'", async () => {
|
|
51
|
-
const tmpDir = await mkdtemp(join(tmpdir(), "uwf-cancel-test-"));
|
|
52
61
|
const threadId = "01JTEST000000000000CANCEL2" as ThreadId;
|
|
53
62
|
const uwf = await makeUwfStore(tmpDir);
|
|
54
63
|
const head = await seedHistoryHead(uwf, "completed-head");
|
|
@@ -61,15 +70,14 @@ describe("thread cancel status", () => {
|
|
|
61
70
|
completedAt: null,
|
|
62
71
|
});
|
|
63
72
|
|
|
64
|
-
completeThread(uwf.varStore, threadId, "
|
|
73
|
+
completeThread(uwf.varStore, threadId, "end");
|
|
65
74
|
|
|
66
75
|
const entry = getThread(uwf.varStore, threadId);
|
|
67
76
|
expect(entry).not.toBeNull();
|
|
68
|
-
expect(entry?.status).toBe("
|
|
77
|
+
expect(entry?.status).toBe("end");
|
|
69
78
|
});
|
|
70
79
|
|
|
71
80
|
test("loadHistoryThreads returns completed and cancelled", async () => {
|
|
72
|
-
const tmpDir = await mkdtemp(join(tmpdir(), "uwf-cancel-test-"));
|
|
73
81
|
const uwf = await makeUwfStore(tmpDir);
|
|
74
82
|
const head1 = await seedHistoryHead(uwf, "head1");
|
|
75
83
|
const head2 = await seedHistoryHead(uwf, "head2");
|
|
@@ -82,7 +90,7 @@ describe("thread cancel status", () => {
|
|
|
82
90
|
suspendMessage: null,
|
|
83
91
|
completedAt: null,
|
|
84
92
|
});
|
|
85
|
-
completeThread(uwf.varStore, threadId1, "
|
|
93
|
+
completeThread(uwf.varStore, threadId1, "end");
|
|
86
94
|
|
|
87
95
|
const threadId2 = "01JTEST000000000000CANCEL5" as ThreadId;
|
|
88
96
|
setThread(uwf.varStore, threadId2, {
|
|
@@ -99,11 +107,10 @@ describe("thread cancel status", () => {
|
|
|
99
107
|
const statuses = Object.values(history)
|
|
100
108
|
.map((entry) => entry.status)
|
|
101
109
|
.sort();
|
|
102
|
-
expect(statuses).toEqual(["cancelled", "
|
|
110
|
+
expect(statuses).toEqual(["cancelled", "end"]);
|
|
103
111
|
});
|
|
104
112
|
|
|
105
113
|
test("mixed completed and cancelled entries preserve distinct statuses", async () => {
|
|
106
|
-
const tmpDir = await mkdtemp(join(tmpdir(), "uwf-cancel-test-"));
|
|
107
114
|
const uwf = await makeUwfStore(tmpDir);
|
|
108
115
|
const head1 = await seedHistoryHead(uwf, "head1");
|
|
109
116
|
const head2 = await seedHistoryHead(uwf, "head2");
|
|
@@ -116,7 +123,7 @@ describe("thread cancel status", () => {
|
|
|
116
123
|
suspendMessage: null,
|
|
117
124
|
completedAt: null,
|
|
118
125
|
});
|
|
119
|
-
completeThread(uwf.varStore, threadId1, "
|
|
126
|
+
completeThread(uwf.varStore, threadId1, "end");
|
|
120
127
|
|
|
121
128
|
const threadId2 = "01JTEST000000000000CANCEL7" as ThreadId;
|
|
122
129
|
setThread(uwf.varStore, threadId2, {
|
|
@@ -133,6 +140,6 @@ describe("thread cancel status", () => {
|
|
|
133
140
|
const statuses = Object.values(history)
|
|
134
141
|
.map((entry) => entry.status)
|
|
135
142
|
.sort();
|
|
136
|
-
expect(statuses).toEqual(["cancelled", "
|
|
143
|
+
expect(statuses).toEqual(["cancelled", "end"]);
|
|
137
144
|
});
|
|
138
145
|
});
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { formatOutput, getTextRenderer, TEXT_RENDERERS } from "../format.js";
|
|
3
|
+
import { renderThreadCancel } from "../text-renderers.js";
|
|
4
|
+
|
|
5
|
+
describe("thread cancel — text renderer registration", () => {
|
|
6
|
+
test("TEXT_RENDERERS contains 'thread cancel'", () => {
|
|
7
|
+
expect(getTextRenderer("thread cancel")).toBeDefined();
|
|
8
|
+
expect(typeof getTextRenderer("thread cancel")).toBe("function");
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
test("TEXT_RENDERERS['thread cancel'] is the same reference as renderThreadCancel", () => {
|
|
12
|
+
expect(TEXT_RENDERERS["thread cancel"]).toBe(renderThreadCancel);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("renderThreadCancel is exported from text-renderers.ts", () => {
|
|
16
|
+
expect(typeof renderThreadCancel).toBe("function");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
describe("renderThreadCancel — output shape", () => {
|
|
21
|
+
test("returns a string for full payload", () => {
|
|
22
|
+
const out = renderThreadCancel({
|
|
23
|
+
thread: "01JTEST000000000000CANCEL1",
|
|
24
|
+
cancelled: true,
|
|
25
|
+
});
|
|
26
|
+
expect(typeof out).toBe("string");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("includes the cancelled thread's ULID", () => {
|
|
30
|
+
const out = renderThreadCancel({
|
|
31
|
+
thread: "01JTEST000000000000CANCEL1",
|
|
32
|
+
cancelled: true,
|
|
33
|
+
});
|
|
34
|
+
expect(out).toContain("01JTEST000000000000CANCEL1");
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
test("indicates cancelled status (Status: cancelled OR Cancelled: yes)", () => {
|
|
38
|
+
const out = renderThreadCancel({
|
|
39
|
+
thread: "01JTEST000000000000CANCEL1",
|
|
40
|
+
cancelled: true,
|
|
41
|
+
});
|
|
42
|
+
// accept either rendering style
|
|
43
|
+
const lower = out.toLowerCase();
|
|
44
|
+
const hasCancelMarker = lower.includes("cancelled") || lower.includes("yes");
|
|
45
|
+
expect(hasCancelMarker).toBe(true);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("does NOT begin with '{' or '[' (not raw JSON)", () => {
|
|
49
|
+
const out = renderThreadCancel({
|
|
50
|
+
thread: "01JTEST000000000000CANCEL1",
|
|
51
|
+
cancelled: true,
|
|
52
|
+
});
|
|
53
|
+
const trimmed = out.trimStart();
|
|
54
|
+
expect(trimmed.startsWith("{")).toBe(false);
|
|
55
|
+
expect(trimmed.startsWith("[")).toBe(false);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("does NOT contain literal 'undefined'", () => {
|
|
59
|
+
const out = renderThreadCancel({
|
|
60
|
+
thread: "01JTEST000000000000CANCEL1",
|
|
61
|
+
cancelled: true,
|
|
62
|
+
});
|
|
63
|
+
expect(out).not.toContain("undefined");
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe("renderThreadCancel — partial / missing data", () => {
|
|
68
|
+
test("missing 'cancelled' field — returns string, no throw, no 'undefined'", () => {
|
|
69
|
+
const out = renderThreadCancel({ thread: "01JTEST000000000000CANCEL1" });
|
|
70
|
+
expect(typeof out).toBe("string");
|
|
71
|
+
expect(out).not.toContain("undefined");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
test("missing 'thread' field — returns string, no throw, no 'undefined'", () => {
|
|
75
|
+
const out = renderThreadCancel({ cancelled: true });
|
|
76
|
+
expect(typeof out).toBe("string");
|
|
77
|
+
expect(out).not.toContain("undefined");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("empty object — returns string, no throw, no 'undefined'", () => {
|
|
81
|
+
const out = renderThreadCancel({});
|
|
82
|
+
expect(typeof out).toBe("string");
|
|
83
|
+
expect(out).not.toContain("undefined");
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("null payload — returns string, no throw", () => {
|
|
87
|
+
expect(() => renderThreadCancel(null)).not.toThrow();
|
|
88
|
+
const out = renderThreadCancel(null);
|
|
89
|
+
expect(typeof out).toBe("string");
|
|
90
|
+
expect(out).not.toContain("undefined");
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
test("non-object payload (string) — returns string, no throw", () => {
|
|
94
|
+
expect(() => renderThreadCancel("oops")).not.toThrow();
|
|
95
|
+
const out = renderThreadCancel("oops");
|
|
96
|
+
expect(typeof out).toBe("string");
|
|
97
|
+
expect(out).not.toContain("undefined");
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
describe("formatOutput integration — thread cancel", () => {
|
|
102
|
+
test("formatOutput(data, 'text', 'thread cancel') uses renderer", () => {
|
|
103
|
+
const data = { thread: "01JTEST000000000000CANCEL1", cancelled: true };
|
|
104
|
+
const out = formatOutput(data, "text", "thread cancel");
|
|
105
|
+
expect(typeof out).toBe("string");
|
|
106
|
+
expect(out).not.toContain("undefined");
|
|
107
|
+
expect(out.trimStart().startsWith("{")).toBe(false);
|
|
108
|
+
expect(out).toContain("01JTEST000000000000CANCEL1");
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
test("formatOutput(data, 'json', 'thread cancel') still emits parseable JSON", () => {
|
|
112
|
+
const data = { thread: "01JTEST000000000000CANCEL1", cancelled: true };
|
|
113
|
+
const out = formatOutput(data, "json", "thread cancel");
|
|
114
|
+
const parsed = JSON.parse(out);
|
|
115
|
+
expect(parsed).toEqual(data);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("formatOutput(data, 'yaml', 'thread cancel') still emits YAML", () => {
|
|
119
|
+
const data = { thread: "01JTEST000000000000CANCEL1", cancelled: true };
|
|
120
|
+
const out = formatOutput(data, "yaml", "thread cancel");
|
|
121
|
+
expect(typeof out).toBe("string");
|
|
122
|
+
expect(out).toContain("thread:");
|
|
123
|
+
expect(out).toContain("cancelled:");
|
|
124
|
+
});
|
|
125
|
+
});
|