@cuongtran001/kanna 1.2.0 → 1.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/dist/client/assets/{arc-BLk1CZKB.js → arc-DXtN3EWJ.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-B01ZQYte.js → architectureDiagram-3BPJPVTR-CIGqW1z-.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-diL6a3cq.js → blockDiagram-GPEHLZMM-BafNS_H6.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-BY1verL8.js → c4Diagram-AAUBKEIU-YdAgRSis.js} +1 -1
- package/dist/client/assets/channel-BEYTrUAm.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-psdZuajw.js → chunk-2J33WTMH-eiP5y5G-.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-CrwQVBc5.js → chunk-4BX2VUAB-CvLGzPMF.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-9-aj4jKO.js → chunk-55IACEB6-Y-S9Fb8A.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-1FNK9_nB.js → chunk-727SXJPM-6sJH1RI9.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-DFhvd_Ek.js → chunk-AQP2D5EJ-hV1r_IXO.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-B7MLrDa7.js → chunk-FMBD7UC4-CC3L28S5.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-D4Df05QE.js → chunk-ND2GUHAM-BZ3czhdH.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-Iq17Dznm.js → chunk-QZHKN3VN-Bjyd6Yr-.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-CvnF5Ud6.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CvnF5Ud6.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-BmaZhtXy.js → cose-bilkent-S5V4N54A-CfxdDghE.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-BCmpfnfP.js → dagre-BM42HDAG-B8CddsbB.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-BIEcKowS.js → diagram-2AECGRRQ-F0yS0fVB.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-CRBABBfv.js → diagram-5GNKFQAL-cW0i0qlh.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BRxUk16N.js → diagram-KO2AKTUF-BzAKMeJT.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-DPBs4xl1.js → diagram-LMA3HP47-qdC4XqIl.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-BE9rgVv8.js → diagram-OG6HWLK6-CGcpi6Dh.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-D3vgA1xJ.js → erDiagram-TEJ5UH35-CxNTDicM.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-Cgu-8XXC.js → flowDiagram-I6XJVG4X-qkGa5TqY.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-CgjXVyTR.js → ganttDiagram-6RSMTGT7-D9mVPoQi.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-zD5D8B-i.js → gitGraphDiagram-PVQCEYII-DA0grAXe.js} +1 -1
- package/dist/client/assets/{index-DBTdhMbJ.js → index-BqUY1Bm4.js} +1 -1
- package/dist/client/assets/index-CLsOWXff.css +32 -0
- package/dist/client/assets/{index-zQLLeAfl.js → index-TU1k6ov6.js} +253 -243
- package/dist/client/assets/{infoDiagram-5YYISTIA-BaFHqT4u.js → infoDiagram-5YYISTIA-CGljtLs3.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-2yAC1br2.js → ishikawaDiagram-YF4QCWOH-CtC0xrmG.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-DacQ-ND5.js → journeyDiagram-JHISSGLW-URLnVZeN.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-Qlbwm3z4.js → kanban-definition-UN3LZRKU-C2Q6aqQh.js} +1 -1
- package/dist/client/assets/{linear-DeafqpgO.js → linear-ByKHtsIx.js} +1 -1
- package/dist/client/assets/{mermaid.core-KYiCPJDj.js → mermaid.core-Dl_f2KLc.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-B1V-T6d3.js → mindmap-definition-RKZ34NQL-CaJ9IDLI.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-DOF9OFRu.js → pieDiagram-4H26LBE5-mmYaf2Oa.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-lH1mB7ko.js → quadrantDiagram-W4KKPZXB-B_PO6OCC.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-BaTsJ_sS.js → requirementDiagram-4Y6WPE33-M4huwJt1.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-Pfxib5iI.js → sankeyDiagram-5OEKKPKP-B0hb1sWh.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BQMEKkBC.js → sequenceDiagram-3UESZ5HK-BAqSptnA.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-CuldNnzp.js → stateDiagram-AJRCARHV-DTNkvPi5.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-CVN3oGTF.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-DP7u0YAg.js → timeline-definition-PNZ67QCA-MgAjHz8Q.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-QlrjpNeQ.js → vennDiagram-CIIHVFJN-DmKoO51W.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-BqdJ_sAM.js → wardley-L42UT6IY-CWcyHnYs.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Wi3kaQ5X.js → wardleyDiagram-YWT4CUSO-BGIGmFP9.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-D-KXMyCG.js → xychartDiagram-2RQKCTM6-D20YIvEl.js} +1 -1
- package/dist/client/index.html +2 -2
- package/package.json +1 -1
- package/src/server/agent-coordinator-types.ts +158 -0
- package/src/server/agent-coordinator.ts +919 -0
- package/src/server/agent-deps-builders.ts +425 -0
- package/src/server/agent.oauth-rotation.test.ts +101 -0
- package/src/server/agent.test.ts +24 -8
- package/src/server/agent.ts +35 -4963
- package/src/server/auto-continue/read-model.test.ts +2 -2
- package/src/server/auto-continue/read-model.ts +4 -1
- package/src/server/claude-autocontinue-commands.test.ts +494 -0
- package/src/server/claude-autocontinue-commands.ts +256 -0
- package/src/server/claude-cancel-handler.test.ts +472 -0
- package/src/server/claude-cancel-handler.ts +241 -0
- package/src/server/claude-chat-management.test.ts +395 -0
- package/src/server/claude-chat-management.ts +251 -0
- package/src/server/claude-harness-stream.test.ts +273 -0
- package/src/server/claude-harness-stream.ts +158 -0
- package/src/server/claude-loop-orch-commands.test.ts +579 -0
- package/src/server/claude-loop-orch-commands.ts +466 -0
- package/src/server/claude-message-normalizer.test.ts +213 -0
- package/src/server/claude-message-normalizer.ts +436 -0
- package/src/server/claude-prompt-helpers.test.ts +248 -0
- package/src/server/claude-prompt-helpers.ts +139 -0
- package/src/server/claude-sdk-queue.test.ts +169 -0
- package/src/server/claude-sdk-queue.ts +82 -0
- package/src/server/claude-send-command.test.ts +414 -0
- package/src/server/claude-send-command.ts +420 -0
- package/src/server/claude-session-config-helpers.test.ts +279 -0
- package/src/server/claude-session-config-helpers.ts +151 -0
- package/src/server/claude-session-config.test.ts +250 -0
- package/src/server/claude-session-config.ts +159 -0
- package/src/server/claude-session-error-handler.test.ts +498 -0
- package/src/server/claude-session-error-handler.ts +361 -0
- package/src/server/claude-session-lifecycle.test.ts +669 -0
- package/src/server/claude-session-lifecycle.ts +283 -0
- package/src/server/claude-session-rebuild.test.ts +224 -0
- package/src/server/claude-session-rebuild.ts +101 -0
- package/src/server/claude-session-runner.test.ts +523 -0
- package/src/server/claude-session-runner.ts +521 -0
- package/src/server/claude-session-spawner.test.ts +401 -0
- package/src/server/claude-session-spawner.ts +401 -0
- package/src/server/claude-session-start.test.ts +205 -0
- package/src/server/claude-session-start.ts +277 -0
- package/src/server/claude-session-state-queries.test.ts +344 -0
- package/src/server/claude-session-state-queries.ts +160 -0
- package/src/server/claude-session-state.ts +104 -0
- package/src/server/claude-slash-commands.test.ts +277 -0
- package/src/server/claude-slash-commands.ts +234 -0
- package/src/server/claude-spawn-helpers.test.ts +221 -0
- package/src/server/claude-spawn-helpers.ts +179 -0
- package/src/server/claude-steer-log.test.ts +243 -0
- package/src/server/claude-steer-log.ts +58 -0
- package/src/server/claude-subagent-tool-response.test.ts +213 -0
- package/src/server/claude-subagent-tool-response.ts +165 -0
- package/src/server/claude-subagent-wiring.test.ts +263 -0
- package/src/server/claude-subagent-wiring.ts +324 -0
- package/src/server/claude-tool-respond.test.ts +321 -0
- package/src/server/claude-tool-respond.ts +142 -0
- package/src/server/claude-turn-runner.test.ts +310 -0
- package/src/server/claude-turn-runner.ts +228 -0
- package/src/server/claude-turn-starter.test.ts +266 -0
- package/src/server/claude-turn-starter.ts +566 -0
- package/src/server/claude-usage-math.test.ts +169 -0
- package/src/server/claude-usage-math.ts +132 -0
- package/src/server/diff-store-branch-ops.adapter.test.ts +332 -0
- package/src/server/diff-store-branch-ops.adapter.ts +602 -0
- package/src/server/diff-store-commit-ops.adapter.test.ts +358 -0
- package/src/server/diff-store-commit-ops.adapter.ts +258 -0
- package/src/server/diff-store-errors.ts +85 -0
- package/src/server/diff-store-file-ops.adapter.ts +212 -0
- package/src/server/diff-store-git-branch.adapter.ts +686 -0
- package/src/server/diff-store-io.adapter.ts +27 -0
- package/src/server/diff-store-parse.test.ts +212 -0
- package/src/server/diff-store-parse.ts +122 -0
- package/src/server/diff-store-state.ts +82 -0
- package/src/server/diff-store.ts +76 -1854
- package/src/server/event-store-apply.test.ts +280 -0
- package/src/server/event-store-apply.ts +132 -0
- package/src/server/event-store-chat-lifecycle.test.ts +408 -0
- package/src/server/event-store-chat-lifecycle.ts +441 -0
- package/src/server/event-store-entity-write.ts +356 -0
- package/src/server/event-store-helpers.test.ts +230 -0
- package/src/server/event-store-helpers.ts +235 -0
- package/src/server/event-store-init.ts +276 -0
- package/src/server/event-store-messages.adapter.test.ts +365 -0
- package/src/server/event-store-messages.adapter.ts +213 -0
- package/src/server/event-store-orch-subscription.ts +124 -0
- package/src/server/event-store-orch.test.ts +462 -0
- package/src/server/event-store-orch.ts +312 -0
- package/src/server/event-store-peripheral-events.adapter.test.ts +254 -0
- package/src/server/event-store-peripheral-events.adapter.ts +105 -0
- package/src/server/event-store-snapshot.test.ts +597 -0
- package/src/server/event-store-snapshot.ts +658 -0
- package/src/server/event-store-subagent.test.ts +408 -0
- package/src/server/event-store-subagent.ts +198 -0
- package/src/server/event-store-tool-requests.test.ts +210 -0
- package/src/server/event-store-tool-requests.ts +131 -0
- package/src/server/event-store-transcript-write.adapter.ts +285 -0
- package/src/server/event-store-write-ops.test.ts +554 -0
- package/src/server/event-store-write-ops.ts +529 -0
- package/src/server/event-store.test.ts +35 -0
- package/src/server/event-store.ts +251 -2284
- package/src/server/events.ts +3 -0
- package/src/server/harness-types.ts +15 -1
- package/src/server/oauth-errors.ts +19 -0
- package/src/server/read-models.ts +26 -1
- package/src/server/subagent-orchestrator.ts +3 -0
- package/src/server/ws-router-agent-ctrl.test.ts +187 -0
- package/src/server/ws-router-agent-ctrl.ts +137 -0
- package/src/server/ws-router-broadcast.ts +488 -0
- package/src/server/ws-router-chat.test.ts +461 -0
- package/src/server/ws-router-chat.ts +279 -0
- package/src/server/ws-router-defaults.test.ts +283 -0
- package/src/server/ws-router-defaults.ts +434 -0
- package/src/server/ws-router-diff.test.ts +167 -0
- package/src/server/ws-router-diff.ts +250 -0
- package/src/server/ws-router-envelope.ts +329 -0
- package/src/server/ws-router-misc.test.ts +422 -0
- package/src/server/ws-router-misc.ts +265 -0
- package/src/server/ws-router-orch.test.ts +190 -0
- package/src/server/ws-router-orch.ts +93 -0
- package/src/server/ws-router-project.test.ts +403 -0
- package/src/server/ws-router-project.ts +256 -0
- package/src/server/ws-router-push.test.ts +193 -0
- package/src/server/ws-router-push.ts +120 -0
- package/src/server/ws-router-settings.test.ts +173 -0
- package/src/server/ws-router-settings.ts +416 -0
- package/src/server/ws-router-skills.test.ts +194 -0
- package/src/server/ws-router-skills.ts +204 -0
- package/src/server/ws-router-utils.ts +224 -0
- package/src/server/ws-router.ts +339 -2254
- package/src/shared/app-settings-types.ts +365 -0
- package/src/shared/core-types.ts +27 -0
- package/src/shared/git-diff-types.ts +165 -0
- package/src/shared/loop-progress.test.ts +106 -0
- package/src/shared/loop-progress.ts +88 -0
- package/src/shared/mcp-types.ts +105 -0
- package/src/shared/provider-model-types.ts +437 -0
- package/src/shared/subagent-types.ts +198 -0
- package/src/shared/tool-call-types.ts +314 -0
- package/src/shared/transcript-types.ts +270 -0
- package/src/shared/types.ts +27 -1668
- package/dist/client/assets/channel-BMkhjiLI.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-C5Kg1XOD.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-C5Kg1XOD.js +0 -1
- package/dist/client/assets/index-H6C-f2Vp.css +0 -32
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Ca2U11af.js +0 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
LoopProgressSnapshot,
|
|
3
|
+
LoopRateLimitInfo,
|
|
4
|
+
LoopRow,
|
|
5
|
+
LoopRowStatus,
|
|
6
|
+
SubagentRunSnapshot,
|
|
7
|
+
} from "./types"
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Loop Progress — a per-chat, read-only view of an armed autonomous loop's
|
|
11
|
+
* work, surfaced as a checklist panel (mockup: a "Progress" card with one row
|
|
12
|
+
* per chunk). Event-sourced per round: each background subagent delegation the
|
|
13
|
+
* loop fires becomes one row, its status driven by the existing subagent-run
|
|
14
|
+
* lifecycle events. A rate-limited loop (see the rate-limit-resilience fix)
|
|
15
|
+
* surfaces a distinct "resume" affordance instead of looking silently stuck.
|
|
16
|
+
*
|
|
17
|
+
* These helpers are pure so the server read-model and the client share one
|
|
18
|
+
* shape; the DTO types live in ./types to avoid a runtime import cycle.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const MAX_LABEL = 80
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* First non-blank line of a spawn prompt, stripped of a single leading markdown
|
|
25
|
+
* marker (heading / list / quote / ordinal) and capped to a chip-friendly
|
|
26
|
+
* length. Deterministic and side-effect free so it can run at delegate time on
|
|
27
|
+
* the server and be asserted in unit tests.
|
|
28
|
+
*/
|
|
29
|
+
export function deriveChunkLabel(prompt: string): string {
|
|
30
|
+
const firstLine =
|
|
31
|
+
prompt
|
|
32
|
+
.split("\n")
|
|
33
|
+
.map((line) => line.trim())
|
|
34
|
+
.find((line) => line.length > 0) ?? ""
|
|
35
|
+
const stripped = firstLine.replace(/^(#{1,6}\s+|[-*+]\s+|\d+[.)]\s+|>\s+)/, "").trim()
|
|
36
|
+
const cleaned = stripped.length > 0 ? stripped : firstLine
|
|
37
|
+
if (cleaned.length <= MAX_LABEL) return cleaned
|
|
38
|
+
return `${cleaned.slice(0, MAX_LABEL - 1).trimEnd()}…`
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function rowStatusFor(run: SubagentRunSnapshot): LoopRowStatus {
|
|
42
|
+
switch (run.status) {
|
|
43
|
+
case "running":
|
|
44
|
+
return "running"
|
|
45
|
+
case "completed":
|
|
46
|
+
return "done"
|
|
47
|
+
default:
|
|
48
|
+
// failed | cancelled | any future terminal-failure state
|
|
49
|
+
return "failed"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface BuildLoopProgressInput {
|
|
54
|
+
chatId: string
|
|
55
|
+
armed: boolean
|
|
56
|
+
/** Timestamp of the current `loop_armed` event; rows before it are excluded. */
|
|
57
|
+
loopArmedAt: number | null
|
|
58
|
+
/** All subagent runs for the chat (any order). */
|
|
59
|
+
runs: readonly SubagentRunSnapshot[]
|
|
60
|
+
rateLimit: LoopRateLimitInfo | null
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Fold the chat's subagent runs + loop/rate-limit state into the panel DTO.
|
|
65
|
+
* Only top-level (depth 0) runs started since the loop was armed count as loop
|
|
66
|
+
* rows — nested sub-spawns and pre-loop delegations are excluded. Rows are
|
|
67
|
+
* sorted newest-first.
|
|
68
|
+
*/
|
|
69
|
+
export function buildLoopProgress(input: BuildLoopProgressInput): LoopProgressSnapshot {
|
|
70
|
+
const since = input.loopArmedAt ?? 0
|
|
71
|
+
const rows: LoopRow[] = input.runs
|
|
72
|
+
.filter((run) => run.depth === 0 && run.startedAt >= since)
|
|
73
|
+
.map((run) => ({
|
|
74
|
+
runId: run.runId,
|
|
75
|
+
label: run.label ?? run.subagentName,
|
|
76
|
+
status: rowStatusFor(run),
|
|
77
|
+
startedAt: run.startedAt,
|
|
78
|
+
finishedAt: run.finishedAt,
|
|
79
|
+
}))
|
|
80
|
+
.sort((a, b) => b.startedAt - a.startedAt)
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
chatId: input.chatId,
|
|
84
|
+
armed: input.armed,
|
|
85
|
+
rows,
|
|
86
|
+
rateLimit: input.rateLimit,
|
|
87
|
+
}
|
|
88
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
// MCP (Model Context Protocol) server types.
|
|
2
|
+
// Extracted from types.ts to keep the barrel lean.
|
|
3
|
+
// All external consumers importing from "../shared/types" continue to work unchanged.
|
|
4
|
+
|
|
5
|
+
import type {
|
|
6
|
+
OAuthTokens,
|
|
7
|
+
OAuthClientInformationFull,
|
|
8
|
+
AuthorizationServerMetadata,
|
|
9
|
+
} from "@modelcontextprotocol/sdk/shared/auth.js"
|
|
10
|
+
|
|
11
|
+
export type McpServerTransport = "stdio" | "http" | "sse" | "ws"
|
|
12
|
+
|
|
13
|
+
export type McpServerTestResult =
|
|
14
|
+
| { status: "untested" }
|
|
15
|
+
| { status: "pending"; startedAt: string }
|
|
16
|
+
| { status: "ok"; testedAt: string; toolCount: number }
|
|
17
|
+
| { status: "error"; testedAt: string; message: string }
|
|
18
|
+
|
|
19
|
+
export interface McpOAuthFlowState {
|
|
20
|
+
codeVerifier: string
|
|
21
|
+
state: string
|
|
22
|
+
issuer: string
|
|
23
|
+
authorizationUrl: string
|
|
24
|
+
// AS metadata cached between start and complete (avoids re-discovery)
|
|
25
|
+
metadata: AuthorizationServerMetadata
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface McpOAuthState {
|
|
29
|
+
enabled: boolean
|
|
30
|
+
status: "unauthenticated" | "authenticated" | "error"
|
|
31
|
+
errorMessage?: string
|
|
32
|
+
// resolved AS issuer (set on complete; used by refresh without re-discovery)
|
|
33
|
+
issuer?: string
|
|
34
|
+
// cached AS metadata (token_endpoint, etc.) persisted at complete so refresh
|
|
35
|
+
// uses it directly instead of re-discovering from issuer (which may be a
|
|
36
|
+
// non-resolvable resource URL, e.g. claude.ai design MCP)
|
|
37
|
+
metadata?: AuthorizationServerMetadata
|
|
38
|
+
// DCR result keyed by AS issuer (SEP-2352)
|
|
39
|
+
clientByIssuer?: Record<string, OAuthClientInformationFull>
|
|
40
|
+
tokens?: OAuthTokens
|
|
41
|
+
obtainedAt?: number
|
|
42
|
+
// present only mid-flow; cleared on complete/cancel
|
|
43
|
+
flow?: McpOAuthFlowState
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
interface McpServerBase {
|
|
47
|
+
id: string
|
|
48
|
+
name: string
|
|
49
|
+
enabled: boolean
|
|
50
|
+
createdAt: string
|
|
51
|
+
updatedAt: string
|
|
52
|
+
lastTest: McpServerTestResult
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface McpServerStdioFields {
|
|
56
|
+
transport: "stdio"
|
|
57
|
+
command: string
|
|
58
|
+
args: string[]
|
|
59
|
+
env: Record<string, string>
|
|
60
|
+
cwd?: string
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface McpServerNetworkFields {
|
|
64
|
+
transport: "http" | "sse" | "ws"
|
|
65
|
+
url: string
|
|
66
|
+
headers: Record<string, string>
|
|
67
|
+
oauth?: McpOAuthState
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type McpServerConfig =
|
|
71
|
+
| (McpServerBase & McpServerStdioFields)
|
|
72
|
+
| (McpServerBase & McpServerNetworkFields)
|
|
73
|
+
|
|
74
|
+
export type McpServerInput =
|
|
75
|
+
| (McpServerStdioFields & { name: string; enabled?: boolean })
|
|
76
|
+
| (McpServerNetworkFields & { name: string; enabled?: boolean })
|
|
77
|
+
|
|
78
|
+
export type McpServerPatch = Partial<{
|
|
79
|
+
name: string
|
|
80
|
+
enabled: boolean
|
|
81
|
+
transport: McpServerTransport
|
|
82
|
+
command: string
|
|
83
|
+
args: string[]
|
|
84
|
+
env: Record<string, string>
|
|
85
|
+
cwd: string | undefined
|
|
86
|
+
url: string
|
|
87
|
+
headers: Record<string, string>
|
|
88
|
+
oauth: McpOAuthState
|
|
89
|
+
}>
|
|
90
|
+
|
|
91
|
+
export interface McpValidationError {
|
|
92
|
+
code:
|
|
93
|
+
| "INVALID_NAME"
|
|
94
|
+
| "DUPLICATE_NAME"
|
|
95
|
+
| "RESERVED_NAME"
|
|
96
|
+
| "INVALID_TRANSPORT"
|
|
97
|
+
| "MISSING_COMMAND"
|
|
98
|
+
| "INVALID_URL"
|
|
99
|
+
| "INVALID_HEADER_KEY"
|
|
100
|
+
| "INVALID_ENV_KEY"
|
|
101
|
+
| "NOT_FOUND"
|
|
102
|
+
| "INVALID_OAUTH_TRANSPORT"
|
|
103
|
+
field?: string
|
|
104
|
+
message: string
|
|
105
|
+
}
|
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider and model catalog types — extracted from shared/types.ts.
|
|
3
|
+
* Imported via the re-export barrel in types.ts; all external consumers
|
|
4
|
+
* continue to import from "../shared/types" unchanged.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// AgentProvider lives in types.ts and is only needed as a type here.
|
|
8
|
+
// import type = erased at compile time → no circular runtime dependency.
|
|
9
|
+
import type { AgentProvider } from "./types"
|
|
10
|
+
|
|
11
|
+
export const DEFAULT_OPENROUTER_SDK_MODEL = "moonshotai/kimi-k2.5:nitro"
|
|
12
|
+
|
|
13
|
+
export const OPENROUTER_BASE_URL = "https://openrouter.ai/api"
|
|
14
|
+
export const OPENROUTER_MODELS_URL = "https://openrouter.ai/api/v1/models"
|
|
15
|
+
|
|
16
|
+
export interface OpenRouterModel {
|
|
17
|
+
id: string
|
|
18
|
+
label: string
|
|
19
|
+
contextLength: number
|
|
20
|
+
pricing?: { promptPerTok: number; completionPerTok: number }
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ---------------------------------------------------------------------------
|
|
24
|
+
// Provider model option primitives
|
|
25
|
+
// ---------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
export interface ProviderModelOption {
|
|
28
|
+
id: string
|
|
29
|
+
label: string
|
|
30
|
+
supportsEffort: boolean
|
|
31
|
+
aliases?: readonly string[]
|
|
32
|
+
contextWindowOptions?: readonly ProviderContextWindowOption[]
|
|
33
|
+
supportsMaxReasoningEffort?: boolean
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface ProviderEffortOption {
|
|
37
|
+
id: string
|
|
38
|
+
label: string
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ProviderContextWindowOption {
|
|
42
|
+
id: ClaudeContextWindow
|
|
43
|
+
label: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const CLAUDE_REASONING_OPTIONS = [
|
|
47
|
+
{ id: "low", label: "Low" },
|
|
48
|
+
{ id: "medium", label: "Medium" },
|
|
49
|
+
{ id: "high", label: "High" },
|
|
50
|
+
{ id: "max", label: "Max" },
|
|
51
|
+
] as const satisfies readonly ProviderEffortOption[]
|
|
52
|
+
|
|
53
|
+
export const CODEX_REASONING_OPTIONS = [
|
|
54
|
+
{ id: "minimal", label: "Minimal" },
|
|
55
|
+
{ id: "low", label: "Low" },
|
|
56
|
+
{ id: "medium", label: "Medium" },
|
|
57
|
+
{ id: "high", label: "High" },
|
|
58
|
+
{ id: "xhigh", label: "XHigh" },
|
|
59
|
+
] as const satisfies readonly ProviderEffortOption[]
|
|
60
|
+
|
|
61
|
+
export type ClaudeReasoningEffort = (typeof CLAUDE_REASONING_OPTIONS)[number]["id"]
|
|
62
|
+
export type CodexReasoningEffort = (typeof CODEX_REASONING_OPTIONS)[number]["id"]
|
|
63
|
+
export type ClaudeContextWindow = "200k" | "1m"
|
|
64
|
+
export type ServiceTier = "fast"
|
|
65
|
+
|
|
66
|
+
export interface ClaudeModelOptions {
|
|
67
|
+
reasoningEffort: ClaudeReasoningEffort
|
|
68
|
+
contextWindow: ClaudeContextWindow
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export interface CodexModelOptions {
|
|
72
|
+
reasoningEffort: CodexReasoningEffort
|
|
73
|
+
fastMode: boolean
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type OpenRouterModelOptions = Record<string, never>
|
|
77
|
+
|
|
78
|
+
export interface ProviderModelOptionsByProvider {
|
|
79
|
+
claude: ClaudeModelOptions
|
|
80
|
+
codex: CodexModelOptions
|
|
81
|
+
openrouter: OpenRouterModelOptions
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface ProviderPreference<TModelOptions> {
|
|
85
|
+
model: string
|
|
86
|
+
modelOptions: TModelOptions
|
|
87
|
+
planMode: boolean
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export type ChatProviderPreferences = {
|
|
91
|
+
claude: ProviderPreference<ClaudeModelOptions>
|
|
92
|
+
codex: ProviderPreference<CodexModelOptions>
|
|
93
|
+
openrouter: ProviderPreference<OpenRouterModelOptions>
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
// Model option defaults and type-guards
|
|
98
|
+
// ---------------------------------------------------------------------------
|
|
99
|
+
|
|
100
|
+
export type ModelOptions = Partial<{
|
|
101
|
+
[K in AgentProvider]: Partial<ProviderModelOptionsByProvider[K]>
|
|
102
|
+
}>
|
|
103
|
+
|
|
104
|
+
export const DEFAULT_CLAUDE_MODEL_OPTIONS = {
|
|
105
|
+
reasoningEffort: "high",
|
|
106
|
+
contextWindow: "200k",
|
|
107
|
+
} as const satisfies ClaudeModelOptions
|
|
108
|
+
|
|
109
|
+
export const DEFAULT_CODEX_MODEL_OPTIONS = {
|
|
110
|
+
reasoningEffort: "high",
|
|
111
|
+
fastMode: false,
|
|
112
|
+
} as const satisfies CodexModelOptions
|
|
113
|
+
|
|
114
|
+
export function isClaudeReasoningEffort(value: string | null | undefined): value is ClaudeReasoningEffort {
|
|
115
|
+
return CLAUDE_REASONING_OPTIONS.some((option) => option.id === value)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
export function isCodexReasoningEffort(value: string | null | undefined): value is CodexReasoningEffort {
|
|
119
|
+
return CODEX_REASONING_OPTIONS.some((option) => option.id === value)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export const CLAUDE_CONTEXT_WINDOW_OPTIONS = [
|
|
123
|
+
{ id: "200k", label: "200k" },
|
|
124
|
+
{ id: "1m", label: "1M" },
|
|
125
|
+
] as const satisfies readonly ProviderContextWindowOption[]
|
|
126
|
+
|
|
127
|
+
export function isClaudeContextWindow(value: string | null | undefined): value is ClaudeContextWindow {
|
|
128
|
+
return CLAUDE_CONTEXT_WINDOW_OPTIONS.some((option) => option.id === value)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
// Provider catalog
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
|
|
135
|
+
export interface ProviderCatalogEntry {
|
|
136
|
+
id: AgentProvider
|
|
137
|
+
label: string
|
|
138
|
+
defaultModel: string
|
|
139
|
+
defaultEffort?: string
|
|
140
|
+
supportsPlanMode: boolean
|
|
141
|
+
models: ProviderModelOption[]
|
|
142
|
+
efforts: ProviderEffortOption[]
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export const PROVIDERS: ProviderCatalogEntry[] = [
|
|
146
|
+
{
|
|
147
|
+
id: "claude",
|
|
148
|
+
label: "Claude",
|
|
149
|
+
defaultModel: "claude-sonnet-4-6",
|
|
150
|
+
defaultEffort: "high",
|
|
151
|
+
supportsPlanMode: true,
|
|
152
|
+
models: [
|
|
153
|
+
{
|
|
154
|
+
id: "claude-fable-5",
|
|
155
|
+
label: "Fable 5",
|
|
156
|
+
supportsEffort: true,
|
|
157
|
+
aliases: ["fable"],
|
|
158
|
+
contextWindowOptions: [...CLAUDE_CONTEXT_WINDOW_OPTIONS],
|
|
159
|
+
supportsMaxReasoningEffort: true,
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
id: "claude-opus-4-7",
|
|
163
|
+
label: "Opus 4.7",
|
|
164
|
+
supportsEffort: true,
|
|
165
|
+
aliases: ["opus"],
|
|
166
|
+
contextWindowOptions: [...CLAUDE_CONTEXT_WINDOW_OPTIONS],
|
|
167
|
+
supportsMaxReasoningEffort: true,
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
id: "claude-sonnet-4-6",
|
|
171
|
+
label: "Sonnet 4.6",
|
|
172
|
+
supportsEffort: true,
|
|
173
|
+
aliases: ["sonnet"],
|
|
174
|
+
contextWindowOptions: [...CLAUDE_CONTEXT_WINDOW_OPTIONS],
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
id: "claude-haiku-4-5-20251001",
|
|
178
|
+
label: "Haiku 4.5",
|
|
179
|
+
supportsEffort: true,
|
|
180
|
+
aliases: ["haiku"],
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
id: "claude-opus-4-8",
|
|
184
|
+
label: "Opus 4.8",
|
|
185
|
+
supportsEffort: true,
|
|
186
|
+
aliases: ["opus-4-8"],
|
|
187
|
+
contextWindowOptions: [...CLAUDE_CONTEXT_WINDOW_OPTIONS],
|
|
188
|
+
supportsMaxReasoningEffort: true,
|
|
189
|
+
},
|
|
190
|
+
],
|
|
191
|
+
efforts: [...CLAUDE_REASONING_OPTIONS],
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
id: "codex",
|
|
195
|
+
label: "Codex",
|
|
196
|
+
defaultModel: "gpt-5.5",
|
|
197
|
+
supportsPlanMode: true,
|
|
198
|
+
models: [
|
|
199
|
+
{ id: "gpt-5.5", label: "GPT-5.5", supportsEffort: false },
|
|
200
|
+
{ id: "gpt-5.4", label: "GPT-5.4", supportsEffort: false },
|
|
201
|
+
{ id: "gpt-5.3-codex", label: "GPT-5.3 Codex", supportsEffort: false, aliases: ["gpt-5-codex"] },
|
|
202
|
+
{ id: "gpt-5.3-codex-spark", label: "GPT-5.3 Codex Spark", supportsEffort: false },
|
|
203
|
+
],
|
|
204
|
+
efforts: [],
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
id: "openrouter",
|
|
208
|
+
label: "OpenRouter",
|
|
209
|
+
defaultModel: DEFAULT_OPENROUTER_SDK_MODEL,
|
|
210
|
+
supportsPlanMode: true,
|
|
211
|
+
models: [],
|
|
212
|
+
efforts: [],
|
|
213
|
+
},
|
|
214
|
+
]
|
|
215
|
+
|
|
216
|
+
export function getProviderCatalog(provider: AgentProvider): ProviderCatalogEntry {
|
|
217
|
+
const entry = PROVIDERS.find((candidate) => candidate.id === provider)
|
|
218
|
+
if (!entry) {
|
|
219
|
+
throw new Error(`Unknown provider: ${provider}`)
|
|
220
|
+
}
|
|
221
|
+
return entry
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// ---------------------------------------------------------------------------
|
|
225
|
+
// Custom model entries (user-configurable overrides over the catalog)
|
|
226
|
+
// ---------------------------------------------------------------------------
|
|
227
|
+
|
|
228
|
+
export interface CustomModelEntry {
|
|
229
|
+
id: string
|
|
230
|
+
label: string
|
|
231
|
+
provider: "claude" | "codex"
|
|
232
|
+
supportsEffort: boolean
|
|
233
|
+
aliases?: readonly string[]
|
|
234
|
+
contextWindowOptions?: readonly ProviderContextWindowOption[]
|
|
235
|
+
supportsMaxReasoningEffort?: boolean
|
|
236
|
+
createdAt: number
|
|
237
|
+
updatedAt: number
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
export interface CustomModelInput {
|
|
241
|
+
id: string
|
|
242
|
+
label: string
|
|
243
|
+
provider: "claude" | "codex"
|
|
244
|
+
supportsEffort: boolean
|
|
245
|
+
aliases?: readonly string[]
|
|
246
|
+
contextWindowOptions?: readonly ProviderContextWindowOption[]
|
|
247
|
+
supportsMaxReasoningEffort?: boolean
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export interface CustomModelPatch {
|
|
251
|
+
label?: string
|
|
252
|
+
supportsEffort?: boolean
|
|
253
|
+
aliases?: readonly string[] | null
|
|
254
|
+
contextWindowOptions?: readonly ProviderContextWindowOption[] | null
|
|
255
|
+
supportsMaxReasoningEffort?: boolean
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// ---------------------------------------------------------------------------
|
|
259
|
+
// Text snippets (keyboard-shortcut text expansions)
|
|
260
|
+
// ---------------------------------------------------------------------------
|
|
261
|
+
|
|
262
|
+
export interface TextSnippet {
|
|
263
|
+
id: string
|
|
264
|
+
shortcut: string
|
|
265
|
+
expansion: string
|
|
266
|
+
createdAt: number
|
|
267
|
+
updatedAt: number
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export interface TextSnippetInput {
|
|
271
|
+
shortcut: string
|
|
272
|
+
expansion: string
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export interface TextSnippetPatch {
|
|
276
|
+
shortcut?: string
|
|
277
|
+
expansion?: string
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// ---------------------------------------------------------------------------
|
|
281
|
+
// mergeCustomModels — folds user overrides into the provider catalog
|
|
282
|
+
// ---------------------------------------------------------------------------
|
|
283
|
+
|
|
284
|
+
function customEntryToModelOption(entry: CustomModelEntry): ProviderModelOption {
|
|
285
|
+
return {
|
|
286
|
+
id: entry.id,
|
|
287
|
+
label: entry.label,
|
|
288
|
+
supportsEffort: entry.supportsEffort,
|
|
289
|
+
...(entry.aliases ? { aliases: entry.aliases } : {}),
|
|
290
|
+
...(entry.contextWindowOptions ? { contextWindowOptions: entry.contextWindowOptions } : {}),
|
|
291
|
+
...(entry.supportsMaxReasoningEffort !== undefined ? { supportsMaxReasoningEffort: entry.supportsMaxReasoningEffort } : {}),
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
export function mergeCustomModels(
|
|
296
|
+
base: ProviderCatalogEntry[],
|
|
297
|
+
customModels: readonly CustomModelEntry[],
|
|
298
|
+
): ProviderCatalogEntry[] {
|
|
299
|
+
return base.map((entry) => {
|
|
300
|
+
if (entry.id !== "claude" && entry.id !== "codex") return { ...entry, models: [...entry.models] }
|
|
301
|
+
const forProvider = customModels.filter((m) => m.provider === entry.id)
|
|
302
|
+
if (forProvider.length === 0) return { ...entry, models: [...entry.models] }
|
|
303
|
+
const models = [...entry.models]
|
|
304
|
+
for (const custom of forProvider) {
|
|
305
|
+
const option = customEntryToModelOption(custom)
|
|
306
|
+
const idx = models.findIndex((m) => m.id === option.id)
|
|
307
|
+
if (idx >= 0) models[idx] = option
|
|
308
|
+
else models.push(option)
|
|
309
|
+
}
|
|
310
|
+
return { ...entry, models }
|
|
311
|
+
})
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// ---------------------------------------------------------------------------
|
|
315
|
+
// Provider session helpers and model-id normalization
|
|
316
|
+
// ---------------------------------------------------------------------------
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* True when the provider's turns run through the Claude SDK session transport
|
|
320
|
+
* (a live `claudeSessions` entry consumed by `runClaudeSession`, prompts
|
|
321
|
+
* delivered via `session.sendPrompt`) rather than the generic harness-turn
|
|
322
|
+
* transport (`runTurn` over `active.turn.stream`).
|
|
323
|
+
*
|
|
324
|
+
* `claude` and `openrouter` both ride the SDK session — openrouter just points
|
|
325
|
+
* the SDK at OpenRouter's Anthropic-compatible endpoint. Branching on
|
|
326
|
+
* `provider === "claude"` where the real intent is "uses the SDK session" is
|
|
327
|
+
* what silently dropped openrouter's prompt delivery; use this predicate so a
|
|
328
|
+
* new SDK-backed provider can never be forgotten by an `if`-chain again.
|
|
329
|
+
*/
|
|
330
|
+
export function providerUsesSdkSession(provider: AgentProvider): boolean {
|
|
331
|
+
return provider === "claude" || provider === "openrouter"
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function catalogModelsFor(
|
|
335
|
+
provider: AgentProvider,
|
|
336
|
+
customModels?: readonly CustomModelEntry[],
|
|
337
|
+
): readonly ProviderModelOption[] {
|
|
338
|
+
const catalog = getProviderCatalog(provider)
|
|
339
|
+
if (!customModels || customModels.length === 0) return catalog.models
|
|
340
|
+
const [merged] = mergeCustomModels([{ ...catalog, models: [...catalog.models] }], customModels)
|
|
341
|
+
return merged.models
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
function getProviderModelMatch(
|
|
345
|
+
provider: AgentProvider,
|
|
346
|
+
modelId?: string,
|
|
347
|
+
customModels?: readonly CustomModelEntry[],
|
|
348
|
+
): ProviderModelOption | undefined {
|
|
349
|
+
if (!modelId) return undefined
|
|
350
|
+
|
|
351
|
+
return catalogModelsFor(provider, customModels).find((candidate) =>
|
|
352
|
+
candidate.id === modelId || candidate.aliases?.includes(modelId)
|
|
353
|
+
)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export function normalizeProviderModelId(
|
|
357
|
+
provider: AgentProvider,
|
|
358
|
+
modelId?: string,
|
|
359
|
+
fallbackModelId?: string,
|
|
360
|
+
customModels?: readonly CustomModelEntry[],
|
|
361
|
+
): string {
|
|
362
|
+
return getProviderModelMatch(provider, modelId, customModels)?.id
|
|
363
|
+
?? fallbackModelId
|
|
364
|
+
?? getProviderCatalog(provider).defaultModel
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
export function normalizeClaudeModelId(
|
|
368
|
+
modelId?: string,
|
|
369
|
+
fallbackModelId = "claude-opus-4-7",
|
|
370
|
+
customModels?: readonly CustomModelEntry[],
|
|
371
|
+
): string {
|
|
372
|
+
return normalizeProviderModelId("claude", modelId, fallbackModelId, customModels)
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function normalizeCodexModelId(
|
|
376
|
+
modelId?: string,
|
|
377
|
+
fallbackModelId = "gpt-5.5",
|
|
378
|
+
customModels?: readonly CustomModelEntry[],
|
|
379
|
+
): string {
|
|
380
|
+
return normalizeProviderModelId("codex", modelId, fallbackModelId, customModels)
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
export function getProviderModelOption(
|
|
384
|
+
provider: AgentProvider,
|
|
385
|
+
modelId: string,
|
|
386
|
+
customModels?: readonly CustomModelEntry[],
|
|
387
|
+
): ProviderModelOption | undefined {
|
|
388
|
+
const normalizedModelId = normalizeProviderModelId(provider, modelId, undefined, customModels)
|
|
389
|
+
return catalogModelsFor(provider, customModels).find((candidate) => candidate.id === normalizedModelId)
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
export function getClaudeModelOption(
|
|
393
|
+
modelId: string,
|
|
394
|
+
customModels?: readonly CustomModelEntry[],
|
|
395
|
+
): ProviderModelOption | undefined {
|
|
396
|
+
return getProviderModelOption("claude", modelId, customModels)
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
export function supportsClaudeMaxReasoningEffort(
|
|
400
|
+
modelId: string,
|
|
401
|
+
customModels?: readonly CustomModelEntry[],
|
|
402
|
+
): boolean {
|
|
403
|
+
return Boolean(getClaudeModelOption(modelId, customModels)?.supportsMaxReasoningEffort)
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
export function getClaudeContextWindowOptions(
|
|
407
|
+
modelId: string,
|
|
408
|
+
customModels?: readonly CustomModelEntry[],
|
|
409
|
+
): readonly ProviderContextWindowOption[] {
|
|
410
|
+
return getClaudeModelOption(modelId, customModels)?.contextWindowOptions ?? []
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
export function normalizeClaudeContextWindow(
|
|
414
|
+
modelId: string,
|
|
415
|
+
contextWindow?: string,
|
|
416
|
+
customModels?: readonly CustomModelEntry[],
|
|
417
|
+
): ClaudeContextWindow {
|
|
418
|
+
const options = getClaudeContextWindowOptions(modelId, customModels)
|
|
419
|
+
if (options.length === 0) return DEFAULT_CLAUDE_MODEL_OPTIONS.contextWindow
|
|
420
|
+
return isClaudeContextWindow(contextWindow) && options.some((option) => option.id === contextWindow)
|
|
421
|
+
? contextWindow
|
|
422
|
+
: DEFAULT_CLAUDE_MODEL_OPTIONS.contextWindow
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
export function resolveClaudeApiModelId(modelId: string, contextWindow?: ClaudeContextWindow): string {
|
|
426
|
+
return contextWindow === "1m" ? `${modelId}[1m]` : modelId
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
export function resolveClaudeContextWindowTokens(contextWindow: ClaudeContextWindow): number {
|
|
430
|
+
switch (contextWindow) {
|
|
431
|
+
case "1m":
|
|
432
|
+
return 1_000_000
|
|
433
|
+
case "200k":
|
|
434
|
+
default:
|
|
435
|
+
return 200_000
|
|
436
|
+
}
|
|
437
|
+
}
|