@dexto/core 1.8.11 → 1.9.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/approval/manager.cjs +37 -325
- package/dist/approval/manager.d.ts +10 -109
- package/dist/approval/manager.d.ts.map +1 -1
- package/dist/approval/manager.js +37 -316
- package/dist/approval/schemas.cjs +8 -51
- package/dist/approval/schemas.d.ts +5 -179
- package/dist/approval/schemas.d.ts.map +1 -1
- package/dist/approval/schemas.js +8 -47
- package/dist/approval/types.cjs +0 -6
- package/dist/approval/types.d.ts +2 -27
- package/dist/approval/types.d.ts.map +1 -1
- package/dist/approval/types.js +0 -6
- package/dist/context/content-clone.cjs +12 -8
- package/dist/context/content-clone.d.ts.map +1 -1
- package/dist/context/content-clone.js +12 -8
- package/dist/errors/DextoRuntimeError.cjs +3 -1
- package/dist/errors/DextoRuntimeError.d.ts +5 -3
- package/dist/errors/DextoRuntimeError.d.ts.map +1 -1
- package/dist/errors/DextoRuntimeError.js +3 -1
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.d.ts.map +1 -1
- package/dist/errors/types.d.ts +1 -0
- package/dist/errors/types.d.ts.map +1 -1
- package/dist/events/index.d.ts +2 -2
- package/dist/events/index.d.ts.map +1 -1
- package/dist/llm/executor/provider-error.cjs +25 -4
- package/dist/llm/executor/provider-error.d.ts.map +1 -1
- package/dist/llm/executor/provider-error.js +25 -4
- package/dist/llm/executor/stream-processor.cjs +61 -0
- package/dist/llm/executor/stream-processor.d.ts.map +1 -1
- package/dist/llm/executor/stream-processor.js +61 -0
- package/dist/llm/executor/turn-executor.cjs +93 -26
- package/dist/llm/executor/turn-executor.d.ts +2 -0
- package/dist/llm/executor/turn-executor.d.ts.map +1 -1
- package/dist/llm/executor/turn-executor.js +93 -26
- package/dist/llm/formatters/vercel.cjs +66 -0
- package/dist/llm/formatters/vercel.d.ts.map +1 -1
- package/dist/llm/formatters/vercel.js +66 -0
- package/dist/llm/services/factory.cjs +3 -2
- package/dist/llm/services/factory.d.ts.map +1 -1
- package/dist/llm/services/factory.js +3 -2
- package/dist/llm/services/types.d.ts +8 -0
- package/dist/llm/services/types.d.ts.map +1 -1
- package/dist/llm/services/vercel.cjs +6 -1
- package/dist/llm/services/vercel.d.ts +3 -2
- package/dist/llm/services/vercel.d.ts.map +1 -1
- package/dist/llm/services/vercel.js +6 -1
- package/dist/session/chat-session.cjs +3 -0
- package/dist/session/chat-session.d.ts +2 -1
- package/dist/session/chat-session.d.ts.map +1 -1
- package/dist/session/chat-session.js +3 -0
- package/dist/session/message-queue.cjs +48 -75
- package/dist/session/message-queue.d.ts +1 -2
- package/dist/session/message-queue.d.ts.map +1 -1
- package/dist/session/message-queue.js +48 -75
- package/dist/session/session-manager.cjs +14 -32
- package/dist/session/session-manager.d.ts +5 -2
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +14 -32
- package/dist/storage/approvals/types.cjs +2 -9
- package/dist/storage/approvals/types.d.ts +4 -16
- package/dist/storage/approvals/types.d.ts.map +1 -1
- package/dist/storage/approvals/types.js +2 -8
- package/dist/storage/database/types.d.ts +5 -0
- package/dist/storage/database/types.d.ts.map +1 -1
- package/dist/storage/index.cjs +0 -2
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +1 -2
- package/dist/storage/message-queue/types.d.ts +14 -6
- package/dist/storage/message-queue/types.d.ts.map +1 -1
- package/dist/storage/stores/backend.cjs +68 -32
- package/dist/storage/stores/backend.d.ts +17 -8
- package/dist/storage/stores/backend.d.ts.map +1 -1
- package/dist/storage/stores/backend.js +69 -33
- package/dist/storage/stores/in-memory.cjs +26 -11
- package/dist/storage/stores/in-memory.d.ts.map +1 -1
- package/dist/storage/stores/in-memory.js +27 -12
- package/dist/test-utils/in-memory-storage.cjs +11 -0
- package/dist/test-utils/in-memory-storage.js +11 -0
- package/dist/test-utils/session-state-stores.cjs +25 -9
- package/dist/test-utils/session-state-stores.js +26 -10
- package/dist/tools/approval/tool-approval-policy.cjs +87 -0
- package/dist/tools/approval/tool-approval-policy.d.ts +34 -0
- package/dist/tools/approval/tool-approval-policy.d.ts.map +1 -0
- package/dist/tools/approval/tool-approval-policy.js +64 -0
- package/dist/tools/error-codes.cjs +0 -1
- package/dist/tools/error-codes.d.ts +0 -1
- package/dist/tools/error-codes.d.ts.map +1 -1
- package/dist/tools/error-codes.js +0 -1
- package/dist/tools/errors.cjs +0 -15
- package/dist/tools/errors.d.ts +0 -9
- package/dist/tools/errors.d.ts.map +1 -1
- package/dist/tools/errors.js +0 -15
- package/dist/tools/index.cjs +2 -0
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +5 -1
- package/dist/tools/tool-manager.cjs +94 -312
- package/dist/tools/tool-manager.d.ts +4 -19
- package/dist/tools/tool-manager.d.ts.map +1 -1
- package/dist/tools/tool-manager.js +95 -316
- package/dist/tools/types.d.ts +10 -9
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/utils/service-initializer.cjs +3 -0
- package/dist/utils/service-initializer.d.ts +2 -1
- package/dist/utils/service-initializer.d.ts.map +1 -1
- package/dist/utils/service-initializer.js +3 -0
- package/package.json +2 -2
- package/dist/tools/pattern-utils.cjs +0 -33
- package/dist/tools/pattern-utils.d.ts +0 -20
- package/dist/tools/pattern-utils.d.ts.map +0 -1
- package/dist/tools/pattern-utils.js +0 -10
|
@@ -51,6 +51,7 @@ var import_types3 = require("../../approval/types.js");
|
|
|
51
51
|
var import_content_audit = require("../../context/content-audit.js");
|
|
52
52
|
const MCP_TOOL_PREFIX = "mcp--";
|
|
53
53
|
const MODEL_REQUEST_MAX_RETRIES = 2;
|
|
54
|
+
const TOOL_SUPPORT_PROBE_TIMEOUT_MS = 5e3;
|
|
54
55
|
const LLMFinishReasonStateSchema = import_zod.z.enum([
|
|
55
56
|
"stop",
|
|
56
57
|
"tool-calls",
|
|
@@ -182,6 +183,24 @@ function toModelStepRequestState(request) {
|
|
|
182
183
|
}
|
|
183
184
|
const toolSupportCache = /* @__PURE__ */ new Map();
|
|
184
185
|
const LOCAL_PROVIDERS = ["ollama", "local"];
|
|
186
|
+
function isManagedGatewayProvider(provider) {
|
|
187
|
+
return provider === "dexto-nova";
|
|
188
|
+
}
|
|
189
|
+
function toolSupportValidationAttributes(result) {
|
|
190
|
+
const attributes = {
|
|
191
|
+
"llm.tool_support.cache_hit": result.cacheHit,
|
|
192
|
+
"llm.tool_support.validation_mode": result.validationMode,
|
|
193
|
+
"llm.tools_supported": result.supported
|
|
194
|
+
};
|
|
195
|
+
if (result.validationMode !== "probe") {
|
|
196
|
+
return attributes;
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
...attributes,
|
|
200
|
+
"llm.tool_support.probe_outcome": result.probeOutcome,
|
|
201
|
+
"llm.tool_support.probe_timeout_ms": result.probeTimeoutMs
|
|
202
|
+
};
|
|
203
|
+
}
|
|
185
204
|
class TurnExecutor {
|
|
186
205
|
constructor(model, toolManager, contextManager, eventBus, resourceManager, sessionId, config, llmContext, logger, steerQueue, followUpQueue, modelLimits, externalSignal, compactionStrategy = null, runContext) {
|
|
187
206
|
this.model = model;
|
|
@@ -607,7 +626,21 @@ class TurnExecutor {
|
|
|
607
626
|
}
|
|
608
627
|
async startTurn() {
|
|
609
628
|
this.eventBus.emit("llm:thinking", {});
|
|
610
|
-
const
|
|
629
|
+
const toolSupportValidation = await (0, import_operation_span.recordOperationSpan)(
|
|
630
|
+
{
|
|
631
|
+
name: "llm.tool_support_validation",
|
|
632
|
+
componentName: "TurnExecutor",
|
|
633
|
+
attributes: {
|
|
634
|
+
"llm.model": this.llmContext.model,
|
|
635
|
+
"llm.provider": this.llmContext.provider,
|
|
636
|
+
"llm.base_url_present": this.config.baseURL !== void 0
|
|
637
|
+
},
|
|
638
|
+
resultAttributes: toolSupportValidationAttributes
|
|
639
|
+
},
|
|
640
|
+
() => this.validateToolSupport(),
|
|
641
|
+
this.logger
|
|
642
|
+
);
|
|
643
|
+
const supportsTools = toolSupportValidation.supported;
|
|
611
644
|
if (!supportsTools) {
|
|
612
645
|
const modelKey = `${this.llmContext.provider}:${this.llmContext.model}`;
|
|
613
646
|
this.eventBus.emit("llm:unsupported-input", {
|
|
@@ -758,14 +791,16 @@ class TurnExecutor {
|
|
|
758
791
|
result.finishReason
|
|
759
792
|
);
|
|
760
793
|
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
794
|
+
if (this.config.executionControl?.followUpQueueMode !== "host-run") {
|
|
795
|
+
await this.followUpQueue.refresh();
|
|
796
|
+
if (this.followUpQueue.hasPending()) {
|
|
797
|
+
return this.continueWithQueuedInput(
|
|
798
|
+
"follow-up",
|
|
799
|
+
this.followUpQueue,
|
|
800
|
+
stepCount,
|
|
801
|
+
result.finishReason
|
|
802
|
+
);
|
|
803
|
+
}
|
|
769
804
|
}
|
|
770
805
|
this.logger.debug(`Terminating: finishReason is "${result.finishReason}"`);
|
|
771
806
|
return {
|
|
@@ -808,14 +843,33 @@ class TurnExecutor {
|
|
|
808
843
|
async validateToolSupport() {
|
|
809
844
|
const modelKey = `${this.llmContext.provider}:${this.llmContext.model}:${this.config.baseURL ?? ""}`;
|
|
810
845
|
if (toolSupportCache.has(modelKey)) {
|
|
811
|
-
return
|
|
846
|
+
return {
|
|
847
|
+
supported: toolSupportCache.get(modelKey),
|
|
848
|
+
cacheHit: true,
|
|
849
|
+
validationMode: "cache"
|
|
850
|
+
};
|
|
812
851
|
}
|
|
813
852
|
if ((0, import_codex_base_url.isCodexBaseURL)(this.config.baseURL)) {
|
|
814
853
|
this.logger.debug(
|
|
815
854
|
`Skipping tool validation for ${modelKey} - Codex app-server integration manages tool support internally`
|
|
816
855
|
);
|
|
817
856
|
toolSupportCache.set(modelKey, true);
|
|
818
|
-
return
|
|
857
|
+
return {
|
|
858
|
+
supported: true,
|
|
859
|
+
cacheHit: false,
|
|
860
|
+
validationMode: "codex_base_url_skip"
|
|
861
|
+
};
|
|
862
|
+
}
|
|
863
|
+
if (isManagedGatewayProvider(this.llmContext.provider)) {
|
|
864
|
+
this.logger.debug(
|
|
865
|
+
`Skipping tool validation for ${modelKey} - managed gateway provider controls tool support`
|
|
866
|
+
);
|
|
867
|
+
toolSupportCache.set(modelKey, true);
|
|
868
|
+
return {
|
|
869
|
+
supported: true,
|
|
870
|
+
cacheHit: false,
|
|
871
|
+
validationMode: "managed_gateway_assumed"
|
|
872
|
+
};
|
|
819
873
|
}
|
|
820
874
|
const isLocalProvider = LOCAL_PROVIDERS.includes(this.llmContext.provider);
|
|
821
875
|
if (!this.config.baseURL && !isLocalProvider) {
|
|
@@ -823,7 +877,11 @@ class TurnExecutor {
|
|
|
823
877
|
`Skipping tool validation for ${modelKey} - known cloud provider without custom baseURL`
|
|
824
878
|
);
|
|
825
879
|
toolSupportCache.set(modelKey, true);
|
|
826
|
-
return
|
|
880
|
+
return {
|
|
881
|
+
supported: true,
|
|
882
|
+
cacheHit: false,
|
|
883
|
+
validationMode: "cloud_provider_assumed"
|
|
884
|
+
};
|
|
827
885
|
}
|
|
828
886
|
this.logger.debug(
|
|
829
887
|
`Testing tool support for ${isLocalProvider ? "local provider" : "custom endpoint"} model: ${modelKey}`
|
|
@@ -839,7 +897,7 @@ class TurnExecutor {
|
|
|
839
897
|
}
|
|
840
898
|
};
|
|
841
899
|
const testAbort = new AbortController();
|
|
842
|
-
const testTimeout = setTimeout(() => testAbort.abort(),
|
|
900
|
+
const testTimeout = setTimeout(() => testAbort.abort(), TOOL_SUPPORT_PROBE_TIMEOUT_MS);
|
|
843
901
|
try {
|
|
844
902
|
await (0, import_ai.generateText)({
|
|
845
903
|
model: this.model,
|
|
@@ -851,7 +909,13 @@ class TurnExecutor {
|
|
|
851
909
|
clearTimeout(testTimeout);
|
|
852
910
|
toolSupportCache.set(modelKey, true);
|
|
853
911
|
this.logger.debug(`Model ${modelKey} supports tools`);
|
|
854
|
-
return
|
|
912
|
+
return {
|
|
913
|
+
supported: true,
|
|
914
|
+
cacheHit: false,
|
|
915
|
+
validationMode: "probe",
|
|
916
|
+
probeOutcome: "supported",
|
|
917
|
+
probeTimeoutMs: TOOL_SUPPORT_PROBE_TIMEOUT_MS
|
|
918
|
+
};
|
|
855
919
|
} catch (error) {
|
|
856
920
|
clearTimeout(testTimeout);
|
|
857
921
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -860,13 +924,25 @@ class TurnExecutor {
|
|
|
860
924
|
this.logger.debug(
|
|
861
925
|
`Detected that model ${modelKey} does not support tool calling - tool functionality will be disabled`
|
|
862
926
|
);
|
|
863
|
-
return
|
|
927
|
+
return {
|
|
928
|
+
supported: false,
|
|
929
|
+
cacheHit: false,
|
|
930
|
+
validationMode: "probe",
|
|
931
|
+
probeOutcome: "unsupported",
|
|
932
|
+
probeTimeoutMs: TOOL_SUPPORT_PROBE_TIMEOUT_MS
|
|
933
|
+
};
|
|
864
934
|
}
|
|
865
935
|
this.logger.debug(
|
|
866
936
|
`Tool validation error for ${modelKey}, assuming supported: ${errorMessage}`
|
|
867
937
|
);
|
|
868
938
|
toolSupportCache.set(modelKey, true);
|
|
869
|
-
return
|
|
939
|
+
return {
|
|
940
|
+
supported: true,
|
|
941
|
+
cacheHit: false,
|
|
942
|
+
validationMode: "probe",
|
|
943
|
+
probeOutcome: "error_assumed_supported",
|
|
944
|
+
probeTimeoutMs: TOOL_SUPPORT_PROBE_TIMEOUT_MS
|
|
945
|
+
};
|
|
870
946
|
}
|
|
871
947
|
}
|
|
872
948
|
async prepareNextModelRequest(input) {
|
|
@@ -1331,11 +1407,7 @@ class TurnExecutor {
|
|
|
1331
1407
|
return approval.modelVisibleResult;
|
|
1332
1408
|
}
|
|
1333
1409
|
const decision = this.toApprovalDecisionInput(approval.response);
|
|
1334
|
-
const applied = await this.toolManager.applyApprovalDecision(
|
|
1335
|
-
recorded,
|
|
1336
|
-
decision,
|
|
1337
|
-
this.runContext
|
|
1338
|
-
);
|
|
1410
|
+
const applied = await this.toolManager.applyApprovalDecision(recorded, decision);
|
|
1339
1411
|
if (applied.kind === "terminal") {
|
|
1340
1412
|
return applied.modelVisibleResult;
|
|
1341
1413
|
}
|
|
@@ -1657,11 +1729,6 @@ class TurnExecutor {
|
|
|
1657
1729
|
if (!this.stepAbortController.signal.aborted) {
|
|
1658
1730
|
this.stepAbortController.abort();
|
|
1659
1731
|
}
|
|
1660
|
-
void this.steerQueue.clear().catch((error) => {
|
|
1661
|
-
this.logger.warn(
|
|
1662
|
-
`Failed to clear queued steer messages during cleanup: ${error instanceof Error ? error.message : String(error)}`
|
|
1663
|
-
);
|
|
1664
|
-
});
|
|
1665
1732
|
}
|
|
1666
1733
|
/**
|
|
1667
1734
|
* Check if context should be compacted based on estimated token count.
|
|
@@ -14,6 +14,7 @@ import type { MessageQueueService } from '../../session/message-queue.js';
|
|
|
14
14
|
import type { CompactionStrategy } from '../../context/compaction/types.js';
|
|
15
15
|
import type { ModelLimits } from '../../context/compaction/overflow.js';
|
|
16
16
|
import type { AgentRunContext } from '../../runtime/run-context.js';
|
|
17
|
+
import type { LLMExecutionControl } from '../services/types.js';
|
|
17
18
|
export declare const ModelStepResultStateSchema: z.ZodObject<{
|
|
18
19
|
text: z.ZodString;
|
|
19
20
|
finishReason: z.ZodEnum<{
|
|
@@ -274,6 +275,7 @@ export declare class TurnExecutor {
|
|
|
274
275
|
temperature?: number | undefined;
|
|
275
276
|
baseURL?: string | undefined;
|
|
276
277
|
usageScopeId?: string | undefined;
|
|
278
|
+
executionControl?: LLMExecutionControl | undefined;
|
|
277
279
|
reasoning?: LLMReasoningConfig | undefined;
|
|
278
280
|
}, llmContext: LLMContext, logger: Logger, steerQueue: MessageQueueService, followUpQueue: MessageQueueService, modelLimits?: ModelLimits | undefined, externalSignal?: AbortSignal | undefined, compactionStrategy?: CompactionStrategy | null, runContext?: AgentRunContext | undefined);
|
|
279
281
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turn-executor.d.ts","sourceRoot":"","sources":["../../../src/llm/executor/turn-executor.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,aAAa,EAMb,KAAK,YAAY,EAEpB,MAAM,IAAI,CAAC;AACZ,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAa,uBAAuB,EAAE,MAAM,kBAAkB,CAAC;AAE3E,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAS1D,OAAO,EACH,WAAW,EAId,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAMpD,OAAO,KAAK,EAAE,cAAc,EAAiB,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAEvF,OAAO,KAAK,EACR,UAAU,EACV,kBAAkB,EAClB,UAAU,EAGb,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAIxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAQ1E,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sCAAsC,CAAC;AAExE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"turn-executor.d.ts","sourceRoot":"","sources":["../../../src/llm/executor/turn-executor.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,6 +28,7 @@ import {
|
|
|
28
28
|
} from "../../context/content-audit.js";
|
|
29
29
|
const MCP_TOOL_PREFIX = "mcp--";
|
|
30
30
|
const MODEL_REQUEST_MAX_RETRIES = 2;
|
|
31
|
+
const TOOL_SUPPORT_PROBE_TIMEOUT_MS = 5e3;
|
|
31
32
|
const LLMFinishReasonStateSchema = z.enum([
|
|
32
33
|
"stop",
|
|
33
34
|
"tool-calls",
|
|
@@ -159,6 +160,24 @@ function toModelStepRequestState(request) {
|
|
|
159
160
|
}
|
|
160
161
|
const toolSupportCache = /* @__PURE__ */ new Map();
|
|
161
162
|
const LOCAL_PROVIDERS = ["ollama", "local"];
|
|
163
|
+
function isManagedGatewayProvider(provider) {
|
|
164
|
+
return provider === "dexto-nova";
|
|
165
|
+
}
|
|
166
|
+
function toolSupportValidationAttributes(result) {
|
|
167
|
+
const attributes = {
|
|
168
|
+
"llm.tool_support.cache_hit": result.cacheHit,
|
|
169
|
+
"llm.tool_support.validation_mode": result.validationMode,
|
|
170
|
+
"llm.tools_supported": result.supported
|
|
171
|
+
};
|
|
172
|
+
if (result.validationMode !== "probe") {
|
|
173
|
+
return attributes;
|
|
174
|
+
}
|
|
175
|
+
return {
|
|
176
|
+
...attributes,
|
|
177
|
+
"llm.tool_support.probe_outcome": result.probeOutcome,
|
|
178
|
+
"llm.tool_support.probe_timeout_ms": result.probeTimeoutMs
|
|
179
|
+
};
|
|
180
|
+
}
|
|
162
181
|
class TurnExecutor {
|
|
163
182
|
constructor(model, toolManager, contextManager, eventBus, resourceManager, sessionId, config, llmContext, logger, steerQueue, followUpQueue, modelLimits, externalSignal, compactionStrategy = null, runContext) {
|
|
164
183
|
this.model = model;
|
|
@@ -584,7 +603,21 @@ class TurnExecutor {
|
|
|
584
603
|
}
|
|
585
604
|
async startTurn() {
|
|
586
605
|
this.eventBus.emit("llm:thinking", {});
|
|
587
|
-
const
|
|
606
|
+
const toolSupportValidation = await recordOperationSpan(
|
|
607
|
+
{
|
|
608
|
+
name: "llm.tool_support_validation",
|
|
609
|
+
componentName: "TurnExecutor",
|
|
610
|
+
attributes: {
|
|
611
|
+
"llm.model": this.llmContext.model,
|
|
612
|
+
"llm.provider": this.llmContext.provider,
|
|
613
|
+
"llm.base_url_present": this.config.baseURL !== void 0
|
|
614
|
+
},
|
|
615
|
+
resultAttributes: toolSupportValidationAttributes
|
|
616
|
+
},
|
|
617
|
+
() => this.validateToolSupport(),
|
|
618
|
+
this.logger
|
|
619
|
+
);
|
|
620
|
+
const supportsTools = toolSupportValidation.supported;
|
|
588
621
|
if (!supportsTools) {
|
|
589
622
|
const modelKey = `${this.llmContext.provider}:${this.llmContext.model}`;
|
|
590
623
|
this.eventBus.emit("llm:unsupported-input", {
|
|
@@ -735,14 +768,16 @@ class TurnExecutor {
|
|
|
735
768
|
result.finishReason
|
|
736
769
|
);
|
|
737
770
|
}
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
771
|
+
if (this.config.executionControl?.followUpQueueMode !== "host-run") {
|
|
772
|
+
await this.followUpQueue.refresh();
|
|
773
|
+
if (this.followUpQueue.hasPending()) {
|
|
774
|
+
return this.continueWithQueuedInput(
|
|
775
|
+
"follow-up",
|
|
776
|
+
this.followUpQueue,
|
|
777
|
+
stepCount,
|
|
778
|
+
result.finishReason
|
|
779
|
+
);
|
|
780
|
+
}
|
|
746
781
|
}
|
|
747
782
|
this.logger.debug(`Terminating: finishReason is "${result.finishReason}"`);
|
|
748
783
|
return {
|
|
@@ -785,14 +820,33 @@ class TurnExecutor {
|
|
|
785
820
|
async validateToolSupport() {
|
|
786
821
|
const modelKey = `${this.llmContext.provider}:${this.llmContext.model}:${this.config.baseURL ?? ""}`;
|
|
787
822
|
if (toolSupportCache.has(modelKey)) {
|
|
788
|
-
return
|
|
823
|
+
return {
|
|
824
|
+
supported: toolSupportCache.get(modelKey),
|
|
825
|
+
cacheHit: true,
|
|
826
|
+
validationMode: "cache"
|
|
827
|
+
};
|
|
789
828
|
}
|
|
790
829
|
if (isCodexBaseURL(this.config.baseURL)) {
|
|
791
830
|
this.logger.debug(
|
|
792
831
|
`Skipping tool validation for ${modelKey} - Codex app-server integration manages tool support internally`
|
|
793
832
|
);
|
|
794
833
|
toolSupportCache.set(modelKey, true);
|
|
795
|
-
return
|
|
834
|
+
return {
|
|
835
|
+
supported: true,
|
|
836
|
+
cacheHit: false,
|
|
837
|
+
validationMode: "codex_base_url_skip"
|
|
838
|
+
};
|
|
839
|
+
}
|
|
840
|
+
if (isManagedGatewayProvider(this.llmContext.provider)) {
|
|
841
|
+
this.logger.debug(
|
|
842
|
+
`Skipping tool validation for ${modelKey} - managed gateway provider controls tool support`
|
|
843
|
+
);
|
|
844
|
+
toolSupportCache.set(modelKey, true);
|
|
845
|
+
return {
|
|
846
|
+
supported: true,
|
|
847
|
+
cacheHit: false,
|
|
848
|
+
validationMode: "managed_gateway_assumed"
|
|
849
|
+
};
|
|
796
850
|
}
|
|
797
851
|
const isLocalProvider = LOCAL_PROVIDERS.includes(this.llmContext.provider);
|
|
798
852
|
if (!this.config.baseURL && !isLocalProvider) {
|
|
@@ -800,7 +854,11 @@ class TurnExecutor {
|
|
|
800
854
|
`Skipping tool validation for ${modelKey} - known cloud provider without custom baseURL`
|
|
801
855
|
);
|
|
802
856
|
toolSupportCache.set(modelKey, true);
|
|
803
|
-
return
|
|
857
|
+
return {
|
|
858
|
+
supported: true,
|
|
859
|
+
cacheHit: false,
|
|
860
|
+
validationMode: "cloud_provider_assumed"
|
|
861
|
+
};
|
|
804
862
|
}
|
|
805
863
|
this.logger.debug(
|
|
806
864
|
`Testing tool support for ${isLocalProvider ? "local provider" : "custom endpoint"} model: ${modelKey}`
|
|
@@ -816,7 +874,7 @@ class TurnExecutor {
|
|
|
816
874
|
}
|
|
817
875
|
};
|
|
818
876
|
const testAbort = new AbortController();
|
|
819
|
-
const testTimeout = setTimeout(() => testAbort.abort(),
|
|
877
|
+
const testTimeout = setTimeout(() => testAbort.abort(), TOOL_SUPPORT_PROBE_TIMEOUT_MS);
|
|
820
878
|
try {
|
|
821
879
|
await generateText({
|
|
822
880
|
model: this.model,
|
|
@@ -828,7 +886,13 @@ class TurnExecutor {
|
|
|
828
886
|
clearTimeout(testTimeout);
|
|
829
887
|
toolSupportCache.set(modelKey, true);
|
|
830
888
|
this.logger.debug(`Model ${modelKey} supports tools`);
|
|
831
|
-
return
|
|
889
|
+
return {
|
|
890
|
+
supported: true,
|
|
891
|
+
cacheHit: false,
|
|
892
|
+
validationMode: "probe",
|
|
893
|
+
probeOutcome: "supported",
|
|
894
|
+
probeTimeoutMs: TOOL_SUPPORT_PROBE_TIMEOUT_MS
|
|
895
|
+
};
|
|
832
896
|
} catch (error) {
|
|
833
897
|
clearTimeout(testTimeout);
|
|
834
898
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -837,13 +901,25 @@ class TurnExecutor {
|
|
|
837
901
|
this.logger.debug(
|
|
838
902
|
`Detected that model ${modelKey} does not support tool calling - tool functionality will be disabled`
|
|
839
903
|
);
|
|
840
|
-
return
|
|
904
|
+
return {
|
|
905
|
+
supported: false,
|
|
906
|
+
cacheHit: false,
|
|
907
|
+
validationMode: "probe",
|
|
908
|
+
probeOutcome: "unsupported",
|
|
909
|
+
probeTimeoutMs: TOOL_SUPPORT_PROBE_TIMEOUT_MS
|
|
910
|
+
};
|
|
841
911
|
}
|
|
842
912
|
this.logger.debug(
|
|
843
913
|
`Tool validation error for ${modelKey}, assuming supported: ${errorMessage}`
|
|
844
914
|
);
|
|
845
915
|
toolSupportCache.set(modelKey, true);
|
|
846
|
-
return
|
|
916
|
+
return {
|
|
917
|
+
supported: true,
|
|
918
|
+
cacheHit: false,
|
|
919
|
+
validationMode: "probe",
|
|
920
|
+
probeOutcome: "error_assumed_supported",
|
|
921
|
+
probeTimeoutMs: TOOL_SUPPORT_PROBE_TIMEOUT_MS
|
|
922
|
+
};
|
|
847
923
|
}
|
|
848
924
|
}
|
|
849
925
|
async prepareNextModelRequest(input) {
|
|
@@ -1308,11 +1384,7 @@ class TurnExecutor {
|
|
|
1308
1384
|
return approval.modelVisibleResult;
|
|
1309
1385
|
}
|
|
1310
1386
|
const decision = this.toApprovalDecisionInput(approval.response);
|
|
1311
|
-
const applied = await this.toolManager.applyApprovalDecision(
|
|
1312
|
-
recorded,
|
|
1313
|
-
decision,
|
|
1314
|
-
this.runContext
|
|
1315
|
-
);
|
|
1387
|
+
const applied = await this.toolManager.applyApprovalDecision(recorded, decision);
|
|
1316
1388
|
if (applied.kind === "terminal") {
|
|
1317
1389
|
return applied.modelVisibleResult;
|
|
1318
1390
|
}
|
|
@@ -1634,11 +1706,6 @@ class TurnExecutor {
|
|
|
1634
1706
|
if (!this.stepAbortController.signal.aborted) {
|
|
1635
1707
|
this.stepAbortController.abort();
|
|
1636
1708
|
}
|
|
1637
|
-
void this.steerQueue.clear().catch((error) => {
|
|
1638
|
-
this.logger.warn(
|
|
1639
|
-
`Failed to clear queued steer messages during cleanup: ${error instanceof Error ? error.message : String(error)}`
|
|
1640
|
-
);
|
|
1641
|
-
});
|
|
1642
1709
|
}
|
|
1643
1710
|
/**
|
|
1644
1711
|
* Check if context should be compacted based on estimated token count.
|
|
@@ -41,6 +41,70 @@ function normalizeToolMediaData(data) {
|
|
|
41
41
|
}
|
|
42
42
|
return data;
|
|
43
43
|
}
|
|
44
|
+
function isTextLikeMimeType(mimeType) {
|
|
45
|
+
const normalized = mimeType.toLowerCase().split(";", 1)[0]?.trim() ?? "";
|
|
46
|
+
if (normalized.startsWith("text/")) return true;
|
|
47
|
+
if (normalized.endsWith("+json") || normalized.endsWith("+xml")) return true;
|
|
48
|
+
return [
|
|
49
|
+
"application/json",
|
|
50
|
+
"application/ld+json",
|
|
51
|
+
"application/xml",
|
|
52
|
+
"application/yaml",
|
|
53
|
+
"application/x-yaml",
|
|
54
|
+
"application/toml",
|
|
55
|
+
"application/x-toml",
|
|
56
|
+
"application/javascript",
|
|
57
|
+
"application/typescript",
|
|
58
|
+
"application/x-sh",
|
|
59
|
+
"application/sql"
|
|
60
|
+
].includes(normalized);
|
|
61
|
+
}
|
|
62
|
+
function isRemoteFileData(data) {
|
|
63
|
+
return data instanceof URL || typeof data === "string" && (/^https?:\/\//i.test(data) || data.startsWith("blob:") || data.startsWith("@blob:"));
|
|
64
|
+
}
|
|
65
|
+
function decodeLikelyBase64Text(value) {
|
|
66
|
+
const normalized = value.replace(/\s/g, "");
|
|
67
|
+
if (normalized.length === 0 || normalized.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(normalized)) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
const decoded = Buffer.from(normalized, "base64");
|
|
71
|
+
const canonical = decoded.toString("base64").replace(/=+$/, "");
|
|
72
|
+
if (canonical !== normalized.replace(/=+$/, "")) return null;
|
|
73
|
+
const text = decoded.toString("utf8");
|
|
74
|
+
const hasInvalidControlCharacter = [...text].some((char) => {
|
|
75
|
+
const code = char.charCodeAt(0);
|
|
76
|
+
return code < 32 && code !== 9 && code !== 10 && code !== 13;
|
|
77
|
+
});
|
|
78
|
+
if (text.includes("\uFFFD") || hasInvalidControlCharacter) {
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
return text;
|
|
82
|
+
}
|
|
83
|
+
function decodeBase64Text(value) {
|
|
84
|
+
return Buffer.from(value.replace(/\s/g, ""), "base64").toString("utf8");
|
|
85
|
+
}
|
|
86
|
+
function decodeTextFileData(data) {
|
|
87
|
+
if (data instanceof URL) return null;
|
|
88
|
+
if (typeof data === "string") {
|
|
89
|
+
const dataUri = (0, import_utils.parseDataUri)(data);
|
|
90
|
+
if (dataUri) return decodeBase64Text(dataUri.base64);
|
|
91
|
+
if (isRemoteFileData(data)) return null;
|
|
92
|
+
return decodeLikelyBase64Text(data) ?? data;
|
|
93
|
+
}
|
|
94
|
+
return Buffer.from(data instanceof ArrayBuffer ? new Uint8Array(data) : data).toString("utf8");
|
|
95
|
+
}
|
|
96
|
+
function filePartToText(part) {
|
|
97
|
+
if (!isTextLikeMimeType(part.mimeType) || isRemoteFileData(part.data)) return null;
|
|
98
|
+
const text = decodeTextFileData(part.data);
|
|
99
|
+
if (text === null) return null;
|
|
100
|
+
const filename = part.filename ?? "attachment";
|
|
101
|
+
return {
|
|
102
|
+
type: "text",
|
|
103
|
+
text: `Attached file "${filename}" (${part.mimeType}):
|
|
104
|
+
|
|
105
|
+
${text}`
|
|
106
|
+
};
|
|
107
|
+
}
|
|
44
108
|
class VercelMessageFormatter {
|
|
45
109
|
logger;
|
|
46
110
|
constructor(logger) {
|
|
@@ -89,6 +153,8 @@ class VercelMessageFormatter {
|
|
|
89
153
|
(part) => part.type !== "ui-resource" && part.type !== "resource"
|
|
90
154
|
).map((part) => {
|
|
91
155
|
if (part.type === "file") {
|
|
156
|
+
const textPart = filePartToText(part);
|
|
157
|
+
if (textPart) return textPart;
|
|
92
158
|
return {
|
|
93
159
|
type: "file",
|
|
94
160
|
data: toUrlIfString(part.data),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vercel.d.ts","sourceRoot":"","sources":["../../../src/llm/formatters/vercel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAiD,MAAM,IAAI,CAAC;AACtF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"vercel.d.ts","sourceRoot":"","sources":["../../../src/llm/formatters/vercel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAiD,MAAM,IAAI,CAAC;AACtF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EACR,eAAe,EAIlB,MAAM,wBAAwB,CAAC;AAOhC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAqHvD;;;;;;;;;;GAUG;AACH,qBAAa,sBAAsB;IAC/B,OAAO,CAAC,MAAM,CAAS;gBAEX,MAAM,EAAE,MAAM;IAG1B;;;;;;OAMG;IACH,MAAM,CACF,OAAO,EAAE,QAAQ,CAAC,eAAe,EAAE,CAAC,EACpC,OAAO,EAAE,UAAU,EACnB,YAAY,EAAE,MAAM,GAAG,IAAI,GAC5B,YAAY,EAAE;IAqKjB;;;;;;OAMG;IACH,kBAAkB,IAAI,IAAI;IAI1B,OAAO,CAAC,wBAAwB;IAUhC,OAAO,CAAC,sBAAsB;IAmG9B,OAAO,CAAC,iBAAiB;CA6E5B"}
|
|
@@ -24,6 +24,70 @@ function normalizeToolMediaData(data) {
|
|
|
24
24
|
}
|
|
25
25
|
return data;
|
|
26
26
|
}
|
|
27
|
+
function isTextLikeMimeType(mimeType) {
|
|
28
|
+
const normalized = mimeType.toLowerCase().split(";", 1)[0]?.trim() ?? "";
|
|
29
|
+
if (normalized.startsWith("text/")) return true;
|
|
30
|
+
if (normalized.endsWith("+json") || normalized.endsWith("+xml")) return true;
|
|
31
|
+
return [
|
|
32
|
+
"application/json",
|
|
33
|
+
"application/ld+json",
|
|
34
|
+
"application/xml",
|
|
35
|
+
"application/yaml",
|
|
36
|
+
"application/x-yaml",
|
|
37
|
+
"application/toml",
|
|
38
|
+
"application/x-toml",
|
|
39
|
+
"application/javascript",
|
|
40
|
+
"application/typescript",
|
|
41
|
+
"application/x-sh",
|
|
42
|
+
"application/sql"
|
|
43
|
+
].includes(normalized);
|
|
44
|
+
}
|
|
45
|
+
function isRemoteFileData(data) {
|
|
46
|
+
return data instanceof URL || typeof data === "string" && (/^https?:\/\//i.test(data) || data.startsWith("blob:") || data.startsWith("@blob:"));
|
|
47
|
+
}
|
|
48
|
+
function decodeLikelyBase64Text(value) {
|
|
49
|
+
const normalized = value.replace(/\s/g, "");
|
|
50
|
+
if (normalized.length === 0 || normalized.length % 4 !== 0 || !/^[A-Za-z0-9+/]+={0,2}$/.test(normalized)) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
const decoded = Buffer.from(normalized, "base64");
|
|
54
|
+
const canonical = decoded.toString("base64").replace(/=+$/, "");
|
|
55
|
+
if (canonical !== normalized.replace(/=+$/, "")) return null;
|
|
56
|
+
const text = decoded.toString("utf8");
|
|
57
|
+
const hasInvalidControlCharacter = [...text].some((char) => {
|
|
58
|
+
const code = char.charCodeAt(0);
|
|
59
|
+
return code < 32 && code !== 9 && code !== 10 && code !== 13;
|
|
60
|
+
});
|
|
61
|
+
if (text.includes("\uFFFD") || hasInvalidControlCharacter) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
return text;
|
|
65
|
+
}
|
|
66
|
+
function decodeBase64Text(value) {
|
|
67
|
+
return Buffer.from(value.replace(/\s/g, ""), "base64").toString("utf8");
|
|
68
|
+
}
|
|
69
|
+
function decodeTextFileData(data) {
|
|
70
|
+
if (data instanceof URL) return null;
|
|
71
|
+
if (typeof data === "string") {
|
|
72
|
+
const dataUri = parseDataUri(data);
|
|
73
|
+
if (dataUri) return decodeBase64Text(dataUri.base64);
|
|
74
|
+
if (isRemoteFileData(data)) return null;
|
|
75
|
+
return decodeLikelyBase64Text(data) ?? data;
|
|
76
|
+
}
|
|
77
|
+
return Buffer.from(data instanceof ArrayBuffer ? new Uint8Array(data) : data).toString("utf8");
|
|
78
|
+
}
|
|
79
|
+
function filePartToText(part) {
|
|
80
|
+
if (!isTextLikeMimeType(part.mimeType) || isRemoteFileData(part.data)) return null;
|
|
81
|
+
const text = decodeTextFileData(part.data);
|
|
82
|
+
if (text === null) return null;
|
|
83
|
+
const filename = part.filename ?? "attachment";
|
|
84
|
+
return {
|
|
85
|
+
type: "text",
|
|
86
|
+
text: `Attached file "${filename}" (${part.mimeType}):
|
|
87
|
+
|
|
88
|
+
${text}`
|
|
89
|
+
};
|
|
90
|
+
}
|
|
27
91
|
class VercelMessageFormatter {
|
|
28
92
|
logger;
|
|
29
93
|
constructor(logger) {
|
|
@@ -72,6 +136,8 @@ class VercelMessageFormatter {
|
|
|
72
136
|
(part) => part.type !== "ui-resource" && part.type !== "resource"
|
|
73
137
|
).map((part) => {
|
|
74
138
|
if (part.type === "file") {
|
|
139
|
+
const textPart = filePartToText(part);
|
|
140
|
+
if (textPart) return textPart;
|
|
75
141
|
return {
|
|
76
142
|
type: "file",
|
|
77
143
|
data: toUrlIfString(part.data),
|
|
@@ -46,7 +46,7 @@ function isLanguageModel(value) {
|
|
|
46
46
|
const candidate = value;
|
|
47
47
|
return typeof candidate["modelId"] === "string" && (typeof candidate["doGenerate"] === "function" || typeof candidate["doStream"] === "function");
|
|
48
48
|
}
|
|
49
|
-
const DEFAULT_DEXTO_GATEWAY_BASE_URL = "https://
|
|
49
|
+
const DEFAULT_DEXTO_GATEWAY_BASE_URL = "https://app.dexto.ai/v1";
|
|
50
50
|
function trimTrailingSlash(value) {
|
|
51
51
|
return value.trim().replace(/\/$/, "");
|
|
52
52
|
}
|
|
@@ -327,7 +327,7 @@ function createVercelModel(llmConfig, context) {
|
|
|
327
327
|
}
|
|
328
328
|
}
|
|
329
329
|
function createLLMService(config, toolManager, systemPromptManager, conversationStore, sessionEventBus, sessionId, resourceManager, logger, options, languageModelFactory) {
|
|
330
|
-
const { usageScopeId, compactionStrategy, steerQueue, followUpQueue } = options;
|
|
330
|
+
const { usageScopeId, compactionStrategy, executionControl, steerQueue, followUpQueue } = options;
|
|
331
331
|
const providerContext = {
|
|
332
332
|
sessionId,
|
|
333
333
|
...options.cwd !== void 0 ? { cwd: options.cwd } : {},
|
|
@@ -359,6 +359,7 @@ function createLLMService(config, toolManager, systemPromptManager, conversation
|
|
|
359
359
|
steerQueue,
|
|
360
360
|
followUpQueue,
|
|
361
361
|
usageScopeId,
|
|
362
|
+
executionControl,
|
|
362
363
|
compactionStrategy
|
|
363
364
|
);
|
|
364
365
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/llm/services/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAYnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,KAAK,EACR,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,EACvB,MAAM,YAAY,CAAC;AAqHpB;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC7B,SAAS,EAAE,kBAAkB,EAC7B,OAAO,CAAC,EAAE,oBAAoB,GAC/B,aAAa,CAsSf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC5B,MAAM,EAAE,kBAAkB,EAC1B,WAAW,EAAE,WAAW,EACxB,mBAAmB,EAAE,mBAAmB,EACxC,iBAAiB,EAAE,iBAAiB,EACpC,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,OAAO,0BAA0B,EAAE,eAAe,EACnE,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,uBAAuB,EAChC,oBAAoB,CAAC,EAAE,oBAAoB,GAC5C,gBAAgB,
|
|
1
|
+
{"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../../src/llm/services/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAYnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,+BAA+B,CAAC;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,KAAK,EACR,uBAAuB,EACvB,oBAAoB,EACpB,oBAAoB,EACvB,MAAM,YAAY,CAAC;AAqHpB;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC7B,SAAS,EAAE,kBAAkB,EAC7B,OAAO,CAAC,EAAE,oBAAoB,GAC/B,aAAa,CAsSf;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC5B,MAAM,EAAE,kBAAkB,EAC1B,WAAW,EAAE,WAAW,EACxB,mBAAmB,EAAE,mBAAmB,EACxC,iBAAiB,EAAE,iBAAiB,EACpC,eAAe,EAAE,eAAe,EAChC,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,OAAO,0BAA0B,EAAE,eAAe,EACnE,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,uBAAuB,EAChC,oBAAoB,CAAC,EAAE,oBAAoB,GAC5C,gBAAgB,CAyClB"}
|
|
@@ -28,7 +28,7 @@ function isLanguageModel(value) {
|
|
|
28
28
|
const candidate = value;
|
|
29
29
|
return typeof candidate["modelId"] === "string" && (typeof candidate["doGenerate"] === "function" || typeof candidate["doStream"] === "function");
|
|
30
30
|
}
|
|
31
|
-
const DEFAULT_DEXTO_GATEWAY_BASE_URL = "https://
|
|
31
|
+
const DEFAULT_DEXTO_GATEWAY_BASE_URL = "https://app.dexto.ai/v1";
|
|
32
32
|
function trimTrailingSlash(value) {
|
|
33
33
|
return value.trim().replace(/\/$/, "");
|
|
34
34
|
}
|
|
@@ -309,7 +309,7 @@ function createVercelModel(llmConfig, context) {
|
|
|
309
309
|
}
|
|
310
310
|
}
|
|
311
311
|
function createLLMService(config, toolManager, systemPromptManager, conversationStore, sessionEventBus, sessionId, resourceManager, logger, options, languageModelFactory) {
|
|
312
|
-
const { usageScopeId, compactionStrategy, steerQueue, followUpQueue } = options;
|
|
312
|
+
const { usageScopeId, compactionStrategy, executionControl, steerQueue, followUpQueue } = options;
|
|
313
313
|
const providerContext = {
|
|
314
314
|
sessionId,
|
|
315
315
|
...options.cwd !== void 0 ? { cwd: options.cwd } : {},
|
|
@@ -341,6 +341,7 @@ function createLLMService(config, toolManager, systemPromptManager, conversation
|
|
|
341
341
|
steerQueue,
|
|
342
342
|
followUpQueue,
|
|
343
343
|
usageScopeId,
|
|
344
|
+
executionControl,
|
|
344
345
|
compactionStrategy
|
|
345
346
|
);
|
|
346
347
|
}
|