@theokit/sdk 4.25.0 → 4.26.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.
- package/dist/{chunk-4HKMQEPX.js → chunk-KDNBTPY2.js} +3 -3
- package/dist/{chunk-4HKMQEPX.js.map → chunk-KDNBTPY2.js.map} +1 -1
- package/dist/{chunk-F3XVLFLM.js → chunk-PSJN532Q.js} +5 -5
- package/dist/{chunk-F3XVLFLM.js.map → chunk-PSJN532Q.js.map} +1 -1
- package/dist/{chunk-7RMWOMDB.cjs → chunk-R43CNCES.cjs} +5 -5
- package/dist/{chunk-7RMWOMDB.cjs.map → chunk-R43CNCES.cjs.map} +1 -1
- package/dist/{chunk-CJ6YJ2L3.cjs → chunk-ZUBIEQJF.cjs} +7 -7
- package/dist/{chunk-CJ6YJ2L3.cjs.map → chunk-ZUBIEQJF.cjs.map} +1 -1
- package/dist/{cron-x3muPNgg.d.cts → cron-D0JKR-yX.d.cts} +2 -1
- package/dist/{cron-B_NkE_VM.d.ts → cron-DivRaEmN.d.ts} +2 -1
- package/dist/cron.cjs +3 -3
- package/dist/cron.d.cts +1 -1
- package/dist/cron.d.ts +1 -1
- package/dist/cron.js +2 -2
- package/dist/errors.d.ts +3 -424
- package/dist/eval.cjs +2 -2
- package/dist/eval.js +1 -1
- package/dist/index.cjs +22 -22
- package/dist/index.d.cts +16 -21
- package/dist/index.d.ts +16 -21
- package/dist/index.js +5 -5
- package/dist/internal/judge/judge-call.d.ts +32 -19
- package/dist/{judge-call-VIMNK5TA.js → judge-call-CEQ3FYYD.js} +38 -4
- package/dist/judge-call-CEQ3FYYD.js.map +1 -0
- package/dist/{judge-call-7CF7D334.cjs → judge-call-QG4WZ7F3.cjs} +38 -3
- package/dist/judge-call-QG4WZ7F3.cjs.map +1 -0
- package/dist/{run-until-DB3LVGZS.cjs → run-until-PNO3QQLI.cjs} +11 -2
- package/dist/run-until-PNO3QQLI.cjs.map +1 -0
- package/dist/{run-until-2PX4QBHZ.js → run-until-XLHEHRQM.js} +11 -2
- package/dist/run-until-XLHEHRQM.js.map +1 -0
- package/dist/types/goal-events.d.ts +2 -1
- package/package.json +1 -1
- package/dist/judge-call-7CF7D334.cjs.map +0 -1
- package/dist/judge-call-VIMNK5TA.js.map +0 -1
- package/dist/run-until-2PX4QBHZ.js.map +0 -1
- package/dist/run-until-DB3LVGZS.cjs.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { T as TheokitAgentError, B as BudgetOptions, a as BudgetHandle, b as BudgetSnapshot, E as ErrorMetadata } from './errors-BdL-buYn.cjs';
|
|
2
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, m as ErrorCode, 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-BdL-buYn.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 Plugin$1, m as ProviderProfile, I as InlineSkill, n as GoalOptions, o as GoalEvent, p as GoalResult, B as BudgetTracker, q as MemoryProvider, r as MemoryId, s as PreToolCallDecision, t as StepResult, u as SDKProvider } from './cron-
|
|
4
|
-
export { v as ActiveMemoryPassArgs, w as ActiveMemoryPassResult, x as AgentMemory, y as BudgetCheck, z as BudgetTotal, D as BudgetUsageEvent, E as CloudEnv, F as CloudRepo, H as ContextBudget, J as ContextManagerKind, K as ContextSnapshot, N as ContextSource, O as ContextSourceStatus, Q as CreateSkillSpec, R as Cron, T as CronCreateOptions, U as CronGetOptions, V as CronJob, W as CronJobStatus, X as CronListOptions, Y as CronOperationOptions, Z as CronRunOptions, _ as CronRuntime, $ as CronSchedulerStatus, a0 as CronStartOptions, a1 as HookName, a2 as InvalidateCacheOptions, a3 as MemoryAdapter, a4 as MemoryAdapterCapabilities, a5 as MemoryContext, a6 as MemoryFact, a7 as MemoryProviderHandle, a8 as MemoryProviderInitOptions, a9 as MemoryRevision, aa as MemoryToolSchema, ab as MemoryTurnMessage, ac as PersonalityPreset, ad as PluginContext, ae as PostAssistantReplyContext, af as PreToolCallContext, ag as PreUserSendContext, ah as PreUserSendResult, ai as ProviderCapability, aj as ProviderRoute, ak as ProviderTransform, al as ProviderTransformContext, am as RecordSessionSummaryArgs, an as ResolvedProviderRoute, ao as RunUntilIterator, ap as SDKAgentPlugins, aq as SDKAgentSkillDetail, ar as SDKAgentSkills, as as SDKArtifact, at as SDKContextManager, au as SDKPluginMetadata, av as SDKProvidersManager, aw as SessionRecord, ax as SessionStore, ay as SettingSource, az as Skill, aA as SkillsResolver, aB as SkillsResolverContext, aC as SystemPromptContext, aD as SystemPromptMemoryFact, aE as SystemPromptSkillRef, aF as TelemetrySettings } from './cron-
|
|
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 Plugin$1, m as ProviderProfile, I as InlineSkill, n as GoalOptions, o as GoalEvent, p as GoalResult, B as BudgetTracker, q as MemoryProvider, r as MemoryId, s as PreToolCallDecision, t as StepResult, u as SDKProvider } from './cron-D0JKR-yX.cjs';
|
|
4
|
+
export { v as ActiveMemoryPassArgs, w as ActiveMemoryPassResult, x as AgentMemory, y as BudgetCheck, z as BudgetTotal, D as BudgetUsageEvent, E as CloudEnv, F as CloudRepo, H as ContextBudget, J as ContextManagerKind, K as ContextSnapshot, N as ContextSource, O as ContextSourceStatus, Q as CreateSkillSpec, R as Cron, T as CronCreateOptions, U as CronGetOptions, V as CronJob, W as CronJobStatus, X as CronListOptions, Y as CronOperationOptions, Z as CronRunOptions, _ as CronRuntime, $ as CronSchedulerStatus, a0 as CronStartOptions, a1 as HookName, a2 as InvalidateCacheOptions, a3 as MemoryAdapter, a4 as MemoryAdapterCapabilities, a5 as MemoryContext, a6 as MemoryFact, a7 as MemoryProviderHandle, a8 as MemoryProviderInitOptions, a9 as MemoryRevision, aa as MemoryToolSchema, ab as MemoryTurnMessage, ac as PersonalityPreset, ad as PluginContext, ae as PostAssistantReplyContext, af as PreToolCallContext, ag as PreUserSendContext, ah as PreUserSendResult, ai as ProviderCapability, aj as ProviderRoute, ak as ProviderTransform, al as ProviderTransformContext, am as RecordSessionSummaryArgs, an as ResolvedProviderRoute, ao as RunUntilIterator, ap as SDKAgentPlugins, aq as SDKAgentSkillDetail, ar as SDKAgentSkills, as as SDKArtifact, at as SDKContextManager, au as SDKPluginMetadata, av as SDKProvidersManager, aw as SessionRecord, ax as SessionStore, ay as SettingSource, az as Skill, aA as SkillsResolver, aB as SkillsResolverContext, aC as SystemPromptContext, aD as SystemPromptMemoryFact, aE as SystemPromptSkillRef, aF as TelemetrySettings } from './cron-D0JKR-yX.cjs';
|
|
5
5
|
import { R as RunResult, M as ModelSelection, C as CustomTool, a as McpServerConfig, b as Run, P as Processor, T as ToolResultContentBlock, c as PermissionMode, d as PermissionEngine, e as RunEventSink, S as SDKMessage } from './run-OJbGyweZ.cjs';
|
|
6
6
|
export { A as AgentConversationTurn, f as AssistantMessage, g as CompletionCheck, h as CompletionCheckResult, i as ConversationStep, j as ConversationTurn, k as CostBreakdown, l as CostSource, m as CostStatus, D as DoomLoopThresholds, G as GenerateOptions, n as GenerateRunResult, I as ImageBlock, o as InputProcessorContext, p as InteractionUpdate, q as McpAuthConfig, r as McpHttpServerConfig, s as McpOAuthConfig, t as McpStdioServerConfig, u as MessageOrigin, v as ModelParameterValue, O as OutputProcessorContext, w as PartialToolCallUpdate, x as PermissionAction, y as PermissionEngineOptions, z as PermissionRule, B as ProcessorControls, E as ProcessorTripwire, F as ProcessorViolation, H as RunCompactBoundaryEvent, J as RunCompletionCheckEvent, K as RunErrorDetail, L as RunEvent, N as RunGitInfo, Q as RunOperation, U as RunPermissionDeniedEvent, V as RunRateLimitEvent, W as RunStatus, X as RunTaskCompletedEvent, Y as RunTaskStartedEvent, Z as RunTaskUpdatedEvent, _ as RunToCompletionOptions, $ as RunToCompletionResult, a0 as RunToolProgressEvent, a1 as RunTripwireEvent, a2 as SDKAssistantMessage, a3 as SDKImage, a4 as SDKImageDimension, a5 as SDKObjectDelta, a6 as SDKRequestMessage, a7 as SDKStatusMessage, a8 as SDKSystemMessage, a9 as SDKTaskMessage, aa as SDKThinkingMessage, ab as SDKToolUseMessage, ac as SDKUserMessage, ad as SDKUserMessageEvent, ae as SendOptions, af as ShellCommand, ag as ShellConversationTurn, ah as ShellOutput, ai as ShellOutputDeltaUpdate, aj as StepCompletedUpdate, ak as StepStartedUpdate, al as StreamToCompletionResult, am as SummaryCompletedUpdate, an as SummaryStartedUpdate, ao as SummaryUpdate, ap as TextBlock, aq as TextDeltaUpdate, ar as ThinkingCompletedUpdate, as as ThinkingDeltaUpdate, at as ThinkingMessage, au as TokenDeltaUpdate, av as TokenUsage, aw as ToolCall, ax as ToolCallCompletedUpdate, ay as ToolCallStartedUpdate, az as ToolContextMessage, aA as ToolResult, aB as ToolResultGuardOptions, aC as ToolUseBlock, aD as TurnEndedUpdate, aE as UserMessage, aF as UserMessageAppendedUpdate, aG as applyMode, aH as emitRunEvent } from './run-OJbGyweZ.cjs';
|
|
7
7
|
import * as zod from 'zod';
|
|
@@ -1163,24 +1163,6 @@ declare class EventBus<Events extends Record<string, unknown>> {
|
|
|
1163
1163
|
once<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): () => void;
|
|
1164
1164
|
}
|
|
1165
1165
|
|
|
1166
|
-
/**
|
|
1167
|
-
* Judge call primitive (T2.2, ADRs D119-D121).
|
|
1168
|
-
*
|
|
1169
|
-
* Instantiates a short-lived auxiliary agent that evaluates whether a
|
|
1170
|
-
* goal is satisfied. The auxiliary judge runs with `tools: []` and a
|
|
1171
|
-
* cheap model (default `openai/gpt-4o-mini`) — see ADR D119. The judge
|
|
1172
|
-
* model needs only API access; we read `OPENROUTER_API_KEY` directly
|
|
1173
|
-
* from the environment (EC-A — single source of truth) and let the
|
|
1174
|
-
* caller override via {@link JudgeOptions.apiKey} for Anthropic or
|
|
1175
|
-
* direct-OpenAI environments.
|
|
1176
|
-
*
|
|
1177
|
-
* NOTE: judge aux agents created from inside a `forkAgent` context will
|
|
1178
|
-
* inherit the parent fork's whitelist via AsyncLocalStorage (EC-J).
|
|
1179
|
-
* `tools: []` keeps this benign today; future callers that add tools to
|
|
1180
|
-
* a judge should be aware.
|
|
1181
|
-
*
|
|
1182
|
-
* @internal
|
|
1183
|
-
*/
|
|
1184
1166
|
/** Inputs to the judge — pure data. */
|
|
1185
1167
|
interface JudgeContext {
|
|
1186
1168
|
goal: string;
|
|
@@ -1189,8 +1171,21 @@ interface JudgeContext {
|
|
|
1189
1171
|
}
|
|
1190
1172
|
/** Caller-supplied tuning knobs for the judge call. */
|
|
1191
1173
|
interface JudgeOptions {
|
|
1192
|
-
/**
|
|
1174
|
+
/**
|
|
1175
|
+
* Judge model identifier. Quando ausente, DERIVA de {@link agentModel} — e só cai no literal
|
|
1176
|
+
* `"openai/gpt-4o-mini"` se nem esse for informado.
|
|
1177
|
+
*
|
|
1178
|
+
* M80 — o default fixo era provider-cego: ele só resolve em OpenRouter. Com chave Anthropic dá
|
|
1179
|
+
* 404, com bearer OAuth dá 401, e em ambos o goal queimava 3 turnos inteiros antes de falhar com
|
|
1180
|
+
* razão enganosa. O agent-builder já contornava isso derivando por conta própria; o conhecimento
|
|
1181
|
+
* pertence aqui.
|
|
1182
|
+
*/
|
|
1193
1183
|
judgeModel?: string;
|
|
1184
|
+
/**
|
|
1185
|
+
* M80 — o modelo do agente CONDUZIDO. É a base da derivação: um judge que roda no mesmo modelo do
|
|
1186
|
+
* chat funciona onde o chat funciona.
|
|
1187
|
+
*/
|
|
1188
|
+
agentModel?: string;
|
|
1194
1189
|
/** Override env. Default `process.env.OPENROUTER_API_KEY` (EC-A). */
|
|
1195
1190
|
apiKey?: string;
|
|
1196
1191
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { T as TheokitAgentError, B as BudgetOptions, a as BudgetHandle, b as BudgetSnapshot, E as ErrorMetadata } from './errors-DHZtSNnj.js';
|
|
2
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, m as ErrorCode, 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-DHZtSNnj.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 Plugin$1, m as ProviderProfile, I as InlineSkill, n as GoalOptions, o as GoalEvent, p as GoalResult, B as BudgetTracker, q as MemoryProvider, r as MemoryId, s as PreToolCallDecision, t as StepResult, u as SDKProvider } from './cron-
|
|
4
|
-
export { v as ActiveMemoryPassArgs, w as ActiveMemoryPassResult, x as AgentMemory, y as BudgetCheck, z as BudgetTotal, D as BudgetUsageEvent, E as CloudEnv, F as CloudRepo, H as ContextBudget, J as ContextManagerKind, K as ContextSnapshot, N as ContextSource, O as ContextSourceStatus, Q as CreateSkillSpec, R as Cron, T as CronCreateOptions, U as CronGetOptions, V as CronJob, W as CronJobStatus, X as CronListOptions, Y as CronOperationOptions, Z as CronRunOptions, _ as CronRuntime, $ as CronSchedulerStatus, a0 as CronStartOptions, a1 as HookName, a2 as InvalidateCacheOptions, a3 as MemoryAdapter, a4 as MemoryAdapterCapabilities, a5 as MemoryContext, a6 as MemoryFact, a7 as MemoryProviderHandle, a8 as MemoryProviderInitOptions, a9 as MemoryRevision, aa as MemoryToolSchema, ab as MemoryTurnMessage, ac as PersonalityPreset, ad as PluginContext, ae as PostAssistantReplyContext, af as PreToolCallContext, ag as PreUserSendContext, ah as PreUserSendResult, ai as ProviderCapability, aj as ProviderRoute, ak as ProviderTransform, al as ProviderTransformContext, am as RecordSessionSummaryArgs, an as ResolvedProviderRoute, ao as RunUntilIterator, ap as SDKAgentPlugins, aq as SDKAgentSkillDetail, ar as SDKAgentSkills, as as SDKArtifact, at as SDKContextManager, au as SDKPluginMetadata, av as SDKProvidersManager, aw as SessionRecord, ax as SessionStore, ay as SettingSource, az as Skill, aA as SkillsResolver, aB as SkillsResolverContext, aC as SystemPromptContext, aD as SystemPromptMemoryFact, aE as SystemPromptSkillRef, aF as TelemetrySettings } from './cron-
|
|
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 Plugin$1, m as ProviderProfile, I as InlineSkill, n as GoalOptions, o as GoalEvent, p as GoalResult, B as BudgetTracker, q as MemoryProvider, r as MemoryId, s as PreToolCallDecision, t as StepResult, u as SDKProvider } from './cron-DivRaEmN.js';
|
|
4
|
+
export { v as ActiveMemoryPassArgs, w as ActiveMemoryPassResult, x as AgentMemory, y as BudgetCheck, z as BudgetTotal, D as BudgetUsageEvent, E as CloudEnv, F as CloudRepo, H as ContextBudget, J as ContextManagerKind, K as ContextSnapshot, N as ContextSource, O as ContextSourceStatus, Q as CreateSkillSpec, R as Cron, T as CronCreateOptions, U as CronGetOptions, V as CronJob, W as CronJobStatus, X as CronListOptions, Y as CronOperationOptions, Z as CronRunOptions, _ as CronRuntime, $ as CronSchedulerStatus, a0 as CronStartOptions, a1 as HookName, a2 as InvalidateCacheOptions, a3 as MemoryAdapter, a4 as MemoryAdapterCapabilities, a5 as MemoryContext, a6 as MemoryFact, a7 as MemoryProviderHandle, a8 as MemoryProviderInitOptions, a9 as MemoryRevision, aa as MemoryToolSchema, ab as MemoryTurnMessage, ac as PersonalityPreset, ad as PluginContext, ae as PostAssistantReplyContext, af as PreToolCallContext, ag as PreUserSendContext, ah as PreUserSendResult, ai as ProviderCapability, aj as ProviderRoute, ak as ProviderTransform, al as ProviderTransformContext, am as RecordSessionSummaryArgs, an as ResolvedProviderRoute, ao as RunUntilIterator, ap as SDKAgentPlugins, aq as SDKAgentSkillDetail, ar as SDKAgentSkills, as as SDKArtifact, at as SDKContextManager, au as SDKPluginMetadata, av as SDKProvidersManager, aw as SessionRecord, ax as SessionStore, ay as SettingSource, az as Skill, aA as SkillsResolver, aB as SkillsResolverContext, aC as SystemPromptContext, aD as SystemPromptMemoryFact, aE as SystemPromptSkillRef, aF as TelemetrySettings } from './cron-DivRaEmN.js';
|
|
5
5
|
import { R as RunResult, M as ModelSelection, C as CustomTool, a as McpServerConfig, b as Run, P as Processor, T as ToolResultContentBlock, c as PermissionMode, d as PermissionEngine, e as RunEventSink, S as SDKMessage } from './run-OJbGyweZ.js';
|
|
6
6
|
export { A as AgentConversationTurn, f as AssistantMessage, g as CompletionCheck, h as CompletionCheckResult, i as ConversationStep, j as ConversationTurn, k as CostBreakdown, l as CostSource, m as CostStatus, D as DoomLoopThresholds, G as GenerateOptions, n as GenerateRunResult, I as ImageBlock, o as InputProcessorContext, p as InteractionUpdate, q as McpAuthConfig, r as McpHttpServerConfig, s as McpOAuthConfig, t as McpStdioServerConfig, u as MessageOrigin, v as ModelParameterValue, O as OutputProcessorContext, w as PartialToolCallUpdate, x as PermissionAction, y as PermissionEngineOptions, z as PermissionRule, B as ProcessorControls, E as ProcessorTripwire, F as ProcessorViolation, H as RunCompactBoundaryEvent, J as RunCompletionCheckEvent, K as RunErrorDetail, L as RunEvent, N as RunGitInfo, Q as RunOperation, U as RunPermissionDeniedEvent, V as RunRateLimitEvent, W as RunStatus, X as RunTaskCompletedEvent, Y as RunTaskStartedEvent, Z as RunTaskUpdatedEvent, _ as RunToCompletionOptions, $ as RunToCompletionResult, a0 as RunToolProgressEvent, a1 as RunTripwireEvent, a2 as SDKAssistantMessage, a3 as SDKImage, a4 as SDKImageDimension, a5 as SDKObjectDelta, a6 as SDKRequestMessage, a7 as SDKStatusMessage, a8 as SDKSystemMessage, a9 as SDKTaskMessage, aa as SDKThinkingMessage, ab as SDKToolUseMessage, ac as SDKUserMessage, ad as SDKUserMessageEvent, ae as SendOptions, af as ShellCommand, ag as ShellConversationTurn, ah as ShellOutput, ai as ShellOutputDeltaUpdate, aj as StepCompletedUpdate, ak as StepStartedUpdate, al as StreamToCompletionResult, am as SummaryCompletedUpdate, an as SummaryStartedUpdate, ao as SummaryUpdate, ap as TextBlock, aq as TextDeltaUpdate, ar as ThinkingCompletedUpdate, as as ThinkingDeltaUpdate, at as ThinkingMessage, au as TokenDeltaUpdate, av as TokenUsage, aw as ToolCall, ax as ToolCallCompletedUpdate, ay as ToolCallStartedUpdate, az as ToolContextMessage, aA as ToolResult, aB as ToolResultGuardOptions, aC as ToolUseBlock, aD as TurnEndedUpdate, aE as UserMessage, aF as UserMessageAppendedUpdate, aG as applyMode, aH as emitRunEvent } from './run-OJbGyweZ.js';
|
|
7
7
|
import * as zod from 'zod';
|
|
@@ -1163,24 +1163,6 @@ declare class EventBus<Events extends Record<string, unknown>> {
|
|
|
1163
1163
|
once<K extends keyof Events>(event: K, handler: EventHandler<Events[K]>): () => void;
|
|
1164
1164
|
}
|
|
1165
1165
|
|
|
1166
|
-
/**
|
|
1167
|
-
* Judge call primitive (T2.2, ADRs D119-D121).
|
|
1168
|
-
*
|
|
1169
|
-
* Instantiates a short-lived auxiliary agent that evaluates whether a
|
|
1170
|
-
* goal is satisfied. The auxiliary judge runs with `tools: []` and a
|
|
1171
|
-
* cheap model (default `openai/gpt-4o-mini`) — see ADR D119. The judge
|
|
1172
|
-
* model needs only API access; we read `OPENROUTER_API_KEY` directly
|
|
1173
|
-
* from the environment (EC-A — single source of truth) and let the
|
|
1174
|
-
* caller override via {@link JudgeOptions.apiKey} for Anthropic or
|
|
1175
|
-
* direct-OpenAI environments.
|
|
1176
|
-
*
|
|
1177
|
-
* NOTE: judge aux agents created from inside a `forkAgent` context will
|
|
1178
|
-
* inherit the parent fork's whitelist via AsyncLocalStorage (EC-J).
|
|
1179
|
-
* `tools: []` keeps this benign today; future callers that add tools to
|
|
1180
|
-
* a judge should be aware.
|
|
1181
|
-
*
|
|
1182
|
-
* @internal
|
|
1183
|
-
*/
|
|
1184
1166
|
/** Inputs to the judge — pure data. */
|
|
1185
1167
|
interface JudgeContext {
|
|
1186
1168
|
goal: string;
|
|
@@ -1189,8 +1171,21 @@ interface JudgeContext {
|
|
|
1189
1171
|
}
|
|
1190
1172
|
/** Caller-supplied tuning knobs for the judge call. */
|
|
1191
1173
|
interface JudgeOptions {
|
|
1192
|
-
/**
|
|
1174
|
+
/**
|
|
1175
|
+
* Judge model identifier. Quando ausente, DERIVA de {@link agentModel} — e só cai no literal
|
|
1176
|
+
* `"openai/gpt-4o-mini"` se nem esse for informado.
|
|
1177
|
+
*
|
|
1178
|
+
* M80 — o default fixo era provider-cego: ele só resolve em OpenRouter. Com chave Anthropic dá
|
|
1179
|
+
* 404, com bearer OAuth dá 401, e em ambos o goal queimava 3 turnos inteiros antes de falhar com
|
|
1180
|
+
* razão enganosa. O agent-builder já contornava isso derivando por conta própria; o conhecimento
|
|
1181
|
+
* pertence aqui.
|
|
1182
|
+
*/
|
|
1193
1183
|
judgeModel?: string;
|
|
1184
|
+
/**
|
|
1185
|
+
* M80 — o modelo do agente CONDUZIDO. É a base da derivação: um judge que roda no mesmo modelo do
|
|
1186
|
+
* chat funciona onde o chat funciona.
|
|
1187
|
+
*/
|
|
1188
|
+
agentModel?: string;
|
|
1194
1189
|
/** Override env. Default `process.env.OPENROUTER_API_KEY` (EC-A). */
|
|
1195
1190
|
apiKey?: string;
|
|
1196
1191
|
}
|
package/dist/index.js
CHANGED
|
@@ -5,9 +5,9 @@ import './chunk-GJAGKFTR.js';
|
|
|
5
5
|
import { Workflow, agentStep } from './chunk-BFWPZMG7.js';
|
|
6
6
|
import './chunk-UVNG67DG.js';
|
|
7
7
|
import './chunk-CAH3G4IS.js';
|
|
8
|
-
export { Cron } from './chunk-
|
|
9
|
-
import { MEMORY_EMBEDDING_ADAPTERS, resolveApiKey, shouldUseFixtureMode, isFixtureApiKey, httpRequest, DEFAULT_AGENTIC_MODEL_ID, Agent } from './chunk-
|
|
10
|
-
export { Agent, AgentBuilder, Tool, ToolError, UsageAccumulator, computeCost, getPricingEntry } from './chunk-
|
|
8
|
+
export { Cron } from './chunk-KDNBTPY2.js';
|
|
9
|
+
import { MEMORY_EMBEDDING_ADAPTERS, resolveApiKey, shouldUseFixtureMode, isFixtureApiKey, httpRequest, DEFAULT_AGENTIC_MODEL_ID, Agent } from './chunk-PSJN532Q.js';
|
|
10
|
+
export { Agent, AgentBuilder, Tool, ToolError, UsageAccumulator, computeCost, getPricingEntry } from './chunk-PSJN532Q.js';
|
|
11
11
|
import { configure, submit, list, get, cancel, subscribe } from './chunk-HRA3CPGG.js';
|
|
12
12
|
export { emitRunEvent } from './chunk-HRA3CPGG.js';
|
|
13
13
|
import './chunk-SQLZ7ONU.js';
|
|
@@ -694,9 +694,9 @@ var EventBus = class {
|
|
|
694
694
|
// src/goal-loop.ts
|
|
695
695
|
function runGoalLoop(agent, goal, options, depsOverride) {
|
|
696
696
|
async function* wrap() {
|
|
697
|
-
const { runUntilImpl } = await import('./run-until-
|
|
697
|
+
const { runUntilImpl } = await import('./run-until-XLHEHRQM.js');
|
|
698
698
|
const deps = depsOverride ?? await (async () => {
|
|
699
|
-
const { judgeCallImpl } = await import('./judge-call-
|
|
699
|
+
const { judgeCallImpl } = await import('./judge-call-CEQ3FYYD.js');
|
|
700
700
|
const { getAgentFacade } = await import('./agent-factory-registry-ZVTABLEY.js');
|
|
701
701
|
const create = getAgentFacade().create;
|
|
702
702
|
return {
|
|
@@ -1,21 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* Judge call primitive (T2.2, ADRs D119-D121).
|
|
3
|
-
*
|
|
4
|
-
* Instantiates a short-lived auxiliary agent that evaluates whether a
|
|
5
|
-
* goal is satisfied. The auxiliary judge runs with `tools: []` and a
|
|
6
|
-
* cheap model (default `openai/gpt-4o-mini`) — see ADR D119. The judge
|
|
7
|
-
* model needs only API access; we read `OPENROUTER_API_KEY` directly
|
|
8
|
-
* from the environment (EC-A — single source of truth) and let the
|
|
9
|
-
* caller override via {@link JudgeOptions.apiKey} for Anthropic or
|
|
10
|
-
* direct-OpenAI environments.
|
|
11
|
-
*
|
|
12
|
-
* NOTE: judge aux agents created from inside a `forkAgent` context will
|
|
13
|
-
* inherit the parent fork's whitelist via AsyncLocalStorage (EC-J).
|
|
14
|
-
* `tools: []` keeps this benign today; future callers that add tools to
|
|
15
|
-
* a judge should be aware.
|
|
16
|
-
*
|
|
17
|
-
* @internal
|
|
18
|
-
*/
|
|
1
|
+
import { TheokitAgentError } from "../../errors.js";
|
|
19
2
|
/** Inputs to the judge — pure data. */
|
|
20
3
|
export interface JudgeContext {
|
|
21
4
|
goal: string;
|
|
@@ -24,11 +7,41 @@ export interface JudgeContext {
|
|
|
24
7
|
}
|
|
25
8
|
/** Caller-supplied tuning knobs for the judge call. */
|
|
26
9
|
export interface JudgeOptions {
|
|
27
|
-
/**
|
|
10
|
+
/**
|
|
11
|
+
* Judge model identifier. Quando ausente, DERIVA de {@link agentModel} — e só cai no literal
|
|
12
|
+
* `"openai/gpt-4o-mini"` se nem esse for informado.
|
|
13
|
+
*
|
|
14
|
+
* M80 — o default fixo era provider-cego: ele só resolve em OpenRouter. Com chave Anthropic dá
|
|
15
|
+
* 404, com bearer OAuth dá 401, e em ambos o goal queimava 3 turnos inteiros antes de falhar com
|
|
16
|
+
* razão enganosa. O agent-builder já contornava isso derivando por conta própria; o conhecimento
|
|
17
|
+
* pertence aqui.
|
|
18
|
+
*/
|
|
28
19
|
judgeModel?: string;
|
|
20
|
+
/**
|
|
21
|
+
* M80 — o modelo do agente CONDUZIDO. É a base da derivação: um judge que roda no mesmo modelo do
|
|
22
|
+
* chat funciona onde o chat funciona.
|
|
23
|
+
*/
|
|
24
|
+
agentModel?: string;
|
|
29
25
|
/** Override env. Default `process.env.OPENROUTER_API_KEY` (EC-A). */
|
|
30
26
|
apiKey?: string;
|
|
31
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* M80 — a credencial ou o modelo do judge não servem: 401/404.
|
|
30
|
+
*
|
|
31
|
+
* Falha RÁPIDA por design. `rules/error-handling.md § 2` separa recuperável de irrecuperável, e um
|
|
32
|
+
* modelo inexistente não passa a existir no retry — dobrar isso em `{parseFailed: true}` fazia o loop
|
|
33
|
+
* tentar três vezes e reportar "failed" por limite de falhas consecutivas, escondendo que a causa era
|
|
34
|
+
* credencial. Falha lenta e opaca trocada por rápida e clara.
|
|
35
|
+
*
|
|
36
|
+
* Falha de PARSE e erro de rede continuam dobrados: são recuperáveis, e o loop já decide por falhas
|
|
37
|
+
* consecutivas.
|
|
38
|
+
*/
|
|
39
|
+
export declare class JudgeCredentialError extends TheokitAgentError {
|
|
40
|
+
readonly httpStatus: number;
|
|
41
|
+
readonly judgeModel: string;
|
|
42
|
+
readonly name = "JudgeCredentialError";
|
|
43
|
+
constructor(httpStatus: number, judgeModel: string, cause: unknown);
|
|
44
|
+
}
|
|
32
45
|
/** Dependencies injected so `judge-call.ts` stays free of `Agent` import. */
|
|
33
46
|
export interface JudgeDeps {
|
|
34
47
|
create: (options: AgentOptions) => Promise<SDKAgent>;
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import { TheokitAgentError } from './chunk-WLKFWQSJ.js';
|
|
2
|
+
import './chunk-JTFYYKDT.js';
|
|
3
|
+
|
|
1
4
|
// src/internal/judge/parse-verdict.ts
|
|
2
5
|
var DONE_PREFIX = "DONE:";
|
|
3
6
|
var CONTINUE_PREFIX = "CONTINUE:";
|
|
4
7
|
var SKIPPED_PREFIX = "SKIPPED:";
|
|
8
|
+
var BLOCKED_PREFIX = "BLOCKED:";
|
|
5
9
|
function parseVerdict(text) {
|
|
6
10
|
const trimmed = text.trim();
|
|
7
11
|
if (trimmed.startsWith(DONE_PREFIX)) {
|
|
@@ -18,6 +22,13 @@ function parseVerdict(text) {
|
|
|
18
22
|
parseFailed: false
|
|
19
23
|
};
|
|
20
24
|
}
|
|
25
|
+
if (trimmed.startsWith(BLOCKED_PREFIX)) {
|
|
26
|
+
return {
|
|
27
|
+
verdict: "blocked",
|
|
28
|
+
reason: trimmed.slice(BLOCKED_PREFIX.length).trim(),
|
|
29
|
+
parseFailed: false
|
|
30
|
+
};
|
|
31
|
+
}
|
|
21
32
|
if (trimmed.startsWith(SKIPPED_PREFIX)) {
|
|
22
33
|
return {
|
|
23
34
|
verdict: "skipped",
|
|
@@ -33,6 +44,25 @@ function parseVerdict(text) {
|
|
|
33
44
|
}
|
|
34
45
|
|
|
35
46
|
// src/internal/judge/judge-call.ts
|
|
47
|
+
var JudgeCredentialError = class extends TheokitAgentError {
|
|
48
|
+
constructor(httpStatus, judgeModel, cause) {
|
|
49
|
+
super(
|
|
50
|
+
`judge unavailable: model "${judgeModel}" returned ${String(httpStatus)}. Pass \`judgeModel\`/\`apiKey\` that resolve for this provider, or omit \`judgeModel\` to derive it from the agent being driven.`,
|
|
51
|
+
{ code: "judge_credential", cause, isRetryable: false }
|
|
52
|
+
);
|
|
53
|
+
this.httpStatus = httpStatus;
|
|
54
|
+
this.judgeModel = judgeModel;
|
|
55
|
+
}
|
|
56
|
+
httpStatus;
|
|
57
|
+
judgeModel;
|
|
58
|
+
name = "JudgeCredentialError";
|
|
59
|
+
};
|
|
60
|
+
function statusHttpDe(err) {
|
|
61
|
+
const s = err.status ?? err.statusCode;
|
|
62
|
+
if (typeof s === "number") return s;
|
|
63
|
+
const m = /\b(401|403|404)\b/.exec(err instanceof Error ? err.message : String(err));
|
|
64
|
+
return m?.[1] !== void 0 ? Number(m[1]) : void 0;
|
|
65
|
+
}
|
|
36
66
|
async function judgeCallImpl(ctx, options, deps) {
|
|
37
67
|
const prompt = composeJudgePrompt(ctx);
|
|
38
68
|
const apiKey = options?.apiKey ?? process.env.OPENROUTER_API_KEY;
|
|
@@ -43,7 +73,7 @@ async function judgeCallImpl(ctx, options, deps) {
|
|
|
43
73
|
parseFailed: true
|
|
44
74
|
};
|
|
45
75
|
}
|
|
46
|
-
const judgeModel = options?.judgeModel ?? "openai/gpt-4o-mini";
|
|
76
|
+
const judgeModel = options?.judgeModel ?? options?.agentModel ?? "openai/gpt-4o-mini";
|
|
47
77
|
let auxAgent;
|
|
48
78
|
try {
|
|
49
79
|
auxAgent = await deps.create({
|
|
@@ -57,6 +87,10 @@ async function judgeCallImpl(ctx, options, deps) {
|
|
|
57
87
|
const result = await run.wait();
|
|
58
88
|
return parseVerdict(result.result ?? "");
|
|
59
89
|
} catch (err) {
|
|
90
|
+
const status = statusHttpDe(err);
|
|
91
|
+
if (status === 401 || status === 403 || status === 404) {
|
|
92
|
+
throw new JudgeCredentialError(status, judgeModel, err);
|
|
93
|
+
}
|
|
60
94
|
return {
|
|
61
95
|
verdict: "continue",
|
|
62
96
|
reason: `judge call failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
@@ -87,6 +121,6 @@ Respond with EXACTLY one of:
|
|
|
87
121
|
Be strict. If unclear, prefer CONTINUE.`;
|
|
88
122
|
}
|
|
89
123
|
|
|
90
|
-
export { composeJudgePrompt, judgeCallImpl };
|
|
91
|
-
//# sourceMappingURL=judge-call-
|
|
92
|
-
//# sourceMappingURL=judge-call-
|
|
124
|
+
export { JudgeCredentialError, composeJudgePrompt, judgeCallImpl };
|
|
125
|
+
//# sourceMappingURL=judge-call-CEQ3FYYD.js.map
|
|
126
|
+
//# sourceMappingURL=judge-call-CEQ3FYYD.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/judge/parse-verdict.ts","../src/internal/judge/judge-call.ts"],"names":[],"mappings":"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","file":"judge-call-CEQ3FYYD.js","sourcesContent":["/**\n * Pure verdict parser (T2.1, ADRs D120-D121).\n *\n * Strict prefix matching against `DONE:`, `CONTINUE:`, `SKIPPED:`. Reason\n * is the suffix, trimmed. Anything else is fail-safe: verdict = `continue`,\n * `parseFailed: true` — caller's max-consecutive-failure cap stops the\n * loop after N flakes.\n *\n * @internal\n */\n\nimport type { JudgeResult } from \"./types.js\";\n\nconst DONE_PREFIX = \"DONE:\";\nconst CONTINUE_PREFIX = \"CONTINUE:\";\nconst SKIPPED_PREFIX = \"SKIPPED:\";\n/** M80 — o judge agora pode declarar impossibilidade, não só \"continue\". */\nconst BLOCKED_PREFIX = \"BLOCKED:\";\n\nexport function parseVerdict(text: string): JudgeResult {\n const trimmed = text.trim();\n\n if (trimmed.startsWith(DONE_PREFIX)) {\n return {\n verdict: \"done\",\n reason: trimmed.slice(DONE_PREFIX.length).trim(),\n parseFailed: false,\n };\n }\n if (trimmed.startsWith(CONTINUE_PREFIX)) {\n return {\n verdict: \"continue\",\n reason: trimmed.slice(CONTINUE_PREFIX.length).trim(),\n parseFailed: false,\n };\n }\n if (trimmed.startsWith(BLOCKED_PREFIX)) {\n return {\n verdict: \"blocked\",\n reason: trimmed.slice(BLOCKED_PREFIX.length).trim(),\n parseFailed: false,\n };\n }\n if (trimmed.startsWith(SKIPPED_PREFIX)) {\n return {\n verdict: \"skipped\",\n reason: trimmed.slice(SKIPPED_PREFIX.length).trim(),\n parseFailed: false,\n };\n }\n\n // Fail-safe: ADR D121 — prefer \"continue\" so we don't stop prematurely.\n // The runUntil loop counts consecutive parseFailed responses and bails\n // after `maxConsecutiveJudgeFailures` (default 3).\n return {\n verdict: \"continue\",\n reason: `judge response malformed: \"${trimmed.slice(0, 100)}\"`,\n parseFailed: true,\n };\n}\n","import { TheokitAgentError } from \"../../errors.js\";\n/**\n * Judge call primitive (T2.2, ADRs D119-D121).\n *\n * Instantiates a short-lived auxiliary agent that evaluates whether a\n * goal is satisfied. The auxiliary judge runs with `tools: []` and a\n * cheap model (default `openai/gpt-4o-mini`) — see ADR D119. The judge\n * model needs only API access; we read `OPENROUTER_API_KEY` directly\n * from the environment (EC-A — single source of truth) and let the\n * caller override via {@link JudgeOptions.apiKey} for Anthropic or\n * direct-OpenAI environments.\n *\n * NOTE: judge aux agents created from inside a `forkAgent` context will\n * inherit the parent fork's whitelist via AsyncLocalStorage (EC-J).\n * `tools: []` keeps this benign today; future callers that add tools to\n * a judge should be aware.\n *\n * @internal\n */\n\nimport type { AgentOptions, SDKAgent } from \"../../types/agent.js\";\nimport { parseVerdict } from \"./parse-verdict.js\";\nimport type { JudgeResult } from \"./types.js\";\n\n/** Inputs to the judge — pure data. */\nexport interface JudgeContext {\n goal: string;\n lastResponse: string;\n subgoals?: string[];\n}\n\n/** Caller-supplied tuning knobs for the judge call. */\nexport interface JudgeOptions {\n /**\n * Judge model identifier. Quando ausente, DERIVA de {@link agentModel} — e só cai no literal\n * `\"openai/gpt-4o-mini\"` se nem esse for informado.\n *\n * M80 — o default fixo era provider-cego: ele só resolve em OpenRouter. Com chave Anthropic dá\n * 404, com bearer OAuth dá 401, e em ambos o goal queimava 3 turnos inteiros antes de falhar com\n * razão enganosa. O agent-builder já contornava isso derivando por conta própria; o conhecimento\n * pertence aqui.\n */\n judgeModel?: string;\n /**\n * M80 — o modelo do agente CONDUZIDO. É a base da derivação: um judge que roda no mesmo modelo do\n * chat funciona onde o chat funciona.\n */\n agentModel?: string;\n /** Override env. Default `process.env.OPENROUTER_API_KEY` (EC-A). */\n apiKey?: string;\n}\n\n/**\n * M80 — a credencial ou o modelo do judge não servem: 401/404.\n *\n * Falha RÁPIDA por design. `rules/error-handling.md § 2` separa recuperável de irrecuperável, e um\n * modelo inexistente não passa a existir no retry — dobrar isso em `{parseFailed: true}` fazia o loop\n * tentar três vezes e reportar \"failed\" por limite de falhas consecutivas, escondendo que a causa era\n * credencial. Falha lenta e opaca trocada por rápida e clara.\n *\n * Falha de PARSE e erro de rede continuam dobrados: são recuperáveis, e o loop já decide por falhas\n * consecutivas.\n */\nexport class JudgeCredentialError extends TheokitAgentError {\n override readonly name = \"JudgeCredentialError\";\n\n constructor(\n readonly httpStatus: number,\n readonly judgeModel: string,\n cause: unknown,\n ) {\n super(\n `judge unavailable: model \"${judgeModel}\" returned ${String(httpStatus)}. ` +\n \"Pass `judgeModel`/`apiKey` that resolve for this provider, or omit `judgeModel` to derive \" +\n \"it from the agent being driven.\",\n { code: \"judge_credential\", cause, isRetryable: false },\n );\n }\n}\n\n/** Extrai o status HTTP de um erro de provider, quando ele o carrega. */\nfunction statusHttpDe(err: unknown): number | undefined {\n const s =\n (err as { status?: unknown; statusCode?: unknown }).status ??\n (err as { statusCode?: unknown }).statusCode;\n if (typeof s === \"number\") return s;\n const m = /\\b(401|403|404)\\b/.exec(err instanceof Error ? err.message : String(err));\n return m?.[1] !== undefined ? Number(m[1]) : undefined;\n}\n\n/** Dependencies injected so `judge-call.ts` stays free of `Agent` import. */\nexport interface JudgeDeps {\n create: (options: AgentOptions) => Promise<SDKAgent>;\n}\n\n/**\n * Run the judge auxiliary agent and parse the verdict. Always returns a\n * `JudgeResult` — failures are folded into `{ parseFailed: true,\n * verdict: \"continue\" }` so the loop can decide based on consecutive\n * failures (ADR D121).\n *\n * @internal\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: judge call must (1) check env or override, (2) catch errors as fail-safe, (3) ensure aux dispose runs once regardless of outcome — three concerns linearly arranged, harm clarity to extract.\nexport async function judgeCallImpl(\n ctx: JudgeContext,\n options: JudgeOptions | undefined,\n deps: JudgeDeps,\n): Promise<JudgeResult> {\n const prompt = composeJudgePrompt(ctx);\n // EC-A: single env source — OpenRouter only. No multi-provider fallback.\n const apiKey = options?.apiKey ?? process.env.OPENROUTER_API_KEY;\n if (apiKey === undefined) {\n return {\n verdict: \"continue\",\n reason:\n \"judge unavailable: OPENROUTER_API_KEY missing and no override passed via options.apiKey\",\n parseFailed: true,\n };\n }\n\n // M80 — precedência: explícito > modelo do agente conduzido > o literal histórico. O literal só\n // sobrevive como último recurso, para não quebrar quem nunca passou nenhum dos dois.\n const judgeModel = options?.judgeModel ?? options?.agentModel ?? \"openai/gpt-4o-mini\";\n let auxAgent: SDKAgent | undefined;\n try {\n auxAgent = await deps.create({\n apiKey,\n model: { id: judgeModel },\n tools: [],\n local: {},\n metadata: { forkOrigin: \"judge\" },\n } as AgentOptions);\n const run = await auxAgent.send(prompt);\n const result = await run.wait();\n return parseVerdict(result.result ?? \"\");\n } catch (err) {\n // M80 — 401/403/404 são de credencial/modelo: irrecuperáveis, falham rápido e tipado. Todo o\n // resto (rede, timeout, 5xx) segue dobrado, porque É recuperável e o loop já decide por falhas\n // consecutivas.\n const status = statusHttpDe(err);\n if (status === 401 || status === 403 || status === 404) {\n throw new JudgeCredentialError(status, judgeModel, err);\n }\n return {\n verdict: \"continue\",\n reason: `judge call failed: ${err instanceof Error ? err.message : String(err)}`,\n parseFailed: true,\n };\n } finally {\n if (auxAgent !== undefined) {\n try {\n await auxAgent.dispose();\n } catch {\n // dispose errors are non-fatal; judge result is already prepared\n }\n }\n }\n}\n\n/**\n * Build the strict-format prompt the judge expects.\n *\n * @internal\n */\nexport function composeJudgePrompt(ctx: JudgeContext): string {\n const subgoals =\n ctx.subgoals !== undefined && ctx.subgoals.length > 0 ? ctx.subgoals.join(\", \") : \"(none)\";\n return `You are a goal judge. Determine if this goal is satisfied.\n\nGoal: ${ctx.goal}\nSubgoals: ${subgoals}\nLast agent response: ${ctx.lastResponse}\n\nRespond with EXACTLY one of:\n- DONE: <reason>\n- CONTINUE: <what's left>\n- SKIPPED: <why not applicable>\n\nBe strict. If unclear, prefer CONTINUE.`;\n}\n"]}
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var chunkA44COQJJ_cjs = require('./chunk-A44COQJJ.cjs');
|
|
4
|
+
require('./chunk-BEURCLDV.cjs');
|
|
5
|
+
|
|
3
6
|
// src/internal/judge/parse-verdict.ts
|
|
4
7
|
var DONE_PREFIX = "DONE:";
|
|
5
8
|
var CONTINUE_PREFIX = "CONTINUE:";
|
|
6
9
|
var SKIPPED_PREFIX = "SKIPPED:";
|
|
10
|
+
var BLOCKED_PREFIX = "BLOCKED:";
|
|
7
11
|
function parseVerdict(text) {
|
|
8
12
|
const trimmed = text.trim();
|
|
9
13
|
if (trimmed.startsWith(DONE_PREFIX)) {
|
|
@@ -20,6 +24,13 @@ function parseVerdict(text) {
|
|
|
20
24
|
parseFailed: false
|
|
21
25
|
};
|
|
22
26
|
}
|
|
27
|
+
if (trimmed.startsWith(BLOCKED_PREFIX)) {
|
|
28
|
+
return {
|
|
29
|
+
verdict: "blocked",
|
|
30
|
+
reason: trimmed.slice(BLOCKED_PREFIX.length).trim(),
|
|
31
|
+
parseFailed: false
|
|
32
|
+
};
|
|
33
|
+
}
|
|
23
34
|
if (trimmed.startsWith(SKIPPED_PREFIX)) {
|
|
24
35
|
return {
|
|
25
36
|
verdict: "skipped",
|
|
@@ -35,6 +46,25 @@ function parseVerdict(text) {
|
|
|
35
46
|
}
|
|
36
47
|
|
|
37
48
|
// src/internal/judge/judge-call.ts
|
|
49
|
+
var JudgeCredentialError = class extends chunkA44COQJJ_cjs.TheokitAgentError {
|
|
50
|
+
constructor(httpStatus, judgeModel, cause) {
|
|
51
|
+
super(
|
|
52
|
+
`judge unavailable: model "${judgeModel}" returned ${String(httpStatus)}. Pass \`judgeModel\`/\`apiKey\` that resolve for this provider, or omit \`judgeModel\` to derive it from the agent being driven.`,
|
|
53
|
+
{ code: "judge_credential", cause, isRetryable: false }
|
|
54
|
+
);
|
|
55
|
+
this.httpStatus = httpStatus;
|
|
56
|
+
this.judgeModel = judgeModel;
|
|
57
|
+
}
|
|
58
|
+
httpStatus;
|
|
59
|
+
judgeModel;
|
|
60
|
+
name = "JudgeCredentialError";
|
|
61
|
+
};
|
|
62
|
+
function statusHttpDe(err) {
|
|
63
|
+
const s = err.status ?? err.statusCode;
|
|
64
|
+
if (typeof s === "number") return s;
|
|
65
|
+
const m = /\b(401|403|404)\b/.exec(err instanceof Error ? err.message : String(err));
|
|
66
|
+
return m?.[1] !== void 0 ? Number(m[1]) : void 0;
|
|
67
|
+
}
|
|
38
68
|
async function judgeCallImpl(ctx, options, deps) {
|
|
39
69
|
const prompt = composeJudgePrompt(ctx);
|
|
40
70
|
const apiKey = options?.apiKey ?? process.env.OPENROUTER_API_KEY;
|
|
@@ -45,7 +75,7 @@ async function judgeCallImpl(ctx, options, deps) {
|
|
|
45
75
|
parseFailed: true
|
|
46
76
|
};
|
|
47
77
|
}
|
|
48
|
-
const judgeModel = options?.judgeModel ?? "openai/gpt-4o-mini";
|
|
78
|
+
const judgeModel = options?.judgeModel ?? options?.agentModel ?? "openai/gpt-4o-mini";
|
|
49
79
|
let auxAgent;
|
|
50
80
|
try {
|
|
51
81
|
auxAgent = await deps.create({
|
|
@@ -59,6 +89,10 @@ async function judgeCallImpl(ctx, options, deps) {
|
|
|
59
89
|
const result = await run.wait();
|
|
60
90
|
return parseVerdict(result.result ?? "");
|
|
61
91
|
} catch (err) {
|
|
92
|
+
const status = statusHttpDe(err);
|
|
93
|
+
if (status === 401 || status === 403 || status === 404) {
|
|
94
|
+
throw new JudgeCredentialError(status, judgeModel, err);
|
|
95
|
+
}
|
|
62
96
|
return {
|
|
63
97
|
verdict: "continue",
|
|
64
98
|
reason: `judge call failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
@@ -89,7 +123,8 @@ Respond with EXACTLY one of:
|
|
|
89
123
|
Be strict. If unclear, prefer CONTINUE.`;
|
|
90
124
|
}
|
|
91
125
|
|
|
126
|
+
exports.JudgeCredentialError = JudgeCredentialError;
|
|
92
127
|
exports.composeJudgePrompt = composeJudgePrompt;
|
|
93
128
|
exports.judgeCallImpl = judgeCallImpl;
|
|
94
|
-
//# sourceMappingURL=judge-call-
|
|
95
|
-
//# sourceMappingURL=judge-call-
|
|
129
|
+
//# sourceMappingURL=judge-call-QG4WZ7F3.cjs.map
|
|
130
|
+
//# sourceMappingURL=judge-call-QG4WZ7F3.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/judge/parse-verdict.ts","../src/internal/judge/judge-call.ts"],"names":["TheokitAgentError"],"mappings":"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","file":"judge-call-QG4WZ7F3.cjs","sourcesContent":["/**\n * Pure verdict parser (T2.1, ADRs D120-D121).\n *\n * Strict prefix matching against `DONE:`, `CONTINUE:`, `SKIPPED:`. Reason\n * is the suffix, trimmed. Anything else is fail-safe: verdict = `continue`,\n * `parseFailed: true` — caller's max-consecutive-failure cap stops the\n * loop after N flakes.\n *\n * @internal\n */\n\nimport type { JudgeResult } from \"./types.js\";\n\nconst DONE_PREFIX = \"DONE:\";\nconst CONTINUE_PREFIX = \"CONTINUE:\";\nconst SKIPPED_PREFIX = \"SKIPPED:\";\n/** M80 — o judge agora pode declarar impossibilidade, não só \"continue\". */\nconst BLOCKED_PREFIX = \"BLOCKED:\";\n\nexport function parseVerdict(text: string): JudgeResult {\n const trimmed = text.trim();\n\n if (trimmed.startsWith(DONE_PREFIX)) {\n return {\n verdict: \"done\",\n reason: trimmed.slice(DONE_PREFIX.length).trim(),\n parseFailed: false,\n };\n }\n if (trimmed.startsWith(CONTINUE_PREFIX)) {\n return {\n verdict: \"continue\",\n reason: trimmed.slice(CONTINUE_PREFIX.length).trim(),\n parseFailed: false,\n };\n }\n if (trimmed.startsWith(BLOCKED_PREFIX)) {\n return {\n verdict: \"blocked\",\n reason: trimmed.slice(BLOCKED_PREFIX.length).trim(),\n parseFailed: false,\n };\n }\n if (trimmed.startsWith(SKIPPED_PREFIX)) {\n return {\n verdict: \"skipped\",\n reason: trimmed.slice(SKIPPED_PREFIX.length).trim(),\n parseFailed: false,\n };\n }\n\n // Fail-safe: ADR D121 — prefer \"continue\" so we don't stop prematurely.\n // The runUntil loop counts consecutive parseFailed responses and bails\n // after `maxConsecutiveJudgeFailures` (default 3).\n return {\n verdict: \"continue\",\n reason: `judge response malformed: \"${trimmed.slice(0, 100)}\"`,\n parseFailed: true,\n };\n}\n","import { TheokitAgentError } from \"../../errors.js\";\n/**\n * Judge call primitive (T2.2, ADRs D119-D121).\n *\n * Instantiates a short-lived auxiliary agent that evaluates whether a\n * goal is satisfied. The auxiliary judge runs with `tools: []` and a\n * cheap model (default `openai/gpt-4o-mini`) — see ADR D119. The judge\n * model needs only API access; we read `OPENROUTER_API_KEY` directly\n * from the environment (EC-A — single source of truth) and let the\n * caller override via {@link JudgeOptions.apiKey} for Anthropic or\n * direct-OpenAI environments.\n *\n * NOTE: judge aux agents created from inside a `forkAgent` context will\n * inherit the parent fork's whitelist via AsyncLocalStorage (EC-J).\n * `tools: []` keeps this benign today; future callers that add tools to\n * a judge should be aware.\n *\n * @internal\n */\n\nimport type { AgentOptions, SDKAgent } from \"../../types/agent.js\";\nimport { parseVerdict } from \"./parse-verdict.js\";\nimport type { JudgeResult } from \"./types.js\";\n\n/** Inputs to the judge — pure data. */\nexport interface JudgeContext {\n goal: string;\n lastResponse: string;\n subgoals?: string[];\n}\n\n/** Caller-supplied tuning knobs for the judge call. */\nexport interface JudgeOptions {\n /**\n * Judge model identifier. Quando ausente, DERIVA de {@link agentModel} — e só cai no literal\n * `\"openai/gpt-4o-mini\"` se nem esse for informado.\n *\n * M80 — o default fixo era provider-cego: ele só resolve em OpenRouter. Com chave Anthropic dá\n * 404, com bearer OAuth dá 401, e em ambos o goal queimava 3 turnos inteiros antes de falhar com\n * razão enganosa. O agent-builder já contornava isso derivando por conta própria; o conhecimento\n * pertence aqui.\n */\n judgeModel?: string;\n /**\n * M80 — o modelo do agente CONDUZIDO. É a base da derivação: um judge que roda no mesmo modelo do\n * chat funciona onde o chat funciona.\n */\n agentModel?: string;\n /** Override env. Default `process.env.OPENROUTER_API_KEY` (EC-A). */\n apiKey?: string;\n}\n\n/**\n * M80 — a credencial ou o modelo do judge não servem: 401/404.\n *\n * Falha RÁPIDA por design. `rules/error-handling.md § 2` separa recuperável de irrecuperável, e um\n * modelo inexistente não passa a existir no retry — dobrar isso em `{parseFailed: true}` fazia o loop\n * tentar três vezes e reportar \"failed\" por limite de falhas consecutivas, escondendo que a causa era\n * credencial. Falha lenta e opaca trocada por rápida e clara.\n *\n * Falha de PARSE e erro de rede continuam dobrados: são recuperáveis, e o loop já decide por falhas\n * consecutivas.\n */\nexport class JudgeCredentialError extends TheokitAgentError {\n override readonly name = \"JudgeCredentialError\";\n\n constructor(\n readonly httpStatus: number,\n readonly judgeModel: string,\n cause: unknown,\n ) {\n super(\n `judge unavailable: model \"${judgeModel}\" returned ${String(httpStatus)}. ` +\n \"Pass `judgeModel`/`apiKey` that resolve for this provider, or omit `judgeModel` to derive \" +\n \"it from the agent being driven.\",\n { code: \"judge_credential\", cause, isRetryable: false },\n );\n }\n}\n\n/** Extrai o status HTTP de um erro de provider, quando ele o carrega. */\nfunction statusHttpDe(err: unknown): number | undefined {\n const s =\n (err as { status?: unknown; statusCode?: unknown }).status ??\n (err as { statusCode?: unknown }).statusCode;\n if (typeof s === \"number\") return s;\n const m = /\\b(401|403|404)\\b/.exec(err instanceof Error ? err.message : String(err));\n return m?.[1] !== undefined ? Number(m[1]) : undefined;\n}\n\n/** Dependencies injected so `judge-call.ts` stays free of `Agent` import. */\nexport interface JudgeDeps {\n create: (options: AgentOptions) => Promise<SDKAgent>;\n}\n\n/**\n * Run the judge auxiliary agent and parse the verdict. Always returns a\n * `JudgeResult` — failures are folded into `{ parseFailed: true,\n * verdict: \"continue\" }` so the loop can decide based on consecutive\n * failures (ADR D121).\n *\n * @internal\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: judge call must (1) check env or override, (2) catch errors as fail-safe, (3) ensure aux dispose runs once regardless of outcome — three concerns linearly arranged, harm clarity to extract.\nexport async function judgeCallImpl(\n ctx: JudgeContext,\n options: JudgeOptions | undefined,\n deps: JudgeDeps,\n): Promise<JudgeResult> {\n const prompt = composeJudgePrompt(ctx);\n // EC-A: single env source — OpenRouter only. No multi-provider fallback.\n const apiKey = options?.apiKey ?? process.env.OPENROUTER_API_KEY;\n if (apiKey === undefined) {\n return {\n verdict: \"continue\",\n reason:\n \"judge unavailable: OPENROUTER_API_KEY missing and no override passed via options.apiKey\",\n parseFailed: true,\n };\n }\n\n // M80 — precedência: explícito > modelo do agente conduzido > o literal histórico. O literal só\n // sobrevive como último recurso, para não quebrar quem nunca passou nenhum dos dois.\n const judgeModel = options?.judgeModel ?? options?.agentModel ?? \"openai/gpt-4o-mini\";\n let auxAgent: SDKAgent | undefined;\n try {\n auxAgent = await deps.create({\n apiKey,\n model: { id: judgeModel },\n tools: [],\n local: {},\n metadata: { forkOrigin: \"judge\" },\n } as AgentOptions);\n const run = await auxAgent.send(prompt);\n const result = await run.wait();\n return parseVerdict(result.result ?? \"\");\n } catch (err) {\n // M80 — 401/403/404 são de credencial/modelo: irrecuperáveis, falham rápido e tipado. Todo o\n // resto (rede, timeout, 5xx) segue dobrado, porque É recuperável e o loop já decide por falhas\n // consecutivas.\n const status = statusHttpDe(err);\n if (status === 401 || status === 403 || status === 404) {\n throw new JudgeCredentialError(status, judgeModel, err);\n }\n return {\n verdict: \"continue\",\n reason: `judge call failed: ${err instanceof Error ? err.message : String(err)}`,\n parseFailed: true,\n };\n } finally {\n if (auxAgent !== undefined) {\n try {\n await auxAgent.dispose();\n } catch {\n // dispose errors are non-fatal; judge result is already prepared\n }\n }\n }\n}\n\n/**\n * Build the strict-format prompt the judge expects.\n *\n * @internal\n */\nexport function composeJudgePrompt(ctx: JudgeContext): string {\n const subgoals =\n ctx.subgoals !== undefined && ctx.subgoals.length > 0 ? ctx.subgoals.join(\", \") : \"(none)\";\n return `You are a goal judge. Determine if this goal is satisfied.\n\nGoal: ${ctx.goal}\nSubgoals: ${subgoals}\nLast agent response: ${ctx.lastResponse}\n\nRespond with EXACTLY one of:\n- DONE: <reason>\n- CONTINUE: <what's left>\n- SKIPPED: <why not applicable>\n\nBe strict. If unclear, prefer CONTINUE.`;\n}\n"]}
|
|
@@ -98,6 +98,15 @@ async function* runUntilImpl(agent, goal, options, deps) {
|
|
|
98
98
|
finalResponse: lastResponse || void 0
|
|
99
99
|
};
|
|
100
100
|
}
|
|
101
|
+
if (judgment.verdict === "blocked") {
|
|
102
|
+
yield { type: "status_change", status: "blocked", reason: judgment.reason };
|
|
103
|
+
return {
|
|
104
|
+
status: "blocked",
|
|
105
|
+
turnsUsed: turn,
|
|
106
|
+
tokensUsed,
|
|
107
|
+
finalResponse: lastResponse || void 0
|
|
108
|
+
};
|
|
109
|
+
}
|
|
101
110
|
if (judgment.verdict === "skipped") {
|
|
102
111
|
yield {
|
|
103
112
|
type: "status_change",
|
|
@@ -167,5 +176,5 @@ ${lastResponse.slice(-1e3)}`
|
|
|
167
176
|
|
|
168
177
|
exports.composeContinuation = composeContinuation;
|
|
169
178
|
exports.runUntilImpl = runUntilImpl;
|
|
170
|
-
//# sourceMappingURL=run-until-
|
|
171
|
-
//# sourceMappingURL=run-until-
|
|
179
|
+
//# sourceMappingURL=run-until-PNO3QQLI.cjs.map
|
|
180
|
+
//# sourceMappingURL=run-until-PNO3QQLI.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/runtime/lifecycle/run-until.ts"],"names":["GOAL_CONTINUATION_MARKER"],"mappings":";;;;;AA2BA,gBAAuB,YAAA,CACrB,KAAA,EACA,IAAA,EACA,OAAA,EACA,IAAA,EAC6C;AAC7C,EAAA,MAAM,QAAA,GAAW,SAAS,QAAA,IAAY,EAAA;AACtC,EAAA,MAAM,QAAA,GAAW,SAAS,2BAAA,IAA+B,CAAA;AACzD,EAAA,MAAM,cAAc,OAAA,EAAS,WAAA;AAC7B,EAAA,MAAM,SAAS,OAAA,EAAS,MAAA;AAKxB,EAAA,MAAM,SAAA,GAAY,MAAe,MAAA,KAAW,MAAA,IAAa,MAAA,CAAO,OAAA;AAChE,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,IAAI,mBAAA,GAAsB,CAAA;AAC1B,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,YAAA,GAAe,EAAA;AAGnB,EAAA,IAAI,WAAU,EAAG;AACf,IAAA,MAAM;AAAA,MACJ,IAAA,EAAM,eAAA;AAAA,MACN,MAAA,EAAQ,QAAA;AAAA,MACR,MAAA,EAAQ;AAAA,KACV;AACA,IAAA,OAAO,EAAE,MAAA,EAAQ,QAAA,EAAU,WAAW,CAAA,EAAG,UAAA,EAAY,eAAe,MAAA,EAAU;AAAA,EAChF;AAEA,EAAA,MAAM,EAAE,IAAA,EAAM,eAAA,EAAiB,MAAA,EAAQ,QAAA,EAAU,QAAQ,cAAA,EAAe;AAExE,EAAA,OAAO,OAAO,QAAA,EAAU;AACtB,IAAA,IAAI,WAAU,EAAG;AACf,MAAA,MAAM,EAAE,IAAA,EAAM,eAAA,EAAiB,MAAA,EAAQ,QAAA,EAAU,QAAQ,yBAAA,EAA0B;AACnF,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,QAAA;AAAA,QACR,SAAA,EAAW,IAAA;AAAA,QACX,UAAA;AAAA,QACA,eAAe,YAAA,IAAgB;AAAA,OACjC;AAAA,IACF;AAEA,IAAA,IAAA,IAAQ,CAAA;AACR,IAAA,MAAM,EAAE,IAAA,EAAM,YAAA,EAAc,IAAA,EAAM,IAAA,EAAK;AAEvC,IAAA,MAAM,qBAAqB,IAAA,KAAS,CAAA,GAAI,IAAA,GAAO,mBAAA,CAAoB,MAAM,YAAY,CAAA;AAErF,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,IAAA,CAAK,kBAAkB,CAAA;AAI/C,IAAA,MAAM,gBAAgB,MAAY;AAChC,MAAA,KAAM,IAAyC,MAAA,IAAS;AAAA,IAC1D,CAAA;AACA,IAAA,IAAI,WAAW,MAAA,EAAW;AACxB,MAAA,IAAI,MAAA,CAAO,SAAS,aAAA,EAAc;AAAA,kBACtB,gBAAA,CAAiB,OAAA,EAAS,eAAe,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,IACrE;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,IAAA,EAAK;AAC9B,IAAA,IAAI,MAAA,KAAW,MAAA,EAAW,MAAA,CAAO,mBAAA,CAAoB,SAAS,aAAa,CAAA;AAC3E,IAAA,YAAA,GAAe,OAAO,MAAA,IAAU,EAAA;AAEhC,IAAA,MAAM,UAAA,GAAc,OAAgD,KAAA,EAAO,WAAA;AAC3E,IAAA,IAAI,OAAO,UAAA,KAAe,QAAA,EAAU,UAAA,IAAc,UAAA;AAElD,IAAA,IAAI,WAAU,EAAG;AACf,MAAA,MAAM,EAAE,IAAA,EAAM,eAAA,EAAiB,MAAA,EAAQ,QAAA,EAAU,QAAQ,yBAAA,EAA0B;AACnF,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,QAAA;AAAA,QACR,SAAA,EAAW,IAAA;AAAA,QACX,UAAA;AAAA,QACA,eAAe,YAAA,IAAgB;AAAA,OACjC;AAAA,IACF;AACA,IAAA,MAAM,EAAE,IAAA,EAAM,gBAAA,EAAkB,IAAA,EAAM,SAAS,YAAA,EAAa;AAE5D,IAAA,MAAM,YAA0B,EAAC;AACjC,IAAA,IAAI,OAAA,EAAS,UAAA,KAAe,MAAA,EAAW,SAAA,CAAU,aAAa,OAAA,CAAQ,UAAA;AACtE,IAAA,IAAI,OAAA,EAAS,WAAA,KAAgB,MAAA,EAAW,SAAA,CAAU,SAAS,OAAA,CAAQ,WAAA;AACnE,IAAA,MAAM,QAAA,GAAyB,EAAE,IAAA,EAAM,YAAA,EAAa;AACpD,IAAA,IAAI,OAAA,EAAS,QAAA,KAAa,MAAA,EAAW,QAAA,CAAS,WAAW,OAAA,CAAQ,QAAA;AACjE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,UAAU,SAAS,CAAA;AACrD,IAAA,MAAM;AAAA,MACJ,IAAA,EAAM,eAAA;AAAA,MACN,IAAA;AAAA,MACA,SAAS,QAAA,CAAS,OAAA;AAAA,MAClB,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,aAAa,QAAA,CAAS;AAAA,KACxB;AAEA,IAAA,IAAI,SAAS,WAAA,EAAa;AACxB,MAAA,mBAAA,IAAuB,CAAA;AACvB,MAAA,IAAI,uBAAuB,QAAA,EAAU;AACnC,QAAA,MAAM;AAAA,UACJ,IAAA,EAAM,eAAA;AAAA,UACN,MAAA,EAAQ,QAAA;AAAA,UACR,MAAA,EAAQ,+BAA+B,mBAAmB,CAAA,yBAAA;AAAA,SAC5D;AACA,QAAA,OAAO;AAAA,UACL,MAAA,EAAQ,QAAA;AAAA,UACR,SAAA,EAAW,IAAA;AAAA,UACX,UAAA;AAAA,UACA,eAAe,YAAA,IAAgB;AAAA,SACjC;AAAA,MACF;AAAA,IACF,CAAA,MAAO;AACL,MAAA,mBAAA,GAAsB,CAAA;AAAA,IACxB;AAEA,IAAA,IAAI,QAAA,CAAS,YAAY,MAAA,EAAQ;AAC/B,MAAA,MAAM,EAAE,IAAA,EAAM,eAAA,EAAiB,QAAQ,WAAA,EAAa,MAAA,EAAQ,SAAS,MAAA,EAAO;AAC5E,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,WAAA;AAAA,QACR,SAAA,EAAW,IAAA;AAAA,QACX,UAAA;AAAA,QACA,eAAe,YAAA,IAAgB;AAAA,OACjC;AAAA,IACF;AAKA,IAAA,IAAI,QAAA,CAAS,YAAY,SAAA,EAAW;AAClC,MAAA,MAAM,EAAE,IAAA,EAAM,eAAA,EAAiB,QAAQ,SAAA,EAAW,MAAA,EAAQ,SAAS,MAAA,EAAO;AAC1E,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,SAAA;AAAA,QACR,SAAA,EAAW,IAAA;AAAA,QACX,UAAA;AAAA,QACA,eAAe,YAAA,IAAgB;AAAA,OACjC;AAAA,IACF;AACA,IAAA,IAAI,QAAA,CAAS,YAAY,SAAA,EAAW;AAClC,MAAA,MAAM;AAAA,QACJ,IAAA,EAAM,eAAA;AAAA,QACN,MAAA,EAAQ,WAAA;AAAA,QACR,MAAA,EAAQ,CAAA,SAAA,EAAY,QAAA,CAAS,MAAM,CAAA;AAAA,OACrC;AACA,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,WAAA;AAAA,QACR,SAAA,EAAW,IAAA;AAAA,QACX,UAAA;AAAA,QACA,eAAe,YAAA,IAAgB;AAAA,OACjC;AAAA,IACF;AAGA,IAAA,IAAI,WAAA,KAAgB,MAAA,IAAa,UAAA,IAAc,WAAA,EAAa;AAC1D,MAAA,MAAM;AAAA,QACJ,IAAA,EAAM,eAAA;AAAA,QACN,MAAA,EAAQ,gBAAA;AAAA,QACR,MAAA,EAAQ,CAAA,cAAA,EAAiB,WAAW,CAAA,WAAA,EAAc,UAAU,CAAA,KAAA;AAAA,OAC9D;AACA,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,gBAAA;AAAA,QACR,SAAA,EAAW,IAAA;AAAA,QACX,UAAA;AAAA,QACA,eAAe,YAAA,IAAgB;AAAA,OACjC;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,IAAA,EAAM,cAAA,EAAgB,IAAA,EAAM,QAAQ,kBAAA,EAAmB;AAAA,EACjE;AAEA,EAAA,MAAM;AAAA,IACJ,IAAA,EAAM,eAAA;AAAA,IACN,MAAA,EAAQ,QAAA;AAAA,IACR,MAAA,EAAQ,cAAc,QAAQ,CAAA,WAAA;AAAA,GAChC;AACA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,QAAA;AAAA,IACR,SAAA,EAAW,IAAA;AAAA,IACX,UAAA;AAAA,IACA,eAAe,YAAA,IAAgB;AAAA,GACjC;AACF;AASO,SAAS,mBAAA,CAAoB,MAAc,YAAA,EAA8B;AAI9E,EAAA,OAAO;AAAA,IACLA,0CAAA;AAAA,IACA,0CAAA;AAAA,IACA,EAAA;AAAA,IACA,CAAA;AAAA,EAAgB,IAAI;AAAA,YAAA,CAAA;AAAA,IACpB,EAAA;AAAA,IACA,wBAAA;AAAA,IACA,kGAAA;AAAA,IACA,mGAAA;AAAA,IACA,2BAAA;AAAA,IACA,EAAA;AAAA,IACA,qBAAA;AAAA,IACA,kGAAA;AAAA,IACA,uGAAA;AAAA,IACA,EAAA;AAAA,IACA,mBAAA;AAAA,IACA,uGAAA;AAAA,IACA,oGAAA;AAAA,IACA,EAAA;AAAA,IACA,CAAA;AAAA,EAA4B,YAAA,CAAa,KAAA,CAAM,IAAK,CAAC,CAAA;AAAA,GACvD,CAAE,KAAK,IAAI,CAAA;AACb","file":"run-until-PNO3QQLI.cjs","sourcesContent":["/**\n * Goal-driven Ralph loop (T3.2, ADRs D115-D121).\n *\n * `runUntilImpl` is an `AsyncGenerator<GoalEvent, GoalResult, void>`:\n * yields events as the loop progresses, returns the final result when\n * the goal completes, fails, or is paused. The auxiliary judge model is\n * injected via `deps.judge` so the generator stays free of the `Agent`\n * façade import.\n *\n * EC-C fix: pre-aborted signals emit only `[paused]`, not `[active, paused]`.\n * EC-D: `maxTurns: 0` is supported (vacuous yield active → failed).\n *\n * @internal\n */\n\nimport type { SDKAgent } from \"../../../types/agent.js\";\nimport type { GoalEvent, GoalOptions, GoalResult } from \"../../../types/goal-events.js\";\nimport type { JudgeContext, JudgeOptions } from \"../../judge/judge-call.js\";\nimport type { JudgeResult } from \"../../judge/types.js\";\nimport { GOAL_CONTINUATION_MARKER } from \"./goal-marker.js\";\n\n/** DI contract: the judge is the only external touchpoint. */\nexport interface RunUntilDeps {\n judge: (ctx: JudgeContext, opts?: JudgeOptions) => Promise<JudgeResult>;\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: the goal-loop interleaves turn-start, send, judge, continuation, abort-check, and failure-bail — extracting helpers harms the linear narrative.\nexport async function* runUntilImpl(\n agent: SDKAgent,\n goal: string,\n options: GoalOptions | undefined,\n deps: RunUntilDeps,\n): AsyncGenerator<GoalEvent, GoalResult, void> {\n const maxTurns = options?.maxTurns ?? 20;\n const maxFails = options?.maxConsecutiveJudgeFailures ?? 3;\n const tokenBudget = options?.tokenBudget; // M55 — undefined ⇒ ilimitado\n const signal = options?.signal;\n // Use a function (not direct property access) so TS does not narrow\n // `signal.aborted` to `false | undefined` after the initial check.\n // AbortSignal.aborted is a getter that can flip true between calls.\n // biome-ignore lint/complexity/useOptionalChain: optional-chain would re-narrow signal?.aborted to `false | undefined` after the first check, defeating the purpose of this helper.\n const isAborted = (): boolean => signal !== undefined && signal.aborted;\n let turn = 0;\n let consecutiveFailures = 0;\n let tokensUsed = 0; // M55 — soma observada (0 se usage ausente — fail-open)\n let lastResponse = \"\";\n\n // EC-C: signal already aborted BEFORE first event → emit only [paused].\n if (isAborted()) {\n yield {\n type: \"status_change\",\n status: \"paused\",\n reason: \"aborted via AbortSignal before first turn\",\n };\n return { status: \"paused\", turnsUsed: 0, tokensUsed, finalResponse: undefined };\n }\n\n yield { type: \"status_change\", status: \"active\", reason: \"Goal started\" };\n\n while (turn < maxTurns) {\n if (isAborted()) {\n yield { type: \"status_change\", status: \"paused\", reason: \"aborted via AbortSignal\" };\n return {\n status: \"paused\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n\n turn += 1;\n yield { type: \"turn_start\", turn, goal };\n\n const continuationPrompt = turn === 1 ? goal : composeContinuation(goal, lastResponse);\n\n const run = await agent.send(continuationPrompt);\n // M55 review HIGH — thread the abort INTO the in-flight run: without this, Esc mid-turn is\n // cosmetic (the turn keeps mutating the workspace until it finishes on its own). `run.cancel()`\n // aborts the stream + in-flight tool calls (types/run.ts contract).\n const cancelOnAbort = (): void => {\n void (run as { cancel?: () => Promise<void> }).cancel?.();\n };\n if (signal !== undefined) {\n if (signal.aborted) cancelOnAbort();\n else signal.addEventListener(\"abort\", cancelOnAbort, { once: true });\n }\n const result = await run.wait();\n if (signal !== undefined) signal.removeEventListener(\"abort\", cancelOnAbort);\n lastResponse = result.result ?? \"\";\n // M55 — token accounting fail-open: só soma quando o run reporta usage.\n const turnTokens = (result as { usage?: { totalTokens?: number } }).usage?.totalTokens;\n if (typeof turnTokens === \"number\") tokensUsed += turnTokens;\n // Re-check aborted right after the turn lands: a cancelled turn must NOT spend a judge call.\n if (isAborted()) {\n yield { type: \"status_change\", status: \"paused\", reason: \"aborted via AbortSignal\" };\n return {\n status: \"paused\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n yield { type: \"agent_response\", turn, content: lastResponse };\n\n const judgeOpts: JudgeOptions = {};\n if (options?.judgeModel !== undefined) judgeOpts.judgeModel = options.judgeModel;\n if (options?.judgeApiKey !== undefined) judgeOpts.apiKey = options.judgeApiKey;\n const judgeCtx: JudgeContext = { goal, lastResponse };\n if (options?.subgoals !== undefined) judgeCtx.subgoals = options.subgoals;\n const judgment = await deps.judge(judgeCtx, judgeOpts);\n yield {\n type: \"judge_verdict\",\n turn,\n verdict: judgment.verdict,\n reason: judgment.reason,\n parseFailed: judgment.parseFailed,\n };\n\n if (judgment.parseFailed) {\n consecutiveFailures += 1;\n if (consecutiveFailures >= maxFails) {\n yield {\n type: \"status_change\",\n status: \"failed\",\n reason: `judge model too unreliable (${consecutiveFailures} parse failures in a row)`,\n };\n return {\n status: \"failed\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n } else {\n consecutiveFailures = 0;\n }\n\n if (judgment.verdict === \"done\") {\n yield { type: \"status_change\", status: \"completed\", reason: judgment.reason };\n return {\n status: \"completed\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n // M80 — o braço que faltava. Sem ele, um judge que reconhecesse impossibilidade só podia dizer\n // \"continue\", e o loop repetia o mesmo turno até estourar o orçamento — reportando `failed` por\n // limite em vez de `blocked` por impossibilidade. Duas causas distintas com o mesmo desfecho\n // visível, e o consumidor precisava reconciliar depois do loop para distingui-las.\n if (judgment.verdict === \"blocked\") {\n yield { type: \"status_change\", status: \"blocked\", reason: judgment.reason };\n return {\n status: \"blocked\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n if (judgment.verdict === \"skipped\") {\n yield {\n type: \"status_change\",\n status: \"completed\",\n reason: `skipped: ${judgment.reason}`,\n };\n return {\n status: \"completed\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n\n // M55 — checagem de token budget APÓS o turno (Codex: wind-down suave, para o loop).\n if (tokenBudget !== undefined && tokensUsed >= tokenBudget) {\n yield {\n type: \"status_change\",\n status: \"budget_limited\",\n reason: `token budget (${tokenBudget}) reached: ${tokensUsed} used`,\n };\n return {\n status: \"budget_limited\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n\n yield { type: \"continuation\", turn, prompt: continuationPrompt };\n }\n\n yield {\n type: \"status_change\",\n status: \"failed\",\n reason: `max turns (${maxTurns}) exhausted`,\n };\n return {\n status: \"failed\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n}\n\n/**\n * Build the continuation user message for turns 2+. Keeps last response\n * preview short so we don't bloat the prompt cache.\n *\n * @internal\n */\n\nexport function composeContinuation(goal: string, lastResponse: string): string {\n // M55 — Codex-faithful continuation (ext/goal templates/goals/continuation.md): keep the FULL\n // objective intact, work from current-state evidence, and audit completion requirement-by-requirement\n // before declaring done. Improves the quality of what the judge then evaluates.\n return [\n GOAL_CONTINUATION_MARKER,\n \"Continue working toward the active goal.\",\n \"\",\n `<objective>\\n${goal}\\n</objective>`,\n \"\",\n \"Continuation behavior:\",\n \"- This goal persists across turns. Keep the full objective intact; if it cannot be finished now,\",\n \" make concrete progress toward the real requested end state and do not redefine success around a\",\n \" smaller or easier task.\",\n \"\",\n \"Work from evidence:\",\n \"- Use the current worktree and external state as authoritative. Inspect the current state before\",\n \" relying on it. Improve, replace, or remove existing work as needed to satisfy the actual objective.\",\n \"\",\n \"Completion audit:\",\n \"- Before deciding the goal is achieved, treat completion as unproven and verify it against the actual\",\n \" current state, requirement by requirement. Treat uncertain or indirect evidence as not achieved.\",\n \"\",\n `Your last response was:\\n${lastResponse.slice(-1000)}`,\n ].join(\"\\n\");\n}\n"]}
|
|
@@ -96,6 +96,15 @@ async function* runUntilImpl(agent, goal, options, deps) {
|
|
|
96
96
|
finalResponse: lastResponse || void 0
|
|
97
97
|
};
|
|
98
98
|
}
|
|
99
|
+
if (judgment.verdict === "blocked") {
|
|
100
|
+
yield { type: "status_change", status: "blocked", reason: judgment.reason };
|
|
101
|
+
return {
|
|
102
|
+
status: "blocked",
|
|
103
|
+
turnsUsed: turn,
|
|
104
|
+
tokensUsed,
|
|
105
|
+
finalResponse: lastResponse || void 0
|
|
106
|
+
};
|
|
107
|
+
}
|
|
99
108
|
if (judgment.verdict === "skipped") {
|
|
100
109
|
yield {
|
|
101
110
|
type: "status_change",
|
|
@@ -164,5 +173,5 @@ ${lastResponse.slice(-1e3)}`
|
|
|
164
173
|
}
|
|
165
174
|
|
|
166
175
|
export { composeContinuation, runUntilImpl };
|
|
167
|
-
//# sourceMappingURL=run-until-
|
|
168
|
-
//# sourceMappingURL=run-until-
|
|
176
|
+
//# sourceMappingURL=run-until-XLHEHRQM.js.map
|
|
177
|
+
//# sourceMappingURL=run-until-XLHEHRQM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/internal/runtime/lifecycle/run-until.ts"],"names":[],"mappings":";;;AA2BA,gBAAuB,YAAA,CACrB,KAAA,EACA,IAAA,EACA,OAAA,EACA,IAAA,EAC6C;AAC7C,EAAA,MAAM,QAAA,GAAW,SAAS,QAAA,IAAY,EAAA;AACtC,EAAA,MAAM,QAAA,GAAW,SAAS,2BAAA,IAA+B,CAAA;AACzD,EAAA,MAAM,cAAc,OAAA,EAAS,WAAA;AAC7B,EAAA,MAAM,SAAS,OAAA,EAAS,MAAA;AAKxB,EAAA,MAAM,SAAA,GAAY,MAAe,MAAA,KAAW,MAAA,IAAa,MAAA,CAAO,OAAA;AAChE,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,IAAI,mBAAA,GAAsB,CAAA;AAC1B,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,YAAA,GAAe,EAAA;AAGnB,EAAA,IAAI,WAAU,EAAG;AACf,IAAA,MAAM;AAAA,MACJ,IAAA,EAAM,eAAA;AAAA,MACN,MAAA,EAAQ,QAAA;AAAA,MACR,MAAA,EAAQ;AAAA,KACV;AACA,IAAA,OAAO,EAAE,MAAA,EAAQ,QAAA,EAAU,WAAW,CAAA,EAAG,UAAA,EAAY,eAAe,MAAA,EAAU;AAAA,EAChF;AAEA,EAAA,MAAM,EAAE,IAAA,EAAM,eAAA,EAAiB,MAAA,EAAQ,QAAA,EAAU,QAAQ,cAAA,EAAe;AAExE,EAAA,OAAO,OAAO,QAAA,EAAU;AACtB,IAAA,IAAI,WAAU,EAAG;AACf,MAAA,MAAM,EAAE,IAAA,EAAM,eAAA,EAAiB,MAAA,EAAQ,QAAA,EAAU,QAAQ,yBAAA,EAA0B;AACnF,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,QAAA;AAAA,QACR,SAAA,EAAW,IAAA;AAAA,QACX,UAAA;AAAA,QACA,eAAe,YAAA,IAAgB;AAAA,OACjC;AAAA,IACF;AAEA,IAAA,IAAA,IAAQ,CAAA;AACR,IAAA,MAAM,EAAE,IAAA,EAAM,YAAA,EAAc,IAAA,EAAM,IAAA,EAAK;AAEvC,IAAA,MAAM,qBAAqB,IAAA,KAAS,CAAA,GAAI,IAAA,GAAO,mBAAA,CAAoB,MAAM,YAAY,CAAA;AAErF,IAAA,MAAM,GAAA,GAAM,MAAM,KAAA,CAAM,IAAA,CAAK,kBAAkB,CAAA;AAI/C,IAAA,MAAM,gBAAgB,MAAY;AAChC,MAAA,KAAM,IAAyC,MAAA,IAAS;AAAA,IAC1D,CAAA;AACA,IAAA,IAAI,WAAW,MAAA,EAAW;AACxB,MAAA,IAAI,MAAA,CAAO,SAAS,aAAA,EAAc;AAAA,kBACtB,gBAAA,CAAiB,OAAA,EAAS,eAAe,EAAE,IAAA,EAAM,MAAM,CAAA;AAAA,IACrE;AACA,IAAA,MAAM,MAAA,GAAS,MAAM,GAAA,CAAI,IAAA,EAAK;AAC9B,IAAA,IAAI,MAAA,KAAW,MAAA,EAAW,MAAA,CAAO,mBAAA,CAAoB,SAAS,aAAa,CAAA;AAC3E,IAAA,YAAA,GAAe,OAAO,MAAA,IAAU,EAAA;AAEhC,IAAA,MAAM,UAAA,GAAc,OAAgD,KAAA,EAAO,WAAA;AAC3E,IAAA,IAAI,OAAO,UAAA,KAAe,QAAA,EAAU,UAAA,IAAc,UAAA;AAElD,IAAA,IAAI,WAAU,EAAG;AACf,MAAA,MAAM,EAAE,IAAA,EAAM,eAAA,EAAiB,MAAA,EAAQ,QAAA,EAAU,QAAQ,yBAAA,EAA0B;AACnF,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,QAAA;AAAA,QACR,SAAA,EAAW,IAAA;AAAA,QACX,UAAA;AAAA,QACA,eAAe,YAAA,IAAgB;AAAA,OACjC;AAAA,IACF;AACA,IAAA,MAAM,EAAE,IAAA,EAAM,gBAAA,EAAkB,IAAA,EAAM,SAAS,YAAA,EAAa;AAE5D,IAAA,MAAM,YAA0B,EAAC;AACjC,IAAA,IAAI,OAAA,EAAS,UAAA,KAAe,MAAA,EAAW,SAAA,CAAU,aAAa,OAAA,CAAQ,UAAA;AACtE,IAAA,IAAI,OAAA,EAAS,WAAA,KAAgB,MAAA,EAAW,SAAA,CAAU,SAAS,OAAA,CAAQ,WAAA;AACnE,IAAA,MAAM,QAAA,GAAyB,EAAE,IAAA,EAAM,YAAA,EAAa;AACpD,IAAA,IAAI,OAAA,EAAS,QAAA,KAAa,MAAA,EAAW,QAAA,CAAS,WAAW,OAAA,CAAQ,QAAA;AACjE,IAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,KAAA,CAAM,UAAU,SAAS,CAAA;AACrD,IAAA,MAAM;AAAA,MACJ,IAAA,EAAM,eAAA;AAAA,MACN,IAAA;AAAA,MACA,SAAS,QAAA,CAAS,OAAA;AAAA,MAClB,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,aAAa,QAAA,CAAS;AAAA,KACxB;AAEA,IAAA,IAAI,SAAS,WAAA,EAAa;AACxB,MAAA,mBAAA,IAAuB,CAAA;AACvB,MAAA,IAAI,uBAAuB,QAAA,EAAU;AACnC,QAAA,MAAM;AAAA,UACJ,IAAA,EAAM,eAAA;AAAA,UACN,MAAA,EAAQ,QAAA;AAAA,UACR,MAAA,EAAQ,+BAA+B,mBAAmB,CAAA,yBAAA;AAAA,SAC5D;AACA,QAAA,OAAO;AAAA,UACL,MAAA,EAAQ,QAAA;AAAA,UACR,SAAA,EAAW,IAAA;AAAA,UACX,UAAA;AAAA,UACA,eAAe,YAAA,IAAgB;AAAA,SACjC;AAAA,MACF;AAAA,IACF,CAAA,MAAO;AACL,MAAA,mBAAA,GAAsB,CAAA;AAAA,IACxB;AAEA,IAAA,IAAI,QAAA,CAAS,YAAY,MAAA,EAAQ;AAC/B,MAAA,MAAM,EAAE,IAAA,EAAM,eAAA,EAAiB,QAAQ,WAAA,EAAa,MAAA,EAAQ,SAAS,MAAA,EAAO;AAC5E,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,WAAA;AAAA,QACR,SAAA,EAAW,IAAA;AAAA,QACX,UAAA;AAAA,QACA,eAAe,YAAA,IAAgB;AAAA,OACjC;AAAA,IACF;AAKA,IAAA,IAAI,QAAA,CAAS,YAAY,SAAA,EAAW;AAClC,MAAA,MAAM,EAAE,IAAA,EAAM,eAAA,EAAiB,QAAQ,SAAA,EAAW,MAAA,EAAQ,SAAS,MAAA,EAAO;AAC1E,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,SAAA;AAAA,QACR,SAAA,EAAW,IAAA;AAAA,QACX,UAAA;AAAA,QACA,eAAe,YAAA,IAAgB;AAAA,OACjC;AAAA,IACF;AACA,IAAA,IAAI,QAAA,CAAS,YAAY,SAAA,EAAW;AAClC,MAAA,MAAM;AAAA,QACJ,IAAA,EAAM,eAAA;AAAA,QACN,MAAA,EAAQ,WAAA;AAAA,QACR,MAAA,EAAQ,CAAA,SAAA,EAAY,QAAA,CAAS,MAAM,CAAA;AAAA,OACrC;AACA,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,WAAA;AAAA,QACR,SAAA,EAAW,IAAA;AAAA,QACX,UAAA;AAAA,QACA,eAAe,YAAA,IAAgB;AAAA,OACjC;AAAA,IACF;AAGA,IAAA,IAAI,WAAA,KAAgB,MAAA,IAAa,UAAA,IAAc,WAAA,EAAa;AAC1D,MAAA,MAAM;AAAA,QACJ,IAAA,EAAM,eAAA;AAAA,QACN,MAAA,EAAQ,gBAAA;AAAA,QACR,MAAA,EAAQ,CAAA,cAAA,EAAiB,WAAW,CAAA,WAAA,EAAc,UAAU,CAAA,KAAA;AAAA,OAC9D;AACA,MAAA,OAAO;AAAA,QACL,MAAA,EAAQ,gBAAA;AAAA,QACR,SAAA,EAAW,IAAA;AAAA,QACX,UAAA;AAAA,QACA,eAAe,YAAA,IAAgB;AAAA,OACjC;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,IAAA,EAAM,cAAA,EAAgB,IAAA,EAAM,QAAQ,kBAAA,EAAmB;AAAA,EACjE;AAEA,EAAA,MAAM;AAAA,IACJ,IAAA,EAAM,eAAA;AAAA,IACN,MAAA,EAAQ,QAAA;AAAA,IACR,MAAA,EAAQ,cAAc,QAAQ,CAAA,WAAA;AAAA,GAChC;AACA,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,QAAA;AAAA,IACR,SAAA,EAAW,IAAA;AAAA,IACX,UAAA;AAAA,IACA,eAAe,YAAA,IAAgB;AAAA,GACjC;AACF;AASO,SAAS,mBAAA,CAAoB,MAAc,YAAA,EAA8B;AAI9E,EAAA,OAAO;AAAA,IACL,wBAAA;AAAA,IACA,0CAAA;AAAA,IACA,EAAA;AAAA,IACA,CAAA;AAAA,EAAgB,IAAI;AAAA,YAAA,CAAA;AAAA,IACpB,EAAA;AAAA,IACA,wBAAA;AAAA,IACA,kGAAA;AAAA,IACA,mGAAA;AAAA,IACA,2BAAA;AAAA,IACA,EAAA;AAAA,IACA,qBAAA;AAAA,IACA,kGAAA;AAAA,IACA,uGAAA;AAAA,IACA,EAAA;AAAA,IACA,mBAAA;AAAA,IACA,uGAAA;AAAA,IACA,oGAAA;AAAA,IACA,EAAA;AAAA,IACA,CAAA;AAAA,EAA4B,YAAA,CAAa,KAAA,CAAM,IAAK,CAAC,CAAA;AAAA,GACvD,CAAE,KAAK,IAAI,CAAA;AACb","file":"run-until-XLHEHRQM.js","sourcesContent":["/**\n * Goal-driven Ralph loop (T3.2, ADRs D115-D121).\n *\n * `runUntilImpl` is an `AsyncGenerator<GoalEvent, GoalResult, void>`:\n * yields events as the loop progresses, returns the final result when\n * the goal completes, fails, or is paused. The auxiliary judge model is\n * injected via `deps.judge` so the generator stays free of the `Agent`\n * façade import.\n *\n * EC-C fix: pre-aborted signals emit only `[paused]`, not `[active, paused]`.\n * EC-D: `maxTurns: 0` is supported (vacuous yield active → failed).\n *\n * @internal\n */\n\nimport type { SDKAgent } from \"../../../types/agent.js\";\nimport type { GoalEvent, GoalOptions, GoalResult } from \"../../../types/goal-events.js\";\nimport type { JudgeContext, JudgeOptions } from \"../../judge/judge-call.js\";\nimport type { JudgeResult } from \"../../judge/types.js\";\nimport { GOAL_CONTINUATION_MARKER } from \"./goal-marker.js\";\n\n/** DI contract: the judge is the only external touchpoint. */\nexport interface RunUntilDeps {\n judge: (ctx: JudgeContext, opts?: JudgeOptions) => Promise<JudgeResult>;\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: the goal-loop interleaves turn-start, send, judge, continuation, abort-check, and failure-bail — extracting helpers harms the linear narrative.\nexport async function* runUntilImpl(\n agent: SDKAgent,\n goal: string,\n options: GoalOptions | undefined,\n deps: RunUntilDeps,\n): AsyncGenerator<GoalEvent, GoalResult, void> {\n const maxTurns = options?.maxTurns ?? 20;\n const maxFails = options?.maxConsecutiveJudgeFailures ?? 3;\n const tokenBudget = options?.tokenBudget; // M55 — undefined ⇒ ilimitado\n const signal = options?.signal;\n // Use a function (not direct property access) so TS does not narrow\n // `signal.aborted` to `false | undefined` after the initial check.\n // AbortSignal.aborted is a getter that can flip true between calls.\n // biome-ignore lint/complexity/useOptionalChain: optional-chain would re-narrow signal?.aborted to `false | undefined` after the first check, defeating the purpose of this helper.\n const isAborted = (): boolean => signal !== undefined && signal.aborted;\n let turn = 0;\n let consecutiveFailures = 0;\n let tokensUsed = 0; // M55 — soma observada (0 se usage ausente — fail-open)\n let lastResponse = \"\";\n\n // EC-C: signal already aborted BEFORE first event → emit only [paused].\n if (isAborted()) {\n yield {\n type: \"status_change\",\n status: \"paused\",\n reason: \"aborted via AbortSignal before first turn\",\n };\n return { status: \"paused\", turnsUsed: 0, tokensUsed, finalResponse: undefined };\n }\n\n yield { type: \"status_change\", status: \"active\", reason: \"Goal started\" };\n\n while (turn < maxTurns) {\n if (isAborted()) {\n yield { type: \"status_change\", status: \"paused\", reason: \"aborted via AbortSignal\" };\n return {\n status: \"paused\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n\n turn += 1;\n yield { type: \"turn_start\", turn, goal };\n\n const continuationPrompt = turn === 1 ? goal : composeContinuation(goal, lastResponse);\n\n const run = await agent.send(continuationPrompt);\n // M55 review HIGH — thread the abort INTO the in-flight run: without this, Esc mid-turn is\n // cosmetic (the turn keeps mutating the workspace until it finishes on its own). `run.cancel()`\n // aborts the stream + in-flight tool calls (types/run.ts contract).\n const cancelOnAbort = (): void => {\n void (run as { cancel?: () => Promise<void> }).cancel?.();\n };\n if (signal !== undefined) {\n if (signal.aborted) cancelOnAbort();\n else signal.addEventListener(\"abort\", cancelOnAbort, { once: true });\n }\n const result = await run.wait();\n if (signal !== undefined) signal.removeEventListener(\"abort\", cancelOnAbort);\n lastResponse = result.result ?? \"\";\n // M55 — token accounting fail-open: só soma quando o run reporta usage.\n const turnTokens = (result as { usage?: { totalTokens?: number } }).usage?.totalTokens;\n if (typeof turnTokens === \"number\") tokensUsed += turnTokens;\n // Re-check aborted right after the turn lands: a cancelled turn must NOT spend a judge call.\n if (isAborted()) {\n yield { type: \"status_change\", status: \"paused\", reason: \"aborted via AbortSignal\" };\n return {\n status: \"paused\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n yield { type: \"agent_response\", turn, content: lastResponse };\n\n const judgeOpts: JudgeOptions = {};\n if (options?.judgeModel !== undefined) judgeOpts.judgeModel = options.judgeModel;\n if (options?.judgeApiKey !== undefined) judgeOpts.apiKey = options.judgeApiKey;\n const judgeCtx: JudgeContext = { goal, lastResponse };\n if (options?.subgoals !== undefined) judgeCtx.subgoals = options.subgoals;\n const judgment = await deps.judge(judgeCtx, judgeOpts);\n yield {\n type: \"judge_verdict\",\n turn,\n verdict: judgment.verdict,\n reason: judgment.reason,\n parseFailed: judgment.parseFailed,\n };\n\n if (judgment.parseFailed) {\n consecutiveFailures += 1;\n if (consecutiveFailures >= maxFails) {\n yield {\n type: \"status_change\",\n status: \"failed\",\n reason: `judge model too unreliable (${consecutiveFailures} parse failures in a row)`,\n };\n return {\n status: \"failed\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n } else {\n consecutiveFailures = 0;\n }\n\n if (judgment.verdict === \"done\") {\n yield { type: \"status_change\", status: \"completed\", reason: judgment.reason };\n return {\n status: \"completed\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n // M80 — o braço que faltava. Sem ele, um judge que reconhecesse impossibilidade só podia dizer\n // \"continue\", e o loop repetia o mesmo turno até estourar o orçamento — reportando `failed` por\n // limite em vez de `blocked` por impossibilidade. Duas causas distintas com o mesmo desfecho\n // visível, e o consumidor precisava reconciliar depois do loop para distingui-las.\n if (judgment.verdict === \"blocked\") {\n yield { type: \"status_change\", status: \"blocked\", reason: judgment.reason };\n return {\n status: \"blocked\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n if (judgment.verdict === \"skipped\") {\n yield {\n type: \"status_change\",\n status: \"completed\",\n reason: `skipped: ${judgment.reason}`,\n };\n return {\n status: \"completed\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n\n // M55 — checagem de token budget APÓS o turno (Codex: wind-down suave, para o loop).\n if (tokenBudget !== undefined && tokensUsed >= tokenBudget) {\n yield {\n type: \"status_change\",\n status: \"budget_limited\",\n reason: `token budget (${tokenBudget}) reached: ${tokensUsed} used`,\n };\n return {\n status: \"budget_limited\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n }\n\n yield { type: \"continuation\", turn, prompt: continuationPrompt };\n }\n\n yield {\n type: \"status_change\",\n status: \"failed\",\n reason: `max turns (${maxTurns}) exhausted`,\n };\n return {\n status: \"failed\",\n turnsUsed: turn,\n tokensUsed,\n finalResponse: lastResponse || undefined,\n };\n}\n\n/**\n * Build the continuation user message for turns 2+. Keeps last response\n * preview short so we don't bloat the prompt cache.\n *\n * @internal\n */\n\nexport function composeContinuation(goal: string, lastResponse: string): string {\n // M55 — Codex-faithful continuation (ext/goal templates/goals/continuation.md): keep the FULL\n // objective intact, work from current-state evidence, and audit completion requirement-by-requirement\n // before declaring done. Improves the quality of what the judge then evaluates.\n return [\n GOAL_CONTINUATION_MARKER,\n \"Continue working toward the active goal.\",\n \"\",\n `<objective>\\n${goal}\\n</objective>`,\n \"\",\n \"Continuation behavior:\",\n \"- This goal persists across turns. Keep the full objective intact; if it cannot be finished now,\",\n \" make concrete progress toward the real requested end state and do not redefine success around a\",\n \" smaller or easier task.\",\n \"\",\n \"Work from evidence:\",\n \"- Use the current worktree and external state as authoritative. Inspect the current state before\",\n \" relying on it. Improve, replace, or remove existing work as needed to satisfy the actual objective.\",\n \"\",\n \"Completion audit:\",\n \"- Before deciding the goal is achieved, treat completion as unproven and verify it against the actual\",\n \" current state, requirement by requirement. Treat uncertain or indirect evidence as not achieved.\",\n \"\",\n `Your last response was:\\n${lastResponse.slice(-1000)}`,\n ].join(\"\\n\");\n}\n"]}
|
|
@@ -40,7 +40,8 @@ export type GoalEvent = {
|
|
|
40
40
|
} | {
|
|
41
41
|
type: "judge_verdict";
|
|
42
42
|
turn: number;
|
|
43
|
-
|
|
43
|
+
/** M80 — `"blocked"` entrou: o judge pode declarar impossibilidade, não só "continue". */
|
|
44
|
+
verdict: "done" | "continue" | "skipped" | "blocked";
|
|
44
45
|
reason: string;
|
|
45
46
|
parseFailed: boolean;
|
|
46
47
|
} | {
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/judge/parse-verdict.ts","../src/internal/judge/judge-call.ts"],"names":[],"mappings":"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","file":"judge-call-7CF7D334.cjs","sourcesContent":["/**\n * Pure verdict parser (T2.1, ADRs D120-D121).\n *\n * Strict prefix matching against `DONE:`, `CONTINUE:`, `SKIPPED:`. Reason\n * is the suffix, trimmed. Anything else is fail-safe: verdict = `continue`,\n * `parseFailed: true` — caller's max-consecutive-failure cap stops the\n * loop after N flakes.\n *\n * @internal\n */\n\nimport type { JudgeResult } from \"./types.js\";\n\nconst DONE_PREFIX = \"DONE:\";\nconst CONTINUE_PREFIX = \"CONTINUE:\";\nconst SKIPPED_PREFIX = \"SKIPPED:\";\n\nexport function parseVerdict(text: string): JudgeResult {\n const trimmed = text.trim();\n\n if (trimmed.startsWith(DONE_PREFIX)) {\n return {\n verdict: \"done\",\n reason: trimmed.slice(DONE_PREFIX.length).trim(),\n parseFailed: false,\n };\n }\n if (trimmed.startsWith(CONTINUE_PREFIX)) {\n return {\n verdict: \"continue\",\n reason: trimmed.slice(CONTINUE_PREFIX.length).trim(),\n parseFailed: false,\n };\n }\n if (trimmed.startsWith(SKIPPED_PREFIX)) {\n return {\n verdict: \"skipped\",\n reason: trimmed.slice(SKIPPED_PREFIX.length).trim(),\n parseFailed: false,\n };\n }\n\n // Fail-safe: ADR D121 — prefer \"continue\" so we don't stop prematurely.\n // The runUntil loop counts consecutive parseFailed responses and bails\n // after `maxConsecutiveJudgeFailures` (default 3).\n return {\n verdict: \"continue\",\n reason: `judge response malformed: \"${trimmed.slice(0, 100)}\"`,\n parseFailed: true,\n };\n}\n","/**\n * Judge call primitive (T2.2, ADRs D119-D121).\n *\n * Instantiates a short-lived auxiliary agent that evaluates whether a\n * goal is satisfied. The auxiliary judge runs with `tools: []` and a\n * cheap model (default `openai/gpt-4o-mini`) — see ADR D119. The judge\n * model needs only API access; we read `OPENROUTER_API_KEY` directly\n * from the environment (EC-A — single source of truth) and let the\n * caller override via {@link JudgeOptions.apiKey} for Anthropic or\n * direct-OpenAI environments.\n *\n * NOTE: judge aux agents created from inside a `forkAgent` context will\n * inherit the parent fork's whitelist via AsyncLocalStorage (EC-J).\n * `tools: []` keeps this benign today; future callers that add tools to\n * a judge should be aware.\n *\n * @internal\n */\n\nimport type { AgentOptions, SDKAgent } from \"../../types/agent.js\";\nimport { parseVerdict } from \"./parse-verdict.js\";\nimport type { JudgeResult } from \"./types.js\";\n\n/** Inputs to the judge — pure data. */\nexport interface JudgeContext {\n goal: string;\n lastResponse: string;\n subgoals?: string[];\n}\n\n/** Caller-supplied tuning knobs for the judge call. */\nexport interface JudgeOptions {\n /** Judge model identifier. Default `\"openai/gpt-4o-mini\"` (ADR D119). */\n judgeModel?: string;\n /** Override env. Default `process.env.OPENROUTER_API_KEY` (EC-A). */\n apiKey?: string;\n}\n\n/** Dependencies injected so `judge-call.ts` stays free of `Agent` import. */\nexport interface JudgeDeps {\n create: (options: AgentOptions) => Promise<SDKAgent>;\n}\n\n/**\n * Run the judge auxiliary agent and parse the verdict. Always returns a\n * `JudgeResult` — failures are folded into `{ parseFailed: true,\n * verdict: \"continue\" }` so the loop can decide based on consecutive\n * failures (ADR D121).\n *\n * @internal\n */\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: judge call must (1) check env or override, (2) catch errors as fail-safe, (3) ensure aux dispose runs once regardless of outcome — three concerns linearly arranged, harm clarity to extract.\nexport async function judgeCallImpl(\n ctx: JudgeContext,\n options: JudgeOptions | undefined,\n deps: JudgeDeps,\n): Promise<JudgeResult> {\n const prompt = composeJudgePrompt(ctx);\n // EC-A: single env source — OpenRouter only. No multi-provider fallback.\n const apiKey = options?.apiKey ?? process.env.OPENROUTER_API_KEY;\n if (apiKey === undefined) {\n return {\n verdict: \"continue\",\n reason:\n \"judge unavailable: OPENROUTER_API_KEY missing and no override passed via options.apiKey\",\n parseFailed: true,\n };\n }\n\n const judgeModel = options?.judgeModel ?? \"openai/gpt-4o-mini\";\n let auxAgent: SDKAgent | undefined;\n try {\n auxAgent = await deps.create({\n apiKey,\n model: { id: judgeModel },\n tools: [],\n local: {},\n metadata: { forkOrigin: \"judge\" },\n } as AgentOptions);\n const run = await auxAgent.send(prompt);\n const result = await run.wait();\n return parseVerdict(result.result ?? \"\");\n } catch (err) {\n return {\n verdict: \"continue\",\n reason: `judge call failed: ${err instanceof Error ? err.message : String(err)}`,\n parseFailed: true,\n };\n } finally {\n if (auxAgent !== undefined) {\n try {\n await auxAgent.dispose();\n } catch {\n // dispose errors are non-fatal; judge result is already prepared\n }\n }\n }\n}\n\n/**\n * Build the strict-format prompt the judge expects.\n *\n * @internal\n */\nexport function composeJudgePrompt(ctx: JudgeContext): string {\n const subgoals =\n ctx.subgoals !== undefined && ctx.subgoals.length > 0 ? ctx.subgoals.join(\", \") : \"(none)\";\n return `You are a goal judge. Determine if this goal is satisfied.\n\nGoal: ${ctx.goal}\nSubgoals: ${subgoals}\nLast agent response: ${ctx.lastResponse}\n\nRespond with EXACTLY one of:\n- DONE: <reason>\n- CONTINUE: <what's left>\n- SKIPPED: <why not applicable>\n\nBe strict. If unclear, prefer CONTINUE.`;\n}\n"]}
|