@theokit/sdk 2.13.1 → 2.15.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 (46) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/a2a/index.cjs +242 -3
  3. package/dist/a2a/index.cjs.map +1 -1
  4. package/dist/a2a/index.js +242 -3
  5. package/dist/a2a/index.js.map +1 -1
  6. package/dist/{cron-CpxLdAXc.d.cts → cron-BxLSz1UH.d.cts} +1 -1
  7. package/dist/{cron-CL_9nfhQ.d.ts → cron-DcaoP7aW.d.ts} +1 -1
  8. package/dist/cron.cjs +225 -3
  9. package/dist/cron.cjs.map +1 -1
  10. package/dist/cron.d.cts +2 -2
  11. package/dist/cron.d.ts +2 -2
  12. package/dist/cron.js +225 -3
  13. package/dist/cron.js.map +1 -1
  14. package/dist/define-tool.d.ts +8 -0
  15. package/dist/{errors-9yw4UQwX.d.cts → errors-Bart0ptP.d.cts} +1 -1
  16. package/dist/{errors-DFiY-NHK.d.ts → errors-DJuuubJK.d.ts} +1 -1
  17. package/dist/errors.d.cts +2 -2
  18. package/dist/eval.cjs +228 -6
  19. package/dist/eval.cjs.map +1 -1
  20. package/dist/eval.js +228 -6
  21. package/dist/eval.js.map +1 -1
  22. package/dist/index.cjs +230 -4
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +41 -6
  25. package/dist/index.d.ts +41 -6
  26. package/dist/index.js +230 -4
  27. package/dist/index.js.map +1 -1
  28. package/dist/internal/agent-loop/doom-loop-tracker.d.ts +22 -0
  29. package/dist/internal/agent-loop/loop-types.d.ts +6 -0
  30. package/dist/internal/llm/hermes-tool-extract.d.ts +1 -0
  31. package/dist/{run-TMdc7gmo.d.cts → run-DXy_MVwz.d.cts} +29 -1
  32. package/dist/{run-TMdc7gmo.d.ts → run-DXy_MVwz.d.ts} +29 -1
  33. package/dist/sanitize/coerce.d.cts +1 -0
  34. package/dist/sanitize/coerce.d.ts +1 -0
  35. package/dist/sanitize/index.cjs +119 -0
  36. package/dist/sanitize/index.cjs.map +1 -0
  37. package/dist/sanitize/index.d.cts +9 -0
  38. package/dist/sanitize/index.d.ts +9 -0
  39. package/dist/sanitize/index.js +116 -0
  40. package/dist/sanitize/index.js.map +1 -0
  41. package/dist/sanitize/sanitize-tool-input.d.cts +11 -0
  42. package/dist/sanitize/sanitize-tool-input.d.ts +11 -0
  43. package/dist/sanitize/types.d.cts +39 -0
  44. package/dist/sanitize/types.d.ts +39 -0
  45. package/dist/types/run.d.ts +28 -0
  46. package/package.json +13 -2
package/dist/index.d.cts CHANGED
@@ -1,9 +1,9 @@
1
- import { T as TheokitAgentError, B as BudgetOptions, a as BudgetHandle, b as BudgetSnapshot } from './errors-9yw4UQwX.cjs';
2
- export { A as AgentDisposedError, c as AgentRunError, d as AgentRunErrorCode, e as AuthenticationError, f as BudgetExceedEvent, g as BudgetExceededError, h as BudgetLimit, i as BudgetMode, j as BudgetScope, k as BudgetThresholdEvent, l as BudgetWindow, C as ConfigurationError, E as ErrorCode, m as ErrorMetadata, I as IntegrationNotConnectedError, n as InvalidTaskIdError, M as MemoryAdapterError, o as MemoryAdapterErrorCode, N as NetworkError, R as RateLimitError, p as TaskNotFoundError, U as UnknownAgentError, q as UnsupportedBudgetOperationError, r as UnsupportedRunOperationError, s as UnsupportedTaskOperationError, t as isTransientError } from './errors-9yw4UQwX.cjs';
3
- import { A as AgentOptions, L as LocalOptions, P as ProviderRoutingSettings, S as SystemPromptResolver, C as CloudOptions, M as MemorySettings, a as AgentDefinition, b as ContextSettings, c as PluginsSettings, d as SkillsSettings, e as SDKAgent, f as ListAgentsOptions, g as ListResult, h as SDKAgentInfo, G as GetAgentOptions, i as ListRunsOptions, j as GetRunOptions, k as AgentOperationOptions, l as ProviderProfile, m as Plugin, n as ConversationStorageAdapter, o as StoredMessage, B as BudgetTracker, p as MemoryProvider, q as MemoryId, r as PreToolCallDecision, s as SDKProvider } from './cron-CpxLdAXc.cjs';
4
- export { t as ActiveMemoryPassArgs, u as ActiveMemoryPassResult, v as AgentMemory, w as BudgetCheck, x as BudgetTotal, y as BudgetUsageEvent, z as CloudEnv, D as CloudRepo, E as ContextBudget, F as ContextManagerKind, H as ContextSnapshot, I as ContextSource, J as ContextSourceStatus, K as Cron, N as CronCreateOptions, O as CronGetOptions, Q as CronJob, R as CronJobStatus, T as CronListOptions, U as CronOperationOptions, V as CronRunOptions, W as CronRuntime, X as CronSchedulerStatus, Y as CronStartOptions, Z as GoalEvent, _ as GoalOptions, $ as GoalResult, a0 as HookName, a1 as InvalidateCacheOptions, a2 as MemoryAdapter, a3 as MemoryAdapterCapabilities, a4 as MemoryContext, a5 as MemoryFact, a6 as MemoryProviderHandle, a7 as MemoryProviderInitOptions, a8 as MemoryRevision, a9 as MemoryToolSchema, aa as MemoryTurnMessage, ab as PersonalityPreset, ac as PluginContext, ad as PostAssistantReplyContext, ae as PreToolCallContext, af as PreUserSendContext, ag as PreUserSendResult, ah as ProviderCapability, ai as ProviderRoute, aj as RecordSessionSummaryArgs, ak as ResolvedProviderRoute, al as RunUntilIterator, am as SDKAgentPlugins, an as SDKAgentSkills, ao as SDKArtifact, ap as SDKContextManager, aq as SDKPluginMetadata, ar as SDKProvidersManager, as as SettingSource, at as SystemPromptContext, au as SystemPromptMemoryFact, av as SystemPromptSkillRef, aw as TelemetrySettings, ax as definePlugin } from './cron-CpxLdAXc.cjs';
5
- import { R as RunResult, M as ModelSelection, C as CustomTool, a as McpServerConfig, b as Run, S as SDKMessage } from './run-TMdc7gmo.cjs';
6
- export { A as AgentConversationTurn, c as AssistantMessage, d as ConversationStep, e as ConversationTurn, f as CostBreakdown, g as CostSource, h as CostStatus, I as InteractionUpdate, i as McpAuthConfig, j as McpHttpServerConfig, k as McpOAuthConfig, l as McpStdioServerConfig, m as ModelParameterValue, P as PartialToolCallUpdate, n as RunErrorDetail, o as RunGitInfo, p as RunOperation, q as RunStatus, r as RunToCompletionOptions, s as RunToCompletionResult, t as SDKAssistantMessage, u as SDKImage, v as SDKImageDimension, w as SDKObjectDelta, x as SDKRequestMessage, y as SDKStatusMessage, z as SDKSystemMessage, B as SDKTaskMessage, D as SDKThinkingMessage, E as SDKToolUseMessage, F as SDKUserMessage, G as SDKUserMessageEvent, H as SendOptions, J as ShellCommand, K as ShellConversationTurn, L as ShellOutput, N as ShellOutputDeltaUpdate, O as StepCompletedUpdate, Q as StepStartedUpdate, T as StreamToCompletionResult, U as SummaryCompletedUpdate, V as SummaryStartedUpdate, W as SummaryUpdate, X as TextBlock, Y as TextDeltaUpdate, Z as ThinkingCompletedUpdate, _ as ThinkingDeltaUpdate, $ as ThinkingMessage, a0 as TokenDeltaUpdate, a1 as TokenUsage, a2 as ToolCall, a3 as ToolCallCompletedUpdate, a4 as ToolCallStartedUpdate, a5 as ToolResult, a6 as ToolUseBlock, a7 as TurnEndedUpdate, a8 as UserMessage, a9 as UserMessageAppendedUpdate } from './run-TMdc7gmo.cjs';
1
+ import { T as TheokitAgentError, B as BudgetOptions, a as BudgetHandle, b as BudgetSnapshot } from './errors-Bart0ptP.cjs';
2
+ export { A as AgentDisposedError, c as AgentRunError, d as AgentRunErrorCode, e as AuthenticationError, f as BudgetExceedEvent, g as BudgetExceededError, h as BudgetLimit, i as BudgetMode, j as BudgetScope, k as BudgetThresholdEvent, l as BudgetWindow, C as ConfigurationError, E as ErrorCode, m as ErrorMetadata, I as IntegrationNotConnectedError, n as InvalidTaskIdError, M as MemoryAdapterError, o as MemoryAdapterErrorCode, N as NetworkError, R as RateLimitError, p as TaskNotFoundError, U as UnknownAgentError, q as UnsupportedBudgetOperationError, r as UnsupportedRunOperationError, s as UnsupportedTaskOperationError, t as isTransientError } from './errors-Bart0ptP.cjs';
3
+ import { A as AgentOptions, L as LocalOptions, P as ProviderRoutingSettings, S as SystemPromptResolver, C as CloudOptions, M as MemorySettings, a as AgentDefinition, b as ContextSettings, c as PluginsSettings, d as SkillsSettings, e as SDKAgent, f as ListAgentsOptions, g as ListResult, h as SDKAgentInfo, G as GetAgentOptions, i as ListRunsOptions, j as GetRunOptions, k as AgentOperationOptions, l as ProviderProfile, m as Plugin, n as ConversationStorageAdapter, o as StoredMessage, B as BudgetTracker, p as MemoryProvider, q as MemoryId, r as PreToolCallDecision, s as SDKProvider } from './cron-BxLSz1UH.cjs';
4
+ export { t as ActiveMemoryPassArgs, u as ActiveMemoryPassResult, v as AgentMemory, w as BudgetCheck, x as BudgetTotal, y as BudgetUsageEvent, z as CloudEnv, D as CloudRepo, E as ContextBudget, F as ContextManagerKind, H as ContextSnapshot, I as ContextSource, J as ContextSourceStatus, K as Cron, N as CronCreateOptions, O as CronGetOptions, Q as CronJob, R as CronJobStatus, T as CronListOptions, U as CronOperationOptions, V as CronRunOptions, W as CronRuntime, X as CronSchedulerStatus, Y as CronStartOptions, Z as GoalEvent, _ as GoalOptions, $ as GoalResult, a0 as HookName, a1 as InvalidateCacheOptions, a2 as MemoryAdapter, a3 as MemoryAdapterCapabilities, a4 as MemoryContext, a5 as MemoryFact, a6 as MemoryProviderHandle, a7 as MemoryProviderInitOptions, a8 as MemoryRevision, a9 as MemoryToolSchema, aa as MemoryTurnMessage, ab as PersonalityPreset, ac as PluginContext, ad as PostAssistantReplyContext, ae as PreToolCallContext, af as PreUserSendContext, ag as PreUserSendResult, ah as ProviderCapability, ai as ProviderRoute, aj as RecordSessionSummaryArgs, ak as ResolvedProviderRoute, al as RunUntilIterator, am as SDKAgentPlugins, an as SDKAgentSkills, ao as SDKArtifact, ap as SDKContextManager, aq as SDKPluginMetadata, ar as SDKProvidersManager, as as SettingSource, at as SystemPromptContext, au as SystemPromptMemoryFact, av as SystemPromptSkillRef, aw as TelemetrySettings, ax as definePlugin } from './cron-BxLSz1UH.cjs';
5
+ import { R as RunResult, M as ModelSelection, C as CustomTool, a as McpServerConfig, b as Run, S as SDKMessage } from './run-DXy_MVwz.cjs';
6
+ export { A as AgentConversationTurn, c as AssistantMessage, d as ConversationStep, e as ConversationTurn, f as CostBreakdown, g as CostSource, h as CostStatus, D as DoomLoopThresholds, I as InteractionUpdate, i as McpAuthConfig, j as McpHttpServerConfig, k as McpOAuthConfig, l as McpStdioServerConfig, m as ModelParameterValue, P as PartialToolCallUpdate, n as RunErrorDetail, o as RunGitInfo, p as RunOperation, q as RunStatus, r as RunToCompletionOptions, s as RunToCompletionResult, t as SDKAssistantMessage, u as SDKImage, v as SDKImageDimension, w as SDKObjectDelta, x as SDKRequestMessage, y as SDKStatusMessage, z as SDKSystemMessage, B as SDKTaskMessage, E as SDKThinkingMessage, F as SDKToolUseMessage, G as SDKUserMessage, H as SDKUserMessageEvent, J as SendOptions, K as ShellCommand, L as ShellConversationTurn, N as ShellOutput, O as ShellOutputDeltaUpdate, Q as StepCompletedUpdate, T as StepStartedUpdate, U as StreamToCompletionResult, V as SummaryCompletedUpdate, W as SummaryStartedUpdate, X as SummaryUpdate, Y as TextBlock, Z as TextDeltaUpdate, _ as ThinkingCompletedUpdate, $ as ThinkingDeltaUpdate, a0 as ThinkingMessage, a1 as TokenDeltaUpdate, a2 as TokenUsage, a3 as ToolCall, a4 as ToolCallCompletedUpdate, a5 as ToolCallStartedUpdate, a6 as ToolResult, a7 as ToolUseBlock, a8 as TurnEndedUpdate, a9 as UserMessage, aa as UserMessageAppendedUpdate } from './run-DXy_MVwz.cjs';
7
7
  import * as zod from 'zod';
8
8
  import { ZodType, z } from 'zod';
9
9
 
@@ -863,6 +863,34 @@ interface DefineProviderOptions {
863
863
  */
864
864
  declare function defineProvider(profile: ProviderProfile, opts?: DefineProviderOptions): Plugin;
865
865
 
866
+ /**
867
+ * Options for {@link sanitizeToolInput}. Trim is the only default-on rung — coercion and JSON
868
+ * repair change a value's representation, so they are opt-in (the SDK's "values are strings; Zod
869
+ * coerces" boundary; see `define-tool.ts` doc-comment).
870
+ *
871
+ * @public
872
+ */
873
+ interface SanitizeOptions {
874
+ /** Trim leading/trailing whitespace from string values. Default `true`. */
875
+ trim?: boolean;
876
+ /** Coerce string values to typed values (`"5"`→`5`, `"true"`→`true`, `"null"`→`null`, JSON). Default `false`. */
877
+ coerce?: boolean;
878
+ /** Repair-then-parse malformed JSON-looking string values (via `jsonrepair`). Default `false`. */
879
+ repairJson?: boolean;
880
+ /**
881
+ * Optional Zod schema. When it is a `z.object(...)`, coercion is schema-aware: each TOP-LEVEL
882
+ * field is coerced only toward a candidate its field-schema accepts (so a `z.string()` field
883
+ * keeps `"5"` as a string). Non-object schemas (union/record) fall back to heuristic coercion.
884
+ * Note: with `deep: true`, nested fields always use heuristic coercion (the schema is not
885
+ * descended into).
886
+ */
887
+ schema?: ZodType;
888
+ /** Recurse into nested objects/arrays. Default `false` (shallow). */
889
+ deep?: boolean;
890
+ /** Max recursion depth when `deep` is set. Default `8`. */
891
+ maxDepth?: number;
892
+ }
893
+
866
894
  /**
867
895
  * Spec accepted by {@link defineTool}. `inputSchema` is a Zod schema; the
868
896
  * `handler` argument type is inferred via `z.infer<T>` — no `as` casts.
@@ -878,6 +906,13 @@ interface DefineToolSpec<T extends ZodType> {
878
906
  inputSchema: T;
879
907
  /** Handler invoked with the parsed input. Type is inferred via `z.infer<T>`. */
880
908
  handler: (input: z.infer<T>) => string | Promise<string>;
909
+ /**
910
+ * Sanitize the raw model-emitted args BEFORE schema validation (`@theokit/sdk/sanitize`).
911
+ * `true` trims whitespace; an object opts into coercion / JSON-repair. Coercion is schema-aware
912
+ * against this tool's `inputSchema`. Absent ⇒ args reach validation untouched. Sanitize is
913
+ * hygiene, not a validity bypass — a genuinely invalid arg still raises `ZodError`.
914
+ */
915
+ sanitize?: boolean | SanitizeOptions;
881
916
  }
882
917
  /**
883
918
  * Type-safe builder for {@link CustomTool}. Converts a Zod schema to JSON
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { T as TheokitAgentError, B as BudgetOptions, a as BudgetHandle, b as BudgetSnapshot } from './errors-DFiY-NHK.js';
2
- export { A as AgentDisposedError, c as AgentRunError, d as AgentRunErrorCode, e as AuthenticationError, f as BudgetExceedEvent, g as BudgetExceededError, h as BudgetLimit, i as BudgetMode, j as BudgetScope, k as BudgetThresholdEvent, l as BudgetWindow, C as ConfigurationError, E as ErrorCode, m as ErrorMetadata, I as IntegrationNotConnectedError, n as InvalidTaskIdError, M as MemoryAdapterError, o as MemoryAdapterErrorCode, N as NetworkError, R as RateLimitError, p as TaskNotFoundError, U as UnknownAgentError, q as UnsupportedBudgetOperationError, r as UnsupportedRunOperationError, s as UnsupportedTaskOperationError, t as isTransientError } from './errors-DFiY-NHK.js';
3
- import { A as AgentOptions, L as LocalOptions, P as ProviderRoutingSettings, S as SystemPromptResolver, C as CloudOptions, M as MemorySettings, a as AgentDefinition, b as ContextSettings, c as PluginsSettings, d as SkillsSettings, e as SDKAgent, f as ListAgentsOptions, g as ListResult, h as SDKAgentInfo, G as GetAgentOptions, i as ListRunsOptions, j as GetRunOptions, k as AgentOperationOptions, l as ProviderProfile, m as Plugin, n as ConversationStorageAdapter, o as StoredMessage, B as BudgetTracker, p as MemoryProvider, q as MemoryId, r as PreToolCallDecision, s as SDKProvider } from './cron-CL_9nfhQ.js';
4
- export { t as ActiveMemoryPassArgs, u as ActiveMemoryPassResult, v as AgentMemory, w as BudgetCheck, x as BudgetTotal, y as BudgetUsageEvent, z as CloudEnv, D as CloudRepo, E as ContextBudget, F as ContextManagerKind, H as ContextSnapshot, I as ContextSource, J as ContextSourceStatus, K as Cron, N as CronCreateOptions, O as CronGetOptions, Q as CronJob, R as CronJobStatus, T as CronListOptions, U as CronOperationOptions, V as CronRunOptions, W as CronRuntime, X as CronSchedulerStatus, Y as CronStartOptions, Z as GoalEvent, _ as GoalOptions, $ as GoalResult, a0 as HookName, a1 as InvalidateCacheOptions, a2 as MemoryAdapter, a3 as MemoryAdapterCapabilities, a4 as MemoryContext, a5 as MemoryFact, a6 as MemoryProviderHandle, a7 as MemoryProviderInitOptions, a8 as MemoryRevision, a9 as MemoryToolSchema, aa as MemoryTurnMessage, ab as PersonalityPreset, ac as PluginContext, ad as PostAssistantReplyContext, ae as PreToolCallContext, af as PreUserSendContext, ag as PreUserSendResult, ah as ProviderCapability, ai as ProviderRoute, aj as RecordSessionSummaryArgs, ak as ResolvedProviderRoute, al as RunUntilIterator, am as SDKAgentPlugins, an as SDKAgentSkills, ao as SDKArtifact, ap as SDKContextManager, aq as SDKPluginMetadata, ar as SDKProvidersManager, as as SettingSource, at as SystemPromptContext, au as SystemPromptMemoryFact, av as SystemPromptSkillRef, aw as TelemetrySettings, ax as definePlugin } from './cron-CL_9nfhQ.js';
5
- import { R as RunResult, M as ModelSelection, C as CustomTool, a as McpServerConfig, b as Run, S as SDKMessage } from './run-TMdc7gmo.js';
6
- export { A as AgentConversationTurn, c as AssistantMessage, d as ConversationStep, e as ConversationTurn, f as CostBreakdown, g as CostSource, h as CostStatus, I as InteractionUpdate, i as McpAuthConfig, j as McpHttpServerConfig, k as McpOAuthConfig, l as McpStdioServerConfig, m as ModelParameterValue, P as PartialToolCallUpdate, n as RunErrorDetail, o as RunGitInfo, p as RunOperation, q as RunStatus, r as RunToCompletionOptions, s as RunToCompletionResult, t as SDKAssistantMessage, u as SDKImage, v as SDKImageDimension, w as SDKObjectDelta, x as SDKRequestMessage, y as SDKStatusMessage, z as SDKSystemMessage, B as SDKTaskMessage, D as SDKThinkingMessage, E as SDKToolUseMessage, F as SDKUserMessage, G as SDKUserMessageEvent, H as SendOptions, J as ShellCommand, K as ShellConversationTurn, L as ShellOutput, N as ShellOutputDeltaUpdate, O as StepCompletedUpdate, Q as StepStartedUpdate, T as StreamToCompletionResult, U as SummaryCompletedUpdate, V as SummaryStartedUpdate, W as SummaryUpdate, X as TextBlock, Y as TextDeltaUpdate, Z as ThinkingCompletedUpdate, _ as ThinkingDeltaUpdate, $ as ThinkingMessage, a0 as TokenDeltaUpdate, a1 as TokenUsage, a2 as ToolCall, a3 as ToolCallCompletedUpdate, a4 as ToolCallStartedUpdate, a5 as ToolResult, a6 as ToolUseBlock, a7 as TurnEndedUpdate, a8 as UserMessage, a9 as UserMessageAppendedUpdate } from './run-TMdc7gmo.js';
1
+ import { T as TheokitAgentError, B as BudgetOptions, a as BudgetHandle, b as BudgetSnapshot } from './errors-DJuuubJK.js';
2
+ export { A as AgentDisposedError, c as AgentRunError, d as AgentRunErrorCode, e as AuthenticationError, f as BudgetExceedEvent, g as BudgetExceededError, h as BudgetLimit, i as BudgetMode, j as BudgetScope, k as BudgetThresholdEvent, l as BudgetWindow, C as ConfigurationError, E as ErrorCode, m as ErrorMetadata, I as IntegrationNotConnectedError, n as InvalidTaskIdError, M as MemoryAdapterError, o as MemoryAdapterErrorCode, N as NetworkError, R as RateLimitError, p as TaskNotFoundError, U as UnknownAgentError, q as UnsupportedBudgetOperationError, r as UnsupportedRunOperationError, s as UnsupportedTaskOperationError, t as isTransientError } from './errors-DJuuubJK.js';
3
+ import { A as AgentOptions, L as LocalOptions, P as ProviderRoutingSettings, S as SystemPromptResolver, C as CloudOptions, M as MemorySettings, a as AgentDefinition, b as ContextSettings, c as PluginsSettings, d as SkillsSettings, e as SDKAgent, f as ListAgentsOptions, g as ListResult, h as SDKAgentInfo, G as GetAgentOptions, i as ListRunsOptions, j as GetRunOptions, k as AgentOperationOptions, l as ProviderProfile, m as Plugin, n as ConversationStorageAdapter, o as StoredMessage, B as BudgetTracker, p as MemoryProvider, q as MemoryId, r as PreToolCallDecision, s as SDKProvider } from './cron-DcaoP7aW.js';
4
+ export { t as ActiveMemoryPassArgs, u as ActiveMemoryPassResult, v as AgentMemory, w as BudgetCheck, x as BudgetTotal, y as BudgetUsageEvent, z as CloudEnv, D as CloudRepo, E as ContextBudget, F as ContextManagerKind, H as ContextSnapshot, I as ContextSource, J as ContextSourceStatus, K as Cron, N as CronCreateOptions, O as CronGetOptions, Q as CronJob, R as CronJobStatus, T as CronListOptions, U as CronOperationOptions, V as CronRunOptions, W as CronRuntime, X as CronSchedulerStatus, Y as CronStartOptions, Z as GoalEvent, _ as GoalOptions, $ as GoalResult, a0 as HookName, a1 as InvalidateCacheOptions, a2 as MemoryAdapter, a3 as MemoryAdapterCapabilities, a4 as MemoryContext, a5 as MemoryFact, a6 as MemoryProviderHandle, a7 as MemoryProviderInitOptions, a8 as MemoryRevision, a9 as MemoryToolSchema, aa as MemoryTurnMessage, ab as PersonalityPreset, ac as PluginContext, ad as PostAssistantReplyContext, ae as PreToolCallContext, af as PreUserSendContext, ag as PreUserSendResult, ah as ProviderCapability, ai as ProviderRoute, aj as RecordSessionSummaryArgs, ak as ResolvedProviderRoute, al as RunUntilIterator, am as SDKAgentPlugins, an as SDKAgentSkills, ao as SDKArtifact, ap as SDKContextManager, aq as SDKPluginMetadata, ar as SDKProvidersManager, as as SettingSource, at as SystemPromptContext, au as SystemPromptMemoryFact, av as SystemPromptSkillRef, aw as TelemetrySettings, ax as definePlugin } from './cron-DcaoP7aW.js';
5
+ import { R as RunResult, M as ModelSelection, C as CustomTool, a as McpServerConfig, b as Run, S as SDKMessage } from './run-DXy_MVwz.js';
6
+ export { A as AgentConversationTurn, c as AssistantMessage, d as ConversationStep, e as ConversationTurn, f as CostBreakdown, g as CostSource, h as CostStatus, D as DoomLoopThresholds, I as InteractionUpdate, i as McpAuthConfig, j as McpHttpServerConfig, k as McpOAuthConfig, l as McpStdioServerConfig, m as ModelParameterValue, P as PartialToolCallUpdate, n as RunErrorDetail, o as RunGitInfo, p as RunOperation, q as RunStatus, r as RunToCompletionOptions, s as RunToCompletionResult, t as SDKAssistantMessage, u as SDKImage, v as SDKImageDimension, w as SDKObjectDelta, x as SDKRequestMessage, y as SDKStatusMessage, z as SDKSystemMessage, B as SDKTaskMessage, E as SDKThinkingMessage, F as SDKToolUseMessage, G as SDKUserMessage, H as SDKUserMessageEvent, J as SendOptions, K as ShellCommand, L as ShellConversationTurn, N as ShellOutput, O as ShellOutputDeltaUpdate, Q as StepCompletedUpdate, T as StepStartedUpdate, U as StreamToCompletionResult, V as SummaryCompletedUpdate, W as SummaryStartedUpdate, X as SummaryUpdate, Y as TextBlock, Z as TextDeltaUpdate, _ as ThinkingCompletedUpdate, $ as ThinkingDeltaUpdate, a0 as ThinkingMessage, a1 as TokenDeltaUpdate, a2 as TokenUsage, a3 as ToolCall, a4 as ToolCallCompletedUpdate, a5 as ToolCallStartedUpdate, a6 as ToolResult, a7 as ToolUseBlock, a8 as TurnEndedUpdate, a9 as UserMessage, aa as UserMessageAppendedUpdate } from './run-DXy_MVwz.js';
7
7
  import * as zod from 'zod';
8
8
  import { ZodType, z } from 'zod';
9
9
 
@@ -863,6 +863,34 @@ interface DefineProviderOptions {
863
863
  */
864
864
  declare function defineProvider(profile: ProviderProfile, opts?: DefineProviderOptions): Plugin;
865
865
 
866
+ /**
867
+ * Options for {@link sanitizeToolInput}. Trim is the only default-on rung — coercion and JSON
868
+ * repair change a value's representation, so they are opt-in (the SDK's "values are strings; Zod
869
+ * coerces" boundary; see `define-tool.ts` doc-comment).
870
+ *
871
+ * @public
872
+ */
873
+ interface SanitizeOptions {
874
+ /** Trim leading/trailing whitespace from string values. Default `true`. */
875
+ trim?: boolean;
876
+ /** Coerce string values to typed values (`"5"`→`5`, `"true"`→`true`, `"null"`→`null`, JSON). Default `false`. */
877
+ coerce?: boolean;
878
+ /** Repair-then-parse malformed JSON-looking string values (via `jsonrepair`). Default `false`. */
879
+ repairJson?: boolean;
880
+ /**
881
+ * Optional Zod schema. When it is a `z.object(...)`, coercion is schema-aware: each TOP-LEVEL
882
+ * field is coerced only toward a candidate its field-schema accepts (so a `z.string()` field
883
+ * keeps `"5"` as a string). Non-object schemas (union/record) fall back to heuristic coercion.
884
+ * Note: with `deep: true`, nested fields always use heuristic coercion (the schema is not
885
+ * descended into).
886
+ */
887
+ schema?: ZodType;
888
+ /** Recurse into nested objects/arrays. Default `false` (shallow). */
889
+ deep?: boolean;
890
+ /** Max recursion depth when `deep` is set. Default `8`. */
891
+ maxDepth?: number;
892
+ }
893
+
866
894
  /**
867
895
  * Spec accepted by {@link defineTool}. `inputSchema` is a Zod schema; the
868
896
  * `handler` argument type is inferred via `z.infer<T>` — no `as` casts.
@@ -878,6 +906,13 @@ interface DefineToolSpec<T extends ZodType> {
878
906
  inputSchema: T;
879
907
  /** Handler invoked with the parsed input. Type is inferred via `z.infer<T>`. */
880
908
  handler: (input: z.infer<T>) => string | Promise<string>;
909
+ /**
910
+ * Sanitize the raw model-emitted args BEFORE schema validation (`@theokit/sdk/sanitize`).
911
+ * `true` trims whitespace; an object opts into coercion / JSON-repair. Coercion is schema-aware
912
+ * against this tool's `inputSchema`. Absent ⇒ args reach validation untouched. Sanitize is
913
+ * hygiene, not a validity bypass — a genuinely invalid arg still raises `ZodError`.
914
+ */
915
+ sanitize?: boolean | SanitizeOptions;
881
916
  }
882
917
  /**
883
918
  * Type-safe builder for {@link CustomTool}. Converts a Zod schema to JSON
package/dist/index.js CHANGED
@@ -2814,6 +2814,7 @@ function isEmptyRound(result) {
2814
2814
  return (result.result ?? "").trim() === "";
2815
2815
  }
2816
2816
  function classifyRound(result, round, maxRounds, emptyStreak) {
2817
+ if (result.stoppedByDoomLoop === true) return "no_progress";
2817
2818
  if (result.stoppedAtIterationLimit !== true) return "done";
2818
2819
  if (isEmptyRound(result) && emptyStreak >= 1) return "no_progress";
2819
2820
  if (round >= maxRounds) return "step_limit";
@@ -6979,6 +6980,7 @@ function applyScriptMetrics(base, script) {
6979
6980
  if (script.usage !== void 0) base.usage = script.usage;
6980
6981
  if (script.cost !== void 0) base.cost = script.cost;
6981
6982
  if (script.stoppedAtIterationLimit === true) base.stoppedAtIterationLimit = true;
6983
+ if (script.stoppedByDoomLoop === true) base.stoppedByDoomLoop = true;
6982
6984
  }
6983
6985
 
6984
6986
  // src/internal/runtime/cloud/cloud-run.ts
@@ -10730,6 +10732,93 @@ function evaluateBudgetGate(tracker) {
10730
10732
  }
10731
10733
  }
10732
10734
 
10735
+ // src/internal/agent-loop/doom-loop-tracker.ts
10736
+ init_errors();
10737
+ function createDoomLoopTracker(option) {
10738
+ if (option === false) return void 0;
10739
+ return new DoomLoopTracker(option);
10740
+ }
10741
+ var DEFAULT_CONFIG = { softThreshold: 3, hardThreshold: 5 };
10742
+ function assertValidThresholds(soft, hard) {
10743
+ for (const [label, value] of [
10744
+ ["softThreshold", soft],
10745
+ ["hardThreshold", hard]
10746
+ ]) {
10747
+ if (!Number.isInteger(value) || value < 1) {
10748
+ throw new ConfigurationError(
10749
+ `doomLoop.${label} must be a positive integer (received ${value}).`,
10750
+ { code: "invalid_doom_loop_threshold" }
10751
+ );
10752
+ }
10753
+ }
10754
+ }
10755
+ function sortKeys(value) {
10756
+ if (value === null || typeof value !== "object") return value;
10757
+ if (Array.isArray(value)) return value.map(sortKeys);
10758
+ const out = {};
10759
+ for (const key2 of Object.keys(value).sort()) {
10760
+ out[key2] = sortKeys(value[key2]);
10761
+ }
10762
+ return out;
10763
+ }
10764
+ function signatureOf(call) {
10765
+ const { input } = call;
10766
+ let inputSig;
10767
+ if (input === null || input === void 0) inputSig = "null";
10768
+ else if (typeof input !== "object") inputSig = String(input);
10769
+ else {
10770
+ try {
10771
+ inputSig = JSON.stringify(sortKeys(input)) ?? "null";
10772
+ } catch {
10773
+ inputSig = String(input);
10774
+ }
10775
+ }
10776
+ return `${call.name}\0${inputSig}`;
10777
+ }
10778
+ var DoomLoopTracker = class {
10779
+ #config;
10780
+ #lastSignature = "";
10781
+ #count = 0;
10782
+ constructor(config) {
10783
+ const softThreshold = config?.softThreshold ?? DEFAULT_CONFIG.softThreshold;
10784
+ const hardThreshold = config?.hardThreshold ?? DEFAULT_CONFIG.hardThreshold;
10785
+ assertValidThresholds(softThreshold, hardThreshold);
10786
+ this.#config = { softThreshold, hardThreshold };
10787
+ }
10788
+ inspect(call) {
10789
+ const signature = signatureOf(call);
10790
+ this.#count = signature === this.#lastSignature ? this.#count + 1 : 1;
10791
+ this.#lastSignature = signature;
10792
+ const count = this.#count;
10793
+ if (count >= this.#config.hardThreshold) {
10794
+ return {
10795
+ kind: "hard",
10796
+ message: `Detected ${count} consecutive identical calls to \`${call.name}\`; stopping to avoid a loop.`
10797
+ };
10798
+ }
10799
+ if (count === this.#config.softThreshold) {
10800
+ return {
10801
+ kind: "soft",
10802
+ message: `Detected ${count} consecutive identical calls to \`${call.name}\`; try a different approach.`
10803
+ };
10804
+ }
10805
+ return { kind: "ok" };
10806
+ }
10807
+ reset() {
10808
+ this.#lastSignature = "";
10809
+ this.#count = 0;
10810
+ }
10811
+ };
10812
+ function firstDoomLoopVerdict(tracker, calls) {
10813
+ let escalation = { kind: "ok" };
10814
+ for (const call of calls) {
10815
+ const v = tracker.inspect(call);
10816
+ if (v.kind === "hard") return v;
10817
+ if (v.kind === "soft" && escalation.kind === "ok") escalation = v;
10818
+ }
10819
+ return escalation;
10820
+ }
10821
+
10733
10822
  // src/internal/budget/usage-accumulator.ts
10734
10823
  var UsageAccumulator = class {
10735
10824
  input = 0;
@@ -10910,6 +10999,7 @@ async function initLoopContext(inputs) {
10910
10999
  tools,
10911
11000
  finalText: "",
10912
11001
  finalStatus: "finished",
11002
+ doomLoop: createDoomLoopTracker(inputs.doomLoop),
10913
11003
  usage: new UsageAccumulator(),
10914
11004
  nudgeAttempts: 0,
10915
11005
  stopFeedbackAttempts: 0,
@@ -11934,6 +12024,7 @@ async function runAgentLoop(inputs) {
11934
12024
  ctx.finalStatus = "error";
11935
12025
  }
11936
12026
  sendSpan?.setAttribute("status", ctx.finalStatus);
12027
+ if (ctx.stoppedByDoomLoop === true) sendSpan?.setAttribute("stoppedByDoomLoop", true);
11937
12028
  if (inputs.telemetry?.includeContent === true && ctx.finalText.length > 0) {
11938
12029
  sendSpan?.addEvent("response", { content: ctx.finalText });
11939
12030
  }
@@ -11960,7 +12051,8 @@ async function runAgentLoop(inputs) {
11960
12051
  ...usage !== void 0 ? { usage } : {},
11961
12052
  ...cost !== void 0 ? { cost } : {},
11962
12053
  ...ctx.error !== void 0 ? { error: ctx.error } : {},
11963
- ...ctx.stoppedAtIterationLimit === true ? { stoppedAtIterationLimit: true } : {}
12054
+ ...ctx.stoppedAtIterationLimit === true ? { stoppedAtIterationLimit: true } : {},
12055
+ ...ctx.stoppedByDoomLoop === true ? { stoppedByDoomLoop: true } : {}
11964
12056
  };
11965
12057
  } finally {
11966
12058
  if (ctxRef !== void 0 && ctxRef.memoryProviderHandle !== void 0 && inputs.memoryProvider !== void 0) {
@@ -12119,8 +12211,26 @@ async function continueOrTerminate(inputs, ctx, llmOutput) {
12119
12211
  }
12120
12212
  }
12121
12213
  pushToolConversationSteps(ctx, llmOutput.toolCalls, toolResults);
12214
+ if (await inspectDoomLoop(inputs, ctx, llmOutput.toolCalls) === "stop") return "done";
12122
12215
  return handleToolErrorContinuation(inputs, ctx, toolResults);
12123
12216
  }
12217
+ async function inspectDoomLoop(inputs, ctx, toolCalls) {
12218
+ if (ctx.doomLoop === void 0) return "continue";
12219
+ const verdict = firstDoomLoopVerdict(ctx.doomLoop, toolCalls);
12220
+ if (verdict.kind === "hard") {
12221
+ ctx.stoppedByDoomLoop = true;
12222
+ await emitAssistantTextStep(
12223
+ inputs,
12224
+ ctx,
12225
+ verdict.message ?? "Stopped: repeated identical tool calls made no progress."
12226
+ );
12227
+ return "stop";
12228
+ }
12229
+ if (verdict.kind === "soft") {
12230
+ ctx.messages.push({ role: "user", content: [{ type: "text", text: verdict.message ?? "" }] });
12231
+ }
12232
+ return "continue";
12233
+ }
12124
12234
 
12125
12235
  // src/internal/llm/fallback-client.ts
12126
12236
  init_errors();
@@ -13424,6 +13534,115 @@ function toOllamaTools(tools) {
13424
13534
  }
13425
13535
  }));
13426
13536
  }
13537
+ var cachedJsonrepair;
13538
+ function loadJsonrepair() {
13539
+ if (cachedJsonrepair === void 0) {
13540
+ const req = createRequire(import.meta.url);
13541
+ cachedJsonrepair = req("jsonrepair").jsonrepair;
13542
+ }
13543
+ return cachedJsonrepair;
13544
+ }
13545
+ function isPlainObject(v) {
13546
+ return v !== null && typeof v === "object" && !Array.isArray(v);
13547
+ }
13548
+ function toFiniteNumber(raw) {
13549
+ if (raw === "") return void 0;
13550
+ const n = Number(raw);
13551
+ return Number.isFinite(n) && String(n) === raw ? n : void 0;
13552
+ }
13553
+ function tryJson(raw, repair) {
13554
+ const t = raw.trimStart();
13555
+ if (!(t.startsWith("{") || t.startsWith("["))) return void 0;
13556
+ try {
13557
+ return JSON.parse(repair ? loadJsonrepair()(t) : t);
13558
+ } catch {
13559
+ return void 0;
13560
+ }
13561
+ }
13562
+ function heuristicCoerce(raw, repairJson) {
13563
+ if (raw === "true") return true;
13564
+ if (raw === "false") return false;
13565
+ if (raw === "null") return null;
13566
+ const n = toFiniteNumber(raw);
13567
+ if (n !== void 0) return n;
13568
+ const json = tryJson(raw, false) ?? (repairJson ? tryJson(raw, true) : void 0);
13569
+ return json === void 0 ? raw : json;
13570
+ }
13571
+ function coerceCandidates(raw, repairJson) {
13572
+ const out = [];
13573
+ if (raw === "true") out.push(true);
13574
+ else if (raw === "false") out.push(false);
13575
+ else if (raw === "null") out.push(null);
13576
+ const n = toFiniteNumber(raw);
13577
+ if (n !== void 0) out.push(n);
13578
+ const json = tryJson(raw, false) ?? (repairJson ? tryJson(raw, true) : void 0);
13579
+ if (json !== void 0) out.push(json);
13580
+ out.push(raw);
13581
+ return out;
13582
+ }
13583
+ function objectShape(schema) {
13584
+ const shape = schema?.shape;
13585
+ return shape !== null && typeof shape === "object" ? shape : void 0;
13586
+ }
13587
+
13588
+ // src/sanitize/sanitize-tool-input.ts
13589
+ function applyTrim(key2, value, ctx) {
13590
+ const trimmed = value.trim();
13591
+ if (trimmed !== value) ctx.notes.push(`trimmed "${key2}"`);
13592
+ return trimmed;
13593
+ }
13594
+ function applyCoerce(key2, raw, ctx) {
13595
+ const field = ctx.shape?.[key2];
13596
+ let coerced = raw;
13597
+ if (field) {
13598
+ for (const candidate of coerceCandidates(raw, ctx.repairJson)) {
13599
+ if (field.safeParse(candidate).success) {
13600
+ coerced = candidate;
13601
+ break;
13602
+ }
13603
+ }
13604
+ } else {
13605
+ coerced = heuristicCoerce(raw, ctx.repairJson);
13606
+ }
13607
+ if (coerced !== raw) ctx.notes.push(`coerced "${key2}"`);
13608
+ return coerced;
13609
+ }
13610
+ function applyRepair(key2, value, ctx) {
13611
+ const repaired = tryJson(value, true);
13612
+ if (repaired === void 0) return value;
13613
+ ctx.notes.push(`repaired json "${key2}"`);
13614
+ return repaired;
13615
+ }
13616
+ function sanitizeString(key2, value, ctx) {
13617
+ let out = ctx.trim ? applyTrim(key2, value, ctx) : value;
13618
+ if (ctx.coerce && typeof out === "string") out = applyCoerce(key2, out, ctx);
13619
+ if (ctx.repairJson && !ctx.coerce && typeof out === "string") out = applyRepair(key2, out, ctx);
13620
+ return out;
13621
+ }
13622
+ function walk(input, ctx, depth) {
13623
+ const out = {};
13624
+ for (const [key2, value] of Object.entries(input)) {
13625
+ if (typeof value === "string") out[key2] = sanitizeString(key2, value, ctx);
13626
+ else if (ctx.deep && depth < ctx.maxDepth && isPlainObject(value))
13627
+ out[key2] = walk(value, ctx, depth + 1);
13628
+ else out[key2] = value;
13629
+ }
13630
+ return out;
13631
+ }
13632
+ function sanitizeToolInput(input, options) {
13633
+ if (!isPlainObject(input)) return { value: input, changed: false, notes: [] };
13634
+ const ctx = {
13635
+ trim: options?.trim ?? true,
13636
+ coerce: options?.coerce ?? false,
13637
+ repairJson: options?.repairJson ?? false,
13638
+ deep: options?.deep ?? false,
13639
+ maxDepth: options?.maxDepth ?? 8,
13640
+ shape: objectShape(options?.schema),
13641
+ notes: []
13642
+ };
13643
+ const value = walk(input, ctx, 0);
13644
+ return { value, changed: ctx.notes.length > 0, notes: ctx.notes };
13645
+ }
13427
13646
 
13428
13647
  // src/internal/llm/hermes-tool-extract.ts
13429
13648
  var HERMES_BLOCK = /<function=\s*([^>\s]+)\s*>([\s\S]*?)<\/tool_call>/g;
@@ -13449,9 +13668,9 @@ function parseHermesParams(inner) {
13449
13668
  const key2 = param[1];
13450
13669
  const value = param[2];
13451
13670
  if (key2 === void 0 || value === void 0) continue;
13452
- input[key2.trim()] = value.trim();
13671
+ input[key2.trim()] = value;
13453
13672
  }
13454
- return input;
13673
+ return sanitizeToolInput(input, { trim: true }).value;
13455
13674
  }
13456
13675
 
13457
13676
  // src/internal/llm/openai.ts
@@ -14572,6 +14791,8 @@ function buildLoopInputs(options, runId, userText) {
14572
14791
  // M1-2: per-send iteration ceiling (validated above). The loop reads
14573
14792
  // inputs.maxIterations (default 8 when unset).
14574
14793
  ...maxIterations !== void 0 ? { maxIterations } : {},
14794
+ // Doom-loop guard config (default on; `false` disables, object tunes thresholds).
14795
+ ...options.sendOptions.doomLoop !== void 0 ? { doomLoop: options.sendOptions.doomLoop } : {},
14575
14796
  // D315-D317 — tool lifecycle hooks (cost tracking + audit + retry/alert)
14576
14797
  ...options.agentOptions.onToolStart !== void 0 ? { onToolStart: options.agentOptions.onToolStart } : {},
14577
14798
  ...options.agentOptions.onToolEnd !== void 0 ? { onToolEnd: options.agentOptions.onToolEnd } : {},
@@ -14704,6 +14925,7 @@ var RealLocalRun = class extends FixtureRunBase {
14704
14925
  if (output.usage !== void 0) this.script.usage = output.usage;
14705
14926
  if (output.cost !== void 0) this.script.cost = output.cost;
14706
14927
  if (output.stoppedAtIterationLimit === true) this.script.stoppedAtIterationLimit = true;
14928
+ if (output.stoppedByDoomLoop === true) this.script.stoppedByDoomLoop = true;
14707
14929
  if (output.error !== void 0 && this.script.errorDetail === void 0) {
14708
14930
  this.script.errorDetail = {
14709
14931
  message: output.error.message,
@@ -18172,7 +18394,11 @@ function defineTool(spec) {
18172
18394
  description: spec.description,
18173
18395
  inputSchema,
18174
18396
  handler: async (input) => {
18175
- const parsed = spec.inputSchema.parse(input);
18397
+ const raw = spec.sanitize ? sanitizeToolInput(input, {
18398
+ ...spec.sanitize === true ? {} : spec.sanitize,
18399
+ schema: spec.inputSchema
18400
+ }).value : input;
18401
+ const parsed = spec.inputSchema.parse(raw);
18176
18402
  return await spec.handler(parsed);
18177
18403
  }
18178
18404
  };