@nac3/forge-cli 0.2.0-alpha.59z.121 → 0.2.0-alpha.59z.158

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 (161) hide show
  1. package/dist/agents/bridge.d.ts +69 -0
  2. package/dist/agents/bridge.d.ts.map +1 -0
  3. package/dist/agents/bridge.js +295 -0
  4. package/dist/agents/bridge.js.map +1 -0
  5. package/dist/agents/cli_real.d.ts +38 -0
  6. package/dist/agents/cli_real.d.ts.map +1 -0
  7. package/dist/agents/cli_real.js +46 -0
  8. package/dist/agents/cli_real.js.map +1 -0
  9. package/dist/agents/config_schema.d.ts +1 -1
  10. package/dist/agents/config_schema.d.ts.map +1 -1
  11. package/dist/agents/config_schema.js +16 -0
  12. package/dist/agents/config_schema.js.map +1 -1
  13. package/dist/agents/defaults.d.ts.map +1 -1
  14. package/dist/agents/defaults.js.map +1 -1
  15. package/dist/agents/delegate.d.ts +36 -0
  16. package/dist/agents/delegate.d.ts.map +1 -0
  17. package/dist/agents/delegate.js +68 -0
  18. package/dist/agents/delegate.js.map +1 -0
  19. package/dist/agents/iterative_step.d.ts +95 -0
  20. package/dist/agents/iterative_step.d.ts.map +1 -0
  21. package/dist/agents/iterative_step.js +249 -0
  22. package/dist/agents/iterative_step.js.map +1 -0
  23. package/dist/agents/llm_step.d.ts +50 -0
  24. package/dist/agents/llm_step.d.ts.map +1 -0
  25. package/dist/agents/llm_step.js +28 -0
  26. package/dist/agents/llm_step.js.map +1 -0
  27. package/dist/agents/real_step_factory.d.ts +95 -0
  28. package/dist/agents/real_step_factory.d.ts.map +1 -0
  29. package/dist/agents/real_step_factory.js +51 -0
  30. package/dist/agents/real_step_factory.js.map +1 -0
  31. package/dist/agents/runner.d.ts +14 -0
  32. package/dist/agents/runner.d.ts.map +1 -1
  33. package/dist/agents/runner.js +10 -1
  34. package/dist/agents/runner.js.map +1 -1
  35. package/dist/agents/runtime.d.ts +115 -0
  36. package/dist/agents/runtime.d.ts.map +1 -0
  37. package/dist/agents/runtime.js +429 -0
  38. package/dist/agents/runtime.js.map +1 -0
  39. package/dist/agents/system_prompt.d.ts +36 -0
  40. package/dist/agents/system_prompt.d.ts.map +1 -0
  41. package/dist/agents/system_prompt.js +101 -0
  42. package/dist/agents/system_prompt.js.map +1 -0
  43. package/dist/agents/types.d.ts +12 -1
  44. package/dist/agents/types.d.ts.map +1 -1
  45. package/dist/agents/types.js.map +1 -1
  46. package/dist/bin/yf.d.ts.map +1 -1
  47. package/dist/bin/yf.js +9 -0
  48. package/dist/bin/yf.js.map +1 -1
  49. package/dist/chat/claude_cli.d.ts +42 -0
  50. package/dist/chat/claude_cli.d.ts.map +1 -0
  51. package/dist/chat/claude_cli.js +299 -0
  52. package/dist/chat/claude_cli.js.map +1 -0
  53. package/dist/chat/graph_snapshot.d.ts +38 -0
  54. package/dist/chat/graph_snapshot.d.ts.map +1 -0
  55. package/dist/chat/graph_snapshot.js +159 -0
  56. package/dist/chat/graph_snapshot.js.map +1 -0
  57. package/dist/chat/ingest_session.d.ts +24 -4
  58. package/dist/chat/ingest_session.d.ts.map +1 -1
  59. package/dist/chat/ingest_session.js +139 -4
  60. package/dist/chat/ingest_session.js.map +1 -1
  61. package/dist/chat/panel.d.ts.map +1 -1
  62. package/dist/chat/panel.js +1358 -0
  63. package/dist/chat/panel.js.map +1 -1
  64. package/dist/chat/server.d.ts +21 -0
  65. package/dist/chat/server.d.ts.map +1 -1
  66. package/dist/chat/server.js +904 -4
  67. package/dist/chat/server.js.map +1 -1
  68. package/dist/chat/tools/nac3_invoke.d.ts +5 -0
  69. package/dist/chat/tools/nac3_invoke.d.ts.map +1 -1
  70. package/dist/chat/tools/nac3_invoke.js +1 -0
  71. package/dist/chat/tools/nac3_invoke.js.map +1 -1
  72. package/dist/chat/tools.d.ts.map +1 -1
  73. package/dist/chat/tools.js +12 -0
  74. package/dist/chat/tools.js.map +1 -1
  75. package/dist/commands/agent.d.ts +12 -1
  76. package/dist/commands/agent.d.ts.map +1 -1
  77. package/dist/commands/agent.js +92 -1
  78. package/dist/commands/agent.js.map +1 -1
  79. package/dist/commands/chat.d.ts +10 -0
  80. package/dist/commands/chat.d.ts.map +1 -1
  81. package/dist/commands/chat.js +12 -1
  82. package/dist/commands/chat.js.map +1 -1
  83. package/dist/commands/director.d.ts +37 -0
  84. package/dist/commands/director.d.ts.map +1 -0
  85. package/dist/commands/director.js +290 -0
  86. package/dist/commands/director.js.map +1 -0
  87. package/dist/commands/keys_setup.d.ts +1 -0
  88. package/dist/commands/keys_setup.d.ts.map +1 -1
  89. package/dist/commands/keys_setup.js +61 -11
  90. package/dist/commands/keys_setup.js.map +1 -1
  91. package/dist/core/pilot_setup.d.ts +14 -1
  92. package/dist/core/pilot_setup.d.ts.map +1 -1
  93. package/dist/core/pilot_setup.js +62 -1
  94. package/dist/core/pilot_setup.js.map +1 -1
  95. package/dist/core/provider_keys.d.ts.map +1 -1
  96. package/dist/core/provider_keys.js +12 -5
  97. package/dist/core/provider_keys.js.map +1 -1
  98. package/dist/design/yujin_design_resolver.d.ts +77 -0
  99. package/dist/design/yujin_design_resolver.d.ts.map +1 -0
  100. package/dist/design/yujin_design_resolver.js +113 -0
  101. package/dist/design/yujin_design_resolver.js.map +1 -0
  102. package/dist/docs/doctrine/default-design-system.md +120 -0
  103. package/dist/docs/doctrine/language-sovereignty.md +143 -0
  104. package/dist/docs/doctrine/testing-policy.md +211 -0
  105. package/dist/nac3/approval_queue.d.ts +8 -0
  106. package/dist/nac3/approval_queue.d.ts.map +1 -1
  107. package/dist/nac3/approval_queue.js.map +1 -1
  108. package/dist/nac3/internal_manifest.d.ts.map +1 -1
  109. package/dist/nac3/internal_manifest.js +178 -0
  110. package/dist/nac3/internal_manifest.js.map +1 -1
  111. package/dist/office/excel.d.ts +22 -0
  112. package/dist/office/excel.d.ts.map +1 -1
  113. package/dist/office/excel.js +82 -0
  114. package/dist/office/excel.js.map +1 -1
  115. package/dist/qa/brain_matrix/fixtures/scenario_a11y_focus_after_open.json +22 -0
  116. package/dist/qa/brain_matrix/fixtures/scenario_a11y_label_unlabeled_button.json +26 -0
  117. package/dist/qa/brain_matrix/fixtures/scenario_agent_director_consults_workflow_before_dispatch.json +42 -0
  118. package/dist/qa/brain_matrix/fixtures/scenario_analyst_extracts_then_returns.json +28 -0
  119. package/dist/qa/brain_matrix/fixtures/scenario_coder_consults_nac_spec_before_writing.json +28 -0
  120. package/dist/qa/brain_matrix/fixtures/scenario_default_design_system_override_shadcn.json +45 -0
  121. package/dist/qa/brain_matrix/fixtures/scenario_default_design_system_use_card_template.json +44 -0
  122. package/dist/qa/brain_matrix/fixtures/scenario_director_delegates_to_analyst.json +26 -0
  123. package/dist/qa/brain_matrix/fixtures/scenario_director_no_self_delegation.json +20 -0
  124. package/dist/qa/brain_matrix/fixtures/scenario_director_terminal_done_marker.json +19 -0
  125. package/dist/qa/brain_matrix/fixtures/scenario_doctrine_discover_default_design_system.json +50 -0
  126. package/dist/qa/brain_matrix/fixtures/scenario_doctrine_discover_language_sovereignty.json +53 -0
  127. package/dist/qa/brain_matrix/fixtures/scenario_doctrine_discover_testing_policy.json +55 -0
  128. package/dist/qa/brain_matrix/fixtures/scenario_language_sovereignty_not_conducive_spa_python.json +61 -0
  129. package/dist/qa/brain_matrix/fixtures/scenario_language_sovereignty_user_picks_python.json +48 -0
  130. package/dist/qa/brain_matrix/fixtures/scenario_mcp_invoke_destructive_pauses_for_r8.json +42 -0
  131. package/dist/qa/brain_matrix/fixtures/scenario_mcp_invoke_happy_path_writes_pizarron.json +76 -0
  132. package/dist/qa/brain_matrix/fixtures/scenario_mcp_invoke_network_timeout_graceful.json +41 -0
  133. package/dist/qa/brain_matrix/fixtures/scenario_no_hardcoded_color_use_token.json +47 -0
  134. package/dist/qa/brain_matrix/fixtures/scenario_office_excel_update_cell_picks_right_verb.json +26 -0
  135. package/dist/qa/brain_matrix/fixtures/scenario_scaffolder_destructive_pauses_for_approval.json +23 -0
  136. package/dist/qa/brain_matrix/fixtures/scenario_sumie_icon_pick_from_catalog.json +56 -0
  137. package/dist/qa/brain_matrix/fixtures/scenario_tester_uses_shell_exec_only.json +27 -0
  138. package/dist/version.d.ts +1 -1
  139. package/dist/version.js +1 -1
  140. package/dist/workflow/graph.d.ts +59 -0
  141. package/dist/workflow/graph.d.ts.map +1 -0
  142. package/dist/workflow/graph.js +137 -0
  143. package/dist/workflow/graph.js.map +1 -0
  144. package/dist/workflow/state.d.ts +34 -0
  145. package/dist/workflow/state.d.ts.map +1 -1
  146. package/dist/workflow/state.js.map +1 -1
  147. package/docs/doctrine/default-design-system.md +120 -0
  148. package/docs/doctrine/language-sovereignty.md +143 -0
  149. package/docs/doctrine/testing-policy.md +211 -0
  150. package/package.json +102 -100
  151. package/src/i18n/catalogs/ar.json +20 -1
  152. package/src/i18n/catalogs/de.json +20 -1
  153. package/src/i18n/catalogs/en.json +20 -21
  154. package/src/i18n/catalogs/es.json +20 -21
  155. package/src/i18n/catalogs/fr.json +20 -1
  156. package/src/i18n/catalogs/hi.json +20 -1
  157. package/src/i18n/catalogs/it.json +20 -1
  158. package/src/i18n/catalogs/ja.json +20 -1
  159. package/src/i18n/catalogs/pt.json +20 -1
  160. package/src/i18n/catalogs/zh.json +20 -1
  161. package/templates/sumi-context.template.md +57 -0
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Agent-to-agent delegation helper (Director sprint slice 15d).
3
+ *
4
+ * Encapsulates: bridge.sendMessage (with cap + loop detector) +
5
+ * runtime.dispatchAgent (with status gate) + result projection.
6
+ *
7
+ * The iterative step calls this when the LLM invokes
8
+ * `yujin.agent.delegate`. The chat server / CLI wires the
9
+ * runtime + bridge root before invoking the step.
10
+ *
11
+ * Graceful: every failure (ACL denial, paused target, runtime
12
+ * unreachable) returns `{ok:false, error}` so the LLM can
13
+ * surface it to the user instead of crashing the run.
14
+ *
15
+ * ASCII-only.
16
+ */
17
+ import { sendMessage, BridgeError } from './bridge.js';
18
+ export async function delegateToAgent(opts) {
19
+ /* Step 1: enqueue via the bridge so the cap + loop detector
20
+ * + ACL check fire BEFORE we touch the runtime. */
21
+ try {
22
+ await sendMessage({
23
+ from_slug: opts.from_slug,
24
+ to_slug: opts.to_slug,
25
+ payload: opts.payload,
26
+ tokens_used: opts.tokens_used,
27
+ }, { root: opts.root });
28
+ }
29
+ catch (err) {
30
+ return {
31
+ ok: false,
32
+ target_slug: opts.to_slug,
33
+ error: err instanceof BridgeError
34
+ ? (err.message + ' (code=' + err.code + ')')
35
+ : (err instanceof Error ? err.message : String(err)),
36
+ };
37
+ }
38
+ /* Step 2: fire-and-forget when no runtime provided. */
39
+ if (!opts.runtime) {
40
+ return { ok: true, target_slug: opts.to_slug };
41
+ }
42
+ /* Step 3: dispatch the target via runtime. The runtime enforces
43
+ * status gates (paused / deleted / unknown -> failed run). */
44
+ const triggerReason = 'bridge: from=' + opts.from_slug;
45
+ try {
46
+ const run = await opts.runtime.dispatchAgent(opts.to_slug, triggerReason);
47
+ return {
48
+ ok: run.status === 'succeeded',
49
+ target_slug: opts.to_slug,
50
+ trigger_reason: triggerReason,
51
+ run_status: run.status,
52
+ last_reply: run.last_reply_summary,
53
+ tokens_in: run.tokens_in,
54
+ tokens_out: run.tokens_out,
55
+ error: run.status === 'succeeded'
56
+ ? undefined
57
+ : ('target run status=' + run.status + (run.kill_reason ? ' (' + run.kill_reason + ')' : '')),
58
+ };
59
+ }
60
+ catch (err) {
61
+ return {
62
+ ok: false,
63
+ target_slug: opts.to_slug,
64
+ error: err instanceof Error ? err.message : String(err),
65
+ };
66
+ }
67
+ }
68
+ //# sourceMappingURL=delegate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delegate.js","sourceRoot":"","sources":["../../src/agents/delegate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAsCvD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAkB;IACtD;uDACmD;IACnD,IAAI,CAAC;QACH,MAAM,WAAW,CACf;YACE,SAAS,EAAI,IAAI,CAAC,SAAS;YAC3B,OAAO,EAAM,IAAI,CAAC,OAAO;YACzB,OAAO,EAAM,IAAI,CAAC,OAAO;YACzB,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,EACD,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CACpB,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAW,KAAK;YAClB,WAAW,EAAE,IAAI,CAAC,OAAO;YACzB,KAAK,EAAQ,GAAG,YAAY,WAAW;gBACrC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,GAAG,SAAS,GAAG,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC;gBAC5C,CAAC,CAAC,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;SACvD,CAAC;IACJ,CAAC;IAED,uDAAuD;IACvD,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QAClB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;IACjD,CAAC;IAED;kEAC8D;IAC9D,MAAM,aAAa,GAAG,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC;IACvD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;QAC1E,OAAO;YACL,EAAE,EAAc,GAAG,CAAC,MAAM,KAAK,WAAW;YAC1C,WAAW,EAAK,IAAI,CAAC,OAAO;YAC5B,cAAc,EAAE,aAAa;YAC7B,UAAU,EAAM,GAAG,CAAC,MAAM;YAC1B,UAAU,EAAM,GAAG,CAAC,kBAAkB;YACtC,SAAS,EAAO,GAAG,CAAC,SAAS;YAC7B,UAAU,EAAM,GAAG,CAAC,UAAU;YAC9B,KAAK,EAAW,GAAG,CAAC,MAAM,KAAK,WAAW;gBACxC,CAAC,CAAC,SAAS;gBACX,CAAC,CAAC,CAAC,oBAAoB,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,WAAW,GAAG,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SAChG,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAW,KAAK;YAClB,WAAW,EAAE,IAAI,CAAC,OAAO;YACzB,KAAK,EAAQ,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;SAC9D,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,95 @@
1
+ import type { AgentDefinition } from './types.js';
2
+ import type { StepFn } from './runner.js';
3
+ interface MinimalClaude {
4
+ chat(req: {
5
+ system?: string;
6
+ messages: Array<{
7
+ role: 'user' | 'assistant' | 'system';
8
+ content: string;
9
+ }>;
10
+ tools?: Array<{
11
+ name: string;
12
+ description?: string;
13
+ input_schema?: Record<string, unknown>;
14
+ }>;
15
+ runTool?: (name: string, input: Record<string, unknown>) => Promise<unknown>;
16
+ maxTokens?: number;
17
+ }): Promise<{
18
+ text: string;
19
+ tokensIn: number;
20
+ tokensOut: number;
21
+ model?: string;
22
+ toolRounds: Array<{
23
+ tool: string;
24
+ input: Record<string, unknown>;
25
+ result: unknown;
26
+ is_error?: boolean;
27
+ tool_use_id: string;
28
+ }>;
29
+ }>;
30
+ }
31
+ type RunNac3InvokeFn = (rawArgs: {
32
+ verb_id: string;
33
+ args?: Record<string, unknown>;
34
+ }, ctx: unknown, opts: {
35
+ legacyRun: unknown;
36
+ panelSessionId?: string;
37
+ llmTurnId?: string;
38
+ agentSlug?: string;
39
+ }) => Promise<{
40
+ tool: string;
41
+ is_error?: boolean;
42
+ result: unknown;
43
+ }>;
44
+ export type DelegateFn = (to_slug: string, payload: string) => Promise<{
45
+ ok: boolean;
46
+ target_slug: string;
47
+ run_status?: string;
48
+ last_reply?: string;
49
+ tokens_in?: number;
50
+ tokens_out?: number;
51
+ error?: string;
52
+ }>;
53
+ export interface BuildIterativeStepOpts {
54
+ def: AgentDefinition;
55
+ claude: MinimalClaude;
56
+ /** The dispatcher that resolves a verb_id to a result. The
57
+ * step gives it the ctx + opts the chat server uses; for
58
+ * tests, inject a mock. */
59
+ runNac3Invoke: RunNac3InvokeFn;
60
+ project_root: string;
61
+ project_name: string;
62
+ forge_version: string;
63
+ /** Becomes the initial user message of the conversation. */
64
+ trigger_reason: string;
65
+ /** Pre-rendered, role-filtered graph snapshot (slice 11). */
66
+ graph_snapshot_section?: string;
67
+ workflow_section?: string;
68
+ /** Max tokens per Claude turn. Defaults to 2048. */
69
+ max_tokens?: number;
70
+ /** Optional ctx pass-through for runNac3Invoke (project root /
71
+ * panel session id etc). The dispatcher needs SOMETHING; an
72
+ * empty object satisfies tests. */
73
+ nac3_ctx?: unknown;
74
+ /** Legacy handler for runNac3Invoke. Tests inject a stub; the
75
+ * chat server wires it to runForgeTool. */
76
+ legacy_run?: unknown;
77
+ /** Director sprint slice 15d -- when present, intercepts the
78
+ * `yujin.agent.delegate` verb BEFORE the runNac3Invoke gate.
79
+ * Used by the chat server / CLI to wire bridge.sendMessage +
80
+ * runtime.dispatchAgent into one call. */
81
+ delegate?: DelegateFn;
82
+ /** Director closure pendiente 4 -- conversation persistence.
83
+ * When `conversation_id` is set, the step loads any existing
84
+ * history from <conversation_root>/<id>.json on construction
85
+ * + atomically saves after each step. Across runtime restarts
86
+ * the LLM continues with the prior context.
87
+ *
88
+ * conversation_root defaults to ~/.yujin-forge/agents/by-slug/
89
+ * <slug>/conversations -- co-located with the runs/ store. */
90
+ conversation_id?: string;
91
+ conversation_root?: string;
92
+ }
93
+ export declare function buildIterativeLlmStep(opts: BuildIterativeStepOpts): StepFn;
94
+ export {};
95
+ //# sourceMappingURL=iterative_step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iterative_step.d.ts","sourceRoot":"","sources":["../../src/agents/iterative_step.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Iterative agent LLM step (Director sprint slice 15c).
3
+ *
4
+ * Multi-turn capable step: each call to the returned StepFn does
5
+ * ONE Claude chat (which itself may run several tool rounds
6
+ * internally via the Claude client's tool-calling loop). The
7
+ * conversation history accumulates in closure so the runner can
8
+ * call the step on each iteration and Claude sees the prior
9
+ * context.
10
+ *
11
+ * Tool surface: a single `nac3_invoke` exposed to Claude. The
12
+ * runTool callback gates each call against `def.allowed_verbs`
13
+ * before delegating to `runNac3Invoke`. A verb NOT in the
14
+ * whitelist returns is_error so Claude (and the audit log) see
15
+ * the explicit denial.
16
+ *
17
+ * "done" detection:
18
+ * - Claude emitted zero tool calls AND text is non-empty -> done.
19
+ * - reply.text matches a terminal marker (\[DONE\], etc) -> done.
20
+ * - One of the tool results is `nac3_panel_approval_required` -> done
21
+ * (with pending_approval=true so the runner records the
22
+ * pause; user resumes via /api/agent/approve in slice 10).
23
+ * - Otherwise (tools called + no terminal marker) -> done=false
24
+ * so the runner calls step again next iteration.
25
+ *
26
+ * ASCII-only.
27
+ */
28
+ import { promises as fs, existsSync, readFileSync } from 'node:fs';
29
+ import path from 'node:path';
30
+ import { buildAgentSystemPrompt } from './system_prompt.js';
31
+ import { NAC3_INVOKE_SPEC } from '../chat/tools/nac3_invoke.js';
32
+ /** Markers that flag a step turn as conclusive even when Claude
33
+ * did call tools mid-turn. ASCII-only / case-insensitive. */
34
+ const TERMINAL_MARKERS = [
35
+ /\[DONE\]/i,
36
+ /\bdone\.\s*$/i,
37
+ /\blisto\b[\s,.]*(termine|terminado|todo listo)?/i,
38
+ /\bterminado\b/i,
39
+ ];
40
+ function isApprovalPending(toolRounds) {
41
+ /* The approval envelope may sit at toolRound.result.nac3_panel_approval_required
42
+ * (when the result is the flat envelope) OR at
43
+ * toolRound.result.result.nac3_panel_approval_required (when the
44
+ * runTool returned the full {tool, is_error, result} wrapper). We
45
+ * accept both shapes so the contract is robust. */
46
+ for (const r of toolRounds) {
47
+ const res = r.result;
48
+ if (!res || typeof res !== 'object')
49
+ continue;
50
+ if (res.nac3_panel_approval_required === true)
51
+ return true;
52
+ const inner = res.result;
53
+ if (inner && typeof inner === 'object' && inner.nac3_panel_approval_required === true)
54
+ return true;
55
+ }
56
+ return false;
57
+ }
58
+ function hasTerminalMarker(text) {
59
+ for (const re of TERMINAL_MARKERS)
60
+ if (re.test(text))
61
+ return true;
62
+ return false;
63
+ }
64
+ export function buildIterativeLlmStep(opts) {
65
+ const system = buildAgentSystemPrompt({
66
+ def: opts.def,
67
+ project_root: opts.project_root,
68
+ project_name: opts.project_name,
69
+ forge_version: opts.forge_version,
70
+ graph_snapshot_section: opts.graph_snapshot_section,
71
+ workflow_section: opts.workflow_section,
72
+ });
73
+ /* Closure-held conversation history. Grows across step calls.
74
+ * When conversation_id is set, also persisted to disk so it
75
+ * survives runtime restarts. */
76
+ let messages = [];
77
+ let firstCall = true;
78
+ const convFile = opts.conversation_id && opts.conversation_root
79
+ ? path.join(opts.conversation_root, opts.conversation_id + '.json')
80
+ : null;
81
+ if (convFile && existsSync(convFile)) {
82
+ try {
83
+ const raw = readFileSync(convFile, 'utf-8');
84
+ const parsed = JSON.parse(raw);
85
+ if (parsed && Array.isArray(parsed.messages)) {
86
+ messages = parsed.messages;
87
+ /* History exists -> first call should NOT append trigger
88
+ * as a new user msg; the conversation already started. */
89
+ firstCall = false;
90
+ }
91
+ }
92
+ catch { /* corrupt -- treat as empty */ }
93
+ }
94
+ async function persistConversation() {
95
+ if (!convFile)
96
+ return;
97
+ try {
98
+ await fs.mkdir(path.dirname(convFile), { recursive: true });
99
+ /* Direct write -- atomic-rename pattern fails on Windows
100
+ * when the destination already exists. The conversation
101
+ * payload is small enough that a crash in the middle is
102
+ * acceptable (worst case: one partial conversation file). */
103
+ await fs.writeFile(convFile, JSON.stringify({ version: 1, messages }, null, 2), 'utf-8');
104
+ }
105
+ catch (err) {
106
+ /* surface but never crash the run */
107
+ try {
108
+ console.error('iterative_step: conversation persist failed: ' + (err instanceof Error ? err.message : String(err)));
109
+ }
110
+ catch { /* console redirected */ }
111
+ }
112
+ }
113
+ const allowed = new Set(opts.def.allowed_verbs ?? []);
114
+ /* runTool gate: nac3_invoke -> validate verb_id is allowed,
115
+ * then delegate to runNac3Invoke. Anything else -> denied. */
116
+ async function runTool(name, input) {
117
+ if (name !== NAC3_INVOKE_SPEC.name) {
118
+ return {
119
+ tool: name,
120
+ is_error: true,
121
+ result: { error: 'tool "' + name + '" is not exposed to this agent' },
122
+ };
123
+ }
124
+ const verbId = typeof input.verb_id === 'string' ? input.verb_id : '';
125
+ if (!verbId) {
126
+ return {
127
+ tool: NAC3_INVOKE_SPEC.name,
128
+ is_error: true,
129
+ result: { error: 'verb_id is required' },
130
+ };
131
+ }
132
+ if (!allowed.has(verbId)) {
133
+ return {
134
+ tool: NAC3_INVOKE_SPEC.name,
135
+ is_error: true,
136
+ result: {
137
+ error: 'verb_id "' + verbId + '" not in allowed_verbs of agent "' + opts.def.slug + '"',
138
+ allowed_verbs: Array.from(allowed),
139
+ },
140
+ };
141
+ }
142
+ const args = (input.args && typeof input.args === 'object' && !Array.isArray(input.args))
143
+ ? input.args
144
+ : {};
145
+ /* Slice 15d -- intercept yujin.agent.delegate before the
146
+ * regular runNac3Invoke path. Routes through the injected
147
+ * delegate callback (bridge + runtime). */
148
+ if (verbId === 'yujin.agent.delegate' && opts.delegate) {
149
+ const toSlug = typeof args.to_slug === 'string' ? args.to_slug : '';
150
+ const payload = typeof args.payload === 'string' ? args.payload : '';
151
+ if (!toSlug || !payload) {
152
+ return {
153
+ tool: NAC3_INVOKE_SPEC.name,
154
+ is_error: true,
155
+ result: { error: 'yujin.agent.delegate requires {to_slug, payload}' },
156
+ };
157
+ }
158
+ try {
159
+ const r = await opts.delegate(toSlug, payload);
160
+ return {
161
+ tool: NAC3_INVOKE_SPEC.name,
162
+ is_error: !r.ok,
163
+ result: r,
164
+ };
165
+ }
166
+ catch (err) {
167
+ return {
168
+ tool: NAC3_INVOKE_SPEC.name,
169
+ is_error: true,
170
+ result: { error: err instanceof Error ? err.message : String(err) },
171
+ };
172
+ }
173
+ }
174
+ return opts.runNac3Invoke({ verb_id: verbId, args }, opts.nac3_ctx ?? {}, {
175
+ legacyRun: opts.legacy_run ?? (() => { throw new Error('legacy_run not wired'); }),
176
+ /* Tag the approval-queue row with this agent's slug so the
177
+ * eventual /api/agent/approve can emit
178
+ * agent_run_paused_resolved targeting the right SVG node. */
179
+ agentSlug: opts.def.slug,
180
+ });
181
+ }
182
+ return async (_state) => {
183
+ if (firstCall) {
184
+ messages.push({ role: 'user', content: opts.trigger_reason });
185
+ firstCall = false;
186
+ }
187
+ else if (messages.length > 0 && messages[messages.length - 1].role === 'assistant') {
188
+ /* Bug fix found in E2E live with Claude API (2026-06-05):
189
+ * each Claude /v1/messages call must end with a user
190
+ * message. After the first iterative turn the closure
191
+ * already pushed the assistant reply, so the next call
192
+ * would 400 with "This model does not support assistant
193
+ * message prefill". Inject a synthetic "continue" user
194
+ * turn so the next iteration is valid. */
195
+ messages.push({ role: 'user', content: 'Continue.' });
196
+ }
197
+ const reply = await opts.claude.chat({
198
+ system,
199
+ messages: messages.slice(),
200
+ /* Bug fix found in E2E live with Claude API (2026-06-05):
201
+ * passing only `[{name}]` makes the API reject the request
202
+ * with "tools.0.custom.input_schema: Field required".
203
+ * The Claude client builds the body from {name, description,
204
+ * input_schema}, so we must hand the full spec. */
205
+ tools: [{
206
+ name: NAC3_INVOKE_SPEC.name,
207
+ description: NAC3_INVOKE_SPEC.description,
208
+ input_schema: NAC3_INVOKE_SPEC.input_schema,
209
+ }],
210
+ runTool,
211
+ maxTokens: opts.max_tokens ?? 2048,
212
+ });
213
+ if (reply.text) {
214
+ messages.push({ role: 'assistant', content: reply.text });
215
+ }
216
+ const toolCount = Array.isArray(reply.toolRounds) ? reply.toolRounds.length : 0;
217
+ const pendingApproval = isApprovalPending(reply.toolRounds || []);
218
+ let done;
219
+ if (pendingApproval) {
220
+ done = true;
221
+ }
222
+ else if (toolCount === 0) {
223
+ done = true;
224
+ }
225
+ else if (hasTerminalMarker(reply.text)) {
226
+ done = true;
227
+ }
228
+ else {
229
+ done = false;
230
+ }
231
+ /* Director closure pendiente 4 -- fire-and-forget persist
232
+ * after every step so a runtime restart resumes from the
233
+ * latest assistant reply. */
234
+ if (convFile) {
235
+ persistConversation().catch(() => undefined);
236
+ }
237
+ const out = {
238
+ text: reply.text,
239
+ tokens_in: reply.tokensIn,
240
+ tokens_out: reply.tokensOut,
241
+ tool_calls: toolCount,
242
+ done,
243
+ };
244
+ if (pendingApproval)
245
+ out.pending_approval = true;
246
+ return out;
247
+ };
248
+ }
249
+ //# sourceMappingURL=iterative_step.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iterative_step.js","sourceRoot":"","sources":["../../src/agents/iterative_step.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Agent LLM step (Director sprint slice 15b).
3
+ *
4
+ * Builds a StepFn that the runner can call. The step composes
5
+ * the agent's system prompt + emits one Claude call + returns a
6
+ * StepResult. Single-shot for now: every step returns done=true
7
+ * so the runner stops after one iteration. Multi-step
8
+ * tool-calling within an agent run lands in slice 16.
9
+ *
10
+ * The Claude client + the (def, project, snapshot) inputs are
11
+ * injected -- this module does not own them so the runtime can
12
+ * compose them with the per-turn context.
13
+ *
14
+ * ASCII-only.
15
+ */
16
+ import type { AgentDefinition } from './types.js';
17
+ import type { StepFn } from './runner.js';
18
+ export interface LlmStepOpts {
19
+ def: AgentDefinition;
20
+ claude: {
21
+ chat: (req: {
22
+ system?: string;
23
+ messages: Array<{
24
+ role: 'user' | 'assistant' | 'system';
25
+ content: string;
26
+ }>;
27
+ maxTokens?: number;
28
+ }) => Promise<{
29
+ text: string;
30
+ tokensIn: number;
31
+ tokensOut: number;
32
+ model: string;
33
+ toolRounds: unknown[];
34
+ }>;
35
+ };
36
+ project_root: string;
37
+ project_name: string;
38
+ forge_version: string;
39
+ /** Inbound bridge payload OR the run trigger reason -- becomes
40
+ * the user message of the Claude turn. */
41
+ trigger_reason: string;
42
+ /** Pre-rendered + role-filtered graph snapshot (slice 11). */
43
+ graph_snapshot_section?: string;
44
+ /** Pre-rendered workflow state section (workflow_inject). */
45
+ workflow_section?: string;
46
+ /** Max tokens for the Claude reply. Defaults to 2048. */
47
+ max_tokens?: number;
48
+ }
49
+ export declare function buildLlmStep(opts: LlmStepOpts): StepFn;
50
+ //# sourceMappingURL=llm_step.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm_step.d.ts","sourceRoot":"","sources":["../../src/agents/llm_step.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,KAAK,EAAE,MAAM,EAAwB,MAAM,aAAa,CAAC;AAGhE,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAY,eAAe,CAAC;IAC/B,MAAM,EAAS;QAAE,IAAI,EAAE,CAAC,GAAG,EAAE;YAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;YAChB,QAAQ,EAAE,KAAK,CAAC;gBAAE,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;gBAAC,OAAO,EAAE,MAAM,CAAA;aAAE,CAAC,CAAC;YAC5E,SAAS,CAAC,EAAE,MAAM,CAAC;SACpB,KAAK,OAAO,CAAC;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,QAAQ,EAAE,MAAM,CAAC;YAAC,SAAS,EAAE,MAAM,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,UAAU,EAAE,OAAO,EAAE,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC;IAC7G,YAAY,EAAG,MAAM,CAAC;IACtB,YAAY,EAAG,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB;+CAC2C;IAC3C,cAAc,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,6DAA6D;IAC7D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CA0BtD"}
@@ -0,0 +1,28 @@
1
+ import { buildAgentSystemPrompt } from './system_prompt.js';
2
+ export function buildLlmStep(opts) {
3
+ const system = buildAgentSystemPrompt({
4
+ def: opts.def,
5
+ project_root: opts.project_root,
6
+ project_name: opts.project_name,
7
+ forge_version: opts.forge_version,
8
+ graph_snapshot_section: opts.graph_snapshot_section,
9
+ workflow_section: opts.workflow_section,
10
+ });
11
+ return async (_state) => {
12
+ const reply = await opts.claude.chat({
13
+ system,
14
+ messages: [
15
+ { role: 'user', content: opts.trigger_reason },
16
+ ],
17
+ maxTokens: opts.max_tokens ?? 2048,
18
+ });
19
+ return {
20
+ text: reply.text,
21
+ tokens_in: reply.tokensIn,
22
+ tokens_out: reply.tokensOut,
23
+ tool_calls: Array.isArray(reply.toolRounds) ? reply.toolRounds.length : 0,
24
+ done: true,
25
+ };
26
+ };
27
+ }
28
+ //# sourceMappingURL=llm_step.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm_step.js","sourceRoot":"","sources":["../../src/agents/llm_step.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAuB5D,MAAM,UAAU,YAAY,CAAC,IAAiB;IAC5C,MAAM,MAAM,GAAG,sBAAsB,CAAC;QACpC,GAAG,EAAY,IAAI,CAAC,GAAG;QACvB,YAAY,EAAG,IAAI,CAAC,YAAY;QAChC,YAAY,EAAG,IAAI,CAAC,YAAY;QAChC,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,sBAAsB,EAAE,IAAI,CAAC,sBAAsB;QACnD,gBAAgB,EAAQ,IAAI,CAAC,gBAAgB;KAC9C,CAAC,CAAC;IAEH,OAAO,KAAK,EAAE,MAAgB,EAAuB,EAAE;QACrD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;YACnC,MAAM;YACN,QAAQ,EAAE;gBACR,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,cAAc,EAAE;aAC/C;YACD,SAAS,EAAE,IAAI,CAAC,UAAU,IAAI,IAAI;SACnC,CAAC,CAAC;QACH,OAAO;YACL,IAAI,EAAQ,KAAK,CAAC,IAAI;YACtB,SAAS,EAAG,KAAK,CAAC,QAAQ;YAC1B,UAAU,EAAE,KAAK,CAAC,SAAS;YAC3B,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACzE,IAAI,EAAQ,IAAI;SACjB,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Real agent step factory (Director sprint slice 15e).
3
+ *
4
+ * Production wiring: composes the live Claude-driven iterative
5
+ * step. Use this from the chat server, the CLI (`yf agent run
6
+ * --real`), and the E2E smoke harness.
7
+ *
8
+ * Inputs (injected so tests + production stay aligned):
9
+ * - claude: the ClaudeClient (or compatible).
10
+ * - runNac3Invoke: the nac3 dispatcher (chat/tools/nac3_invoke).
11
+ * - runtime: optional. When present, the factory wires
12
+ * yujin.agent.delegate -> delegateToAgent so
13
+ * inter-agent bridges work end-to-end.
14
+ * - bridge_root: optional. Override the ~/.yujin-forge root
15
+ * the bridge persists to (tests only).
16
+ *
17
+ * Output: a function (def, trigger_reason) => StepFn the runner
18
+ * can call directly.
19
+ *
20
+ * ASCII-only.
21
+ */
22
+ import type { AgentDefinition } from './types.js';
23
+ import type { StepFn } from './runner.js';
24
+ import type { Runtime } from './runtime.js';
25
+ interface MinimalClaude {
26
+ chat(req: {
27
+ system?: string;
28
+ messages: Array<{
29
+ role: 'user' | 'assistant' | 'system';
30
+ content: string;
31
+ }>;
32
+ tools?: Array<{
33
+ name: string;
34
+ description?: string;
35
+ input_schema?: Record<string, unknown>;
36
+ }>;
37
+ runTool?: (name: string, input: Record<string, unknown>) => Promise<unknown>;
38
+ maxTokens?: number;
39
+ }): Promise<{
40
+ text: string;
41
+ tokensIn: number;
42
+ tokensOut: number;
43
+ model?: string;
44
+ toolRounds: Array<{
45
+ tool: string;
46
+ input: Record<string, unknown>;
47
+ result: unknown;
48
+ is_error?: boolean;
49
+ tool_use_id: string;
50
+ }>;
51
+ }>;
52
+ }
53
+ type RunNac3InvokeFn = (rawArgs: {
54
+ verb_id: string;
55
+ args?: Record<string, unknown>;
56
+ }, ctx: unknown, opts: {
57
+ legacyRun: unknown;
58
+ panelSessionId?: string;
59
+ llmTurnId?: string;
60
+ agentSlug?: string;
61
+ }) => Promise<{
62
+ tool: string;
63
+ is_error?: boolean;
64
+ result: unknown;
65
+ }>;
66
+ export interface BuildStepFactoryOpts {
67
+ claude: MinimalClaude;
68
+ runNac3Invoke: RunNac3InvokeFn;
69
+ project_root: string;
70
+ project_name: string;
71
+ forge_version: string;
72
+ /** Optional. When present, wire the delegate verb so inter-
73
+ * agent calls (Director -> Analyst) work end-to-end. */
74
+ runtime?: Runtime;
75
+ /** Optional bridge root override (tests inject tmp). */
76
+ bridge_root?: string;
77
+ /** Optional pre-rendered, role-filtered graph snapshot from
78
+ * slice 11. The chat server / CLI can compute this once per
79
+ * project + reuse across factory calls (cache hit). */
80
+ graph_snapshot_section?: string;
81
+ workflow_section?: string;
82
+ /** Optional ctx pass-through for runNac3Invoke. */
83
+ nac3_ctx?: unknown;
84
+ legacy_run?: unknown;
85
+ /** Director closure pendiente 4 -- conversation persistence.
86
+ * When provided, the conversation is loaded from
87
+ * <conversation_root>/<conversation_id>.json on factory call
88
+ * + persisted after every step. Survives runtime restarts. */
89
+ conversation_id?: string;
90
+ conversation_root?: string;
91
+ }
92
+ export type AgentStepFactory = (def: AgentDefinition, trigger_reason: string) => StepFn;
93
+ export declare function buildAgentStepFactory(opts: BuildStepFactoryOpts): AgentStepFactory;
94
+ export {};
95
+ //# sourceMappingURL=real_step_factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"real_step_factory.d.ts","sourceRoot":"","sources":["../../src/agents/real_step_factory.ts"],"names":[],"mappings":"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"}