@kindgi/agents 0.0.0-bootstrap.0 → 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.
Files changed (240) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +131 -2
  3. package/dist/agent-turn-flow.d.ts +57 -0
  4. package/dist/agent-turn-flow.d.ts.map +1 -0
  5. package/dist/agent-turn-flow.js +172 -0
  6. package/dist/agent-turn-flow.js.map +1 -0
  7. package/dist/conversation-binding.d.ts +111 -0
  8. package/dist/conversation-binding.d.ts.map +1 -0
  9. package/dist/conversation-binding.js +4 -0
  10. package/dist/conversation-binding.js.map +1 -0
  11. package/dist/define.d.ts +180 -0
  12. package/dist/define.d.ts.map +1 -0
  13. package/dist/define.js +361 -0
  14. package/dist/define.js.map +1 -0
  15. package/dist/errors.d.ts +62 -0
  16. package/dist/errors.d.ts.map +1 -0
  17. package/dist/errors.js +4 -0
  18. package/dist/errors.js.map +1 -0
  19. package/dist/guardrails-gate.d.ts +169 -0
  20. package/dist/guardrails-gate.d.ts.map +1 -0
  21. package/dist/guardrails-gate.js +202 -0
  22. package/dist/guardrails-gate.js.map +1 -0
  23. package/dist/handlers/budget-check.d.ts +22 -0
  24. package/dist/handlers/budget-check.d.ts.map +1 -0
  25. package/dist/handlers/budget-check.js +109 -0
  26. package/dist/handlers/budget-check.js.map +1 -0
  27. package/dist/handlers/build-initial-messages.d.ts +17 -0
  28. package/dist/handlers/build-initial-messages.d.ts.map +1 -0
  29. package/dist/handlers/build-initial-messages.js +86 -0
  30. package/dist/handlers/build-initial-messages.js.map +1 -0
  31. package/dist/handlers/compose-result.d.ts +10 -0
  32. package/dist/handlers/compose-result.d.ts.map +1 -0
  33. package/dist/handlers/compose-result.js +79 -0
  34. package/dist/handlers/compose-result.js.map +1 -0
  35. package/dist/handlers/constants.d.ts +8 -0
  36. package/dist/handlers/constants.d.ts.map +1 -0
  37. package/dist/handlers/constants.js +10 -0
  38. package/dist/handlers/constants.js.map +1 -0
  39. package/dist/handlers/context.d.ts +210 -0
  40. package/dist/handlers/context.d.ts.map +1 -0
  41. package/dist/handlers/context.js +4 -0
  42. package/dist/handlers/context.js.map +1 -0
  43. package/dist/handlers/dispatch-tools.d.ts +15 -0
  44. package/dist/handlers/dispatch-tools.d.ts.map +1 -0
  45. package/dist/handlers/dispatch-tools.js +511 -0
  46. package/dist/handlers/dispatch-tools.js.map +1 -0
  47. package/dist/handlers/errors.d.ts +133 -0
  48. package/dist/handlers/errors.d.ts.map +1 -0
  49. package/dist/handlers/errors.js +134 -0
  50. package/dist/handlers/errors.js.map +1 -0
  51. package/dist/handlers/evaluate-guardrails.d.ts +14 -0
  52. package/dist/handlers/evaluate-guardrails.d.ts.map +1 -0
  53. package/dist/handlers/evaluate-guardrails.js +128 -0
  54. package/dist/handlers/evaluate-guardrails.js.map +1 -0
  55. package/dist/handlers/final-iteration.d.ts +7 -0
  56. package/dist/handlers/final-iteration.d.ts.map +1 -0
  57. package/dist/handlers/final-iteration.js +26 -0
  58. package/dist/handlers/final-iteration.js.map +1 -0
  59. package/dist/handlers/index.d.ts +5 -0
  60. package/dist/handlers/index.d.ts.map +1 -0
  61. package/dist/handlers/index.js +41 -0
  62. package/dist/handlers/index.js.map +1 -0
  63. package/dist/handlers/model-call.d.ts +13 -0
  64. package/dist/handlers/model-call.d.ts.map +1 -0
  65. package/dist/handlers/model-call.js +136 -0
  66. package/dist/handlers/model-call.js.map +1 -0
  67. package/dist/handlers/persist-final-message.d.ts +14 -0
  68. package/dist/handlers/persist-final-message.d.ts.map +1 -0
  69. package/dist/handlers/persist-final-message.js +54 -0
  70. package/dist/handlers/persist-final-message.js.map +1 -0
  71. package/dist/handlers/persist-provenance.d.ts +12 -0
  72. package/dist/handlers/persist-provenance.d.ts.map +1 -0
  73. package/dist/handlers/persist-provenance.js +34 -0
  74. package/dist/handlers/persist-provenance.js.map +1 -0
  75. package/dist/handlers/persist-user-message.d.ts +15 -0
  76. package/dist/handlers/persist-user-message.d.ts.map +1 -0
  77. package/dist/handlers/persist-user-message.js +59 -0
  78. package/dist/handlers/persist-user-message.js.map +1 -0
  79. package/dist/handlers/public-types.d.ts +201 -0
  80. package/dist/handlers/public-types.d.ts.map +1 -0
  81. package/dist/handlers/public-types.js +4 -0
  82. package/dist/handlers/public-types.js.map +1 -0
  83. package/dist/handlers/rehydrate.d.ts +8 -0
  84. package/dist/handlers/rehydrate.d.ts.map +1 -0
  85. package/dist/handlers/rehydrate.js +94 -0
  86. package/dist/handlers/rehydrate.js.map +1 -0
  87. package/dist/handlers/render-prompt.d.ts +12 -0
  88. package/dist/handlers/render-prompt.d.ts.map +1 -0
  89. package/dist/handlers/render-prompt.js +41 -0
  90. package/dist/handlers/render-prompt.js.map +1 -0
  91. package/dist/handlers/resolve-tools.d.ts +10 -0
  92. package/dist/handlers/resolve-tools.d.ts.map +1 -0
  93. package/dist/handlers/resolve-tools.js +55 -0
  94. package/dist/handlers/resolve-tools.js.map +1 -0
  95. package/dist/handlers/result-shape.d.ts +94 -0
  96. package/dist/handlers/result-shape.d.ts.map +1 -0
  97. package/dist/handlers/result-shape.js +19 -0
  98. package/dist/handlers/result-shape.js.map +1 -0
  99. package/dist/handlers/run-retrievals.d.ts +10 -0
  100. package/dist/handlers/run-retrievals.d.ts.map +1 -0
  101. package/dist/handlers/run-retrievals.js +64 -0
  102. package/dist/handlers/run-retrievals.js.map +1 -0
  103. package/dist/handlers/run-snapshot.d.ts +4 -0
  104. package/dist/handlers/run-snapshot.d.ts.map +1 -0
  105. package/dist/handlers/run-snapshot.js +26 -0
  106. package/dist/handlers/run-snapshot.js.map +1 -0
  107. package/dist/handlers/setup.d.ts +25 -0
  108. package/dist/handlers/setup.d.ts.map +1 -0
  109. package/dist/handlers/setup.js +231 -0
  110. package/dist/handlers/setup.js.map +1 -0
  111. package/dist/handlers/structured-output.d.ts +38 -0
  112. package/dist/handlers/structured-output.d.ts.map +1 -0
  113. package/dist/handlers/structured-output.js +89 -0
  114. package/dist/handlers/structured-output.js.map +1 -0
  115. package/dist/handlers/tool-errors.d.ts +56 -0
  116. package/dist/handlers/tool-errors.d.ts.map +1 -0
  117. package/dist/handlers/tool-errors.js +73 -0
  118. package/dist/handlers/tool-errors.js.map +1 -0
  119. package/dist/handlers/tool-hitl.d.ts +45 -0
  120. package/dist/handlers/tool-hitl.d.ts.map +1 -0
  121. package/dist/handlers/tool-hitl.js +81 -0
  122. package/dist/handlers/tool-hitl.js.map +1 -0
  123. package/dist/handlers/turn-environment.d.ts +26 -0
  124. package/dist/handlers/turn-environment.d.ts.map +1 -0
  125. package/dist/handlers/turn-environment.js +154 -0
  126. package/dist/handlers/turn-environment.js.map +1 -0
  127. package/dist/hitl-policy.d.ts +45 -0
  128. package/dist/hitl-policy.d.ts.map +1 -0
  129. package/dist/hitl-policy.js +74 -0
  130. package/dist/hitl-policy.js.map +1 -0
  131. package/dist/index.d.ts +31 -0
  132. package/dist/index.d.ts.map +1 -0
  133. package/dist/index.js +19 -0
  134. package/dist/index.js.map +1 -0
  135. package/dist/invoke.d.ts +36 -0
  136. package/dist/invoke.d.ts.map +1 -0
  137. package/dist/invoke.js +228 -0
  138. package/dist/invoke.js.map +1 -0
  139. package/dist/migrations-dir.d.ts +11 -0
  140. package/dist/migrations-dir.d.ts.map +1 -0
  141. package/dist/migrations-dir.js +14 -0
  142. package/dist/migrations-dir.js.map +1 -0
  143. package/dist/project-run-result.d.ts +23 -0
  144. package/dist/project-run-result.d.ts.map +1 -0
  145. package/dist/project-run-result.js +116 -0
  146. package/dist/project-run-result.js.map +1 -0
  147. package/dist/prompt.d.ts +83 -0
  148. package/dist/prompt.d.ts.map +1 -0
  149. package/dist/prompt.js +119 -0
  150. package/dist/prompt.js.map +1 -0
  151. package/dist/provenance-emit.d.ts +44 -0
  152. package/dist/provenance-emit.d.ts.map +1 -0
  153. package/dist/provenance-emit.js +51 -0
  154. package/dist/provenance-emit.js.map +1 -0
  155. package/dist/registry.d.ts +38 -0
  156. package/dist/registry.d.ts.map +1 -0
  157. package/dist/registry.js +125 -0
  158. package/dist/registry.js.map +1 -0
  159. package/dist/retrieval.d.ts +47 -0
  160. package/dist/retrieval.d.ts.map +1 -0
  161. package/dist/retrieval.js +155 -0
  162. package/dist/retrieval.js.map +1 -0
  163. package/dist/run-snapshot-binding.d.ts +77 -0
  164. package/dist/run-snapshot-binding.d.ts.map +1 -0
  165. package/dist/run-snapshot-binding.js +4 -0
  166. package/dist/run-snapshot-binding.js.map +1 -0
  167. package/dist/schema.d.ts +497 -0
  168. package/dist/schema.d.ts.map +1 -0
  169. package/dist/schema.js +133 -0
  170. package/dist/schema.js.map +1 -0
  171. package/dist/streaming.d.ts +118 -0
  172. package/dist/streaming.d.ts.map +1 -0
  173. package/dist/streaming.js +17 -0
  174. package/dist/streaming.js.map +1 -0
  175. package/dist/tenant-policy.d.ts +16 -0
  176. package/dist/tenant-policy.d.ts.map +1 -0
  177. package/dist/tenant-policy.js +77 -0
  178. package/dist/tenant-policy.js.map +1 -0
  179. package/dist/types.d.ts +435 -0
  180. package/dist/types.d.ts.map +1 -0
  181. package/dist/types.js +4 -0
  182. package/dist/types.js.map +1 -0
  183. package/dist/versioning.d.ts +29 -0
  184. package/dist/versioning.d.ts.map +1 -0
  185. package/dist/versioning.js +58 -0
  186. package/dist/versioning.js.map +1 -0
  187. package/migrations/0000_sparkling_talkback.sql +18 -0
  188. package/migrations/0001_tired_warhawk.sql +16 -0
  189. package/migrations/0002_violet_ezekiel.sql +2 -0
  190. package/migrations/meta/0000_snapshot.json +172 -0
  191. package/migrations/meta/0001_snapshot.json +275 -0
  192. package/migrations/meta/0002_snapshot.json +287 -0
  193. package/migrations/meta/_journal.json +27 -0
  194. package/package.json +76 -4
  195. package/src/agent-turn-flow.ts +183 -0
  196. package/src/conversation-binding.ts +147 -0
  197. package/src/define.ts +572 -0
  198. package/src/errors.ts +80 -0
  199. package/src/guardrails-gate.ts +342 -0
  200. package/src/handlers/budget-check.ts +143 -0
  201. package/src/handlers/build-initial-messages.ts +103 -0
  202. package/src/handlers/compose-result.ts +90 -0
  203. package/src/handlers/constants.ts +10 -0
  204. package/src/handlers/context.ts +226 -0
  205. package/src/handlers/dispatch-tools.ts +633 -0
  206. package/src/handlers/errors.ts +282 -0
  207. package/src/handlers/evaluate-guardrails.ts +153 -0
  208. package/src/handlers/final-iteration.ts +30 -0
  209. package/src/handlers/index.ts +63 -0
  210. package/src/handlers/model-call.ts +151 -0
  211. package/src/handlers/persist-final-message.ts +67 -0
  212. package/src/handlers/persist-provenance.ts +39 -0
  213. package/src/handlers/persist-user-message.ts +70 -0
  214. package/src/handlers/public-types.ts +209 -0
  215. package/src/handlers/rehydrate.ts +161 -0
  216. package/src/handlers/render-prompt.ts +46 -0
  217. package/src/handlers/resolve-tools.ts +68 -0
  218. package/src/handlers/result-shape.ts +113 -0
  219. package/src/handlers/run-retrievals.ts +77 -0
  220. package/src/handlers/run-snapshot.ts +44 -0
  221. package/src/handlers/setup.ts +269 -0
  222. package/src/handlers/structured-output.ts +117 -0
  223. package/src/handlers/tool-errors.ts +122 -0
  224. package/src/handlers/tool-hitl.ts +126 -0
  225. package/src/handlers/turn-environment.ts +191 -0
  226. package/src/hitl-policy.ts +128 -0
  227. package/src/index.ts +154 -0
  228. package/src/invoke.ts +299 -0
  229. package/src/migrations-dir.ts +17 -0
  230. package/src/project-run-result.ts +131 -0
  231. package/src/prompt.ts +185 -0
  232. package/src/provenance-emit.ts +100 -0
  233. package/src/registry.ts +164 -0
  234. package/src/retrieval.ts +219 -0
  235. package/src/run-snapshot-binding.ts +87 -0
  236. package/src/schema.ts +154 -0
  237. package/src/streaming.ts +153 -0
  238. package/src/tenant-policy.ts +78 -0
  239. package/src/types.ts +453 -0
  240. package/src/versioning.ts +77 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/handlers/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,134 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ /**
4
+ * Thrown by a node handler when a precondition fails or a runtime step
5
+ * short-circuits with a structured error. The kernel captures
6
+ * `Error.message` into `step.failed.payload.message`; we serialize the
7
+ * full structured error as JSON so `projectRunResult` can recover the
8
+ * discriminated union shape on the way out.
9
+ *
10
+ * Deliberately narrowed to `Error` subclass so `cause` becomes a plain
11
+ * property (JSON-round-trippable) instead of the native ErrorOptions
12
+ * behavior.
13
+ */
14
+ export class AgentTurnFailure extends Error {
15
+ payload;
16
+ constructor(payload) {
17
+ super(serializeError(payload));
18
+ this.name = 'AgentTurnFailure';
19
+ this.payload = payload;
20
+ }
21
+ }
22
+ const FAILURE_SENTINEL = '__agent_turn_failure__';
23
+ /**
24
+ * Encode an `InvokeAgentError` as a JSON string carried in an Error's
25
+ * message. The sentinel field lets `parseFailureMessage` distinguish
26
+ * our structured failures from other error messages that happen to be
27
+ * JSON-shaped.
28
+ *
29
+ * `cause` fields on inner errors are downgraded to their message form
30
+ * so the payload is JSON-safe.
31
+ */
32
+ function serializeError(error) {
33
+ return JSON.stringify({
34
+ [FAILURE_SENTINEL]: true,
35
+ error: stripCauseFunctions(error),
36
+ }, (_key, value) => {
37
+ if (value instanceof Error) {
38
+ return { code: value.code, message: value.message };
39
+ }
40
+ return value;
41
+ });
42
+ }
43
+ function stripCauseFunctions(error) {
44
+ // JSON.stringify replacer above handles Error instances; nothing more
45
+ // to do here. A pass-through hook for error variants that embed
46
+ // callbacks.
47
+ return error;
48
+ }
49
+ /**
50
+ * Attempt to reconstruct a structured `InvokeAgentError` from a run's
51
+ * `failureMessage`. Returns `undefined` when the message is not one of
52
+ * ours (e.g. a raw kernel-level exception message).
53
+ */
54
+ export function parseFailureMessage(raw) {
55
+ if (raw === undefined || raw.length === 0)
56
+ return undefined;
57
+ // Fast path: the raw message IS the single serialized failure (one
58
+ // step.failed for the whole turn, which is the common case).
59
+ const whole = tryParseChunk(raw);
60
+ if (whole !== undefined)
61
+ return whole;
62
+ // Fallback: the kernel joins multiple step.failed messages with '; '.
63
+ // Recover by extracting balanced-brace substrings and trying each.
64
+ for (const chunk of extractJsonCandidates(raw)) {
65
+ const parsed = tryParseChunk(chunk);
66
+ if (parsed !== undefined)
67
+ return parsed;
68
+ }
69
+ return undefined;
70
+ }
71
+ /**
72
+ * Extract substrings that look like well-formed JSON objects by
73
+ * scanning for balanced braces. Only single-level scan — inner strings
74
+ * are respected. Cheap parser used for the rare multi-failure case.
75
+ */
76
+ function extractJsonCandidates(raw) {
77
+ const out = [];
78
+ let depth = 0;
79
+ let start = -1;
80
+ let inString = false;
81
+ let escaped = false;
82
+ for (let i = 0; i < raw.length; i++) {
83
+ const ch = raw[i];
84
+ if (escaped) {
85
+ escaped = false;
86
+ continue;
87
+ }
88
+ if (ch === '\\') {
89
+ escaped = true;
90
+ continue;
91
+ }
92
+ if (ch === '"') {
93
+ inString = !inString;
94
+ continue;
95
+ }
96
+ if (inString)
97
+ continue;
98
+ if (ch === '{') {
99
+ if (depth === 0)
100
+ start = i;
101
+ depth += 1;
102
+ }
103
+ else if (ch === '}') {
104
+ depth -= 1;
105
+ if (depth === 0 && start >= 0) {
106
+ out.push(raw.slice(start, i + 1));
107
+ start = -1;
108
+ }
109
+ }
110
+ }
111
+ return out;
112
+ }
113
+ function tryParseChunk(chunk) {
114
+ const trimmed = chunk.trim();
115
+ if (!trimmed.startsWith('{'))
116
+ return undefined;
117
+ try {
118
+ const doc = JSON.parse(trimmed);
119
+ if (typeof doc === 'object' &&
120
+ doc !== null &&
121
+ doc[FAILURE_SENTINEL] === true) {
122
+ return doc.error;
123
+ }
124
+ }
125
+ catch {
126
+ // Not our JSON — probably a raw JS Error.message. Fall through.
127
+ }
128
+ return undefined;
129
+ }
130
+ /** Helper for handlers to short-circuit with a structured error. */
131
+ export function throwAgentTurnFailure(error) {
132
+ throw new AgentTurnFailure(error);
133
+ }
134
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/handlers/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { NodeHandler } from '@kindgi/handler';
2
+ import type { TurnContext } from './context.js';
3
+ /**
4
+ * Guardrail gate on the turn's final response, before it is stored.
5
+ * Receives the agent loop's output. A failed guardrail whose action is
6
+ * `halt` throws, so the run fails and the response never reaches the
7
+ * conversation; failures with any other action are stashed on `ctx` for
8
+ * `compose-result` to surface in `AgentTurnResult.violations`. Every
9
+ * failure emits a `guardrail.violated` event. Also records the
10
+ * response's `model-output` provenance node, which the guardrail checks
11
+ * link to.
12
+ */
13
+ export declare function buildEvaluateGuardrailsHandler(ctx: TurnContext): NodeHandler;
14
+ //# sourceMappingURL=evaluate-guardrails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate-guardrails.d.ts","sourceRoot":"","sources":["../../src/handlers/evaluate-guardrails.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAYnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKhD;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAAC,GAAG,EAAE,WAAW,GAAG,WAAW,CA0H5E"}
@@ -0,0 +1,128 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ import { buildRunTrace, categorizeOutcomes, describeBlockingViolations, evaluateGate, } from '../guardrails-gate.js';
4
+ import { emitTurnEvent } from '../streaming.js';
5
+ import { throwAgentTurnFailure } from './errors.js';
6
+ import { finalIteration } from './final-iteration.js';
7
+ import { parseJsonAnswer } from './structured-output.js';
8
+ /**
9
+ * Guardrail gate on the turn's final response, before it is stored.
10
+ * Receives the agent loop's output. A failed guardrail whose action is
11
+ * `halt` throws, so the run fails and the response never reaches the
12
+ * conversation; failures with any other action are stashed on `ctx` for
13
+ * `compose-result` to surface in `AgentTurnResult.violations`. Every
14
+ * failure emits a `guardrail.violated` event. Also records the
15
+ * response's `model-output` provenance node, which the guardrail checks
16
+ * link to.
17
+ */
18
+ export function buildEvaluateGuardrailsHandler(ctx) {
19
+ return async (input, kctx) => {
20
+ if (ctx.guardrails === undefined) {
21
+ throwAgentTurnFailure({
22
+ code: 'model-invocation-failed',
23
+ message: 'evaluate-guardrails invoked before setup completed',
24
+ cause: null,
25
+ });
26
+ }
27
+ const final = finalIteration(input, 'evaluate-guardrails');
28
+ const evaluatedAt = new Date().toISOString();
29
+ // The response as it would be stored; not persisted yet.
30
+ const response = {
31
+ sequence: -1,
32
+ role: 'agent',
33
+ content: final.message.content ?? '',
34
+ createdAt: evaluatedAt,
35
+ actor: ctx.input.agent.id,
36
+ };
37
+ if (ctx.provenance !== undefined) {
38
+ ctx.provenance.addNode({
39
+ id: `model-output:${ctx.usage.steps}`,
40
+ kind: 'model-output',
41
+ timestamp: evaluatedAt,
42
+ modelVersion: `${final.provider.id}/${final.provider.model}`,
43
+ });
44
+ ctx.provenance.addEdge({
45
+ from: `model-output:${ctx.usage.steps}`,
46
+ to: `model-call:${ctx.usage.steps}`,
47
+ kind: 'produced',
48
+ });
49
+ }
50
+ const finalUsage = {
51
+ steps: ctx.usage.steps,
52
+ promptTokens: ctx.usage.promptTokens,
53
+ completionTokens: ctx.usage.completionTokens,
54
+ totalCostUsd: ctx.usage.totalCostUsd,
55
+ durationMs: Date.now() - ctx.startedAt,
56
+ };
57
+ const structured = ctx.input.agent.output !== undefined && !kctx.dryRun
58
+ ? parseJsonAnswer(final.message.content)
59
+ : undefined;
60
+ const trace = buildRunTrace({
61
+ runId: kctx.runId,
62
+ tenantId: ctx.input.tenantId,
63
+ projectId: ctx.input.projectId,
64
+ conversationId: ctx.input.conversationId,
65
+ turnNumber: (ctx.conversation?.turnCount ?? 0) + 1,
66
+ agent: ctx.input.agent,
67
+ userMessage: ctx.input.userMessage,
68
+ ...(ctx.input.input !== undefined && { stepInput: ctx.input.input }),
69
+ ...(structured?.kind === 'ok' && { structuredOutput: structured.value }),
70
+ appended: ctx.appended,
71
+ finalResponse: response,
72
+ usage: finalUsage,
73
+ });
74
+ const outcomes = await evaluateGate(ctx.guardrails, trace, ctx.bindings, ctx.tenantPolicy, ctx.turnAbort.signal);
75
+ const categorized = categorizeOutcomes(outcomes);
76
+ const allViolations = [...categorized.blocking, ...categorized.warnings, ...categorized.other];
77
+ for (const v of allViolations) {
78
+ await emitTurnEvent(ctx.bindings.onEvent, {
79
+ kind: 'guardrail.violated',
80
+ action: v.action,
81
+ severity: v.severity,
82
+ guardrailId: v.guardrailId,
83
+ ...(v.result.reason !== undefined && { reason: v.result.reason }),
84
+ });
85
+ if (ctx.provenance !== undefined) {
86
+ ctx.provenance.addNode({
87
+ id: `guardrail-check:${v.guardrailId}`,
88
+ kind: 'guardrail-check',
89
+ timestamp: v.at,
90
+ attributes: {
91
+ guardrailId: v.guardrailId,
92
+ action: v.action,
93
+ severity: v.severity,
94
+ passed: false,
95
+ ...(v.result.reason !== undefined && { reason: v.result.reason }),
96
+ },
97
+ });
98
+ ctx.provenance.addEdge({
99
+ from: `guardrail-check:${v.guardrailId}`,
100
+ to: `model-output:${ctx.usage.steps}`,
101
+ kind: 'influenced-by',
102
+ });
103
+ }
104
+ }
105
+ if (categorized.blocking.length > 0) {
106
+ const message = describeBlockingViolations(categorized.blocking);
107
+ await emitTurnEvent(ctx.bindings.onEvent, {
108
+ kind: 'turn.failed',
109
+ conversationId: ctx.input.conversationId,
110
+ errorCode: 'guardrail-violation',
111
+ message,
112
+ });
113
+ throwAgentTurnFailure({
114
+ code: 'guardrail-violation',
115
+ message,
116
+ violations: categorized.blocking,
117
+ evaluationErrors: categorized.errors,
118
+ });
119
+ }
120
+ ctx.nonBlockingViolations = [...categorized.warnings, ...categorized.other];
121
+ return {
122
+ blocking: categorized.blocking.length,
123
+ warnings: categorized.warnings.length,
124
+ other: categorized.other.length,
125
+ };
126
+ };
127
+ }
128
+ //# sourceMappingURL=evaluate-guardrails.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evaluate-guardrails.js","sourceRoot":"","sources":["../../src/handlers/evaluate-guardrails.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { AgentTurnIterationOutput } from './context.js';
2
+ /**
3
+ * The agent loop's final iteration — the response the turn ends with.
4
+ * `nodeName` names the reading node in the failure message.
5
+ */
6
+ export declare function finalIteration(loopOutput: unknown, nodeName: string): AgentTurnIterationOutput;
7
+ //# sourceMappingURL=final-iteration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"final-iteration.d.ts","sourceRoot":"","sources":["../../src/handlers/final-iteration.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAG7D;;;GAGG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,wBAAwB,CAiB9F"}
@@ -0,0 +1,26 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ import { throwAgentTurnFailure } from './errors.js';
4
+ /**
5
+ * The agent loop's final iteration — the response the turn ends with.
6
+ * `nodeName` names the reading node in the failure message.
7
+ */
8
+ export function finalIteration(loopOutput, nodeName) {
9
+ const output = loopOutput;
10
+ if (output === undefined) {
11
+ throwAgentTurnFailure({
12
+ code: 'model-invocation-failed',
13
+ message: `${nodeName} received undefined loop output`,
14
+ cause: null,
15
+ });
16
+ }
17
+ if (output.finalOutput === undefined) {
18
+ throwAgentTurnFailure({
19
+ code: 'model-invocation-failed',
20
+ message: `${nodeName} received loop output without finalOutput`,
21
+ cause: null,
22
+ });
23
+ }
24
+ return output.finalOutput;
25
+ }
26
+ //# sourceMappingURL=final-iteration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"final-iteration.js","sourceRoot":"","sources":["../../src/handlers/final-iteration.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAKjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEpD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,UAAmB,EAAE,QAAgB;IAClE,MAAM,MAAM,GAAG,UAAkE,CAAC;IAClF,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,qBAAqB,CAAC;YACpB,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,GAAG,QAAQ,iCAAiC;YACrD,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;IACL,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACrC,qBAAqB,CAAC;YACpB,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,GAAG,QAAQ,2CAA2C;YAC/D,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;IACL,CAAC;IACD,OAAO,MAAM,CAAC,WAAW,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,5 @@
1
+ import type { HandlerRegistry } from '@kindgi/handler';
2
+ import type { TurnContext } from './context.js';
3
+ export declare function buildHandlers(ctx: TurnContext): HandlerRegistry;
4
+ export type { TurnContext };
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAe,MAAM,iBAAiB,CAAC;AAsBpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAahD,wBAAgB,aAAa,CAAC,GAAG,EAAE,WAAW,GAAG,eAAe,CAsB/D;AAED,YAAY,EAAE,WAAW,EAAE,CAAC"}
@@ -0,0 +1,41 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ import { AGENT_LOOP_NODE, BUDGET_CHECK_NODE, BUILD_INITIAL_MESSAGES_NODE, COMPOSE_RESULT_NODE, DISPATCH_TOOLS_NODE, EVALUATE_GUARDRAILS_NODE, MODEL_CALL_NODE, PERSIST_FINAL_MESSAGE_NODE, PERSIST_PROVENANCE_NODE, PERSIST_USER_MESSAGE_NODE, RENDER_PROMPT_NODE, RUN_RETRIEVALS_NODE, SETUP_NODE, } from '../agent-turn-flow.js';
4
+ import { buildBudgetCheckHandler } from './budget-check.js';
5
+ import { buildBuildInitialMessagesHandler } from './build-initial-messages.js';
6
+ import { buildComposeResultHandler } from './compose-result.js';
7
+ import { buildDispatchToolsHandler } from './dispatch-tools.js';
8
+ import { buildEvaluateGuardrailsHandler } from './evaluate-guardrails.js';
9
+ import { buildModelCallHandler } from './model-call.js';
10
+ import { buildPersistFinalMessageHandler } from './persist-final-message.js';
11
+ import { buildPersistProvenanceHandler } from './persist-provenance.js';
12
+ import { buildPersistUserMessageHandler } from './persist-user-message.js';
13
+ import { buildRenderPromptHandler } from './render-prompt.js';
14
+ import { buildRunRetrievalsHandler } from './run-retrievals.js';
15
+ import { buildSetupHandler } from './setup.js';
16
+ // `agent-loop` is a kernel loop node — the executor dispatches it
17
+ // internally; only body-node handlers are registered.
18
+ export function buildHandlers(ctx) {
19
+ const entries = [
20
+ [SETUP_NODE, buildSetupHandler(ctx)],
21
+ [RENDER_PROMPT_NODE, buildRenderPromptHandler(ctx)],
22
+ [PERSIST_USER_MESSAGE_NODE, buildPersistUserMessageHandler(ctx)],
23
+ [RUN_RETRIEVALS_NODE, buildRunRetrievalsHandler(ctx)],
24
+ [BUILD_INITIAL_MESSAGES_NODE, buildBuildInitialMessagesHandler(ctx)],
25
+ [MODEL_CALL_NODE, buildModelCallHandler(ctx)],
26
+ [DISPATCH_TOOLS_NODE, buildDispatchToolsHandler(ctx)],
27
+ [BUDGET_CHECK_NODE, buildBudgetCheckHandler(ctx)],
28
+ [PERSIST_FINAL_MESSAGE_NODE, buildPersistFinalMessageHandler(ctx)],
29
+ [EVALUATE_GUARDRAILS_NODE, buildEvaluateGuardrailsHandler(ctx)],
30
+ [PERSIST_PROVENANCE_NODE, buildPersistProvenanceHandler(ctx)],
31
+ [COMPOSE_RESULT_NODE, buildComposeResultHandler(ctx)],
32
+ ];
33
+ // Assert `agent-loop` isn't accidentally registered — the runtime's
34
+ // flow executor rejects handlers for internal-dispatch nodes at load
35
+ // time. Sanity check for regressions.
36
+ if (entries.some(([id]) => id === AGENT_LOOP_NODE)) {
37
+ throw new Error('agent-loop must not have a handler — it is dispatched by the kernel');
38
+ }
39
+ return new Map(entries);
40
+ }
41
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,iCAAiC;AAKjC,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,2BAA2B,EAC3B,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EACxB,eAAe,EACf,0BAA0B,EAC1B,uBAAuB,EACvB,yBAAyB,EACzB,kBAAkB,EAClB,mBAAmB,EACnB,UAAU,GACX,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,EAAE,gCAAgC,EAAE,MAAM,6BAA6B,CAAC;AAC/E,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAEhE,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,8BAA8B,EAAE,MAAM,0BAA0B,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,+BAA+B,EAAE,MAAM,4BAA4B,CAAC;AAC7E,OAAO,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,8BAA8B,EAAE,MAAM,2BAA2B,CAAC;AAC3E,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE/C,kEAAkE;AAClE,sDAAsD;AACtD,MAAM,UAAU,aAAa,CAAC,GAAgB;IAC5C,MAAM,OAAO,GAA4B;QACvC,CAAC,UAAoB,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAC9C,CAAC,kBAA4B,EAAE,wBAAwB,CAAC,GAAG,CAAC,CAAC;QAC7D,CAAC,yBAAmC,EAAE,8BAA8B,CAAC,GAAG,CAAC,CAAC;QAC1E,CAAC,mBAA6B,EAAE,yBAAyB,CAAC,GAAG,CAAC,CAAC;QAC/D,CAAC,2BAAqC,EAAE,gCAAgC,CAAC,GAAG,CAAC,CAAC;QAC9E,CAAC,eAAyB,EAAE,qBAAqB,CAAC,GAAG,CAAC,CAAC;QACvD,CAAC,mBAA6B,EAAE,yBAAyB,CAAC,GAAG,CAAC,CAAC;QAC/D,CAAC,iBAA2B,EAAE,uBAAuB,CAAC,GAAG,CAAC,CAAC;QAC3D,CAAC,0BAAoC,EAAE,+BAA+B,CAAC,GAAG,CAAC,CAAC;QAC5E,CAAC,wBAAkC,EAAE,8BAA8B,CAAC,GAAG,CAAC,CAAC;QACzE,CAAC,uBAAiC,EAAE,6BAA6B,CAAC,GAAG,CAAC,CAAC;QACvE,CAAC,mBAA6B,EAAE,yBAAyB,CAAC,GAAG,CAAC,CAAC;KAChE,CAAC;IACF,oEAAoE;IACpE,qEAAqE;IACrE,sCAAsC;IACtC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,KAAM,eAA0B,CAAC,EAAE,CAAC;QAC/D,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { NodeHandler } from '@kindgi/handler';
2
+ import type { TurnContext } from './context.js';
3
+ /**
4
+ * Loop-body node #1. Invoke the model with the current
5
+ * `nextMessages` accumulator. Emits `model.call.started` +
6
+ * `model.call.completed`, records provenance for the model-call node,
7
+ * and accumulates usage on `ctx.usage`.
8
+ *
9
+ * Output is a partial `AgentTurnIterationOutput` — `dispatch-tools`
10
+ * receives it and finishes composing the iteration output.
11
+ */
12
+ export declare function buildModelCallHandler(ctx: TurnContext): NodeHandler;
13
+ //# sourceMappingURL=model-call.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-call.d.ts","sourceRoot":"","sources":["../../src/handlers/model-call.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAInD,OAAO,KAAK,EAA4B,WAAW,EAAE,MAAM,cAAc,CAAC;AAG1E;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,WAAW,GAAG,WAAW,CAwHnE"}
@@ -0,0 +1,136 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ import { emitTurnEvent } from '../streaming.js';
4
+ import { throwAgentTurnFailure } from './errors.js';
5
+ /**
6
+ * Loop-body node #1. Invoke the model with the current
7
+ * `nextMessages` accumulator. Emits `model.call.started` +
8
+ * `model.call.completed`, records provenance for the model-call node,
9
+ * and accumulates usage on `ctx.usage`.
10
+ *
11
+ * Output is a partial `AgentTurnIterationOutput` — `dispatch-tools`
12
+ * receives it and finishes composing the iteration output.
13
+ */
14
+ export function buildModelCallHandler(ctx) {
15
+ return async (input, kctx) => {
16
+ if (ctx.provider === undefined || ctx.model === undefined || ctx.tools === undefined) {
17
+ throwAgentTurnFailure({
18
+ code: 'model-invocation-failed',
19
+ message: 'model-call invoked before setup completed',
20
+ cause: null,
21
+ });
22
+ }
23
+ const shaped = input;
24
+ const nextMessages = shaped?.nextMessages ?? [];
25
+ ctx.usage.steps += 1;
26
+ await emitTurnEvent(ctx.bindings.onEvent, {
27
+ kind: 'model.call.started',
28
+ step: ctx.usage.steps,
29
+ providerId: ctx.provider.metadata.id,
30
+ model: ctx.model.name,
31
+ });
32
+ let callResult;
33
+ if (kctx.dryRun) {
34
+ // Dry-run: skip the network call. Return a schema-conformant
35
+ // mock indicating the model would have terminated cleanly. The
36
+ // mock requests no tools, so a dry run does not preview tool
37
+ // planning.
38
+ callResult = {
39
+ finishReason: 'stop',
40
+ message: { role: 'assistant', content: '[dry-run: model call skipped]' },
41
+ usage: { promptTokens: 0, completionTokens: 0 },
42
+ costUsd: 0,
43
+ durationMs: 0,
44
+ provider: { id: ctx.provider.metadata.id, model: ctx.model.name },
45
+ };
46
+ }
47
+ else {
48
+ const callInput = {
49
+ model: ctx.model.name,
50
+ messages: nextMessages,
51
+ ...(ctx.tools.definitions.length > 0 && {
52
+ tools: ctx.tools.definitions,
53
+ }),
54
+ abortSignal: ctx.turnAbort.signal,
55
+ };
56
+ try {
57
+ callResult = await ctx.provider.invoke(callInput);
58
+ }
59
+ catch (cause) {
60
+ if (ctx.turnAbort.signal.aborted) {
61
+ throwAgentTurnFailure({
62
+ code: 'agent-turn-aborted',
63
+ message: `Agent turn aborted: ${cause instanceof Error ? cause.message : String(cause)}`,
64
+ reason: ctx.abortReason ?? 'timeout',
65
+ });
66
+ }
67
+ // The provider's own words (a 401's "invalid x-api-key", a 429)
68
+ // are what the caller needs; they're in `cause` too, but callers
69
+ // show `message`.
70
+ throwAgentTurnFailure({
71
+ code: 'model-invocation-failed',
72
+ message: `Model call to ${ctx.provider.metadata.id} (${ctx.model.name}) failed: ${describeCause(cause)}`,
73
+ cause,
74
+ });
75
+ }
76
+ }
77
+ ctx.usage.promptTokens += callResult.usage.promptTokens;
78
+ ctx.usage.completionTokens += callResult.usage.completionTokens;
79
+ ctx.usage.totalCostUsd += callResult.costUsd;
80
+ ctx.lastProvider = callResult.provider;
81
+ await emitTurnEvent(ctx.bindings.onEvent, {
82
+ kind: 'model.call.completed',
83
+ step: ctx.usage.steps,
84
+ finishReason: callResult.finishReason,
85
+ promptTokens: callResult.usage.promptTokens,
86
+ completionTokens: callResult.usage.completionTokens,
87
+ costUsd: callResult.costUsd,
88
+ durationMs: callResult.durationMs,
89
+ });
90
+ if (ctx.provenance !== undefined && ctx.userMessage !== undefined) {
91
+ const modelCallNodeId = `model-call:${ctx.usage.steps}`;
92
+ ctx.provenance.addNode({
93
+ id: modelCallNodeId,
94
+ kind: 'model-call',
95
+ timestamp: new Date().toISOString(),
96
+ modelVersion: `${callResult.provider.id}/${callResult.provider.model}`,
97
+ attributes: {
98
+ step: ctx.usage.steps,
99
+ promptTokens: callResult.usage.promptTokens,
100
+ completionTokens: callResult.usage.completionTokens,
101
+ costUsd: callResult.costUsd,
102
+ finishReason: callResult.finishReason,
103
+ },
104
+ });
105
+ ctx.provenance.addEdge({
106
+ from: modelCallNodeId,
107
+ to: `input:${ctx.userMessage.sequence}`,
108
+ kind: 'caused-by',
109
+ });
110
+ }
111
+ // Partial iteration output — `dispatch-tools` finishes it.
112
+ const partial = {
113
+ step: ctx.usage.steps,
114
+ finishReason: callResult.finishReason,
115
+ message: callResult.message,
116
+ iterationUsage: {
117
+ promptTokens: callResult.usage.promptTokens,
118
+ completionTokens: callResult.usage.completionTokens,
119
+ costUsd: callResult.costUsd,
120
+ },
121
+ provider: callResult.provider,
122
+ nextMessages,
123
+ };
124
+ return partial;
125
+ };
126
+ }
127
+ /** Longest cause text a failure message carries. */
128
+ const MAX_CAUSE_CHARS = 500;
129
+ /** A thrown value's message on one line, at most `MAX_CAUSE_CHARS` long. */
130
+ function describeCause(cause) {
131
+ const text = (cause instanceof Error ? cause.message : String(cause)).replace(/\s+/g, ' ').trim();
132
+ if (text.length === 0)
133
+ return cause instanceof Error ? cause.name : 'no detail';
134
+ return text.length > MAX_CAUSE_CHARS ? `${text.slice(0, MAX_CAUSE_CHARS - 1)}…` : text;
135
+ }
136
+ //# sourceMappingURL=model-call.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-call.js","sourceRoot":"","sources":["../../src/handlers/model-call.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { NodeHandler } from '@kindgi/handler';
2
+ import type { TurnContext } from './context.js';
3
+ /**
4
+ * Persist the turn's terminal assistant message (non-intermediate —
5
+ * increments `turnCount`). Runs after `evaluate-guardrails`, so only a
6
+ * response that no `halt` guardrail rejected is stored. Reads the
7
+ * response from the agent loop's output.
8
+ *
9
+ * Dry-run branch: skips the DB write; builds a synthetic
10
+ * `ConversationMessage` with `sequence: -1`. `turnCount` is NOT
11
+ * incremented (no persistence happened).
12
+ */
13
+ export declare function buildPersistFinalMessageHandler(ctx: TurnContext): NodeHandler;
14
+ //# sourceMappingURL=persist-final-message.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persist-final-message.d.ts","sourceRoot":"","sources":["../../src/handlers/persist-final-message.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAOnD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAIhD;;;;;;;;;GASG;AACH,wBAAgB,+BAA+B,CAAC,GAAG,EAAE,WAAW,GAAG,WAAW,CA0C7E"}
@@ -0,0 +1,54 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+ import { AGENT_LOOP_NODE } from '../agent-turn-flow.js';
4
+ import { emitTurnEvent } from '../streaming.js';
5
+ import { throwAgentTurnFailure } from './errors.js';
6
+ import { finalIteration } from './final-iteration.js';
7
+ /**
8
+ * Persist the turn's terminal assistant message (non-intermediate —
9
+ * increments `turnCount`). Runs after `evaluate-guardrails`, so only a
10
+ * response that no `halt` guardrail rejected is stored. Reads the
11
+ * response from the agent loop's output.
12
+ *
13
+ * Dry-run branch: skips the DB write; builds a synthetic
14
+ * `ConversationMessage` with `sequence: -1`. `turnCount` is NOT
15
+ * incremented (no persistence happened).
16
+ */
17
+ export function buildPersistFinalMessageHandler(ctx) {
18
+ return async (_input, kctx) => {
19
+ const final = finalIteration(kctx.nodeOutputs.get(AGENT_LOOP_NODE), 'persist-final-message');
20
+ const assistantMsg = final.message;
21
+ let finalMessage;
22
+ if (kctx.dryRun) {
23
+ finalMessage = {
24
+ sequence: -1,
25
+ role: 'agent',
26
+ content: assistantMsg.content ?? '',
27
+ createdAt: new Date().toISOString(),
28
+ actor: ctx.input.agent.id,
29
+ };
30
+ }
31
+ else {
32
+ const persist = await ctx.bindings.conversationBinding.appendMessage({
33
+ tenantId: ctx.input.tenantId,
34
+ conversationId: ctx.input.conversationId,
35
+ role: 'agent',
36
+ content: assistantMsg.content ?? '',
37
+ actor: ctx.input.agent.id,
38
+ });
39
+ if (persist.kind === 'err')
40
+ throwAgentTurnFailure(persist.error);
41
+ finalMessage = persist.value;
42
+ }
43
+ ctx.appended.push(finalMessage);
44
+ ctx.finalMessage = finalMessage;
45
+ await emitTurnEvent(ctx.bindings.onEvent, {
46
+ kind: 'agent.message',
47
+ step: ctx.usage.steps,
48
+ isFinal: true,
49
+ message: finalMessage,
50
+ });
51
+ return { sequence: finalMessage.sequence };
52
+ };
53
+ }
54
+ //# sourceMappingURL=persist-final-message.js.map