paseo-plugin-zcode-provider 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE.md +29 -0
- package/README.md +112 -2
- package/client/account.tsx +827 -0
- package/client/diagnostics.tsx +379 -0
- package/client/runtime.tsx +296 -0
- package/client/settings.tsx +84 -0
- package/client/value.tsx +20 -0
- package/icon.svg +1 -0
- package/index.client.tsx +22 -0
- package/index.server.ts +39 -0
- package/package.json +77 -4
- package/paseo-plugin.json +6 -0
- package/server/account.ts +781 -0
- package/server/attachments.ts +150 -0
- package/server/build-info.ts +2 -0
- package/server/conversation.ts +319 -0
- package/server/diagnostics.ts +252 -0
- package/server/discovery/discover.ts +225 -0
- package/server/discovery/manifest.ts +36 -0
- package/server/discovery/types.ts +30 -0
- package/server/errors.ts +36 -0
- package/server/host/bridge.ts +490 -0
- package/server/host/schemas.ts +119 -0
- package/server/logger.ts +19 -0
- package/server/mapping.ts +270 -0
- package/server/models.ts +68 -0
- package/server/persistence.ts +146 -0
- package/server/presentation.ts +470 -0
- package/server/provider-status.ts +81 -0
- package/server/provider.ts +838 -0
- package/server/runtime/managed.ts +501 -0
- package/server/runtime/pins.ts +72 -0
- package/server/runtime-setup.ts +77 -0
- package/server/session-types.ts +49 -0
- package/server/session.ts +866 -0
- package/server/status.ts +89 -0
- package/server/timeline.ts +18 -0
- package/server/usage.ts +362 -0
- package/server/vendor/zcode/LICENSE +202 -0
- package/server/vendor/zcode/NOTICE.md +70 -0
- package/server/vendor/zcode/THIRD-PARTY-NOTICES.md +37 -0
- package/server/vendor/zcode/packages/model-option-map/src/compiler.ts +92 -0
- package/server/vendor/zcode/packages/model-option-map/src/evaluator.ts +214 -0
- package/server/vendor/zcode/packages/model-option-map/src/index.ts +5 -0
- package/server/vendor/zcode/packages/model-option-map/src/merge-patch.ts +97 -0
- package/server/vendor/zcode/packages/model-option-map/src/option-maps.ts +42 -0
- package/server/vendor/zcode/packages/model-option-map/src/parser.ts +240 -0
- package/server/vendor/zcode/packages/model-option-map/src/tokenizer.ts +141 -0
- package/server/vendor/zcode/packages/model-option-map/src/types.ts +36 -0
- package/server/vendor/zcode/packages/rpc/src/buffer.ts +88 -0
- package/server/vendor/zcode/packages/rpc/src/channelClient.ts +275 -0
- package/server/vendor/zcode/packages/rpc/src/channelServer.ts +283 -0
- package/server/vendor/zcode/packages/rpc/src/channels.shared.ts +66 -0
- package/server/vendor/zcode/packages/rpc/src/channels.ts +4 -0
- package/server/vendor/zcode/packages/rpc/src/delayedChannel.ts +17 -0
- package/server/vendor/zcode/packages/rpc/src/foundation.ts +260 -0
- package/server/vendor/zcode/packages/rpc/src/protocol.ts +397 -0
- package/server/vendor/zcode/packages/rpc/src/proxy-channel.ts +213 -0
- package/server/vendor/zcode/packages/rpc/src/serialization.ts +291 -0
- package/server/vendor/zcode/packages/shared/src/account-provider-state.ts +13 -0
- package/server/vendor/zcode/packages/shared/src/background-bash-output.ts +24 -0
- package/server/vendor/zcode/packages/shared/src/background-task-controls.ts +404 -0
- package/server/vendor/zcode/packages/shared/src/bash-output-display.ts +11 -0
- package/server/vendor/zcode/packages/shared/src/bots.ts +558 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/backend.ts +80 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/command-metadata.ts +170 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/commands.ts +588 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/result.ts +130 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/snapshot.ts +77 -0
- package/server/vendor/zcode/packages/shared/src/command-types.ts +96 -0
- package/server/vendor/zcode/packages/shared/src/config-schema.ts +8 -0
- package/server/vendor/zcode/packages/shared/src/cuaAccessibilitySettings.ts +41 -0
- package/server/vendor/zcode/packages/shared/src/database-startup.ts +178 -0
- package/server/vendor/zcode/packages/shared/src/env.ts +63 -0
- package/server/vendor/zcode/packages/shared/src/execution-output-preview.ts +14 -0
- package/server/vendor/zcode/packages/shared/src/localTtft.ts +192 -0
- package/server/vendor/zcode/packages/shared/src/model-config.ts +123 -0
- package/server/vendor/zcode/packages/shared/src/model-execution.ts +23 -0
- package/server/vendor/zcode/packages/shared/src/model-provider-family.ts +171 -0
- package/server/vendor/zcode/packages/shared/src/model-provider-types.ts +81 -0
- package/server/vendor/zcode/packages/shared/src/model-selection.ts +60 -0
- package/server/vendor/zcode/packages/shared/src/oauth.ts +203 -0
- package/server/vendor/zcode/packages/shared/src/official-mcp-auth.ts +272 -0
- package/server/vendor/zcode/packages/shared/src/official-mcp-tool-error.ts +68 -0
- package/server/vendor/zcode/packages/shared/src/process-diagnostic.ts +42 -0
- package/server/vendor/zcode/packages/shared/src/protocol.ts +369 -0
- package/server/vendor/zcode/packages/shared/src/provider-family-connection-selection.ts +32 -0
- package/server/vendor/zcode/packages/shared/src/remoteAssetInstallMode.ts +11 -0
- package/server/vendor/zcode/packages/shared/src/remoteResourcePackages.ts +91 -0
- package/server/vendor/zcode/packages/shared/src/runtimeEnv.ts +315 -0
- package/server/vendor/zcode/packages/shared/src/settings-source.ts +10 -0
- package/server/vendor/zcode/packages/shared/src/usage-quota.ts +74 -0
- package/server/vendor/zcode/packages/shared/src/usage-stats.ts +462 -0
- package/server/vendor/zcode/packages/shared/src/validationAppSettings.ts +562 -0
- package/server/vendor/zcode/packages/shared/src/workspacePurpose.ts +2 -0
- package/server/vendor/zcode/packages/shared/src/wslUserValidation.ts +33 -0
- package/server/vendor/zcode/packages/shared/src/zcode-agent-policy.ts +25 -0
- package/server/vendor/zcode/packages/shared/src/zcode-media-policy.ts +10 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol/index.ts +3720 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-legacy-types.ts +529 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/apply.ts +218 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/attachment-ref.ts +14 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/command.ts +482 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/core.ts +100 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/create-workflow-display.ts +156 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/cuaPermission.ts +41 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/delta.ts +147 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/input-intent.ts +69 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/rows.ts +432 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/session-config.ts +43 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index-workflow-activity.ts +195 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index.ts +85 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/shared-context-import.ts +38 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/shared-context-ref.ts +10 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/snapshot.ts +509 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/submission.ts +5 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/toolDisplay.ts +264 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/transport.ts +1152 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-assembler.ts +574 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-binary.ts +65 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-codec.ts +240 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-fault.ts +39 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire.ts +159 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-artifacts.ts +291 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-observation-display.ts +281 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-row-meta.ts +163 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-run-settings-command.ts +62 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs-delta.ts +517 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs.ts +512 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workspace-config.ts +81 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workspace-hook-review.ts +210 -0
- package/server/vendor/zcode/packages/shared/src/zcode-task-mode-schema.ts +6 -0
- package/server/vendor/zcode/packages/shared/src/zcode-task-types-core.ts +1187 -0
- package/server/vendor/zcode/packages/shared/src/zcodeEndpoint.ts +296 -0
- package/server/vendor/zcode/provenance.json +405 -0
- package/shared/account.ts +201 -0
- package/shared/diagnostics.ts +52 -0
- package/shared/runtime-setup.ts +73 -0
- package/vendor/acp-registry/LICENSE +176 -0
- package/vendor/paseo/LICENSE +211 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const LOCAL_TTFT_STAGES = [
|
|
4
|
+
"renderer_prepare",
|
|
5
|
+
"command_admission",
|
|
6
|
+
"execution_wait",
|
|
7
|
+
"request_prepare",
|
|
8
|
+
"model_request",
|
|
9
|
+
"output_return",
|
|
10
|
+
] as const;
|
|
11
|
+
export const LOCAL_TTFT_BUCKETS_MS = [
|
|
12
|
+
1, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 30000, 60000, 300000,
|
|
13
|
+
];
|
|
14
|
+
export const LOCAL_TTFT_MAX_DETAILS = 64;
|
|
15
|
+
export const LOCAL_TTFT_PREPARATION_STAGES = [
|
|
16
|
+
"context",
|
|
17
|
+
"hooks",
|
|
18
|
+
"persistence",
|
|
19
|
+
"compaction",
|
|
20
|
+
"mcp",
|
|
21
|
+
"tools",
|
|
22
|
+
"request_assembly",
|
|
23
|
+
] as const;
|
|
24
|
+
const diagnosticTime = z.number().finite().nonnegative();
|
|
25
|
+
export const localTtftDetailSchema = z
|
|
26
|
+
.object({
|
|
27
|
+
id: z.string().min(1).max(128),
|
|
28
|
+
stage: z.enum([...LOCAL_TTFT_PREPARATION_STAGES, "attempt", "retry_wait", "user_confirmation"]),
|
|
29
|
+
start: diagnosticTime,
|
|
30
|
+
end: diagnosticTime.optional(),
|
|
31
|
+
outcome: z.enum(["completed", "failed", "cancelled", "first_output"]).optional(),
|
|
32
|
+
requestId: z.string().min(1).max(128).optional(),
|
|
33
|
+
logicalCallId: z.string().min(1).max(128).optional(),
|
|
34
|
+
role: z.enum(["response", "preparation"]).optional(),
|
|
35
|
+
source: z.enum(["renderer", "cli"]),
|
|
36
|
+
})
|
|
37
|
+
.strict()
|
|
38
|
+
.refine((value) => value.end === undefined || value.end >= value.start);
|
|
39
|
+
export type LocalTtftDetail = z.infer<typeof localTtftDetailSchema>;
|
|
40
|
+
export const LOCAL_TTFT_MAX_PENDING = 128;
|
|
41
|
+
export const LOCAL_TTFT_TTL_MS = 300_000;
|
|
42
|
+
export const LOCAL_TTFT_CLOCK_MAX_ERROR_MS = 10;
|
|
43
|
+
export const LOCAL_TTFT_CLOCK_TTL_MS = 60_000;
|
|
44
|
+
const time = z.number().finite().nonnegative();
|
|
45
|
+
const identifier = z.string().min(1).max(128);
|
|
46
|
+
export const localTtftContextSchema = z
|
|
47
|
+
.object({ version: z.literal(1), observationId: z.string().uuid() })
|
|
48
|
+
.strict();
|
|
49
|
+
export type LocalTtftContext = z.infer<typeof localTtftContextSchema>;
|
|
50
|
+
export const localTtftClockSchema = z
|
|
51
|
+
.object({ instanceId: identifier, receivedAt: time, sentAt: time })
|
|
52
|
+
.strict();
|
|
53
|
+
export type LocalTtftClock = z.infer<typeof localTtftClockSchema>;
|
|
54
|
+
export interface LocalTtftCalibration {
|
|
55
|
+
instanceId: string;
|
|
56
|
+
offsetMs: number;
|
|
57
|
+
errorMs: number;
|
|
58
|
+
measuredAt: number;
|
|
59
|
+
}
|
|
60
|
+
export function calibrateLocalTtftClock(
|
|
61
|
+
start: number,
|
|
62
|
+
end: number,
|
|
63
|
+
clock: LocalTtftClock,
|
|
64
|
+
): LocalTtftCalibration | undefined {
|
|
65
|
+
const networkMs = end - start - (clock.sentAt - clock.receivedAt);
|
|
66
|
+
if (
|
|
67
|
+
![start, end, clock.receivedAt, clock.sentAt].every(Number.isFinite) ||
|
|
68
|
+
end < start ||
|
|
69
|
+
clock.sentAt < clock.receivedAt ||
|
|
70
|
+
networkMs < 0 ||
|
|
71
|
+
networkMs / 2 > LOCAL_TTFT_CLOCK_MAX_ERROR_MS
|
|
72
|
+
)
|
|
73
|
+
return undefined;
|
|
74
|
+
return {
|
|
75
|
+
instanceId: clock.instanceId,
|
|
76
|
+
offsetMs: (start + end - clock.receivedAt - clock.sentAt) / 2,
|
|
77
|
+
errorMs: networkMs / 2,
|
|
78
|
+
measuredAt: end,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export const localTtftOutputKindSchema = z.enum(["text", "reasoning", "tool"]);
|
|
82
|
+
export type LocalTtftOutputKind = z.infer<typeof localTtftOutputKindSchema>;
|
|
83
|
+
export const localTtftFactsSchema = z
|
|
84
|
+
.object({
|
|
85
|
+
...localTtftContextSchema.shape,
|
|
86
|
+
instanceId: identifier,
|
|
87
|
+
commandId: identifier,
|
|
88
|
+
sessionId: identifier.optional(),
|
|
89
|
+
turnId: identifier.optional(),
|
|
90
|
+
productTurnId: identifier.optional(),
|
|
91
|
+
queryId: identifier.optional(),
|
|
92
|
+
requestId: identifier.optional(),
|
|
93
|
+
logicalCallId: identifier.optional(),
|
|
94
|
+
cliVersion: identifier.optional(),
|
|
95
|
+
provider: identifier.optional(),
|
|
96
|
+
model: identifier.optional(),
|
|
97
|
+
details: z.array(localTtftDetailSchema).max(LOCAL_TTFT_MAX_DETAILS).optional(),
|
|
98
|
+
truncated: z.boolean().optional(),
|
|
99
|
+
revision: z.number().int().nonnegative().optional(),
|
|
100
|
+
sendMode: z.enum(["idle", "queued", "guided"]).optional(),
|
|
101
|
+
clockInvalid: z.boolean().optional(),
|
|
102
|
+
receivedAt: time,
|
|
103
|
+
admittedAt: time.optional(),
|
|
104
|
+
executionAt: time.optional(),
|
|
105
|
+
requestAt: time.optional(),
|
|
106
|
+
outputAt: time.optional(),
|
|
107
|
+
outputKind: localTtftOutputKindSchema.optional(),
|
|
108
|
+
terminal: z.enum(["completed", "failed", "cancelled", "rejected", "interrupted"]).optional(),
|
|
109
|
+
excluded: z.enum(["busy", "retry", "unsupported", "failed", "capacity"]).optional(),
|
|
110
|
+
})
|
|
111
|
+
.strict();
|
|
112
|
+
export type LocalTtftFacts = z.infer<typeof localTtftFactsSchema>;
|
|
113
|
+
export const localTtftIntervalSchema = z
|
|
114
|
+
.object({
|
|
115
|
+
stage: z.enum(LOCAL_TTFT_STAGES),
|
|
116
|
+
start: time,
|
|
117
|
+
end: time,
|
|
118
|
+
source: z.enum(["renderer", "cli", "aligned"]),
|
|
119
|
+
})
|
|
120
|
+
.strict()
|
|
121
|
+
.refine((interval) => interval.end >= interval.start);
|
|
122
|
+
export const localTtftRecordSchema = z
|
|
123
|
+
.object({
|
|
124
|
+
version: z.literal(1),
|
|
125
|
+
observationId: z.string().uuid(),
|
|
126
|
+
commandId: identifier.optional(),
|
|
127
|
+
sessionId: identifier.optional(),
|
|
128
|
+
turnId: identifier.optional(),
|
|
129
|
+
productTurnId: identifier.optional(),
|
|
130
|
+
queryId: identifier.optional(),
|
|
131
|
+
requestId: identifier.optional(),
|
|
132
|
+
logicalCallId: identifier.optional(),
|
|
133
|
+
cliVersion: identifier.optional(),
|
|
134
|
+
cliInstanceId: identifier.optional(),
|
|
135
|
+
kind: z.enum(["start", "first_output", "first_text", "no_text", "excluded", "checkpoint"]),
|
|
136
|
+
outcome: z.enum([
|
|
137
|
+
"success",
|
|
138
|
+
"busy",
|
|
139
|
+
"retry",
|
|
140
|
+
"unsupported",
|
|
141
|
+
"failed",
|
|
142
|
+
"cancelled",
|
|
143
|
+
"background",
|
|
144
|
+
"expired",
|
|
145
|
+
"capacity",
|
|
146
|
+
"recovery",
|
|
147
|
+
// 桌面 continuous 缓冲溢出/投影重建后的 online snapshot;不是手机 replayable 恢复。
|
|
148
|
+
"resync",
|
|
149
|
+
"clock_invalid",
|
|
150
|
+
"rejected",
|
|
151
|
+
"interrupted",
|
|
152
|
+
"guided",
|
|
153
|
+
"unclosed",
|
|
154
|
+
]),
|
|
155
|
+
start: time,
|
|
156
|
+
end: time,
|
|
157
|
+
firstOutputKind: localTtftOutputKindSchema.optional(),
|
|
158
|
+
quality: z.enum(["complete", "missing", "clock_invalid"]),
|
|
159
|
+
clockErrorMs: time.optional(),
|
|
160
|
+
intervals: z.array(localTtftIntervalSchema).max(6),
|
|
161
|
+
checkpointId: identifier.optional(),
|
|
162
|
+
details: z.array(localTtftDetailSchema).max(LOCAL_TTFT_MAX_DETAILS).optional(),
|
|
163
|
+
truncated: z.boolean().optional(),
|
|
164
|
+
sendMode: z.enum(["idle", "queued", "guided"]).optional(),
|
|
165
|
+
visibility: z.enum(["foreground", "background", "background_returned"]).optional(),
|
|
166
|
+
visibilityChanges: z
|
|
167
|
+
.array(z.object({ at: time, foreground: z.boolean() }).strict())
|
|
168
|
+
.max(32)
|
|
169
|
+
.optional(),
|
|
170
|
+
userWaitMs: time.optional(),
|
|
171
|
+
executionMs: time.optional(),
|
|
172
|
+
timingReliable: z.boolean().optional(),
|
|
173
|
+
cliTimingReliable: z.boolean().optional(),
|
|
174
|
+
provider: identifier.optional(),
|
|
175
|
+
model: identifier.optional(),
|
|
176
|
+
})
|
|
177
|
+
.strict()
|
|
178
|
+
.refine((record) => record.end >= record.start);
|
|
179
|
+
export type LocalTtftRecord = z.infer<typeof localTtftRecordSchema>;
|
|
180
|
+
export const localTtftBatchSchema = z
|
|
181
|
+
.object({
|
|
182
|
+
version: z.literal(1),
|
|
183
|
+
rendererInstanceId: identifier,
|
|
184
|
+
sequence: z.number().int().nonnegative(),
|
|
185
|
+
records: z.array(localTtftRecordSchema).max(32),
|
|
186
|
+
dropped: z.number().int().nonnegative(),
|
|
187
|
+
})
|
|
188
|
+
.strict();
|
|
189
|
+
export type LocalTtftBatch = z.infer<typeof localTtftBatchSchema>;
|
|
190
|
+
export function localTtftNow(): number {
|
|
191
|
+
return performance.timeOrigin + performance.now();
|
|
192
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { compileModelOptionMap } from "../../model-option-map/src/index.js";
|
|
3
|
+
import { sparseShape } from "./config-schema.js";
|
|
4
|
+
|
|
5
|
+
function optionMapSchema(variableName: "reasoningLevel" | "maxOutputTokens") {
|
|
6
|
+
return z
|
|
7
|
+
.string()
|
|
8
|
+
.min(1)
|
|
9
|
+
.superRefine((source, context) => {
|
|
10
|
+
try {
|
|
11
|
+
compileModelOptionMap(source, variableName);
|
|
12
|
+
} catch (error) {
|
|
13
|
+
context.addIssue({
|
|
14
|
+
code: "custom",
|
|
15
|
+
message: error instanceof Error ? error.message : "Option map 无法编译",
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export const completeEnumOptionSpecDataSchema = z
|
|
22
|
+
.object({
|
|
23
|
+
/** 按语义强度从低到高排列;首项是辅助调用可选的最低公开档位。 */
|
|
24
|
+
values: z
|
|
25
|
+
.array(
|
|
26
|
+
z
|
|
27
|
+
.string()
|
|
28
|
+
.refine((value) => value.trim().length > 0, "reasoningLevel.values 必须是非空字符串"),
|
|
29
|
+
)
|
|
30
|
+
.min(1, "reasoningLevel.values 不能为空")
|
|
31
|
+
.refine((values) => new Set(values).size === values.length, "reasoningLevel.values 不能重复")
|
|
32
|
+
.readonly(),
|
|
33
|
+
map: optionMapSchema("reasoningLevel"),
|
|
34
|
+
})
|
|
35
|
+
.strict();
|
|
36
|
+
|
|
37
|
+
export const completeLimitOptionSpecDataSchema = z
|
|
38
|
+
.object({
|
|
39
|
+
max: z.number().int().positive(),
|
|
40
|
+
map: optionMapSchema("maxOutputTokens"),
|
|
41
|
+
})
|
|
42
|
+
.strict();
|
|
43
|
+
|
|
44
|
+
export const enumOptionSpecDataSchema = z
|
|
45
|
+
.object(sparseShape(completeEnumOptionSpecDataSchema.shape))
|
|
46
|
+
.strict();
|
|
47
|
+
export const limitOptionSpecDataSchema = z
|
|
48
|
+
.object(sparseShape(completeLimitOptionSpecDataSchema.shape))
|
|
49
|
+
.strict();
|
|
50
|
+
|
|
51
|
+
export const completeModelInputFormatDataSchema = z
|
|
52
|
+
.object({
|
|
53
|
+
supportsText: z.boolean(),
|
|
54
|
+
supportsImage: z.boolean(),
|
|
55
|
+
supportsVideo: z.boolean(),
|
|
56
|
+
supportsAudio: z.boolean(),
|
|
57
|
+
supportsPdf: z.boolean(),
|
|
58
|
+
})
|
|
59
|
+
.strict();
|
|
60
|
+
export const completeModelOutputFormatDataSchema = z.object({ supportsText: z.boolean() }).strict();
|
|
61
|
+
export const modelInputFormatDataSchema = z
|
|
62
|
+
.object(sparseShape(completeModelInputFormatDataSchema.shape))
|
|
63
|
+
.strict();
|
|
64
|
+
export const modelOutputFormatDataSchema = z
|
|
65
|
+
.object(sparseShape(completeModelOutputFormatDataSchema.shape))
|
|
66
|
+
.strict();
|
|
67
|
+
|
|
68
|
+
export const completeModelPropertiesDataSchema = z
|
|
69
|
+
.object({
|
|
70
|
+
requiresMfjsToolSchema: z.boolean(),
|
|
71
|
+
contextWindow: z.number().int().positive(),
|
|
72
|
+
inputFormat: completeModelInputFormatDataSchema,
|
|
73
|
+
outputFormat: completeModelOutputFormatDataSchema,
|
|
74
|
+
supportsToolCall: z.boolean(),
|
|
75
|
+
supportsJsonSchemaOutput: z.boolean(),
|
|
76
|
+
supportsNativeWebSearch: z.boolean(),
|
|
77
|
+
supportsMidConversationSystem: z.boolean(),
|
|
78
|
+
})
|
|
79
|
+
.strict();
|
|
80
|
+
export const modelPropertiesDataSchema = z
|
|
81
|
+
.object({
|
|
82
|
+
...sparseShape(completeModelPropertiesDataSchema.shape),
|
|
83
|
+
inputFormat: modelInputFormatDataSchema.nullable().optional(),
|
|
84
|
+
outputFormat: modelOutputFormatDataSchema.nullable().optional(),
|
|
85
|
+
})
|
|
86
|
+
.strict();
|
|
87
|
+
|
|
88
|
+
export const completeModelOptionSpecsDataSchema = z
|
|
89
|
+
.object({
|
|
90
|
+
reasoningLevel: completeEnumOptionSpecDataSchema,
|
|
91
|
+
maxOutputTokens: completeLimitOptionSpecDataSchema,
|
|
92
|
+
})
|
|
93
|
+
.strict();
|
|
94
|
+
export const modelOptionSpecsDataSchema = z
|
|
95
|
+
.object({
|
|
96
|
+
...sparseShape(completeModelOptionSpecsDataSchema.shape),
|
|
97
|
+
reasoningLevel: enumOptionSpecDataSchema.nullable().optional(),
|
|
98
|
+
maxOutputTokens: limitOptionSpecDataSchema.nullable().optional(),
|
|
99
|
+
})
|
|
100
|
+
.strict();
|
|
101
|
+
|
|
102
|
+
export const completeModelConfigDataSchema = z
|
|
103
|
+
.object({
|
|
104
|
+
enabled: z.boolean(),
|
|
105
|
+
properties: completeModelPropertiesDataSchema,
|
|
106
|
+
optionSpecs: completeModelOptionSpecsDataSchema,
|
|
107
|
+
})
|
|
108
|
+
.strict();
|
|
109
|
+
export const modelConfigDataSchema = z
|
|
110
|
+
.object({
|
|
111
|
+
...sparseShape(completeModelConfigDataSchema.shape),
|
|
112
|
+
properties: modelPropertiesDataSchema.nullable().optional(),
|
|
113
|
+
optionSpecs: modelOptionSpecsDataSchema.nullable().optional(),
|
|
114
|
+
})
|
|
115
|
+
.strict();
|
|
116
|
+
|
|
117
|
+
// 跨层只共享数据合同;Provider 行为类与 IO 不进入公共 Schema。
|
|
118
|
+
export type ModelInputFormatData = z.infer<typeof completeModelInputFormatDataSchema>;
|
|
119
|
+
export type ModelOutputFormatData = z.infer<typeof completeModelOutputFormatDataSchema>;
|
|
120
|
+
export type ModelPropertiesData = z.infer<typeof completeModelPropertiesDataSchema>;
|
|
121
|
+
export type EnumOptionSpecData = z.infer<typeof completeEnumOptionSpecDataSchema>;
|
|
122
|
+
export type LimitOptionSpecData = z.infer<typeof completeLimitOptionSpecDataSchema>;
|
|
123
|
+
export type ModelOptionSpecsData = z.infer<typeof completeModelOptionSpecsDataSchema>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/** 文本与附件发送共用执行约束,凭据只属于单次执行,不进入 Session 配置。 */
|
|
4
|
+
export const modelExecutionSchema = z
|
|
5
|
+
.object({
|
|
6
|
+
memoryExtraction: z.literal("skip").optional(),
|
|
7
|
+
selectionScope: z.literal("execution"),
|
|
8
|
+
requestAuth: z
|
|
9
|
+
.object({
|
|
10
|
+
apiKey: z.string().min(1).optional(),
|
|
11
|
+
headers: z.record(z.string().min(1), z.string().min(1)).optional(),
|
|
12
|
+
})
|
|
13
|
+
.strict()
|
|
14
|
+
.optional(),
|
|
15
|
+
subagents: z
|
|
16
|
+
.object({
|
|
17
|
+
foregroundModel: z.literal("submission"),
|
|
18
|
+
background: z.literal("deny"),
|
|
19
|
+
})
|
|
20
|
+
.strict()
|
|
21
|
+
.optional(),
|
|
22
|
+
})
|
|
23
|
+
.strict();
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { BIGMODEL_PROVIDER_ID, type OAuthProviderId, ZAI_PROVIDER_ID } from "./oauth.js";
|
|
2
|
+
import { BUILTIN_MODEL_PROVIDER_IDS, type BuiltinModelProviderId } from "./model-provider-types.js";
|
|
3
|
+
import { ZCODE_ENV } from "./env.js";
|
|
4
|
+
import { buildBigModelCodingPlanTeamManageUrl } from "./zcodeEndpoint.js";
|
|
5
|
+
|
|
6
|
+
export type ModelProviderFamilyId = "zai" | "bigmodel";
|
|
7
|
+
export type ProviderFamilyDomain = ModelProviderFamilyId;
|
|
8
|
+
|
|
9
|
+
export interface ModelProviderFamilySpec {
|
|
10
|
+
id: ModelProviderFamilyId;
|
|
11
|
+
label: string;
|
|
12
|
+
rootDomain: string;
|
|
13
|
+
oauthProviderId: typeof ZAI_PROVIDER_ID | typeof BIGMODEL_PROVIDER_ID;
|
|
14
|
+
startPlanProviderId:
|
|
15
|
+
| typeof BUILTIN_MODEL_PROVIDER_IDS.zaiStartPlan
|
|
16
|
+
| typeof BUILTIN_MODEL_PROVIDER_IDS.bigmodelStartPlan;
|
|
17
|
+
individualCodingPlanProviderId:
|
|
18
|
+
| typeof BUILTIN_MODEL_PROVIDER_IDS.zaiIndividualCodingPlan
|
|
19
|
+
| typeof BUILTIN_MODEL_PROVIDER_IDS.bigmodelIndividualCodingPlan;
|
|
20
|
+
teamCodingPlanProviderId:
|
|
21
|
+
| typeof BUILTIN_MODEL_PROVIDER_IDS.zaiTeamCodingPlan
|
|
22
|
+
| typeof BUILTIN_MODEL_PROVIDER_IDS.bigmodelTeamCodingPlan;
|
|
23
|
+
teamCodingPlanManageUrl: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const MODEL_PROVIDER_FAMILY_SPECS = [
|
|
27
|
+
{
|
|
28
|
+
id: "zai",
|
|
29
|
+
label: "Z.ai",
|
|
30
|
+
rootDomain: "z.ai",
|
|
31
|
+
oauthProviderId: ZAI_PROVIDER_ID,
|
|
32
|
+
startPlanProviderId: BUILTIN_MODEL_PROVIDER_IDS.zaiStartPlan,
|
|
33
|
+
individualCodingPlanProviderId: BUILTIN_MODEL_PROVIDER_IDS.zaiIndividualCodingPlan,
|
|
34
|
+
teamCodingPlanProviderId: BUILTIN_MODEL_PROVIDER_IDS.zaiTeamCodingPlan,
|
|
35
|
+
teamCodingPlanManageUrl: "https://z.ai/manage-apikey/subscription",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: "bigmodel",
|
|
39
|
+
label: "BigModel",
|
|
40
|
+
rootDomain: "bigmodel.cn",
|
|
41
|
+
oauthProviderId: BIGMODEL_PROVIDER_ID,
|
|
42
|
+
startPlanProviderId: BUILTIN_MODEL_PROVIDER_IDS.bigmodelStartPlan,
|
|
43
|
+
individualCodingPlanProviderId: BUILTIN_MODEL_PROVIDER_IDS.bigmodelIndividualCodingPlan,
|
|
44
|
+
teamCodingPlanProviderId: BUILTIN_MODEL_PROVIDER_IDS.bigmodelTeamCodingPlan,
|
|
45
|
+
teamCodingPlanManageUrl: buildBigModelCodingPlanTeamManageUrl({ ZCODE_ENV }),
|
|
46
|
+
},
|
|
47
|
+
] as const satisfies readonly ModelProviderFamilySpec[];
|
|
48
|
+
|
|
49
|
+
const MODEL_PROVIDER_FAMILY_SPEC_BY_ID = new Map<ModelProviderFamilyId, ModelProviderFamilySpec>(
|
|
50
|
+
MODEL_PROVIDER_FAMILY_SPECS.map((spec) => [spec.id, spec]),
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const MODEL_PROVIDER_FAMILY_ID_BY_PROVIDER_ID = new Map<
|
|
54
|
+
BuiltinModelProviderId,
|
|
55
|
+
ModelProviderFamilyId
|
|
56
|
+
>(
|
|
57
|
+
MODEL_PROVIDER_FAMILY_SPECS.flatMap((spec) =>
|
|
58
|
+
[
|
|
59
|
+
spec.startPlanProviderId,
|
|
60
|
+
spec.individualCodingPlanProviderId,
|
|
61
|
+
spec.teamCodingPlanProviderId,
|
|
62
|
+
].map((providerId) => [providerId, spec.id] as const),
|
|
63
|
+
),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
export function getModelProviderFamilySpec(
|
|
67
|
+
familyId: ModelProviderFamilyId,
|
|
68
|
+
): ModelProviderFamilySpec {
|
|
69
|
+
return MODEL_PROVIDER_FAMILY_SPEC_BY_ID.get(familyId)!;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function resolveModelProviderFamilyIdByProviderId(
|
|
73
|
+
providerId: string,
|
|
74
|
+
): ModelProviderFamilyId | null {
|
|
75
|
+
return MODEL_PROVIDER_FAMILY_ID_BY_PROVIDER_ID.get(providerId as BuiltinModelProviderId) ?? null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function resolveModelProviderFamilyIdByBaseURL(
|
|
79
|
+
baseURL: string | null | undefined,
|
|
80
|
+
): ModelProviderFamilyId | null {
|
|
81
|
+
const trimmed = baseURL?.trim();
|
|
82
|
+
if (!trimmed) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
let hostname: string;
|
|
86
|
+
try {
|
|
87
|
+
hostname = new URL(trimmed).hostname.toLowerCase();
|
|
88
|
+
} catch {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
for (const spec of MODEL_PROVIDER_FAMILY_SPECS) {
|
|
92
|
+
if (hostname === spec.rootDomain || hostname.endsWith(`.${spec.rootDomain}`)) {
|
|
93
|
+
return spec.id;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function resolveModelProviderFamilySpecByProviderId(
|
|
100
|
+
providerId: string,
|
|
101
|
+
): ModelProviderFamilySpec | null {
|
|
102
|
+
const familyId = resolveModelProviderFamilyIdByProviderId(providerId);
|
|
103
|
+
return familyId ? getModelProviderFamilySpec(familyId) : null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function resolveModelProviderFamilyLabelByProviderId(providerId: string): string | null {
|
|
107
|
+
return resolveModelProviderFamilySpecByProviderId(providerId)?.label ?? null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function normalizeProviderFamilyDomain(
|
|
111
|
+
value: string | null | undefined,
|
|
112
|
+
): ProviderFamilyDomain | null {
|
|
113
|
+
return value === "zai" || value === "bigmodel" ? value : null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function resolveProviderFamilyDomainFromOAuthProvider(
|
|
117
|
+
provider: OAuthProviderId | string | null | undefined,
|
|
118
|
+
): ProviderFamilyDomain | null {
|
|
119
|
+
if (provider === ZAI_PROVIDER_ID) {
|
|
120
|
+
return "zai";
|
|
121
|
+
}
|
|
122
|
+
if (provider === BIGMODEL_PROVIDER_ID) {
|
|
123
|
+
return "bigmodel";
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function shouldShowModelProviderFamilyForDomain(params: {
|
|
129
|
+
familyId: ModelProviderFamilyId;
|
|
130
|
+
providerFamilyDomain: ProviderFamilyDomain | null | undefined;
|
|
131
|
+
}): boolean {
|
|
132
|
+
const providerFamilyDomain = normalizeProviderFamilyDomain(params.providerFamilyDomain);
|
|
133
|
+
if (!providerFamilyDomain) {
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
return params.familyId === providerFamilyDomain;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function shouldShowModelProviderFamilyForActiveOAuth(params: {
|
|
140
|
+
familyId: ModelProviderFamilyId;
|
|
141
|
+
activeOAuthProvider: OAuthProviderId | null | undefined;
|
|
142
|
+
}): boolean {
|
|
143
|
+
return shouldShowModelProviderFamilyForDomain({
|
|
144
|
+
familyId: params.familyId,
|
|
145
|
+
providerFamilyDomain: resolveProviderFamilyDomainFromOAuthProvider(params.activeOAuthProvider),
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function shouldShowBuiltinModelProviderForDomain(params: {
|
|
150
|
+
providerId: string;
|
|
151
|
+
providerFamilyDomain: ProviderFamilyDomain | null | undefined;
|
|
152
|
+
}): boolean {
|
|
153
|
+
const familyId = resolveModelProviderFamilyIdByProviderId(params.providerId);
|
|
154
|
+
if (!familyId) {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
return shouldShowModelProviderFamilyForDomain({
|
|
158
|
+
familyId,
|
|
159
|
+
providerFamilyDomain: params.providerFamilyDomain,
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function shouldShowBuiltinModelProviderForActiveOAuth(params: {
|
|
164
|
+
providerId: string;
|
|
165
|
+
activeOAuthProvider: OAuthProviderId | null | undefined;
|
|
166
|
+
}): boolean {
|
|
167
|
+
return shouldShowBuiltinModelProviderForDomain({
|
|
168
|
+
providerId: params.providerId,
|
|
169
|
+
providerFamilyDomain: resolveProviderFamilyDomainFromOAuthProvider(params.activeOAuthProvider),
|
|
170
|
+
});
|
|
171
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/* eslint-disable max-lines -- 模型供应商 schema、迁移和运行时投影 helper 需要共享同一套类型边界,暂时集中在单文件避免契约分散。 */
|
|
2
|
+
export const BUILTIN_PROVIDER_TEMPLATE_IDS = {
|
|
3
|
+
zai: "zai-api",
|
|
4
|
+
bigmodel: "bigmodel-api",
|
|
5
|
+
} as const;
|
|
6
|
+
|
|
7
|
+
export const BUILTIN_MODEL_PROVIDER_IDS = {
|
|
8
|
+
zaiIndividualCodingPlan: "account:zai-individual-coding-plan",
|
|
9
|
+
zaiTeamCodingPlan: "account:zai-team-coding-plan",
|
|
10
|
+
zaiStartPlan: "account:zai-start-plan",
|
|
11
|
+
bigmodelIndividualCodingPlan: "account:bigmodel-individual-coding-plan",
|
|
12
|
+
bigmodelTeamCodingPlan: "account:bigmodel-team-coding-plan",
|
|
13
|
+
bigmodelStartPlan: "account:bigmodel-start-plan",
|
|
14
|
+
} as const;
|
|
15
|
+
|
|
16
|
+
export type BuiltinOAuthProviderId = keyof typeof BUILTIN_MODEL_PROVIDER_IDS;
|
|
17
|
+
|
|
18
|
+
export type BuiltinModelProviderId = (typeof BUILTIN_MODEL_PROVIDER_IDS)[BuiltinOAuthProviderId];
|
|
19
|
+
|
|
20
|
+
export function isBuiltinModelProviderId(id: string): id is BuiltinModelProviderId {
|
|
21
|
+
return (
|
|
22
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.zaiIndividualCodingPlan ||
|
|
23
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.zaiTeamCodingPlan ||
|
|
24
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.zaiStartPlan ||
|
|
25
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.bigmodelIndividualCodingPlan ||
|
|
26
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.bigmodelTeamCodingPlan ||
|
|
27
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.bigmodelStartPlan
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function isZaiCodingPlanProviderId(id: string): boolean {
|
|
32
|
+
return (
|
|
33
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.zaiIndividualCodingPlan ||
|
|
34
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.zaiTeamCodingPlan ||
|
|
35
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.zaiStartPlan
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function isBigModelStartPlanProviderId(id: string): boolean {
|
|
40
|
+
return id === BUILTIN_MODEL_PROVIDER_IDS.bigmodelStartPlan;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function isStartPlanModelProviderId(id: string): boolean {
|
|
44
|
+
return (
|
|
45
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.zaiStartPlan ||
|
|
46
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.bigmodelStartPlan
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* 个人版 Coding Plan(不含 Start Plan 与 Team Plan)。
|
|
52
|
+
* Start Plan 用 disconnected 展示领取/付费卡,Team Plan 有独立文案,
|
|
53
|
+
* "服务端明确无权益"只对个人版需要区分成"未开通"。
|
|
54
|
+
*/
|
|
55
|
+
export function isIndividualCodingPlanModelProviderId(id: string): boolean {
|
|
56
|
+
return (
|
|
57
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.zaiIndividualCodingPlan ||
|
|
58
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.bigmodelIndividualCodingPlan
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function isCodingPlanModelProviderId(id: string): boolean {
|
|
63
|
+
return (
|
|
64
|
+
isZaiCodingPlanProviderId(id) ||
|
|
65
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.bigmodelIndividualCodingPlan ||
|
|
66
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.bigmodelTeamCodingPlan ||
|
|
67
|
+
id === BUILTIN_MODEL_PROVIDER_IDS.bigmodelStartPlan
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** 一个正式 Model 的连通性测试结果。 */
|
|
72
|
+
export type ModelConnectivityResult =
|
|
73
|
+
| { readonly success: true }
|
|
74
|
+
| {
|
|
75
|
+
readonly success: false;
|
|
76
|
+
readonly error: {
|
|
77
|
+
readonly message: string;
|
|
78
|
+
/** 设置连接测试边界已确认的资格失败;其他执行错误保留原消息。 */
|
|
79
|
+
readonly code?: "provider-unavailable" | "model-unavailable";
|
|
80
|
+
};
|
|
81
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/** 用户对后续模型执行的完整选择;不表达已经创建的 Active Model。 */
|
|
4
|
+
export const modelSelectionSchema = z
|
|
5
|
+
.object({
|
|
6
|
+
providerId: z.string().trim().min(1),
|
|
7
|
+
modelId: z.string().trim().min(1),
|
|
8
|
+
options: z
|
|
9
|
+
.object({
|
|
10
|
+
reasoningLevel: z.string().trim().min(1).optional(),
|
|
11
|
+
})
|
|
12
|
+
.strict()
|
|
13
|
+
.optional(),
|
|
14
|
+
})
|
|
15
|
+
.strict();
|
|
16
|
+
|
|
17
|
+
export type ModelSelection = z.infer<typeof modelSelectionSchema>;
|
|
18
|
+
|
|
19
|
+
/** 公共解析结果。页面可以展示不完整选择,执行入口必须同时检查 selectionIssue。 */
|
|
20
|
+
export interface EffectiveModelSelectionResult {
|
|
21
|
+
readonly effectiveSelection: ModelSelection | null;
|
|
22
|
+
readonly selectionIssue?:
|
|
23
|
+
| "selection-missing"
|
|
24
|
+
| "account-connection-unavailable"
|
|
25
|
+
| "provider-not-found"
|
|
26
|
+
| "model-not-found"
|
|
27
|
+
| "reasoning-level-missing"
|
|
28
|
+
| "reasoning-level-not-supported";
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export const ZCODE_MODEL_REASONING_SEPARATOR = "$";
|
|
32
|
+
|
|
33
|
+
/** UI Picker/legacy CLI 的展示值;不是可逆的 ModelSelection 序列化格式。 */
|
|
34
|
+
export function formatModelPickerValue(selection: ModelSelection | undefined): string {
|
|
35
|
+
// 只在显示边界把未绑定表示为空;实际执行仍校验完整 ModelSelection。
|
|
36
|
+
if (!selection) return "";
|
|
37
|
+
const base = `${selection.providerId}/${selection.modelId}`;
|
|
38
|
+
const reasoningLevel = selection.options?.reasoningLevel;
|
|
39
|
+
return reasoningLevel ? `${base}${ZCODE_MODEL_REASONING_SEPARATOR}${reasoningLevel}` : base;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** 只解析 Picker/legacy 字符串边界;领域状态与协议必须直接保存 ModelSelection。 */
|
|
43
|
+
export function parseModelPickerValue(value: string): ModelSelection {
|
|
44
|
+
const normalized = value.trim();
|
|
45
|
+
const providerSeparatorIndex = normalized.indexOf("/");
|
|
46
|
+
if (providerSeparatorIndex <= 0) {
|
|
47
|
+
throw new Error(`模型选择缺少 Provider: ${normalized}`);
|
|
48
|
+
}
|
|
49
|
+
const providerId = normalized.slice(0, providerSeparatorIndex);
|
|
50
|
+
const rawModelId = normalized.slice(providerSeparatorIndex + 1);
|
|
51
|
+
const reasoningSeparatorIndex = rawModelId.indexOf(ZCODE_MODEL_REASONING_SEPARATOR);
|
|
52
|
+
if (reasoningSeparatorIndex <= 0 || reasoningSeparatorIndex >= rawModelId.length - 1) {
|
|
53
|
+
return modelSelectionSchema.parse({ providerId, modelId: rawModelId });
|
|
54
|
+
}
|
|
55
|
+
return modelSelectionSchema.parse({
|
|
56
|
+
providerId,
|
|
57
|
+
modelId: rawModelId.slice(0, reasoningSeparatorIndex),
|
|
58
|
+
options: { reasoningLevel: rawModelId.slice(reasoningSeparatorIndex + 1) },
|
|
59
|
+
});
|
|
60
|
+
}
|