@united-workforce/cli 0.1.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/LICENSE +21 -0
- package/README.md +221 -0
- package/dist/__tests__/adapter-json-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/adapter-json-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/adapter-json-roundtrip.test.js +147 -0
- package/dist/__tests__/adapter-json-roundtrip.test.js.map +1 -0
- package/dist/__tests__/config.test.d.ts +2 -0
- package/dist/__tests__/config.test.d.ts.map +1 -0
- package/dist/__tests__/config.test.js +685 -0
- package/dist/__tests__/config.test.js.map +1 -0
- package/dist/__tests__/current-role.test.d.ts +2 -0
- package/dist/__tests__/current-role.test.d.ts.map +1 -0
- package/dist/__tests__/current-role.test.js +401 -0
- package/dist/__tests__/current-role.test.js.map +1 -0
- package/dist/__tests__/e2e-mock-agent.test.d.ts +2 -0
- package/dist/__tests__/e2e-mock-agent.test.d.ts.map +1 -0
- package/dist/__tests__/e2e-mock-agent.test.js +401 -0
- package/dist/__tests__/e2e-mock-agent.test.js.map +1 -0
- package/dist/__tests__/include-tag.test.d.ts +2 -0
- package/dist/__tests__/include-tag.test.d.ts.map +1 -0
- package/dist/__tests__/include-tag.test.js +69 -0
- package/dist/__tests__/include-tag.test.js.map +1 -0
- package/dist/__tests__/log.test.d.ts +2 -0
- package/dist/__tests__/log.test.d.ts.map +1 -0
- package/dist/__tests__/log.test.js +161 -0
- package/dist/__tests__/log.test.js.map +1 -0
- package/dist/__tests__/moderator-evaluate.test.d.ts +2 -0
- package/dist/__tests__/moderator-evaluate.test.d.ts.map +1 -0
- package/dist/__tests__/moderator-evaluate.test.js +170 -0
- package/dist/__tests__/moderator-evaluate.test.js.map +1 -0
- package/dist/__tests__/preload.d.ts +3 -0
- package/dist/__tests__/preload.d.ts.map +1 -0
- package/dist/__tests__/preload.js +6 -0
- package/dist/__tests__/preload.js.map +1 -0
- package/dist/__tests__/prompt.test.d.ts +2 -0
- package/dist/__tests__/prompt.test.d.ts.map +1 -0
- package/dist/__tests__/prompt.test.js +111 -0
- package/dist/__tests__/prompt.test.js.map +1 -0
- package/dist/__tests__/resolve-head-hash.test.d.ts +2 -0
- package/dist/__tests__/resolve-head-hash.test.d.ts.map +1 -0
- package/dist/__tests__/resolve-head-hash.test.js +66 -0
- package/dist/__tests__/resolve-head-hash.test.js.map +1 -0
- package/dist/__tests__/setup-agent-discovery.test.d.ts +2 -0
- package/dist/__tests__/setup-agent-discovery.test.d.ts.map +1 -0
- package/dist/__tests__/setup-agent-discovery.test.js +119 -0
- package/dist/__tests__/setup-agent-discovery.test.js.map +1 -0
- package/dist/__tests__/setup-complexity.test.d.ts +2 -0
- package/dist/__tests__/setup-complexity.test.d.ts.map +1 -0
- package/dist/__tests__/setup-complexity.test.js +314 -0
- package/dist/__tests__/setup-complexity.test.js.map +1 -0
- package/dist/__tests__/setup-validate.test.d.ts +2 -0
- package/dist/__tests__/setup-validate.test.d.ts.map +1 -0
- package/dist/__tests__/setup-validate.test.js +108 -0
- package/dist/__tests__/setup-validate.test.js.map +1 -0
- package/dist/__tests__/solve-issue-tea-worktree.test.d.ts +2 -0
- package/dist/__tests__/solve-issue-tea-worktree.test.d.ts.map +1 -0
- package/dist/__tests__/solve-issue-tea-worktree.test.js +107 -0
- package/dist/__tests__/solve-issue-tea-worktree.test.js.map +1 -0
- package/dist/__tests__/spawn-agent-json.test.d.ts +2 -0
- package/dist/__tests__/spawn-agent-json.test.d.ts.map +1 -0
- package/dist/__tests__/spawn-agent-json.test.js +79 -0
- package/dist/__tests__/spawn-agent-json.test.js.map +1 -0
- package/dist/__tests__/step-read.test.d.ts +2 -0
- package/dist/__tests__/step-read.test.d.ts.map +1 -0
- package/dist/__tests__/step-read.test.js +561 -0
- package/dist/__tests__/step-read.test.js.map +1 -0
- package/dist/__tests__/step-show-json.test.d.ts +2 -0
- package/dist/__tests__/step-show-json.test.d.ts.map +1 -0
- package/dist/__tests__/step-show-json.test.js +311 -0
- package/dist/__tests__/step-show-json.test.js.map +1 -0
- package/dist/__tests__/step-timing.test.d.ts +2 -0
- package/dist/__tests__/step-timing.test.d.ts.map +1 -0
- package/dist/__tests__/step-timing.test.js +345 -0
- package/dist/__tests__/step-timing.test.js.map +1 -0
- package/dist/__tests__/store-global-cas.test.d.ts +2 -0
- package/dist/__tests__/store-global-cas.test.d.ts.map +1 -0
- package/dist/__tests__/store-global-cas.test.js +235 -0
- package/dist/__tests__/store-global-cas.test.js.map +1 -0
- package/dist/__tests__/store-storage-root.test.d.ts +2 -0
- package/dist/__tests__/store-storage-root.test.d.ts.map +1 -0
- package/dist/__tests__/store-storage-root.test.js +43 -0
- package/dist/__tests__/store-storage-root.test.js.map +1 -0
- package/dist/__tests__/store-unified-threads.test.d.ts +2 -0
- package/dist/__tests__/store-unified-threads.test.d.ts.map +1 -0
- package/dist/__tests__/store-unified-threads.test.js +189 -0
- package/dist/__tests__/store-unified-threads.test.js.map +1 -0
- package/dist/__tests__/thread-cancel-status.test.d.ts +2 -0
- package/dist/__tests__/thread-cancel-status.test.d.ts.map +1 -0
- package/dist/__tests__/thread-cancel-status.test.js +111 -0
- package/dist/__tests__/thread-cancel-status.test.js.map +1 -0
- package/dist/__tests__/thread-list-filters.test.d.ts +2 -0
- package/dist/__tests__/thread-list-filters.test.d.ts.map +1 -0
- package/dist/__tests__/thread-list-filters.test.js +442 -0
- package/dist/__tests__/thread-list-filters.test.js.map +1 -0
- package/dist/__tests__/thread-location.test.d.ts +2 -0
- package/dist/__tests__/thread-location.test.d.ts.map +1 -0
- package/dist/__tests__/thread-location.test.js +159 -0
- package/dist/__tests__/thread-location.test.js.map +1 -0
- package/dist/__tests__/thread-read-quota.test.d.ts +2 -0
- package/dist/__tests__/thread-read-quota.test.d.ts.map +1 -0
- package/dist/__tests__/thread-read-quota.test.js +546 -0
- package/dist/__tests__/thread-read-quota.test.js.map +1 -0
- package/dist/__tests__/thread-read-xml-tags.test.d.ts +2 -0
- package/dist/__tests__/thread-read-xml-tags.test.d.ts.map +1 -0
- package/dist/__tests__/thread-read-xml-tags.test.js +610 -0
- package/dist/__tests__/thread-read-xml-tags.test.js.map +1 -0
- package/dist/__tests__/thread-resume.test.d.ts +2 -0
- package/dist/__tests__/thread-resume.test.d.ts.map +1 -0
- package/dist/__tests__/thread-resume.test.js +592 -0
- package/dist/__tests__/thread-resume.test.js.map +1 -0
- package/dist/__tests__/thread-show-status.test.d.ts +2 -0
- package/dist/__tests__/thread-show-status.test.d.ts.map +1 -0
- package/dist/__tests__/thread-show-status.test.js +267 -0
- package/dist/__tests__/thread-show-status.test.js.map +1 -0
- package/dist/__tests__/thread-start-cwd-cli.test.d.ts +2 -0
- package/dist/__tests__/thread-start-cwd-cli.test.d.ts.map +1 -0
- package/dist/__tests__/thread-start-cwd-cli.test.js +130 -0
- package/dist/__tests__/thread-start-cwd-cli.test.js.map +1 -0
- package/dist/__tests__/thread-step-count.test.d.ts +2 -0
- package/dist/__tests__/thread-step-count.test.d.ts.map +1 -0
- package/dist/__tests__/thread-step-count.test.js +55 -0
- package/dist/__tests__/thread-step-count.test.js.map +1 -0
- package/dist/__tests__/thread-suspend-step.test.d.ts +2 -0
- package/dist/__tests__/thread-suspend-step.test.d.ts.map +1 -0
- package/dist/__tests__/thread-suspend-step.test.js +155 -0
- package/dist/__tests__/thread-suspend-step.test.js.map +1 -0
- package/dist/__tests__/thread-suspended-display.test.d.ts +2 -0
- package/dist/__tests__/thread-suspended-display.test.d.ts.map +1 -0
- package/dist/__tests__/thread-suspended-display.test.js +247 -0
- package/dist/__tests__/thread-suspended-display.test.js.map +1 -0
- package/dist/__tests__/thread-test-helpers.d.ts +4 -0
- package/dist/__tests__/thread-test-helpers.d.ts.map +1 -0
- package/dist/__tests__/thread-test-helpers.js +23 -0
- package/dist/__tests__/thread-test-helpers.js.map +1 -0
- package/dist/__tests__/thread.test.d.ts +2 -0
- package/dist/__tests__/thread.test.d.ts.map +1 -0
- package/dist/__tests__/thread.test.js +883 -0
- package/dist/__tests__/thread.test.js.map +1 -0
- package/dist/__tests__/validate-semantic.test.d.ts +2 -0
- package/dist/__tests__/validate-semantic.test.d.ts.map +1 -0
- package/dist/__tests__/validate-semantic.test.js +408 -0
- package/dist/__tests__/validate-semantic.test.js.map +1 -0
- package/dist/__tests__/workflow-resolution.test.d.ts +2 -0
- package/dist/__tests__/workflow-resolution.test.d.ts.map +1 -0
- package/dist/__tests__/workflow-resolution.test.js +308 -0
- package/dist/__tests__/workflow-resolution.test.js.map +1 -0
- package/dist/background/background.d.ts +38 -0
- package/dist/background/background.d.ts.map +1 -0
- package/dist/background/background.js +123 -0
- package/dist/background/background.js.map +1 -0
- package/dist/background/index.d.ts +3 -0
- package/dist/background/index.d.ts.map +1 -0
- package/dist/background/index.js +2 -0
- package/dist/background/index.js.map +1 -0
- package/dist/background/types.d.ts +9 -0
- package/dist/background/types.d.ts.map +1 -0
- package/dist/background/types.js +2 -0
- package/dist/background/types.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +535 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/config.d.ts +41 -0
- package/dist/commands/config.d.ts.map +1 -0
- package/dist/commands/config.js +252 -0
- package/dist/commands/config.js.map +1 -0
- package/dist/commands/log.d.ts +26 -0
- package/dist/commands/log.d.ts.map +1 -0
- package/dist/commands/log.js +79 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/prompt.d.ts +6 -0
- package/dist/commands/prompt.d.ts.map +1 -0
- package/dist/commands/prompt.js +67 -0
- package/dist/commands/prompt.js.map +1 -0
- package/dist/commands/setup.d.ts +73 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/commands/setup.js +522 -0
- package/dist/commands/setup.js.map +1 -0
- package/dist/commands/shared.d.ts +31 -0
- package/dist/commands/shared.d.ts.map +1 -0
- package/dist/commands/shared.js +154 -0
- package/dist/commands/shared.js.map +1 -0
- package/dist/commands/step.d.ts +18 -0
- package/dist/commands/step.d.ts.map +1 -0
- package/dist/commands/step.js +257 -0
- package/dist/commands/step.js.map +1 -0
- package/dist/commands/thread-time-parser.d.ts +6 -0
- package/dist/commands/thread-time-parser.d.ts.map +1 -0
- package/dist/commands/thread-time-parser.js +22 -0
- package/dist/commands/thread-time-parser.js.map +1 -0
- package/dist/commands/thread.d.ts +38 -0
- package/dist/commands/thread.d.ts.map +1 -0
- package/dist/commands/thread.js +1087 -0
- package/dist/commands/thread.js.map +1 -0
- package/dist/commands/workflow.d.ts +24 -0
- package/dist/commands/workflow.d.ts.map +1 -0
- package/dist/commands/workflow.js +138 -0
- package/dist/commands/workflow.js.map +1 -0
- package/dist/format.d.ts +3 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +10 -0
- package/dist/format.js.map +1 -0
- package/dist/include.d.ts +12 -0
- package/dist/include.d.ts.map +1 -0
- package/dist/include.js +35 -0
- package/dist/include.js.map +1 -0
- package/dist/moderator/__tests__/evaluate.test.d.ts +2 -0
- package/dist/moderator/__tests__/evaluate.test.d.ts.map +1 -0
- package/dist/moderator/__tests__/evaluate.test.js +167 -0
- package/dist/moderator/__tests__/evaluate.test.js.map +1 -0
- package/dist/moderator/evaluate.d.ts +6 -0
- package/dist/moderator/evaluate.d.ts.map +1 -0
- package/dist/moderator/evaluate.js +65 -0
- package/dist/moderator/evaluate.js.map +1 -0
- package/dist/moderator/index.d.ts +4 -0
- package/dist/moderator/index.d.ts.map +1 -0
- package/dist/moderator/index.js +3 -0
- package/dist/moderator/index.js.map +1 -0
- package/dist/moderator/types.d.ts +25 -0
- package/dist/moderator/types.d.ts.map +1 -0
- package/dist/moderator/types.js +4 -0
- package/dist/moderator/types.js.map +1 -0
- package/dist/schemas.d.ts +16 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +17 -0
- package/dist/schemas.js.map +1 -0
- package/dist/store.d.ts +77 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +392 -0
- package/dist/store.js.map +1 -0
- package/dist/validate-semantic.d.ts +7 -0
- package/dist/validate-semantic.d.ts.map +1 -0
- package/dist/validate-semantic.js +263 -0
- package/dist/validate-semantic.js.map +1 -0
- package/dist/validate.d.ts +16 -0
- package/dist/validate.d.ts.map +1 -0
- package/dist/validate.js +115 -0
- package/dist/validate.js.map +1 -0
- package/package.json +44 -0
- package/src/__tests__/adapter-json-roundtrip.test.ts +181 -0
- package/src/__tests__/config.test.ts +740 -0
- package/src/__tests__/current-role.test.ts +438 -0
- package/src/__tests__/e2e-mock-agent.test.ts +498 -0
- package/src/__tests__/fixtures/e2e-completed-resume.mock.yaml +15 -0
- package/src/__tests__/fixtures/e2e-count.mock.yaml +19 -0
- package/src/__tests__/fixtures/e2e-count.workflow.yaml +45 -0
- package/src/__tests__/fixtures/e2e-linear.mock.yaml +13 -0
- package/src/__tests__/fixtures/e2e-linear.workflow.yaml +32 -0
- package/src/__tests__/fixtures/e2e-loop.mock.yaml +25 -0
- package/src/__tests__/fixtures/e2e-loop.workflow.yaml +36 -0
- package/src/__tests__/fixtures/e2e-mismatch.mock.yaml +16 -0
- package/src/__tests__/fixtures/e2e-mustache.mock.yaml +15 -0
- package/src/__tests__/fixtures/e2e-mustache.workflow.yaml +34 -0
- package/src/__tests__/fixtures/e2e-suspend.mock.yaml +14 -0
- package/src/__tests__/fixtures/e2e-suspend.workflow.yaml +24 -0
- package/src/__tests__/include-tag.test.ts +84 -0
- package/src/__tests__/log.test.ts +181 -0
- package/src/__tests__/moderator-evaluate.test.ts +186 -0
- package/src/__tests__/preload.ts +7 -0
- package/src/__tests__/prompt.test.ts +129 -0
- package/src/__tests__/resolve-head-hash.test.ts +86 -0
- package/src/__tests__/setup-agent-discovery.test.ts +167 -0
- package/src/__tests__/setup-complexity.test.ts +381 -0
- package/src/__tests__/setup-validate.test.ts +148 -0
- package/src/__tests__/solve-issue-tea-worktree.test.ts +144 -0
- package/src/__tests__/spawn-agent-json.test.ts +100 -0
- package/src/__tests__/step-read.test.ts +632 -0
- package/src/__tests__/step-show-json.test.ts +373 -0
- package/src/__tests__/step-timing.test.ts +392 -0
- package/src/__tests__/store-global-cas.test.ts +308 -0
- package/src/__tests__/store-storage-root.test.ts +49 -0
- package/src/__tests__/store-unified-threads.test.ts +235 -0
- package/src/__tests__/thread-cancel-status.test.ts +138 -0
- package/src/__tests__/thread-list-filters.test.ts +572 -0
- package/src/__tests__/thread-location.test.ts +186 -0
- package/src/__tests__/thread-read-quota.test.ts +613 -0
- package/src/__tests__/thread-read-xml-tags.test.ts +717 -0
- package/src/__tests__/thread-resume.test.ts +710 -0
- package/src/__tests__/thread-show-status.test.ts +317 -0
- package/src/__tests__/thread-start-cwd-cli.test.ts +164 -0
- package/src/__tests__/thread-step-count.test.ts +70 -0
- package/src/__tests__/thread-suspend-step.test.ts +181 -0
- package/src/__tests__/thread-suspended-display.test.ts +287 -0
- package/src/__tests__/thread-test-helpers.ts +37 -0
- package/src/__tests__/thread.test.ts +1025 -0
- package/src/__tests__/validate-semantic.test.ts +474 -0
- package/src/__tests__/workflow-resolution.test.ts +421 -0
- package/src/background/background.ts +147 -0
- package/src/background/index.ts +11 -0
- package/src/background/types.ts +9 -0
- package/src/cli.ts +692 -0
- package/src/commands/config.ts +304 -0
- package/src/commands/log.ts +116 -0
- package/src/commands/prompt.ts +81 -0
- package/src/commands/setup.ts +603 -0
- package/src/commands/shared.ts +227 -0
- package/src/commands/step.ts +343 -0
- package/src/commands/thread-time-parser.ts +23 -0
- package/src/commands/thread.ts +1575 -0
- package/src/commands/workflow.ts +213 -0
- package/src/format.ts +12 -0
- package/src/include.ts +37 -0
- package/src/moderator/__tests__/evaluate.test.ts +199 -0
- package/src/moderator/evaluate.ts +80 -0
- package/src/moderator/index.ts +7 -0
- package/src/moderator/types.ts +24 -0
- package/src/schemas.ts +26 -0
- package/src/store.ts +479 -0
- package/src/validate-semantic.ts +304 -0
- package/src/validate.ts +137 -0
|
@@ -0,0 +1,632 @@
|
|
|
1
|
+
import { mkdir, mkdtemp, rm } from "node:fs/promises";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { bootstrap, putSchema } from "@ocas/core";
|
|
5
|
+
import { openStore } from "@ocas/fs";
|
|
6
|
+
import type { CasRef } from "@united-workforce/protocol";
|
|
7
|
+
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
|
8
|
+
import { cmdStepRead } from "../commands/step.js";
|
|
9
|
+
import { registerUwfSchemas } from "../schemas.js";
|
|
10
|
+
|
|
11
|
+
// ── schemas used in tests ────────────────────────────────────────────────────
|
|
12
|
+
|
|
13
|
+
const TURN_SCHEMA = {
|
|
14
|
+
title: "hermes-turn",
|
|
15
|
+
type: "object" as const,
|
|
16
|
+
required: ["index", "role", "content"],
|
|
17
|
+
properties: {
|
|
18
|
+
index: { type: "integer" as const },
|
|
19
|
+
role: { type: "string" as const },
|
|
20
|
+
content: { type: "string" as const },
|
|
21
|
+
toolCalls: {
|
|
22
|
+
anyOf: [
|
|
23
|
+
{ type: "array" as const, items: { type: "object" as const } },
|
|
24
|
+
{ type: "null" as const },
|
|
25
|
+
],
|
|
26
|
+
},
|
|
27
|
+
reasoning: { anyOf: [{ type: "string" as const }, { type: "null" as const }] },
|
|
28
|
+
},
|
|
29
|
+
additionalProperties: false,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const DETAIL_SCHEMA = {
|
|
33
|
+
title: "hermes-detail",
|
|
34
|
+
type: "object" as const,
|
|
35
|
+
required: ["sessionId", "model", "duration", "turnCount", "turns"],
|
|
36
|
+
properties: {
|
|
37
|
+
sessionId: { type: "string" as const },
|
|
38
|
+
model: { type: "string" as const },
|
|
39
|
+
duration: { type: "integer" as const },
|
|
40
|
+
turnCount: { type: "integer" as const },
|
|
41
|
+
turns: {
|
|
42
|
+
type: "array" as const,
|
|
43
|
+
items: { type: "string" as const, format: "ocas_ref" },
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
additionalProperties: false,
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// ── helpers ───────────────────────────────────────────────────────────────────
|
|
50
|
+
|
|
51
|
+
async function registerDetailSchemas(store: Awaited<ReturnType<typeof openStore>>) {
|
|
52
|
+
await bootstrap(store);
|
|
53
|
+
const [turn, detail] = await Promise.all([
|
|
54
|
+
putSchema(store, TURN_SCHEMA),
|
|
55
|
+
putSchema(store, DETAIL_SCHEMA),
|
|
56
|
+
]);
|
|
57
|
+
return { turn, detail };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function generateContent(size: number, prefix = "Content"): string {
|
|
61
|
+
const base = `${prefix} `;
|
|
62
|
+
const repeat = Math.ceil(size / base.length);
|
|
63
|
+
return base.repeat(repeat).slice(0, size);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// ── fixture ───────────────────────────────────────────────────────────────────
|
|
67
|
+
|
|
68
|
+
let tmpDir: string;
|
|
69
|
+
let originalEnv: string | undefined;
|
|
70
|
+
|
|
71
|
+
beforeEach(async () => {
|
|
72
|
+
tmpDir = await mkdtemp(join(tmpdir(), "cli-uwf-step-read-test-"));
|
|
73
|
+
originalEnv = process.env.OCAS_HOME;
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
afterEach(async () => {
|
|
77
|
+
await rm(tmpDir, { recursive: true, force: true });
|
|
78
|
+
// Restore original environment
|
|
79
|
+
if (originalEnv === undefined) {
|
|
80
|
+
delete process.env.OCAS_HOME;
|
|
81
|
+
} else {
|
|
82
|
+
process.env.OCAS_HOME = originalEnv;
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
// ── step read tests ───────────────────────────────────────────────────────────
|
|
87
|
+
|
|
88
|
+
describe("step read", () => {
|
|
89
|
+
test("test 1: basic single-step read with 3 turns", async () => {
|
|
90
|
+
const casDir = join(tmpDir, "cas");
|
|
91
|
+
process.env.OCAS_HOME = casDir;
|
|
92
|
+
await mkdir(casDir, { recursive: true });
|
|
93
|
+
process.env.OCAS_HOME = casDir;
|
|
94
|
+
process.env.OCAS_HOME = casDir;
|
|
95
|
+
const store = await openStore(casDir);
|
|
96
|
+
const schemas = await registerUwfSchemas(store);
|
|
97
|
+
const detailSchemas = await registerDetailSchemas(store);
|
|
98
|
+
|
|
99
|
+
const workflowHash = await store.cas.put(schemas.workflow, {
|
|
100
|
+
name: "test-wf",
|
|
101
|
+
description: "desc",
|
|
102
|
+
roles: {
|
|
103
|
+
worker: {
|
|
104
|
+
description: "Worker",
|
|
105
|
+
goal: "You are a worker agent.",
|
|
106
|
+
capabilities: [],
|
|
107
|
+
procedure: "Do the work.",
|
|
108
|
+
output: "Summarize the work.",
|
|
109
|
+
meta: "placeholder00" as CasRef,
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
conditions: {},
|
|
113
|
+
graph: {},
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
const startHash = await store.cas.put(schemas.startNode, {
|
|
117
|
+
workflow: workflowHash,
|
|
118
|
+
prompt: "Test task",
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const outputHash = await store.cas.put(schemas.workflow, {
|
|
122
|
+
name: "out",
|
|
123
|
+
description: "",
|
|
124
|
+
roles: {},
|
|
125
|
+
conditions: {},
|
|
126
|
+
graph: {},
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
// Create 3 turns
|
|
130
|
+
const turnHashes: CasRef[] = [];
|
|
131
|
+
for (let i = 1; i <= 3; i++) {
|
|
132
|
+
const content = `Turn ${i} content with some text to make it readable.`;
|
|
133
|
+
const turnHash = await store.cas.put(detailSchemas.turn, {
|
|
134
|
+
index: i - 1,
|
|
135
|
+
role: "assistant",
|
|
136
|
+
content,
|
|
137
|
+
toolCalls: null,
|
|
138
|
+
reasoning: null,
|
|
139
|
+
});
|
|
140
|
+
turnHashes.push(turnHash);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const detailHash = await store.cas.put(detailSchemas.detail, {
|
|
144
|
+
sessionId: "session-1",
|
|
145
|
+
model: "test-model",
|
|
146
|
+
duration: 1000,
|
|
147
|
+
turnCount: 3,
|
|
148
|
+
turns: turnHashes,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const stepHash = await store.cas.put(schemas.stepNode, {
|
|
152
|
+
start: startHash,
|
|
153
|
+
prev: null,
|
|
154
|
+
role: "worker",
|
|
155
|
+
output: outputHash,
|
|
156
|
+
detail: detailHash,
|
|
157
|
+
agent: "uwf-test",
|
|
158
|
+
startedAtMs: 1000000000000,
|
|
159
|
+
completedAtMs: 1000000005000,
|
|
160
|
+
assembledPrompt: null,
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
// Read step with large quota
|
|
164
|
+
const markdown = await cmdStepRead(tmpDir, stepHash, 10000, false);
|
|
165
|
+
|
|
166
|
+
// Assert structure
|
|
167
|
+
expect(markdown).toContain(`# Step ${stepHash}`);
|
|
168
|
+
expect(markdown).toContain("**Role:** worker");
|
|
169
|
+
expect(markdown).toContain("**Agent:** uwf-test");
|
|
170
|
+
expect(markdown).toContain("## Turn 1");
|
|
171
|
+
expect(markdown).toContain("## Turn 2");
|
|
172
|
+
expect(markdown).toContain("## Turn 3");
|
|
173
|
+
expect(markdown).toContain("Turn 1 content with some text to make it readable.");
|
|
174
|
+
expect(markdown).toContain("Turn 2 content with some text to make it readable.");
|
|
175
|
+
expect(markdown).toContain("Turn 3 content with some text to make it readable.");
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("test 2: quota enforcement - multiple turns", async () => {
|
|
179
|
+
const casDir = join(tmpDir, "cas");
|
|
180
|
+
process.env.OCAS_HOME = casDir;
|
|
181
|
+
await mkdir(casDir, { recursive: true });
|
|
182
|
+
process.env.OCAS_HOME = casDir;
|
|
183
|
+
const store = await openStore(casDir);
|
|
184
|
+
const schemas = await registerUwfSchemas(store);
|
|
185
|
+
const detailSchemas = await registerDetailSchemas(store);
|
|
186
|
+
|
|
187
|
+
const workflowHash = await store.cas.put(schemas.workflow, {
|
|
188
|
+
name: "test-wf",
|
|
189
|
+
description: "desc",
|
|
190
|
+
roles: {
|
|
191
|
+
worker: {
|
|
192
|
+
description: "Worker",
|
|
193
|
+
goal: "You are a worker agent.",
|
|
194
|
+
capabilities: [],
|
|
195
|
+
procedure: "Do the work.",
|
|
196
|
+
output: "Summarize the work.",
|
|
197
|
+
meta: "placeholder00" as CasRef,
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
conditions: {},
|
|
201
|
+
graph: {},
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
const startHash = await store.cas.put(schemas.startNode, {
|
|
205
|
+
workflow: workflowHash,
|
|
206
|
+
prompt: "Test task",
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const outputHash = await store.cas.put(schemas.workflow, {
|
|
210
|
+
name: "out",
|
|
211
|
+
description: "",
|
|
212
|
+
roles: {},
|
|
213
|
+
conditions: {},
|
|
214
|
+
graph: {},
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
// Create 4 turns of ~300 chars each
|
|
218
|
+
const turnHashes: CasRef[] = [];
|
|
219
|
+
for (let i = 1; i <= 4; i++) {
|
|
220
|
+
const content = generateContent(300, `Turn${i}`);
|
|
221
|
+
const turnHash = await store.cas.put(detailSchemas.turn, {
|
|
222
|
+
index: i - 1,
|
|
223
|
+
role: "assistant",
|
|
224
|
+
content,
|
|
225
|
+
toolCalls: null,
|
|
226
|
+
reasoning: null,
|
|
227
|
+
});
|
|
228
|
+
turnHashes.push(turnHash);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const detailHash = await store.cas.put(detailSchemas.detail, {
|
|
232
|
+
sessionId: "session-1",
|
|
233
|
+
model: "test-model",
|
|
234
|
+
duration: 1000,
|
|
235
|
+
turnCount: 4,
|
|
236
|
+
turns: turnHashes,
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
const stepHash = await store.cas.put(schemas.stepNode, {
|
|
240
|
+
start: startHash,
|
|
241
|
+
prev: null,
|
|
242
|
+
role: "worker",
|
|
243
|
+
output: outputHash,
|
|
244
|
+
detail: detailHash,
|
|
245
|
+
agent: "uwf-test",
|
|
246
|
+
startedAtMs: 1000000000000,
|
|
247
|
+
completedAtMs: 1000000005000,
|
|
248
|
+
assembledPrompt: null,
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
// Read step with limited quota (700 chars)
|
|
252
|
+
const markdown = await cmdStepRead(tmpDir, stepHash, 700, false);
|
|
253
|
+
|
|
254
|
+
// Assert only most recent turns fit
|
|
255
|
+
expect(markdown).toContain(`# Step ${stepHash}`);
|
|
256
|
+
// Should have skip hint
|
|
257
|
+
expect(markdown).toContain("Earlier turns omitted");
|
|
258
|
+
// Should include at least Turn 4 (most recent)
|
|
259
|
+
expect(markdown).toContain("Turn4");
|
|
260
|
+
// Total length should respect quota (with tolerance for structural overhead)
|
|
261
|
+
expect(markdown.length).toBeLessThanOrEqual(900); // 700 quota + 200 buffer tolerance
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
test("test 3: minimal quota edge case - always show at least one turn", async () => {
|
|
265
|
+
const casDir = join(tmpDir, "cas");
|
|
266
|
+
process.env.OCAS_HOME = casDir;
|
|
267
|
+
await mkdir(casDir, { recursive: true });
|
|
268
|
+
process.env.OCAS_HOME = casDir;
|
|
269
|
+
const store = await openStore(casDir);
|
|
270
|
+
const schemas = await registerUwfSchemas(store);
|
|
271
|
+
const detailSchemas = await registerDetailSchemas(store);
|
|
272
|
+
|
|
273
|
+
const workflowHash = await store.cas.put(schemas.workflow, {
|
|
274
|
+
name: "test-wf",
|
|
275
|
+
description: "desc",
|
|
276
|
+
roles: {
|
|
277
|
+
worker: {
|
|
278
|
+
description: "Worker",
|
|
279
|
+
goal: "You are a worker agent.",
|
|
280
|
+
capabilities: [],
|
|
281
|
+
procedure: "Do the work.",
|
|
282
|
+
output: "Summarize the work.",
|
|
283
|
+
meta: "placeholder00" as CasRef,
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
conditions: {},
|
|
287
|
+
graph: {},
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const startHash = await store.cas.put(schemas.startNode, {
|
|
291
|
+
workflow: workflowHash,
|
|
292
|
+
prompt: "Test task",
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
const outputHash = await store.cas.put(schemas.workflow, {
|
|
296
|
+
name: "out",
|
|
297
|
+
description: "",
|
|
298
|
+
roles: {},
|
|
299
|
+
conditions: {},
|
|
300
|
+
graph: {},
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
// Create 1 turn of 500 chars
|
|
304
|
+
const content = generateContent(500, "LongTurn");
|
|
305
|
+
const turnHash = await store.cas.put(detailSchemas.turn, {
|
|
306
|
+
index: 0,
|
|
307
|
+
role: "assistant",
|
|
308
|
+
content,
|
|
309
|
+
toolCalls: null,
|
|
310
|
+
reasoning: null,
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
const detailHash = await store.cas.put(detailSchemas.detail, {
|
|
314
|
+
sessionId: "session-1",
|
|
315
|
+
model: "test-model",
|
|
316
|
+
duration: 1000,
|
|
317
|
+
turnCount: 1,
|
|
318
|
+
turns: [turnHash],
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
const stepHash = await store.cas.put(schemas.stepNode, {
|
|
322
|
+
start: startHash,
|
|
323
|
+
prev: null,
|
|
324
|
+
role: "worker",
|
|
325
|
+
output: outputHash,
|
|
326
|
+
detail: detailHash,
|
|
327
|
+
agent: "uwf-test",
|
|
328
|
+
startedAtMs: 1000000000000,
|
|
329
|
+
completedAtMs: 1000000005000,
|
|
330
|
+
assembledPrompt: null,
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
// Read step with minimal quota (1 char)
|
|
334
|
+
const markdown = await cmdStepRead(tmpDir, stepHash, 1, false);
|
|
335
|
+
|
|
336
|
+
// Assert at least one turn is always shown
|
|
337
|
+
expect(markdown).toContain("LongTurn");
|
|
338
|
+
expect(markdown.length).toBeGreaterThan(1);
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
test("test 4: step with no detail field", async () => {
|
|
342
|
+
const casDir = join(tmpDir, "cas");
|
|
343
|
+
process.env.OCAS_HOME = casDir;
|
|
344
|
+
await mkdir(casDir, { recursive: true });
|
|
345
|
+
process.env.OCAS_HOME = casDir;
|
|
346
|
+
const store = await openStore(casDir);
|
|
347
|
+
const schemas = await registerUwfSchemas(store);
|
|
348
|
+
|
|
349
|
+
const workflowHash = await store.cas.put(schemas.workflow, {
|
|
350
|
+
name: "test-wf",
|
|
351
|
+
description: "desc",
|
|
352
|
+
roles: {
|
|
353
|
+
worker: {
|
|
354
|
+
description: "Worker",
|
|
355
|
+
goal: "You are a worker agent.",
|
|
356
|
+
capabilities: [],
|
|
357
|
+
procedure: "Do the work.",
|
|
358
|
+
output: "Summarize the work.",
|
|
359
|
+
meta: "placeholder00" as CasRef,
|
|
360
|
+
},
|
|
361
|
+
},
|
|
362
|
+
conditions: {},
|
|
363
|
+
graph: {},
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
const startHash = await store.cas.put(schemas.startNode, {
|
|
367
|
+
workflow: workflowHash,
|
|
368
|
+
prompt: "Test task",
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
const outputHash = await store.cas.put(schemas.workflow, {
|
|
372
|
+
name: "out",
|
|
373
|
+
description: "",
|
|
374
|
+
roles: {},
|
|
375
|
+
conditions: {},
|
|
376
|
+
graph: {},
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
const stepHash = await store.cas.put(schemas.stepNode, {
|
|
380
|
+
start: startHash,
|
|
381
|
+
prev: null,
|
|
382
|
+
role: "worker",
|
|
383
|
+
output: outputHash,
|
|
384
|
+
detail: null,
|
|
385
|
+
agent: "uwf-test",
|
|
386
|
+
startedAtMs: 1000000000000,
|
|
387
|
+
completedAtMs: 1000000005000,
|
|
388
|
+
assembledPrompt: null,
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
// Read step - should return metadata only (no error)
|
|
392
|
+
const markdown = await cmdStepRead(tmpDir, stepHash, 4000, false);
|
|
393
|
+
|
|
394
|
+
// Assert metadata is present
|
|
395
|
+
expect(markdown).toContain(`# Step ${stepHash}`);
|
|
396
|
+
expect(markdown).toContain("**Role:** worker");
|
|
397
|
+
expect(markdown).toContain("**Agent:** uwf-test");
|
|
398
|
+
// Should not have turn sections
|
|
399
|
+
expect(markdown).not.toContain("## Turn");
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
test("test 5: step with detail but no turns array", async () => {
|
|
403
|
+
const casDir = join(tmpDir, "cas");
|
|
404
|
+
process.env.OCAS_HOME = casDir;
|
|
405
|
+
await mkdir(casDir, { recursive: true });
|
|
406
|
+
process.env.OCAS_HOME = casDir;
|
|
407
|
+
const store = await openStore(casDir);
|
|
408
|
+
const schemas = await registerUwfSchemas(store);
|
|
409
|
+
await registerDetailSchemas(store);
|
|
410
|
+
|
|
411
|
+
const workflowHash = await store.cas.put(schemas.workflow, {
|
|
412
|
+
name: "test-wf",
|
|
413
|
+
description: "desc",
|
|
414
|
+
roles: {
|
|
415
|
+
worker: {
|
|
416
|
+
description: "Worker",
|
|
417
|
+
goal: "You are a worker agent.",
|
|
418
|
+
capabilities: [],
|
|
419
|
+
procedure: "Do the work.",
|
|
420
|
+
output: "Summarize the work.",
|
|
421
|
+
meta: "placeholder00" as CasRef,
|
|
422
|
+
},
|
|
423
|
+
},
|
|
424
|
+
conditions: {},
|
|
425
|
+
graph: {},
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
const startHash = await store.cas.put(schemas.startNode, {
|
|
429
|
+
workflow: workflowHash,
|
|
430
|
+
prompt: "Test task",
|
|
431
|
+
});
|
|
432
|
+
|
|
433
|
+
const outputHash = await store.cas.put(schemas.workflow, {
|
|
434
|
+
name: "out",
|
|
435
|
+
description: "",
|
|
436
|
+
roles: {},
|
|
437
|
+
conditions: {},
|
|
438
|
+
graph: {},
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
// Create detail with different schema (no turns)
|
|
442
|
+
const SIMPLE_DETAIL_SCHEMA = {
|
|
443
|
+
title: "simple-detail",
|
|
444
|
+
type: "object" as const,
|
|
445
|
+
required: ["sessionId"],
|
|
446
|
+
properties: {
|
|
447
|
+
sessionId: { type: "string" as const },
|
|
448
|
+
},
|
|
449
|
+
additionalProperties: false,
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
await bootstrap(store);
|
|
453
|
+
const simpleDetailType = await putSchema(store, SIMPLE_DETAIL_SCHEMA);
|
|
454
|
+
const detailHash = await store.cas.put(simpleDetailType, {
|
|
455
|
+
sessionId: "session-1",
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
const stepHash = await store.cas.put(schemas.stepNode, {
|
|
459
|
+
start: startHash,
|
|
460
|
+
prev: null,
|
|
461
|
+
role: "worker",
|
|
462
|
+
output: outputHash,
|
|
463
|
+
detail: detailHash,
|
|
464
|
+
agent: "uwf-test",
|
|
465
|
+
startedAtMs: 1000000000000,
|
|
466
|
+
completedAtMs: 1000000005000,
|
|
467
|
+
assembledPrompt: null,
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
// Read step - should return metadata only (no error)
|
|
471
|
+
const markdown = await cmdStepRead(tmpDir, stepHash, 4000, false);
|
|
472
|
+
|
|
473
|
+
// Assert metadata is present
|
|
474
|
+
expect(markdown).toContain(`# Step ${stepHash}`);
|
|
475
|
+
expect(markdown).toContain("**Role:** worker");
|
|
476
|
+
// Should not have turn sections
|
|
477
|
+
expect(markdown).not.toContain("## Turn");
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
test("test 6: displays role and tool calls in turn body", async () => {
|
|
481
|
+
const casDir = join(tmpDir, "cas");
|
|
482
|
+
process.env.OCAS_HOME = casDir;
|
|
483
|
+
await mkdir(casDir, { recursive: true });
|
|
484
|
+
process.env.OCAS_HOME = casDir;
|
|
485
|
+
const store = await openStore(casDir);
|
|
486
|
+
const schemas = await registerUwfSchemas(store);
|
|
487
|
+
const detailSchemas = await registerDetailSchemas(store);
|
|
488
|
+
|
|
489
|
+
const workflowHash = await store.cas.put(schemas.workflow, {
|
|
490
|
+
name: "test-wf",
|
|
491
|
+
description: "desc",
|
|
492
|
+
roles: {
|
|
493
|
+
worker: {
|
|
494
|
+
description: "Worker",
|
|
495
|
+
goal: "You are a worker agent.",
|
|
496
|
+
capabilities: [],
|
|
497
|
+
procedure: "Do the work.",
|
|
498
|
+
output: "Summarize the work.",
|
|
499
|
+
meta: "placeholder00" as CasRef,
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
conditions: {},
|
|
503
|
+
graph: {},
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
const startHash = await store.cas.put(schemas.startNode, {
|
|
507
|
+
workflow: workflowHash,
|
|
508
|
+
prompt: "Test task",
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
const outputHash = await store.cas.put(schemas.workflow, {
|
|
512
|
+
name: "out",
|
|
513
|
+
description: "",
|
|
514
|
+
roles: {},
|
|
515
|
+
conditions: {},
|
|
516
|
+
graph: {},
|
|
517
|
+
});
|
|
518
|
+
|
|
519
|
+
const turnHash = await store.cas.put(detailSchemas.turn, {
|
|
520
|
+
index: 0,
|
|
521
|
+
role: "assistant",
|
|
522
|
+
content: "",
|
|
523
|
+
toolCalls: [{ name: "terminal", args: '{"command":"echo hi"}' }],
|
|
524
|
+
reasoning: null,
|
|
525
|
+
});
|
|
526
|
+
|
|
527
|
+
const detailHash = await store.cas.put(detailSchemas.detail, {
|
|
528
|
+
sessionId: "session-1",
|
|
529
|
+
model: "test-model",
|
|
530
|
+
duration: 1000,
|
|
531
|
+
turnCount: 1,
|
|
532
|
+
turns: [turnHash],
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
const stepHash = await store.cas.put(schemas.stepNode, {
|
|
536
|
+
start: startHash,
|
|
537
|
+
prev: null,
|
|
538
|
+
role: "worker",
|
|
539
|
+
output: outputHash,
|
|
540
|
+
detail: detailHash,
|
|
541
|
+
agent: "uwf-hermes",
|
|
542
|
+
startedAtMs: 1000000000000,
|
|
543
|
+
completedAtMs: 1000000005000,
|
|
544
|
+
assembledPrompt: null,
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
const markdown = await cmdStepRead(tmpDir, stepHash, 4000, false);
|
|
548
|
+
|
|
549
|
+
expect(markdown).toContain("**Turn role:** assistant");
|
|
550
|
+
expect(markdown).toContain("**terminal**");
|
|
551
|
+
expect(markdown).toContain('{"command":"echo hi"}');
|
|
552
|
+
});
|
|
553
|
+
|
|
554
|
+
test("test 7: turn content with special characters", async () => {
|
|
555
|
+
const casDir = join(tmpDir, "cas");
|
|
556
|
+
process.env.OCAS_HOME = casDir;
|
|
557
|
+
await mkdir(casDir, { recursive: true });
|
|
558
|
+
process.env.OCAS_HOME = casDir;
|
|
559
|
+
const store = await openStore(casDir);
|
|
560
|
+
const schemas = await registerUwfSchemas(store);
|
|
561
|
+
const detailSchemas = await registerDetailSchemas(store);
|
|
562
|
+
|
|
563
|
+
const workflowHash = await store.cas.put(schemas.workflow, {
|
|
564
|
+
name: "test-wf",
|
|
565
|
+
description: "desc",
|
|
566
|
+
roles: {
|
|
567
|
+
worker: {
|
|
568
|
+
description: "Worker",
|
|
569
|
+
goal: "You are a worker agent.",
|
|
570
|
+
capabilities: [],
|
|
571
|
+
procedure: "Do the work.",
|
|
572
|
+
output: "Summarize the work.",
|
|
573
|
+
meta: "placeholder00" as CasRef,
|
|
574
|
+
},
|
|
575
|
+
},
|
|
576
|
+
conditions: {},
|
|
577
|
+
graph: {},
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
const startHash = await store.cas.put(schemas.startNode, {
|
|
581
|
+
workflow: workflowHash,
|
|
582
|
+
prompt: "Test task",
|
|
583
|
+
});
|
|
584
|
+
|
|
585
|
+
const outputHash = await store.cas.put(schemas.workflow, {
|
|
586
|
+
name: "out",
|
|
587
|
+
description: "",
|
|
588
|
+
roles: {},
|
|
589
|
+
conditions: {},
|
|
590
|
+
graph: {},
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
// Create turn with special markdown characters
|
|
594
|
+
const content = "This has `backticks`, **bold**, *italic*, and [links](http://example.com)";
|
|
595
|
+
const turnHash = await store.cas.put(detailSchemas.turn, {
|
|
596
|
+
index: 0,
|
|
597
|
+
role: "assistant",
|
|
598
|
+
content,
|
|
599
|
+
toolCalls: null,
|
|
600
|
+
reasoning: null,
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
const detailHash = await store.cas.put(detailSchemas.detail, {
|
|
604
|
+
sessionId: "session-1",
|
|
605
|
+
model: "test-model",
|
|
606
|
+
duration: 1000,
|
|
607
|
+
turnCount: 1,
|
|
608
|
+
turns: [turnHash],
|
|
609
|
+
});
|
|
610
|
+
|
|
611
|
+
const stepHash = await store.cas.put(schemas.stepNode, {
|
|
612
|
+
start: startHash,
|
|
613
|
+
prev: null,
|
|
614
|
+
role: "worker",
|
|
615
|
+
output: outputHash,
|
|
616
|
+
detail: detailHash,
|
|
617
|
+
agent: "uwf-test",
|
|
618
|
+
startedAtMs: 1000000000000,
|
|
619
|
+
completedAtMs: 1000000005000,
|
|
620
|
+
assembledPrompt: null,
|
|
621
|
+
});
|
|
622
|
+
|
|
623
|
+
// Read step
|
|
624
|
+
const markdown = await cmdStepRead(tmpDir, stepHash, 4000, false);
|
|
625
|
+
|
|
626
|
+
// Assert content is rendered correctly without corruption
|
|
627
|
+
expect(markdown).toContain("`backticks`");
|
|
628
|
+
expect(markdown).toContain("**bold**");
|
|
629
|
+
expect(markdown).toContain("*italic*");
|
|
630
|
+
expect(markdown).toContain("[links](http://example.com)");
|
|
631
|
+
});
|
|
632
|
+
});
|