mixdog 1.3.4 → 1.3.5
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/LICENSES/oh-my-pi-MIT.txt +23 -0
- package/NOTICE.md +15 -0
- package/README.md +11 -0
- package/package.json +2 -1
- package/scripts/embed-google-oauth-client.mjs +49 -0
- package/scripts/lib/test-spawn-ledger.mjs +46 -1
- package/scripts/test.mjs +5 -0
- package/src/defaults/shipped-history.json +8 -0
- package/src/defaults/skills/browser-use/SKILL.md +21 -9
- package/src/defaults/skills/setup/SKILL.md +7 -2
- package/src/defaults/skills/setup/references/actions.md +82 -27
- package/src/defaults/skills/setup/references/surfaces.md +67 -34
- package/src/defaults/skills/setup-guide/SKILL.md +3 -3
- package/src/lib/keychain-cjs.cjs +359 -29
- package/src/rules/agent-mode/AGENT_MODE.md +10 -2
- package/src/rules/agent-mode/MIXY.md +12 -0
- package/src/runtime/agent/orchestrator/agent-runtime/heartbeat-completion.mjs +193 -0
- package/src/runtime/agent/orchestrator/config.mjs +18 -0
- package/src/runtime/agent/orchestrator/mcp/client-transport.mjs +2 -2
- package/src/runtime/agent/orchestrator/mcp/client.mjs +6 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-callback.mjs +31 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-client.mjs +16 -3
- package/src/runtime/agent/orchestrator/mcp/oauth-login.mjs +42 -7
- package/src/runtime/agent/orchestrator/mcp/oauth-provider.mjs +21 -2
- package/src/runtime/agent/orchestrator/mcp/oauth-shared.mjs +23 -0
- package/src/runtime/agent/orchestrator/mcp/oauth.mjs +11 -1
- package/src/runtime/agent/orchestrator/providers/account-pool.mjs +68 -23
- package/src/runtime/agent/orchestrator/providers/admission-scheduler.mjs +22 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-api-request.mjs +18 -5
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/anthropic-oauth.mjs +15 -3
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth-catalog.mjs +52 -8
- package/src/runtime/agent/orchestrator/providers/antigravity-oauth.mjs +10 -1
- package/src/runtime/agent/orchestrator/providers/antigravity-request.mjs +22 -6
- package/src/runtime/agent/orchestrator/providers/antigravity-response.mjs +15 -4
- package/src/runtime/agent/orchestrator/providers/antigravity-stream.mjs +17 -2
- package/src/runtime/agent/orchestrator/providers/antigravity-transport.mjs +19 -2
- package/src/runtime/agent/orchestrator/providers/codex-client-meta.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/cursor-wire-normalization.mjs +10 -4
- package/src/runtime/agent/orchestrator/providers/cursor-wire-protobuf.mjs +10 -217
- package/src/runtime/agent/orchestrator/providers/cursor.mjs +7 -0
- package/src/runtime/agent/orchestrator/providers/devin-auth.mjs +409 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-families.mjs +187 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-identity.mjs +342 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-models.mjs +541 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-protobuf.mjs +305 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-request.mjs +558 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-schema.mjs +880 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-session.mjs +190 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-tool-args.mjs +351 -0
- package/src/runtime/agent/orchestrator/providers/devin-wire-transport.mjs +560 -0
- package/src/runtime/agent/orchestrator/providers/devin.mjs +491 -0
- package/src/runtime/agent/orchestrator/providers/effort-configuration.mjs +3 -0
- package/src/runtime/agent/orchestrator/providers/gemini-output-limit.mjs +46 -0
- package/src/runtime/agent/orchestrator/providers/gemini-reasoning-relay.mjs +30 -0
- package/src/runtime/agent/orchestrator/providers/gemini-request-body.mjs +7 -11
- package/src/runtime/agent/orchestrator/providers/gemini-retry-policy.mjs +61 -22
- package/src/runtime/agent/orchestrator/providers/gemini-sdk-request.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/gemini-stream.mjs +71 -4
- package/src/runtime/agent/orchestrator/providers/gemini.mjs +25 -2
- package/src/runtime/agent/orchestrator/providers/grok-client-version.mjs +1 -1
- package/src/runtime/agent/orchestrator/providers/lib/anthropic-request-utils.mjs +96 -5
- package/src/runtime/agent/orchestrator/providers/lib/tail-reminder-split.mjs +23 -5
- package/src/runtime/agent/orchestrator/providers/oauth-credential-probes.mjs +17 -0
- package/src/runtime/agent/orchestrator/providers/oauth-usage.mjs +39 -3
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream/stream-state.mjs +3 -1
- package/src/runtime/agent/orchestrator/providers/openai-compat-chat-stream.mjs +2 -0
- package/src/runtime/agent/orchestrator/providers/openai-error-contract.mjs +6 -1
- package/src/runtime/agent/orchestrator/providers/opencode-go-gemini.mjs +1 -0
- package/src/runtime/agent/orchestrator/providers/provider-availability.mjs +19 -0
- package/src/runtime/agent/orchestrator/providers/registry.mjs +17 -3
- package/src/runtime/agent/orchestrator/providers/wire-protobuf-codec.mjs +368 -0
- package/src/runtime/agent/orchestrator/runtime-core/builtin-features.mjs +2 -0
- package/src/runtime/agent/orchestrator/runtime-core/orchestration.mjs +1 -1
- package/src/runtime/agent/orchestrator/runtime-core/reaction-tool-defs.mjs +133 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-catalog-data.mjs +3 -0
- package/src/runtime/agent/orchestrator/runtime-core/tool-defs.mjs +23 -5
- package/src/runtime/agent/orchestrator/runtime-core/tool-profile.mjs +35 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/agents.mjs +57 -10
- package/src/runtime/agent/orchestrator/runtime-core/workflow/context.mjs +9 -6
- package/src/runtime/agent/orchestrator/runtime-core/workflow-ids.mjs +1 -1
- package/src/runtime/agent/orchestrator/session/agent-loop.mjs +18 -0
- package/src/runtime/agent/orchestrator/session/agent-room.d.mts +0 -3
- package/src/runtime/agent/orchestrator/session/agent-room.mjs +10 -4
- package/src/runtime/agent/orchestrator/session/compact/runner.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/eager-dispatch.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/human-gate/gate.mjs +36 -4
- package/src/runtime/agent/orchestrator/session/human-gate/outbound-policy.mjs +6 -0
- package/src/runtime/agent/orchestrator/session/human-gate/store.mjs +15 -3
- package/src/runtime/agent/orchestrator/session/loop/assistant-commit.mjs +8 -0
- package/src/runtime/agent/orchestrator/session/loop/loop-state.mjs +8 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn/segments.mjs +4 -1
- package/src/runtime/agent/orchestrator/session/loop/no-tool-turn.mjs +50 -2
- package/src/runtime/agent/orchestrator/session/loop/send-phase.mjs +3 -0
- package/src/runtime/agent/orchestrator/session/loop/tool-exec/before-hook.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/loop/tool-phase.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/loop/turn-limits.mjs +60 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-commit.mjs +2 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-loop-options.mjs +14 -0
- package/src/runtime/agent/orchestrator/session/manager/ask-turn-settle.mjs +2 -1
- package/src/runtime/agent/orchestrator/session/manager/session-tool-surface.mjs +13 -0
- package/src/runtime/agent/orchestrator/session/message-ids.mjs +5 -3
- package/src/runtime/agent/orchestrator/session/message-reactions.mjs +89 -0
- package/src/runtime/agent/orchestrator/session/message-reactions.test-support.mjs +75 -0
- package/src/runtime/agent/orchestrator/session/routine-result.d.mts +0 -2
- package/src/runtime/agent/orchestrator/session/routine-result.mjs +11 -2
- package/src/runtime/agent/orchestrator/session/send-with-recovery.mjs +20 -2
- package/src/runtime/agent/orchestrator/session/store-agent-worker-header-cache.mjs +85 -0
- package/src/runtime/agent/orchestrator/session/store-agent-worker-rows.mjs +125 -12
- package/src/runtime/agent/orchestrator/session/tail-reminder-rules.mjs +11 -5
- package/src/runtime/agent/orchestrator/session/tool-batch/state.mjs +4 -0
- package/src/runtime/agent/orchestrator/session/tool-batch.mjs +5 -0
- package/src/runtime/agent/orchestrator/session/transcript-restore/restore.mjs +7 -1
- package/src/runtime/channels/lib/schedule-errors.mjs +51 -0
- package/src/runtime/channels/lib/scheduler.mjs +109 -14
- package/src/runtime/channels/lib/schedules-db.mjs +49 -0
- package/src/runtime/channels/lib/tool-dispatch.mjs +13 -0
- package/src/runtime/channels/lib/worker-main.mjs +9 -0
- package/src/runtime/office/com/com-adapter.mjs +17 -1
- package/src/runtime/office/com/office-com-host.ps1 +51 -1
- package/src/runtime/office/pdf/cfb-fixture.mjs +328 -0
- package/src/runtime/office/pdf/cfb-protection.mjs +311 -0
- package/src/runtime/office/pdf/document-preview.mjs +326 -8
- package/src/runtime/office/pdf/ooxml-crypto.mjs +469 -0
- package/src/runtime/office/pdf/ooxml-key-worker.mjs +14 -0
- package/src/runtime/office/portable/portable-soffice.mjs +45 -5
- package/src/runtime/shared/bot-hops.mjs +62 -2
- package/src/runtime/shared/config.mjs +49 -22
- package/src/runtime/shared/connector-catalog.d.mts +4 -2
- package/src/runtime/shared/connector-catalog.mjs +16 -8
- package/src/runtime/shared/developer-options.mjs +32 -1
- package/src/runtime/shared/google-oauth-client.generated.json +4 -0
- package/src/runtime/shared/google-oauth-client.mjs +34 -9
- package/src/runtime/shared/llm/anthropic-betas.mjs +7 -0
- package/src/runtime/shared/llm/anthropic-thinking-contract.mjs +12 -0
- package/src/runtime/shared/llm/provider-catalog-registry.mjs +1 -0
- package/src/runtime/shared/llm/well-formed.mjs +66 -0
- package/src/runtime/shared/provider-accounts.mjs +224 -58
- package/src/runtime/shared/provider-api-key.mjs +19 -8
- package/src/runtime/shared/routine-trigger.mjs +42 -0
- package/src/runtime/shared/tool-execution-contract.mjs +2 -0
- package/src/runtime/shared/transcript-metadata.mjs +38 -0
- package/src/runtime/shared/user-data-guard.mjs +30 -2
- package/src/runtime/shared/worktrees/activity-gate.mjs +12 -5
- package/src/session-runtime/agent-home-delivery.mjs +57 -13
- package/src/session-runtime/agent-room-delivery.mjs +28 -1
- package/src/session-runtime/agent-task-sessions.mjs +292 -79
- package/src/session-runtime/boot/begin.mjs +3 -2
- package/src/session-runtime/boot/tools.mjs +2 -0
- package/src/session-runtime/bot-chain.mjs +32 -0
- package/src/session-runtime/bot-status.mjs +7 -4
- package/src/session-runtime/channel-config-api.mjs +63 -17
- package/src/session-runtime/internal-tool-executor/reaction-tool.mjs +45 -0
- package/src/session-runtime/internal-tool-executor/workspace-tools.mjs +72 -5
- package/src/session-runtime/internal-tool-executor.mjs +4 -0
- package/src/session-runtime/mcp-glue/server-catalog.mjs +7 -1
- package/src/session-runtime/mixy-heartbeat.mjs +807 -0
- package/src/session-runtime/model-route/route-tuning.mjs +10 -6
- package/src/session-runtime/owned-automation-run.mjs +33 -12
- package/src/session-runtime/provider-auth/login.mjs +7 -0
- package/src/session-runtime/provider-models/row-hydration.mjs +13 -2
- package/src/session-runtime/routine-home-turn.mjs +33 -6
- package/src/session-runtime/schedule-session-run.mjs +7 -3
- package/src/session-runtime/services/agent-tool/spawn-flow/spawn-plan.mjs +8 -12
- package/src/session-runtime/services/channel-admin.mjs +66 -18
- package/src/session-runtime/services/channel-worker.mjs +1 -1
- package/src/session-runtime/services/provider-admin.mjs +128 -25
- package/src/session-runtime/services/schedule-access.mjs +14 -0
- package/src/session-runtime/services/usage-dashboard-model.mjs +1 -0
- package/src/session-runtime/session-create/session-options.mjs +7 -4
- package/src/session-runtime/settings-system-api.mjs +16 -1
- package/src/session-runtime/setup-tool/executor.mjs +49 -14
- package/src/session-runtime/setup-tool/extended-actions.mjs +29 -3
- package/src/session-runtime/setup-tool/settings-contract.mjs +65 -4
- package/src/session-runtime/setup-tool/tool-defs.mjs +30 -3
- package/src/session-runtime/task-session-route.mjs +99 -0
- package/src/session-runtime/tool-policy/policy-stage.mjs +5 -2
- package/src/session-runtime/tool-policy/surface-helpers.mjs +2 -3
- package/src/session-runtime/tool-surface.mjs +4 -0
- package/src/session-runtime/workflow-agents-api/agent-editor.mjs +98 -21
- package/src/session-runtime/workflow-agents-api/workflow-packs.mjs +6 -1
- package/src/session-runtime/workspace/transitions.mjs +10 -2
- package/src/standalone/daemon-session-control.mjs +88 -20
- package/src/standalone/daemon.mjs +8 -0
- package/src/standalone/session-protocol.mjs +5 -0
- package/src/standalone/session-service/agent-tree/agent-cancel.mjs +6 -2
- package/src/standalone/session-service/session-calls/session-turns.mjs +6 -0
- package/src/standalone/session-service.mjs +13 -0
- package/src/standalone/session-tool-output.mjs +8 -5
- package/src/tui/app/model-options.mjs +2 -0
- package/src/tui/dist/index.mjs +24 -2
- package/src/tui/session/notice-surface.mjs +17 -1
- package/src/tui/session/session-api/integrations.mjs +1 -0
- package/src/tui/session/session-api/lifecycle.mjs +8 -0
- package/src/tui/session/session-api/settings.mjs +14 -2
- package/src/tui/session/turn-stream.mjs +17 -1
- package/src/tui/session/turn.mjs +22 -2
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
// Lowers a Mixdog transcript, system prompt and tool list into one Devin
|
|
2
|
+
// GetChatMessageRequest (Cascade request type), the way the native CLI
|
|
3
|
+
// builds it.
|
|
4
|
+
//
|
|
5
|
+
// Wire roles: USER for user/developer turns (and mid-history system notes),
|
|
6
|
+
// SYSTEM (the Cascade "bot" channel) for assistant turns, TOOL for tool
|
|
7
|
+
// results. Leading system messages become the request `prompt`.
|
|
8
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
9
|
+
import { DEVIN_ENUMS, encodeDevinMessage } from './devin-wire-protobuf.mjs';
|
|
10
|
+
import { DEVIN_DEFAULT_MAX_OUTPUT_TOKENS } from './devin-wire-models.mjs';
|
|
11
|
+
import { degradeMediaParts, normalizeContentForGeminiParts } from './media-normalization.mjs';
|
|
12
|
+
import { devinDemotedThinking, isDevinGeminiModel } from './devin-wire-identity.mjs';
|
|
13
|
+
import { devinGoogleToolSchema, devinToolWireSchema } from './devin-wire-schema.mjs';
|
|
14
|
+
import { providerReplayItems } from './lib/provider-replay.mjs';
|
|
15
|
+
|
|
16
|
+
export const DEVIN_PROVIDER_ID = 'devin-oauth';
|
|
17
|
+
// Replayed tool-call ids reach the backend serving the model; OpenAI-routed
|
|
18
|
+
// models refuse ids over 40 chars or outside [A-Za-z0-9_-].
|
|
19
|
+
export const DEVIN_TOOL_CALL_ID_MAX_LENGTH = 40;
|
|
20
|
+
// The providerReplay item a Devin assistant turn carries (see devin.mjs).
|
|
21
|
+
export const DEVIN_REPLAY_ITEM_TYPE = 'devin_assistant';
|
|
22
|
+
// Result text for a tool call whose result never committed.
|
|
23
|
+
export const DEVIN_MISSING_TOOL_RESULT = 'No result provided';
|
|
24
|
+
// An opaque invalid_argument on a request whose compactable history is at
|
|
25
|
+
// least this large is treated as a context overflow.
|
|
26
|
+
export const DEVIN_LARGE_HISTORY_RECOVERY_BYTES = 512 * 1024;
|
|
27
|
+
|
|
28
|
+
const { ChatMessageSource, ChatMessageRequestType, ConversationalPlannerMode, CacheControlType } = DEVIN_ENUMS;
|
|
29
|
+
// Cascade has no ASSISTANT source: the model's own turns ride the SYSTEM channel.
|
|
30
|
+
export const DEVIN_ASSISTANT_SOURCE = ChatMessageSource.SYSTEM;
|
|
31
|
+
|
|
32
|
+
// Completion knobs the native CLI sends with every Cascade turn.
|
|
33
|
+
const CLI_TOP_K = 40;
|
|
34
|
+
const CLI_TOP_P = 0.95;
|
|
35
|
+
const CLI_MAX_NEWLINES = 400;
|
|
36
|
+
|
|
37
|
+
/** The leading 128 bits of sha256(`seed`) in the 8-4-4-4-12 UUID layout. */
|
|
38
|
+
export function devinDeterministicUuid(seed) {
|
|
39
|
+
const hex = createHash('sha256').update(String(seed)).digest('hex');
|
|
40
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20, 32)}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** A foreign tool-call id on the Devin wire: unsupported characters to `_`, capped. */
|
|
44
|
+
export function normalizeDevinToolCallId(id) {
|
|
45
|
+
return String(id)
|
|
46
|
+
.replace(/[^a-zA-Z0-9_-]/g, '_')
|
|
47
|
+
.slice(0, DEVIN_TOOL_CALL_ID_MAX_LENGTH);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Tool-call ids a Responses-API turn mints can be composite (`call_id|item_id`).
|
|
51
|
+
// A turn is Responses-origin when its replay record came from a Responses
|
|
52
|
+
// transport (OpenAI/Codex, xAI, or a compat gateway's Responses wire).
|
|
53
|
+
function isResponsesOrigin(message) {
|
|
54
|
+
const owner = message?.providerReplay?.provider;
|
|
55
|
+
return (
|
|
56
|
+
owner === 'openai-responses' ||
|
|
57
|
+
owner === 'xai-responses' ||
|
|
58
|
+
(typeof owner === 'string' && owner.startsWith('compat-responses:'))
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** The call_id half of a composite Responses id; an id with no non-empty first half stays whole. */
|
|
63
|
+
export function responsesCallComponent(id) {
|
|
64
|
+
const value = String(id);
|
|
65
|
+
const pipe = value.indexOf('|');
|
|
66
|
+
return pipe <= 0 ? value : value.slice(0, pipe);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function duplicateId(id, index) {
|
|
70
|
+
const suffix = `_dup${index}`;
|
|
71
|
+
if (id.length + suffix.length <= DEVIN_TOOL_CALL_ID_MAX_LENGTH) return `${id}${suffix}`;
|
|
72
|
+
return `${id.slice(0, Math.max(0, DEVIN_TOOL_CALL_ID_MAX_LENGTH - suffix.length))}${suffix}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Text plus inline images of one content value; parts concatenate as written.
|
|
76
|
+
// Images are sent only to a vision model; otherwise every media part degrades
|
|
77
|
+
// to its fixed text form.
|
|
78
|
+
function loweredContent(content, vision) {
|
|
79
|
+
if (typeof content === 'string') return { text: content, images: [] };
|
|
80
|
+
const source = !vision && Array.isArray(content) ? degradeMediaParts(content) : content;
|
|
81
|
+
let text = '';
|
|
82
|
+
const images = [];
|
|
83
|
+
for (const part of normalizeContentForGeminiParts(source)) {
|
|
84
|
+
if (part.inlineData && String(part.inlineData.mimeType).startsWith('image/')) {
|
|
85
|
+
if (vision) images.push({ base64Data: part.inlineData.data, mimeType: part.inlineData.mimeType });
|
|
86
|
+
} else if (part.fileData?.fileUri) {
|
|
87
|
+
text += `[image: ${part.fileData.fileUri}]`;
|
|
88
|
+
} else if (typeof part.text === 'string') {
|
|
89
|
+
text += part.text;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return { text, images };
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/** The Devin replay record of an assistant turn (any model), or null. */
|
|
96
|
+
export function devinReplayItem(message) {
|
|
97
|
+
return (
|
|
98
|
+
providerReplayItems(message, DEVIN_PROVIDER_ID)?.find((entry) => entry?.type === DEVIN_REPLAY_ITEM_TYPE) || null
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Same-model turns: produced by this provider for the requested model uid.
|
|
103
|
+
function sameModelReplay(message, model) {
|
|
104
|
+
const item = devinReplayItem(message);
|
|
105
|
+
return item && item.model === model ? item : null;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const textsOf = (parts, type) =>
|
|
109
|
+
(Array.isArray(parts) ? parts : []).filter((part) => part?.type === type).map((part) => part.text);
|
|
110
|
+
|
|
111
|
+
const thinkingTexts = (blocks) =>
|
|
112
|
+
(Array.isArray(blocks) ? blocks : []).filter((block) => block?.type === 'thinking').map((block) => block.thinking);
|
|
113
|
+
|
|
114
|
+
const reasoningItemTexts = (items) =>
|
|
115
|
+
(Array.isArray(items) ? items : [])
|
|
116
|
+
.filter((item) => item?.type === 'reasoning' || (item && item.type === undefined && item.summary))
|
|
117
|
+
.map((item) => {
|
|
118
|
+
const summary = textsOf(item.summary, 'summary_text');
|
|
119
|
+
return (summary.length ? summary : textsOf(item.content, 'reasoning_text')).join('\n');
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
function providerReplayReasoning(message) {
|
|
123
|
+
const replay = message.providerReplay;
|
|
124
|
+
const items = Array.isArray(replay?.items) ? replay.items : [];
|
|
125
|
+
if (replay?.provider === 'anthropic') return thinkingTexts(items);
|
|
126
|
+
if (replay?.provider === 'gemini' || replay?.provider === 'antigravity') {
|
|
127
|
+
return items.filter((part) => part?.thought === true).map((part) => part.text);
|
|
128
|
+
}
|
|
129
|
+
if (isResponsesOrigin(message)) return reasoningItemTexts(items);
|
|
130
|
+
return [];
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const nonBlank = (blocks) => blocks.filter((text) => typeof text === 'string' && text.trim());
|
|
134
|
+
|
|
135
|
+
// The reasoning blocks another model's turn carries. Mixdog may keep one
|
|
136
|
+
// trace in several representations, so the first one that holds any reasoning
|
|
137
|
+
// wins and the rest are never added. Block-shaped sources come first, so each
|
|
138
|
+
// block is demoted on its own: a Devin replay record of another model, the
|
|
139
|
+
// provider replay (Anthropic thinking blocks, Gemini thought parts, Responses
|
|
140
|
+
// reasoning summaries or reasoning text), the ordered Anthropic
|
|
141
|
+
// `assistantBlocks`, the standalone `thinkingBlocks`, Responses
|
|
142
|
+
// `reasoningItems`; the flattened `reasoningContent` and plain `reasoning`
|
|
143
|
+
// strings are the fallback. Signatures and encrypted payloads never carry over.
|
|
144
|
+
function foreignReasoningBlocks(message) {
|
|
145
|
+
const sources = [
|
|
146
|
+
() => {
|
|
147
|
+
const devin = devinReplayItem(message);
|
|
148
|
+
return devin ? [devin.thinking] : [];
|
|
149
|
+
},
|
|
150
|
+
() => providerReplayReasoning(message),
|
|
151
|
+
() => thinkingTexts(message.assistantBlocks),
|
|
152
|
+
() => thinkingTexts(message.thinkingBlocks),
|
|
153
|
+
() => reasoningItemTexts(message.reasoningItems),
|
|
154
|
+
() => [message.reasoningContent],
|
|
155
|
+
() => [message.reasoning],
|
|
156
|
+
];
|
|
157
|
+
for (const source of sources) {
|
|
158
|
+
const blocks = nonBlank(source());
|
|
159
|
+
if (blocks.length) return blocks;
|
|
160
|
+
}
|
|
161
|
+
return [];
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Reasoning of another model replays as text in the target's thinking form,
|
|
165
|
+
// each block followed by a line break; a block with nothing after it is
|
|
166
|
+
// trimmed first. Blank blocks are dropped.
|
|
167
|
+
function assistantPrompt(message, model, messageId) {
|
|
168
|
+
const native = sameModelReplay(message, model);
|
|
169
|
+
const demoted = native
|
|
170
|
+
? []
|
|
171
|
+
: foreignReasoningBlocks(message)
|
|
172
|
+
.filter((thinking) => typeof thinking === 'string' && thinking.trim())
|
|
173
|
+
.map((thinking) => devinDemotedThinking(model, thinking));
|
|
174
|
+
const text = loweredContent(message.content, false).text;
|
|
175
|
+
let prompt = demoted.map((block) => `${block}\n`).join('') + text;
|
|
176
|
+
if (demoted.length && !text)
|
|
177
|
+
prompt = `${demoted
|
|
178
|
+
.slice(0, -1)
|
|
179
|
+
.map((block) => `${block}\n`)
|
|
180
|
+
.join('')}${demoted.at(-1).trimEnd()}\n`;
|
|
181
|
+
const toolCalls = (message.toolCalls || []).map((call) => ({
|
|
182
|
+
id: String(call.id),
|
|
183
|
+
name: call.name,
|
|
184
|
+
argumentsJson: typeof call.arguments === 'string' ? call.arguments : JSON.stringify(call.arguments ?? {}),
|
|
185
|
+
}));
|
|
186
|
+
const thinking = native?.thinking || '';
|
|
187
|
+
const signature = native?.signature || '';
|
|
188
|
+
const signatureType = (signature && native?.signatureType) || '';
|
|
189
|
+
if (!prompt && !thinking && !signature && !toolCalls.length) return null;
|
|
190
|
+
return {
|
|
191
|
+
// Native assistant ids are the response's own message id.
|
|
192
|
+
messageId: native?.messageId || messageId,
|
|
193
|
+
source: DEVIN_ASSISTANT_SOURCE,
|
|
194
|
+
prompt,
|
|
195
|
+
...(thinking ? { thinking } : {}),
|
|
196
|
+
...(signature ? { signature } : {}),
|
|
197
|
+
// The signature type the stream reported for that signature, echoed back.
|
|
198
|
+
...(signatureType ? { signatureType } : {}),
|
|
199
|
+
toolCalls,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Tool-call ids as the wire carries them: a same-model turn keeps its ids
|
|
205
|
+
* verbatim; any other turn's ids are normalized (normalizeDevinToolCallId).
|
|
206
|
+
* A Responses-API turn's composite id (`call_id|item_id`) keeps only its
|
|
207
|
+
* call_id first; ids of every other origin keep all their segments.
|
|
208
|
+
* A repeated id then gets a `_dupN` suffix and the next unanswered result of
|
|
209
|
+
* that id follows it, so every call/result pair stays distinct.
|
|
210
|
+
*/
|
|
211
|
+
export function devinWireToolCallIds(messages, model) {
|
|
212
|
+
// Exact original id → wire id, for every call whose id changed.
|
|
213
|
+
const normalized = new Map();
|
|
214
|
+
// call_id component of every Responses-origin call → its wire id, recorded
|
|
215
|
+
// even when the id did not change: a composite result (`call_A|item`) of a
|
|
216
|
+
// plain call `call_A` resolves through it. Opaque ids of other origins pair
|
|
217
|
+
// by exact id only, so their `|` segments stay distinct.
|
|
218
|
+
const responsesComponents = new Map();
|
|
219
|
+
// Concrete `|`-bearing call ids of every other origin, same-model turns
|
|
220
|
+
// included: opaque correlation tokens that only ever pair by exact id, even
|
|
221
|
+
// when their first segment matches an earlier Responses call.
|
|
222
|
+
const opaqueCompositeIds = new Set();
|
|
223
|
+
for (const message of messages) {
|
|
224
|
+
if (message?.role !== 'assistant' || isResponsesOrigin(message)) continue;
|
|
225
|
+
for (const call of message.toolCalls || []) {
|
|
226
|
+
const id = String(call.id);
|
|
227
|
+
if (id.includes('|')) opaqueCompositeIds.add(id);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const projected = messages.map((message) => {
|
|
231
|
+
if (message?.role === 'tool') {
|
|
232
|
+
const id = String(message.toolCallId);
|
|
233
|
+
const viaComponent =
|
|
234
|
+
id.includes('|') && !opaqueCompositeIds.has(id)
|
|
235
|
+
? responsesComponents.get(responsesCallComponent(id))
|
|
236
|
+
: undefined;
|
|
237
|
+
const wire = normalized.get(id) ?? viaComponent;
|
|
238
|
+
return wire && wire !== id ? { ...message, toolCallId: wire } : message;
|
|
239
|
+
}
|
|
240
|
+
if (message?.role !== 'assistant' || !message.toolCalls?.length || sameModelReplay(message, model)) return message;
|
|
241
|
+
const responses = isResponsesOrigin(message);
|
|
242
|
+
let changed = false;
|
|
243
|
+
const toolCalls = message.toolCalls.map((call) => {
|
|
244
|
+
const id = String(call.id);
|
|
245
|
+
const wire = normalizeDevinToolCallId(responses ? responsesCallComponent(id) : id);
|
|
246
|
+
if (responses) responsesComponents.set(responsesCallComponent(id), wire);
|
|
247
|
+
if (wire === id) return call;
|
|
248
|
+
normalized.set(id, wire);
|
|
249
|
+
changed = true;
|
|
250
|
+
return { ...call, id: wire };
|
|
251
|
+
});
|
|
252
|
+
return changed ? { ...message, toolCalls } : message;
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
const seen = new Map();
|
|
256
|
+
const pending = new Map();
|
|
257
|
+
return projected.map((message) => {
|
|
258
|
+
if (message?.role === 'tool') {
|
|
259
|
+
const id = String(message.toolCallId);
|
|
260
|
+
const queue = pending.get(id);
|
|
261
|
+
if (!queue?.length) return message;
|
|
262
|
+
const replacement = queue.shift();
|
|
263
|
+
if (!queue.length) pending.delete(id);
|
|
264
|
+
return replacement ? { ...message, toolCallId: replacement } : message;
|
|
265
|
+
}
|
|
266
|
+
if (message?.role !== 'assistant' || !message.toolCalls?.length) return message;
|
|
267
|
+
const touched = new Set();
|
|
268
|
+
let changed = false;
|
|
269
|
+
const toolCalls = message.toolCalls.map((call) => {
|
|
270
|
+
const id = String(call.id);
|
|
271
|
+
// A later turn re-emitting an id takes over its pending results.
|
|
272
|
+
if (!touched.has(id)) {
|
|
273
|
+
touched.add(id);
|
|
274
|
+
pending.delete(id);
|
|
275
|
+
}
|
|
276
|
+
const queue = pending.get(id) || [];
|
|
277
|
+
pending.set(id, queue);
|
|
278
|
+
const previous = seen.get(id) || 0;
|
|
279
|
+
if (previous === 0) {
|
|
280
|
+
seen.set(id, 1);
|
|
281
|
+
queue.push(undefined);
|
|
282
|
+
return call;
|
|
283
|
+
}
|
|
284
|
+
let index = previous;
|
|
285
|
+
let replacement = duplicateId(id, index);
|
|
286
|
+
while (seen.has(replacement)) replacement = duplicateId(id, ++index);
|
|
287
|
+
seen.set(id, index + 1);
|
|
288
|
+
seen.set(replacement, 1);
|
|
289
|
+
queue.push(replacement);
|
|
290
|
+
changed = true;
|
|
291
|
+
return { ...call, id: replacement };
|
|
292
|
+
});
|
|
293
|
+
return changed ? { ...message, toolCalls } : message;
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function toolResultTexts(content) {
|
|
298
|
+
if (typeof content === 'string') return content.trim() ? [content] : [];
|
|
299
|
+
if (!Array.isArray(content)) return [];
|
|
300
|
+
return content
|
|
301
|
+
.filter((part) => part?.type === 'text' && typeof part.text === 'string' && part.text.trim())
|
|
302
|
+
.map((part) => part.text);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Tool-call pairing on the wire transcript: every assistant tool call is
|
|
307
|
+
* answered right after its turn by exactly one result. A result that arrives
|
|
308
|
+
* later (after other messages) is pulled forward into that slot; a call with
|
|
309
|
+
* no result gets an error result ("No result provided", or "aborted" for an
|
|
310
|
+
* errored/aborted turn). A duplicate result is dropped. A result whose call
|
|
311
|
+
* is gone (folded away by compaction) survives as a user note of its text,
|
|
312
|
+
* unless a call window is still open, in which case it is dropped.
|
|
313
|
+
*/
|
|
314
|
+
export function devinPairedTranscript(messages) {
|
|
315
|
+
const realResults = new Map();
|
|
316
|
+
const liveCallIds = new Set();
|
|
317
|
+
messages.forEach((message, index) => {
|
|
318
|
+
if (message?.role === 'tool') {
|
|
319
|
+
const id = String(message.toolCallId);
|
|
320
|
+
if (!realResults.has(id)) realResults.set(id, []);
|
|
321
|
+
realResults.get(id).push({ index, message, consumed: false });
|
|
322
|
+
} else if (message?.role === 'assistant') {
|
|
323
|
+
for (const call of message.toolCalls || []) liveCallIds.add(String(call.id));
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
const takeResult = (id, afterIndex) => {
|
|
327
|
+
for (const entry of realResults.get(id) || []) {
|
|
328
|
+
if (entry.consumed || entry.index <= afterIndex) continue;
|
|
329
|
+
entry.consumed = true;
|
|
330
|
+
return entry.message;
|
|
331
|
+
}
|
|
332
|
+
return undefined;
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
const out = [];
|
|
336
|
+
const resolved = new Set();
|
|
337
|
+
let pending = [];
|
|
338
|
+
let pendingStart = -1;
|
|
339
|
+
let aborted = new Map();
|
|
340
|
+
let abortedOpen = false;
|
|
341
|
+
let abortedStart = -1;
|
|
342
|
+
const resolveCalls = (calls, startIndex, fallbackText) => {
|
|
343
|
+
for (const call of calls) {
|
|
344
|
+
const id = String(call.id);
|
|
345
|
+
if (resolved.has(id)) continue;
|
|
346
|
+
out.push(
|
|
347
|
+
takeResult(id, startIndex) || {
|
|
348
|
+
role: 'tool',
|
|
349
|
+
toolCallId: id,
|
|
350
|
+
toolName: call.name,
|
|
351
|
+
content: fallbackText,
|
|
352
|
+
isError: true,
|
|
353
|
+
}
|
|
354
|
+
);
|
|
355
|
+
resolved.add(id);
|
|
356
|
+
}
|
|
357
|
+
};
|
|
358
|
+
const flushPending = () => {
|
|
359
|
+
if (!pending.length) return;
|
|
360
|
+
resolveCalls(pending, pendingStart, DEVIN_MISSING_TOOL_RESULT);
|
|
361
|
+
pending = [];
|
|
362
|
+
};
|
|
363
|
+
const flushAborted = () => {
|
|
364
|
+
if (!abortedOpen) return;
|
|
365
|
+
resolveCalls([...aborted.values()], abortedStart, 'aborted');
|
|
366
|
+
aborted = new Map();
|
|
367
|
+
abortedOpen = false;
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
messages.forEach((message, index) => {
|
|
371
|
+
const role = message?.role;
|
|
372
|
+
if (role === 'assistant') {
|
|
373
|
+
flushPending();
|
|
374
|
+
flushAborted();
|
|
375
|
+
const calls = message.toolCalls || [];
|
|
376
|
+
out.push(message);
|
|
377
|
+
if (message.stopReason === 'error' || message.stopReason === 'aborted') {
|
|
378
|
+
aborted = new Map(calls.map((call) => [String(call.id), call]));
|
|
379
|
+
abortedOpen = true;
|
|
380
|
+
abortedStart = index;
|
|
381
|
+
} else if (calls.length) {
|
|
382
|
+
pending = calls;
|
|
383
|
+
pendingStart = index;
|
|
384
|
+
}
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
387
|
+
if (role !== 'tool') {
|
|
388
|
+
flushPending();
|
|
389
|
+
flushAborted();
|
|
390
|
+
out.push(message);
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const id = String(message.toolCallId);
|
|
394
|
+
if (resolved.has(id)) return;
|
|
395
|
+
if (aborted.has(id) || pending.some((call) => String(call.id) === id)) {
|
|
396
|
+
aborted.delete(id);
|
|
397
|
+
resolved.add(id);
|
|
398
|
+
out.push(message);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
if (liveCallIds.has(id)) return;
|
|
402
|
+
if (pending.some((call) => !resolved.has(String(call.id))) || aborted.size > 0) return;
|
|
403
|
+
const texts = toolResultTexts(message.content);
|
|
404
|
+
if (!texts.length) return;
|
|
405
|
+
const errorAttr = message.isError === true || message.toolKind === 'error' ? ' is-error="true"' : '';
|
|
406
|
+
const toolName = message.toolName ?? message.name ?? '';
|
|
407
|
+
out.push({
|
|
408
|
+
role: 'user',
|
|
409
|
+
content: `<stale-tool-result tool="${toolName}" id="${id}"${errorAttr}>\n${texts.join('\n')}\n</stale-tool-result>`,
|
|
410
|
+
});
|
|
411
|
+
});
|
|
412
|
+
flushPending();
|
|
413
|
+
flushAborted();
|
|
414
|
+
return out;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function chatPrompts(messages, { model, vision, cascadeId }) {
|
|
418
|
+
const prompts = [];
|
|
419
|
+
messages.forEach((message, index) => {
|
|
420
|
+
const role = message?.role;
|
|
421
|
+
const seed = `${cascadeId}\0${index}\0${role}`;
|
|
422
|
+
if (role === 'assistant') {
|
|
423
|
+
const prompt = assistantPrompt(message, model, devinDeterministicUuid(`${cascadeId}\0${index}\0assistant`));
|
|
424
|
+
if (prompt) prompts.push(prompt);
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
if (role === 'tool') {
|
|
428
|
+
const { text, images } = loweredContent(message.content, vision);
|
|
429
|
+
prompts.push({
|
|
430
|
+
messageId: devinDeterministicUuid(`${cascadeId}\0${index}\0tool\0${message.toolCallId}`),
|
|
431
|
+
source: ChatMessageSource.TOOL,
|
|
432
|
+
toolCallId: String(message.toolCallId),
|
|
433
|
+
toolResultIsError: message.toolKind === 'error' || message.isError === true,
|
|
434
|
+
prompt: text,
|
|
435
|
+
images,
|
|
436
|
+
});
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
const { text, images } = loweredContent(message?.content, vision);
|
|
440
|
+
prompts.push({ messageId: devinDeterministicUuid(seed), source: ChatMessageSource.USER, prompt: text, images });
|
|
441
|
+
});
|
|
442
|
+
return prompts;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// The current turn, read off the conversation as Mixdog holds it (before
|
|
446
|
+
// pairing adds synthetic results or stale-result notes): the trailing user
|
|
447
|
+
// prompt, plus the user/developer messages right before a trailing developer
|
|
448
|
+
// message. Everything earlier is history that compaction can shrink.
|
|
449
|
+
function activeTailCount(messages) {
|
|
450
|
+
const userRole = (message) => message?.role === 'user' || message?.role === 'developer';
|
|
451
|
+
const last = messages.at(-1);
|
|
452
|
+
if (!userRole(last)) return 0;
|
|
453
|
+
if (last.role === 'user') return 1;
|
|
454
|
+
let count = 1;
|
|
455
|
+
for (let index = messages.length - 2; index >= 0 && userRole(messages[index]); index -= 1) count += 1;
|
|
456
|
+
return count;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/** Wire bytes of the request's compactable history (every prompt before the active turn). */
|
|
460
|
+
export function devinHistoryBytes(request, activeTail) {
|
|
461
|
+
const prompts = request.chatMessagePrompts || [];
|
|
462
|
+
return encodeDevinMessage('GetChatMessageRequest', {
|
|
463
|
+
chatMessagePrompts: activeTail > 0 ? prompts.slice(0, -activeTail) : prompts,
|
|
464
|
+
}).length;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/**
|
|
468
|
+
* The prompt a model router scores: the latest user/developer turn alone,
|
|
469
|
+
* with no message id (the chat request that follows mints it).
|
|
470
|
+
*/
|
|
471
|
+
export function devinRouterPrompt(messages, { vision = false } = {}) {
|
|
472
|
+
const message = (Array.isArray(messages) ? messages : []).findLast(
|
|
473
|
+
(entry) => entry?.role === 'user' || entry?.role === 'developer'
|
|
474
|
+
);
|
|
475
|
+
if (!message) return undefined;
|
|
476
|
+
const { text, images } = loweredContent(message.content, vision);
|
|
477
|
+
return { messageId: '', source: ChatMessageSource.USER, prompt: text, images };
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function toolDefinitions(tools, model, chatModelUid) {
|
|
481
|
+
if (!tools?.length) return [];
|
|
482
|
+
// Gemini backends (the catalog model or the concrete wire uid, e.g. a
|
|
483
|
+
// router's MODEL_GOOGLE_GEMINI_* assignment) apply Google's schema rules.
|
|
484
|
+
const google = isDevinGeminiModel(model, chatModelUid);
|
|
485
|
+
return tools.map((tool) => {
|
|
486
|
+
const schema = devinToolWireSchema(tool.inputSchema);
|
|
487
|
+
return {
|
|
488
|
+
name: tool.name,
|
|
489
|
+
description: tool.description || '',
|
|
490
|
+
jsonSchemaString: JSON.stringify(google ? devinGoogleToolSchema(schema) : schema),
|
|
491
|
+
strict: tool.strict === true,
|
|
492
|
+
};
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* The GetChatMessageRequest for one turn.
|
|
498
|
+
* `model` is the catalog model id (replay identity); `chatModelUid` the
|
|
499
|
+
* concrete wire uid (effort route or router assignment, default `model`);
|
|
500
|
+
* `modelAssignmentJwt` the router assignment that authorizes it.
|
|
501
|
+
* `modelRow` is the normalized catalog row of `model` (null when unknown:
|
|
502
|
+
* text-only, sequential tool calls, default output cap).
|
|
503
|
+
* Returns { request, activeTail }: `activeTail` is the number of trailing
|
|
504
|
+
* prompts that belong to the current turn (see devinHistoryBytes).
|
|
505
|
+
*/
|
|
506
|
+
export function buildDevinChatRequest(
|
|
507
|
+
messages,
|
|
508
|
+
{
|
|
509
|
+
model,
|
|
510
|
+
chatModelUid = model,
|
|
511
|
+
modelAssignmentJwt,
|
|
512
|
+
modelRow = null,
|
|
513
|
+
tools = [],
|
|
514
|
+
metadata,
|
|
515
|
+
cascadeId,
|
|
516
|
+
executionId = randomUUID(),
|
|
517
|
+
maxOutputTokens,
|
|
518
|
+
temperature,
|
|
519
|
+
topP,
|
|
520
|
+
stopSequences,
|
|
521
|
+
}
|
|
522
|
+
) {
|
|
523
|
+
const all = Array.isArray(messages) ? messages : [];
|
|
524
|
+
let start = 0;
|
|
525
|
+
while (start < all.length && all[start]?.role === 'system') start += 1;
|
|
526
|
+
const prompt = all
|
|
527
|
+
.slice(0, start)
|
|
528
|
+
.map((message) => loweredContent(message.content, false).text)
|
|
529
|
+
.filter((text) => text.trim())
|
|
530
|
+
.join('\n\n');
|
|
531
|
+
const history = devinPairedTranscript(devinWireToolCallIds(all.slice(start), model));
|
|
532
|
+
const request = {
|
|
533
|
+
metadata,
|
|
534
|
+
prompt,
|
|
535
|
+
chatMessagePrompts: chatPrompts(history, { model, vision: modelRow?.supportsVision === true, cascadeId }),
|
|
536
|
+
chatModelUid,
|
|
537
|
+
...(modelAssignmentJwt ? { modelAssignmentJwt } : {}),
|
|
538
|
+
requestType: ChatMessageRequestType.CASCADE,
|
|
539
|
+
plannerMode: ConversationalPlannerMode.DEFAULT,
|
|
540
|
+
toolChoice: { optionName: 'auto' },
|
|
541
|
+
systemPromptCacheOptions: { type: CacheControlType.EPHEMERAL },
|
|
542
|
+
disableParallelToolCalls: modelRow?.supportsParallelToolCalls !== true,
|
|
543
|
+
cascadeId,
|
|
544
|
+
executionId,
|
|
545
|
+
configuration: {
|
|
546
|
+
numCompletions: 1,
|
|
547
|
+
maxTokens: Number(maxOutputTokens) || Number(modelRow?.maxOutputTokens) || DEVIN_DEFAULT_MAX_OUTPUT_TOKENS,
|
|
548
|
+
maxNewlines: CLI_MAX_NEWLINES,
|
|
549
|
+
temperature: Number.isFinite(Number(temperature)) && temperature !== null ? Number(temperature) : 1,
|
|
550
|
+
topK: CLI_TOP_K,
|
|
551
|
+
// The CLI sends topP as a float32 widened to double.
|
|
552
|
+
topP: Math.fround(Number.isFinite(Number(topP)) && topP !== null ? Number(topP) : CLI_TOP_P),
|
|
553
|
+
stopPatterns: Array.isArray(stopSequences) ? stopSequences.map(String) : [],
|
|
554
|
+
},
|
|
555
|
+
tools: toolDefinitions(tools, model, chatModelUid),
|
|
556
|
+
};
|
|
557
|
+
return { request, activeTail: activeTailCount(all.slice(start)) };
|
|
558
|
+
}
|