@kindgi/agents 0.0.0-bootstrap.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +131 -2
- package/dist/agent-turn-flow.d.ts +57 -0
- package/dist/agent-turn-flow.d.ts.map +1 -0
- package/dist/agent-turn-flow.js +172 -0
- package/dist/agent-turn-flow.js.map +1 -0
- package/dist/conversation-binding.d.ts +111 -0
- package/dist/conversation-binding.d.ts.map +1 -0
- package/dist/conversation-binding.js +4 -0
- package/dist/conversation-binding.js.map +1 -0
- package/dist/define.d.ts +180 -0
- package/dist/define.d.ts.map +1 -0
- package/dist/define.js +361 -0
- package/dist/define.js.map +1 -0
- package/dist/errors.d.ts +62 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +4 -0
- package/dist/errors.js.map +1 -0
- package/dist/guardrails-gate.d.ts +169 -0
- package/dist/guardrails-gate.d.ts.map +1 -0
- package/dist/guardrails-gate.js +202 -0
- package/dist/guardrails-gate.js.map +1 -0
- package/dist/handlers/budget-check.d.ts +22 -0
- package/dist/handlers/budget-check.d.ts.map +1 -0
- package/dist/handlers/budget-check.js +109 -0
- package/dist/handlers/budget-check.js.map +1 -0
- package/dist/handlers/build-initial-messages.d.ts +17 -0
- package/dist/handlers/build-initial-messages.d.ts.map +1 -0
- package/dist/handlers/build-initial-messages.js +86 -0
- package/dist/handlers/build-initial-messages.js.map +1 -0
- package/dist/handlers/compose-result.d.ts +10 -0
- package/dist/handlers/compose-result.d.ts.map +1 -0
- package/dist/handlers/compose-result.js +79 -0
- package/dist/handlers/compose-result.js.map +1 -0
- package/dist/handlers/constants.d.ts +8 -0
- package/dist/handlers/constants.d.ts.map +1 -0
- package/dist/handlers/constants.js +10 -0
- package/dist/handlers/constants.js.map +1 -0
- package/dist/handlers/context.d.ts +210 -0
- package/dist/handlers/context.d.ts.map +1 -0
- package/dist/handlers/context.js +4 -0
- package/dist/handlers/context.js.map +1 -0
- package/dist/handlers/dispatch-tools.d.ts +15 -0
- package/dist/handlers/dispatch-tools.d.ts.map +1 -0
- package/dist/handlers/dispatch-tools.js +511 -0
- package/dist/handlers/dispatch-tools.js.map +1 -0
- package/dist/handlers/errors.d.ts +133 -0
- package/dist/handlers/errors.d.ts.map +1 -0
- package/dist/handlers/errors.js +134 -0
- package/dist/handlers/errors.js.map +1 -0
- package/dist/handlers/evaluate-guardrails.d.ts +14 -0
- package/dist/handlers/evaluate-guardrails.d.ts.map +1 -0
- package/dist/handlers/evaluate-guardrails.js +128 -0
- package/dist/handlers/evaluate-guardrails.js.map +1 -0
- package/dist/handlers/final-iteration.d.ts +7 -0
- package/dist/handlers/final-iteration.d.ts.map +1 -0
- package/dist/handlers/final-iteration.js +26 -0
- package/dist/handlers/final-iteration.js.map +1 -0
- package/dist/handlers/index.d.ts +5 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +41 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/model-call.d.ts +13 -0
- package/dist/handlers/model-call.d.ts.map +1 -0
- package/dist/handlers/model-call.js +136 -0
- package/dist/handlers/model-call.js.map +1 -0
- package/dist/handlers/persist-final-message.d.ts +14 -0
- package/dist/handlers/persist-final-message.d.ts.map +1 -0
- package/dist/handlers/persist-final-message.js +54 -0
- package/dist/handlers/persist-final-message.js.map +1 -0
- package/dist/handlers/persist-provenance.d.ts +12 -0
- package/dist/handlers/persist-provenance.d.ts.map +1 -0
- package/dist/handlers/persist-provenance.js +34 -0
- package/dist/handlers/persist-provenance.js.map +1 -0
- package/dist/handlers/persist-user-message.d.ts +15 -0
- package/dist/handlers/persist-user-message.d.ts.map +1 -0
- package/dist/handlers/persist-user-message.js +59 -0
- package/dist/handlers/persist-user-message.js.map +1 -0
- package/dist/handlers/public-types.d.ts +201 -0
- package/dist/handlers/public-types.d.ts.map +1 -0
- package/dist/handlers/public-types.js +4 -0
- package/dist/handlers/public-types.js.map +1 -0
- package/dist/handlers/rehydrate.d.ts +8 -0
- package/dist/handlers/rehydrate.d.ts.map +1 -0
- package/dist/handlers/rehydrate.js +94 -0
- package/dist/handlers/rehydrate.js.map +1 -0
- package/dist/handlers/render-prompt.d.ts +12 -0
- package/dist/handlers/render-prompt.d.ts.map +1 -0
- package/dist/handlers/render-prompt.js +41 -0
- package/dist/handlers/render-prompt.js.map +1 -0
- package/dist/handlers/resolve-tools.d.ts +10 -0
- package/dist/handlers/resolve-tools.d.ts.map +1 -0
- package/dist/handlers/resolve-tools.js +55 -0
- package/dist/handlers/resolve-tools.js.map +1 -0
- package/dist/handlers/result-shape.d.ts +94 -0
- package/dist/handlers/result-shape.d.ts.map +1 -0
- package/dist/handlers/result-shape.js +19 -0
- package/dist/handlers/result-shape.js.map +1 -0
- package/dist/handlers/run-retrievals.d.ts +10 -0
- package/dist/handlers/run-retrievals.d.ts.map +1 -0
- package/dist/handlers/run-retrievals.js +64 -0
- package/dist/handlers/run-retrievals.js.map +1 -0
- package/dist/handlers/run-snapshot.d.ts +4 -0
- package/dist/handlers/run-snapshot.d.ts.map +1 -0
- package/dist/handlers/run-snapshot.js +26 -0
- package/dist/handlers/run-snapshot.js.map +1 -0
- package/dist/handlers/setup.d.ts +25 -0
- package/dist/handlers/setup.d.ts.map +1 -0
- package/dist/handlers/setup.js +231 -0
- package/dist/handlers/setup.js.map +1 -0
- package/dist/handlers/structured-output.d.ts +38 -0
- package/dist/handlers/structured-output.d.ts.map +1 -0
- package/dist/handlers/structured-output.js +89 -0
- package/dist/handlers/structured-output.js.map +1 -0
- package/dist/handlers/tool-errors.d.ts +56 -0
- package/dist/handlers/tool-errors.d.ts.map +1 -0
- package/dist/handlers/tool-errors.js +73 -0
- package/dist/handlers/tool-errors.js.map +1 -0
- package/dist/handlers/tool-hitl.d.ts +45 -0
- package/dist/handlers/tool-hitl.d.ts.map +1 -0
- package/dist/handlers/tool-hitl.js +81 -0
- package/dist/handlers/tool-hitl.js.map +1 -0
- package/dist/handlers/turn-environment.d.ts +26 -0
- package/dist/handlers/turn-environment.d.ts.map +1 -0
- package/dist/handlers/turn-environment.js +154 -0
- package/dist/handlers/turn-environment.js.map +1 -0
- package/dist/hitl-policy.d.ts +45 -0
- package/dist/hitl-policy.d.ts.map +1 -0
- package/dist/hitl-policy.js +74 -0
- package/dist/hitl-policy.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/invoke.d.ts +36 -0
- package/dist/invoke.d.ts.map +1 -0
- package/dist/invoke.js +228 -0
- package/dist/invoke.js.map +1 -0
- package/dist/migrations-dir.d.ts +11 -0
- package/dist/migrations-dir.d.ts.map +1 -0
- package/dist/migrations-dir.js +14 -0
- package/dist/migrations-dir.js.map +1 -0
- package/dist/project-run-result.d.ts +23 -0
- package/dist/project-run-result.d.ts.map +1 -0
- package/dist/project-run-result.js +116 -0
- package/dist/project-run-result.js.map +1 -0
- package/dist/prompt.d.ts +83 -0
- package/dist/prompt.d.ts.map +1 -0
- package/dist/prompt.js +119 -0
- package/dist/prompt.js.map +1 -0
- package/dist/provenance-emit.d.ts +44 -0
- package/dist/provenance-emit.d.ts.map +1 -0
- package/dist/provenance-emit.js +51 -0
- package/dist/provenance-emit.js.map +1 -0
- package/dist/registry.d.ts +38 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +125 -0
- package/dist/registry.js.map +1 -0
- package/dist/retrieval.d.ts +47 -0
- package/dist/retrieval.d.ts.map +1 -0
- package/dist/retrieval.js +155 -0
- package/dist/retrieval.js.map +1 -0
- package/dist/run-snapshot-binding.d.ts +77 -0
- package/dist/run-snapshot-binding.d.ts.map +1 -0
- package/dist/run-snapshot-binding.js +4 -0
- package/dist/run-snapshot-binding.js.map +1 -0
- package/dist/schema.d.ts +497 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +133 -0
- package/dist/schema.js.map +1 -0
- package/dist/streaming.d.ts +118 -0
- package/dist/streaming.d.ts.map +1 -0
- package/dist/streaming.js +17 -0
- package/dist/streaming.js.map +1 -0
- package/dist/tenant-policy.d.ts +16 -0
- package/dist/tenant-policy.d.ts.map +1 -0
- package/dist/tenant-policy.js +77 -0
- package/dist/tenant-policy.js.map +1 -0
- package/dist/types.d.ts +435 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/types.js.map +1 -0
- package/dist/versioning.d.ts +29 -0
- package/dist/versioning.d.ts.map +1 -0
- package/dist/versioning.js +58 -0
- package/dist/versioning.js.map +1 -0
- package/migrations/0000_sparkling_talkback.sql +18 -0
- package/migrations/0001_tired_warhawk.sql +16 -0
- package/migrations/0002_violet_ezekiel.sql +2 -0
- package/migrations/meta/0000_snapshot.json +172 -0
- package/migrations/meta/0001_snapshot.json +275 -0
- package/migrations/meta/0002_snapshot.json +287 -0
- package/migrations/meta/_journal.json +27 -0
- package/package.json +76 -4
- package/src/agent-turn-flow.ts +183 -0
- package/src/conversation-binding.ts +147 -0
- package/src/define.ts +572 -0
- package/src/errors.ts +80 -0
- package/src/guardrails-gate.ts +342 -0
- package/src/handlers/budget-check.ts +143 -0
- package/src/handlers/build-initial-messages.ts +103 -0
- package/src/handlers/compose-result.ts +90 -0
- package/src/handlers/constants.ts +10 -0
- package/src/handlers/context.ts +226 -0
- package/src/handlers/dispatch-tools.ts +633 -0
- package/src/handlers/errors.ts +282 -0
- package/src/handlers/evaluate-guardrails.ts +153 -0
- package/src/handlers/final-iteration.ts +30 -0
- package/src/handlers/index.ts +63 -0
- package/src/handlers/model-call.ts +151 -0
- package/src/handlers/persist-final-message.ts +67 -0
- package/src/handlers/persist-provenance.ts +39 -0
- package/src/handlers/persist-user-message.ts +70 -0
- package/src/handlers/public-types.ts +209 -0
- package/src/handlers/rehydrate.ts +161 -0
- package/src/handlers/render-prompt.ts +46 -0
- package/src/handlers/resolve-tools.ts +68 -0
- package/src/handlers/result-shape.ts +113 -0
- package/src/handlers/run-retrievals.ts +77 -0
- package/src/handlers/run-snapshot.ts +44 -0
- package/src/handlers/setup.ts +269 -0
- package/src/handlers/structured-output.ts +117 -0
- package/src/handlers/tool-errors.ts +122 -0
- package/src/handlers/tool-hitl.ts +126 -0
- package/src/handlers/turn-environment.ts +191 -0
- package/src/hitl-policy.ts +128 -0
- package/src/index.ts +154 -0
- package/src/invoke.ts +299 -0
- package/src/migrations-dir.ts +17 -0
- package/src/project-run-result.ts +131 -0
- package/src/prompt.ts +185 -0
- package/src/provenance-emit.ts +100 -0
- package/src/registry.ts +164 -0
- package/src/retrieval.ts +219 -0
- package/src/run-snapshot-binding.ts +87 -0
- package/src/schema.ts +154 -0
- package/src/streaming.ts +153 -0
- package/src/tenant-policy.ts +78 -0
- package/src/types.ts +453 -0
- 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
|
+
}
|