@dexto/core 1.8.3 → 1.8.4
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/agent/DextoAgent.cjs +3 -1
- package/dist/agent/DextoAgent.d.ts +2 -0
- package/dist/agent/DextoAgent.d.ts.map +1 -1
- package/dist/agent/DextoAgent.js +7 -2
- package/dist/events/index.d.ts +3 -0
- package/dist/events/index.d.ts.map +1 -1
- package/dist/index.browser.cjs +6 -0
- package/dist/index.browser.d.ts +2 -0
- package/dist/index.browser.d.ts.map +1 -1
- package/dist/index.browser.js +4 -0
- package/dist/llm/executor/provider-error.cjs +214 -0
- package/dist/llm/executor/provider-error.d.ts +26 -0
- package/dist/llm/executor/provider-error.d.ts.map +1 -0
- package/dist/llm/executor/provider-error.js +190 -0
- package/dist/llm/executor/stream-processor.cjs +34 -5
- package/dist/llm/executor/stream-processor.d.ts +4 -1
- package/dist/llm/executor/stream-processor.d.ts.map +1 -1
- package/dist/llm/executor/stream-processor.js +34 -5
- package/dist/llm/executor/turn-executor.cjs +185 -124
- package/dist/llm/executor/turn-executor.d.ts +5 -5
- package/dist/llm/executor/turn-executor.d.ts.map +1 -1
- package/dist/llm/executor/turn-executor.js +184 -120
- package/dist/session/title-generator.cjs +19 -2
- package/dist/session/title-generator.d.ts +8 -0
- package/dist/session/title-generator.d.ts.map +1 -1
- package/dist/session/title-generator.js +19 -2
- package/dist/systemPrompt/contributors.cjs +10 -1
- package/dist/systemPrompt/contributors.d.ts.map +1 -1
- package/dist/systemPrompt/contributors.js +10 -1
- package/dist/telemetry/browser.cjs +138 -0
- package/dist/telemetry/browser.d.ts +30 -0
- package/dist/telemetry/browser.d.ts.map +1 -0
- package/dist/telemetry/browser.js +115 -0
- package/dist/telemetry/index.cjs +5 -2
- package/dist/telemetry/index.d.ts +1 -0
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/index.js +3 -1
- package/dist/telemetry/operation-span.cjs +73 -0
- package/dist/telemetry/operation-span.d.ts +13 -0
- package/dist/telemetry/operation-span.d.ts.map +1 -0
- package/dist/telemetry/operation-span.js +50 -0
- package/dist/telemetry/telemetry.cjs +2 -3
- package/dist/telemetry/telemetry.d.ts.map +1 -1
- package/dist/telemetry/telemetry.js +2 -3
- package/dist/telemetry/utils.cjs +11 -12
- package/dist/telemetry/utils.d.ts.map +1 -1
- package/dist/telemetry/utils.js +11 -12
- package/dist/tools/tool-call-metadata.cjs +118 -6
- package/dist/tools/tool-call-metadata.d.ts.map +1 -1
- package/dist/tools/tool-call-metadata.js +118 -6
- package/package.json +2 -2
|
@@ -13,9 +13,11 @@ import { StreamProcessor } from "./stream-processor.js";
|
|
|
13
13
|
import { truncateToolResult } from "./tool-output-truncator.js";
|
|
14
14
|
import { buildProviderOptions, getEffectiveReasoningBudgetTokens } from "./provider-options.js";
|
|
15
15
|
import { DextoLogComponent } from "../../logger/v2/types.js";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
|
|
16
|
+
import { recordOperationSpan } from "../../telemetry/operation-span.js";
|
|
17
|
+
import {
|
|
18
|
+
extractProviderErrorDetails,
|
|
19
|
+
mapProviderError as mapCoreProviderError
|
|
20
|
+
} from "./provider-error.js";
|
|
19
21
|
import { toError } from "../../utils/error-conversion.js";
|
|
20
22
|
import { isCodexBaseURL } from "../providers/codex-base-url.js";
|
|
21
23
|
import { createModelToolDefinitions } from "./tool-definitions.js";
|
|
@@ -350,11 +352,19 @@ class TurnExecutor {
|
|
|
350
352
|
this.currentModelStepId = `in-memory-model-step-${stepCount}`;
|
|
351
353
|
modelStepPreparing = true;
|
|
352
354
|
try {
|
|
353
|
-
preparedModelRequest = await
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
355
|
+
preparedModelRequest = await recordOperationSpan(
|
|
356
|
+
{
|
|
357
|
+
name: "turn.prepare_model_step",
|
|
358
|
+
componentName: "TurnExecutor",
|
|
359
|
+
attributes: { "turn.step_count": stepCount }
|
|
360
|
+
},
|
|
361
|
+
() => this.prepareNextModelRequest({
|
|
362
|
+
contributorContext,
|
|
363
|
+
supportsTools: turn.supportsTools,
|
|
364
|
+
streaming: options.streaming
|
|
365
|
+
}),
|
|
366
|
+
this.logger
|
|
367
|
+
);
|
|
358
368
|
} catch (error) {
|
|
359
369
|
currentStepScope[Symbol.dispose]();
|
|
360
370
|
currentStepScope = null;
|
|
@@ -380,11 +390,19 @@ class TurnExecutor {
|
|
|
380
390
|
}
|
|
381
391
|
currentStepScope = this.startModelStepScope();
|
|
382
392
|
this.currentModelStepId = `in-memory-model-step-${stepCount}`;
|
|
383
|
-
preparedModelRequest = await
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
393
|
+
preparedModelRequest = await recordOperationSpan(
|
|
394
|
+
{
|
|
395
|
+
name: "turn.prepare_model_step",
|
|
396
|
+
componentName: "TurnExecutor",
|
|
397
|
+
attributes: { "turn.step_count": stepCount }
|
|
398
|
+
},
|
|
399
|
+
() => this.prepareNextModelRequest({
|
|
400
|
+
contributorContext,
|
|
401
|
+
supportsTools: turn.supportsTools,
|
|
402
|
+
streaming: options.streaming
|
|
403
|
+
}),
|
|
404
|
+
this.logger
|
|
405
|
+
);
|
|
388
406
|
}
|
|
389
407
|
const modelStepRequest = preparedModelRequest;
|
|
390
408
|
if (currentStepScope === null || modelStepRequest === null) {
|
|
@@ -576,7 +594,13 @@ class TurnExecutor {
|
|
|
576
594
|
this.eventBus.emit("llm:error", {
|
|
577
595
|
error: mappedError,
|
|
578
596
|
context: "TurnExecutor",
|
|
579
|
-
recoverable: false
|
|
597
|
+
recoverable: false,
|
|
598
|
+
details: extractProviderErrorDetails({
|
|
599
|
+
error,
|
|
600
|
+
provider: this.llmContext.provider,
|
|
601
|
+
model: this.llmContext.model,
|
|
602
|
+
sessionId: this.sessionId
|
|
603
|
+
})
|
|
580
604
|
});
|
|
581
605
|
await this.contextManager.flush();
|
|
582
606
|
this.eventBus.emit("run:complete", {
|
|
@@ -773,48 +797,159 @@ class TurnExecutor {
|
|
|
773
797
|
await this.injectQueuedMessages(coalesced);
|
|
774
798
|
}
|
|
775
799
|
await this.pruneOldToolOutputs();
|
|
776
|
-
let
|
|
777
|
-
|
|
778
|
-
|
|
800
|
+
let systemPrompt = await recordOperationSpan(
|
|
801
|
+
{
|
|
802
|
+
name: "system_prompt.build",
|
|
803
|
+
componentName: "TurnExecutor",
|
|
804
|
+
attributes: {
|
|
805
|
+
"llm.model": this.llmContext.model,
|
|
806
|
+
"llm.provider": this.llmContext.provider
|
|
807
|
+
}
|
|
808
|
+
},
|
|
809
|
+
() => this.contextManager.getSystemPrompt(input.contributorContext),
|
|
810
|
+
this.logger
|
|
779
811
|
);
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
812
|
+
let { preparedHistory, formattedMessages } = await recordOperationSpan(
|
|
813
|
+
{
|
|
814
|
+
name: "context.build_messages",
|
|
815
|
+
componentName: "TurnExecutor",
|
|
816
|
+
attributes: {
|
|
817
|
+
"llm.model": this.llmContext.model,
|
|
818
|
+
"llm.provider": this.llmContext.provider
|
|
819
|
+
}
|
|
820
|
+
},
|
|
821
|
+
async () => {
|
|
822
|
+
const preparedHistory2 = (await this.contextManager.prepareHistory()).preparedHistory;
|
|
823
|
+
const formattedMessages2 = await this.contextManager.getFormattedMessages(
|
|
824
|
+
input.contributorContext,
|
|
825
|
+
this.llmContext,
|
|
826
|
+
systemPrompt,
|
|
827
|
+
preparedHistory2
|
|
828
|
+
);
|
|
829
|
+
return { preparedHistory: preparedHistory2, formattedMessages: formattedMessages2 };
|
|
830
|
+
},
|
|
831
|
+
this.logger
|
|
832
|
+
);
|
|
833
|
+
const toolDefinitions = input.supportsTools ? await recordOperationSpan(
|
|
834
|
+
{
|
|
835
|
+
name: "tools.list",
|
|
836
|
+
componentName: "TurnExecutor",
|
|
837
|
+
attributes: { "tools.supports": input.supportsTools },
|
|
838
|
+
resultAttributes: (tools) => ({ "tools.count": Object.keys(tools).length })
|
|
839
|
+
},
|
|
840
|
+
async () => this.toolManager.filterToolsForSession(
|
|
841
|
+
await this.toolManager.getAllTools(),
|
|
842
|
+
this.sessionId
|
|
843
|
+
),
|
|
844
|
+
this.logger
|
|
783
845
|
) : {};
|
|
784
|
-
let estimatedInputTokens = await
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
846
|
+
let estimatedInputTokens = await recordOperationSpan(
|
|
847
|
+
{
|
|
848
|
+
name: "context.token_estimate",
|
|
849
|
+
componentName: "TurnExecutor",
|
|
850
|
+
attributes: { "tools.count": Object.keys(toolDefinitions).length },
|
|
851
|
+
resultAttributes: (tokens) => ({ "context.estimated_input_tokens": tokens })
|
|
852
|
+
},
|
|
853
|
+
() => this.contextManager.getEstimatedNextInputTokens(
|
|
854
|
+
systemPrompt,
|
|
855
|
+
preparedHistory,
|
|
856
|
+
toolDefinitions
|
|
857
|
+
),
|
|
858
|
+
this.logger
|
|
788
859
|
);
|
|
789
860
|
if (this.shouldCompact(estimatedInputTokens)) {
|
|
790
861
|
this.logger.debug(
|
|
791
862
|
`Pre-check: estimated ${estimatedInputTokens} tokens exceeds threshold, compacting`
|
|
792
863
|
);
|
|
793
|
-
const didCompact = await
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
864
|
+
const didCompact = await recordOperationSpan(
|
|
865
|
+
{
|
|
866
|
+
name: "context.compact",
|
|
867
|
+
componentName: "TurnExecutor",
|
|
868
|
+
attributes: { "context.estimated_input_tokens": estimatedInputTokens }
|
|
869
|
+
},
|
|
870
|
+
() => this.compactContext(
|
|
871
|
+
estimatedInputTokens,
|
|
872
|
+
input.contributorContext,
|
|
873
|
+
toolDefinitions
|
|
874
|
+
),
|
|
875
|
+
this.logger
|
|
797
876
|
);
|
|
798
877
|
if (didCompact) {
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
878
|
+
systemPrompt = await recordOperationSpan(
|
|
879
|
+
{
|
|
880
|
+
name: "system_prompt.build",
|
|
881
|
+
componentName: "TurnExecutor",
|
|
882
|
+
attributes: {
|
|
883
|
+
"context.after_compaction": true,
|
|
884
|
+
"llm.model": this.llmContext.model,
|
|
885
|
+
"llm.provider": this.llmContext.provider
|
|
886
|
+
}
|
|
887
|
+
},
|
|
888
|
+
() => this.contextManager.getSystemPrompt(input.contributorContext),
|
|
889
|
+
this.logger
|
|
802
890
|
);
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
891
|
+
({ preparedHistory, formattedMessages } = await recordOperationSpan(
|
|
892
|
+
{
|
|
893
|
+
name: "context.build_messages",
|
|
894
|
+
componentName: "TurnExecutor",
|
|
895
|
+
attributes: {
|
|
896
|
+
"context.after_compaction": true,
|
|
897
|
+
"llm.model": this.llmContext.model,
|
|
898
|
+
"llm.provider": this.llmContext.provider
|
|
899
|
+
}
|
|
900
|
+
},
|
|
901
|
+
async () => {
|
|
902
|
+
const preparedHistory2 = (await this.contextManager.prepareHistory()).preparedHistory;
|
|
903
|
+
const formattedMessages2 = await this.contextManager.getFormattedMessages(
|
|
904
|
+
input.contributorContext,
|
|
905
|
+
this.llmContext,
|
|
906
|
+
systemPrompt,
|
|
907
|
+
preparedHistory2
|
|
908
|
+
);
|
|
909
|
+
return { preparedHistory: preparedHistory2, formattedMessages: formattedMessages2 };
|
|
910
|
+
},
|
|
911
|
+
this.logger
|
|
912
|
+
));
|
|
913
|
+
estimatedInputTokens = await recordOperationSpan(
|
|
914
|
+
{
|
|
915
|
+
name: "context.token_estimate",
|
|
916
|
+
componentName: "TurnExecutor",
|
|
917
|
+
attributes: {
|
|
918
|
+
"context.after_compaction": true,
|
|
919
|
+
"tools.count": Object.keys(toolDefinitions).length
|
|
920
|
+
},
|
|
921
|
+
resultAttributes: (tokens) => ({
|
|
922
|
+
"context.estimated_input_tokens": tokens
|
|
923
|
+
})
|
|
924
|
+
},
|
|
925
|
+
() => this.contextManager.getEstimatedNextInputTokens(
|
|
926
|
+
systemPrompt,
|
|
927
|
+
preparedHistory,
|
|
928
|
+
toolDefinitions
|
|
929
|
+
),
|
|
930
|
+
this.logger
|
|
807
931
|
);
|
|
808
932
|
this.logger.debug(
|
|
809
933
|
`Post-compaction: recomputed estimate is ${estimatedInputTokens} tokens`
|
|
810
934
|
);
|
|
811
935
|
}
|
|
812
936
|
}
|
|
813
|
-
const providerOptions =
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
937
|
+
const providerOptions = await recordOperationSpan(
|
|
938
|
+
{
|
|
939
|
+
name: "llm.request_setup",
|
|
940
|
+
componentName: "TurnExecutor",
|
|
941
|
+
attributes: {
|
|
942
|
+
"llm.model": this.llmContext.model,
|
|
943
|
+
"llm.provider": this.llmContext.provider
|
|
944
|
+
}
|
|
945
|
+
},
|
|
946
|
+
() => buildProviderOptions({
|
|
947
|
+
provider: this.llmContext.provider,
|
|
948
|
+
model: this.llmContext.model,
|
|
949
|
+
reasoning: this.config.reasoning
|
|
950
|
+
}),
|
|
951
|
+
this.logger
|
|
952
|
+
);
|
|
818
953
|
this.logger.debug("LLM request options", {
|
|
819
954
|
provider: this.llmContext.provider,
|
|
820
955
|
model: this.llmContext.model,
|
|
@@ -831,7 +966,7 @@ class TurnExecutor {
|
|
|
831
966
|
...reasoningBudgetTokens !== void 0 && { reasoningBudgetTokens }
|
|
832
967
|
} : void 0;
|
|
833
968
|
return {
|
|
834
|
-
messages:
|
|
969
|
+
messages: formattedMessages,
|
|
835
970
|
tools: input.supportsTools ? createModelToolDefinitions(toolDefinitions) : {},
|
|
836
971
|
toolDefinitions,
|
|
837
972
|
estimatedInputTokens,
|
|
@@ -862,7 +997,8 @@ class TurnExecutor {
|
|
|
862
997
|
this.stepAbortController.signal,
|
|
863
998
|
this.getStreamProcessorConfig(request.estimatedInputTokens, request.reasoning),
|
|
864
999
|
this.logger,
|
|
865
|
-
request.streaming
|
|
1000
|
+
request.streaming,
|
|
1001
|
+
false
|
|
866
1002
|
);
|
|
867
1003
|
return streamProcessor.process(
|
|
868
1004
|
() => streamText({
|
|
@@ -1499,84 +1635,12 @@ class TurnExecutor {
|
|
|
1499
1635
|
* Map provider errors to DextoRuntimeError.
|
|
1500
1636
|
*/
|
|
1501
1637
|
mapProviderError(err) {
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
let balance;
|
|
1509
|
-
try {
|
|
1510
|
-
const parsed = JSON.parse(body);
|
|
1511
|
-
const msg = parsed?.error?.message || "";
|
|
1512
|
-
const match = msg.match(/Balance:\s*\$?([\d.]+)/i);
|
|
1513
|
-
if (match) {
|
|
1514
|
-
balance = parseFloat(match[1]);
|
|
1515
|
-
}
|
|
1516
|
-
} catch {
|
|
1517
|
-
}
|
|
1518
|
-
return new DextoRuntimeError(
|
|
1519
|
-
LLMErrorCode.INSUFFICIENT_CREDITS,
|
|
1520
|
-
ErrorScope.LLM,
|
|
1521
|
-
ErrorType.PAYMENT_REQUIRED,
|
|
1522
|
-
`Insufficient Dexto credits${balance !== void 0 ? `. Balance: $${balance.toFixed(2)}` : ""}`,
|
|
1523
|
-
{
|
|
1524
|
-
sessionId: this.sessionId,
|
|
1525
|
-
provider: this.llmContext.provider,
|
|
1526
|
-
model: this.llmContext.model,
|
|
1527
|
-
status,
|
|
1528
|
-
balance,
|
|
1529
|
-
body
|
|
1530
|
-
},
|
|
1531
|
-
"Run `dexto billing` to check your balance"
|
|
1532
|
-
);
|
|
1533
|
-
}
|
|
1534
|
-
if (status === 429) {
|
|
1535
|
-
return new DextoRuntimeError(
|
|
1536
|
-
LLMErrorCode.RATE_LIMIT_EXCEEDED,
|
|
1537
|
-
ErrorScope.LLM,
|
|
1538
|
-
ErrorType.RATE_LIMIT,
|
|
1539
|
-
`Rate limit exceeded${body ? ` - ${body}` : ""}`,
|
|
1540
|
-
{
|
|
1541
|
-
sessionId: this.sessionId,
|
|
1542
|
-
provider: this.llmContext.provider,
|
|
1543
|
-
model: this.llmContext.model,
|
|
1544
|
-
status,
|
|
1545
|
-
retryAfter,
|
|
1546
|
-
body
|
|
1547
|
-
}
|
|
1548
|
-
);
|
|
1549
|
-
}
|
|
1550
|
-
if (status === 408) {
|
|
1551
|
-
return new DextoRuntimeError(
|
|
1552
|
-
LLMErrorCode.GENERATION_FAILED,
|
|
1553
|
-
ErrorScope.LLM,
|
|
1554
|
-
ErrorType.TIMEOUT,
|
|
1555
|
-
`Provider timed out${body ? ` - ${body}` : ""}`,
|
|
1556
|
-
{
|
|
1557
|
-
sessionId: this.sessionId,
|
|
1558
|
-
provider: this.llmContext.provider,
|
|
1559
|
-
model: this.llmContext.model,
|
|
1560
|
-
status,
|
|
1561
|
-
body
|
|
1562
|
-
}
|
|
1563
|
-
);
|
|
1564
|
-
}
|
|
1565
|
-
return new DextoRuntimeError(
|
|
1566
|
-
LLMErrorCode.GENERATION_FAILED,
|
|
1567
|
-
ErrorScope.LLM,
|
|
1568
|
-
ErrorType.THIRD_PARTY,
|
|
1569
|
-
`Provider error ${status}${body ? ` - ${body}` : ""}`,
|
|
1570
|
-
{
|
|
1571
|
-
sessionId: this.sessionId,
|
|
1572
|
-
provider: this.llmContext.provider,
|
|
1573
|
-
model: this.llmContext.model,
|
|
1574
|
-
status,
|
|
1575
|
-
body
|
|
1576
|
-
}
|
|
1577
|
-
);
|
|
1578
|
-
}
|
|
1579
|
-
return toError(err, this.logger);
|
|
1638
|
+
return mapCoreProviderError({
|
|
1639
|
+
error: err,
|
|
1640
|
+
provider: this.llmContext.provider,
|
|
1641
|
+
model: this.llmContext.model,
|
|
1642
|
+
sessionId: this.sessionId
|
|
1643
|
+
});
|
|
1580
1644
|
}
|
|
1581
1645
|
}
|
|
1582
1646
|
export {
|
|
@@ -53,9 +53,12 @@ async function generateSessionTitle(config, userText, logger, opts = {}) {
|
|
|
53
53
|
});
|
|
54
54
|
const processed = postProcessTitle(result.text);
|
|
55
55
|
if (!processed) {
|
|
56
|
-
return {
|
|
56
|
+
return {
|
|
57
|
+
error: "LLM returned empty title",
|
|
58
|
+
usage: toSessionTitleTokenUsage(result.totalUsage)
|
|
59
|
+
};
|
|
57
60
|
}
|
|
58
|
-
return { title: processed };
|
|
61
|
+
return { title: processed, usage: toSessionTitleTokenUsage(result.totalUsage) };
|
|
59
62
|
} catch (error) {
|
|
60
63
|
if (controller?.signal.aborted) {
|
|
61
64
|
return { timedOut: true, error: "Timed out while waiting for LLM response" };
|
|
@@ -68,6 +71,20 @@ async function generateSessionTitle(config, userText, logger, opts = {}) {
|
|
|
68
71
|
}
|
|
69
72
|
}
|
|
70
73
|
}
|
|
74
|
+
function toSessionTitleTokenUsage(usage) {
|
|
75
|
+
const tokenUsage = {};
|
|
76
|
+
copyTokenUsageNumber(tokenUsage, "cachedInputTokens", usage.cachedInputTokens);
|
|
77
|
+
copyTokenUsageNumber(tokenUsage, "inputTokens", usage.inputTokens);
|
|
78
|
+
copyTokenUsageNumber(tokenUsage, "outputTokens", usage.outputTokens);
|
|
79
|
+
copyTokenUsageNumber(tokenUsage, "reasoningTokens", usage.reasoningTokens);
|
|
80
|
+
copyTokenUsageNumber(tokenUsage, "totalTokens", usage.totalTokens);
|
|
81
|
+
return tokenUsage;
|
|
82
|
+
}
|
|
83
|
+
function copyTokenUsageNumber(target, key, value) {
|
|
84
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
85
|
+
target[key] = value;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
71
88
|
function deriveHeuristicTitle(userText) {
|
|
72
89
|
const sanitized = sanitizeUserText(userText, 120);
|
|
73
90
|
if (!sanitized) return void 0;
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
import type { ValidatedLLMConfig } from '../llm/schemas.js';
|
|
2
2
|
import type { Logger } from '../logger/v2/types.js';
|
|
3
3
|
import type { DextoProviderContext, LanguageModelFactory } from '../llm/services/types.js';
|
|
4
|
+
export interface GenerateSessionTitleTokenUsage {
|
|
5
|
+
cachedInputTokens?: number;
|
|
6
|
+
inputTokens?: number;
|
|
7
|
+
outputTokens?: number;
|
|
8
|
+
reasoningTokens?: number;
|
|
9
|
+
totalTokens?: number;
|
|
10
|
+
}
|
|
4
11
|
export interface GenerateSessionTitleResult {
|
|
5
12
|
title?: string;
|
|
6
13
|
error?: string;
|
|
7
14
|
timedOut?: boolean;
|
|
15
|
+
usage?: GenerateSessionTitleTokenUsage;
|
|
8
16
|
}
|
|
9
17
|
/**
|
|
10
18
|
* Generate a concise title for a chat based on the first user message.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"title-generator.d.ts","sourceRoot":"","sources":["../../src/session/title-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAI3F,MAAM,WAAW,0BAA0B;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"title-generator.d.ts","sourceRoot":"","sources":["../../src/session/title-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAI3F,MAAM,WAAW,8BAA8B;IAC3C,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,0BAA0B;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,8BAA8B,CAAC;CAC1C;AAED;;;GAGG;AACH,wBAAsB,oBAAoB,CACtC,MAAM,EAAE,kBAAkB,EAC1B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE;IACF,oBAAoB,CAAC,EAAE,oBAAoB,CAAC;IAC5C,eAAe,CAAC,EAAE,oBAAoB,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACjB,GACP,OAAO,CAAC,0BAA0B,CAAC,CAmDrC;AAsBD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CA8BzE"}
|
|
@@ -30,9 +30,12 @@ async function generateSessionTitle(config, userText, logger, opts = {}) {
|
|
|
30
30
|
});
|
|
31
31
|
const processed = postProcessTitle(result.text);
|
|
32
32
|
if (!processed) {
|
|
33
|
-
return {
|
|
33
|
+
return {
|
|
34
|
+
error: "LLM returned empty title",
|
|
35
|
+
usage: toSessionTitleTokenUsage(result.totalUsage)
|
|
36
|
+
};
|
|
34
37
|
}
|
|
35
|
-
return { title: processed };
|
|
38
|
+
return { title: processed, usage: toSessionTitleTokenUsage(result.totalUsage) };
|
|
36
39
|
} catch (error) {
|
|
37
40
|
if (controller?.signal.aborted) {
|
|
38
41
|
return { timedOut: true, error: "Timed out while waiting for LLM response" };
|
|
@@ -45,6 +48,20 @@ async function generateSessionTitle(config, userText, logger, opts = {}) {
|
|
|
45
48
|
}
|
|
46
49
|
}
|
|
47
50
|
}
|
|
51
|
+
function toSessionTitleTokenUsage(usage) {
|
|
52
|
+
const tokenUsage = {};
|
|
53
|
+
copyTokenUsageNumber(tokenUsage, "cachedInputTokens", usage.cachedInputTokens);
|
|
54
|
+
copyTokenUsageNumber(tokenUsage, "inputTokens", usage.inputTokens);
|
|
55
|
+
copyTokenUsageNumber(tokenUsage, "outputTokens", usage.outputTokens);
|
|
56
|
+
copyTokenUsageNumber(tokenUsage, "reasoningTokens", usage.reasoningTokens);
|
|
57
|
+
copyTokenUsageNumber(tokenUsage, "totalTokens", usage.totalTokens);
|
|
58
|
+
return tokenUsage;
|
|
59
|
+
}
|
|
60
|
+
function copyTokenUsageNumber(target, key, value) {
|
|
61
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
62
|
+
target[key] = value;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
48
65
|
function deriveHeuristicTitle(userText) {
|
|
49
66
|
const sanitized = sanitizeUserText(userText, 120);
|
|
50
67
|
if (!sanitized) return void 0;
|
|
@@ -29,6 +29,7 @@ var import_promises = require("fs/promises");
|
|
|
29
29
|
var import_path = require("path");
|
|
30
30
|
var import_errors = require("./errors.js");
|
|
31
31
|
var import_DextoRuntimeError = require("../errors/DextoRuntimeError.js");
|
|
32
|
+
var import_operation_span = require("../telemetry/operation-span.js");
|
|
32
33
|
class StaticContributor {
|
|
33
34
|
constructor(id, priority, content) {
|
|
34
35
|
this.id = id;
|
|
@@ -203,7 +204,15 @@ class SkillsContributor {
|
|
|
203
204
|
logger;
|
|
204
205
|
async getContent(_context) {
|
|
205
206
|
try {
|
|
206
|
-
const skills = await
|
|
207
|
+
const skills = await (0, import_operation_span.recordOperationSpan)(
|
|
208
|
+
{
|
|
209
|
+
name: "skills.list",
|
|
210
|
+
componentName: "SkillsContributor",
|
|
211
|
+
resultAttributes: (skills2) => ({ "skills.count": skills2.length })
|
|
212
|
+
},
|
|
213
|
+
() => this.skillManager.list(),
|
|
214
|
+
this.logger
|
|
215
|
+
);
|
|
207
216
|
if (skills.length === 0) {
|
|
208
217
|
return "";
|
|
209
218
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contributors.d.ts","sourceRoot":"","sources":["../../src/systemPrompt/contributors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAGhF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAGpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"contributors.d.ts","sourceRoot":"","sources":["../../src/systemPrompt/contributors.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import { readFile, stat } from "fs/promises";
|
|
|
3
3
|
import { resolve, extname } from "path";
|
|
4
4
|
import { SystemPromptError } from "./errors.js";
|
|
5
5
|
import { DextoRuntimeError } from "../errors/DextoRuntimeError.js";
|
|
6
|
+
import { recordOperationSpan } from "../telemetry/operation-span.js";
|
|
6
7
|
class StaticContributor {
|
|
7
8
|
constructor(id, priority, content) {
|
|
8
9
|
this.id = id;
|
|
@@ -177,7 +178,15 @@ class SkillsContributor {
|
|
|
177
178
|
logger;
|
|
178
179
|
async getContent(_context) {
|
|
179
180
|
try {
|
|
180
|
-
const skills = await
|
|
181
|
+
const skills = await recordOperationSpan(
|
|
182
|
+
{
|
|
183
|
+
name: "skills.list",
|
|
184
|
+
componentName: "SkillsContributor",
|
|
185
|
+
resultAttributes: (skills2) => ({ "skills.count": skills2.length })
|
|
186
|
+
},
|
|
187
|
+
() => this.skillManager.list(),
|
|
188
|
+
this.logger
|
|
189
|
+
);
|
|
181
190
|
if (skills.length === 0) {
|
|
182
191
|
return "";
|
|
183
192
|
}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var browser_exports = {};
|
|
20
|
+
__export(browser_exports, {
|
|
21
|
+
Telemetry: () => Telemetry
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(browser_exports);
|
|
24
|
+
var import_api = require("@opentelemetry/api");
|
|
25
|
+
function isGlobalTelemetryLike(value) {
|
|
26
|
+
if (typeof value !== "object" || value === null) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return typeof Reflect.get(value, "forceFlush") === "function" && typeof Reflect.get(value, "isInitialized") === "function" && typeof Reflect.get(value, "name") === "string" && typeof Reflect.get(value, "shutdown") === "function" && Reflect.get(value, "tracer") !== void 0;
|
|
30
|
+
}
|
|
31
|
+
class Telemetry {
|
|
32
|
+
tracer;
|
|
33
|
+
name;
|
|
34
|
+
_isInitialized;
|
|
35
|
+
_shutdownHandler;
|
|
36
|
+
static _initPromise;
|
|
37
|
+
constructor(config, options) {
|
|
38
|
+
const serviceName = config.serviceName ?? "dexto-service";
|
|
39
|
+
const tracerName = config.tracerName ?? serviceName;
|
|
40
|
+
this.name = serviceName;
|
|
41
|
+
this.tracer = import_api.trace.getTracer(tracerName);
|
|
42
|
+
this._shutdownHandler = options.shutdown;
|
|
43
|
+
this._isInitialized = options.initialized;
|
|
44
|
+
}
|
|
45
|
+
static async registerGlobal(options = {}) {
|
|
46
|
+
const existing = Telemetry.getGlobalInstance();
|
|
47
|
+
if (existing !== void 0) {
|
|
48
|
+
return existing;
|
|
49
|
+
}
|
|
50
|
+
if (Telemetry._initPromise !== void 0) {
|
|
51
|
+
return Telemetry._initPromise;
|
|
52
|
+
}
|
|
53
|
+
Telemetry._initPromise = Promise.resolve().then(() => {
|
|
54
|
+
const current = Telemetry.getGlobalInstance();
|
|
55
|
+
if (current !== void 0) {
|
|
56
|
+
return current;
|
|
57
|
+
}
|
|
58
|
+
const telemetry = new Telemetry(options.config ?? {}, {
|
|
59
|
+
initialized: options.initialized ?? true,
|
|
60
|
+
...options.shutdown !== void 0 && { shutdown: options.shutdown }
|
|
61
|
+
});
|
|
62
|
+
Telemetry.setGlobalInstance(telemetry);
|
|
63
|
+
return telemetry;
|
|
64
|
+
});
|
|
65
|
+
return Telemetry._initPromise;
|
|
66
|
+
}
|
|
67
|
+
static getActiveSpan() {
|
|
68
|
+
return import_api.trace.getActiveSpan();
|
|
69
|
+
}
|
|
70
|
+
static get() {
|
|
71
|
+
const telemetry = Telemetry.getGlobalInstance();
|
|
72
|
+
if (telemetry === void 0) {
|
|
73
|
+
throw new Error("Telemetry not initialized. Call Telemetry.registerGlobal() first.");
|
|
74
|
+
}
|
|
75
|
+
return telemetry;
|
|
76
|
+
}
|
|
77
|
+
static hasGlobalInstance() {
|
|
78
|
+
return Telemetry.getGlobalInstance() !== void 0;
|
|
79
|
+
}
|
|
80
|
+
static async shutdownGlobal() {
|
|
81
|
+
const telemetry = Telemetry.getGlobalInstance();
|
|
82
|
+
if (telemetry !== void 0) {
|
|
83
|
+
await telemetry.shutdown();
|
|
84
|
+
}
|
|
85
|
+
Telemetry.setGlobalInstance(void 0);
|
|
86
|
+
Telemetry._initPromise = void 0;
|
|
87
|
+
}
|
|
88
|
+
static setBaggage(baggage, ctx = import_api.context.active()) {
|
|
89
|
+
const currentBaggage = Object.fromEntries(
|
|
90
|
+
import_api.propagation.getBaggage(ctx)?.getAllEntries() ?? []
|
|
91
|
+
);
|
|
92
|
+
return import_api.propagation.setBaggage(
|
|
93
|
+
ctx,
|
|
94
|
+
import_api.propagation.createBaggage({
|
|
95
|
+
...currentBaggage,
|
|
96
|
+
...baggage
|
|
97
|
+
})
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
static withContext(ctx, fn) {
|
|
101
|
+
return import_api.context.with(ctx, fn);
|
|
102
|
+
}
|
|
103
|
+
isInitialized() {
|
|
104
|
+
return this._isInitialized;
|
|
105
|
+
}
|
|
106
|
+
async forceFlush() {
|
|
107
|
+
const provider = import_api.trace.getTracerProvider();
|
|
108
|
+
const forceFlush = Reflect.get(provider, "forceFlush");
|
|
109
|
+
if (typeof forceFlush === "function") {
|
|
110
|
+
await Reflect.apply(forceFlush, provider, []);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async shutdown() {
|
|
114
|
+
try {
|
|
115
|
+
await this._shutdownHandler?.();
|
|
116
|
+
} finally {
|
|
117
|
+
this._isInitialized = false;
|
|
118
|
+
this._shutdownHandler = void 0;
|
|
119
|
+
Telemetry.setGlobalInstance(void 0);
|
|
120
|
+
Telemetry._initPromise = void 0;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
static getGlobalInstance() {
|
|
124
|
+
const telemetry = Reflect.get(globalThis, "__TELEMETRY__");
|
|
125
|
+
return isGlobalTelemetryLike(telemetry) ? telemetry : void 0;
|
|
126
|
+
}
|
|
127
|
+
static setGlobalInstance(telemetry) {
|
|
128
|
+
if (telemetry === void 0) {
|
|
129
|
+
Reflect.deleteProperty(globalThis, "__TELEMETRY__");
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
Reflect.set(globalThis, "__TELEMETRY__", telemetry);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
136
|
+
0 && (module.exports = {
|
|
137
|
+
Telemetry
|
|
138
|
+
});
|