@united-workforce/cli 0.6.1 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (167) hide show
  1. package/README.md +120 -5
  2. package/dist/.build-fingerprint +1 -1
  3. package/dist/__tests__/agent-resolution-llm-free.test.js +9 -2
  4. package/dist/__tests__/agent-resolution-llm-free.test.js.map +1 -1
  5. package/dist/__tests__/broker-prompt.test.d.ts +10 -0
  6. package/dist/__tests__/broker-prompt.test.d.ts.map +1 -0
  7. package/dist/__tests__/broker-prompt.test.js +129 -0
  8. package/dist/__tests__/broker-prompt.test.js.map +1 -0
  9. package/dist/__tests__/broker-step-active-turns.test.d.ts +20 -0
  10. package/dist/__tests__/broker-step-active-turns.test.d.ts.map +1 -0
  11. package/dist/__tests__/broker-step-active-turns.test.js +428 -0
  12. package/dist/__tests__/broker-step-active-turns.test.js.map +1 -0
  13. package/dist/__tests__/broker-step-turn-chain-phase2.test.d.ts +13 -0
  14. package/dist/__tests__/broker-step-turn-chain-phase2.test.d.ts.map +1 -0
  15. package/dist/__tests__/broker-step-turn-chain-phase2.test.js +429 -0
  16. package/dist/__tests__/broker-step-turn-chain-phase2.test.js.map +1 -0
  17. package/dist/__tests__/config.test.js +33 -37
  18. package/dist/__tests__/config.test.js.map +1 -1
  19. package/dist/__tests__/e2e-broker-step-suspend.test.d.ts +18 -0
  20. package/dist/__tests__/e2e-broker-step-suspend.test.d.ts.map +1 -0
  21. package/dist/__tests__/e2e-broker-step-suspend.test.js +313 -0
  22. package/dist/__tests__/e2e-broker-step-suspend.test.js.map +1 -0
  23. package/dist/__tests__/e2e-broker-step.test.d.ts +13 -0
  24. package/dist/__tests__/e2e-broker-step.test.d.ts.map +1 -0
  25. package/dist/__tests__/e2e-broker-step.test.js +278 -0
  26. package/dist/__tests__/e2e-broker-step.test.js.map +1 -0
  27. package/dist/__tests__/e2e-mock-agent.test.js +1 -1
  28. package/dist/__tests__/e2e-mock-agent.test.js.map +1 -1
  29. package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.d.ts +28 -0
  30. package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.d.ts.map +1 -0
  31. package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.js +322 -0
  32. package/dist/__tests__/e2e-thread-resume-timeout-suspend.test.js.map +1 -0
  33. package/dist/__tests__/log-tag-validity.test.d.ts +2 -0
  34. package/dist/__tests__/log-tag-validity.test.d.ts.map +1 -0
  35. package/dist/__tests__/log-tag-validity.test.js +110 -0
  36. package/dist/__tests__/log-tag-validity.test.js.map +1 -0
  37. package/dist/__tests__/setup-agent-discovery.test.js +35 -23
  38. package/dist/__tests__/setup-agent-discovery.test.js.map +1 -1
  39. package/dist/__tests__/setup-no-llm.test.js +5 -2
  40. package/dist/__tests__/setup-no-llm.test.js.map +1 -1
  41. package/dist/__tests__/step-ask.test.js +9 -6
  42. package/dist/__tests__/step-ask.test.js.map +1 -1
  43. package/dist/__tests__/step-show-json.test.js +5 -5
  44. package/dist/__tests__/step-show-json.test.js.map +1 -1
  45. package/dist/__tests__/step-show-text.test.d.ts +2 -0
  46. package/dist/__tests__/step-show-text.test.d.ts.map +1 -0
  47. package/dist/__tests__/step-show-text.test.js +192 -0
  48. package/dist/__tests__/step-show-text.test.js.map +1 -0
  49. package/dist/__tests__/step-turns-cli-subprocess.test.d.ts +21 -0
  50. package/dist/__tests__/step-turns-cli-subprocess.test.d.ts.map +1 -0
  51. package/dist/__tests__/step-turns-cli-subprocess.test.js +356 -0
  52. package/dist/__tests__/step-turns-cli-subprocess.test.js.map +1 -0
  53. package/dist/__tests__/step-turns-panorama-phase3.test.d.ts +21 -0
  54. package/dist/__tests__/step-turns-panorama-phase3.test.d.ts.map +1 -0
  55. package/dist/__tests__/step-turns-panorama-phase3.test.js +476 -0
  56. package/dist/__tests__/step-turns-panorama-phase3.test.js.map +1 -0
  57. package/dist/__tests__/step-turns.test.d.ts +24 -0
  58. package/dist/__tests__/step-turns.test.d.ts.map +1 -0
  59. package/dist/__tests__/step-turns.test.js +646 -0
  60. package/dist/__tests__/step-turns.test.js.map +1 -0
  61. package/dist/__tests__/store-turn-chain.test.d.ts +2 -0
  62. package/dist/__tests__/store-turn-chain.test.d.ts.map +1 -0
  63. package/dist/__tests__/store-turn-chain.test.js +341 -0
  64. package/dist/__tests__/store-turn-chain.test.js.map +1 -0
  65. package/dist/__tests__/thread-agent-failure-suspended.test.js +3 -3
  66. package/dist/__tests__/thread-agent-failure-suspended.test.js.map +1 -1
  67. package/dist/__tests__/thread-list-limit-offset.test.d.ts +24 -0
  68. package/dist/__tests__/thread-list-limit-offset.test.d.ts.map +1 -0
  69. package/dist/__tests__/thread-list-limit-offset.test.js +254 -0
  70. package/dist/__tests__/thread-list-limit-offset.test.js.map +1 -0
  71. package/dist/__tests__/thread-list-template-ms-date.test.js +7 -2
  72. package/dist/__tests__/thread-list-template-ms-date.test.js.map +1 -1
  73. package/dist/__tests__/thread-poke.test.js +6 -6
  74. package/dist/__tests__/thread-poke.test.js.map +1 -1
  75. package/dist/__tests__/thread-resume.test.js +2 -2
  76. package/dist/__tests__/thread-resume.test.js.map +1 -1
  77. package/dist/__tests__/thread-suspend-step.test.js +1 -1
  78. package/dist/__tests__/thread-suspend-step.test.js.map +1 -1
  79. package/dist/__tests__/thread.test.js +28 -14
  80. package/dist/__tests__/thread.test.js.map +1 -1
  81. package/dist/cli.js +910 -344
  82. package/dist/cli.js.map +1 -1
  83. package/dist/commands/broker-step.d.ts +117 -0
  84. package/dist/commands/broker-step.d.ts.map +1 -0
  85. package/dist/commands/broker-step.js +654 -0
  86. package/dist/commands/broker-step.js.map +1 -0
  87. package/dist/commands/config.d.ts.map +1 -1
  88. package/dist/commands/config.js +2 -23
  89. package/dist/commands/config.js.map +1 -1
  90. package/dist/commands/prompt.d.ts.map +1 -1
  91. package/dist/commands/prompt.js +43 -51
  92. package/dist/commands/prompt.js.map +1 -1
  93. package/dist/commands/setup.d.ts +6 -4
  94. package/dist/commands/setup.d.ts.map +1 -1
  95. package/dist/commands/setup.js +24 -27
  96. package/dist/commands/setup.js.map +1 -1
  97. package/dist/commands/step.d.ts +54 -6
  98. package/dist/commands/step.d.ts.map +1 -1
  99. package/dist/commands/step.js +484 -134
  100. package/dist/commands/step.js.map +1 -1
  101. package/dist/commands/thread.d.ts +4 -0
  102. package/dist/commands/thread.d.ts.map +1 -1
  103. package/dist/commands/thread.js +77 -151
  104. package/dist/commands/thread.js.map +1 -1
  105. package/dist/output-mappers.d.ts +8 -0
  106. package/dist/output-mappers.d.ts.map +1 -1
  107. package/dist/output-mappers.js +72 -18
  108. package/dist/output-mappers.js.map +1 -1
  109. package/dist/schemas.d.ts +3 -0
  110. package/dist/schemas.d.ts.map +1 -1
  111. package/dist/schemas.js +17 -3
  112. package/dist/schemas.js.map +1 -1
  113. package/dist/store.d.ts +147 -1
  114. package/dist/store.d.ts.map +1 -1
  115. package/dist/store.js +254 -1
  116. package/dist/store.js.map +1 -1
  117. package/dist/text-renderers.d.ts.map +1 -1
  118. package/dist/text-renderers.js +27 -2
  119. package/dist/text-renderers.js.map +1 -1
  120. package/package.json +7 -5
  121. package/src/__tests__/agent-resolution-llm-free.test.ts +14 -2
  122. package/src/__tests__/broker-prompt.test.ts +142 -0
  123. package/src/__tests__/broker-step-active-turns.test.ts +509 -0
  124. package/src/__tests__/broker-step-turn-chain-phase2.test.ts +525 -0
  125. package/src/__tests__/config.test.ts +35 -39
  126. package/src/__tests__/e2e-broker-step-suspend.test.ts +351 -0
  127. package/src/__tests__/e2e-broker-step.test.ts +320 -0
  128. package/src/__tests__/e2e-mock-agent.test.ts +1 -1
  129. package/src/__tests__/e2e-thread-resume-timeout-suspend.test.ts +360 -0
  130. package/src/__tests__/log-tag-validity.test.ts +124 -0
  131. package/src/__tests__/setup-agent-discovery.test.ts +35 -23
  132. package/src/__tests__/setup-no-llm.test.ts +5 -2
  133. package/src/__tests__/step-ask.test.ts +9 -6
  134. package/src/__tests__/step-show-json.test.ts +5 -5
  135. package/src/__tests__/step-show-text.test.ts +236 -0
  136. package/src/__tests__/step-turns-cli-subprocess.test.ts +411 -0
  137. package/src/__tests__/step-turns-panorama-phase3.test.ts +579 -0
  138. package/src/__tests__/step-turns.test.ts +734 -0
  139. package/src/__tests__/store-turn-chain.test.ts +386 -0
  140. package/src/__tests__/thread-agent-failure-suspended.test.ts +3 -3
  141. package/src/__tests__/thread-list-limit-offset.test.ts +305 -0
  142. package/src/__tests__/thread-list-template-ms-date.test.ts +7 -2
  143. package/src/__tests__/thread-poke.test.ts +6 -6
  144. package/src/__tests__/thread-resume.test.ts +2 -2
  145. package/src/__tests__/thread-suspend-step.test.ts +1 -1
  146. package/src/__tests__/thread.test.ts +29 -15
  147. package/src/cli.ts +1056 -483
  148. package/src/commands/broker-step.ts +913 -0
  149. package/src/commands/config.ts +2 -24
  150. package/src/commands/prompt.ts +43 -51
  151. package/src/commands/setup.ts +25 -29
  152. package/src/commands/step.ts +645 -176
  153. package/src/commands/thread.ts +87 -192
  154. package/src/output-mappers.ts +99 -21
  155. package/src/schemas.ts +32 -2
  156. package/src/store.ts +297 -2
  157. package/src/text-renderers.ts +35 -2
  158. package/dist/__tests__/adapter-json-roundtrip.test.d.ts +0 -2
  159. package/dist/__tests__/adapter-json-roundtrip.test.d.ts.map +0 -1
  160. package/dist/__tests__/adapter-json-roundtrip.test.js +0 -160
  161. package/dist/__tests__/adapter-json-roundtrip.test.js.map +0 -1
  162. package/dist/__tests__/spawn-agent-json.test.d.ts +0 -2
  163. package/dist/__tests__/spawn-agent-json.test.d.ts.map +0 -1
  164. package/dist/__tests__/spawn-agent-json.test.js +0 -79
  165. package/dist/__tests__/spawn-agent-json.test.js.map +0 -1
  166. package/src/__tests__/adapter-json-roundtrip.test.ts +0 -193
  167. package/src/__tests__/spawn-agent-json.test.ts +0 -100
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@united-workforce/cli",
3
- "version": "0.6.1",
3
+ "version": "0.8.1",
4
4
  "files": [
5
5
  "src",
6
6
  "dist",
@@ -14,13 +14,15 @@
14
14
  "dependencies": {
15
15
  "@ocas/core": "^0.5.0",
16
16
  "@ocas/fs": "^0.4.1",
17
- "commander": "^14.0.3",
17
+ "@ocas/cli-kit": "^0.2.1",
18
18
  "dotenv": "^16.6.1",
19
19
  "liquidjs": "^10.27.0",
20
20
  "yaml": "^2.8.4",
21
- "@united-workforce/util": "^0.2.0",
22
- "@united-workforce/util-agent": "^0.2.1",
23
- "@united-workforce/protocol": "^0.3.0"
21
+ "zod": "^4.1.12",
22
+ "@united-workforce/broker": "^0.3.0",
23
+ "@united-workforce/util": "^0.3.0",
24
+ "@united-workforce/protocol": "^0.5.0",
25
+ "@united-workforce/util-agent": "^0.4.0"
24
26
  },
25
27
  "publishConfig": {
26
28
  "access": "public"
@@ -14,12 +14,14 @@ describe("agent resolution works without LLM fields in config.yaml (issue #143)"
14
14
  tempDir = mkdtempSync(join(tmpdir(), "uwf-engine-cfg-"));
15
15
  writeFileSync(
16
16
  join(tempDir, "config.yaml"),
17
- "agents:\n hermes: { command: uwf-hermes, args: [] }\ndefaultAgent: hermes\n",
17
+ "agents:\n hermes: { host: 'http://127.0.0.1:7900', gateway: hermes }\ndefaultAgent: hermes\n",
18
18
  "utf8",
19
19
  );
20
20
  const cfg = await loadWorkflowConfig(tempDir);
21
21
  expect(cfg.defaultAgent).toBe("hermes");
22
22
  expect(cfg.agents.hermes).toBeDefined();
23
+ expect(cfg.agents.hermes.host).toBe("http://127.0.0.1:7900");
24
+ expect(cfg.agents.hermes.gateway).toBe("hermes");
23
25
  expect(cfg.agentOverrides).toBeNull();
24
26
  });
25
27
 
@@ -27,7 +29,7 @@ describe("agent resolution works without LLM fields in config.yaml (issue #143)"
27
29
  tempDir = mkdtempSync(join(tmpdir(), "uwf-engine-cfg-"));
28
30
  writeFileSync(
29
31
  join(tempDir, "config.yaml"),
30
- "providers:\n openai: { baseUrl: x, apiKey: y }\nmodels:\n default: { provider: openai, name: gpt-4o }\ndefaultModel: default\nagents:\n hermes: { command: uwf-hermes, args: [] }\ndefaultAgent: hermes\n",
32
+ "providers:\n openai: { baseUrl: x, apiKey: y }\nmodels:\n default: { provider: openai, name: gpt-4o }\ndefaultModel: default\nagents:\n hermes: { host: 'http://127.0.0.1:7900', gateway: hermes }\ndefaultAgent: hermes\n",
31
33
  "utf8",
32
34
  );
33
35
  const cfg = (await loadWorkflowConfig(tempDir)) as Record<string, unknown>;
@@ -36,4 +38,14 @@ describe("agent resolution works without LLM fields in config.yaml (issue #143)"
36
38
  expect(cfg.models).toBeUndefined();
37
39
  expect(cfg.defaultModel).toBeUndefined();
38
40
  });
41
+
42
+ test("loadWorkflowConfig rejects legacy {command, args} agent shape", async () => {
43
+ tempDir = mkdtempSync(join(tmpdir(), "uwf-engine-cfg-"));
44
+ writeFileSync(
45
+ join(tempDir, "config.yaml"),
46
+ "agents:\n hermes: { command: uwf-hermes, args: [] }\ndefaultAgent: hermes\n",
47
+ "utf8",
48
+ );
49
+ await expect(loadWorkflowConfig(tempDir)).rejects.toThrow(/legacy \{command, args\} fields/);
50
+ });
39
51
  });
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Unit tests for `assembleBrokerPrompt` (#387).
3
+ *
4
+ * Verifies the broker path assembles the same five-part prompt the legacy
5
+ * spawned-agent path produced: output-format instruction, thread progress,
6
+ * role prompt (goal/procedure/output), task prompt, and the
7
+ * continuation/edge-prompt context (branching on first visit vs re-entry).
8
+ */
9
+
10
+ import type { CasRef, StepContext, ThreadId, WorkflowPayload } from "@united-workforce/protocol";
11
+ import { describe, expect, test } from "vitest";
12
+ import { assembleBrokerPrompt } from "../commands/broker-step.js";
13
+
14
+ const THREAD_ID = "06FCBROKERPROMPTTEST000001" as ThreadId;
15
+
16
+ const OUTPUT_FORMAT_INSTRUCTION = "## Deliverable Format\n\nemit YAML frontmatter";
17
+
18
+ function buildWorkflow(): WorkflowPayload {
19
+ return {
20
+ version: 1,
21
+ name: "review-flow",
22
+ description: "two-role review flow",
23
+ roles: {
24
+ developer: {
25
+ description: "writes code",
26
+ goal: "implement the requested behavior",
27
+ capabilities: ["coding"],
28
+ procedure: "follow the spec and write tests",
29
+ output: "a patch plus a short summary",
30
+ frontmatter: "schema_developer" as CasRef,
31
+ },
32
+ reviewer: {
33
+ description: "reviews code",
34
+ goal: "review the implementation",
35
+ capabilities: [],
36
+ procedure: "check the diff carefully",
37
+ output: "approve or reject",
38
+ frontmatter: "schema_reviewer" as CasRef,
39
+ },
40
+ },
41
+ graph: {},
42
+ };
43
+ }
44
+
45
+ function stepContext(role: string, content: string | null, output: unknown): StepContext {
46
+ return {
47
+ role,
48
+ output,
49
+ detail: "detail_ref" as CasRef,
50
+ agent: "test-agent",
51
+ edgePrompt: "",
52
+ startedAtMs: 0,
53
+ completedAtMs: 1,
54
+ cwd: "",
55
+ assembledPrompt: null,
56
+ usage: null,
57
+ previousAttempts: null,
58
+ content,
59
+ };
60
+ }
61
+
62
+ describe("assembleBrokerPrompt", () => {
63
+ test("first visit with no prior steps embeds role prompt, task, and edge prompt", () => {
64
+ const prompt = assembleBrokerPrompt({
65
+ workflow: buildWorkflow(),
66
+ role: "developer",
67
+ threadId: THREAD_ID,
68
+ startPrompt: "Build the login form",
69
+ steps: [],
70
+ edgePrompt: "Implement the behavior defined in the spec files",
71
+ outputFormatInstruction: OUTPUT_FORMAT_INSTRUCTION,
72
+ });
73
+
74
+ // 1. output-format instruction
75
+ expect(prompt).toContain("## Deliverable Format");
76
+ // 2. thread progress
77
+ expect(prompt).toContain("## Thread Progress");
78
+ expect(prompt).toContain("This is the first step of the thread");
79
+ // 3. role prompt (goal + procedure + output)
80
+ expect(prompt).toContain("## Goal");
81
+ expect(prompt).toContain("implement the requested behavior");
82
+ expect(prompt).toContain("## Procedure");
83
+ expect(prompt).toContain("follow the spec and write tests");
84
+ expect(prompt).toContain("## Output");
85
+ expect(prompt).toContain("a patch plus a short summary");
86
+ // 4. task prompt
87
+ expect(prompt).toContain("## Task");
88
+ expect(prompt).toContain("Build the login form");
89
+ // 5. edge prompt (no prior steps → "Current Instruction")
90
+ expect(prompt).toContain("## Current Instruction");
91
+ expect(prompt).toContain("Implement the behavior defined in the spec files");
92
+ });
93
+
94
+ test("first visit with prior steps includes step content as continuation context", () => {
95
+ const steps: StepContext[] = [
96
+ stepContext("planner", "Here is the detailed plan for the feature.", { $status: "done" }),
97
+ ];
98
+
99
+ const prompt = assembleBrokerPrompt({
100
+ workflow: buildWorkflow(),
101
+ role: "developer",
102
+ threadId: THREAD_ID,
103
+ startPrompt: "Build the login form",
104
+ steps,
105
+ edgePrompt: "Implement the plan",
106
+ outputFormatInstruction: OUTPUT_FORMAT_INSTRUCTION,
107
+ });
108
+
109
+ // Developer has not spoken yet → first visit, prior steps shown WITH content.
110
+ expect(prompt).toContain("## What Happened Since Your Last Turn");
111
+ expect(prompt).toContain("Here is the detailed plan for the feature.");
112
+ expect(prompt).toContain("## Moderator Instruction");
113
+ expect(prompt).toContain("Implement the plan");
114
+ // Thread progress reflects the prior step.
115
+ expect(prompt).toContain("Thread step 2");
116
+ });
117
+
118
+ test("re-entry shows only steps since last visit (meta-only continuation)", () => {
119
+ const steps: StepContext[] = [
120
+ stepContext("developer", "My first implementation attempt.", { $status: "done" }),
121
+ stepContext("reviewer", "Please fix the validation logic.", { $status: "reject" }),
122
+ ];
123
+
124
+ const prompt = assembleBrokerPrompt({
125
+ workflow: buildWorkflow(),
126
+ role: "developer",
127
+ threadId: THREAD_ID,
128
+ startPrompt: "Build the login form",
129
+ steps,
130
+ edgePrompt: "Address the reviewer feedback",
131
+ outputFormatInstruction: OUTPUT_FORMAT_INSTRUCTION,
132
+ });
133
+
134
+ // Re-entry: continuation lists the reviewer step since the last developer turn.
135
+ expect(prompt).toContain("## What Happened Since Your Last Turn");
136
+ expect(prompt).toContain("reviewer");
137
+ expect(prompt).toContain("## Moderator Instruction");
138
+ expect(prompt).toContain("Address the reviewer feedback");
139
+ // Meta-only re-entry omits raw step content from before the last visit.
140
+ expect(prompt).not.toContain("My first implementation attempt.");
141
+ });
142
+ });