dsh-github-copilot 0.4.0-alpha.19 → 0.4.0-alpha.20
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/AGENTS.md +6 -1
- package/CHANGELOG.md +8 -0
- package/README.md +16 -6
- package/README.zh.md +16 -6
- package/deployment-baseline.json +2 -1
- package/docs/dual-model.md +63 -0
- package/docs/images/dual-model-desktop.png +0 -0
- package/docs/images/dual-model-mobile.png +0 -0
- package/docs/images/dual-model-provenance.json +35 -0
- package/docs/npm-distribution.md +68 -12
- package/lib/client.js +721 -42
- package/lib/client.js.map +1 -1
- package/lib/index.js +741 -4
- package/lib/remote.js +129 -29
- package/lib/types/client.d.ts +1 -0
- package/lib/types/dual-model-card.d.ts +51 -0
- package/lib/types/dual-model-host.d.ts +119 -0
- package/lib/types/dual-model-remote.d.ts +63 -0
- package/lib/types/dual-model-types.d.ts +34 -0
- package/lib/types/dual-model-ui.d.ts +5 -0
- package/package.json +6 -1
package/lib/client.js
CHANGED
|
@@ -5366,6 +5366,102 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5366
5366
|
return /* @__PURE__ */ _superRefine(fn, params);
|
|
5367
5367
|
}
|
|
5368
5368
|
//#endregion
|
|
5369
|
+
//#region lib/types/dual-model-remote.js
|
|
5370
|
+
const id = string().min(1).max(512);
|
|
5371
|
+
const revision = number().int().nonnegative().max(Number.MAX_SAFE_INTEGER);
|
|
5372
|
+
const DualModelConfigSchema = object({
|
|
5373
|
+
enabled: boolean(),
|
|
5374
|
+
plannerModel: string().max(512),
|
|
5375
|
+
executorModel: string().max(512)
|
|
5376
|
+
}).strict();
|
|
5377
|
+
const DualModelViewSchema = object({
|
|
5378
|
+
supported: boolean(),
|
|
5379
|
+
diagnostic: string().min(1).max(128).optional(),
|
|
5380
|
+
writable: boolean(),
|
|
5381
|
+
revision: revision.nullable(),
|
|
5382
|
+
configuration: DualModelConfigSchema,
|
|
5383
|
+
models: array(object({
|
|
5384
|
+
id,
|
|
5385
|
+
name: string().min(1).max(1024)
|
|
5386
|
+
}).strict()).max(512),
|
|
5387
|
+
workspaces: array(object({
|
|
5388
|
+
id,
|
|
5389
|
+
name: string().min(1).max(1024)
|
|
5390
|
+
}).strict()).max(1024)
|
|
5391
|
+
}).strict();
|
|
5392
|
+
const DualModelSaveSchema = object({
|
|
5393
|
+
configuration: DualModelConfigSchema,
|
|
5394
|
+
expectedRevision: revision
|
|
5395
|
+
}).strict();
|
|
5396
|
+
const DualModelCreateSchema = object({
|
|
5397
|
+
requestId: string().uuid(),
|
|
5398
|
+
workspaceId: id,
|
|
5399
|
+
expectedRevision: revision
|
|
5400
|
+
}).strict();
|
|
5401
|
+
const DualModelCreateResultSchema = object({ sessionId: id }).strict();
|
|
5402
|
+
const contribution$1 = {
|
|
5403
|
+
package: "dsh-github-copilot",
|
|
5404
|
+
descriptors: [
|
|
5405
|
+
{
|
|
5406
|
+
id: "dsh-github-copilot:githubCopilotDualModel.view",
|
|
5407
|
+
namespace: "githubCopilotDualModel",
|
|
5408
|
+
service: "githubCopilotDualModel",
|
|
5409
|
+
method: "view",
|
|
5410
|
+
invocation: { kind: "direct" },
|
|
5411
|
+
parameters: [],
|
|
5412
|
+
result: {
|
|
5413
|
+
mode: "strict",
|
|
5414
|
+
typeSymbol: "dsh-github-copilot#DualModelView",
|
|
5415
|
+
schema: DualModelViewSchema
|
|
5416
|
+
}
|
|
5417
|
+
},
|
|
5418
|
+
{
|
|
5419
|
+
id: "dsh-github-copilot:githubCopilotDualModel.save",
|
|
5420
|
+
namespace: "githubCopilotDualModel",
|
|
5421
|
+
service: "githubCopilotDualModel",
|
|
5422
|
+
method: "save",
|
|
5423
|
+
invocation: { kind: "direct" },
|
|
5424
|
+
parameters: [{
|
|
5425
|
+
name: "input",
|
|
5426
|
+
wire: "input",
|
|
5427
|
+
source: "json",
|
|
5428
|
+
codec: {
|
|
5429
|
+
mode: "strict",
|
|
5430
|
+
typeSymbol: "dsh-github-copilot#DualModelSaveRequest",
|
|
5431
|
+
schema: DualModelSaveSchema
|
|
5432
|
+
}
|
|
5433
|
+
}],
|
|
5434
|
+
result: {
|
|
5435
|
+
mode: "strict",
|
|
5436
|
+
typeSymbol: "dsh-github-copilot#DualModelView",
|
|
5437
|
+
schema: DualModelViewSchema
|
|
5438
|
+
}
|
|
5439
|
+
},
|
|
5440
|
+
{
|
|
5441
|
+
id: "dsh-github-copilot:githubCopilotDualModel.create",
|
|
5442
|
+
namespace: "githubCopilotDualModel",
|
|
5443
|
+
service: "githubCopilotDualModel",
|
|
5444
|
+
method: "create",
|
|
5445
|
+
invocation: { kind: "direct" },
|
|
5446
|
+
parameters: [{
|
|
5447
|
+
name: "input",
|
|
5448
|
+
wire: "input",
|
|
5449
|
+
source: "json",
|
|
5450
|
+
codec: {
|
|
5451
|
+
mode: "strict",
|
|
5452
|
+
typeSymbol: "dsh-github-copilot#DualModelCreateRequest",
|
|
5453
|
+
schema: DualModelCreateSchema
|
|
5454
|
+
}
|
|
5455
|
+
}],
|
|
5456
|
+
result: {
|
|
5457
|
+
mode: "strict",
|
|
5458
|
+
typeSymbol: "dsh-github-copilot#DualModelCreateResult",
|
|
5459
|
+
schema: DualModelCreateResultSchema
|
|
5460
|
+
}
|
|
5461
|
+
}
|
|
5462
|
+
]
|
|
5463
|
+
};
|
|
5464
|
+
//#endregion
|
|
5369
5465
|
//#region lib/types/remote.js
|
|
5370
5466
|
/**
|
|
5371
5467
|
* Client-safe Remote contribution for the plugin-owned authorization bridge.
|
|
@@ -5495,35 +5591,39 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5495
5591
|
}).strict();
|
|
5496
5592
|
const contribution = {
|
|
5497
5593
|
package: "dsh-github-copilot",
|
|
5498
|
-
descriptors: [
|
|
5499
|
-
|
|
5500
|
-
|
|
5501
|
-
|
|
5502
|
-
|
|
5503
|
-
|
|
5504
|
-
|
|
5505
|
-
|
|
5506
|
-
|
|
5507
|
-
|
|
5508
|
-
|
|
5509
|
-
|
|
5510
|
-
|
|
5511
|
-
|
|
5512
|
-
|
|
5513
|
-
|
|
5514
|
-
|
|
5515
|
-
|
|
5516
|
-
|
|
5517
|
-
|
|
5518
|
-
|
|
5519
|
-
|
|
5520
|
-
|
|
5521
|
-
|
|
5522
|
-
|
|
5523
|
-
|
|
5524
|
-
|
|
5525
|
-
|
|
5526
|
-
|
|
5594
|
+
descriptors: [
|
|
5595
|
+
...[
|
|
5596
|
+
"status",
|
|
5597
|
+
"reconcile",
|
|
5598
|
+
"discoverModels",
|
|
5599
|
+
"ensureModels",
|
|
5600
|
+
"start",
|
|
5601
|
+
"cancel",
|
|
5602
|
+
"signOut"
|
|
5603
|
+
].map((method) => ({
|
|
5604
|
+
id: `dsh-github-copilot:githubCopilot.${method}`,
|
|
5605
|
+
service: "githubCopilotAuthorization",
|
|
5606
|
+
namespace: "githubCopilot",
|
|
5607
|
+
method,
|
|
5608
|
+
invocation: direct,
|
|
5609
|
+
parameters: [],
|
|
5610
|
+
result
|
|
5611
|
+
})),
|
|
5612
|
+
{
|
|
5613
|
+
id: "dsh-github-copilot:githubCopilot.migrationStatus",
|
|
5614
|
+
service: "githubCopilotAuthorization",
|
|
5615
|
+
namespace: "githubCopilot",
|
|
5616
|
+
method: "migrationStatus",
|
|
5617
|
+
invocation: direct,
|
|
5618
|
+
parameters: [],
|
|
5619
|
+
result: {
|
|
5620
|
+
mode: "strict",
|
|
5621
|
+
typeSymbol: GITHUB_COPILOT_MIGRATION_STATUS_TYPE_SYMBOL,
|
|
5622
|
+
schema: GitHubCopilotMigrationStatusSchema
|
|
5623
|
+
}
|
|
5624
|
+
},
|
|
5625
|
+
...contribution$1.descriptors
|
|
5626
|
+
]
|
|
5527
5627
|
};
|
|
5528
5628
|
//#endregion
|
|
5529
5629
|
//#region lib/types/copilot-identity.js
|
|
@@ -5788,7 +5888,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5788
5888
|
const DEEPSEEK_SEARCH_PROVIDER = "deepseek-official";
|
|
5789
5889
|
const EXA_SEARCH_PROVIDER = "exa";
|
|
5790
5890
|
const PERPLEXITY_SEARCH_PROVIDER = "perplexity";
|
|
5791
|
-
const cardStyle = {
|
|
5891
|
+
const cardStyle$1 = {
|
|
5792
5892
|
display: "grid",
|
|
5793
5893
|
gap: "14px",
|
|
5794
5894
|
padding: "18px",
|
|
@@ -5797,11 +5897,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5797
5897
|
borderRadius: "14px",
|
|
5798
5898
|
background: "color-mix(in srgb, currentColor 4%, transparent)"
|
|
5799
5899
|
};
|
|
5800
|
-
const fieldStyle = {
|
|
5900
|
+
const fieldStyle$1 = {
|
|
5801
5901
|
display: "grid",
|
|
5802
5902
|
gap: "6px"
|
|
5803
5903
|
};
|
|
5804
|
-
const controlStyle = {
|
|
5904
|
+
const controlStyle$1 = {
|
|
5805
5905
|
width: "100%",
|
|
5806
5906
|
padding: "9px 11px",
|
|
5807
5907
|
borderRadius: "9px",
|
|
@@ -5810,7 +5910,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
5810
5910
|
background: "color-mix(in srgb, currentColor 3%, transparent)",
|
|
5811
5911
|
font: "inherit"
|
|
5812
5912
|
};
|
|
5813
|
-
const buttonStyle = {
|
|
5913
|
+
const buttonStyle$1 = {
|
|
5814
5914
|
justifySelf: "start",
|
|
5815
5915
|
padding: "9px 16px",
|
|
5816
5916
|
borderRadius: "999px",
|
|
@@ -6003,7 +6103,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6003
6103
|
usesCopilot
|
|
6004
6104
|
]);
|
|
6005
6105
|
return (0, react.createElement)("section", {
|
|
6006
|
-
style: cardStyle,
|
|
6106
|
+
style: cardStyle$1,
|
|
6007
6107
|
"data-dsh-web-search-routing": true
|
|
6008
6108
|
}, (0, react.createElement)("div", null, (0, react.createElement)("h3", { style: {
|
|
6009
6109
|
margin: 0,
|
|
@@ -6013,11 +6113,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6013
6113
|
opacity: .72,
|
|
6014
6114
|
fontSize: "13px",
|
|
6015
6115
|
lineHeight: 1.5
|
|
6016
|
-
} }, "Auto tries native search for the initiating Copilot model, then the default provider when unavailable. Other model providers use the default directly. Fixed always uses the default. Chat remains available when search is unavailable.")), (0, react.createElement)("label", { style: fieldStyle }, (0, react.createElement)("span", { style: {
|
|
6116
|
+
} }, "Auto tries native search for the initiating Copilot model, then the default provider when unavailable. Other model providers use the default directly. Fixed always uses the default. Chat remains available when search is unavailable.")), (0, react.createElement)("label", { style: fieldStyle$1 }, (0, react.createElement)("span", { style: {
|
|
6017
6117
|
fontSize: "13px",
|
|
6018
6118
|
fontWeight: 600
|
|
6019
6119
|
} }, "Search mode"), (0, react.createElement)("select", {
|
|
6020
|
-
style: controlStyle,
|
|
6120
|
+
style: controlStyle$1,
|
|
6021
6121
|
disabled,
|
|
6022
6122
|
value: draft.mode,
|
|
6023
6123
|
"data-dsh-web-search-mode": true,
|
|
@@ -6028,11 +6128,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6028
6128
|
mode
|
|
6029
6129
|
}));
|
|
6030
6130
|
}
|
|
6031
|
-
}, (0, react.createElement)("option", { value: "auto" }, "Auto — native Copilot search first, then default provider"), (0, react.createElement)("option", { value: "fixed" }, "Fixed — always use the default provider"))), (0, react.createElement)("label", { style: fieldStyle }, (0, react.createElement)("span", { style: {
|
|
6131
|
+
}, (0, react.createElement)("option", { value: "auto" }, "Auto — native Copilot search first, then default provider"), (0, react.createElement)("option", { value: "fixed" }, "Fixed — always use the default provider"))), (0, react.createElement)("label", { style: fieldStyle$1 }, (0, react.createElement)("span", { style: {
|
|
6032
6132
|
fontSize: "13px",
|
|
6033
6133
|
fontWeight: 600
|
|
6034
6134
|
} }, "Default search provider"), (0, react.createElement)("input", {
|
|
6035
|
-
style: controlStyle,
|
|
6135
|
+
style: controlStyle$1,
|
|
6036
6136
|
list: "dsh-search-provider-options",
|
|
6037
6137
|
disabled,
|
|
6038
6138
|
value: draft.provider,
|
|
@@ -6052,11 +6152,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6052
6152
|
}))), (0, react.createElement)("span", { style: {
|
|
6053
6153
|
opacity: .66,
|
|
6054
6154
|
fontSize: "12px"
|
|
6055
|
-
} }, "Suggestions are examples, not installed-provider or capability checks. Enter any registered search provider id, or none; unavailable providers fail without affecting chat.")), !usesCopilot ? null : (0, react.createElement)("label", { style: fieldStyle }, (0, react.createElement)("span", { style: {
|
|
6155
|
+
} }, "Suggestions are examples, not installed-provider or capability checks. Enter any registered search provider id, or none; unavailable providers fail without affecting chat.")), !usesCopilot ? null : (0, react.createElement)("label", { style: fieldStyle$1 }, (0, react.createElement)("span", { style: {
|
|
6056
6156
|
fontSize: "13px",
|
|
6057
6157
|
fontWeight: 600
|
|
6058
6158
|
} }, "Copilot search model"), (0, react.createElement)("input", {
|
|
6059
|
-
style: controlStyle,
|
|
6159
|
+
style: controlStyle$1,
|
|
6060
6160
|
list: "dsh-copilot-search-models",
|
|
6061
6161
|
disabled: disabled || missingCopilot,
|
|
6062
6162
|
value: draft.model,
|
|
@@ -6085,7 +6185,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6085
6185
|
flexWrap: "wrap"
|
|
6086
6186
|
} }, (0, react.createElement)("button", {
|
|
6087
6187
|
type: "button",
|
|
6088
|
-
style: buttonStyle,
|
|
6188
|
+
style: buttonStyle$1,
|
|
6089
6189
|
disabled: disabled || missingCopilot,
|
|
6090
6190
|
"data-dsh-web-search-save": true,
|
|
6091
6191
|
onClick: () => {
|
|
@@ -6093,7 +6193,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6093
6193
|
}
|
|
6094
6194
|
}, loading ? "Loading…" : saving ? "Saving…" : "Save search routing"), (0, react.createElement)("button", {
|
|
6095
6195
|
type: "button",
|
|
6096
|
-
style: buttonStyle,
|
|
6196
|
+
style: buttonStyle$1,
|
|
6097
6197
|
disabled: loading || saving,
|
|
6098
6198
|
title: "Reload saved values and discard unsaved edits",
|
|
6099
6199
|
"data-dsh-web-search-reload": true,
|
|
@@ -6109,6 +6209,582 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
6109
6209
|
}, message)));
|
|
6110
6210
|
}
|
|
6111
6211
|
//#endregion
|
|
6212
|
+
//#region lib/types/dual-model-card.js
|
|
6213
|
+
const creations = /* @__PURE__ */ new WeakMap();
|
|
6214
|
+
const off = {
|
|
6215
|
+
enabled: false,
|
|
6216
|
+
plannerModel: "",
|
|
6217
|
+
executorModel: ""
|
|
6218
|
+
};
|
|
6219
|
+
const copy = {
|
|
6220
|
+
en: {
|
|
6221
|
+
title: "Model roles",
|
|
6222
|
+
description: "The planning model plans and reviews acceptance. The execution model changes code and runs tests.",
|
|
6223
|
+
scope: "Only new dual-model sessions use this configuration. Existing sessions and the global default stay unchanged. Models are never substituted automatically.",
|
|
6224
|
+
enabled: "Enable dual-model sessions",
|
|
6225
|
+
planner: "Planning model",
|
|
6226
|
+
executor: "Execution model",
|
|
6227
|
+
acceptance: "Acceptance always uses the planning model.",
|
|
6228
|
+
selectModel: "Select an available model",
|
|
6229
|
+
unavailable: "unavailable",
|
|
6230
|
+
modelsMissing: "Choose two available account models to save an enabled configuration. An unavailable saved model is kept, not replaced.",
|
|
6231
|
+
workspace: "Workspace for the new session",
|
|
6232
|
+
selectWorkspace: "Select a workspace",
|
|
6233
|
+
noWorkspaces: "No accessible workspaces are available. Reload settings after opening a workspace.",
|
|
6234
|
+
save: "Save configuration",
|
|
6235
|
+
saving: "Saving…",
|
|
6236
|
+
create: "Create session with this configuration",
|
|
6237
|
+
creating: "Creating session…",
|
|
6238
|
+
retryCreate: "Retry the same creation request",
|
|
6239
|
+
openCreated: "Open created session",
|
|
6240
|
+
reload: "Reload settings",
|
|
6241
|
+
reloadTitle: "Reload saved values and discard unsaved edits",
|
|
6242
|
+
loading: "Loading model roles…",
|
|
6243
|
+
dirty: "Save your changes before creating a session.",
|
|
6244
|
+
disabled: "Dual-model sessions are off. You can save this configuration, but cannot create a dual-model session.",
|
|
6245
|
+
readonly: "These settings are read-only. Ask the deployment owner to enable writes, then reload settings.",
|
|
6246
|
+
unsupported: "Dual-model sessions are unavailable in this deployment. Check plugin support, then reload settings.",
|
|
6247
|
+
revision: "A settings revision is unavailable. Reload settings before saving or creating a session.",
|
|
6248
|
+
conflict: "These settings changed elsewhere. Reload settings to review the saved configuration before trying again.",
|
|
6249
|
+
modelUnavailable: "A selected model is unavailable. Reload settings and choose available account models. No model was substituted.",
|
|
6250
|
+
workspaceUnavailable: "The selected workspace is unavailable. Reload settings and choose an accessible workspace.",
|
|
6251
|
+
loadError: "Could not load model roles. Reload settings to retry.",
|
|
6252
|
+
saveError: "The save was not confirmed. Reload settings to check the saved configuration before trying again.",
|
|
6253
|
+
uncertain: "Session creation is not confirmed. Retry the same request to recover its result without creating a duplicate. Workspace and configuration are held until confirmation.",
|
|
6254
|
+
pending: "A previous creation request needs confirmation. Retry the same request; it is not replayed automatically.",
|
|
6255
|
+
saved: "Saved. This configuration applies only to new dual-model sessions.",
|
|
6256
|
+
created: "Session created.",
|
|
6257
|
+
openError: "Session created, but navigation failed. Open the created session from the session list.",
|
|
6258
|
+
requestUnavailable: "Secure request IDs are unavailable in this browser. Use a secure browser context before creating a session."
|
|
6259
|
+
},
|
|
6260
|
+
zh: {
|
|
6261
|
+
title: "模型分工",
|
|
6262
|
+
description: "主模型负责规划与验收;执行模型负责修改代码和运行测试。",
|
|
6263
|
+
scope: "仅对新建的双模型会话生效。已有会话和全局默认模型保持不变。不会自动替换模型。",
|
|
6264
|
+
enabled: "启用双模型会话",
|
|
6265
|
+
planner: "主模型(规划)",
|
|
6266
|
+
executor: "执行模型",
|
|
6267
|
+
acceptance: "验收固定跟随主模型。",
|
|
6268
|
+
selectModel: "选择可用模型",
|
|
6269
|
+
unavailable: "不可用",
|
|
6270
|
+
modelsMissing: "启用时须选择两个当前账号可用的模型才能保存。已保存但不可用的模型会保留,不会自动替换。",
|
|
6271
|
+
workspace: "新会话的工作区",
|
|
6272
|
+
selectWorkspace: "选择工作区",
|
|
6273
|
+
noWorkspaces: "暂无可访问的工作区。打开工作区后重新加载设置。",
|
|
6274
|
+
save: "保存配置",
|
|
6275
|
+
saving: "正在保存…",
|
|
6276
|
+
create: "用此配置新建会话",
|
|
6277
|
+
creating: "正在创建会话…",
|
|
6278
|
+
retryCreate: "重试同一创建请求",
|
|
6279
|
+
openCreated: "打开已创建的会话",
|
|
6280
|
+
reload: "重新加载设置",
|
|
6281
|
+
reloadTitle: "重新读取已保存的配置,并放弃未保存的修改",
|
|
6282
|
+
loading: "正在加载模型分工…",
|
|
6283
|
+
dirty: "请先保存修改,再新建会话。",
|
|
6284
|
+
disabled: "双模型会话已关闭。可以保存配置,但不能新建双模型会话。",
|
|
6285
|
+
readonly: "当前设置为只读。请联系部署管理员启用写入后,重新加载设置。",
|
|
6286
|
+
unsupported: "当前部署不支持双模型会话。请检查插件支持情况后,重新加载设置。",
|
|
6287
|
+
revision: "无法获取设置版本。请重新加载设置后,再保存或新建会话。",
|
|
6288
|
+
conflict: "设置已在其他位置修改。请重新加载,检查已保存的配置后再重试。",
|
|
6289
|
+
modelUnavailable: "所选模型当前不可用。请重新加载设置并选择可用模型。未自动替换任何模型。",
|
|
6290
|
+
workspaceUnavailable: "所选工作区当前不可用。请重新加载设置并选择可访问的工作区。",
|
|
6291
|
+
loadError: "无法加载模型分工。请重新加载设置以重试。",
|
|
6292
|
+
saveError: "尚未确认保存结果。请重新加载并检查已保存的配置后再重试。",
|
|
6293
|
+
uncertain: "尚未确认会话创建结果。请重试同一请求以获取结果,避免重复创建。确认前将保持原工作区和配置不变。",
|
|
6294
|
+
pending: "上次创建请求的结果尚待确认。请重试同一请求;不会自动重新提交。",
|
|
6295
|
+
saved: "已保存。配置仅用于新建的双模型会话。",
|
|
6296
|
+
created: "会话已创建。",
|
|
6297
|
+
openError: "会话已创建,但无法自动打开。请从会话列表打开。",
|
|
6298
|
+
requestUnavailable: "当前浏览器无法生成安全的请求标识。请使用安全浏览器环境后再创建会话。"
|
|
6299
|
+
}
|
|
6300
|
+
};
|
|
6301
|
+
const diagnosticMessages = {
|
|
6302
|
+
DUAL_MODEL_UNSUPPORTED: "unsupported",
|
|
6303
|
+
DUAL_MODEL_READ_ONLY: "readonly",
|
|
6304
|
+
DUAL_MODEL_REVISION_CONFLICT: "conflict",
|
|
6305
|
+
DUAL_MODEL_MODEL_UNAVAILABLE: "modelUnavailable",
|
|
6306
|
+
DUAL_MODEL_WORKSPACE_UNAVAILABLE: "workspaceUnavailable",
|
|
6307
|
+
DUAL_MODEL_DISABLED: "disabled"
|
|
6308
|
+
};
|
|
6309
|
+
function diagnostic(value) {
|
|
6310
|
+
let code = value;
|
|
6311
|
+
if (typeof value === "object" && value !== null) {
|
|
6312
|
+
const details = "details" in value ? value.details : void 0;
|
|
6313
|
+
code = typeof details === "object" && details !== null && "reason" in details ? details.reason : "code" in value ? value.code : void 0;
|
|
6314
|
+
}
|
|
6315
|
+
return typeof code === "string" && Object.hasOwn(diagnosticMessages, code) ? diagnosticMessages[code] : void 0;
|
|
6316
|
+
}
|
|
6317
|
+
/** A reason alone says nothing about an earlier attempt with the same UUID. */
|
|
6318
|
+
function notCreatedDiagnostic(value) {
|
|
6319
|
+
if (typeof value !== "object" || value === null || !("details" in value)) return void 0;
|
|
6320
|
+
const details = value.details;
|
|
6321
|
+
if (typeof details !== "object" || details === null || !("creation" in details) || details.creation !== "not-created" || !("reason" in details) || typeof details.reason !== "string") return void 0;
|
|
6322
|
+
return diagnostic(details.reason);
|
|
6323
|
+
}
|
|
6324
|
+
function validRevision(value) {
|
|
6325
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
6326
|
+
}
|
|
6327
|
+
function validView(value) {
|
|
6328
|
+
const namedItems = (items) => Array.isArray(items) && items.every((item) => item && typeof item.id === "string" && item.id.length > 0 && typeof item.name === "string") && new Set(items.map((item) => item.id)).size === items.length;
|
|
6329
|
+
return !!value && typeof value.supported === "boolean" && typeof value.writable === "boolean" && (value.revision === null || validRevision(value.revision)) && !!value.configuration && typeof value.configuration.enabled === "boolean" && typeof value.configuration.plannerModel === "string" && typeof value.configuration.executorModel === "string" && namedItems(value.models) && namedItems(value.workspaces);
|
|
6330
|
+
}
|
|
6331
|
+
function sameConfig(a, b) {
|
|
6332
|
+
return a.enabled === b.enabled && a.plannerModel === b.plannerModel && a.executorModel === b.executorModel;
|
|
6333
|
+
}
|
|
6334
|
+
const cardStyle = {
|
|
6335
|
+
display: "grid",
|
|
6336
|
+
gap: "14px",
|
|
6337
|
+
padding: "18px",
|
|
6338
|
+
marginTop: "16px",
|
|
6339
|
+
minWidth: 0,
|
|
6340
|
+
border: "1px solid color-mix(in srgb, currentColor 20%, transparent)",
|
|
6341
|
+
borderRadius: "14px",
|
|
6342
|
+
background: "color-mix(in srgb, currentColor 4%, transparent)",
|
|
6343
|
+
overflowWrap: "anywhere"
|
|
6344
|
+
};
|
|
6345
|
+
const fieldStyle = {
|
|
6346
|
+
display: "grid",
|
|
6347
|
+
gap: "6px",
|
|
6348
|
+
minWidth: 0
|
|
6349
|
+
};
|
|
6350
|
+
const textStyle = {
|
|
6351
|
+
margin: 0,
|
|
6352
|
+
fontSize: "13px",
|
|
6353
|
+
lineHeight: 1.5
|
|
6354
|
+
};
|
|
6355
|
+
const labelStyle = {
|
|
6356
|
+
fontSize: "13px",
|
|
6357
|
+
fontWeight: 600
|
|
6358
|
+
};
|
|
6359
|
+
const controlStyle = {
|
|
6360
|
+
width: "100%",
|
|
6361
|
+
minWidth: 0,
|
|
6362
|
+
boxSizing: "border-box",
|
|
6363
|
+
padding: "9px 11px",
|
|
6364
|
+
borderRadius: "9px",
|
|
6365
|
+
color: "inherit",
|
|
6366
|
+
border: "1px solid color-mix(in srgb, currentColor 24%, transparent)",
|
|
6367
|
+
background: "color-mix(in srgb, currentColor 3%, transparent)",
|
|
6368
|
+
font: "inherit"
|
|
6369
|
+
};
|
|
6370
|
+
const buttonStyle = {
|
|
6371
|
+
padding: "9px 16px",
|
|
6372
|
+
maxWidth: "100%",
|
|
6373
|
+
borderRadius: "999px",
|
|
6374
|
+
cursor: "pointer",
|
|
6375
|
+
whiteSpace: "normal",
|
|
6376
|
+
overflowWrap: "anywhere",
|
|
6377
|
+
font: "inherit",
|
|
6378
|
+
color: "inherit",
|
|
6379
|
+
border: "1px solid color-mix(in srgb, currentColor 30%, transparent)",
|
|
6380
|
+
background: "color-mix(in srgb, currentColor 10%, transparent)"
|
|
6381
|
+
};
|
|
6382
|
+
const styleForButton = (disabled) => ({
|
|
6383
|
+
...buttonStyle,
|
|
6384
|
+
opacity: disabled ? .55 : 1,
|
|
6385
|
+
cursor: disabled ? "not-allowed" : "pointer"
|
|
6386
|
+
});
|
|
6387
|
+
/** Additive Models settings card. All mutations belong to the injected scoped Remote. */
|
|
6388
|
+
function DualModelCard(props) {
|
|
6389
|
+
const t = props.locale?.toLowerCase().startsWith("zh") ? copy.zh : copy.en;
|
|
6390
|
+
const id = (0, react.useId)();
|
|
6391
|
+
const [view, setView] = (0, react.useState)();
|
|
6392
|
+
const [draft, setDraft] = (0, react.useState)(off);
|
|
6393
|
+
const [workspace, setWorkspace] = (0, react.useState)("");
|
|
6394
|
+
const [phase, setPhase] = (0, react.useState)("loading");
|
|
6395
|
+
const [message, setMessage] = (0, react.useState)();
|
|
6396
|
+
const [needsReload, setNeedsReload] = (0, react.useState)(false);
|
|
6397
|
+
const [pending, setPending] = (0, react.useState)();
|
|
6398
|
+
const lifecycle = (0, react.useRef)({
|
|
6399
|
+
active: false,
|
|
6400
|
+
generation: 0,
|
|
6401
|
+
busy: false
|
|
6402
|
+
});
|
|
6403
|
+
const load = (0, react.useCallback)(async () => {
|
|
6404
|
+
const owner = lifecycle.current;
|
|
6405
|
+
if (!owner.active || owner.busy) return;
|
|
6406
|
+
const generation = ++owner.generation;
|
|
6407
|
+
const current = () => owner.active && owner.generation === generation;
|
|
6408
|
+
owner.busy = true;
|
|
6409
|
+
setPhase("loading");
|
|
6410
|
+
setMessage(void 0);
|
|
6411
|
+
setNeedsReload(true);
|
|
6412
|
+
const creation = creations.get(props.remote);
|
|
6413
|
+
setPending(creation);
|
|
6414
|
+
if (creation) setWorkspace(creation.input.workspaceId);
|
|
6415
|
+
try {
|
|
6416
|
+
const result = await props.remote.view();
|
|
6417
|
+
if (!current()) return;
|
|
6418
|
+
if (!result.ok || !validView(result.value)) {
|
|
6419
|
+
setView(void 0);
|
|
6420
|
+
setMessage(!result.ok ? diagnostic(result.error) ?? "loadError" : "loadError");
|
|
6421
|
+
return;
|
|
6422
|
+
}
|
|
6423
|
+
setView(result.value);
|
|
6424
|
+
setDraft({ ...result.value.configuration });
|
|
6425
|
+
setNeedsReload(false);
|
|
6426
|
+
if (creation) setMessage(creation.sessionId ? "created" : "pending");
|
|
6427
|
+
} catch {
|
|
6428
|
+
if (current()) {
|
|
6429
|
+
setView(void 0);
|
|
6430
|
+
setMessage("loadError");
|
|
6431
|
+
}
|
|
6432
|
+
} finally {
|
|
6433
|
+
if (current()) {
|
|
6434
|
+
owner.busy = false;
|
|
6435
|
+
setPhase("idle");
|
|
6436
|
+
}
|
|
6437
|
+
}
|
|
6438
|
+
}, [props.remote]);
|
|
6439
|
+
(0, react.useEffect)(() => {
|
|
6440
|
+
const owner = lifecycle.current;
|
|
6441
|
+
owner.active = true;
|
|
6442
|
+
setView(void 0);
|
|
6443
|
+
setDraft(off);
|
|
6444
|
+
setWorkspace("");
|
|
6445
|
+
load();
|
|
6446
|
+
return () => {
|
|
6447
|
+
owner.active = false;
|
|
6448
|
+
owner.generation++;
|
|
6449
|
+
owner.busy = false;
|
|
6450
|
+
};
|
|
6451
|
+
}, [load]);
|
|
6452
|
+
const busy = phase !== "idle";
|
|
6453
|
+
const dirty = !!view && !sameConfig(draft, view.configuration);
|
|
6454
|
+
const models = view?.models ?? [];
|
|
6455
|
+
const validModels = models.some((model) => model.id === draft.plannerModel) && models.some((model) => model.id === draft.executorModel);
|
|
6456
|
+
const disabled = busy || !!pending || needsReload || !view?.supported || !view.writable || !validRevision(view.revision);
|
|
6457
|
+
const saveDisabled = disabled || draft.enabled && !validModels;
|
|
6458
|
+
const createDisabled = pending ? busy : disabled || dirty || !draft.enabled || !validModels || !view?.workspaces.some((item) => item.id === workspace);
|
|
6459
|
+
const save = async () => {
|
|
6460
|
+
const owner = lifecycle.current;
|
|
6461
|
+
if (!owner.active || owner.busy || saveDisabled || !view || !validRevision(view.revision)) return;
|
|
6462
|
+
owner.busy = true;
|
|
6463
|
+
const generation = owner.generation;
|
|
6464
|
+
const current = () => owner.active && owner.generation === generation;
|
|
6465
|
+
setPhase("saving");
|
|
6466
|
+
setMessage(void 0);
|
|
6467
|
+
try {
|
|
6468
|
+
const result = await props.remote.save({
|
|
6469
|
+
configuration: { ...draft },
|
|
6470
|
+
expectedRevision: view.revision
|
|
6471
|
+
});
|
|
6472
|
+
if (!current()) return;
|
|
6473
|
+
if (!result.ok || !validView(result.value)) {
|
|
6474
|
+
setNeedsReload(true);
|
|
6475
|
+
setMessage(!result.ok ? diagnostic(result.error) ?? "saveError" : "saveError");
|
|
6476
|
+
return;
|
|
6477
|
+
}
|
|
6478
|
+
setView(result.value);
|
|
6479
|
+
setDraft({ ...result.value.configuration });
|
|
6480
|
+
setMessage("saved");
|
|
6481
|
+
} catch {
|
|
6482
|
+
if (current()) {
|
|
6483
|
+
setNeedsReload(true);
|
|
6484
|
+
setMessage("saveError");
|
|
6485
|
+
}
|
|
6486
|
+
} finally {
|
|
6487
|
+
if (current()) {
|
|
6488
|
+
owner.busy = false;
|
|
6489
|
+
setPhase("idle");
|
|
6490
|
+
}
|
|
6491
|
+
}
|
|
6492
|
+
};
|
|
6493
|
+
const create = async () => {
|
|
6494
|
+
const owner = lifecycle.current;
|
|
6495
|
+
if (!owner.active || owner.busy || createDisabled) return;
|
|
6496
|
+
let creation = creations.get(props.remote);
|
|
6497
|
+
if (!creation) {
|
|
6498
|
+
if (!view || !validRevision(view.revision)) return;
|
|
6499
|
+
try {
|
|
6500
|
+
creation = { input: {
|
|
6501
|
+
requestId: globalThis.crypto.randomUUID(),
|
|
6502
|
+
workspaceId: workspace,
|
|
6503
|
+
expectedRevision: view.revision
|
|
6504
|
+
} };
|
|
6505
|
+
} catch {
|
|
6506
|
+
setMessage("requestUnavailable");
|
|
6507
|
+
return;
|
|
6508
|
+
}
|
|
6509
|
+
creations.set(props.remote, creation);
|
|
6510
|
+
}
|
|
6511
|
+
const request = creation;
|
|
6512
|
+
const generation = owner.generation;
|
|
6513
|
+
const current = () => owner.active && owner.generation === generation;
|
|
6514
|
+
owner.busy = true;
|
|
6515
|
+
setPending(request);
|
|
6516
|
+
setPhase("creating");
|
|
6517
|
+
setMessage(void 0);
|
|
6518
|
+
if (!request.sessionId && !request.flight) request.flight = Promise.resolve().then(() => props.remote.create({ ...request.input })).catch(() => ({
|
|
6519
|
+
ok: false,
|
|
6520
|
+
error: void 0
|
|
6521
|
+
})).then((result) => {
|
|
6522
|
+
request.flight = void 0;
|
|
6523
|
+
if (result?.ok === true && typeof result.value?.sessionId === "string" && result.value.sessionId.length > 0) {
|
|
6524
|
+
request.sessionId = result.value.sessionId;
|
|
6525
|
+
return {
|
|
6526
|
+
ok: true,
|
|
6527
|
+
value: { sessionId: request.sessionId }
|
|
6528
|
+
};
|
|
6529
|
+
}
|
|
6530
|
+
return {
|
|
6531
|
+
ok: false,
|
|
6532
|
+
error: result?.ok === false ? result.error : void 0
|
|
6533
|
+
};
|
|
6534
|
+
});
|
|
6535
|
+
const result = request.sessionId ? {
|
|
6536
|
+
ok: true,
|
|
6537
|
+
value: { sessionId: request.sessionId }
|
|
6538
|
+
} : await request.flight;
|
|
6539
|
+
if (!current()) return;
|
|
6540
|
+
owner.busy = false;
|
|
6541
|
+
setPhase("idle");
|
|
6542
|
+
if (result.ok && typeof result.value?.sessionId === "string" && result.value.sessionId.length > 0) {
|
|
6543
|
+
creations.delete(props.remote);
|
|
6544
|
+
setPending(void 0);
|
|
6545
|
+
setMessage("created");
|
|
6546
|
+
try {
|
|
6547
|
+
props.onOpenSession?.(result.value.sessionId);
|
|
6548
|
+
} catch {
|
|
6549
|
+
setMessage("openError");
|
|
6550
|
+
}
|
|
6551
|
+
} else {
|
|
6552
|
+
const notCreated = !result.ok ? notCreatedDiagnostic(result.error) : void 0;
|
|
6553
|
+
if (notCreated) {
|
|
6554
|
+
creations.delete(props.remote);
|
|
6555
|
+
setPending(void 0);
|
|
6556
|
+
setNeedsReload(true);
|
|
6557
|
+
setMessage(notCreated);
|
|
6558
|
+
} else setMessage("uncertain");
|
|
6559
|
+
}
|
|
6560
|
+
};
|
|
6561
|
+
const field = (role, label, value) => {
|
|
6562
|
+
const missing = value !== "" && !models.some((model) => model.id === value);
|
|
6563
|
+
return (0, react.createElement)("div", { style: fieldStyle }, (0, react.createElement)("label", {
|
|
6564
|
+
htmlFor: `${id}-${role}`,
|
|
6565
|
+
style: labelStyle
|
|
6566
|
+
}, label), (0, react.createElement)("select", {
|
|
6567
|
+
id: `${id}-${role}`,
|
|
6568
|
+
style: controlStyle,
|
|
6569
|
+
value,
|
|
6570
|
+
disabled,
|
|
6571
|
+
[`data-dsh-dual-model-${role}`]: true,
|
|
6572
|
+
"aria-invalid": draft.enabled && !models.some((model) => model.id === value) ? true : void 0,
|
|
6573
|
+
"aria-describedby": `${id}-model-help`,
|
|
6574
|
+
onChange: (event) => {
|
|
6575
|
+
const value = event.currentTarget.value;
|
|
6576
|
+
if (disabled || !models.some((model) => model.id === value)) return;
|
|
6577
|
+
setMessage(void 0);
|
|
6578
|
+
setDraft((current) => ({
|
|
6579
|
+
...current,
|
|
6580
|
+
[role === "planner" ? "plannerModel" : "executorModel"]: value
|
|
6581
|
+
}));
|
|
6582
|
+
}
|
|
6583
|
+
}, (0, react.createElement)("option", {
|
|
6584
|
+
value: "",
|
|
6585
|
+
disabled: true
|
|
6586
|
+
}, t.selectModel), missing ? (0, react.createElement)("option", {
|
|
6587
|
+
value,
|
|
6588
|
+
disabled: true
|
|
6589
|
+
}, `${value} (${t.unavailable})`) : null, ...models.map((model) => (0, react.createElement)("option", {
|
|
6590
|
+
key: model.id,
|
|
6591
|
+
value: model.id
|
|
6592
|
+
}, model.name || model.id))));
|
|
6593
|
+
};
|
|
6594
|
+
const viewNotice = !view ? void 0 : !view.supported ? diagnostic(view.diagnostic) ?? "unsupported" : !view.writable ? "readonly" : !validRevision(view.revision) ? "revision" : void 0;
|
|
6595
|
+
const status = phase === "loading" ? t.loading : message ? t[message] : "";
|
|
6596
|
+
const shownWorkspace = pending?.input.workspaceId ?? workspace;
|
|
6597
|
+
return (0, react.createElement)("section", {
|
|
6598
|
+
style: cardStyle,
|
|
6599
|
+
"data-dsh-dual-model-card": true,
|
|
6600
|
+
"aria-labelledby": `${id}-title`,
|
|
6601
|
+
"aria-busy": busy
|
|
6602
|
+
}, (0, react.createElement)("div", null, (0, react.createElement)("h3", {
|
|
6603
|
+
id: `${id}-title`,
|
|
6604
|
+
style: {
|
|
6605
|
+
margin: 0,
|
|
6606
|
+
fontSize: "16px"
|
|
6607
|
+
}
|
|
6608
|
+
}, t.title), (0, react.createElement)("p", { style: {
|
|
6609
|
+
...textStyle,
|
|
6610
|
+
marginTop: "5px"
|
|
6611
|
+
} }, t.description), (0, react.createElement)("p", { style: {
|
|
6612
|
+
...textStyle,
|
|
6613
|
+
marginTop: "6px"
|
|
6614
|
+
} }, t.scope)), (0, react.createElement)("div", { style: {
|
|
6615
|
+
display: "flex",
|
|
6616
|
+
alignItems: "center",
|
|
6617
|
+
gap: "9px"
|
|
6618
|
+
} }, (0, react.createElement)("input", {
|
|
6619
|
+
type: "checkbox",
|
|
6620
|
+
id: `${id}-enabled`,
|
|
6621
|
+
checked: draft.enabled,
|
|
6622
|
+
disabled,
|
|
6623
|
+
style: {
|
|
6624
|
+
margin: 0,
|
|
6625
|
+
flexShrink: 0
|
|
6626
|
+
},
|
|
6627
|
+
"data-dsh-dual-model-enabled": true,
|
|
6628
|
+
onChange: (event) => {
|
|
6629
|
+
const enabled = event.currentTarget.checked;
|
|
6630
|
+
if (disabled) return;
|
|
6631
|
+
setMessage(void 0);
|
|
6632
|
+
setDraft((current) => ({
|
|
6633
|
+
...current,
|
|
6634
|
+
enabled
|
|
6635
|
+
}));
|
|
6636
|
+
}
|
|
6637
|
+
}), (0, react.createElement)("label", {
|
|
6638
|
+
htmlFor: `${id}-enabled`,
|
|
6639
|
+
style: labelStyle
|
|
6640
|
+
}, t.enabled)), field("planner", t.planner, draft.plannerModel), field("executor", t.executor, draft.executorModel), (0, react.createElement)("p", {
|
|
6641
|
+
id: `${id}-model-help`,
|
|
6642
|
+
style: textStyle
|
|
6643
|
+
}, t.acceptance, view && draft.enabled && !validModels ? ` ${t.modelsMissing}` : ""), (0, react.createElement)("div", { style: fieldStyle }, (0, react.createElement)("label", {
|
|
6644
|
+
htmlFor: `${id}-workspace`,
|
|
6645
|
+
style: labelStyle
|
|
6646
|
+
}, t.workspace), (0, react.createElement)("select", {
|
|
6647
|
+
id: `${id}-workspace`,
|
|
6648
|
+
style: controlStyle,
|
|
6649
|
+
disabled,
|
|
6650
|
+
value: shownWorkspace,
|
|
6651
|
+
"data-dsh-dual-model-workspace": true,
|
|
6652
|
+
onChange: (event) => {
|
|
6653
|
+
const value = event.currentTarget.value;
|
|
6654
|
+
if (!disabled && view?.workspaces.some((item) => item.id === value)) setWorkspace(value);
|
|
6655
|
+
}
|
|
6656
|
+
}, (0, react.createElement)("option", {
|
|
6657
|
+
value: "",
|
|
6658
|
+
disabled: true
|
|
6659
|
+
}, t.selectWorkspace), shownWorkspace && !view?.workspaces.some((item) => item.id === shownWorkspace) ? (0, react.createElement)("option", {
|
|
6660
|
+
value: shownWorkspace,
|
|
6661
|
+
disabled: true
|
|
6662
|
+
}, `${shownWorkspace} (${t.unavailable})`) : null, ...(view?.workspaces ?? []).map((item) => (0, react.createElement)("option", {
|
|
6663
|
+
key: item.id,
|
|
6664
|
+
value: item.id
|
|
6665
|
+
}, item.name || item.id))), view && view.workspaces.length === 0 ? (0, react.createElement)("p", { style: textStyle }, t.noWorkspaces) : null), viewNotice ? (0, react.createElement)("p", { style: textStyle }, t[viewNotice]) : null, !pending && view && !viewNotice ? (0, react.createElement)("p", { style: textStyle }, dirty ? t.dirty : !draft.enabled ? t.disabled : "") : null, (0, react.createElement)("div", { style: {
|
|
6666
|
+
display: "flex",
|
|
6667
|
+
gap: "12px",
|
|
6668
|
+
flexWrap: "wrap",
|
|
6669
|
+
alignItems: "center",
|
|
6670
|
+
minWidth: 0
|
|
6671
|
+
} }, (0, react.createElement)("button", {
|
|
6672
|
+
type: "button",
|
|
6673
|
+
style: styleForButton(saveDisabled),
|
|
6674
|
+
disabled: saveDisabled,
|
|
6675
|
+
"data-dsh-dual-model-save": true,
|
|
6676
|
+
onClick: () => {
|
|
6677
|
+
save();
|
|
6678
|
+
}
|
|
6679
|
+
}, phase === "saving" ? t.saving : t.save), (0, react.createElement)("button", {
|
|
6680
|
+
type: "button",
|
|
6681
|
+
style: styleForButton(createDisabled),
|
|
6682
|
+
disabled: createDisabled,
|
|
6683
|
+
"data-dsh-dual-model-create": true,
|
|
6684
|
+
onClick: () => {
|
|
6685
|
+
create();
|
|
6686
|
+
}
|
|
6687
|
+
}, phase === "creating" ? t.creating : pending?.sessionId ? t.openCreated : pending ? t.retryCreate : t.create)), (0, react.createElement)("div", {
|
|
6688
|
+
role: "status",
|
|
6689
|
+
"aria-live": "polite",
|
|
6690
|
+
"aria-atomic": true,
|
|
6691
|
+
style: textStyle
|
|
6692
|
+
}, status), (0, react.createElement)("button", {
|
|
6693
|
+
type: "button",
|
|
6694
|
+
style: {
|
|
6695
|
+
...styleForButton(busy || !!pending),
|
|
6696
|
+
justifySelf: "start"
|
|
6697
|
+
},
|
|
6698
|
+
disabled: busy || !!pending,
|
|
6699
|
+
title: t.reloadTitle,
|
|
6700
|
+
"data-dsh-dual-model-reload": true,
|
|
6701
|
+
onClick: () => {
|
|
6702
|
+
if (!creations.has(props.remote)) load();
|
|
6703
|
+
}
|
|
6704
|
+
}, t.reload));
|
|
6705
|
+
}
|
|
6706
|
+
//#endregion
|
|
6707
|
+
//#region lib/types/dual-model-ui.js
|
|
6708
|
+
const emptySubscribe = () => () => {};
|
|
6709
|
+
function DualModelSurface({ ctx, close }) {
|
|
6710
|
+
const locale = ctx.get("locale");
|
|
6711
|
+
const navigation = ctx.get("uiWorkspace");
|
|
6712
|
+
const language = (0, react.useSyncExternalStore)(locale === void 0 ? emptySubscribe : (listener) => locale.subscribe(listener), () => locale?.getLocale().active ?? "en", () => "en");
|
|
6713
|
+
return (0, react.createElement)(DualModelCard, {
|
|
6714
|
+
remote: ctx.remote.githubCopilotDualModel,
|
|
6715
|
+
locale: language,
|
|
6716
|
+
onOpenSession: navigation === void 0 ? void 0 : (id) => {
|
|
6717
|
+
navigation.openSession(id);
|
|
6718
|
+
close?.();
|
|
6719
|
+
}
|
|
6720
|
+
});
|
|
6721
|
+
}
|
|
6722
|
+
/** A single visible seat under Models, with a section fallback on older Clients. */
|
|
6723
|
+
function registerDualModelUi(ctx) {
|
|
6724
|
+
if (ctx.remote.githubCopilotDualModel === void 0) return () => {};
|
|
6725
|
+
let active = true, footerActive = false, sectionActive = false;
|
|
6726
|
+
let fallback;
|
|
6727
|
+
const syncFallback = () => {
|
|
6728
|
+
if (active && sectionActive && !footerActive) fallback ??= ctx.slots.register({
|
|
6729
|
+
name: "settings.section",
|
|
6730
|
+
id: "github-copilot-dual-model",
|
|
6731
|
+
order: 13,
|
|
6732
|
+
label: "Copilot · Model roles"
|
|
6733
|
+
}, (props) => (0, react.createElement)(DualModelSurface, {
|
|
6734
|
+
ctx,
|
|
6735
|
+
close: props.close
|
|
6736
|
+
}));
|
|
6737
|
+
else {
|
|
6738
|
+
fallback?.();
|
|
6739
|
+
fallback = void 0;
|
|
6740
|
+
}
|
|
6741
|
+
};
|
|
6742
|
+
let footer = () => {};
|
|
6743
|
+
try {
|
|
6744
|
+
footer = ctx.slots.inject("settings.models.footer", () => {
|
|
6745
|
+
try {
|
|
6746
|
+
const spec = ctx.slots.spec?.("settings.models.footer");
|
|
6747
|
+
if (spec?.kind !== "list" || spec.scope !== "root") return () => {};
|
|
6748
|
+
const dispose = ctx.slots.register({
|
|
6749
|
+
name: "settings.models.footer",
|
|
6750
|
+
id: "github-copilot-dual-model",
|
|
6751
|
+
order: 15
|
|
6752
|
+
}, () => (0, react.createElement)(DualModelSurface, { ctx }));
|
|
6753
|
+
footerActive = true;
|
|
6754
|
+
syncFallback();
|
|
6755
|
+
let removed = false;
|
|
6756
|
+
return () => {
|
|
6757
|
+
if (removed) return;
|
|
6758
|
+
removed = true;
|
|
6759
|
+
dispose();
|
|
6760
|
+
footerActive = false;
|
|
6761
|
+
syncFallback();
|
|
6762
|
+
};
|
|
6763
|
+
} catch {
|
|
6764
|
+
ctx.logger.warn("[github-copilot] DUAL_MODEL_FOOTER_UNAVAILABLE");
|
|
6765
|
+
return () => {};
|
|
6766
|
+
}
|
|
6767
|
+
});
|
|
6768
|
+
} catch {
|
|
6769
|
+
ctx.logger.warn("[github-copilot] DUAL_MODEL_FOOTER_UNAVAILABLE");
|
|
6770
|
+
}
|
|
6771
|
+
const section = ctx.slots.inject("settings.section", () => {
|
|
6772
|
+
sectionActive = true;
|
|
6773
|
+
syncFallback();
|
|
6774
|
+
return () => {
|
|
6775
|
+
sectionActive = false;
|
|
6776
|
+
syncFallback();
|
|
6777
|
+
};
|
|
6778
|
+
});
|
|
6779
|
+
return () => {
|
|
6780
|
+
active = false;
|
|
6781
|
+
footer();
|
|
6782
|
+
section();
|
|
6783
|
+
fallback?.();
|
|
6784
|
+
fallback = void 0;
|
|
6785
|
+
};
|
|
6786
|
+
}
|
|
6787
|
+
//#endregion
|
|
6112
6788
|
//#region lib/types/client.js
|
|
6113
6789
|
/**
|
|
6114
6790
|
* Browser companion for the Models provider-card slot.
|
|
@@ -7112,6 +7788,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7112
7788
|
"remote.settings",
|
|
7113
7789
|
"slots"
|
|
7114
7790
|
], registerSearchUi);
|
|
7791
|
+
const dualModelUi = ctx.inject(["remote.githubCopilotDualModel", "slots"], registerDualModelUi);
|
|
7115
7792
|
const presentation = ctx.inject(["uiConversation", "slots"], (scope) => installReasoningPresentation({
|
|
7116
7793
|
slots: scope.slots,
|
|
7117
7794
|
uiConversation: scope.get("uiConversation"),
|
|
@@ -7119,12 +7796,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
7119
7796
|
}));
|
|
7120
7797
|
return async () => {
|
|
7121
7798
|
await presentation.dispose();
|
|
7799
|
+
await dualModelUi.dispose();
|
|
7122
7800
|
await searchUi.dispose();
|
|
7123
7801
|
await ui.dispose();
|
|
7124
7802
|
await disposeRemote();
|
|
7125
7803
|
};
|
|
7126
7804
|
}
|
|
7127
7805
|
//#endregion
|
|
7806
|
+
exports.DualModelCard = DualModelCard;
|
|
7128
7807
|
exports.GitHubCopilotAccountModelsPanel = GitHubCopilotAccountModelsPanel;
|
|
7129
7808
|
exports.GitHubCopilotAccountModelsSummary = GitHubCopilotAccountModelsSummary;
|
|
7130
7809
|
exports.GitHubCopilotAccountModelsUpdatedAt = GitHubCopilotAccountModelsUpdatedAt;
|