dsh-ptc-plus 0.5.2 → 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +3 -1
- package/README.md +3 -1
- package/client.cjs +165 -29
- package/docs/adr/0017-track-the-latest-dsh-public-surface.md +4 -2
- package/docs/adr/0019-plugin-settings-and-kill-switch.md +2 -2
- package/docs/adr/0023-global-user-bindings.md +12 -0
- package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +1 -1
- package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +2 -2
- package/docs/adr/0044-coexist-with-the-official-persistent-repl.md +4 -4
- package/docs/adr/0046-gate-the-commit-with-the-semantic-evidence-tier.md +1 -1
- package/docs/adr/0048-supersede-a-rewritten-cell.md +48 -0
- package/docs/adr/0049-prove-a-settlement-against-its-published-record.md +53 -0
- package/docs/adr/0050-read-host-surfaces-through-their-published-contract.md +48 -0
- package/docs/adr/README.md +7 -1
- package/docs/architecture.md +1 -1
- package/docs/durability-design.md +9 -2
- package/docs/installation.md +9 -9
- package/docs/releases/v0.5.2.md +26 -14
- package/docs/releases/v0.5.3.md +77 -0
- package/docs/runtime-reference.md +7 -1
- package/docs/user-bindings.en.md +15 -0
- package/docs/user-bindings.md +15 -0
- package/docs/v0.5.3-goals.md +117 -0
- package/docs/verification.md +4 -4
- package/index.js +67 -19
- package/internal/binding-adoption.js +136 -0
- package/internal/capability-command-receipt.js +18 -4
- package/internal/capability-delivery-proof.js +70 -0
- package/internal/capability-environment.js +38 -1
- package/internal/config-spec.js +14 -5
- package/internal/cordis-tools-owner.js +2 -1
- package/internal/direct-surface-owner.js +27 -13
- package/internal/edit-transport-owner.js +6 -5
- package/internal/execution-provider-owner.js +6 -0
- package/internal/execution-seam-compat.js +25 -0
- package/internal/host-tool-sdk.js +308 -0
- package/internal/official-repl-priority.js +31 -10
- package/internal/program-bindings.js +12 -1
- package/internal/repl-memory-projection.js +21 -2
- package/internal/runtime-bridge-owner.js +113 -8
- package/internal/runtime-messages.js +5 -0
- package/internal/session-journal-recovery.js +210 -32
- package/internal/session-journal-schema.js +3 -0
- package/internal/session-journal.js +46 -9
- package/internal/session-log-view.js +22 -2
- package/internal/session-runtime.js +106 -39
- package/internal/user-bindings-owner.js +109 -6
- package/package.json +15 -7
- package/src/client-capabilities-view.js +45 -3
- package/src/client-copy.js +24 -0
- package/src/client-indicator-view.js +2 -1
- package/src/client-repl-view.js +35 -16
- package/src/client.js +3 -1
package/README.en.md
CHANGED
|
@@ -114,6 +114,8 @@ An `accepted: true, scheduled: true` receipt means the edit is scheduled: the en
|
|
|
114
114
|
|
|
115
115
|
When an accepted edit cannot obtain a compute baseline before it runs, the receipt stays a receipt: the revision does not execute, publishes no new binding, and the outer cell keeps its own result, so a restart does not lose what that cell already saved as a durable checkpoint.
|
|
116
116
|
|
|
117
|
+
The `editRewritesHistory` setting (off by default) decides how a rebuilt environment reads that edit. Off keeps append semantics: the edited cell and its revision both stay in the environment, and the revision only overwrites the names it declares again. On leaves the edited cell in the session log but stops it from building the environment, replaced by the revision; names the revision no longer declares are reported as superseded (`PTC-R007`) rather than lost. The names the log can prove are named; where it cannot, only the relation is stated.
|
|
118
|
+
|
|
117
119
|
The first two behaviors are on by default and can be disabled in settings. Syntax suggestions never execute on their own, and they say nothing about whether the code matches the task's intent. A volatile state cannot be saved as a durable checkpoint, but a rejected save leaves the current variables usable; restore does not undo external effects or change global binding configuration.
|
|
118
120
|
|
|
119
121
|
## Project files and tool capabilities
|
|
@@ -170,7 +172,7 @@ Before a new session starts, capability and global binding changes only update i
|
|
|
170
172
|
|
|
171
173
|
The host execution provider must use TypeScript; changing it to another language during a reload withdraws the plugin and reports a diagnostic, and switching back re-enables it.
|
|
172
174
|
|
|
173
|
-
|
|
175
|
+
When the official runtime keeps a program environment per state owner, **Prioritize the official REPL mode** under State and recovery chooses who owns the PTC session: disabled by default, so PTC Plus owns `run_code`; enabled, the official runtime owns execution and PTC Plus leaves execution, REPL state semantics, and observation to it. The decision follows what the runtime declares: a provider that publishes `retainsState` answers directly (an older one expresses the same fact with `repl` source), and the setting has no effect on a runtime that keeps no state. Ownership changes take effect immediately and leaving plugin execution disposes its in-memory environment. Official in-memory state follows DSH's Agent/provider lifecycle; changing priority does not guarantee clearing it. Official-mode calls stay outside the plugin's records, so they never count as recoverable state after switching back to the plugin.
|
|
174
176
|
|
|
175
177
|

|
|
176
178
|
|
package/README.md
CHANGED
|
@@ -114,6 +114,8 @@ return receipt
|
|
|
114
114
|
|
|
115
115
|
被接受的编辑若在真正执行前因为没有取得计算基线而未能运行,收据仍然是收据:修订不执行、不产生新变量,外层 cell 自己的结果照常保存,重启恢复时也不会再因为这次编辑而连带丢掉它已保存为 durable 检查点的状态。
|
|
116
116
|
|
|
117
|
+
设置里的“编辑时替换原单元格”(`editRewritesHistory`,默认关闭)决定日志重建环境时怎么看待这次编辑。关闭时保持追加语义:被编辑的单元格和修订都留在环境里,修订只是覆盖了它重新声明的名字。打开后被编辑的单元格仍然留在会话日志里,但不再参与环境重建,改由修订代替它;修订不再声明的名字按“被取代”报告(`PTC-R007`),而不是按“丢失”报告。日志能证明的具体名字会被点名,证明不了时只陈述取代关系。
|
|
118
|
+
|
|
117
119
|
前两项默认开启,可以在设置里关掉。语法建议不会自动执行,也不代表代码符合任务意图。volatile 状态存不成 durable 检查点,但保存被拒绝后当前变量还能接着用;恢复不撤销外部效果,也不改全局绑定配置。
|
|
118
120
|
|
|
119
121
|
## 项目文件与工具能力
|
|
@@ -170,7 +172,7 @@ return capabilities.search({ query: 'read file content', budgetBytes: 8192 })
|
|
|
170
172
|
|
|
171
173
|
宿主执行 provider 必须使用 TypeScript;热重载换成别的语言时插件会撤出并报出诊断,换回来就重新启用。
|
|
172
174
|
|
|
173
|
-
|
|
175
|
+
当官方运行时按状态所有者保留程序环境时,可以在“状态与恢复”里用**官方 REPL 模式优先**选择谁接管 PTC 会话:默认关闭,`run_code` 由 PTC Plus 接管;开启后由官方运行时接管,PTC Plus 让出执行、REPL 状态语义与观察。判断依据是运行时自己的声明(`retainsState`;更早的运行时通过 `repl` 源码形式表达同一件事),不是某个执行模式名或版本号,无状态运行时上该设置不生效。切换立即生效,离开插件执行时会释放插件的内存环境;官方内存状态由 DSH 的 Agent/provider 生命周期管理,切换优先设置不保证清空它。官方执行期间的调用不进入插件记录,切回插件后不会当作可恢复状态。
|
|
174
176
|
|
|
175
177
|

|
|
176
178
|
|
package/client.cjs
CHANGED
|
@@ -1984,10 +1984,10 @@ var CONFIG_FIELDS = Object.freeze([
|
|
|
1984
1984
|
type: "enum",
|
|
1985
1985
|
options: Object.freeze(["stateful", "protected"]),
|
|
1986
1986
|
default: "stateful",
|
|
1987
|
-
label: "\
|
|
1988
|
-
labelEn: "
|
|
1989
|
-
description: "\u540C\u4E00\u4F5C\u7528\u57DF\u7684\u58F0\u660E\u548C\u8D4B\u503C\u53EF\u66F4\u65B0\u53D8\u91CF\u3001\u51FD\u6570\u3001\u7C7B\u53CA\u5BFC\u5165\u3002\
|
|
1990
|
-
descriptionEn: "Declarations and assignments update variables, functions, classes and imports in the same scope.
|
|
1987
|
+
label: "\u8DE8 cell \u58F0\u660E\u7B56\u7565",
|
|
1988
|
+
labelEn: "Cross-cell declaration policy",
|
|
1989
|
+
description: "\u540C\u4E00\u4F5C\u7528\u57DF\u7684\u58F0\u660E\u548C\u8D4B\u503C\u53EF\u66F4\u65B0\u53D8\u91CF\u3001\u51FD\u6570\u3001\u7C7B\u53CA\u5BFC\u5165\u3002\u9009\u201C\u542F\u7528\u540D\u79F0\u4FDD\u62A4\u201D\u65F6\u6539\u4E3A\u68C0\u6D4B\u8DE8 cell \u91CD\u58F0\u660E\uFF0C\u5E76\u4FDD\u62A4\u65B0\u5EFA\u7684 const \u548C import\uFF1B\u9759\u6001 import/export \u59CB\u7EC8\u53EF\u7528\u3002",
|
|
1990
|
+
descriptionEn: "Declarations and assignments update variables, functions, classes and imports in the same scope. With \u201CProtect names\u201D selected, cross-cell redeclarations are detected instead and newly created const and import bindings are protected; static import/export remains available."
|
|
1991
1991
|
},
|
|
1992
1992
|
{
|
|
1993
1993
|
key: "canonicalizeToolCalls",
|
|
@@ -2141,6 +2141,15 @@ var CONFIG_FIELDS = Object.freeze([
|
|
|
2141
2141
|
description: "\u68C0\u6D4B\u5230\u5B98\u65B9\u6301\u4E45 REPL \u6A21\u5F0F\u65F6\u7531\u5B98\u65B9\u8FD0\u884C\u65F6\u63A5\u7BA1 PTC \u4F1A\u8BDD\u6267\u884C\uFF1BPTC Plus \u8BA9\u51FA run_code \u53CA\u5176\u8FDB\u7A0B\u5185\u4F1A\u8BDD\u72B6\u6001\u8BED\u4E49\uFF0C\u5173\u95ED\u65F6\u59CB\u7EC8\u7531 PTC Plus \u63A5\u7BA1\u3002",
|
|
2142
2142
|
descriptionEn: "Lets the official runtime own PTC session execution when the official persistent REPL mode is active; PTC Plus then leaves run_code and its in-process session-state semantics to DSH. Disabled keeps PTC Plus in charge."
|
|
2143
2143
|
},
|
|
2144
|
+
{
|
|
2145
|
+
key: "editRewritesHistory",
|
|
2146
|
+
type: "boolean",
|
|
2147
|
+
default: false,
|
|
2148
|
+
label: "\u7F16\u8F91\u65F6\u66FF\u6362\u539F\u5355\u5143\u683C",
|
|
2149
|
+
labelEn: "Replace the edited cell in place",
|
|
2150
|
+
description: '\u9ED8\u8BA4\u5173\u95ED\uFF0C\u4E00\u822C\u4E5F\u4E0D\u9700\u8981\u6253\u5F00\uFF1A\u7F16\u8F91\u53EA\u4F1A\u8FFD\u52A0\u4E00\u6B21\u6267\u884C\uFF0C\u539F\u5355\u5143\u683C\u548C\u5B83\u521B\u5EFA\u7684\u7ED1\u5B9A\u90FD\u8FD8\u5728\u3002\u5F00\u542F\u540E\uFF0C\u7F16\u8F91\u4F1A\u66FF\u6362\u539F\u5355\u5143\u683C\uFF0C\u4E4B\u540E\u7684\u91CD\u5EFA\u6309\u65B0\u7248\u672C\u8FDB\u884C\uFF0C\u65B0\u7248\u672C\u91CC\u4E0D\u518D\u58F0\u660E\u7684\u540D\u5B57\u4F1A\u88AB\u70B9\u540D"\u5DF2\u88AB\u66FF\u6362"\uFF0C\u800C\u4E0D\u662F\u6084\u6084\u6D88\u5931\u3002\u53EA\u6709\u5F53\u4F60\u5E0C\u671B\u73AF\u5883\u8868\u73B0\u5F97"\u8FD9\u4E00\u683C\u4E00\u76F4\u5C31\u662F\u65B0\u7248\u672C"\u65F6\u624D\u9700\u8981\u6253\u5F00\u3002',
|
|
2151
|
+
descriptionEn: "Off by default, and usually unnecessary: an edit appends one more execution, leaving the original cell and the bindings it created in place. When on, the edit replaces the original cell, later rebuilds follow the new version, and a name the new version no longer declares is reported as replaced rather than silently disappearing. Turn it on only when the environment should behave as if that cell had always been the new version."
|
|
2152
|
+
},
|
|
2144
2153
|
{
|
|
2145
2154
|
key: "tipsEnabled",
|
|
2146
2155
|
type: "boolean",
|
|
@@ -2335,7 +2344,7 @@ var CONFIG_GROUPS = Object.freeze([
|
|
|
2335
2344
|
key: "recovery",
|
|
2336
2345
|
label: "\u72B6\u6001\u4E0E\u6062\u590D",
|
|
2337
2346
|
labelEn: "State and recovery",
|
|
2338
|
-
fields: Object.freeze(["durableReplay", "unmeasuredCellLimit", "officialReplPriority", "tipsEnabled", "tipCooldownMessages", "tipEscalationFailures"])
|
|
2347
|
+
fields: Object.freeze(["durableReplay", "editRewritesHistory", "unmeasuredCellLimit", "officialReplPriority", "tipsEnabled", "tipCooldownMessages", "tipEscalationFailures"])
|
|
2339
2348
|
},
|
|
2340
2349
|
{
|
|
2341
2350
|
key: "extensions",
|
|
@@ -3604,6 +3613,44 @@ function registerGated(scope, { subscribe, isEnabled, register }) {
|
|
|
3604
3613
|
});
|
|
3605
3614
|
}
|
|
3606
3615
|
|
|
3616
|
+
// internal/capability-delivery-proof.js
|
|
3617
|
+
var CAPABILITY_PROOF_SCHEMA = "ptc-capability-proof/v1";
|
|
3618
|
+
var CAPABILITY_DELIVERY_STATES = /* @__PURE__ */ new Set(["delivered", "pending", "absent"]);
|
|
3619
|
+
var CAPABILITY_USABILITY_STATES = /* @__PURE__ */ new Set(["proven", "unproven"]);
|
|
3620
|
+
var CAPABILITY_ID = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$/;
|
|
3621
|
+
function isRecord4(value) {
|
|
3622
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
3623
|
+
}
|
|
3624
|
+
function normalizeCapabilityProof(value) {
|
|
3625
|
+
if (!isRecord4(value) || Reflect.ownKeys(value).length !== 5 || !Object.hasOwn(value, "schema") || !Object.hasOwn(value, "id") || !Object.hasOwn(value, "saved") || !Object.hasOwn(value, "delivery") || !Object.hasOwn(value, "usability")) {
|
|
3626
|
+
throw new TypeError("invalid capability proof");
|
|
3627
|
+
}
|
|
3628
|
+
if (value.schema !== CAPABILITY_PROOF_SCHEMA) throw new TypeError("invalid capability proof schema");
|
|
3629
|
+
if (typeof value.id !== "string" || !CAPABILITY_ID.test(value.id)) throw new TypeError("invalid capability proof id");
|
|
3630
|
+
if (typeof value.saved !== "boolean") throw new TypeError("invalid capability proof saved fact");
|
|
3631
|
+
if (!CAPABILITY_DELIVERY_STATES.has(value.delivery)) throw new TypeError("invalid capability proof delivery state");
|
|
3632
|
+
if (!CAPABILITY_USABILITY_STATES.has(value.usability)) throw new TypeError("invalid capability proof usability state");
|
|
3633
|
+
return Object.freeze({
|
|
3634
|
+
schema: CAPABILITY_PROOF_SCHEMA,
|
|
3635
|
+
id: value.id,
|
|
3636
|
+
saved: value.saved,
|
|
3637
|
+
delivery: value.delivery,
|
|
3638
|
+
usability: value.usability
|
|
3639
|
+
});
|
|
3640
|
+
}
|
|
3641
|
+
function capabilityProofText(proof) {
|
|
3642
|
+
const normalized = normalizeCapabilityProof(proof);
|
|
3643
|
+
const id2 = normalized.id;
|
|
3644
|
+
const saved = normalized.saved ? `Saved: yes. The global configuration records a choice for ${id2}.` : `Saved: no. The global configuration records no choice for ${id2}, so this save did not happen; the session choice below is the only change.`;
|
|
3645
|
+
const delivery = {
|
|
3646
|
+
delivered: `Delivered: yes. The model-visible capability catalog published ${id2} at an accepted step.`,
|
|
3647
|
+
pending: `Delivered: not yet. The saved configuration reaches the model-visible catalog at the next accepted step, so ${id2} is not in it now.`,
|
|
3648
|
+
absent: `Delivered: no. The published capability catalog does not list ${id2}, so the model never received it.`
|
|
3649
|
+
}[normalized.delivery];
|
|
3650
|
+
const usability = normalized.usability === "proven" ? `Usable: proven. A completed execution in this session reached ${id2}.` : `Usable: unproven. No completed execution in this session reached ${id2}; only such a result would prove it, and a saved or published entry does not.`;
|
|
3651
|
+
return `${saved} ${delivery} ${usability}`;
|
|
3652
|
+
}
|
|
3653
|
+
|
|
3607
3654
|
// internal/capability-command-receipt.js
|
|
3608
3655
|
var PREFIX = "\n\nPTC Plus capability refresh receipt:\n";
|
|
3609
3656
|
var FALLBACKS = Object.freeze({
|
|
@@ -3616,17 +3663,25 @@ var FALLBACKS = Object.freeze({
|
|
|
3616
3663
|
off: "Capability management is off; the session stays with the Host capabilities for session"
|
|
3617
3664
|
});
|
|
3618
3665
|
var STATES = /* @__PURE__ */ new Set(["recorded", "pending", "unavailable", "usage", "saved-only", "paused", "off"]);
|
|
3619
|
-
function capabilityCommandReceipt(state, sessionId, error, proposal) {
|
|
3666
|
+
function capabilityCommandReceipt(state, sessionId, error, proposal, proof) {
|
|
3620
3667
|
if (!STATES.has(state) || typeof sessionId !== "string" || !sessionId) throw new TypeError("invalid capability command receipt");
|
|
3621
3668
|
if (error !== void 0 && (state !== "saved-only" || typeof error !== "string" || !error)) throw new TypeError("invalid capability command error");
|
|
3622
3669
|
if (proposal !== void 0 && (state !== "pending" || !proposal || typeof proposal.commandId !== "string" || typeof proposal.rawInput !== "string" || !proposal.message)) throw new TypeError("invalid capability proposal receipt");
|
|
3623
|
-
|
|
3670
|
+
const layers = proof === void 0 ? void 0 : normalizeCapabilityProof(proof);
|
|
3671
|
+
return `${FALLBACKS[state]} ${sessionId}.${error ? ` ${error}` : ""}` + (layers === void 0 ? "" : ` ${capabilityProofText(layers)}`) + PREFIX + JSON.stringify({
|
|
3672
|
+
schema: "ptc-capability-command/v1",
|
|
3673
|
+
state,
|
|
3674
|
+
sessionId,
|
|
3675
|
+
...error === void 0 ? {} : { error },
|
|
3676
|
+
...proposal === void 0 ? {} : { proposal },
|
|
3677
|
+
...layers === void 0 ? {} : { proof: layers }
|
|
3678
|
+
});
|
|
3624
3679
|
}
|
|
3625
3680
|
function readCapabilityCommandReceipt(text) {
|
|
3626
3681
|
if (typeof text !== "string" || !text.includes(PREFIX)) return void 0;
|
|
3627
3682
|
try {
|
|
3628
3683
|
const receipt = JSON.parse(text.slice(text.indexOf(PREFIX) + PREFIX.length));
|
|
3629
|
-
return receipt?.schema === "ptc-capability-command/v1" && STATES.has(receipt.state) && typeof receipt.sessionId === "string" && receipt.sessionId && capabilityCommandReceipt(receipt.state, receipt.sessionId, receipt.error, receipt.proposal) === text ? receipt : void 0;
|
|
3684
|
+
return receipt?.schema === "ptc-capability-command/v1" && STATES.has(receipt.state) && typeof receipt.sessionId === "string" && receipt.sessionId && capabilityCommandReceipt(receipt.state, receipt.sessionId, receipt.error, receipt.proposal, receipt.proof) === text ? receipt : void 0;
|
|
3630
3685
|
} catch {
|
|
3631
3686
|
return void 0;
|
|
3632
3687
|
}
|
|
@@ -9154,10 +9209,22 @@ function sortCapabilityEntries(entries, current, valueFor) {
|
|
|
9154
9209
|
}
|
|
9155
9210
|
|
|
9156
9211
|
// src/client-capabilities-view.js
|
|
9212
|
+
function capabilityProofCopy(t2, proof) {
|
|
9213
|
+
const delivery = ["delivered", "pending", "absent"].includes(proof?.delivery) ? proof.delivery : void 0;
|
|
9214
|
+
const usability = ["proven", "unproven"].includes(proof?.usability) ? proof.usability : void 0;
|
|
9215
|
+
if (delivery === void 0 || usability === void 0) return t2("capabilities.quick.unknown");
|
|
9216
|
+
return t2("capabilities.proof.line", {
|
|
9217
|
+
saved: t2(proof.saved === true ? "capabilities.proof.saved.yes" : "capabilities.proof.saved.no"),
|
|
9218
|
+
delivery: t2(`capabilities.proof.delivery.${delivery}`),
|
|
9219
|
+
usability: t2(`capabilities.proof.usability.${usability}`)
|
|
9220
|
+
});
|
|
9221
|
+
}
|
|
9157
9222
|
function capabilityCommandText(t2, text) {
|
|
9158
9223
|
if (text?.key) return t2(text.key, text.params);
|
|
9159
9224
|
const receipt = readCapabilityCommandReceipt(text);
|
|
9160
|
-
|
|
9225
|
+
if (!receipt) return text;
|
|
9226
|
+
const line = t2(`capabilities.receipt.${receipt.state}`, { session: receipt.sessionId, error: receipt.error ?? "" });
|
|
9227
|
+
return receipt.proof === void 0 ? line : `${line} ${capabilityProofCopy(t2, receipt.proof)}`;
|
|
9161
9228
|
}
|
|
9162
9229
|
var HOST_CONTEXT_SECTIONS = Object.freeze([
|
|
9163
9230
|
Object.freeze({ id: "host:system-prompt", presence: "capabilities.prompt.hostPresenceEvery" }),
|
|
@@ -9210,11 +9277,12 @@ function createCapabilityCommandCard(React32) {
|
|
|
9210
9277
|
const legacyRefresh = text === "Session capability environment refreshed; the model-visible notification is recorded.";
|
|
9211
9278
|
if (receipt || String(node.args ?? "").trim() === "refresh" || legacyRefresh) {
|
|
9212
9279
|
const outcome2 = receipt ? t2(`capabilities.card.${receipt.state}`, { error: receipt.error ?? "" }) : legacyRefresh ? t2("capabilities.card.recorded") : node.outcome ? (typeof text === "string" && !text.trim() ? void 0 : capabilityCommandText(t2, text)) ?? t2(node.outcome.kind === "error" ? "capabilities.commandFailed" : "capabilities.refreshAcknowledged") : t2("capabilities.refreshing");
|
|
9280
|
+
const notice = receipt?.proof === void 0 || outcome2 === void 0 ? outcome2 : `${outcome2} ${capabilityProofCopy(t2, receipt.proof)}`;
|
|
9213
9281
|
return h("p", {
|
|
9214
9282
|
className: "ptcPlusCapabilityCommandNotice",
|
|
9215
9283
|
role: node.outcome?.kind === "error" ? "alert" : "status",
|
|
9216
9284
|
"data-state": node.outcome?.kind ?? "pending"
|
|
9217
|
-
},
|
|
9285
|
+
}, notice);
|
|
9218
9286
|
}
|
|
9219
9287
|
let json;
|
|
9220
9288
|
if (typeof text === "string") {
|
|
@@ -11403,6 +11471,7 @@ function createCapabilityRefreshView(React32, commands) {
|
|
|
11403
11471
|
function createSessionCapabilityControlsView(React32, { commands, Modal, Select: Select2, inspectSessionCatalog }) {
|
|
11404
11472
|
const h = React32.createElement;
|
|
11405
11473
|
const emptyDrafts = () => ({});
|
|
11474
|
+
const emptyProofs = () => ({});
|
|
11406
11475
|
return function SessionCapabilityControls({ sessionId, open, enabled, t: t2, onClose }) {
|
|
11407
11476
|
const source = React32.useMemo(() => commands.source(sessionId), [sessionId]);
|
|
11408
11477
|
const available = React32.useSyncExternalStore(source.subscribe, source.getSnapshot);
|
|
@@ -11424,6 +11493,7 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
|
|
|
11424
11493
|
const [sort2, setSort] = React32.useState(null);
|
|
11425
11494
|
const [focusDimension, setFocusDimension] = React32.useState(null);
|
|
11426
11495
|
const [status, setStatus] = React32.useState(null);
|
|
11496
|
+
const [proofs, setProofs] = React32.useState(emptyProofs);
|
|
11427
11497
|
const [pending, setPending] = React32.useState(false);
|
|
11428
11498
|
const request = React32.useRef(null);
|
|
11429
11499
|
const applying = React32.useRef(false);
|
|
@@ -11458,6 +11528,7 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
|
|
|
11458
11528
|
setPane("list");
|
|
11459
11529
|
setFocusDimension(null);
|
|
11460
11530
|
setStatus(null);
|
|
11531
|
+
setProofs(emptyProofs());
|
|
11461
11532
|
setPending(false);
|
|
11462
11533
|
setError(null);
|
|
11463
11534
|
}, [sessionId]);
|
|
@@ -11588,15 +11659,18 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
|
|
|
11588
11659
|
let pendingCount = 0;
|
|
11589
11660
|
let failure = null;
|
|
11590
11661
|
let savedOnly = null;
|
|
11662
|
+
const observed = {};
|
|
11591
11663
|
for (const [id2, selection, dimension] of staged) {
|
|
11592
11664
|
if (controller.signal.aborted) break;
|
|
11665
|
+
const line = `set ${targetScope} ${encodeURIComponent(id2)} ${dimension ? dimension + " " : ""}${selection}`;
|
|
11593
11666
|
try {
|
|
11594
|
-
const result = await commands.run(sessionId,
|
|
11667
|
+
const result = await commands.run(sessionId, line, controller.signal);
|
|
11595
11668
|
const receipt = readCapabilityCommandReceipt(result.text);
|
|
11596
11669
|
if (!receipt || receipt.sessionId !== sessionId || !["recorded", "pending"].includes(receipt.state)) {
|
|
11597
11670
|
throw new Error(receipt ? capabilityCommandText(t2, result.text) : t2("capabilities.quick.unknownReceipt"));
|
|
11598
11671
|
}
|
|
11599
11672
|
if (receipt?.state === "pending") pendingCount += 1;
|
|
11673
|
+
if (receipt.proof !== void 0) observed[receipt.proof.id] = { proof: receipt.proof, command: `/capabilities ${line}` };
|
|
11600
11674
|
completed += 1;
|
|
11601
11675
|
} catch (cause) {
|
|
11602
11676
|
failure = String(cause?.message ?? cause);
|
|
@@ -11604,6 +11678,7 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
|
|
|
11604
11678
|
break;
|
|
11605
11679
|
}
|
|
11606
11680
|
}
|
|
11681
|
+
if (mounted.current && Object.keys(observed).length) setProofs((current) => ({ ...current, ...observed }));
|
|
11607
11682
|
if (request.current !== controller || controller.signal.aborted || !mounted.current) return;
|
|
11608
11683
|
const refreshed = await load(controller.signal);
|
|
11609
11684
|
if (request.current !== controller || controller.signal.aborted || !mounted.current) return;
|
|
@@ -11997,6 +12072,17 @@ function createSessionCapabilityControlsView(React32, { commands, Modal, Select:
|
|
|
11997
12072
|
selected.sourceDimensions ? h(React32.Fragment, null, h("dt", null, t2("capabilities.policy.frozenSource")), h("dd", null, dimensionFacts(selected.sourceDimensions))) : null,
|
|
11998
12073
|
selected.effectiveDimensions ? h(React32.Fragment, null, h("dt", null, t2("capabilities.policy.effectiveDimensions")), h("dd", null, dimensionFacts(selected.effectiveDimensions))) : null
|
|
11999
12074
|
),
|
|
12075
|
+
h(
|
|
12076
|
+
"div",
|
|
12077
|
+
{ className: "ptcPlusCapabilityProof", "data-capability-proof": selected.id },
|
|
12078
|
+
h("h4", null, t2("capabilities.proof.title")),
|
|
12079
|
+
proofs[selected.id] ? h(
|
|
12080
|
+
React32.Fragment,
|
|
12081
|
+
null,
|
|
12082
|
+
h("p", { className: "ptcPlusDetail", role: "status" }, capabilityProofCopy(t2, proofs[selected.id].proof)),
|
|
12083
|
+
h("small", null, t2("capabilities.proof.observed", { command: proofs[selected.id].command }))
|
|
12084
|
+
) : h("p", { className: "ptcPlusDetail" }, t2("capabilities.proof.unobserved"))
|
|
12085
|
+
),
|
|
12000
12086
|
selected.source?.kind === "mcp" && selected.category !== "server" ? (() => {
|
|
12001
12087
|
const server = catalog.find((entry) => entry.category === "server" && entry.source?.server === selected.source.server);
|
|
12002
12088
|
if (!server) return null;
|
|
@@ -12993,6 +13079,7 @@ function createReplView(React32, deps) {
|
|
|
12993
13079
|
Select: Select2,
|
|
12994
13080
|
featureEnabled: featureEnabled2,
|
|
12995
13081
|
normalizeReplMemorySnapshot: normalizeReplMemorySnapshot2,
|
|
13082
|
+
normalizeReplMemoryView: normalizeReplMemoryView2,
|
|
12996
13083
|
unavailableReplMemorySnapshot: unavailableReplMemorySnapshot2,
|
|
12997
13084
|
useSessionPreset: useSessionPreset2,
|
|
12998
13085
|
sessionUsesPtcPreset: sessionUsesPtcPreset2,
|
|
@@ -13005,23 +13092,29 @@ function createReplView(React32, deps) {
|
|
|
13005
13092
|
return null;
|
|
13006
13093
|
}
|
|
13007
13094
|
function useObservedReplMemory({ sessionId, projected, active, elementRef, observeRepl }) {
|
|
13008
|
-
const
|
|
13095
|
+
const view = React32.useMemo(() => {
|
|
13009
13096
|
try {
|
|
13010
|
-
return
|
|
13097
|
+
return normalizeReplMemoryView2(projected);
|
|
13011
13098
|
} catch {
|
|
13012
|
-
return
|
|
13099
|
+
return void 0;
|
|
13013
13100
|
}
|
|
13014
13101
|
}, [projected]);
|
|
13102
|
+
const memory = view?.memory ?? unavailableReplMemorySnapshot2();
|
|
13015
13103
|
const [observed, setObserved] = React32.useState(null);
|
|
13016
13104
|
React32.useEffect(() => active && typeof observeRepl === "function" ? observeRepl(
|
|
13017
13105
|
sessionId,
|
|
13018
13106
|
elementRef.current,
|
|
13019
13107
|
memory,
|
|
13020
|
-
(value) => setObserved({ sessionId, source: memory, value })
|
|
13021
|
-
) : void 0, [active, observeRepl, sessionId, memory, elementRef]);
|
|
13022
|
-
if (observed?.sessionId !== sessionId) return memory;
|
|
13023
|
-
if (
|
|
13024
|
-
|
|
13108
|
+
(value) => setObserved({ sessionId, runtime: view?.runtime, source: memory, value })
|
|
13109
|
+
) : void 0, [active, observeRepl, sessionId, memory, view, elementRef]);
|
|
13110
|
+
if (observed?.sessionId !== sessionId) return { memory, provenance: "current" };
|
|
13111
|
+
if (view !== void 0 && observed.runtime !== view.runtime && !(observed.runtime === void 0 && view.runtime === void 0)) {
|
|
13112
|
+
return { memory, provenance: "previous-runtime" };
|
|
13113
|
+
}
|
|
13114
|
+
if (observed.runtime === view?.runtime && !memory.available && observed.value?.available === true) {
|
|
13115
|
+
return { memory: observed.value, provenance: "refreshed" };
|
|
13116
|
+
}
|
|
13117
|
+
return { memory: observed.source === memory ? observed.value : memory, provenance: "current" };
|
|
13025
13118
|
}
|
|
13026
13119
|
function ReplBindingInspector({ entry, preview, t: t2 }) {
|
|
13027
13120
|
const readable = preview?.status === "readable";
|
|
@@ -13051,7 +13144,7 @@ function createReplView(React32, deps) {
|
|
|
13051
13144
|
readable ? h("pre", { className: "ptcPlusObservationPreview" }, preview.text) : h("p", { className: "ptcPlusObservationUnavailable" }, t2(preview === void 0 ? "console.unobservedValue" : "console.unreadable"))
|
|
13052
13145
|
);
|
|
13053
13146
|
}
|
|
13054
|
-
function ReplSessionBindings({ memory, t: t2 }) {
|
|
13147
|
+
function ReplSessionBindings({ memory, provenance, t: t2 }) {
|
|
13055
13148
|
const [query, setQuery] = React32.useState("");
|
|
13056
13149
|
const [kind, setKind] = React32.useState("all");
|
|
13057
13150
|
const [selectedName, setSelectedName] = React32.useState(null);
|
|
@@ -13085,7 +13178,7 @@ function createReplView(React32, deps) {
|
|
|
13085
13178
|
memory.entries.length === 0 ? h(
|
|
13086
13179
|
"div",
|
|
13087
13180
|
{ className: "ptcPlusSessionEmpty" },
|
|
13088
|
-
t2(memory.available ? "memory.
|
|
13181
|
+
t2(!memory.available ? provenance === "previous-runtime" ? "memory.previousRuntime" : "memory.unavailable" : "memory.empty")
|
|
13089
13182
|
) : h(
|
|
13090
13183
|
"div",
|
|
13091
13184
|
{ className: "ptcPlusObservationGrid", "data-empty": selected === void 0 },
|
|
@@ -13176,7 +13269,7 @@ function createReplView(React32, deps) {
|
|
|
13176
13269
|
const workbench = useWorkbenchController({ enabled: globalEnabled, active: true, callUserBindings });
|
|
13177
13270
|
const eligible = featureEnabled2(settings, "replView") && sessionUsesPtcPreset2(preset);
|
|
13178
13271
|
const observationRegion = React32.useRef(null);
|
|
13179
|
-
const memory = useObservedReplMemory({
|
|
13272
|
+
const { memory, provenance } = useObservedReplMemory({
|
|
13180
13273
|
sessionId,
|
|
13181
13274
|
projected,
|
|
13182
13275
|
active: eligible,
|
|
@@ -13191,6 +13284,7 @@ function createReplView(React32, deps) {
|
|
|
13191
13284
|
h("div", { className: "ptcPlusConsoleSection", ref: observationRegion }, h(ReplSessionBindings, {
|
|
13192
13285
|
key: sessionId,
|
|
13193
13286
|
memory,
|
|
13287
|
+
provenance,
|
|
13194
13288
|
t: t2
|
|
13195
13289
|
})),
|
|
13196
13290
|
globalEnabled ? h(
|
|
@@ -13231,6 +13325,7 @@ function createReplView(React32, deps) {
|
|
|
13231
13325
|
}
|
|
13232
13326
|
function ReplMemoryCard({
|
|
13233
13327
|
memory,
|
|
13328
|
+
provenance,
|
|
13234
13329
|
globalEnabled,
|
|
13235
13330
|
globalBindings,
|
|
13236
13331
|
loadGlobalBinding,
|
|
@@ -13330,7 +13425,7 @@ function createReplView(React32, deps) {
|
|
|
13330
13425
|
),
|
|
13331
13426
|
globalSource?.id !== entry.id ? null : globalSource.error === true ? h("span", { className: "ptcPlusReplEmpty" }, t2("memory.globalUnavailable")) : h("pre", { className: "ptcPlusGlobalSource" }, globalSource.source)
|
|
13332
13427
|
)))
|
|
13333
|
-
) : !memory.available ? h("span", { className: "ptcPlusReplEmpty" }, t2("memory.unavailable")) : memory.entries.length === 0 ? h("span", { className: "ptcPlusReplEmpty" }, t2("memory.empty")) : h("ul", { className: "ptcPlusReplList" }, memory.entries.map((binding, index2) => {
|
|
13428
|
+
) : !memory.available ? h("span", { className: "ptcPlusReplEmpty" }, t2(provenance === "previous-runtime" ? "memory.previousRuntime" : "memory.unavailable")) : memory.entries.length === 0 ? h("span", { className: "ptcPlusReplEmpty" }, t2("memory.empty")) : h("ul", { className: "ptcPlusReplList" }, memory.entries.map((binding, index2) => {
|
|
13334
13429
|
const expanded = expandedBinding === binding.name;
|
|
13335
13430
|
const preview = binding.definition.source.replace(/\s+/g, " ").trim();
|
|
13336
13431
|
const definitionId = `${id2}-binding-${index2}`;
|
|
@@ -13595,7 +13690,7 @@ var {
|
|
|
13595
13690
|
appendArray: appendArray2,
|
|
13596
13691
|
popArray
|
|
13597
13692
|
} = runtimeIntrinsics;
|
|
13598
|
-
function
|
|
13693
|
+
function isRecord5(value) {
|
|
13599
13694
|
return value !== null && typeof value === "object" && !isArray2(value);
|
|
13600
13695
|
}
|
|
13601
13696
|
function assertOwnFields(value, allowed, label) {
|
|
@@ -13612,7 +13707,7 @@ function assertOwnFields(value, allowed, label) {
|
|
|
13612
13707
|
var FIELDS = /* @__PURE__ */ new Set(["includeDeclaration", "instructions", "enabled", "declaration"]);
|
|
13613
13708
|
function normalizeBindingModelContext(value) {
|
|
13614
13709
|
if (value === void 0) return void 0;
|
|
13615
|
-
if (!
|
|
13710
|
+
if (!isRecord5(value)) throw new TypeError("binding modelContext must be an object");
|
|
13616
13711
|
assertOwnFields(value, FIELDS, "binding modelContext");
|
|
13617
13712
|
const { includeDeclaration = true, instructions = "", enabled = true, declaration = "" } = value;
|
|
13618
13713
|
if (typeof includeDeclaration !== "boolean") throw new TypeError("binding modelContext.includeDeclaration must be a boolean");
|
|
@@ -13645,7 +13740,7 @@ var MAX_COMMAND_ID_LENGTH = 256;
|
|
|
13645
13740
|
var VIEW_FIELDS = /* @__PURE__ */ new Set(["phase", "capability", "commandId"]);
|
|
13646
13741
|
var PHASES2 = /* @__PURE__ */ new Set(["idle", "pending", "ready", "failed"]);
|
|
13647
13742
|
function normalizeCandidate(value) {
|
|
13648
|
-
if (!
|
|
13743
|
+
if (!isRecord5(value) || typeof value.requestId !== "string" || value.requestId.length === 0 || value.requestId.length > 128 || !Number.isSafeInteger(value.version) || value.version < 1 || !["new", "edit"].includes(value.mode) || !isRecord5(value.entry) || !["namespace", "top-level"].includes(value.entry.scope) || value.entry.enabled !== false || !Array.isArray(value.entry.symbols) || value.entry.symbols.some((symbol) => typeof symbol !== "string") || ["id", "name", "purpose", "source"].some((key) => typeof value.entry[key] !== "string") || value.entry.source.length === 0 || value.entry.source.length > 65536) {
|
|
13649
13744
|
throw new Error("invalid dsh-ptc-plus accepted binding candidate");
|
|
13650
13745
|
}
|
|
13651
13746
|
const modelContext = normalizeBindingModelContext(value.entry.modelContext);
|
|
@@ -13694,7 +13789,7 @@ function historyFields(value) {
|
|
|
13694
13789
|
return value.history === void 0 ? {} : { history: normalizeHistory(value.history) };
|
|
13695
13790
|
}
|
|
13696
13791
|
function exactFields(value, fields) {
|
|
13697
|
-
if (!
|
|
13792
|
+
if (!isRecord5(value)) return false;
|
|
13698
13793
|
const keys2 = Reflect.ownKeys(value);
|
|
13699
13794
|
return keys2.length === fields.size && keys2.every((key) => typeof key === "string" && fields.has(key) && Object.prototype.propertyIsEnumerable.call(value, key));
|
|
13700
13795
|
}
|
|
@@ -15183,7 +15278,7 @@ function createIndicatorView(React32, deps) {
|
|
|
15183
15278
|
}
|
|
15184
15279
|
};
|
|
15185
15280
|
}, [cancelClose, cancelOpen, schedulePlacement]);
|
|
15186
|
-
const memory = useObservedReplMemory({
|
|
15281
|
+
const { memory, provenance } = useObservedReplMemory({
|
|
15187
15282
|
sessionId,
|
|
15188
15283
|
projected: projectionMemory,
|
|
15189
15284
|
active: expanded && sessionUsesPtcPreset2(preset) && featureEnabled2(settings, "plugin"),
|
|
@@ -15223,6 +15318,7 @@ function createIndicatorView(React32, deps) {
|
|
|
15223
15318
|
}, h("span", { className: "ptcPlusActiveLabel" }, "PTC Plus")),
|
|
15224
15319
|
h(ReplMemoryCard, {
|
|
15225
15320
|
memory,
|
|
15321
|
+
provenance,
|
|
15226
15322
|
globalEnabled,
|
|
15227
15323
|
globalBindings,
|
|
15228
15324
|
loadGlobalBinding: (id2) => callUserBindings("load", { id: id2 }),
|
|
@@ -41092,6 +41188,7 @@ var MAX_BINDINGS = 128;
|
|
|
41092
41188
|
var MAX_BINDING_NAME_LENGTH = 128;
|
|
41093
41189
|
var MAX_DEFINITION_SOURCE_LENGTH = 1024;
|
|
41094
41190
|
var MAX_DEFINITION_SOURCE_TOTAL_LENGTH = 16 * 1024;
|
|
41191
|
+
var MAX_GENERATION_LENGTH = 128;
|
|
41095
41192
|
var SNAPSHOT_FIELDS = /* @__PURE__ */ new Set(["available", "entries", "total", "omitted"]);
|
|
41096
41193
|
var COUNTED_SNAPSHOT_FIELDS = /* @__PURE__ */ new Set([...SNAPSHOT_FIELDS, "reuseTotal"]);
|
|
41097
41194
|
var OBSERVED_SNAPSHOT_FIELDS = /* @__PURE__ */ new Set([...SNAPSHOT_FIELDS, "observation"]);
|
|
@@ -41101,11 +41198,12 @@ var PREVIEW_FIELDS = /* @__PURE__ */ new Set(["name", "status", "text", "truncat
|
|
|
41101
41198
|
var ENTRY_FIELDS = /* @__PURE__ */ new Set(["name", "kind", "definition"]);
|
|
41102
41199
|
var COUNTED_ENTRY_FIELDS = /* @__PURE__ */ new Set([...ENTRY_FIELDS, "reuseCount"]);
|
|
41103
41200
|
var DEFINITION_FIELDS = /* @__PURE__ */ new Set(["source", "line", "column"]);
|
|
41201
|
+
var VIEW_FIELDS2 = /* @__PURE__ */ new Set(["runtime", "memory"]);
|
|
41104
41202
|
function isReuseCount(value) {
|
|
41105
41203
|
return Number.isSafeInteger(value) && value >= 0;
|
|
41106
41204
|
}
|
|
41107
41205
|
function exactFields2(value, fields) {
|
|
41108
|
-
if (!
|
|
41206
|
+
if (!isRecord5(value)) return false;
|
|
41109
41207
|
const keys2 = Reflect.ownKeys(value);
|
|
41110
41208
|
return keys2.length === fields.size && keys2.every((key) => typeof key === "string" && fields.has(key) && Object.prototype.propertyIsEnumerable.call(value, key));
|
|
41111
41209
|
}
|
|
@@ -41119,6 +41217,12 @@ var EMPTY_REPL_MEMORY = Object.freeze({
|
|
|
41119
41217
|
function unavailableReplMemorySnapshot() {
|
|
41120
41218
|
return EMPTY_REPL_MEMORY;
|
|
41121
41219
|
}
|
|
41220
|
+
function normalizeGeneration(value) {
|
|
41221
|
+
if (typeof value !== "string" || value.length === 0 || value.length > MAX_GENERATION_LENGTH) {
|
|
41222
|
+
throw new Error("invalid dsh-ptc-plus REPL memory generation");
|
|
41223
|
+
}
|
|
41224
|
+
return value;
|
|
41225
|
+
}
|
|
41122
41226
|
function normalizeDefinition(value) {
|
|
41123
41227
|
if (!exactFields2(value, DEFINITION_FIELDS) || typeof value.source !== "string" || value.source.length === 0 || value.source.length > MAX_DEFINITION_SOURCE_LENGTH || !Number.isSafeInteger(value.line) || value.line < 1 || !Number.isSafeInteger(value.column) || value.column < 1) {
|
|
41124
41228
|
throw new Error("invalid dsh-ptc-plus REPL binding definition");
|
|
@@ -41193,6 +41297,13 @@ function normalizeReplMemorySnapshot(value) {
|
|
|
41193
41297
|
...observation === void 0 ? {} : { observation }
|
|
41194
41298
|
});
|
|
41195
41299
|
}
|
|
41300
|
+
function normalizeReplMemoryView(value) {
|
|
41301
|
+
if (!exactFields2(value, VIEW_FIELDS2)) throw new Error("invalid dsh-ptc-plus REPL memory view");
|
|
41302
|
+
return Object.freeze({
|
|
41303
|
+
runtime: normalizeGeneration(value.runtime),
|
|
41304
|
+
memory: normalizeReplMemorySnapshot(value.memory)
|
|
41305
|
+
});
|
|
41306
|
+
}
|
|
41196
41307
|
|
|
41197
41308
|
// src/client-copy.js
|
|
41198
41309
|
var LOCALE_NS = "settings.ptcPlus";
|
|
@@ -41436,6 +41547,17 @@ var CHROME_COPY = Object.freeze({
|
|
|
41436
41547
|
"capabilities.receipt.off": "\u80FD\u529B\u7BA1\u7406\u5DF2\u5173\u95ED\uFF1B\u4F1A\u8BDD {session} \u6CBF\u7528\u5BBF\u4E3B\u80FD\u529B\u3002",
|
|
41437
41548
|
"capabilities.receipt.unavailable": "\u8BF7\u9009\u62E9\u4ECD\u6D3B\u8DC3\u7684 PTC \u4F1A\u8BDD\u3002",
|
|
41438
41549
|
"capabilities.receipt.usage": "\u4F7F\u7528 /capabilities \u67E5\u770B\uFF0C\u6216 /capabilities refresh \u540C\u6B65\u5DF2\u4FDD\u5B58\u8BBE\u7F6E\u3002",
|
|
41550
|
+
"capabilities.proof.title": "\u4E09\u5C42\u4E8B\u5B9E",
|
|
41551
|
+
"capabilities.proof.line": "\u5DF2\u4FDD\u5B58\uFF1A{saved}\uFF1B\u5DF2\u6295\u9012\uFF1A{delivery}\uFF1B\u5DF2\u53EF\u7528\uFF1A{usability}\u3002",
|
|
41552
|
+
"capabilities.proof.saved.yes": "\u662F\uFF0C\u5168\u5C40\u8BBE\u7F6E\u8BB0\u5F55\u4E86\u8FD9\u9879\u9009\u62E9",
|
|
41553
|
+
"capabilities.proof.saved.no": "\u5426\uFF0C\u8FD9\u6761\u547D\u4EE4\u6CA1\u6709\u6539\u52A8\u5168\u5C40\u8BBE\u7F6E",
|
|
41554
|
+
"capabilities.proof.delivery.delivered": "\u662F\uFF0C\u6A21\u578B\u53EF\u89C1\u76EE\u5F55\u5DF2\u5728\u53D7\u7406\u7684\u6B65\u9AA4\u53D1\u5E03\u8BE5\u9879",
|
|
41555
|
+
"capabilities.proof.delivery.pending": "\u5C1A\u672A\uFF0C\u5DF2\u4FDD\u5B58\u7684\u8BBE\u7F6E\u8981\u5230\u4E0B\u4E00\u4E2A\u53D7\u7406\u6B65\u9AA4\u624D\u8FDB\u5165\u76EE\u5F55",
|
|
41556
|
+
"capabilities.proof.delivery.absent": "\u5426\uFF0C\u76EE\u5F55\u6CA1\u6709\u5217\u51FA\u8BE5\u9879\uFF0C\u6A21\u578B\u6CA1\u6709\u6536\u5230\u5B83",
|
|
41557
|
+
"capabilities.proof.usability.proven": "\u5DF2\u8BC1\u660E\uFF0C\u672C\u4F1A\u8BDD\u6709\u5B8C\u6210\u7684\u6267\u884C\u53D6\u5230\u4E86\u5B83",
|
|
41558
|
+
"capabilities.proof.usability.unproven": "\u672A\u8BC1\u660E\uFF0C\u672C\u4F1A\u8BDD\u6CA1\u6709\u5B8C\u6210\u7684\u6267\u884C\u53D6\u5230\u8FC7\u5B83\uFF1B\u4FDD\u5B58\u6216\u53D1\u5E03\u90FD\u4E0D\u6784\u6210\u8BC1\u660E",
|
|
41559
|
+
"capabilities.proof.observed": "\u6765\u81EA {command} \u8FD4\u56DE\u7684\u6536\u636E\u3002",
|
|
41560
|
+
"capabilities.proof.unobserved": "\u672C\u9762\u677F\u8FD8\u6CA1\u6709\u8FD9\u9879\u80FD\u529B\u7684\u6295\u9012\u4E0E\u53EF\u7528\u6027\u8BC1\u636E\uFF1B\u5E94\u7528\u4E00\u6B21\u6539\u52A8\uFF0C\u6216\u56DE\u5230\u4F1A\u8BDD\u67E5\u770B\u547D\u4EE4\u6536\u636E\u3002",
|
|
41439
41561
|
"bindings.toggleEnabled": "\u5DF2\u4FDD\u5B58\u201C{name}\u201D\u7684\u542F\u7528\u9009\u62E9\uFF1B\u6A21\u578B\u76EE\u5F55\u5728\u4E0B\u4E00\u6B21\u83B7\u51C6\u6B65\u9AA4\u66F4\u65B0\uFF0C\u7A0B\u5E8F\u503C\u5C1A\u672A\u8BC1\u660E\u521D\u59CB\u5316\u3002",
|
|
41440
41562
|
"bindings.toggleDisabled": "\u5DF2\u4FDD\u5B58\u201C{name}\u201D\u7684\u505C\u7528\u9009\u62E9\uFF1B\u6A21\u578B\u76EE\u5F55\u5728\u4E0B\u4E00\u6B21\u83B7\u51C6\u6B65\u9AA4\u64A4\u9500\uFF0C\u4E0D\u64A4\u9500\u5DF2\u7ECF\u53D1\u751F\u7684\u6548\u679C\u3002",
|
|
41441
41563
|
"capabilities.observationGroup": "\u53EA\u8BFB\u4F1A\u8BDD\u89C2\u5BDF",
|
|
@@ -41875,6 +41997,7 @@ var CHROME_COPY = Object.freeze({
|
|
|
41875
41997
|
"memory.globalCount": "{count} \u4E2A\u5168\u5C40\u6761\u76EE",
|
|
41876
41998
|
"memory.empty": "\u5F53\u524D\u6CA1\u6709\u53EF\u590D\u7528\u7ED1\u5B9A",
|
|
41877
41999
|
"memory.unavailable": "\u5F53\u524D\u7ED1\u5B9A\u72B6\u6001\u5C1A\u4E0D\u53EF\u786E\u8BA4",
|
|
42000
|
+
"memory.previousRuntime": "\u8FD9\u4EFD\u6E05\u5355\u6765\u81EA\u4E0A\u4E00\u4E2A\u8FD0\u884C\u671F\uFF0C\u4E0D\u518D\u4EE3\u8868\u5F53\u524D\u73AF\u5883\uFF1B\u6267\u884C\u4E00\u683C\u5373\u53EF\u91CD\u65B0\u89C2\u5BDF",
|
|
41878
42001
|
"memory.more": "\u53E6\u6709 {count} \u4E2A\u7ED1\u5B9A\u672A\u663E\u793A",
|
|
41879
42002
|
"memory.reuseCount": "\u590D\u7528 {count} \u6B21",
|
|
41880
42003
|
"memory.reuseTotal": "\u5171\u590D\u7528 {count} \u6B21",
|
|
@@ -42149,6 +42272,17 @@ var CHROME_COPY = Object.freeze({
|
|
|
42149
42272
|
"capabilities.receipt.off": "Capability management is off; session {session} stays with the Host capabilities.",
|
|
42150
42273
|
"capabilities.receipt.unavailable": "Select an active PTC session.",
|
|
42151
42274
|
"capabilities.receipt.usage": "Use /capabilities to inspect or /capabilities refresh to apply saved settings.",
|
|
42275
|
+
"capabilities.proof.title": "Three separate facts",
|
|
42276
|
+
"capabilities.proof.line": "Saved: {saved}; delivered: {delivery}; usable: {usability}.",
|
|
42277
|
+
"capabilities.proof.saved.yes": "yes, the global configuration records this choice",
|
|
42278
|
+
"capabilities.proof.saved.no": "no, this command did not change the global configuration",
|
|
42279
|
+
"capabilities.proof.delivery.delivered": "yes, the model-visible catalog published it at an accepted step",
|
|
42280
|
+
"capabilities.proof.delivery.pending": "not yet, the saved configuration reaches the catalog at the next accepted step",
|
|
42281
|
+
"capabilities.proof.delivery.absent": "no, the catalog does not list it, so the model never received it",
|
|
42282
|
+
"capabilities.proof.usability.proven": "proven, a completed execution in this session reached it",
|
|
42283
|
+
"capabilities.proof.usability.unproven": "unproven, no completed execution in this session reached it; a save or a published entry does not prove it",
|
|
42284
|
+
"capabilities.proof.observed": "From the receipt {command} returned.",
|
|
42285
|
+
"capabilities.proof.unobserved": "This panel holds no delivery or usability evidence for this capability yet; apply a change, or read the command receipt in the conversation.",
|
|
42152
42286
|
"bindings.toggleEnabled": "Enabled \u201C{name}\u201D in saved configuration. The model catalog updates at the next accepted step; worker initialization is not yet established.",
|
|
42153
42287
|
"bindings.toggleDisabled": "Disabled \u201C{name}\u201D in saved configuration. The model catalog withdraws it at the next accepted step; earlier effects are unchanged.",
|
|
42154
42288
|
"capabilities.observationGroup": "Read-only session observation",
|
|
@@ -42585,6 +42719,7 @@ var CHROME_COPY = Object.freeze({
|
|
|
42585
42719
|
"memory.globalCount": "{count} global entries",
|
|
42586
42720
|
"memory.empty": "No reusable bindings",
|
|
42587
42721
|
"memory.unavailable": "Current binding state cannot be confirmed",
|
|
42722
|
+
"memory.previousRuntime": "This inventory came from a previous runtime and no longer describes the current environment; run a cell to observe it again",
|
|
42588
42723
|
"memory.more": "{count} more bindings not shown",
|
|
42589
42724
|
// Number-neutral so a single reuse stays grammatical without a plural rule.
|
|
42590
42725
|
"memory.reuseCount": "reused {count}\xD7",
|
|
@@ -43844,6 +43979,7 @@ function createClientPlugin(require2) {
|
|
|
43844
43979
|
Select: Select2,
|
|
43845
43980
|
featureEnabled,
|
|
43846
43981
|
normalizeReplMemorySnapshot,
|
|
43982
|
+
normalizeReplMemoryView,
|
|
43847
43983
|
unavailableReplMemorySnapshot,
|
|
43848
43984
|
useSessionPreset,
|
|
43849
43985
|
sessionUsesPtcPreset,
|
|
@@ -10,9 +10,11 @@ PTC Plus must remain independently installable on unmodified official DSH distri
|
|
|
10
10
|
|
|
11
11
|
The compatibility target is the latest available DSH release. Production behavior, configuration, tests, installation guidance, and current compatibility claims depend on public extension contracts and observed live schemas, never on a DSH version allowlist or comparison. An upstream default projection is not an extension ceiling: when public scoped registration and presentation support a plugin-owned capability, PTC Plus preserves that capability and its model-visible identity instead of deleting or renaming it to match the default. Deterministic normalization remains valid for a call that is outside the declared direct surface when the live schema proves one native target and the lowering preserves arguments, call identity, authority, and result semantics. Deterministic tests exercise the consumed contracts; model-backed and packaging acceptance runners use the installed DSH and record `dsh --version` in generated reports so failures remain attributable without turning the observed value into policy. Concrete DSH release numbers may appear only in source comments that identify historical integration or evaluation evidence and cannot influence execution or acceptance.
|
|
12
12
|
|
|
13
|
-
Release discovery is separated from candidate verification.
|
|
13
|
+
Release discovery is separated from candidate verification. Support is expressed as channels, not versions. `compat/channels.json` is generated from the official dist-tags and records, per channel, the resolved host release, the tarball integrity of every host package whose published surface the plugin probes, and whether that channel may block a release: `latest` (newest published release) and `next` (in-flight release candidate) block, while `alpha` (a pre-adaptation for a line the host has not released yet) only reports. A probe package the release does not publish is recorded with the version and integrity that release's own dependency range resolves to, so the channel still names the bytes an install receives; a probe package the release neither publishes nor depends on is recorded as absent, and the install proof rejects a graph that contains one. These records are reproducibility evidence selected by the channel declarations; they are not compatibility allowlists or runtime branches. `npm run host:channels:update` is the only way to refresh them and starts from the registry; ordinary `verify` and the full branch of `check` make no registry request and validate the tracked manifest offline. The root manifest declares the official `next` channel for the DSH packages used by development, and `host:channels:graph` moves the lock onto the release that channel resolves to; the scheduled channel workflow runs it in the same commit as a channel change. Ordinary gates read whichever graph the lock froze and never resolve a tag.
|
|
14
14
|
|
|
15
|
-
The scheduled
|
|
15
|
+
The scheduled channel refresh resolves every channel from its dist-tag. When a channel moves it commits the regenerated manifest on an automation-owned branch, opens or updates one pull request, and dispatches the normal CI workflow once for that candidate. GitHub suppresses workflow runs from branch and pull-request events produced by the workflow's `GITHUB_TOKEN`, so the explicit dispatch is the candidate's only CI run. If no channel moved, the refresh writes the identical document and nothing is committed. The Host contract suite installs each channel on demand from the manifest into an ignored cache, proves the installed versions against the manifest, packs the plugin, and runs the execution-seam, RPC-codec, compressed Session persistence, and pathless Cordis companion contracts through a repository-external consumer that exposes the selected Host's public packages. `npm run test:host-contract -- <channel>` selects one channel, and the default selection is the blocking set. CI runs one job per channel and lets the `alpha` job report without failing the workflow. No compatibility run independently selects tags for DSH service packages, because their dist-tags need not move as one cohort.
|
|
16
|
+
|
|
17
|
+
The development-lock move is a mechanical convenience with one known limit. `host:channels:graph` re-pins the DSH declarations in `package.json` and then asks npm to resolve the graph, which works when the cohort already moved together in the lock. A development graph that still carries a large previous-release cohort (the lock holds far more `@deepseek-ai/dsh-*` packages than the manifest declares) makes npm reject the half-moved peer graph with `ERESOLVE`; the command then throws, and both `package.json` and `package-lock.json` are restored to the bytes the command found, so no partly moved graph is left behind. Because that command runs before the refresh workflow commits, a channel move waits for a maintainer to install the whole cohort and re-run the check, and `host:channels:verify` keeps reporting the drift until then. This limit touches release tooling only: the plugin's behaviour, its install proof and the compatibility claim a consumer reads are unaffected, and every gate that ships the package reads the tracked manifest rather than the development lock.
|
|
16
18
|
|
|
17
19
|
Preceding public contracts remain supported where capability detection is
|
|
18
20
|
unambiguous. Tools presentation is selected by the installed public schema;
|
|
@@ -18,7 +18,7 @@ The settings card belongs to plugin configuration. Current DSH renders a bundle'
|
|
|
18
18
|
|
|
19
19
|
The settings form groups controls into core workspace (REPL syntax, state and recovery), extensions and tolerance (tool extensions, tool call tolerance), interface and resources (interface display, resource limits), and experimental (capabilities and context). Page and dialog navigation integrate the single main switch into a borderless PTC Plus title row without a duplicate enabled badge; static module captions differ from section links with icons, arrows and selected markers. The legacy disclosure card retains its first switch section. Experimental controls remain last and carry an explicit marker. The wide settings dialog presents the groups as a two-column workbench with independently scrolling navigation and content; settings wheel scrolling and section selection leave the rail and shared modal frame in place. Narrow viewports use horizontal navigation above independently scrolling content. Recovery tips and their thresholds stay together, and global binding management appears directly below its enable switch. `CONFIG_MODULES` and `CONFIG_GROUPS` own this presentation grouping and order independently of Host schema field order and defaults. The session capability-plan section inside capabilities and context shows effective selections and pending configuration changes only while capability management is enabled; disabling it cancels plan inspection and discards stale replies while manual configuration and catalog reads remain available. Capabilities and context uses four tabs for manual preferences, statistics, budgets and session plans. MCP lists group tools/resources under a server master switch; closing the server preserves child strategies and takes precedence when the frozen plan is derived. Typed catalog rows keep common preferences, manual strategies and selected frozen-session results separate, with source/strategy/common/availability filters and stable within-group sorting. Display names and source metadata belong only to the catalog RPC view: Skill provider/source and public MCP server directory and captured MCP owner sections supply evidence, while ordinary tools are attributed to the Host registry without guessing their package origin. Catalog errors preserve last-observed entries as unconfirmed, and unavailable saved preferences remain editable/removable. The core execution surface is read-only. Capability controls serialize structured selections and retain invalid numeric drafts without committing them; saving capability settings affects new sessions, while existing sessions retain their frozen plan until `/capabilities refresh` as defined by [ADR 0038](0038-freeze-session-capability-plans.md). The sparkle menu refreshes its current session through the authenticated Host command; settings require an explicit target from a read-only active-PTC identity view. This identity view does not prepare or inspect plans and remains available with capability management off so users can synchronize the disabled configuration. Reloading catalog/plans is read-only. Global binding disablement hides binding actions while settings and capability refresh remain accessible; the plugin switch and configured sparkle visibility still gate the menu. Refresh receipts preserve Host outcomes, and cancellation stops waiting without claiming rollback. `autoDescribeRunCode` defaults to true and controls only a request-bound local execution policy. When enabled, a call that omits the outer `description` uses derived arguments for local DSH validation, and the fallback summary enters presentation metadata only; when disabled, DSH validates the original arguments. Both states produce byte-stable model-visible tool schemas, order, and system sections with the required `description` declaration. Original call arguments, explicit summaries, cell source, and nested native-tool arguments remain unchanged.
|
|
20
20
|
|
|
21
|
-
The configurable set is the Host runtime configuration plus `enabled: boolean` (default true). `enabled` is the kill switch: when false the Host keeps the settings namespace, client card, and passive message cleanup defined in [ADR 0010](0010-session-log-derived-recovery-tips.md). The next permitted accepted step may clear earlier PTC declarations. It does not install the runtime bridge, edit transport, direct-surface owner, system prompt section, tool registrations, or execution hooks, and does not read binding storage. When true the same runtime as pre-settings PTC Plus is installed. On the generations that expose a section installer, every field is live when its owner can reconcile it: the Host observes the settings scope and installs, uninstalls, or reconfigures owners without replacing existing session-bound bindings. The volatile-only settings shape exposed by both
|
|
21
|
+
The configurable set is the Host runtime configuration plus `enabled: boolean` (default true). `enabled` is the kill switch: when false the Host keeps the settings namespace, client card, and passive message cleanup defined in [ADR 0010](0010-session-log-derived-recovery-tips.md). The next permitted accepted step may clear earlier PTC declarations. It does not install the runtime bridge, edit transport, direct-surface owner, system prompt section, tool registrations, or execution hooks, and does not read binding storage. When true the same runtime as pre-settings PTC Plus is installed. On the generations that expose a section installer, every field is live when its owner can reconcile it: the Host observes the settings scope and installs, uninstalls, or reconfigures owners without replacing existing session-bound bindings. The volatile-only settings shape exposed by both installed channel graphs has no section installer and serves only fields marked volatile in the plugin's exported `Config`; the Host provides the form and commits volatile-only changes into the live references, notifying the owning fiber through the public `loader/volatile-update` event. The plugin subscribes and reconciles through its existing update path instead of running a per-field settings watch. Node fixes a worker's V8 `maxOldGenerationSizeMb` limit at construction, so changing that field while a session worker is active or a submitted cell is preparing to execute is rejected and the settings provider is restored to the previous value; other reconfiguration failures use the same compensation path. The TypeScript language check occurs at activation, allowing disabled settings to load on a host using another code runtime while rejecting and rolling back an enable attempt. If the settings service is absent, the Host falls back to composition config and enables the runtime.
|
|
22
22
|
|
|
23
23
|
The host-only log-fact projection remains owned by the plugin/controller lifecycle when the runtime is disabled, as specified in [ADR 0032](0032-own-session-log-facts-in-a-host-only-projection.md). It supports passive message cleanup without retaining a worker, tool or default model-visible state projection.
|
|
24
24
|
|
|
@@ -43,7 +43,7 @@ namespace. Enable-failure and live-reconfiguration compensation use that same
|
|
|
43
43
|
bound writer, not a fixed namespace substituted for the owning entry. The
|
|
44
44
|
writer and page policy are released with the settings provider.
|
|
45
45
|
|
|
46
|
-
Compatibility evidence and the consequences of removing historical branches are bounded by [Installation: Compatibility Evidence](../installation.md#compatibility-evidence). The two
|
|
46
|
+
Compatibility evidence and the consequences of removing historical branches are bounded by [Installation: Compatibility Evidence](../installation.md#compatibility-evidence). The two installed channel graphs do not establish full Host coverage of the section-installer or settingsScope shapes.
|
|
47
47
|
|
|
48
48
|
## Alternatives Considered
|
|
49
49
|
|
|
@@ -22,6 +22,18 @@ Journal version 6 introduced the required `userBindingsReusePolicy`: new cells w
|
|
|
22
22
|
|
|
23
23
|
Namespace call names and selected export names must parse as exactly one Identifier whose AST name equals the complete supplied string. Whitespace, comments, binding patterns, extra declarations and escaped spellings cannot change identifier identity between validation, declarations, conflict checks, activation and recovery. Supported Unicode identifiers keep their exact spelling. Top-level entry display names remain separate from callable export names.
|
|
24
24
|
|
|
25
|
+
## Supply, Adoption, Materialization and Proof
|
|
26
|
+
|
|
27
|
+
Global bindings answer four different questions, and each layer may report only its own answer. **Supply** is which entries the global configuration offers; `bindings.json` and each entry's `enabled` switch own it, and an entry disabled there is simply absent from the catalog. **Adoption** is which of those entries one session uses; the session owns it. **Materialization** is which adopted entries the worker actually installed; the activated set and its per-entry failures own it. **Proof** is what the model can check; the tool result, its journal and the diagnostics it names own that.
|
|
28
|
+
|
|
29
|
+
Adoption is a two-state decision per entry plus a default: a session uses an entry unless it declined it. "Adopted explicitly" and "never mentioned" therefore produce the same environment, so they are one state rather than two, and no sentinel value is needed. The capability pane's `automatic` is not borrowed here: that word means "the host derives this value", while a binding has no host-derived value to defer to.
|
|
30
|
+
|
|
31
|
+
Adoption can only withdraw a supplied entry. It cannot add, enable or revive one, because an entry the global configuration disabled does not exist in the catalog for a session to name; `/binding skip <id>` rejects an entry the catalog does not supply instead of recording a decision that would claim authority over supply. No rule forbids "an override revives a deleted entry", because the record has no encoding that could express it.
|
|
32
|
+
|
|
33
|
+
`/binding status|skip <id>|use <id>|reset` states the decision as one `plugin:ptc-plus` `binding-adoption` message, and the session-log projection reads the newest record back. A restart therefore reconstructs the same environment from the log; no second store or process-local map exists to migrate. A session that never states a decision receives exactly the supplied catalog, so the previous release's environment is unchanged.
|
|
34
|
+
|
|
35
|
+
Materialization remains a separate report. A declined entry is never offered to the worker, while an entry the worker could not install is named by its execution diagnostic (`PTC-R002`, and `PTC-R006` for a name that was live and then disappeared). An adoption receipt claims neither delivery nor initialization.
|
|
36
|
+
|
|
25
37
|
## Storage and Source Ownership
|
|
26
38
|
|
|
27
39
|
The Host owns one document at `$DSH_HOME/ptc-plus/bindings.json`. The store serializes mutations, holds a file lock, compares the last-read disk bytes, requires an expected revision, and atomically replaces the file with owner-only permissions. The complete enabled declaration budget is validated before replacement; an externally written document that exceeds the same budget is treated as damaged storage. A malformed document remains an explicit error, and stale or external changes require reload instead of blind overwrite. A new Agent draft uses create-only persistence so a concurrent entry with the same ID cannot be replaced.
|