@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
package/src/index.ts ADDED
@@ -0,0 +1,154 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+
4
+ export type {
5
+ AppendMessageInput,
6
+ ConversationBinding,
7
+ ConversationPage,
8
+ ConversationPageCursor,
9
+ ListConversationsInput,
10
+ ListConversationsPageInput,
11
+ OpenConversationInput,
12
+ ReadMessagesInput,
13
+ } from './conversation-binding.js';
14
+ export type {
15
+ RunSnapshotBinding,
16
+ RunSnapshotRecord,
17
+ RunSnapshotWriteInput,
18
+ } from './run-snapshot-binding.js';
19
+ export { defineAgent } from './define.js';
20
+ export type { DefineAgentSpec } from './define.js';
21
+ export { resolveEffectiveHitlPolicy } from './hitl-policy.js';
22
+ export type { EffectiveHitlPolicy } from './hitl-policy.js';
23
+ export { agentStepOutput, invokeAgent, resumeAgentTurn } from './invoke.js';
24
+ export type {
25
+ AgentStepOutput,
26
+ AgentTurnAbortedError,
27
+ AgentTurnResult,
28
+ AgentTurnUsage,
29
+ AgentTurnWarning,
30
+ BudgetExceededError,
31
+ CapabilityRoutingError,
32
+ InvokeAgentBindings,
33
+ InvokeAgentError,
34
+ InvokeAgentInput,
35
+ ModelInvocationError,
36
+ OutputSchemaViolationError,
37
+ ResumeAgentTurnInput,
38
+ ToolInvocationError,
39
+ UnresolvedToolError,
40
+ } from './invoke.js';
41
+ export {
42
+ buildRunTrace,
43
+ categorizeOutcomes,
44
+ evaluateGate,
45
+ evaluateSessionGate,
46
+ resolveGuardrails,
47
+ } from './guardrails-gate.js';
48
+ export type {
49
+ HitlRequiredError,
50
+ GuardrailViolationError,
51
+ GuardrailsBindings,
52
+ SessionGateResult,
53
+ UnresolvedGuardrailError,
54
+ } from './guardrails-gate.js';
55
+ export { persistProvenance } from './provenance-emit.js';
56
+ export type { ProvenanceBindings } from './provenance-emit.js';
57
+ export type {
58
+ AgentMessageEvent,
59
+ GuardrailViolatedEvent,
60
+ ModelCallCompletedEvent,
61
+ ModelCallStartedEvent,
62
+ OnTurnEvent,
63
+ RetrievalCompletedEvent,
64
+ ToolCompletedEvent,
65
+ ToolFailedEvent,
66
+ ToolStartedEvent,
67
+ TurnCompletedEvent,
68
+ TurnEvent,
69
+ TurnFailedEvent,
70
+ TurnStartedEvent,
71
+ } from './streaming.js';
72
+ export { AUTO_INJECTED_VARS, renderInstructions } from './prompt.js';
73
+ export { formatRetrievedForPrompt, runRetrievals } from './retrieval.js';
74
+ export type { RetrievalBindings } from './retrieval.js';
75
+ export type {
76
+ MissingParameterError,
77
+ PromptRenderError,
78
+ RenderContext,
79
+ RenderFailureError,
80
+ RenderResult,
81
+ } from './prompt.js';
82
+ export { createAgentRegistry } from './registry.js';
83
+ export type { AgentRegistry } from './registry.js';
84
+ export {
85
+ AGENTS_TENANT_SCOPED_TABLES,
86
+ agentConversations,
87
+ agentRunSnapshots,
88
+ } from './schema.js';
89
+ export type {
90
+ AgentConversationRow,
91
+ AgentRunSnapshotRow,
92
+ NewAgentConversationRow,
93
+ NewAgentRunSnapshotRow,
94
+ } from './schema.js';
95
+ export type {
96
+ Agent,
97
+ AgentBindings,
98
+ AgentId,
99
+ AgentOutputSpec,
100
+ Conversation,
101
+ ConversationId,
102
+ ConversationMessage,
103
+ ConversationPolicy,
104
+ MessageRole,
105
+ PromptParameter,
106
+ RetrievalIntent,
107
+ RetrievedFact,
108
+ ToolRef,
109
+ TurnBudget,
110
+ } from './types.js';
111
+ export { DEFAULT_TOOL_ERRORS, effectiveToolErrorPolicy } from './handlers/tool-errors.js';
112
+ export type { ToolErrorPolicy, ToolErrorResult } from './handlers/tool-errors.js';
113
+ export type { ToolErrorKind, ToolErrorsSpec } from '@kindgi/policy-contract';
114
+ export type {
115
+ AgentAlreadyRegisteredError,
116
+ AgentError,
117
+ AgentNotFoundError,
118
+ AgentVersionMismatchError,
119
+ ConversationClosedError,
120
+ ConversationNotFoundError,
121
+ InvalidAgentError,
122
+ InvalidMessageError,
123
+ PersistenceError,
124
+ } from './errors.js';
125
+ export { CURRENT_AGENTS_PAYLOAD_VERSION, unwrap, unwrapOrThrow, wrap } from './versioning.js';
126
+ export type {
127
+ EnvelopeError,
128
+ MalformedEnvelopeError,
129
+ UnsupportedPayloadVersionError,
130
+ } from './versioning.js';
131
+ export { AGENTS_MIGRATIONS_DIR } from './migrations-dir.js';
132
+
133
+ // ============ Built-in agent-turn flow ============
134
+ // The flow every agent turn runs on, plus its node IDs — the same IDs
135
+ // that appear in run journals, exported so consumers can match on them.
136
+ export {
137
+ AGENT_LOOP_NODE,
138
+ AGENT_TURN_FLOW,
139
+ AGENT_TURN_FLOW_ID,
140
+ AGENT_TURN_FLOW_VERSION,
141
+ AGENT_TURN_LOOP_MAX_ITERATIONS,
142
+ BUDGET_CHECK_NODE,
143
+ BUILD_INITIAL_MESSAGES_NODE,
144
+ COMPOSE_RESULT_NODE,
145
+ DISPATCH_TOOLS_NODE,
146
+ EVALUATE_GUARDRAILS_NODE,
147
+ MODEL_CALL_NODE,
148
+ PERSIST_FINAL_MESSAGE_NODE,
149
+ PERSIST_PROVENANCE_NODE,
150
+ PERSIST_USER_MESSAGE_NODE,
151
+ RENDER_PROMPT_NODE,
152
+ RUN_RETRIEVALS_NODE,
153
+ SETUP_NODE,
154
+ } from './agent-turn-flow.js';
package/src/invoke.ts ADDED
@@ -0,0 +1,299 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+
4
+ import type { Principal } from '@kindgi/authz';
5
+ import type { KernelError, RunResult } from '@kindgi/runtime';
6
+ import type { Result, RunId, TenantId } from '@kindgi/types';
7
+
8
+ import { AGENT_TURN_FLOW } from './agent-turn-flow.js';
9
+ import { DEFAULT_MAX_WALL_MS } from './handlers/constants.js';
10
+ import type { TurnContext } from './handlers/context.js';
11
+ import { AgentTurnFailure, type InvokeAgentError } from './handlers/errors.js';
12
+ import { buildHandlers } from './handlers/index.js';
13
+ import type { InvokeAgentBindings, InvokeAgentInput } from './handlers/public-types.js';
14
+ import { rehydrateTurnContext } from './handlers/rehydrate.js';
15
+ import type { AgentTurnResult } from './handlers/result-shape.js';
16
+ import { projectRunResult } from './project-run-result.js';
17
+ import type { Agent } from './types.js';
18
+
19
+ /**
20
+ * Execute one agent turn end-to-end as a flow run: one `runGraph`
21
+ * invocation (through `bindings.runBinding`) against
22
+ * `AGENT_TURN_FLOW`; handler modules under `./handlers/` implement
23
+ * each node. The run's outcome is projected back to an
24
+ * `AgentTurnResult` or an `InvokeAgentError`.
25
+ *
26
+ * Budgets enforced (all optional, all take agent-declared defaults):
27
+ * - `agent.budget.maxSteps` — cap on model↔tool iterations (default 8).
28
+ * - `agent.budget.maxCostUsd` — cumulative USD across model calls.
29
+ * - `agent.budget.maxWallMs` — wall-clock cap; combined with abortSignal.
30
+ */
31
+ export async function invokeAgent(
32
+ input: InvokeAgentInput,
33
+ bindings: InvokeAgentBindings,
34
+ ): Promise<Result<AgentTurnResult, InvokeAgentError>> {
35
+ const started = Date.now();
36
+ const maxWallMs = input.agent.budget?.maxWallMs ?? DEFAULT_MAX_WALL_MS;
37
+ const controller = new AbortController();
38
+ const ctx: TurnContext = {
39
+ input,
40
+ bindings,
41
+ turnAbort: controller,
42
+ startedAt: started,
43
+ appended: [],
44
+ usage: {
45
+ steps: 0,
46
+ promptTokens: 0,
47
+ completionTokens: 0,
48
+ totalCostUsd: 0,
49
+ },
50
+ abortReason: undefined,
51
+ };
52
+ const timer = setTimeout(() => {
53
+ ctx.abortReason = 'timeout';
54
+ controller.abort(new Error('wall-clock budget exhausted'));
55
+ }, maxWallMs);
56
+ if (input.abortSignal !== undefined) {
57
+ const external = input.abortSignal;
58
+ if (external.aborted) {
59
+ ctx.abortReason = 'external';
60
+ controller.abort(external.reason);
61
+ } else {
62
+ external.addEventListener('abort', () => {
63
+ ctx.abortReason = 'external';
64
+ controller.abort(external.reason);
65
+ });
66
+ }
67
+ }
68
+
69
+ try {
70
+ const handlers = buildHandlers(ctx);
71
+ if (bindings.runBinding === undefined) {
72
+ throw new Error(
73
+ 'invokeAgent: bindings.runBinding is required — pass the RunBinding (from @kindgi/runtime) of the runtime that executes the turn.',
74
+ );
75
+ }
76
+ const runResult: Result<
77
+ RunResult<AgentTurnResult>,
78
+ KernelError
79
+ > = await bindings.runBinding.runGraph<AgentTurnResult>({
80
+ tenantId: input.tenantId,
81
+ projectId: input.projectId,
82
+ flow: AGENT_TURN_FLOW,
83
+ handlers,
84
+ input: input.userMessage,
85
+ ...(input.parent !== undefined && { parent: input.parent }),
86
+ ...(input.dryRun === true && { options: { dryRun: true } }),
87
+ // Authorization — carry principal + authz into the run so every
88
+ // tool invocation inside the agent's turn is checked.
89
+ ...(input.principal !== undefined && { principal: input.principal }),
90
+ ...(input.authz !== undefined && { authz: input.authz }),
91
+ });
92
+ return await projectRunResult(runResult, ctx);
93
+ } finally {
94
+ clearTimeout(timer);
95
+ }
96
+ }
97
+
98
+ export interface ResumeAgentTurnInput {
99
+ readonly tenantId: TenantId;
100
+ readonly runId: RunId;
101
+ /**
102
+ * The agent spec resolved at the target version. Callers of
103
+ * `resumeAgentTurn` are responsible for resolving `agentId +
104
+ * agentVersion` from the run snapshot against their agent registry
105
+ * (replay must match the version the run started on — see the setup
106
+ * handler's agent-version-mismatch guard).
107
+ */
108
+ readonly agent: Agent;
109
+ }
110
+
111
+ /**
112
+ * Resume a suspended agent turn — invoked after a kernel waitpoint
113
+ * resolves (e.g. a HITL approval completes). Loads the reconstruction
114
+ * snapshot written by the setup handler, rebuilds an equivalent
115
+ * `InvokeAgentInput` + `TurnContext`, then calls
116
+ * `bindings.runBinding.resumeRun`, which replays the flow from the
117
+ * journal.
118
+ *
119
+ * Same runId, same conversationId, same provenance record across the
120
+ * park-and-resume cycle. Any handler that was mid-execution when the
121
+ * wait suspended runs again from the top; `ctx.waitForToken` returns
122
+ * the resolved value from derived state instead of throwing another
123
+ * SuspensionSignal.
124
+ *
125
+ * Fails with `run-snapshot-missing` when no snapshot exists for the
126
+ * runId — this happens when the setup handler's snapshot write failed
127
+ * (the write is best-effort). Recovery: cancel the run explicitly;
128
+ * there is no way to reconstruct the InvokeAgentInput without the
129
+ * snapshot.
130
+ */
131
+ /**
132
+ * Rebuild a resumed turn's context from its journal (see
133
+ * `rehydrateTurnContext`). Returns the turn's error when it can't be
134
+ * rebuilt; `undefined` to go on and resume.
135
+ */
136
+ async function rehydrateFromJournal(
137
+ ctx: TurnContext,
138
+ runId: RunId,
139
+ runBinding: NonNullable<InvokeAgentBindings['runBinding']>,
140
+ ): Promise<Result<AgentTurnResult, InvokeAgentError> | undefined> {
141
+ const journal = await runBinding.readJournal(ctx.input.tenantId, runId);
142
+ if (journal.kind === 'err') {
143
+ return {
144
+ kind: 'err',
145
+ error: {
146
+ code: 'run-journal-unavailable',
147
+ message: `Failed to read the journal of run ${runId as unknown as string}: ${journal.error.message}`,
148
+ } as never,
149
+ };
150
+ }
151
+ try {
152
+ await rehydrateTurnContext(ctx, runId as unknown as string, journal.value);
153
+ return undefined;
154
+ } catch (cause) {
155
+ if (cause instanceof AgentTurnFailure) return { kind: 'err', error: cause.payload };
156
+ throw cause;
157
+ }
158
+ }
159
+
160
+ export async function resumeAgentTurn(
161
+ input: ResumeAgentTurnInput,
162
+ bindings: InvokeAgentBindings,
163
+ ): Promise<Result<AgentTurnResult, InvokeAgentError>> {
164
+ // 1. Load the snapshot via the run-snapshot binding.
165
+ const snapshotResult = await bindings.runSnapshotBinding.read(input.tenantId, input.runId);
166
+ if (snapshotResult.kind === 'err') {
167
+ return {
168
+ kind: 'err',
169
+ error: {
170
+ code: 'run-snapshot-missing',
171
+ message: `Failed to load run snapshot for run ${input.runId as unknown as string}: ${snapshotResult.error.message}`,
172
+ } as never,
173
+ };
174
+ }
175
+ const snapshot = snapshotResult.value;
176
+ if (snapshot === null) {
177
+ return {
178
+ kind: 'err',
179
+ error: {
180
+ code: 'run-snapshot-missing',
181
+ message: `No run snapshot for run ${input.runId as unknown as string} — resume-context unavailable.`,
182
+ } as never,
183
+ };
184
+ }
185
+
186
+ // 2. Agent-version sanity check — the caller passes the Agent spec they
187
+ // resolved via the registry; we refuse if it doesn't match the pinned
188
+ // version in the snapshot. Mirrors the setup handler's guard.
189
+ if (
190
+ (snapshot.agentId as unknown as string) !== (input.agent.id as unknown as string) ||
191
+ snapshot.agentVersion !== input.agent.version
192
+ ) {
193
+ return {
194
+ kind: 'err',
195
+ error: {
196
+ code: 'agent-version-mismatch',
197
+ message: `Snapshot pinned to ${snapshot.agentId as unknown as string}@${snapshot.agentVersion}; resume called with ${input.agent.id as unknown as string}@${input.agent.version as unknown as string}`,
198
+ expectedVersion: snapshot.agentVersion,
199
+ actualVersion: input.agent.version,
200
+ } as never,
201
+ };
202
+ }
203
+
204
+ // 3. Reconstruct the InvokeAgentInput envelope from the snapshot.
205
+ const reconstructedInput: InvokeAgentInput = {
206
+ tenantId: snapshot.tenantId,
207
+ projectId: snapshot.projectId,
208
+ agent: input.agent,
209
+ conversationId: snapshot.conversationId,
210
+ userMessage: snapshot.userMessage,
211
+ ...(snapshot.parameters !== undefined && { parameters: snapshot.parameters }),
212
+ ...(snapshot.input !== undefined && { input: snapshot.input }),
213
+ ...(snapshot.participantId !== undefined && { participantId: snapshot.participantId }),
214
+ ...(snapshot.dryRun && { dryRun: true }),
215
+ ...(snapshot.principal !== undefined &&
216
+ snapshot.principal !== null && {
217
+ principal: snapshot.principal as Principal,
218
+ }),
219
+ ...(snapshot.authz !== undefined &&
220
+ snapshot.authz !== null && {
221
+ authz: snapshot.authz as { readonly fgaApiUrl: string },
222
+ }),
223
+ };
224
+
225
+ // 4. Build the same TurnContext + handlers as invokeAgent().
226
+ const started = Date.now();
227
+ const maxWallMs = input.agent.budget?.maxWallMs ?? DEFAULT_MAX_WALL_MS;
228
+ const controller = new AbortController();
229
+ const ctx: TurnContext = {
230
+ input: reconstructedInput,
231
+ bindings,
232
+ turnAbort: controller,
233
+ startedAt: started,
234
+ appended: [],
235
+ usage: {
236
+ steps: 0,
237
+ promptTokens: 0,
238
+ completionTokens: 0,
239
+ totalCostUsd: 0,
240
+ },
241
+ abortReason: undefined,
242
+ };
243
+ const timer = setTimeout(() => {
244
+ ctx.abortReason = 'timeout';
245
+ controller.abort(new Error('wall-clock budget exhausted'));
246
+ }, maxWallMs);
247
+
248
+ try {
249
+ const handlers = buildHandlers(ctx);
250
+ if (bindings.runBinding === undefined) {
251
+ throw new Error('resumeAgentTurn: bindings.runBinding is required.');
252
+ }
253
+ // The kernel won't re-run the steps that completed before the park,
254
+ // and they kept their state on the in-memory context: rebuild it.
255
+ const rehydrated = await rehydrateFromJournal(ctx, input.runId, bindings.runBinding);
256
+ if (rehydrated !== undefined) return rehydrated;
257
+ const runResult: Result<
258
+ RunResult<AgentTurnResult>,
259
+ KernelError
260
+ > = await bindings.runBinding.resumeRun<AgentTurnResult>({
261
+ tenantId: reconstructedInput.tenantId,
262
+ runId: input.runId,
263
+ flow: AGENT_TURN_FLOW,
264
+ handlers,
265
+ });
266
+ return await projectRunResult(runResult, ctx);
267
+ } finally {
268
+ clearTimeout(timer);
269
+ }
270
+ }
271
+
272
+ // ============ public API re-exports ============
273
+ // The public types live under `./handlers/`; index.ts re-exports them
274
+ // from here.
275
+
276
+ export type {
277
+ AgentStepOutput,
278
+ AgentTurnResult,
279
+ AgentTurnUsage,
280
+ AgentTurnWarning,
281
+ } from './handlers/result-shape.js';
282
+ export { agentStepOutput } from './handlers/result-shape.js';
283
+ export type {
284
+ AgentTurnAbortedError,
285
+ BudgetExceededError,
286
+ CapabilityRoutingError,
287
+ InvokeAgentError,
288
+ ModelInvocationError,
289
+ OutputSchemaViolationError,
290
+ ToolInvocationError,
291
+ UnresolvedToolError,
292
+ } from './handlers/errors.js';
293
+ export type {
294
+ HitlBindings,
295
+ HitlEnqueueInput,
296
+ HitlEnqueueResult,
297
+ InvokeAgentBindings,
298
+ InvokeAgentInput,
299
+ } from './handlers/public-types.js';
@@ -0,0 +1,17 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+
4
+ import { fileURLToPath } from 'node:url';
5
+
6
+ /**
7
+ * Absolute path to the SQL migrations shipped with `@kindgi/agents`.
8
+ *
9
+ * Resolved from this module's own URL, so it is correct in every layout
10
+ * the package can be installed in (workspace checkout, a workspace in
11
+ * another repository, `node_modules`, `pnpm deploy` output) — from both
12
+ * `src/` and `dist/`. Migration runners use this instead of computing
13
+ * package-relative paths themselves.
14
+ */
15
+ export const AGENTS_MIGRATIONS_DIR: string = fileURLToPath(
16
+ new URL('../migrations/', import.meta.url),
17
+ );
@@ -0,0 +1,131 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (C) 2026 Kindgi Inc.
3
+
4
+ import type { KernelError, RunResult } from '@kindgi/runtime';
5
+ import type { Result } from '@kindgi/types';
6
+
7
+ import type { TurnContext } from './handlers/context.js';
8
+ import { parseFailureMessage } from './handlers/errors.js';
9
+ import type { InvokeAgentError } from './handlers/errors.js';
10
+ import type { AgentTurnResult } from './handlers/result-shape.js';
11
+ import { emitTurnEvent } from './streaming.js';
12
+
13
+ /**
14
+ * Translate a kernel `Result<RunResult, KernelError>` into the
15
+ * caller-facing `Result<AgentTurnResult, InvokeAgentError>`. Rules:
16
+ *
17
+ * - Kernel-level errors (`handler-missing`, `flow-mismatch`,
18
+ * `journal-error`, `stuck`, `run-not-found`, etc.) map to
19
+ * `model-invocation-failed` with the KernelError as cause.
20
+ * - Run status `completed` — output is the `AgentTurnResult`
21
+ * composed by `compose-result`; unwrap and return `Result.ok`.
22
+ * - Run status `failed` — `failureMessage` was serialized by
23
+ * `AgentTurnFailure` on the throwing handler; parse back into
24
+ * structured `InvokeAgentError`. Fall back to
25
+ * `model-invocation-failed` if the message isn't ours.
26
+ * - Run status `cancelled` — external abort. Use `ctx.abortReason`
27
+ * to distinguish external vs timeout.
28
+ */
29
+ export async function projectRunResult(
30
+ kernelResult: Result<RunResult<AgentTurnResult>, KernelError>,
31
+ ctx: TurnContext,
32
+ ): Promise<Result<AgentTurnResult, InvokeAgentError>> {
33
+ if (kernelResult.kind === 'err') {
34
+ return {
35
+ kind: 'err',
36
+ error: {
37
+ code: 'model-invocation-failed',
38
+ message: `Kernel run failed: ${kernelResult.error.message}`,
39
+ cause: kernelResult.error,
40
+ },
41
+ };
42
+ }
43
+
44
+ const run = kernelResult.value;
45
+ if (run.status === 'completed') {
46
+ if (run.output === undefined) {
47
+ return {
48
+ kind: 'err',
49
+ error: {
50
+ code: 'model-invocation-failed',
51
+ message: 'Agent-turn run completed without emitting a result',
52
+ cause: null,
53
+ },
54
+ };
55
+ }
56
+ return { kind: 'ok', value: { ...run.output, status: 'completed' } };
57
+ }
58
+
59
+ // Park-and-resume: the run suspended on a waitpoint (the setup
60
+ // handler's session-HITL gate or a tool-level gate in the
61
+ // dispatch-tools handler). Turn hasn't produced a response yet — the
62
+ // reviewer's decision will resume the flow, and the resumed run's
63
+ // completion produces the final AgentTurnResult in a follow-up call
64
+ // (via resumeAgentTurn). An HTTP caller surfaces status='suspended'
65
+ // to its client. Return a minimally-shaped AgentTurnResult so
66
+ // kind='ok' is honest — the parked run is a successful start, not a
67
+ // failure.
68
+ if (run.status === 'suspended') {
69
+ return {
70
+ kind: 'ok',
71
+ value: {
72
+ runId: run.runId,
73
+ conversationId: ctx.input.conversationId,
74
+ turnNumber: 0,
75
+ appended: [],
76
+ response: {
77
+ role: 'assistant',
78
+ content: '',
79
+ } as never,
80
+ retrieved: [],
81
+ violations: [],
82
+ usage: {
83
+ steps: 0,
84
+ promptTokens: 0,
85
+ completionTokens: 0,
86
+ totalCostUsd: 0,
87
+ durationMs: Date.now() - ctx.startedAt,
88
+ },
89
+ provider: { id: '', model: '' },
90
+ status: 'suspended',
91
+ },
92
+ };
93
+ }
94
+
95
+ if (run.status === 'cancelled') {
96
+ const err: InvokeAgentError = {
97
+ code: 'agent-turn-aborted',
98
+ message: `Agent turn cancelled${run.failureMessage !== undefined ? `: ${run.failureMessage}` : ''}`,
99
+ reason: ctx.abortReason ?? 'external',
100
+ };
101
+ await emitTurnEvent(ctx.bindings.onEvent, {
102
+ kind: 'turn.failed',
103
+ conversationId: ctx.input.conversationId,
104
+ errorCode: err.code,
105
+ message: err.message,
106
+ });
107
+ return { kind: 'err', error: err };
108
+ }
109
+
110
+ // Failed
111
+ const parsed = parseFailureMessage(run.failureMessage);
112
+ if (parsed !== undefined) {
113
+ // For failed runs, `turn.failed` is emitted only for guardrail
114
+ // violations, by the evaluate-guardrails handler — nothing to emit
115
+ // here.
116
+ if (parsed.code === 'guardrail-violation') {
117
+ // Already emitted by the evaluate-guardrails handler — skip.
118
+ }
119
+ return { kind: 'err', error: parsed };
120
+ }
121
+
122
+ // Unstructured failure — a bare exception the handlers didn't wrap.
123
+ return {
124
+ kind: 'err',
125
+ error: {
126
+ code: 'model-invocation-failed',
127
+ message: run.failureMessage ?? 'Agent turn failed',
128
+ cause: null,
129
+ },
130
+ };
131
+ }