@duetso/agent 0.2.6 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -16
- package/dist/package.json +8 -3
- package/dist/src/cli/auto-upgrade.d.ts.map +1 -1
- package/dist/src/cli/auto-upgrade.js +7 -54
- package/dist/src/cli/auto-upgrade.js.map +1 -1
- package/dist/src/cli/connect.d.ts +45 -0
- package/dist/src/cli/connect.d.ts.map +1 -0
- package/dist/src/cli/connect.js +265 -0
- package/dist/src/cli/connect.js.map +1 -0
- package/dist/src/cli/help.d.ts +1 -0
- package/dist/src/cli/help.d.ts.map +1 -1
- package/dist/src/cli/help.js +66 -32
- package/dist/src/cli/help.js.map +1 -1
- package/dist/src/cli/memory-add.d.ts +18 -13
- package/dist/src/cli/memory-add.d.ts.map +1 -1
- package/dist/src/cli/memory-add.js +91 -32
- package/dist/src/cli/memory-add.js.map +1 -1
- package/dist/src/cli/memory-recall.d.ts.map +1 -1
- package/dist/src/cli/memory-recall.js +3 -0
- package/dist/src/cli/memory-recall.js.map +1 -1
- package/dist/src/cli/memory-sources.d.ts +20 -0
- package/dist/src/cli/memory-sources.d.ts.map +1 -0
- package/dist/src/cli/memory-sources.js +40 -0
- package/dist/src/cli/memory-sources.js.map +1 -0
- package/dist/src/cli/model.d.ts +5 -0
- package/dist/src/cli/model.d.ts.map +1 -1
- package/dist/src/cli/model.js +43 -0
- package/dist/src/cli/model.js.map +1 -1
- package/dist/src/cli/route.d.ts +12 -0
- package/dist/src/cli/route.d.ts.map +1 -1
- package/dist/src/cli/route.js +39 -9
- package/dist/src/cli/route.js.map +1 -1
- package/dist/src/cli/rpc.d.ts +3 -2
- package/dist/src/cli/rpc.d.ts.map +1 -1
- package/dist/src/cli/rpc.js +3 -2
- package/dist/src/cli/rpc.js.map +1 -1
- package/dist/src/cli/run.d.ts +1 -0
- package/dist/src/cli/run.d.ts.map +1 -1
- package/dist/src/cli/run.js +1 -0
- package/dist/src/cli/run.js.map +1 -1
- package/dist/src/cli/shared.d.ts +11 -0
- package/dist/src/cli/shared.d.ts.map +1 -1
- package/dist/src/cli/shared.js +31 -0
- package/dist/src/cli/shared.js.map +1 -1
- package/dist/src/cli/train.d.ts +31 -7
- package/dist/src/cli/train.d.ts.map +1 -1
- package/dist/src/cli/train.js +233 -79
- package/dist/src/cli/train.js.map +1 -1
- package/dist/src/cli.d.ts +3 -1
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/cli.js +9 -1
- package/dist/src/cli.js.map +1 -1
- package/dist/src/connected-providers/billing.d.ts +6 -0
- package/dist/src/connected-providers/billing.d.ts.map +1 -0
- package/dist/src/connected-providers/billing.js +11 -0
- package/dist/src/connected-providers/billing.js.map +1 -0
- package/dist/src/connected-providers/capability-probe.d.ts +17 -0
- package/dist/src/connected-providers/capability-probe.d.ts.map +1 -0
- package/dist/src/connected-providers/capability-probe.js +92 -0
- package/dist/src/connected-providers/capability-probe.js.map +1 -0
- package/dist/src/connected-providers/fake-issuer.d.ts +61 -0
- package/dist/src/connected-providers/fake-issuer.d.ts.map +1 -0
- package/dist/src/connected-providers/fake-issuer.js +161 -0
- package/dist/src/connected-providers/fake-issuer.js.map +1 -0
- package/dist/src/connected-providers/fallback-notice.d.ts +11 -0
- package/dist/src/connected-providers/fallback-notice.d.ts.map +1 -0
- package/dist/src/connected-providers/fallback-notice.js +20 -0
- package/dist/src/connected-providers/fallback-notice.js.map +1 -0
- package/dist/src/connected-providers/fallback.d.ts +11 -0
- package/dist/src/connected-providers/fallback.d.ts.map +1 -0
- package/dist/src/connected-providers/fallback.js +37 -0
- package/dist/src/connected-providers/fallback.js.map +1 -0
- package/dist/src/connected-providers/refresh.d.ts +12 -0
- package/dist/src/connected-providers/refresh.d.ts.map +1 -0
- package/dist/src/connected-providers/refresh.js +72 -0
- package/dist/src/connected-providers/refresh.js.map +1 -0
- package/dist/src/connected-providers/registry.d.ts +17 -0
- package/dist/src/connected-providers/registry.d.ts.map +1 -0
- package/dist/src/connected-providers/registry.js +30 -0
- package/dist/src/connected-providers/registry.js.map +1 -0
- package/dist/src/connected-providers/store.d.ts +41 -0
- package/dist/src/connected-providers/store.d.ts.map +1 -0
- package/dist/src/connected-providers/store.js +145 -0
- package/dist/src/connected-providers/store.js.map +1 -0
- package/dist/src/connected-providers/tokens.d.ts +42 -0
- package/dist/src/connected-providers/tokens.d.ts.map +1 -0
- package/dist/src/connected-providers/tokens.js +148 -0
- package/dist/src/connected-providers/tokens.js.map +1 -0
- package/dist/src/connected-providers/transport-preference.d.ts +26 -0
- package/dist/src/connected-providers/transport-preference.d.ts.map +1 -0
- package/dist/src/connected-providers/transport-preference.js +42 -0
- package/dist/src/connected-providers/transport-preference.js.map +1 -0
- package/dist/src/core/structured-output.d.ts.map +1 -1
- package/dist/src/core/structured-output.js +2 -1
- package/dist/src/core/structured-output.js.map +1 -1
- package/dist/src/file-lock.d.ts +22 -0
- package/dist/src/file-lock.d.ts.map +1 -0
- package/dist/src/file-lock.js +69 -0
- package/dist/src/file-lock.js.map +1 -0
- package/dist/src/memory/context-pack.d.ts +5 -0
- package/dist/src/memory/context-pack.d.ts.map +1 -1
- package/dist/src/memory/context-pack.js +6 -0
- package/dist/src/memory/context-pack.js.map +1 -1
- package/dist/src/memory/id.d.ts +3 -0
- package/dist/src/memory/id.d.ts.map +1 -0
- package/dist/src/memory/id.js +6 -0
- package/dist/src/memory/id.js.map +1 -0
- package/dist/src/memory/observational-prompts.d.ts +2 -0
- package/dist/src/memory/observational-prompts.d.ts.map +1 -1
- package/dist/src/memory/observational-prompts.js +4 -2
- package/dist/src/memory/observational-prompts.js.map +1 -1
- package/dist/src/memory/observational.d.ts +22 -0
- package/dist/src/memory/observational.d.ts.map +1 -1
- package/dist/src/memory/observational.js +65 -22
- package/dist/src/memory/observational.js.map +1 -1
- package/dist/src/memory/paths.d.ts +9 -0
- package/dist/src/memory/paths.d.ts.map +1 -0
- package/dist/src/memory/paths.js +11 -0
- package/dist/src/memory/paths.js.map +1 -0
- package/dist/src/memory/storage.d.ts.map +1 -1
- package/dist/src/memory/storage.js +1 -4
- package/dist/src/memory/storage.js.map +1 -1
- package/dist/src/memory/store/discovery.d.ts +7 -0
- package/dist/src/memory/store/discovery.d.ts.map +1 -0
- package/dist/src/memory/store/discovery.js +34 -0
- package/dist/src/memory/store/discovery.js.map +1 -0
- package/dist/src/memory/store/file.d.ts +52 -0
- package/dist/src/memory/store/file.d.ts.map +1 -0
- package/dist/src/memory/store/file.js +287 -0
- package/dist/src/memory/store/file.js.map +1 -0
- package/dist/src/memory/store/index.d.ts +5 -0
- package/dist/src/memory/store/index.d.ts.map +1 -0
- package/dist/src/memory/store/index.js +5 -0
- package/dist/src/memory/store/index.js.map +1 -0
- package/dist/src/memory/store/pack.d.ts +25 -0
- package/dist/src/memory/store/pack.d.ts.map +1 -0
- package/dist/src/memory/store/pack.js +71 -0
- package/dist/src/memory/store/pack.js.map +1 -0
- package/dist/src/memory/store/sources.d.ts +55 -0
- package/dist/src/memory/store/sources.d.ts.map +1 -0
- package/dist/src/memory/store/sources.js +85 -0
- package/dist/src/memory/store/sources.js.map +1 -0
- package/dist/src/memory/store/store.d.ts +46 -0
- package/dist/src/memory/store/store.d.ts.map +1 -0
- package/dist/src/memory/store/store.js +171 -0
- package/dist/src/memory/store/store.js.map +1 -0
- package/dist/src/memory/store.d.ts +19 -16
- package/dist/src/memory/store.d.ts.map +1 -1
- package/dist/src/memory/store.js +14 -11
- package/dist/src/memory/store.js.map +1 -1
- package/dist/src/memory-store.js +554 -0
- package/dist/src/model-resolution/catalog.d.ts +24 -10
- package/dist/src/model-resolution/catalog.d.ts.map +1 -1
- package/dist/src/model-resolution/catalog.js +61 -36
- package/dist/src/model-resolution/catalog.js.map +1 -1
- package/dist/src/model-resolution/duet-gateway.d.ts +2 -0
- package/dist/src/model-resolution/duet-gateway.d.ts.map +1 -1
- package/dist/src/model-resolution/duet-gateway.js +57 -4
- package/dist/src/model-resolution/duet-gateway.js.map +1 -1
- package/dist/src/model-resolution/resolver.d.ts +17 -0
- package/dist/src/model-resolution/resolver.d.ts.map +1 -1
- package/dist/src/model-resolution/resolver.js +49 -4
- package/dist/src/model-resolution/resolver.js.map +1 -1
- package/dist/src/model-routing/advisor-context.d.ts +31 -5
- package/dist/src/model-routing/advisor-context.d.ts.map +1 -1
- package/dist/src/model-routing/advisor-context.js +87 -10
- package/dist/src/model-routing/advisor-context.js.map +1 -1
- package/dist/src/model-routing/advisor-lifecycle.d.ts +14 -5
- package/dist/src/model-routing/advisor-lifecycle.d.ts.map +1 -1
- package/dist/src/model-routing/advisor-lifecycle.js +24 -7
- package/dist/src/model-routing/advisor-lifecycle.js.map +1 -1
- package/dist/src/model-routing/prompts.d.ts.map +1 -1
- package/dist/src/model-routing/prompts.js +18 -10
- package/dist/src/model-routing/prompts.js.map +1 -1
- package/dist/src/model-routing/table.js +18 -18
- package/dist/src/model-routing/table.js.map +1 -1
- package/dist/src/session/session-manager.d.ts +1 -4
- package/dist/src/session/session-manager.d.ts.map +1 -1
- package/dist/src/session/session-manager.js +2 -5
- package/dist/src/session/session-manager.js.map +1 -1
- package/dist/src/session/session.d.ts +2 -2
- package/dist/src/session/session.d.ts.map +1 -1
- package/dist/src/session/session.js +10 -7
- package/dist/src/session/session.js.map +1 -1
- package/dist/src/train/archive.d.ts.map +1 -1
- package/dist/src/train/archive.js +5 -0
- package/dist/src/train/archive.js.map +1 -1
- package/dist/src/train/types.d.ts +8 -7
- package/dist/src/train/types.d.ts.map +1 -1
- package/dist/src/tui/sidebar.d.ts.map +1 -1
- package/dist/src/tui/sidebar.js +40 -1
- package/dist/src/tui/sidebar.js.map +1 -1
- package/dist/src/turn-runner/agent-events.d.ts +2 -0
- package/dist/src/turn-runner/agent-events.d.ts.map +1 -1
- package/dist/src/turn-runner/agent-events.js +11 -0
- package/dist/src/turn-runner/agent-events.js.map +1 -1
- package/dist/src/turn-runner/subagent.d.ts +4 -1
- package/dist/src/turn-runner/subagent.d.ts.map +1 -1
- package/dist/src/turn-runner/subagent.js +11 -3
- package/dist/src/turn-runner/subagent.js.map +1 -1
- package/dist/src/turn-runner/tools.d.ts +3 -3
- package/dist/src/turn-runner/tools.d.ts.map +1 -1
- package/dist/src/turn-runner/tools.js +1 -1
- package/dist/src/turn-runner/tools.js.map +1 -1
- package/dist/src/turn-runner/turn-runner.d.ts +19 -3
- package/dist/src/turn-runner/turn-runner.d.ts.map +1 -1
- package/dist/src/turn-runner/turn-runner.js +162 -33
- package/dist/src/turn-runner/turn-runner.js.map +1 -1
- package/dist/src/turn-runner/usage-accounting.d.ts +5 -2
- package/dist/src/turn-runner/usage-accounting.d.ts.map +1 -1
- package/dist/src/turn-runner/usage-accounting.js +18 -6
- package/dist/src/turn-runner/usage-accounting.js.map +1 -1
- package/dist/src/turn-runner/wire-shaping.d.ts +3 -1
- package/dist/src/turn-runner/wire-shaping.d.ts.map +1 -1
- package/dist/src/turn-runner/wire-shaping.js +5 -1
- package/dist/src/turn-runner/wire-shaping.js.map +1 -1
- package/dist/src/types/config.d.ts +7 -0
- package/dist/src/types/config.d.ts.map +1 -1
- package/dist/src/types/protocol.d.ts +13 -5
- package/dist/src/types/protocol.d.ts.map +1 -1
- package/package.json +8 -3
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
1
2
|
import { Agent, } from "@earendil-works/pi-agent-core";
|
|
2
3
|
import { isContextOverflow } from "@earendil-works/pi-ai";
|
|
3
4
|
import { resolveProviderApiKey } from "../model-resolution/duet-gateway.js";
|
|
5
|
+
import { ensureFreshConnectedTokens, markConnectedProviderReconnectNeeded, } from "../connected-providers/tokens.js";
|
|
6
|
+
import { isConnectedProviderId } from "../connected-providers/store.js";
|
|
7
|
+
import { connectedFallbackCause, isPostOutputConnectedFailure, nextTransportAfterConnectedFailure, } from "../connected-providers/fallback.js";
|
|
8
|
+
import { transportFallbackNotice } from "../connected-providers/fallback-notice.js";
|
|
9
|
+
import { usageForTransport } from "../connected-providers/billing.js";
|
|
10
|
+
import { connectedTransportSnapshot, demoteConnectedTransport } from "../cli/shared.js";
|
|
4
11
|
import dedent from "dedent";
|
|
5
12
|
import { stripSystemReminders, systemReminder } from "../lib/system-reminder.js";
|
|
6
13
|
import { assistantText } from "../core/serializer.js";
|
|
@@ -8,20 +15,22 @@ import { classifyRoute } from "../model-routing/classifier.js";
|
|
|
8
15
|
import { loadRoutingTable } from "../model-routing/loader.js";
|
|
9
16
|
import { AdvisorTurnLifecycle } from "../model-routing/advisor-lifecycle.js";
|
|
10
17
|
import { ADVISOR_COMPLETION_REVIEW_REMINDER, ADVISOR_EXECUTOR_GUIDANCE_LAYER, ADVISOR_ORIENTATION_REMINDER, } from "../model-routing/prompts.js";
|
|
11
|
-
import { captureAdvisorExecutorContext } from "../model-routing/advisor-context.js";
|
|
18
|
+
import { ADVISOR_RECENT_MESSAGE_TARGET_TOKENS, buildAdvisorContext, captureAdvisorExecutorContext, } from "../model-routing/advisor-context.js";
|
|
19
|
+
import { ADVISOR_MAX_OUTPUT_TOKENS } from "../model-routing/advisor.js";
|
|
12
20
|
import { resolveTierDefault } from "../model-routing/resolve.js";
|
|
13
21
|
import { ModelRouter, } from "../model-routing/router.js";
|
|
14
22
|
import { BUILT_IN_ROUTING_TABLE, isVirtualModel, } from "../model-routing/table.js";
|
|
15
23
|
import { toXML } from "../lib/xml.js";
|
|
16
|
-
import { createObservationalContextTransform, DEFAULT_EFFECTIVE_CONTEXT, estimateTokens, resolveObservationalMemorySettings, stripObservationalContextMessages, updateObservationalMemory, } from "../memory/observational.js";
|
|
17
|
-
import { rebuildMemoryContextPack } from "../memory/context-pack.js";
|
|
24
|
+
import { compactObservationalContext, createObservationalContextTransform, DEFAULT_EFFECTIVE_CONTEXT, estimateTokens, resolveObservationalMemorySettings, stripObservationalContextMessages, updateObservationalMemory, } from "../memory/observational.js";
|
|
25
|
+
import { rebuildMemoryContextPack, rebuildPinnedStoreContextPack } from "../memory/context-pack.js";
|
|
18
26
|
import { createEmbeddingClient } from "../memory/embedding.js";
|
|
19
27
|
import { loadStoredMemory, replaceSessionObservations, } from "../memory/storage.js";
|
|
20
28
|
import { MemoryContextCache } from "../memory/store.js";
|
|
21
|
-
import {
|
|
29
|
+
import { discoverMemoryStores } from "../memory/store/discovery.js";
|
|
30
|
+
import { DEFAULT_CLI_MEMORY_MODEL, DEFAULT_CLI_MODEL, resolveMeteredModelName, resolveModelName, routingCatalogAdapter, } from "../model-resolution/resolver.js";
|
|
22
31
|
import { DEFAULT_TASK_WAIT_BUDGET_MS } from "../types/config.js";
|
|
23
32
|
import { COMPACT_MESSAGE_TOKENS_RATIO, compactTurnState, } from "./state-compaction.js";
|
|
24
|
-
import { createAgentEventTranslator, agentMessageText } from "./agent-events.js";
|
|
33
|
+
import { createAgentEventTranslator, agentMessageText, isExternallyVisibleAgentEvent, } from "./agent-events.js";
|
|
25
34
|
import { createRecallMemorySystemPromptLayer, createSourceOfTruthSystemPromptLayer, createStateMachineSystemPromptLayer, withheldAskReminder, parkNudge, } from "./prompts.js";
|
|
26
35
|
import { applyEvictionHorizon, calculateWireTokens, createInitialHorizon, findEvictionHorizon, } from "./wire-shaping.js";
|
|
27
36
|
import { createDefaultTurnRunnerTools, createTurnRunnerTools, resolveStateCwd, formatCarriedTodosReminder, formatStateMachineTerminalAcknowledgmentPrompt, isTurnRunnerControlResult, MINIMUM_STATE_MACHINE_DELAY_MS, } from "./tools.js";
|
|
@@ -284,8 +293,9 @@ export class TurnRunner {
|
|
|
284
293
|
}
|
|
285
294
|
: undefined),
|
|
286
295
|
retryTransientServerErrors: (agent) => this.retryTransientServerErrors(agent),
|
|
296
|
+
retryConnectedTransportFallback: (agent, visibleOutput) => this.retryConnectedTransportFallback(agent, visibleOutput),
|
|
287
297
|
emitAgentEvent: (event, origin) => this.emitAgentEvent(event, origin),
|
|
288
|
-
recordUsage: (usage, modelId) => this.recordUsage(usage, modelId),
|
|
298
|
+
recordUsage: (usage, modelId, provider) => this.recordUsage(usage, modelId, provider),
|
|
289
299
|
emitTurnUsage: (origin) => this.emitTurnUsage(origin),
|
|
290
300
|
});
|
|
291
301
|
}
|
|
@@ -442,6 +452,7 @@ export class TurnRunner {
|
|
|
442
452
|
* sees available skills before typing the first prompt.
|
|
443
453
|
*/
|
|
444
454
|
async start(command) {
|
|
455
|
+
await ensureFreshConnectedTokens();
|
|
445
456
|
await this.ensureMemoryLoaded();
|
|
446
457
|
await this.ensureSkillsLoaded();
|
|
447
458
|
await this.ensureMcpServersConnected(command.mcpServers);
|
|
@@ -508,6 +519,7 @@ export class TurnRunner {
|
|
|
508
519
|
*/
|
|
509
520
|
async turn(command, onAccepted) {
|
|
510
521
|
this.requireStarted();
|
|
522
|
+
await ensureFreshConnectedTokens();
|
|
511
523
|
await this.ensureMemoryLoaded();
|
|
512
524
|
await this.ensureSkillsLoaded();
|
|
513
525
|
// Serialize behind an in-flight compact. Compact advances the wire
|
|
@@ -1881,12 +1893,9 @@ export class TurnRunner {
|
|
|
1881
1893
|
});
|
|
1882
1894
|
}
|
|
1883
1895
|
createAskAdvisorStorage(router, policy) {
|
|
1884
|
-
const resolveAdvisorModel = () =>
|
|
1896
|
+
const resolveAdvisorModel = () => resolveMeteredModelName(policy.target.modelName);
|
|
1885
1897
|
return {
|
|
1886
|
-
getContext: async () =>
|
|
1887
|
-
const agent = this.requireParentAgent();
|
|
1888
|
-
return await captureAdvisorExecutorContext(agent);
|
|
1889
|
-
},
|
|
1898
|
+
getContext: async (contextWindowTokens) => await this.captureContextForAdvisor(contextWindowTokens),
|
|
1890
1899
|
resolveModel: () => {
|
|
1891
1900
|
const model = resolveAdvisorModel();
|
|
1892
1901
|
return {
|
|
@@ -1905,7 +1914,7 @@ export class TurnRunner {
|
|
|
1905
1914
|
},
|
|
1906
1915
|
recordUsage: (usage) => {
|
|
1907
1916
|
const model = resolveAdvisorModel();
|
|
1908
|
-
this.recordAndEmitUsage(usageFromAiSdk(usage, model), model.id);
|
|
1917
|
+
this.recordAndEmitUsage(usageFromAiSdk(usage, model), model.id, model.provider);
|
|
1909
1918
|
},
|
|
1910
1919
|
onUsageError: (error) => {
|
|
1911
1920
|
const reason = error instanceof Error ? error.message : String(error);
|
|
@@ -1925,6 +1934,55 @@ export class TurnRunner {
|
|
|
1925
1934
|
},
|
|
1926
1935
|
};
|
|
1927
1936
|
}
|
|
1937
|
+
/**
|
|
1938
|
+
* Keep ordinary advisor calls raw when already efficient. Above the soft
|
|
1939
|
+
* target, drain older work through the normal memory observer and project it
|
|
1940
|
+
* with an advisor-owned horizon so the executor's next request is unchanged.
|
|
1941
|
+
*/
|
|
1942
|
+
async captureContextForAdvisor(contextWindowTokens, options = {}) {
|
|
1943
|
+
const agent = this.requireParentAgent();
|
|
1944
|
+
const rawContext = await captureAdvisorExecutorContext(agent);
|
|
1945
|
+
const rawRequest = buildAdvisorContext({
|
|
1946
|
+
context: rawContext,
|
|
1947
|
+
contextWindowTokens,
|
|
1948
|
+
reservedOutputTokens: ADVISOR_MAX_OUTPUT_TOKENS,
|
|
1949
|
+
});
|
|
1950
|
+
const inputTargetTokens = rawRequest.metadata.inputTargetTokens;
|
|
1951
|
+
if (!rawRequest.metadata.truncated &&
|
|
1952
|
+
rawRequest.metadata.estimatedInputTokens <= inputTargetTokens) {
|
|
1953
|
+
return rawContext;
|
|
1954
|
+
}
|
|
1955
|
+
if (!this.memoryPersistence?.session)
|
|
1956
|
+
return rawContext;
|
|
1957
|
+
let recentMessageTarget = Math.min(ADVISOR_RECENT_MESSAGE_TARGET_TOKENS, Math.floor(inputTargetTokens / 2));
|
|
1958
|
+
let projectedContext = rawContext;
|
|
1959
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
1960
|
+
projectedContext = await captureAdvisorExecutorContext(agent, {
|
|
1961
|
+
transformMessages: async (messages) => await compactObservationalContext({
|
|
1962
|
+
messages,
|
|
1963
|
+
memory: this.memory,
|
|
1964
|
+
horizon: this.advisorWireGuardHorizon,
|
|
1965
|
+
targetMessageTokens: recentMessageTarget,
|
|
1966
|
+
protectRecentToolInteraction: true,
|
|
1967
|
+
...(options.drainObservations === false
|
|
1968
|
+
? {}
|
|
1969
|
+
: {
|
|
1970
|
+
onCompaction: async (observable) => await this.ensureMemoryCoverageForCompaction(observable),
|
|
1971
|
+
}),
|
|
1972
|
+
}),
|
|
1973
|
+
});
|
|
1974
|
+
const projectedRequest = buildAdvisorContext({
|
|
1975
|
+
context: projectedContext,
|
|
1976
|
+
contextWindowTokens,
|
|
1977
|
+
reservedOutputTokens: ADVISOR_MAX_OUTPUT_TOKENS,
|
|
1978
|
+
});
|
|
1979
|
+
const excess = projectedRequest.metadata.estimatedInputTokens - inputTargetTokens;
|
|
1980
|
+
if (excess <= 0)
|
|
1981
|
+
return projectedContext;
|
|
1982
|
+
recentMessageTarget = Math.max(1, recentMessageTarget - excess);
|
|
1983
|
+
}
|
|
1984
|
+
return projectedContext;
|
|
1985
|
+
}
|
|
1928
1986
|
/**
|
|
1929
1987
|
* Pass-prep applied to EVERY parent pass, including harness overrides of
|
|
1930
1988
|
* `runAgentWorker` (they must call this first). One-shot reminders that must
|
|
@@ -1947,7 +2005,12 @@ export class TurnRunner {
|
|
|
1947
2005
|
agent.state.tools = this.turnTools ?? this.createTools(input.state.mode).tools;
|
|
1948
2006
|
this.parentControlResults.length = 0;
|
|
1949
2007
|
this.setParentAgentRunning(true);
|
|
1950
|
-
|
|
2008
|
+
let visibleOutput = false;
|
|
2009
|
+
const unsubscribe = agent.subscribe((event) => {
|
|
2010
|
+
if (isExternallyVisibleAgentEvent(event))
|
|
2011
|
+
visibleOutput = true;
|
|
2012
|
+
this.emitParentAgentEvent(event);
|
|
2013
|
+
});
|
|
1951
2014
|
this.parentAgentInterrupted = false;
|
|
1952
2015
|
try {
|
|
1953
2016
|
if (!input.continuation) {
|
|
@@ -1960,6 +2023,7 @@ export class TurnRunner {
|
|
|
1960
2023
|
if (switched)
|
|
1961
2024
|
await this.applyRouterSwitch(agent, switched);
|
|
1962
2025
|
await agent.prompt(input.prompt, input.images);
|
|
2026
|
+
await this.retryConnectedTransportFallback(agent, () => visibleOutput);
|
|
1963
2027
|
// Single-shot recovery: if the provider rejected the first attempt
|
|
1964
2028
|
// with a context-overflow error, advance the sticky wire-shaping
|
|
1965
2029
|
// horizon so the next send carries roughly the newer half of
|
|
@@ -1971,7 +2035,9 @@ export class TurnRunner {
|
|
|
1971
2035
|
if (await this.tryRecoverFromContextOverflow(agent)) {
|
|
1972
2036
|
await agent.continue();
|
|
1973
2037
|
}
|
|
1974
|
-
|
|
2038
|
+
if (!isPostOutputConnectedFailure(agent.state.model.provider, agent.state.messages.at(-1), visibleOutput)) {
|
|
2039
|
+
await this.retryTransientServerErrors(agent);
|
|
2040
|
+
}
|
|
1975
2041
|
}
|
|
1976
2042
|
catch (error) {
|
|
1977
2043
|
if (!this.parentAgentInterrupted) {
|
|
@@ -2152,6 +2218,37 @@ export class TurnRunner {
|
|
|
2152
2218
|
attempt = messagesAppended > 1 ? 1 : attempt + 1;
|
|
2153
2219
|
}
|
|
2154
2220
|
}
|
|
2221
|
+
/** Retry a connected-provider refusal on the next transport before any visible effect. */
|
|
2222
|
+
async retryConnectedTransportFallback(agent, visibleOutput) {
|
|
2223
|
+
while (agent.state.errorMessage) {
|
|
2224
|
+
const provider = agent.state.model.provider;
|
|
2225
|
+
if (!isConnectedProviderId(provider))
|
|
2226
|
+
return;
|
|
2227
|
+
const cause = connectedFallbackCause(agent.state.messages.at(-1));
|
|
2228
|
+
if (!cause || visibleOutput())
|
|
2229
|
+
return;
|
|
2230
|
+
const fallback = nextTransportAfterConnectedFailure(provider, agent.state.model.id, connectedTransportSnapshot());
|
|
2231
|
+
if (!fallback || fallback.transport === provider)
|
|
2232
|
+
return;
|
|
2233
|
+
const failedModelName = agent.state.model.id;
|
|
2234
|
+
demoteConnectedTransport(provider);
|
|
2235
|
+
if (cause === "auth_failed")
|
|
2236
|
+
await markConnectedProviderReconnectNeeded(provider);
|
|
2237
|
+
agent.state.messages.pop();
|
|
2238
|
+
agent.state.model = resolveModelName(`${fallback.transport}:${fallback.modelId}`);
|
|
2239
|
+
this.emit({
|
|
2240
|
+
type: "system",
|
|
2241
|
+
level: "info",
|
|
2242
|
+
message: transportFallbackNotice({
|
|
2243
|
+
provider,
|
|
2244
|
+
modelName: failedModelName,
|
|
2245
|
+
fallbackTransport: fallback.transport,
|
|
2246
|
+
cause,
|
|
2247
|
+
}),
|
|
2248
|
+
});
|
|
2249
|
+
await agent.continue();
|
|
2250
|
+
}
|
|
2251
|
+
}
|
|
2155
2252
|
async updateMemoryAfterAgentRun(messages, options, sessionId = this.config.sessionId, refreshReflections = true) {
|
|
2156
2253
|
if (this.config.memoryDbPath === undefined) {
|
|
2157
2254
|
return;
|
|
@@ -2164,13 +2261,14 @@ export class TurnRunner {
|
|
|
2164
2261
|
// state-agent entries in `usageByModel` (e.g. `openai/gpt-5.4-mini`) rather
|
|
2165
2262
|
// than mixing a shorthand in among resolved ids.
|
|
2166
2263
|
const memoryModel = this.resolveMemoryActorModel(options);
|
|
2167
|
-
const
|
|
2264
|
+
const resolvedMemoryModel = resolveMeteredModelName(memoryModel);
|
|
2265
|
+
const memoryModelId = resolvedMemoryModel.id;
|
|
2168
2266
|
const result = await updateObservationalMemory({
|
|
2169
2267
|
session,
|
|
2170
2268
|
memory: this.memory,
|
|
2171
2269
|
sessionId,
|
|
2172
2270
|
effectiveContext: this.resolveEffectiveContext(this.parentAgent?.state.model.contextWindow),
|
|
2173
|
-
actorModel:
|
|
2271
|
+
actorModel: `${resolvedMemoryModel.provider}:${resolvedMemoryModel.id}`,
|
|
2174
2272
|
settings: this.config.memory,
|
|
2175
2273
|
messages,
|
|
2176
2274
|
cwd: this.config.cwd ?? process.cwd(),
|
|
@@ -2180,7 +2278,7 @@ export class TurnRunner {
|
|
|
2180
2278
|
// the terminal aggregate even though memory runs after the parent's
|
|
2181
2279
|
// final `message_end`.
|
|
2182
2280
|
onUsage: (usage) => {
|
|
2183
|
-
this.recordUsage(usage, memoryModelId);
|
|
2281
|
+
this.recordUsage(usage, memoryModelId, resolvedMemoryModel.provider);
|
|
2184
2282
|
this.emitTurnUsage();
|
|
2185
2283
|
},
|
|
2186
2284
|
onActivity: (event) => this.emit({ type: "memory", ...event }),
|
|
@@ -2333,18 +2431,21 @@ export class TurnRunner {
|
|
|
2333
2431
|
// `runAgentWorker` on a provider context-overflow error so the retry
|
|
2334
2432
|
// sends the newer half of history.
|
|
2335
2433
|
wireGuardHorizon = createInitialHorizon();
|
|
2434
|
+
/** Sticky only for repeated advisor projections; never persisted into executor state. */
|
|
2435
|
+
advisorWireGuardHorizon = createInitialHorizon();
|
|
2336
2436
|
async getSkills() {
|
|
2337
2437
|
await this.ensureSkillsLoaded();
|
|
2338
2438
|
return this.skillContext.getSkills();
|
|
2339
2439
|
}
|
|
2340
2440
|
/**
|
|
2341
|
-
* Re-discover installed skills from disk. Surfaces
|
|
2342
|
-
*
|
|
2441
|
+
* Re-discover installed skills and curated memory stores from disk. Surfaces
|
|
2442
|
+
* newly added skills or edited memory files without restarting the runner.
|
|
2343
2443
|
* Callers typically pair this with `getSkills()` to refresh their
|
|
2344
2444
|
* autocomplete catalog.
|
|
2345
2445
|
*/
|
|
2346
2446
|
async reloadSkills() {
|
|
2347
2447
|
await this.skillContext.reload();
|
|
2448
|
+
await this.refreshPinnedStoreContextPack();
|
|
2348
2449
|
return this.skillContext.getSkills();
|
|
2349
2450
|
}
|
|
2350
2451
|
/** System-prompt files (AGENTS.md by default) that resolved on disk for this session. */
|
|
@@ -2383,10 +2484,11 @@ export class TurnRunner {
|
|
|
2383
2484
|
// call so a `duet login` mid-session lights up retrieval without
|
|
2384
2485
|
// a runner restart.
|
|
2385
2486
|
//
|
|
2386
|
-
//
|
|
2387
|
-
//
|
|
2388
|
-
//
|
|
2389
|
-
//
|
|
2487
|
+
// The file-backed pack loads alongside the database-backed pack so the
|
|
2488
|
+
// first dispatched turn sees both frozen layers. Later database compaction
|
|
2489
|
+
// triggers refresh only observations; explicit skills reload refreshes the
|
|
2490
|
+
// file-backed layer.
|
|
2491
|
+
const pinnedStoreLoad = this.refreshPinnedStoreContextPack();
|
|
2390
2492
|
this.memoryPersistence = await loadStoredMemory(this.config.memoryDbPath, this.config.cwd ?? process.cwd(), {
|
|
2391
2493
|
embed: createEmbeddingClient(),
|
|
2392
2494
|
contextPack: {
|
|
@@ -2415,6 +2517,27 @@ export class TurnRunner {
|
|
|
2415
2517
|
});
|
|
2416
2518
|
},
|
|
2417
2519
|
});
|
|
2520
|
+
await pinnedStoreLoad;
|
|
2521
|
+
}
|
|
2522
|
+
/** Reload the frozen file-backed layer without touching database memory. */
|
|
2523
|
+
async refreshPinnedStoreContextPack() {
|
|
2524
|
+
if (this.config.memoryStores === false) {
|
|
2525
|
+
this.memory.setStoredContextPack([]);
|
|
2526
|
+
return;
|
|
2527
|
+
}
|
|
2528
|
+
try {
|
|
2529
|
+
const base = this.config.cwd ?? process.cwd();
|
|
2530
|
+
// Explicit entries may be relative; resolve them against the configured
|
|
2531
|
+
// cwd like relative db and system-prompt paths, not the process cwd.
|
|
2532
|
+
const stores = this.config.memoryStores
|
|
2533
|
+
? this.config.memoryStores.map((store) => resolve(base, store))
|
|
2534
|
+
: await discoverMemoryStores(base);
|
|
2535
|
+
await rebuildPinnedStoreContextPack({ stores, cache: this.memory });
|
|
2536
|
+
}
|
|
2537
|
+
catch (error) {
|
|
2538
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
2539
|
+
console.warn(`[duet-agent] failed to load pinned memory stores: ${reason}`);
|
|
2540
|
+
}
|
|
2418
2541
|
}
|
|
2419
2542
|
createBaseSystemPromptWithAppendedLayers(input) {
|
|
2420
2543
|
return this.skillContext.createSystemPromptWithAppendedLayers(input);
|
|
@@ -2433,15 +2556,21 @@ export class TurnRunner {
|
|
|
2433
2556
|
thinkingLevel: options?.thinkingLevel ?? base?.thinkingLevel ?? this.config.thinkingLevel,
|
|
2434
2557
|
};
|
|
2435
2558
|
}
|
|
2436
|
-
recordUsage(usage, modelId) {
|
|
2437
|
-
|
|
2438
|
-
if (usage && modelId) {
|
|
2439
|
-
|
|
2559
|
+
recordUsage(usage, modelId, provider) {
|
|
2560
|
+
const transport = provider ?? this.parentAgent?.state.model.provider;
|
|
2561
|
+
if (usage && (!modelId || !transport)) {
|
|
2562
|
+
throw new Error("Usage accounting requires both model id and transport provider.");
|
|
2563
|
+
}
|
|
2564
|
+
const accounted = usage && transport ? usageForTransport(usage, transport) : usage;
|
|
2565
|
+
this.turnUsage = addUsage(this.turnUsage, accounted);
|
|
2566
|
+
if (accounted && modelId && transport) {
|
|
2567
|
+
this.turnUsageByModel = addUsageByModel(this.turnUsageByModel, modelId, transport, accounted);
|
|
2568
|
+
this.turnUsage.cost.total = this.turnUsageByModel.reduce((total, entry) => total + entry.usage.cost.total, 0);
|
|
2440
2569
|
}
|
|
2441
2570
|
}
|
|
2442
2571
|
/** Attribute a non-parent model call and publish it once a flat context snapshot exists. */
|
|
2443
|
-
recordAndEmitUsage(usage, modelId) {
|
|
2444
|
-
this.recordUsage(usage, modelId);
|
|
2572
|
+
recordAndEmitUsage(usage, modelId, provider) {
|
|
2573
|
+
this.recordUsage(usage, modelId, provider);
|
|
2445
2574
|
this.emitTurnUsage();
|
|
2446
2575
|
}
|
|
2447
2576
|
emitAgentEvent(event, origin) {
|
|
@@ -2475,7 +2604,7 @@ export class TurnRunner {
|
|
|
2475
2604
|
// consumed tokens, so a rejected attempt (e.g. a provider context-overflow
|
|
2476
2605
|
// error the turn then recovers from) carries no usage and would otherwise
|
|
2477
2606
|
// emit a degenerate all-zero bar.
|
|
2478
|
-
this.recordUsage(event.message.usage, event.message.model);
|
|
2607
|
+
this.recordUsage(event.message.usage, event.message.model, event.message.provider);
|
|
2479
2608
|
if (event.message.usage.totalTokens > 0)
|
|
2480
2609
|
this.emitTurnUsage();
|
|
2481
2610
|
}
|
|
@@ -2593,7 +2722,7 @@ export class TurnRunner {
|
|
|
2593
2722
|
systemPrompt: estimateTokens(agent.state.systemPrompt),
|
|
2594
2723
|
messages: messageWireTokens,
|
|
2595
2724
|
localMemory: pack.local.reduce((total, row) => total + estimateTokens(row.content), 0),
|
|
2596
|
-
globalMemory: pack.global.reduce((total, row) => total + estimateTokens(row.content), 0),
|
|
2725
|
+
globalMemory: [...pack.stored, ...pack.global].reduce((total, row) => total + estimateTokens(row.content), 0),
|
|
2597
2726
|
};
|
|
2598
2727
|
}
|
|
2599
2728
|
/**
|
|
@@ -2646,11 +2775,11 @@ export class TurnRunner {
|
|
|
2646
2775
|
}
|
|
2647
2776
|
/** One metered classifier contract shared by parent routing and spawned children. */
|
|
2648
2777
|
classifierOptions(table) {
|
|
2649
|
-
const model =
|
|
2778
|
+
const model = resolveMeteredModelName(table.classifier.target.modelName);
|
|
2650
2779
|
return {
|
|
2651
2780
|
model: `${model.provider}:${model.id}`,
|
|
2652
2781
|
thinkingLevel: table.classifier.target.thinkingLevel,
|
|
2653
|
-
onUsage: (usage) => this.recordAndEmitUsage(usage, model.id),
|
|
2782
|
+
onUsage: (usage) => this.recordAndEmitUsage(usage, model.id, model.provider),
|
|
2654
2783
|
};
|
|
2655
2784
|
}
|
|
2656
2785
|
/** True when a model name is owned by the validated project table. */
|