@genesislcap/ai-assistant 15.19.0 → 15.19.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/package.json +17 -18
- package/api-extractor.json +0 -11
- package/dist/dts/components/chat-driver/chat-driver.compact.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.compact.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.invocation-scope.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.invocation-scope.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.thinking-policy.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.thinking-policy.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.trace-capture.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.trace-capture.test.d.ts.map +0 -1
- package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts +0 -2
- package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts.map +0 -1
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.test.d.ts +0 -2
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.test.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.budget.test.d.ts +0 -2
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.budget.test.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts +0 -2
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts.map +0 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.pin.test.d.ts +0 -2
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.pin.test.d.ts.map +0 -1
- package/dist/dts/components/settings-modal/settings-modal.styles.test.d.ts +0 -2
- package/dist/dts/components/settings-modal/settings-modal.styles.test.d.ts.map +0 -1
- package/dist/dts/components/settings-modal/settings-modal.template.test.d.ts +0 -2
- package/dist/dts/components/settings-modal/settings-modal.template.test.d.ts.map +0 -1
- package/dist/dts/config/define-stateful-agent.test.d.ts +0 -2
- package/dist/dts/config/define-stateful-agent.test.d.ts.map +0 -1
- package/dist/dts/config/validate-providers.test.d.ts +0 -2
- package/dist/dts/config/validate-providers.test.d.ts.map +0 -1
- package/dist/dts/main/blocked-state.test.d.ts +0 -2
- package/dist/dts/main/blocked-state.test.d.ts.map +0 -1
- package/dist/dts/main/budget-meter.test.d.ts +0 -2
- package/dist/dts/main/budget-meter.test.d.ts.map +0 -1
- package/dist/dts/main/cost-session-banking.test.d.ts +0 -2
- package/dist/dts/main/cost-session-banking.test.d.ts.map +0 -1
- package/dist/dts/main/file-attachments.test.d.ts +0 -2
- package/dist/dts/main/file-attachments.test.d.ts.map +0 -1
- package/dist/dts/main/interaction-cost.test.d.ts +0 -2
- package/dist/dts/main/interaction-cost.test.d.ts.map +0 -1
- package/dist/dts/main/main.styles.test.d.ts +0 -2
- package/dist/dts/main/main.styles.test.d.ts.map +0 -1
- package/dist/dts/main/persistence-broken-sources.test.d.ts +0 -2
- package/dist/dts/main/persistence-broken-sources.test.d.ts.map +0 -1
- package/dist/dts/main/popout-interaction-gate.test.d.ts +0 -2
- package/dist/dts/main/popout-interaction-gate.test.d.ts.map +0 -1
- package/dist/dts/state/ai-assistant-slice.test.d.ts +0 -2
- package/dist/dts/state/ai-assistant-slice.test.d.ts.map +0 -1
- package/dist/dts/state/debug-event-log.test.d.ts +0 -2
- package/dist/dts/state/debug-event-log.test.d.ts.map +0 -1
- package/dist/dts/state/driver-registry.test.d.ts +0 -2
- package/dist/dts/state/driver-registry.test.d.ts.map +0 -1
- package/dist/dts/state/interaction-context.test.d.ts +0 -2
- package/dist/dts/state/interaction-context.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/diagnostics-cursors.test.d.ts +0 -2
- package/dist/dts/state/persistence/diagnostics-cursors.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/diagnostics.test.d.ts +0 -2
- package/dist/dts/state/persistence/diagnostics.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-persistence-provider.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-persistence-provider.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-persistence.integration.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-persistence.integration.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-persister.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-persister.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/session-snapshot.test.d.ts +0 -2
- package/dist/dts/state/persistence/session-snapshot.test.d.ts.map +0 -1
- package/dist/dts/state/persistence/stateful-restore.e2e.test.d.ts +0 -2
- package/dist/dts/state/persistence/stateful-restore.e2e.test.d.ts.map +0 -1
- package/dist/dts/utils/animation-exclusivity.test.d.ts +0 -2
- package/dist/dts/utils/animation-exclusivity.test.d.ts.map +0 -1
- package/dist/dts/utils/collect-session-models.test.d.ts +0 -2
- package/dist/dts/utils/collect-session-models.test.d.ts.map +0 -1
- package/dist/dts/utils/condense-history.test.d.ts +0 -2
- package/dist/dts/utils/condense-history.test.d.ts.map +0 -1
- package/dist/dts/utils/cost-session-history.test.d.ts +0 -2
- package/dist/dts/utils/cost-session-history.test.d.ts.map +0 -1
- package/dist/dts/utils/derive-cost-session-title.test.d.ts +0 -2
- package/dist/dts/utils/derive-cost-session-title.test.d.ts.map +0 -1
- package/dist/dts/utils/flatten-sub-agent-messages.test.d.ts +0 -2
- package/dist/dts/utils/flatten-sub-agent-messages.test.d.ts.map +0 -1
- package/dist/dts/utils/history-transform.test.d.ts +0 -2
- package/dist/dts/utils/history-transform.test.d.ts.map +0 -1
- package/dist/dts/utils/message-partition.test.d.ts +0 -2
- package/dist/dts/utils/message-partition.test.d.ts.map +0 -1
- package/dist/dts/utils/resolve-cost-history-config.test.d.ts +0 -2
- package/dist/dts/utils/resolve-cost-history-config.test.d.ts.map +0 -1
- package/dist/dts/utils/resolve-preference-baseline.test.d.ts +0 -2
- package/dist/dts/utils/resolve-preference-baseline.test.d.ts.map +0 -1
- package/dist/dts/utils/strip-agent-handlers.test.d.ts +0 -2
- package/dist/dts/utils/strip-agent-handlers.test.d.ts.map +0 -1
- package/dist/dts/utils/sum-costs.test.d.ts +0 -2
- package/dist/dts/utils/sum-costs.test.d.ts.map +0 -1
- package/dist/dts/utils/sum-tokens.test.d.ts +0 -2
- package/dist/dts/utils/sum-tokens.test.d.ts.map +0 -1
- package/dist/dts/utils/sum-usage.test.d.ts +0 -2
- package/dist/dts/utils/sum-usage.test.d.ts.map +0 -1
- package/dist/dts/utils/usage-rows.test.d.ts +0 -2
- package/dist/dts/utils/usage-rows.test.d.ts.map +0 -1
- package/dist/esm/components/chat-driver/chat-driver.compact.test.js +0 -93
- package/dist/esm/components/chat-driver/chat-driver.invocation-scope.test.js +0 -238
- package/dist/esm/components/chat-driver/chat-driver.test.js +0 -2770
- package/dist/esm/components/chat-driver/chat-driver.thinking-policy.test.js +0 -137
- package/dist/esm/components/chat-driver/chat-driver.trace-capture.test.js +0 -200
- package/dist/esm/components/chat-driver/chat-driver.turn-usage.test.js +0 -268
- package/dist/esm/components/chat-interaction-wrapper/chat-interaction-wrapper.test.js +0 -104
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.budget.test.js +0 -312
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.cost.test.js +0 -76
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.pin.test.js +0 -61
- package/dist/esm/components/settings-modal/settings-modal.styles.test.js +0 -80
- package/dist/esm/components/settings-modal/settings-modal.template.test.js +0 -91
- package/dist/esm/config/define-stateful-agent.test.js +0 -53
- package/dist/esm/config/validate-providers.test.js +0 -100
- package/dist/esm/main/blocked-state.test.js +0 -1065
- package/dist/esm/main/budget-meter.test.js +0 -359
- package/dist/esm/main/cost-session-banking.test.js +0 -538
- package/dist/esm/main/file-attachments.test.js +0 -164
- package/dist/esm/main/interaction-cost.test.js +0 -107
- package/dist/esm/main/main.styles.test.js +0 -161
- package/dist/esm/main/persistence-broken-sources.test.js +0 -180
- package/dist/esm/main/popout-interaction-gate.test.js +0 -54
- package/dist/esm/state/ai-assistant-slice.test.js +0 -229
- package/dist/esm/state/debug-event-log.test.js +0 -117
- package/dist/esm/state/driver-registry.test.js +0 -55
- package/dist/esm/state/interaction-context.test.js +0 -78
- package/dist/esm/state/persistence/diagnostics-cursors.test.js +0 -30
- package/dist/esm/state/persistence/diagnostics.test.js +0 -280
- package/dist/esm/state/persistence/session-persistence-provider.test.js +0 -110
- package/dist/esm/state/persistence/session-persistence.integration.test.js +0 -113
- package/dist/esm/state/persistence/session-persister.test.js +0 -613
- package/dist/esm/state/persistence/session-snapshot.test.js +0 -256
- package/dist/esm/state/persistence/stateful-restore.e2e.test.js +0 -158
- package/dist/esm/utils/animation-exclusivity.test.js +0 -52
- package/dist/esm/utils/collect-session-models.test.js +0 -53
- package/dist/esm/utils/condense-history.test.js +0 -547
- package/dist/esm/utils/cost-session-history.test.js +0 -174
- package/dist/esm/utils/derive-cost-session-title.test.js +0 -37
- package/dist/esm/utils/flatten-sub-agent-messages.test.js +0 -139
- package/dist/esm/utils/history-transform.test.js +0 -158
- package/dist/esm/utils/message-partition.test.js +0 -90
- package/dist/esm/utils/resolve-cost-history-config.test.js +0 -32
- package/dist/esm/utils/resolve-preference-baseline.test.js +0 -69
- package/dist/esm/utils/strip-agent-handlers.test.js +0 -81
- package/dist/esm/utils/sum-costs.test.js +0 -114
- package/dist/esm/utils/sum-tokens.test.js +0 -51
- package/dist/esm/utils/sum-usage.test.js +0 -164
- package/dist/esm/utils/usage-rows.test.js +0 -189
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/license.txt +0 -46
- package/sandbox/tsconfig.json +0 -8
- package/src/channel/ai-activity-bus.ts +0 -209
- package/src/channel/ai-activity-channel.ts +0 -146
- package/src/chat-driver-node.ts +0 -159
- package/src/components/activity-halo/activity-halo.ts +0 -106
- package/src/components/agent-picker/agent-picker.constants.ts +0 -2
- package/src/components/agent-picker/agent-picker.styles.ts +0 -24
- package/src/components/agent-picker/agent-picker.template.ts +0 -54
- package/src/components/agent-picker/agent-picker.ts +0 -99
- package/src/components/agent-picker/index.ts +0 -1
- package/src/components/ai-driver/ai-driver.ts +0 -166
- package/src/components/ai-driver/index.ts +0 -1
- package/src/components/chat-bubble/chat-bubble.styles.ts +0 -194
- package/src/components/chat-bubble/chat-bubble.template.ts +0 -67
- package/src/components/chat-bubble/chat-bubble.ts +0 -436
- package/src/components/chat-bubble/index.ts +0 -1
- package/src/components/chat-driver/align-event-globals.ts +0 -23
- package/src/components/chat-driver/chat-driver.compact.test.ts +0 -131
- package/src/components/chat-driver/chat-driver.invocation-scope.test.ts +0 -285
- package/src/components/chat-driver/chat-driver.test.ts +0 -3679
- package/src/components/chat-driver/chat-driver.thinking-policy.test.ts +0 -185
- package/src/components/chat-driver/chat-driver.trace-capture.test.ts +0 -251
- package/src/components/chat-driver/chat-driver.ts +0 -3925
- package/src/components/chat-driver/chat-driver.turn-usage.test.ts +0 -362
- package/src/components/chat-driver/index.ts +0 -1
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.ts +0 -7
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.template.ts +0 -6
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.test.ts +0 -144
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts +0 -243
- package/src/components/chat-interaction-wrapper/index.ts +0 -3
- package/src/components/chat-markdown/chat-markdown.ts +0 -89
- package/src/components/chat-markdown/index.ts +0 -1
- package/src/components/flowing-waves-indicator.ts +0 -286
- package/src/components/halo-overlay.ts +0 -184
- package/src/components/orchestrating-driver/index.ts +0 -1
- package/src/components/orchestrating-driver/orchestrating-driver.budget.test.ts +0 -438
- package/src/components/orchestrating-driver/orchestrating-driver.cost.test.ts +0 -107
- package/src/components/orchestrating-driver/orchestrating-driver.pin.test.ts +0 -96
- package/src/components/orchestrating-driver/orchestrating-driver.ts +0 -813
- package/src/components/plasma-orb-indicator.ts +0 -281
- package/src/components/popout-manager/index.ts +0 -1
- package/src/components/popout-manager/popout-manager.ts +0 -212
- package/src/components/settings-modal/index.ts +0 -2
- package/src/components/settings-modal/settings-modal.styles.test.ts +0 -94
- package/src/components/settings-modal/settings-modal.styles.ts +0 -853
- package/src/components/settings-modal/settings-modal.template.test.ts +0 -124
- package/src/components/settings-modal/settings-modal.template.ts +0 -943
- package/src/components/waves-indicator.ts +0 -241
- package/src/config/config.ts +0 -608
- package/src/config/define-stateful-agent.test.ts +0 -64
- package/src/config/define-stateful-agent.ts +0 -642
- package/src/config/fallback-agents.ts +0 -29
- package/src/config/index.ts +0 -2
- package/src/config/validate-providers.test.ts +0 -148
- package/src/config/validate-providers.ts +0 -58
- package/src/index.ts +0 -29
- package/src/main/blocked-state.test.ts +0 -1444
- package/src/main/budget-meter.test.ts +0 -477
- package/src/main/cost-session-banking.test.ts +0 -679
- package/src/main/file-attachments.test.ts +0 -215
- package/src/main/index.ts +0 -3
- package/src/main/interaction-cost.test.ts +0 -140
- package/src/main/main.styles.test.ts +0 -216
- package/src/main/main.styles.ts +0 -995
- package/src/main/main.template.ts +0 -1119
- package/src/main/main.ts +0 -5432
- package/src/main/main.types.ts +0 -225
- package/src/main/persistence-broken-sources.test.ts +0 -219
- package/src/main/popout-interaction-gate.test.ts +0 -87
- package/src/provider/ai-provider-switcher.ts +0 -40
- package/src/provider/assistant-app-settings.ts +0 -84
- package/src/state/ai-assistant-slice.test.ts +0 -336
- package/src/state/ai-assistant-slice.ts +0 -604
- package/src/state/debug-event-log.test.ts +0 -154
- package/src/state/debug-event-log.ts +0 -358
- package/src/state/driver-registry.test.ts +0 -70
- package/src/state/driver-registry.ts +0 -79
- package/src/state/interaction-context.test.ts +0 -90
- package/src/state/interaction-context.ts +0 -101
- package/src/state/persistence/build-timeline-entries.ts +0 -66
- package/src/state/persistence/diagnostics-cursors.test.ts +0 -53
- package/src/state/persistence/diagnostics-cursors.ts +0 -80
- package/src/state/persistence/diagnostics.test.ts +0 -346
- package/src/state/persistence/diagnostics.ts +0 -220
- package/src/state/persistence/index.ts +0 -10
- package/src/state/persistence/persister-registry.ts +0 -55
- package/src/state/persistence/session-persistence-provider.test.ts +0 -136
- package/src/state/persistence/session-persistence-provider.ts +0 -226
- package/src/state/persistence/session-persistence.integration.test.ts +0 -141
- package/src/state/persistence/session-persister.test.ts +0 -787
- package/src/state/persistence/session-persister.ts +0 -917
- package/src/state/persistence/session-snapshot.test.ts +0 -352
- package/src/state/persistence/session-snapshot.ts +0 -344
- package/src/state/persistence/stateful-restore.e2e.test.ts +0 -229
- package/src/state/session-store.ts +0 -56
- package/src/styles/ai-colours.ts +0 -30
- package/src/styles/menu.ts +0 -187
- package/src/styles/settings-section.ts +0 -40
- package/src/suggestions/chat-suggestions.ts +0 -186
- package/src/tags/index.ts +0 -1
- package/src/types/ai-chat-widget.ts +0 -67
- package/src/types/interaction-context.ts +0 -82
- package/src/utils/animated-panel-toggle.ts +0 -62
- package/src/utils/animation-exclusivity.test.ts +0 -72
- package/src/utils/animation-exclusivity.ts +0 -40
- package/src/utils/banked-usage-baselines.ts +0 -90
- package/src/utils/collect-session-models.test.ts +0 -82
- package/src/utils/collect-session-models.ts +0 -65
- package/src/utils/condense-history.test.ts +0 -746
- package/src/utils/condense-history.ts +0 -448
- package/src/utils/cost-session-history.test.ts +0 -226
- package/src/utils/cost-session-history.ts +0 -218
- package/src/utils/derive-cost-session-title.test.ts +0 -63
- package/src/utils/derive-cost-session-title.ts +0 -76
- package/src/utils/flatten-sub-agent-messages.test.ts +0 -163
- package/src/utils/flatten-sub-agent-messages.ts +0 -88
- package/src/utils/format-usd.ts +0 -26
- package/src/utils/history-transform.test.ts +0 -228
- package/src/utils/history-transform.ts +0 -163
- package/src/utils/index.ts +0 -3
- package/src/utils/logger.ts +0 -3
- package/src/utils/message-partition.test.ts +0 -129
- package/src/utils/message-partition.ts +0 -115
- package/src/utils/resolve-cost-history-config.test.ts +0 -38
- package/src/utils/resolve-cost-history-config.ts +0 -38
- package/src/utils/resolve-preference-baseline.test.ts +0 -84
- package/src/utils/resolve-preference-baseline.ts +0 -80
- package/src/utils/strip-agent-handlers.test.ts +0 -99
- package/src/utils/strip-agent-handlers.ts +0 -53
- package/src/utils/sum-costs.test.ts +0 -136
- package/src/utils/sum-costs.ts +0 -18
- package/src/utils/sum-tokens.test.ts +0 -93
- package/src/utils/sum-tokens.ts +0 -68
- package/src/utils/sum-usage.test.ts +0 -191
- package/src/utils/sum-usage.ts +0 -208
- package/src/utils/tool-fold.ts +0 -181
- package/src/utils/usage-rows.test.ts +0 -237
- package/src/utils/usage-rows.ts +0 -187
- package/src/utils/with-timeout.ts +0 -24
- package/tsconfig.json +0 -9
|
@@ -1,642 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
CachePolicy,
|
|
3
|
-
ChatMessage,
|
|
4
|
-
ChatThinkingPolicy,
|
|
5
|
-
ChatToolChoice,
|
|
6
|
-
ChatToolDefinition,
|
|
7
|
-
ChatToolHandlers,
|
|
8
|
-
} from '@genesislcap/foundation-ai';
|
|
9
|
-
import { TOOL_FOLD_SYMBOL } from '../utils/tool-fold';
|
|
10
|
-
import type {
|
|
11
|
-
AgentConfig,
|
|
12
|
-
AgentLifecycleContext,
|
|
13
|
-
AgentPersistenceContext,
|
|
14
|
-
CachePolicyInput,
|
|
15
|
-
ChatInputDuringExecutionMode,
|
|
16
|
-
ManualSelectionConfig,
|
|
17
|
-
ProviderInput,
|
|
18
|
-
SystemPromptContext,
|
|
19
|
-
SystemPromptInput,
|
|
20
|
-
TailContextInput,
|
|
21
|
-
TemperatureInput,
|
|
22
|
-
ThinkingPolicyInput,
|
|
23
|
-
ToolChoiceInput,
|
|
24
|
-
ToolDefinitionsInput,
|
|
25
|
-
ToolHandlersInput,
|
|
26
|
-
UnresolvedToolContext,
|
|
27
|
-
UnresolvedToolInput,
|
|
28
|
-
} from './config';
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Context passed to per-turn resolvers on a stateful agent — the standard
|
|
32
|
-
* {@link SystemPromptContext} plus the live `state` value. Used by
|
|
33
|
-
* `systemPrompt`, `displayName`, and the function form of `toolDefinitions`.
|
|
34
|
-
*
|
|
35
|
-
* Exported so consumers can lift resolvers into separate files without
|
|
36
|
-
* re-deriving the shape.
|
|
37
|
-
*
|
|
38
|
-
* @beta
|
|
39
|
-
*/
|
|
40
|
-
export type StatefulAgentContext<S> = SystemPromptContext & { state: S };
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Context passed to a stateful agent's `resumable` predicate (GENC-1351 §5.9) —
|
|
44
|
-
* the standard {@link AgentPersistenceContext} but with `state` as the **live**
|
|
45
|
-
* state bag `S` (not the serialized image), so a machine agent can gate on its
|
|
46
|
-
* current step directly.
|
|
47
|
-
*
|
|
48
|
-
* @beta
|
|
49
|
-
*/
|
|
50
|
-
export type StatefulAgentPersistenceContext<S> = Omit<AgentPersistenceContext, 'state'> & {
|
|
51
|
-
state: S;
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Init options for {@link defineStatefulAgent}. Generic over the state shape `S`
|
|
56
|
-
* the agent owns (a state machine, an observable controller, anything).
|
|
57
|
-
*
|
|
58
|
-
* The helper threads `state` through `systemPrompt`, `toolDefinitions`, and the
|
|
59
|
-
* `toolHandlers` factory so consumer code never has to reach for a closure or
|
|
60
|
-
* a module-level mutable.
|
|
61
|
-
*
|
|
62
|
-
* @beta
|
|
63
|
-
*/
|
|
64
|
-
export interface StatefulAgentInit<S> {
|
|
65
|
-
/** Display name — must be unique within the agents array. */
|
|
66
|
-
name: string;
|
|
67
|
-
/** Plain-language description used by the classifier. Required: stateful agents are always specialists. */
|
|
68
|
-
description: string;
|
|
69
|
-
/**
|
|
70
|
-
* Hide this agent from the classifier — only reachable via manual pinning.
|
|
71
|
-
* Stateful agents are always specialists; they cannot be the fallback (a
|
|
72
|
-
* fallback is a leaf invoked when no specialist matches, with no flow to
|
|
73
|
-
* own state for).
|
|
74
|
-
*/
|
|
75
|
-
excludeFromClassifier?: boolean;
|
|
76
|
-
/** Static primer history prepended to every call (not visible to the user). */
|
|
77
|
-
primerHistory?: ChatMessage[];
|
|
78
|
-
/** Sub-agents available to this agent's tool handlers via `requestSubAgent`. */
|
|
79
|
-
subAgents?: AgentConfig[];
|
|
80
|
-
/** Opt this agent in to manual picker selection. */
|
|
81
|
-
manualSelection?: ManualSelectionConfig;
|
|
82
|
-
/** How the main chat input behaves while this agent is executing. */
|
|
83
|
-
chatInputDuringExecution?: ChatInputDuringExecutionMode;
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Construct the agent-scoped state. Called by the framework when this agent
|
|
87
|
-
* becomes active (`onActivate`). Awaited before the agent's first turn runs.
|
|
88
|
-
*
|
|
89
|
-
* On a persisted-session restore, `ctx.restored` carries this agent's previous
|
|
90
|
-
* `serialize` output — rebuild from it (e.g. via `restoreMachine`), or start
|
|
91
|
-
* fresh when it is `undefined`.
|
|
92
|
-
*/
|
|
93
|
-
init: (ctx: AgentLifecycleContext) => S | Promise<S>;
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Tear down the agent-scoped state. Called when the agent is being replaced.
|
|
97
|
-
* Awaited before the incoming agent's `init` runs.
|
|
98
|
-
*/
|
|
99
|
-
dispose?: (ctx: AgentLifecycleContext & { state: S }) => void | Promise<void>;
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* System prompt composed from current state. Resolved each tool-loop
|
|
103
|
-
* iteration. Use this to feed the LLM whatever the current state implies
|
|
104
|
-
* (e.g. a state machine's `meta.systemPrompt` plus captured context).
|
|
105
|
-
*/
|
|
106
|
-
systemPrompt?: (ctx: StatefulAgentContext<S>) => string | Promise<string>;
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Per-turn display label, e.g. "Guided Booking (Counterparties)". Resolved
|
|
110
|
-
* each tool-loop iteration and stamped onto outgoing messages and the
|
|
111
|
-
* debug-log timeline — display only. The agent's `name` stays as the
|
|
112
|
-
* canonical identity used for routing/history filtering.
|
|
113
|
-
*/
|
|
114
|
-
displayName?: (ctx: StatefulAgentContext<S>) => string | Promise<string>;
|
|
115
|
-
|
|
116
|
-
/**
|
|
117
|
-
* Tool definitions the LLM sees. Either a static array (resolved once) or a
|
|
118
|
-
* function resolved each tool-loop iteration. The function form is how a
|
|
119
|
-
* machine-driven agent narrows the surface per state.
|
|
120
|
-
*
|
|
121
|
-
* **Constraint:** the resolved handlers (returned from {@link StatefulAgentInit.toolHandlers})
|
|
122
|
-
* must not include fold facades. Folds are an LLM-driven UX optimisation
|
|
123
|
-
* that competes with the machine for control of the tool view; one of them
|
|
124
|
-
* has to be in charge. Helper throws at init time if a fold-tagged handler
|
|
125
|
-
* is detected.
|
|
126
|
-
*/
|
|
127
|
-
toolDefinitions?:
|
|
128
|
-
| ChatToolDefinition[]
|
|
129
|
-
| ((ctx: StatefulAgentContext<S>) => ChatToolDefinition[] | Promise<ChatToolDefinition[]>);
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Factory returning the handler map for the **current state**. Called each
|
|
133
|
-
* tool-loop iteration with the live `state` value, so the handler set the
|
|
134
|
-
* driver dispatches against matches what `toolDefinitions` exposes to the
|
|
135
|
-
* LLM that turn. Return only the handlers valid right now — no need to
|
|
136
|
-
* advertise every handler the agent might ever expose, and no defensive
|
|
137
|
-
* `if (!machine.matches(...))` guards inside each handler.
|
|
138
|
-
*
|
|
139
|
-
* Pair with the function form of `toolDefinitions` so the visible tools and
|
|
140
|
-
* the dispatchable handlers stay in lockstep.
|
|
141
|
-
*
|
|
142
|
-
* **Constraint:** resolved handlers must not include fold facades. Folds and
|
|
143
|
-
* state-machine-driven tool filtering both try to control the LLM's tool
|
|
144
|
-
* view — pick one. Helper samples once on activation (init state) and
|
|
145
|
-
* throws if a fold-tagged handler is detected; subsequent resolves also
|
|
146
|
-
* validate, so misuse on a non-init state surfaces when that state is
|
|
147
|
-
* reached.
|
|
148
|
-
*/
|
|
149
|
-
toolHandlers?: (state: S) => ChatToolHandlers | Promise<ChatToolHandlers>;
|
|
150
|
-
|
|
151
|
-
/**
|
|
152
|
-
* Which registered AI provider this agent uses, by name. Either a static
|
|
153
|
-
* string or a function resolved each tool-loop iteration with the current
|
|
154
|
-
* `state` — pick the function form to vary provider per machine state
|
|
155
|
-
* (e.g. swap to a heavier model only for the planning step).
|
|
156
|
-
*
|
|
157
|
-
* Omit to use the registry's default provider. Unknown names hard-error.
|
|
158
|
-
*/
|
|
159
|
-
provider?: string | ((ctx: StatefulAgentContext<S>) => string | Promise<string>);
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Sampling temperature, normalized to `0`–`1`. Either a static number or a
|
|
163
|
-
* function resolved each tool-loop iteration with the current `state` — pick
|
|
164
|
-
* the function form to vary it per machine state (e.g. low for a precise
|
|
165
|
-
* extraction step, higher for free-form drafting). Omit for the default.
|
|
166
|
-
*/
|
|
167
|
-
temperature?: number | ((ctx: StatefulAgentContext<S>) => number | Promise<number>);
|
|
168
|
-
|
|
169
|
-
/**
|
|
170
|
-
* Tool-call mode. Either a static `ChatToolChoice` or a function
|
|
171
|
-
* resolved each tool-loop iteration with the current `state` — pick the
|
|
172
|
-
* function form to force a specific tool in one state (e.g. a classifier in
|
|
173
|
-
* intake) and leave `'auto'` in states where multi-step work happens. Omit
|
|
174
|
-
* for the default.
|
|
175
|
-
*/
|
|
176
|
-
toolChoice?:
|
|
177
|
-
| ChatToolChoice
|
|
178
|
-
| ((ctx: StatefulAgentContext<S>) => ChatToolChoice | Promise<ChatToolChoice>);
|
|
179
|
-
|
|
180
|
-
/**
|
|
181
|
-
* Prompt-cache policy. Either a static `CachePolicy` or a function resolved each tool-loop
|
|
182
|
-
* iteration with the current `state` — pick the function form to vary it per machine state
|
|
183
|
-
* (e.g. `'history'` in a long generating phase, `'default'` in short low-touch ones). Omit to
|
|
184
|
-
* request no caching.
|
|
185
|
-
*/
|
|
186
|
-
cachePolicy?:
|
|
187
|
-
| CachePolicy
|
|
188
|
-
| ((ctx: StatefulAgentContext<S>) => CachePolicy | Promise<CachePolicy>);
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Extended-thinking posture. Either a static `ChatThinkingPolicy` or a function resolved with
|
|
192
|
-
* the current `state` **once per user turn** — the function form is the point of this option on
|
|
193
|
-
* a machine agent: `'auto'` in the state that makes a real decision, `'off'` in the states that
|
|
194
|
-
* only step a known sequence, where reasoning is billed at the full output rate to re-derive
|
|
195
|
-
* what the machine already knows. Omit, or return `undefined` from the function, to keep the
|
|
196
|
-
* model's own default for that turn.
|
|
197
|
-
*
|
|
198
|
-
* Resolved once per turn rather than per tool-loop iteration (unlike `temperature` and
|
|
199
|
-
* `toolChoice`): a tool-use loop is one assistant turn and its thinking mode must hold for the
|
|
200
|
-
* whole of it. A state transition part-way through a loop therefore takes effect on the next
|
|
201
|
-
* user turn, not immediately.
|
|
202
|
-
*/
|
|
203
|
-
thinkingPolicy?:
|
|
204
|
-
| ChatThinkingPolicy
|
|
205
|
-
| ((
|
|
206
|
-
ctx: StatefulAgentContext<S>,
|
|
207
|
-
) => ChatThinkingPolicy | undefined | Promise<ChatThinkingPolicy | undefined>);
|
|
208
|
-
|
|
209
|
-
/**
|
|
210
|
-
* Volatile per-turn tail context (current file/spec, diagnostics, live state). Either a static
|
|
211
|
-
* string or a function resolved each tool-loop iteration with the current `state`. Provide raw
|
|
212
|
-
* content; the framework frames it. Omit, or return an empty string, for none.
|
|
213
|
-
*/
|
|
214
|
-
tailContext?: string | ((ctx: StatefulAgentContext<S>) => string | Promise<string>);
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Hook consulted when the model calls a tool that isn't dispatchable in the
|
|
218
|
-
* current state — a *stale* tool (valid in an earlier state of this agent) or
|
|
219
|
-
* an *unknown* one. Receives the current `state` alongside the attempted tool
|
|
220
|
-
* name and the currently dispatchable tools, so a machine-driven agent can
|
|
221
|
-
* return a step-aware redirect (e.g. "that belongs to a later step — finish
|
|
222
|
-
* this one first"). Return `undefined` to keep the framework default; a
|
|
223
|
-
* pre-init call also degrades to the default rather than throwing.
|
|
224
|
-
* See {@link UnresolvedToolContext}.
|
|
225
|
-
*/
|
|
226
|
-
onUnresolvedTool?: (
|
|
227
|
-
ctx: UnresolvedToolContext & { state: S },
|
|
228
|
-
) => string | undefined | Promise<string | undefined>;
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Optional getter for the debug-log snapshot. Defaults to auto-snapshotting
|
|
232
|
-
* any property on `state` that looks like a foundation-state-machine
|
|
233
|
-
* instance (has `state`, `context`, and `complete` fields). Override when
|
|
234
|
-
* the default doesn't capture what you need — e.g. multiple machines, or
|
|
235
|
-
* non-machine state worth recording.
|
|
236
|
-
*
|
|
237
|
-
* Return value must be JSON-serializable.
|
|
238
|
-
*/
|
|
239
|
-
getDebugSnapshot?: (state: S) => unknown;
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* Lossless serializer for session persistence — infra-agnostic. Return any
|
|
243
|
-
* JSON/structured-clone-safe image of `state`.
|
|
244
|
-
* • Machine agents (`{ machine }`): omit — the default snapshots every
|
|
245
|
-
* machine-shaped property via `getPersistedSnapshot()`.
|
|
246
|
-
* • Plain-data agents (e.g. `{ plan, cursor }`): omit too — the default
|
|
247
|
-
* returns plain state as-is. Provide one only when the state holds
|
|
248
|
-
* something the default can't capture.
|
|
249
|
-
* Distinct from `getDebugSnapshot` (which may be lossy by design). Pair with
|
|
250
|
-
* `init` reading `ctx.restored` to rebuild.
|
|
251
|
-
*/
|
|
252
|
-
serialize?: (state: S) => unknown;
|
|
253
|
-
|
|
254
|
-
/**
|
|
255
|
-
* Whether the agent's current state is resumable — worth persisting so the
|
|
256
|
-
* session restores mid-flow (GENC-1351 §5.9). Receives the **live** state bag
|
|
257
|
-
* `S` (like the other per-turn resolvers), so a machine agent gates on its step
|
|
258
|
-
* directly: `resumable: ({ state }) => state.machine.state !== 'confirm'`.
|
|
259
|
-
* Return `false` for a point that shouldn't resume — the session isn't persisted,
|
|
260
|
-
* and on return the assistant shows {@link StatefulAgentInit.notResumableMessage}
|
|
261
|
-
* (or a default) and pre-fills the composer with the prompt that started the flow.
|
|
262
|
-
* Only consulted with persistence enabled; a thrown error is treated as `true`
|
|
263
|
-
* (fail-safe — never drop a resumable chat on a predicate bug).
|
|
264
|
-
*/
|
|
265
|
-
resumable?: (ctx: StatefulAgentPersistenceContext<S>) => boolean | Promise<boolean>;
|
|
266
|
-
/**
|
|
267
|
-
* Message shown on return when {@link StatefulAgentInit.resumable} returned
|
|
268
|
-
* `false`. Falls back to a built-in default when omitted.
|
|
269
|
-
*/
|
|
270
|
-
notResumableMessage?: string;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Walk a state object and snapshot any machine-shaped values found on it.
|
|
275
|
-
* Recognises foundation-state-machine instances by structural shape rather
|
|
276
|
-
* than `instanceof`, so the helper stays free of a runtime dep on
|
|
277
|
-
* foundation-state-machine.
|
|
278
|
-
*
|
|
279
|
-
* Strips the `errors`/`error` framework noise from each machine's context —
|
|
280
|
-
* these are foundation-state-machine internals (an ErrorMap instance and its
|
|
281
|
-
* last-error pointer) that bloat the debug payload without aiding debugging.
|
|
282
|
-
*/
|
|
283
|
-
function defaultStatefulDebugSnapshot(state: unknown): unknown {
|
|
284
|
-
if (!state || typeof state !== 'object') return state;
|
|
285
|
-
const result: Record<string, unknown> = {};
|
|
286
|
-
for (const [key, val] of Object.entries(state as Record<string, unknown>)) {
|
|
287
|
-
if (val && typeof val === 'object' && 'state' in val && 'context' in val && 'complete' in val) {
|
|
288
|
-
const m = val as {
|
|
289
|
-
state: unknown;
|
|
290
|
-
context: Record<string, unknown>;
|
|
291
|
-
complete: unknown;
|
|
292
|
-
output?: unknown;
|
|
293
|
-
};
|
|
294
|
-
const ctx = m.context ?? {};
|
|
295
|
-
const { errors: _e, error: _err, ...userContext } = ctx;
|
|
296
|
-
result[key] = {
|
|
297
|
-
state: m.state,
|
|
298
|
-
context: userContext,
|
|
299
|
-
complete: m.complete,
|
|
300
|
-
output: m.output,
|
|
301
|
-
};
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
return Object.keys(result).length
|
|
305
|
-
? result
|
|
306
|
-
: '<no auto-snapshot — state has no machine-shaped properties; provide getDebugSnapshot>';
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
/**
|
|
310
|
-
* Build a restore-ready snapshot of agent state. Each property exposing a
|
|
311
|
-
* `getPersistedSnapshot()` method (a foundation-state-machine `AbstractMachine`)
|
|
312
|
-
* is replaced by its persisted snapshot — the lossless, JSON-safe image
|
|
313
|
-
* {@link restoreMachine} feeds back via `start({ state })`. Every other property
|
|
314
|
-
* is kept as-is, so plain serializable state (e.g. a planner's `{ plan, cursor }`)
|
|
315
|
-
* round-trips directly with no per-agent `serialize`.
|
|
316
|
-
*
|
|
317
|
-
* Distinct from `defaultStatefulDebugSnapshot`, which abbreviates for the debug
|
|
318
|
-
* log and is not guaranteed lossless.
|
|
319
|
-
*/
|
|
320
|
-
function defaultStatefulSerialize(state: unknown): unknown {
|
|
321
|
-
if (!state || typeof state !== 'object') return state;
|
|
322
|
-
const result: Record<string, unknown> = {};
|
|
323
|
-
for (const [key, val] of Object.entries(state as Record<string, unknown>)) {
|
|
324
|
-
result[key] =
|
|
325
|
-
val &&
|
|
326
|
-
typeof val === 'object' &&
|
|
327
|
-
typeof (val as { getPersistedSnapshot?: unknown }).getPersistedSnapshot === 'function'
|
|
328
|
-
? (val as { getPersistedSnapshot: () => unknown }).getPersistedSnapshot()
|
|
329
|
-
: val;
|
|
330
|
-
}
|
|
331
|
-
return result;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
/**
|
|
335
|
-
* Restore a foundation-state-machine instance from a snapshot produced by the
|
|
336
|
-
* default serializer (or `machine.getPersistedSnapshot()`). Call inside a
|
|
337
|
-
* stateful agent's `init` to resume the machine in its exact prior place:
|
|
338
|
-
*
|
|
339
|
-
* ```ts
|
|
340
|
-
* init: ({ restored }) => {
|
|
341
|
-
* const machine = new MyMachine();
|
|
342
|
-
* restoreMachine(machine, restored); // resume, or no-op on a fresh start
|
|
343
|
-
* return { machine };
|
|
344
|
-
* }
|
|
345
|
-
* ```
|
|
346
|
-
*
|
|
347
|
-
* No-ops when there is nothing to restore (a fresh session), leaving the
|
|
348
|
-
* freshly-constructed machine in its initial state.
|
|
349
|
-
*
|
|
350
|
-
* @param machine - the machine to restore (already constructed/started).
|
|
351
|
-
* @param restored - the agent's serialized image (`ctx.restored` in `init`).
|
|
352
|
-
* @param key - the property the machine occupies in the snapshot; defaults to
|
|
353
|
-
* `'machine'` to match the conventional `{ machine }` state bag.
|
|
354
|
-
* @beta
|
|
355
|
-
*/
|
|
356
|
-
export function restoreMachine(
|
|
357
|
-
machine: { stop: () => void; start: (options?: { state?: unknown }) => void },
|
|
358
|
-
restored: unknown,
|
|
359
|
-
key = 'machine',
|
|
360
|
-
): void {
|
|
361
|
-
const snapshot = (restored as Record<string, unknown> | undefined)?.[key];
|
|
362
|
-
if (snapshot === undefined || snapshot === null) {
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
machine.stop();
|
|
366
|
-
machine.start({ state: snapshot });
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* Build an `AgentConfig` whose `systemPrompt`, `toolDefinitions`, and tool
|
|
371
|
-
* handlers all close over a long-lived state object created on activation.
|
|
372
|
-
*
|
|
373
|
-
* The framework wires the lifecycle: `init` on `onActivate`, `dispose` on
|
|
374
|
-
* `onDeactivate`. State is held inside the helper's closure — never exposed on
|
|
375
|
-
* the resulting `AgentConfig` — so the redux serializer doesn't see it.
|
|
376
|
-
*
|
|
377
|
-
* @example
|
|
378
|
-
* ```ts
|
|
379
|
-
* const guidedBooking = defineStatefulAgent<{ machine: GuidedBookingMachine }>({
|
|
380
|
-
* name: 'Guided Booking',
|
|
381
|
-
* description: 'Books a trade via a guided wizard.',
|
|
382
|
-
* excludeFromClassifier: true,
|
|
383
|
-
* manualSelection: { enabled: true, hint: 'Step-by-step trade booking' },
|
|
384
|
-
* init: () => ({ machine: new GuidedBookingMachine() }),
|
|
385
|
-
* dispose: ({ state }) => state.machine.stop(),
|
|
386
|
-
* systemPrompt: ({ state }) => composeFromMachine(state.machine),
|
|
387
|
-
* toolDefinitions: ({ state }) => toolsForState(state.machine.state),
|
|
388
|
-
* toolHandlers: ({ machine }) => ({ ... }),
|
|
389
|
-
* });
|
|
390
|
-
* ```
|
|
391
|
-
*
|
|
392
|
-
* @beta
|
|
393
|
-
*/
|
|
394
|
-
export function defineStatefulAgent<S>(opts: StatefulAgentInit<S>): AgentConfig {
|
|
395
|
-
let state: S | undefined;
|
|
396
|
-
|
|
397
|
-
const assertNoFolds = (handlers: ChatToolHandlers): void => {
|
|
398
|
-
for (const [name, handler] of Object.entries(handlers)) {
|
|
399
|
-
if ((handler as any)[TOOL_FOLD_SYMBOL]) {
|
|
400
|
-
throw new Error(
|
|
401
|
-
`Stateful agent "${opts.name}" tool "${name}" carries fold metadata. ` +
|
|
402
|
-
`Folds and state-machine-driven tool filtering both try to control the ` +
|
|
403
|
-
`LLM's tool view — pick one. Remove the fold or migrate this agent to ` +
|
|
404
|
-
`a non-stateful AgentConfig.`,
|
|
405
|
-
);
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
};
|
|
409
|
-
|
|
410
|
-
// Wrap the optional dynamic-tools factory so it threads `state` in and asserts
|
|
411
|
-
// we never accidentally resolved a fold-tagged tool. Static arrays are passed
|
|
412
|
-
// through unchanged.
|
|
413
|
-
const wrappedTools: ToolDefinitionsInput | undefined = (() => {
|
|
414
|
-
const td = opts.toolDefinitions;
|
|
415
|
-
if (typeof td === 'function') {
|
|
416
|
-
return async (ctx: SystemPromptContext) => {
|
|
417
|
-
if (!state) {
|
|
418
|
-
throw new Error(`Stateful agent "${opts.name}" tools called before init`);
|
|
419
|
-
}
|
|
420
|
-
return td({ ...ctx, state });
|
|
421
|
-
};
|
|
422
|
-
}
|
|
423
|
-
return td;
|
|
424
|
-
})();
|
|
425
|
-
|
|
426
|
-
// Wrap the handler factory into the ctx-shaped form the driver expects, and
|
|
427
|
-
// validate folds on each resolve. The driver re-resolves this per tool-loop
|
|
428
|
-
// iteration, so the handler set the driver dispatches against always
|
|
429
|
-
// matches the LLM-visible tools for the current state — handlers don't need
|
|
430
|
-
// defensive `if (!machine.matches(...))` guards.
|
|
431
|
-
const wrappedHandlers: ToolHandlersInput | undefined = opts.toolHandlers
|
|
432
|
-
? async () => {
|
|
433
|
-
if (!state) {
|
|
434
|
-
throw new Error(`Stateful agent "${opts.name}" handlers called before init`);
|
|
435
|
-
}
|
|
436
|
-
const handlers = await opts.toolHandlers!(state);
|
|
437
|
-
assertNoFolds(handlers);
|
|
438
|
-
return handlers;
|
|
439
|
-
}
|
|
440
|
-
: undefined;
|
|
441
|
-
|
|
442
|
-
const wrappedDisplayName: SystemPromptInput | undefined = opts.displayName
|
|
443
|
-
? async (ctx: SystemPromptContext) => {
|
|
444
|
-
if (!state) {
|
|
445
|
-
throw new Error(`Stateful agent "${opts.name}" displayName called before init`);
|
|
446
|
-
}
|
|
447
|
-
return opts.displayName!({ ...ctx, state });
|
|
448
|
-
}
|
|
449
|
-
: undefined;
|
|
450
|
-
|
|
451
|
-
// Function-form `provider` needs `state` injected the same way the other
|
|
452
|
-
// per-turn resolvers do; the static-string form is passed through unchanged
|
|
453
|
-
// and validated up-front by OrchestratingDriver.
|
|
454
|
-
const wrappedProvider: ProviderInput | undefined =
|
|
455
|
-
typeof opts.provider === 'function'
|
|
456
|
-
? async (ctx: SystemPromptContext) => {
|
|
457
|
-
if (!state) {
|
|
458
|
-
throw new Error(`Stateful agent "${opts.name}" provider called before init`);
|
|
459
|
-
}
|
|
460
|
-
return (opts.provider as (ctx: StatefulAgentContext<S>) => string | Promise<string>)({
|
|
461
|
-
...ctx,
|
|
462
|
-
state,
|
|
463
|
-
});
|
|
464
|
-
}
|
|
465
|
-
: opts.provider;
|
|
466
|
-
|
|
467
|
-
// `temperature` and `toolChoice` thread `state` in exactly like `provider`;
|
|
468
|
-
// static values pass through unchanged.
|
|
469
|
-
const wrappedTemperature: TemperatureInput | undefined =
|
|
470
|
-
typeof opts.temperature === 'function'
|
|
471
|
-
? async (ctx: SystemPromptContext) => {
|
|
472
|
-
if (!state) {
|
|
473
|
-
throw new Error(`Stateful agent "${opts.name}" temperature called before init`);
|
|
474
|
-
}
|
|
475
|
-
return (opts.temperature as (ctx: StatefulAgentContext<S>) => number | Promise<number>)({
|
|
476
|
-
...ctx,
|
|
477
|
-
state,
|
|
478
|
-
});
|
|
479
|
-
}
|
|
480
|
-
: opts.temperature;
|
|
481
|
-
|
|
482
|
-
const wrappedToolChoice: ToolChoiceInput | undefined =
|
|
483
|
-
typeof opts.toolChoice === 'function'
|
|
484
|
-
? async (ctx: SystemPromptContext) => {
|
|
485
|
-
if (!state) {
|
|
486
|
-
throw new Error(`Stateful agent "${opts.name}" toolChoice called before init`);
|
|
487
|
-
}
|
|
488
|
-
return (
|
|
489
|
-
opts.toolChoice as (
|
|
490
|
-
ctx: StatefulAgentContext<S>,
|
|
491
|
-
) => ChatToolChoice | Promise<ChatToolChoice>
|
|
492
|
-
)({ ...ctx, state });
|
|
493
|
-
}
|
|
494
|
-
: opts.toolChoice;
|
|
495
|
-
|
|
496
|
-
const wrappedCachePolicy: CachePolicyInput | undefined =
|
|
497
|
-
typeof opts.cachePolicy === 'function'
|
|
498
|
-
? async (ctx: SystemPromptContext) => {
|
|
499
|
-
if (!state) {
|
|
500
|
-
throw new Error(`Stateful agent "${opts.name}" cachePolicy called before init`);
|
|
501
|
-
}
|
|
502
|
-
return (
|
|
503
|
-
opts.cachePolicy as (ctx: StatefulAgentContext<S>) => CachePolicy | Promise<CachePolicy>
|
|
504
|
-
)({ ...ctx, state });
|
|
505
|
-
}
|
|
506
|
-
: opts.cachePolicy;
|
|
507
|
-
|
|
508
|
-
// Unlike the resolvers above, a pre-init call returns `undefined` rather than throwing: that is
|
|
509
|
-
// this option's "model default" state, so degrading to it costs a turn its thinking preference
|
|
510
|
-
// instead of breaking the turn outright.
|
|
511
|
-
const wrappedThinkingPolicy: ThinkingPolicyInput | undefined =
|
|
512
|
-
typeof opts.thinkingPolicy === 'function'
|
|
513
|
-
? async (ctx: SystemPromptContext) => {
|
|
514
|
-
if (!state) return undefined;
|
|
515
|
-
return (
|
|
516
|
-
opts.thinkingPolicy as (
|
|
517
|
-
ctx: StatefulAgentContext<S>,
|
|
518
|
-
) => ChatThinkingPolicy | undefined | Promise<ChatThinkingPolicy | undefined>
|
|
519
|
-
)({ ...ctx, state });
|
|
520
|
-
}
|
|
521
|
-
: opts.thinkingPolicy;
|
|
522
|
-
|
|
523
|
-
const wrappedTailContext: TailContextInput | undefined =
|
|
524
|
-
typeof opts.tailContext === 'function'
|
|
525
|
-
? async (ctx: SystemPromptContext) => {
|
|
526
|
-
if (!state) {
|
|
527
|
-
throw new Error(`Stateful agent "${opts.name}" tailContext called before init`);
|
|
528
|
-
}
|
|
529
|
-
return (opts.tailContext as (ctx: StatefulAgentContext<S>) => string | Promise<string>)({
|
|
530
|
-
...ctx,
|
|
531
|
-
state,
|
|
532
|
-
});
|
|
533
|
-
}
|
|
534
|
-
: opts.tailContext;
|
|
535
|
-
|
|
536
|
-
// `onUnresolvedTool` threads `state` in like the resolvers above, but unlike
|
|
537
|
-
// them returns `undefined` before init rather than throwing: it fires on the
|
|
538
|
-
// tool-dispatch path, so a pre-init call must degrade to the framework
|
|
539
|
-
// default instead of breaking dispatch.
|
|
540
|
-
const wrappedOnUnresolvedTool: UnresolvedToolInput | undefined =
|
|
541
|
-
typeof opts.onUnresolvedTool === 'function'
|
|
542
|
-
? async (ctx) => {
|
|
543
|
-
if (!state) {
|
|
544
|
-
return undefined;
|
|
545
|
-
}
|
|
546
|
-
return opts.onUnresolvedTool!({ ...ctx, state });
|
|
547
|
-
}
|
|
548
|
-
: opts.onUnresolvedTool;
|
|
549
|
-
|
|
550
|
-
// `resumable` threads the LIVE state bag in (like the resolvers above) rather
|
|
551
|
-
// than the serialized image the raw `AgentConfig` form receives — so a machine
|
|
552
|
-
// agent gates on `state.machine.state` directly. Consulted only while active
|
|
553
|
-
// (state is set); a pre-init call degrades to `true` (resumable, fail-safe).
|
|
554
|
-
const wrappedResumable: AgentConfig['resumable'] | undefined = opts.resumable
|
|
555
|
-
? async (ctx: AgentPersistenceContext): Promise<boolean> => {
|
|
556
|
-
if (state === undefined) return true;
|
|
557
|
-
return opts.resumable!({
|
|
558
|
-
agentName: ctx.agentName,
|
|
559
|
-
sessionKey: ctx.sessionKey,
|
|
560
|
-
messages: ctx.messages,
|
|
561
|
-
isFlowOwner: ctx.isFlowOwner,
|
|
562
|
-
state,
|
|
563
|
-
});
|
|
564
|
-
}
|
|
565
|
-
: undefined;
|
|
566
|
-
|
|
567
|
-
const base = {
|
|
568
|
-
name: opts.name,
|
|
569
|
-
displayName: wrappedDisplayName,
|
|
570
|
-
primerHistory: opts.primerHistory,
|
|
571
|
-
subAgents: opts.subAgents,
|
|
572
|
-
manualSelection: opts.manualSelection,
|
|
573
|
-
chatInputDuringExecution: opts.chatInputDuringExecution,
|
|
574
|
-
toolDefinitions: wrappedTools,
|
|
575
|
-
toolHandlers: wrappedHandlers,
|
|
576
|
-
provider: wrappedProvider,
|
|
577
|
-
temperature: wrappedTemperature,
|
|
578
|
-
toolChoice: wrappedToolChoice,
|
|
579
|
-
cachePolicy: wrappedCachePolicy,
|
|
580
|
-
thinkingPolicy: wrappedThinkingPolicy,
|
|
581
|
-
tailContext: wrappedTailContext,
|
|
582
|
-
onUnresolvedTool: wrappedOnUnresolvedTool,
|
|
583
|
-
resumable: wrappedResumable,
|
|
584
|
-
notResumableMessage: opts.notResumableMessage,
|
|
585
|
-
|
|
586
|
-
onActivate: async (ctx: AgentLifecycleContext) => {
|
|
587
|
-
state = await opts.init(ctx);
|
|
588
|
-
// Sample once with the init state to fail loud on fold misuse at the
|
|
589
|
-
// agent-switch boundary instead of waiting for the first tool call.
|
|
590
|
-
// The driver re-resolves the factory each iteration, so misuse on
|
|
591
|
-
// handlers gated behind a non-init state surfaces when that state is
|
|
592
|
-
// reached — same loud failure mode, narrower coverage.
|
|
593
|
-
if (opts.toolHandlers) {
|
|
594
|
-
const sampled = await opts.toolHandlers(state);
|
|
595
|
-
assertNoFolds(sampled);
|
|
596
|
-
}
|
|
597
|
-
},
|
|
598
|
-
|
|
599
|
-
onDeactivate: async (ctx: AgentLifecycleContext) => {
|
|
600
|
-
if (state !== undefined && opts.dispose) {
|
|
601
|
-
await opts.dispose({ ...ctx, state });
|
|
602
|
-
}
|
|
603
|
-
// Orchestrator serializes onActivate/onDeactivate; concurrent calls
|
|
604
|
-
// cannot interleave the read-then-write of `state`.
|
|
605
|
-
// eslint-disable-next-line require-atomic-updates
|
|
606
|
-
state = undefined;
|
|
607
|
-
},
|
|
608
|
-
|
|
609
|
-
systemPrompt: opts.systemPrompt
|
|
610
|
-
? async (ctx: SystemPromptContext) => {
|
|
611
|
-
if (!state) {
|
|
612
|
-
throw new Error(`Stateful agent "${opts.name}" systemPrompt called before init`);
|
|
613
|
-
}
|
|
614
|
-
return opts.systemPrompt!({ ...ctx, state });
|
|
615
|
-
}
|
|
616
|
-
: undefined,
|
|
617
|
-
|
|
618
|
-
// Called per LLM call by ChatDriver, and once at debug-log export time.
|
|
619
|
-
// Returns `undefined` before activation (state hasn't been built yet) and
|
|
620
|
-
// after deactivation (state was disposed) — the snapshotter is best-effort
|
|
621
|
-
// and the driver tolerates undefined.
|
|
622
|
-
getDebugSnapshot: () => {
|
|
623
|
-
if (!state) return undefined;
|
|
624
|
-
return opts.getDebugSnapshot
|
|
625
|
-
? opts.getDebugSnapshot(state)
|
|
626
|
-
: defaultStatefulDebugSnapshot(state);
|
|
627
|
-
},
|
|
628
|
-
|
|
629
|
-
// Lossless restore image for session persistence (see `serialize` on the
|
|
630
|
-
// config). Returns undefined before activation / after disposal.
|
|
631
|
-
serialize: () => {
|
|
632
|
-
if (state === undefined) return undefined;
|
|
633
|
-
return opts.serialize ? opts.serialize(state) : defaultStatefulSerialize(state);
|
|
634
|
-
},
|
|
635
|
-
};
|
|
636
|
-
|
|
637
|
-
return {
|
|
638
|
-
...base,
|
|
639
|
-
description: opts.description,
|
|
640
|
-
excludeFromClassifier: opts.excludeFromClassifier,
|
|
641
|
-
} as AgentConfig;
|
|
642
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import type { FallbackAgentConfig } from './config';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A warm, conversational fallback agent. Acknowledges it can't help directly,
|
|
5
|
-
* explains what the available specialists can do, and invites the user to retry.
|
|
6
|
-
*
|
|
7
|
-
* The system prompt is generated at runtime by `OrchestratingDriver` from the
|
|
8
|
-
* specialist list — no manual authoring required.
|
|
9
|
-
*
|
|
10
|
-
* @beta
|
|
11
|
-
*/
|
|
12
|
-
export const friendlyFallbackAgent: FallbackAgentConfig = {
|
|
13
|
-
name: 'Assistant',
|
|
14
|
-
fallback: true,
|
|
15
|
-
systemPrompt: `You are a warm, friendly assistant. For general conversation like "Hi" or "How are you", you can have a friendly chat. For anything more complex, you cannot directly help, but you can explain what specialists are available. The available specialists are:\n\n{{agents}}\n\nPolitely let the user know what you can help with and invite them to rephrase their request if it is outside your scope.`,
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* A brief, professional fallback agent. States what is available without
|
|
20
|
-
* elaboration. The `{{agents}}` placeholder is replaced at runtime by
|
|
21
|
-
* `OrchestratingDriver` with the generated specialist list.
|
|
22
|
-
*
|
|
23
|
-
* @beta
|
|
24
|
-
*/
|
|
25
|
-
export const strictFallbackAgent: FallbackAgentConfig = {
|
|
26
|
-
name: 'Assistant',
|
|
27
|
-
fallback: true,
|
|
28
|
-
systemPrompt: `You are a concise assistant. The user's request is outside your scope. Respond with a single short sentence stating what you can assist with. Do not elaborate. The available specialists are: {{agents}}.`,
|
|
29
|
-
};
|
package/src/config/index.ts
DELETED