dsh-ptc-plus 0.3.1 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +66 -73
- package/README.md +66 -73
- package/assets/ptc-plus-bindings-en.png +0 -0
- package/assets/ptc-plus-bindings-zh.png +0 -0
- package/assets/ptc-plus-repair-en.png +0 -0
- package/assets/ptc-plus-repair-zh.png +0 -0
- package/assets/ptc-plus-repl-workspace-en.png +0 -0
- package/assets/ptc-plus-repl-workspace-zh.png +0 -0
- package/assets/ptc-plus-settings-en.png +0 -0
- package/assets/ptc-plus-settings-zh.png +0 -0
- package/client.js +30610 -722
- package/compiler-amaro.cjs +5 -0
- package/compiler-amaro.cjs.map +6 -0
- package/compiler-asset-124f80c1bba92ff5fe79cfec6e8ad518f476de4a42514cae3919538887f510e8.txt +1 -0
- package/compiler-assets.json +3 -0
- package/compiler-core.cjs +554 -0
- package/compiler-core.cjs.map +6 -0
- package/compiler-platform.cjs +2 -0
- package/compiler-platform.cjs.map +6 -0
- package/compiler-typescript.cjs +388 -0
- package/compiler-typescript.cjs.map +6 -0
- package/docs/README.md +6 -0
- package/docs/adr/0004-declare-program-bindings-at-the-host.md +1 -1
- package/docs/adr/0006-rewrite-module-syntax-with-an-ast.md +6 -4
- package/docs/adr/0007-separate-worker-transport-from-session-semantics.md +15 -3
- package/docs/adr/0009-bound-expensive-acceptance-default.md +2 -0
- package/docs/adr/0010-session-log-derived-recovery-tips.md +59 -5
- package/docs/adr/0011-isolate-the-local-recovery-tip-provider.md +1 -1
- package/docs/adr/0012-preserve-mixed-destructuring-initialization.md +3 -1
- package/docs/adr/0013-isolate-repl-redeclaration-convenience.md +9 -3
- package/docs/adr/0014-persist-cell-rewrite-policy.md +11 -5
- package/docs/adr/0015-preserve-source-positions-through-rewrites.md +1 -1
- package/docs/adr/0016-archive-resolved-review-findings.md +1 -1
- package/docs/adr/0017-track-the-latest-dsh-public-surface.md +49 -0
- package/docs/adr/0018-use-versioned-fixture-for-ab-benchmark.md +3 -3
- package/docs/adr/0019-plugin-settings-and-kill-switch.md +8 -6
- package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -2
- package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +17 -3
- package/docs/adr/0023-global-user-bindings.md +104 -0
- package/docs/adr/0024-repl-console-observation.md +33 -0
- package/docs/adr/0025-use-versioned-logical-binding-identities.md +119 -0
- package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +21 -0
- package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +37 -0
- package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +103 -0
- package/docs/adr/0029-keep-plugin-unavailability-out-of-the-host-agent-lifecycle.md +27 -0
- package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +27 -0
- package/docs/architecture.md +82 -22
- package/docs/binding-review-placement-design.md +200 -0
- package/docs/capability-projection.md +1 -1
- package/docs/client-ui.md +96 -20
- package/docs/durability-design.md +61 -24
- package/docs/evaluation.md +78 -6
- package/docs/installation.md +41 -6
- package/docs/program-data-plane.md +6 -0
- package/docs/publishing.md +5 -3
- package/docs/runtime-reference.md +79 -25
- package/docs/semantic-validation.md +29 -0
- package/docs/stateful-binding-updates-proposal.md +755 -0
- package/docs/user-bindings.en.md +64 -0
- package/docs/user-bindings.md +64 -0
- package/docs/value-wire.md +3 -3
- package/docs/verification.md +57 -0
- package/index.js +374 -92
- package/internal/ast-traversal.js +5 -2
- package/internal/binding-descriptors.js +1 -0
- package/internal/binding-pattern-traversal.js +25 -0
- package/internal/binding-pattern.js +26 -29
- package/internal/binding-source-analysis.js +391 -0
- package/internal/binding-update-policy.js +66 -0
- package/internal/bounded-worker-round.js +56 -0
- package/internal/callable-definition-environment.js +42 -0
- package/internal/callable-source-catalog.js +129 -0
- package/internal/callable-source-encoding.js +47 -0
- package/internal/callable-source-facts.js +459 -0
- package/internal/callable-source-format.js +2 -0
- package/internal/callable-source-lowering.js +123 -0
- package/internal/cell-analysis-contract.js +25 -0
- package/internal/cell-analysis.js +252 -242
- package/internal/cell-completion.js +15 -0
- package/internal/cell-error.js +7 -0
- package/internal/cell-parser.js +66 -0
- package/internal/cell-rewriter.js +3 -553
- package/internal/commonjs-export-evidence.js +63 -0
- package/internal/commonjs-source-evidence.js +72 -0
- package/internal/compiler-amaro.cjs +2 -0
- package/internal/compiler-compression.js +12 -0
- package/internal/compiler-data.js +58 -0
- package/internal/compiler-descriptors.js +54 -0
- package/internal/compiler-dynamic-cache.js +48 -0
- package/internal/compiler-entry.js +35 -0
- package/internal/compiler-generated-names.js +17 -0
- package/internal/compiler-intrinsics.js +84 -0
- package/internal/compiler-module-links.js +34 -0
- package/internal/compiler-operations.js +61 -0
- package/internal/compiler-platform-factory.js +84 -0
- package/internal/compiler-platform.js +136 -0
- package/internal/compiler-record-roles.js +53 -0
- package/internal/compiler-region-output.js +259 -0
- package/internal/compiler-resource-lowering.js +103 -0
- package/internal/compiler-scope-facts.js +115 -0
- package/internal/compiler-service.js +109 -0
- package/internal/compiler-source-cache.js +32 -0
- package/internal/compiler-source-pieces.js +93 -0
- package/internal/compiler-source-regions.js +132 -0
- package/internal/compiler-storage-source.js +54 -0
- package/internal/compiler-text.js +15 -0
- package/internal/compiler-typescript.cjs +2 -0
- package/internal/config-spec.js +91 -25
- package/internal/cordis-tools-owner.js +130 -21
- package/internal/diagnostic.js +27 -1
- package/internal/direct-surface-owner.js +76 -23
- package/internal/dynamic-binding-evidence.js +16 -0
- package/internal/dynamic-environment-compiler.js +779 -0
- package/internal/dynamic-environment-integration.js +87 -0
- package/internal/dynamic-environment-runtime.js +362 -0
- package/internal/dynamic-native-calls.js +150 -0
- package/internal/dynamic-native-runtime.js +248 -0
- package/internal/dynamic-scope-analysis.js +90 -0
- package/internal/edit-transport-owner.js +28 -3
- package/internal/execution-seam-compat.js +193 -0
- package/internal/failure-reporting.js +118 -18
- package/internal/host-rpc.js +66 -0
- package/internal/isolated-worker.js +548 -0
- package/internal/kernel-child.js +139 -0
- package/internal/kernel-worker.js +911 -116
- package/internal/language-semantics.js +14 -0
- package/internal/legacy-binding-catalog.js +48 -0
- package/internal/legacy-cell-analysis.js +600 -0
- package/internal/legacy-cell-parser.js +50 -0
- package/internal/legacy-cell-rewriter.js +631 -0
- package/internal/legacy-repl-convenience.js +291 -0
- package/internal/managed-module-operations.js +170 -0
- package/internal/module-compilation.js +321 -0
- package/internal/module-runtime-platform.js +19 -0
- package/internal/module-transform-contract.js +12 -0
- package/internal/native-await-declarations.js +68 -0
- package/internal/native-root-compilation.js +54 -0
- package/internal/native-root-dynamic.js +67 -0
- package/internal/recovery-tips.js +27 -15
- package/internal/rejected-cell-editor.js +13 -8
- package/internal/repl-convenience.js +2 -201
- package/internal/repl-memory-projection.js +81 -12
- package/internal/repl-observation-interest.js +70 -0
- package/internal/repl-rewrite-contract.js +21 -0
- package/internal/repl-scope-normalizer.js +2091 -0
- package/internal/repl-value-observer.js +114 -0
- package/internal/rpc-contract.js +52 -0
- package/internal/runtime-bridge-owner.js +172 -28
- package/internal/runtime-config.js +48 -51
- package/internal/runtime-contexts.js +82 -10
- package/internal/runtime-messages.js +111 -0
- package/internal/session-cell-executor.js +455 -91
- package/internal/session-journal-recovery.js +684 -0
- package/internal/session-journal-schema.js +106 -0
- package/internal/session-journal.js +237 -440
- package/internal/session-log-view.js +42 -9
- package/internal/session-runtime.js +325 -80
- package/internal/session-state.js +249 -40
- package/internal/source-position-map.js +211 -71
- package/internal/stateful-module-compiler.js +154 -0
- package/internal/stateful-module-runtime.js +303 -0
- package/internal/stateful-root-compiler.js +598 -0
- package/internal/stateful-root-runtime.js +340 -0
- package/internal/typert-codec-compat.js +28 -0
- package/internal/typescript-transform.js +29 -0
- package/internal/user-binding-authoring.js +70 -0
- package/internal/user-binding-console-worker.js +184 -0
- package/internal/user-binding-console.js +148 -0
- package/internal/user-binding-draft-projection.js +335 -0
- package/internal/user-binding-model-context.js +31 -0
- package/internal/user-binding-runner.js +56 -0
- package/internal/user-bindings-owner.js +1065 -0
- package/internal/user-bindings-store.js +293 -0
- package/internal/user-bindings.js +353 -0
- package/internal/value-wire-schema.js +28 -0
- package/internal/value-wire.js +29 -20
- package/internal/worker-client.js +57 -67
- package/internal/worker-environment.js +45 -0
- package/internal/worker-output-relay.js +29 -0
- package/internal/worker-shutdown.js +14 -0
- package/package.json +81 -11
- package/src/client-activity.js +109 -45
- package/src/client-authoring-view.js +580 -0
- package/src/client-binding-review.js +230 -0
- package/src/client-bindings-data.js +29 -0
- package/src/client-catalog.js +127 -0
- package/src/client-code-editor.js +84 -0
- package/src/client-console.js +112 -0
- package/src/client-copy.js +370 -0
- package/src/client-feature-gates.js +62 -0
- package/src/client-host-compat.js +150 -0
- package/src/client-indicator-view.js +267 -0
- package/src/client-repl-view.js +292 -0
- package/src/client-rpc.js +20 -0
- package/src/client-settings-view.js +221 -0
- package/src/client-styles.js +106 -0
- package/src/client-tool-view.js +108 -0
- package/src/client-transport.js +159 -0
- package/src/client-workbench.js +521 -0
- package/src/client.js +233 -615
|
@@ -0,0 +1,370 @@
|
|
|
1
|
+
import { CONFIG_FIELDS, CONFIG_GROUPS } from '../internal/config-spec.js'
|
|
2
|
+
|
|
3
|
+
/** Locale namespace owning every settings-card string (field copy plus chrome). */
|
|
4
|
+
const LOCALE_NS = 'settings.ptcPlus'
|
|
5
|
+
|
|
6
|
+
/** Card chrome copy; field labels and hints ride the shared config spec. */
|
|
7
|
+
const CHROME_COPY = Object.freeze({
|
|
8
|
+
zh: Object.freeze({
|
|
9
|
+
'console.session': '会话绑定',
|
|
10
|
+
'console.global': '全局绑定',
|
|
11
|
+
'console.definition': '定义',
|
|
12
|
+
'console.name': '名称',
|
|
13
|
+
'console.kind': '类型',
|
|
14
|
+
'console.reuse': '复用',
|
|
15
|
+
'console.search': '搜索绑定名称',
|
|
16
|
+
'console.allKinds': '全部类型',
|
|
17
|
+
'console.noMatches': '没有匹配的绑定',
|
|
18
|
+
'bindings.search': '搜索全局条目',
|
|
19
|
+
'console.value': '值预览',
|
|
20
|
+
'console.observed': '结算后观察:{time}',
|
|
21
|
+
'console.unobserved': '尚无值观察记录',
|
|
22
|
+
'console.unobservedValue': '尚未观察',
|
|
23
|
+
'console.unreadable': '不可读取',
|
|
24
|
+
'console.bounded': '已截断',
|
|
25
|
+
'bindings.manage': '管理全局绑定',
|
|
26
|
+
'settings.menuEntry': 'PTC Plus 设置',
|
|
27
|
+
'settings.dialogTitle': 'PTC Plus 设置',
|
|
28
|
+
'settings.close': '关闭 PTC Plus 设置',
|
|
29
|
+
'settings.pathSettings': '设置 → 插件配置 → PTC Plus',
|
|
30
|
+
'settings.pathPlugins': '侧栏 Plugins → dsh-ptc-plus → 行 ptc-plus → Configure',
|
|
31
|
+
'bindings.entry': '条目配置',
|
|
32
|
+
'bindings.close': '关闭全局绑定工作台',
|
|
33
|
+
'card.description': 'PTC 模式的会话级 TypeScript REPL。',
|
|
34
|
+
'status.enabled': '已启用',
|
|
35
|
+
'status.disabled': '已停用',
|
|
36
|
+
'action.expand': '展开 PTC Plus 设置',
|
|
37
|
+
'action.collapse': '收起 PTC Plus 设置',
|
|
38
|
+
'state.syncing': '正在同步设置...',
|
|
39
|
+
'bindingPolicy.legacy': '沿用旧版设置(尚未迁移)',
|
|
40
|
+
'bindingPolicy.stateful': '允许重声明和覆盖',
|
|
41
|
+
'bindingPolicy.protected': '启用名称保护',
|
|
42
|
+
'bindingPolicy.migrationDescription': '当前按下方旧版开关执行。选择统一策略后停用旧版开关,并对后续代码生效。',
|
|
43
|
+
'state.unavailable': '当前 DSH 实例未提供设置服务',
|
|
44
|
+
'footer.live': '设置会在修改后立即生效',
|
|
45
|
+
'footer.readOnly': '当前设置为只读',
|
|
46
|
+
'status.applied': '设置已立即生效',
|
|
47
|
+
'status.conflict': '设置未生效,请检查设置冲突',
|
|
48
|
+
'status.failed': '设置失败:{error}',
|
|
49
|
+
'bindings.title': '全局用户绑定',
|
|
50
|
+
'bindings.reload': '重新加载',
|
|
51
|
+
'bindings.new': '新建条目',
|
|
52
|
+
'bindings.empty': '尚无全局条目',
|
|
53
|
+
'bindings.loading': '正在加载全局用户绑定...',
|
|
54
|
+
'bindings.name': '名称',
|
|
55
|
+
'bindings.id': '稳定 ID',
|
|
56
|
+
'bindings.scope': '作用域',
|
|
57
|
+
'bindings.symbols': '导出符号',
|
|
58
|
+
'bindings.symbolsPlaceholder': '逗号分隔;留空则从源码推导',
|
|
59
|
+
'bindings.purpose': '用途',
|
|
60
|
+
'bindings.source': 'TypeScript 源码',
|
|
61
|
+
'bindings.sourcePreview': '实现源码',
|
|
62
|
+
'bindings.declaration': '接口声明',
|
|
63
|
+
'bindings.modelContext': '模型上下文',
|
|
64
|
+
'bindings.includeDeclaration': '将接口声明提供给模型',
|
|
65
|
+
'bindings.declarationIncluded': '向模型提供',
|
|
66
|
+
'bindings.declarationExcluded': '不向模型提供',
|
|
67
|
+
'bindings.instructions': '给模型的提示词',
|
|
68
|
+
'bindings.noInstructions': '未设置提示词',
|
|
69
|
+
'bindings.debug': '代码控制台',
|
|
70
|
+
'bindings.edit': '编辑',
|
|
71
|
+
'bindings.cancel': '取消',
|
|
72
|
+
'bindings.unvalidated': '尚未验证当前草稿',
|
|
73
|
+
'bindings.working': '正在处理...',
|
|
74
|
+
'bindings.enabled': '启用',
|
|
75
|
+
'bindings.disabledEntry': '停用',
|
|
76
|
+
'bindings.enableAction': '启用',
|
|
77
|
+
'bindings.disableAction': '停用',
|
|
78
|
+
'bindings.validate': '验证',
|
|
79
|
+
'bindings.save': '保存',
|
|
80
|
+
'bindings.remove': '删除',
|
|
81
|
+
'bindings.importPath': '本地 .ts 路径',
|
|
82
|
+
'bindings.import': '导入',
|
|
83
|
+
'bindings.run': '运行',
|
|
84
|
+
'execution.ready': '就绪',
|
|
85
|
+
'execution.running': '运行中',
|
|
86
|
+
'execution.released': '环境已释放',
|
|
87
|
+
'execution.stopped': '已停止,环境已释放',
|
|
88
|
+
'execution.stop': '停止',
|
|
89
|
+
'execution.reset': '重置环境',
|
|
90
|
+
'execution.clear': '清空记录',
|
|
91
|
+
'execution.history': '执行记录',
|
|
92
|
+
'execution.output': '输出',
|
|
93
|
+
'execution.input': 'TypeScript 命令',
|
|
94
|
+
'execution.restarted': '已从当前草稿重新开始',
|
|
95
|
+
'execution.truncated': '记录已截断',
|
|
96
|
+
'bindings.saved': '条目已保存;从下一次 run_code 请求生效。',
|
|
97
|
+
'bindings.valid': '源码与派生声明有效。',
|
|
98
|
+
'bindings.removed': '条目已删除。',
|
|
99
|
+
'bindings.imported': '源码已导入为停用条目。',
|
|
100
|
+
'bindings.reloaded': '已从磁盘重新加载。',
|
|
101
|
+
'bindings.reloadedDraft': '目录已重新加载,未保存的编辑已保留。',
|
|
102
|
+
'bindings.reloadConflict': '读取期间目录再次发生变化,请重新加载。',
|
|
103
|
+
'bindings.failed': '全局用户绑定操作失败:{error}',
|
|
104
|
+
'bindings.authorEdit': '修改绑定',
|
|
105
|
+
'bindings.open': '全局绑定',
|
|
106
|
+
'bindings.openHint': 'PTC Plus 插件 · 打开全局用户绑定菜单,可编写、启停或管理',
|
|
107
|
+
'bindings.draftHint': 'PTC Plus 插件 · 绑定草稿待处理,点击查看',
|
|
108
|
+
'bindings.quickHeading': '全局用户绑定 · 对所有会话生效',
|
|
109
|
+
'bindings.quickDrafts': '待处理草稿',
|
|
110
|
+
'bindings.quickLoading': '正在读取绑定…',
|
|
111
|
+
'bindings.quickSaving': '正在保存…',
|
|
112
|
+
'bindings.authorNewDraft': '编写新绑定',
|
|
113
|
+
'bindings.quickEditHeading': '选择要修改的绑定',
|
|
114
|
+
'bindings.back': '返回',
|
|
115
|
+
'bindings.composerBusy': '输入框已有内容,未覆盖现有草稿。',
|
|
116
|
+
'bindings.reviewTitle': '绑定草稿',
|
|
117
|
+
'bindings.reviewExpand': '展开绑定草稿',
|
|
118
|
+
'bindings.reviewCollapse': '折叠绑定草稿',
|
|
119
|
+
'bindings.reviewClose': '关闭绑定草稿面板',
|
|
120
|
+
'bindings.reviewOpen': '打开草稿',
|
|
121
|
+
'bindings.reviewMenuLabel': '绑定草稿({count})',
|
|
122
|
+
'bindings.reviewLoading': '正在确认草稿操作资格…',
|
|
123
|
+
'bindings.reviewSaving': '正在处理草稿…',
|
|
124
|
+
'bindings.reviewAttention': '有待查看的操作状态',
|
|
125
|
+
'bindings.reviewUnconfirmed': '操作结果尚未确认,请刷新状态后查看。',
|
|
126
|
+
'bindings.reviewReadOnly': '只读草稿,当前没有可确认的操作资格',
|
|
127
|
+
'bindings.reviewUnavailable': '草稿审阅面板暂不可用',
|
|
128
|
+
'bindings.reviewRetry': '刷新操作状态',
|
|
129
|
+
'bindings.commandAccepted': '请求已受理,编写结果未知',
|
|
130
|
+
'bindings.commandAdmitting': '正在处理编写请求…',
|
|
131
|
+
'bindings.commandGenerated': '草稿已生成',
|
|
132
|
+
'bindings.draftSave': '保存为停用',
|
|
133
|
+
'bindings.draftSaveEnable': '保存并启用',
|
|
134
|
+
'bindings.draftDiscard': '丢弃草稿',
|
|
135
|
+
'bindings.commandTitle': '绑定编写',
|
|
136
|
+
'bindings.commandPending': 'Agent 正在编写草稿...',
|
|
137
|
+
'bindings.commandReady': '草稿已生成,可保存或丢弃',
|
|
138
|
+
'bindings.commandFailed': '未生成可保存的草稿',
|
|
139
|
+
'bindings.commandSaved': '草稿已保存为停用条目',
|
|
140
|
+
'bindings.commandSavedEnabled': '草稿已保存并启用',
|
|
141
|
+
'bindings.commandDiscarded': '草稿已丢弃',
|
|
142
|
+
'indicator.title': 'PTC Plus 已启用;查看当前可复用的 REPL 绑定',
|
|
143
|
+
'memory.title': 'REPL 可复用绑定',
|
|
144
|
+
'memory.count': '{count} 个可复用绑定',
|
|
145
|
+
'memory.globalCount': '{count} 个全局条目',
|
|
146
|
+
'memory.empty': '当前没有可复用绑定',
|
|
147
|
+
'memory.unavailable': '当前绑定状态尚不可确认',
|
|
148
|
+
'memory.more': '另有 {count} 个绑定未显示',
|
|
149
|
+
'memory.reuseCount': '复用 {count} 次',
|
|
150
|
+
'memory.reuseTotal': '共复用 {count} 次',
|
|
151
|
+
'memory.reuseHint': '被后续 cell 复用的次数',
|
|
152
|
+
'memory.kind.variable': '变量',
|
|
153
|
+
'memory.kind.function': '函数',
|
|
154
|
+
'memory.kind.class': '类',
|
|
155
|
+
'memory.kind.import': '导入',
|
|
156
|
+
'memory.location': '第 {line} 行,第 {column} 列',
|
|
157
|
+
'memory.sessionTab': '可复用绑定',
|
|
158
|
+
'memory.globalTab': '全局默认绑定',
|
|
159
|
+
'memory.globalEmpty': '没有全局默认绑定',
|
|
160
|
+
'memory.globalUnavailable': '无法读取全局默认绑定',
|
|
161
|
+
'tool.code': '执行',
|
|
162
|
+
'tool.codeEdit': '修正执行',
|
|
163
|
+
'tool.running': '正在运行',
|
|
164
|
+
'tool.completed': '执行完成',
|
|
165
|
+
'tool.failed': '执行失败',
|
|
166
|
+
'tool.stopped': '执行已中断',
|
|
167
|
+
'tool.source': '源码',
|
|
168
|
+
'tool.result': '结果',
|
|
169
|
+
'tool.copy': '复制代码',
|
|
170
|
+
'tool.copied': '已复制',
|
|
171
|
+
'tool.inspect': '检查调用',
|
|
172
|
+
'feature.safeEdit': '安全编辑执行',
|
|
173
|
+
'feature.codeRun': '隔离执行 code.run',
|
|
174
|
+
'feature.stateSaved': '保存 REPL 状态',
|
|
175
|
+
'feature.stateRestored': '恢复 REPL 状态',
|
|
176
|
+
'feature.stateDeleted': '删除 REPL 状态',
|
|
177
|
+
}),
|
|
178
|
+
en: Object.freeze({
|
|
179
|
+
'console.session': 'Session bindings',
|
|
180
|
+
'console.global': 'Global bindings',
|
|
181
|
+
'console.definition': 'Definition',
|
|
182
|
+
'console.name': 'Name',
|
|
183
|
+
'console.kind': 'Kind',
|
|
184
|
+
'console.reuse': 'Reuses',
|
|
185
|
+
'console.search': 'Search binding names',
|
|
186
|
+
'console.allKinds': 'All kinds',
|
|
187
|
+
'console.noMatches': 'No matching bindings',
|
|
188
|
+
'bindings.search': 'Search global entries',
|
|
189
|
+
'console.value': 'Value preview',
|
|
190
|
+
'console.observed': 'Observed after settlement: {time}',
|
|
191
|
+
'console.unobserved': 'No value observation yet',
|
|
192
|
+
'console.unobservedValue': 'Not observed yet',
|
|
193
|
+
'console.unreadable': 'Unreadable',
|
|
194
|
+
'console.bounded': 'Truncated',
|
|
195
|
+
'bindings.manage': 'Manage global bindings',
|
|
196
|
+
'settings.menuEntry': 'PTC Plus settings',
|
|
197
|
+
'settings.dialogTitle': 'PTC Plus settings',
|
|
198
|
+
'settings.close': 'Close PTC Plus settings',
|
|
199
|
+
'settings.pathSettings': 'Settings → Plugin configuration → PTC Plus',
|
|
200
|
+
'settings.pathPlugins': 'Side bar Plugins → dsh-ptc-plus → row ptc-plus → Configure',
|
|
201
|
+
'bindings.entry': 'Entry configuration',
|
|
202
|
+
'bindings.close': 'Close global bindings workbench',
|
|
203
|
+
'card.description': 'The session-bound TypeScript REPL for PTC mode.',
|
|
204
|
+
'status.enabled': 'Enabled',
|
|
205
|
+
'status.disabled': 'Disabled',
|
|
206
|
+
'action.expand': 'Expand PTC Plus settings',
|
|
207
|
+
'action.collapse': 'Collapse PTC Plus settings',
|
|
208
|
+
'state.syncing': 'Syncing settings...',
|
|
209
|
+
'bindingPolicy.legacy': 'Legacy settings (not migrated)',
|
|
210
|
+
'bindingPolicy.stateful': 'Allow redeclarations and overrides',
|
|
211
|
+
'bindingPolicy.protected': 'Protect names',
|
|
212
|
+
'bindingPolicy.migrationDescription': 'The legacy switches below currently apply. Choosing a unified policy replaces those switches for subsequent code.',
|
|
213
|
+
'state.unavailable': 'This DSH instance does not provide a settings service',
|
|
214
|
+
'footer.live': 'Changes take effect immediately.',
|
|
215
|
+
'footer.readOnly': 'These settings are read-only.',
|
|
216
|
+
'status.applied': 'Setting applied immediately.',
|
|
217
|
+
'status.conflict': 'The setting did not take effect; check for conflicting settings.',
|
|
218
|
+
'status.failed': 'Could not save: {error}',
|
|
219
|
+
'bindings.title': 'Global User Bindings',
|
|
220
|
+
'bindings.reload': 'Reload',
|
|
221
|
+
'bindings.new': 'New entry',
|
|
222
|
+
'bindings.empty': 'No global entries yet',
|
|
223
|
+
'bindings.loading': 'Loading Global User Bindings...',
|
|
224
|
+
'bindings.name': 'Name',
|
|
225
|
+
'bindings.id': 'Stable ID',
|
|
226
|
+
'bindings.scope': 'Scope',
|
|
227
|
+
'bindings.symbols': 'Selected exports',
|
|
228
|
+
'bindings.symbolsPlaceholder': 'Comma-separated; blank derives from source',
|
|
229
|
+
'bindings.purpose': 'Purpose',
|
|
230
|
+
'bindings.source': 'TypeScript source',
|
|
231
|
+
'bindings.sourcePreview': 'Implementation source',
|
|
232
|
+
'bindings.declaration': 'Interface declaration',
|
|
233
|
+
'bindings.modelContext': 'Model context',
|
|
234
|
+
'bindings.includeDeclaration': 'Include API declaration in model context',
|
|
235
|
+
'bindings.declarationIncluded': 'Include in model context',
|
|
236
|
+
'bindings.declarationExcluded': 'Exclude from model context',
|
|
237
|
+
'bindings.instructions': 'Prompt for the model',
|
|
238
|
+
'bindings.noInstructions': 'No prompt configured',
|
|
239
|
+
'bindings.debug': 'Code console',
|
|
240
|
+
'bindings.edit': 'Edit',
|
|
241
|
+
'bindings.cancel': 'Cancel',
|
|
242
|
+
'bindings.unvalidated': 'Current draft has not been validated',
|
|
243
|
+
'bindings.working': 'Working...',
|
|
244
|
+
'bindings.enabled': 'Enabled',
|
|
245
|
+
'bindings.disabledEntry': 'Disabled',
|
|
246
|
+
'bindings.enableAction': 'Enable',
|
|
247
|
+
'bindings.disableAction': 'Disable',
|
|
248
|
+
'bindings.validate': 'Validate',
|
|
249
|
+
'bindings.save': 'Save',
|
|
250
|
+
'bindings.remove': 'Remove',
|
|
251
|
+
'bindings.importPath': 'Local .ts path',
|
|
252
|
+
'bindings.import': 'Import',
|
|
253
|
+
'bindings.run': 'Run',
|
|
254
|
+
'execution.ready': 'Ready',
|
|
255
|
+
'execution.running': 'Running',
|
|
256
|
+
'execution.released': 'Environment released',
|
|
257
|
+
'execution.stopped': 'Stopped; environment released',
|
|
258
|
+
'execution.stop': 'Stop',
|
|
259
|
+
'execution.reset': 'Reset environment',
|
|
260
|
+
'execution.clear': 'Clear history',
|
|
261
|
+
'execution.history': 'Execution history',
|
|
262
|
+
'execution.output': 'Output',
|
|
263
|
+
'execution.input': 'TypeScript command',
|
|
264
|
+
'execution.restarted': 'Started again from the current draft',
|
|
265
|
+
'execution.truncated': 'Record truncated',
|
|
266
|
+
'bindings.saved': 'Entry saved; it takes effect from the next run_code request.',
|
|
267
|
+
'bindings.valid': 'Source and derived declaration are valid.',
|
|
268
|
+
'bindings.removed': 'Entry removed.',
|
|
269
|
+
'bindings.imported': 'Source imported as a disabled entry.',
|
|
270
|
+
'bindings.reloaded': 'Reloaded from disk.',
|
|
271
|
+
'bindings.reloadedDraft': 'Catalog reloaded; unsaved edits retained.',
|
|
272
|
+
'bindings.reloadConflict': 'The catalog changed during reload. Reload again.',
|
|
273
|
+
'bindings.failed': 'Global User Binding operation failed: {error}',
|
|
274
|
+
'bindings.authorEdit': 'Revise a binding',
|
|
275
|
+
'bindings.open': 'Global bindings',
|
|
276
|
+
'bindings.openHint': 'PTC Plus plugin · Open the Global User Binding menu to author, toggle, or manage',
|
|
277
|
+
'bindings.draftHint': 'PTC Plus plugin · Binding draft pending; click to review',
|
|
278
|
+
'bindings.quickHeading': 'Global bindings · Applies to all sessions',
|
|
279
|
+
'bindings.quickDrafts': 'Pending drafts',
|
|
280
|
+
'bindings.quickLoading': 'Loading bindings…',
|
|
281
|
+
'bindings.quickSaving': 'Saving…',
|
|
282
|
+
'bindings.authorNewDraft': 'Write a new binding',
|
|
283
|
+
'bindings.quickEditHeading': 'Choose a binding to revise',
|
|
284
|
+
'bindings.back': 'Back',
|
|
285
|
+
'bindings.composerBusy': 'The composer already has text, so its draft was not replaced.',
|
|
286
|
+
'bindings.reviewTitle': 'Binding draft',
|
|
287
|
+
'bindings.reviewExpand': 'Expand binding draft',
|
|
288
|
+
'bindings.reviewCollapse': 'Collapse binding draft',
|
|
289
|
+
'bindings.reviewClose': 'Close binding draft panel',
|
|
290
|
+
'bindings.reviewOpen': 'Open draft',
|
|
291
|
+
'bindings.reviewMenuLabel': 'Binding drafts ({count})',
|
|
292
|
+
'bindings.reviewLoading': 'Confirming draft actions…',
|
|
293
|
+
'bindings.reviewSaving': 'Processing draft…',
|
|
294
|
+
'bindings.reviewAttention': 'Action status needs attention',
|
|
295
|
+
'bindings.reviewUnconfirmed': 'The action result is unconfirmed. Refresh its status to check.',
|
|
296
|
+
'bindings.reviewReadOnly': 'Read-only draft; current action eligibility is unconfirmed',
|
|
297
|
+
'bindings.reviewUnavailable': 'Draft review panel is temporarily unavailable',
|
|
298
|
+
'bindings.reviewRetry': 'Refresh action status',
|
|
299
|
+
'bindings.commandAccepted': 'Request admitted; authoring result unknown',
|
|
300
|
+
'bindings.commandAdmitting': 'Processing authoring request…',
|
|
301
|
+
'bindings.commandGenerated': 'Draft generated',
|
|
302
|
+
'bindings.draftSave': 'Save as disabled',
|
|
303
|
+
'bindings.draftSaveEnable': 'Save and enable',
|
|
304
|
+
'bindings.draftDiscard': 'Discard draft',
|
|
305
|
+
'bindings.commandTitle': 'Binding authoring',
|
|
306
|
+
'bindings.commandPending': 'Agent is writing a draft...',
|
|
307
|
+
'bindings.commandReady': 'Draft ready to save or discard',
|
|
308
|
+
'bindings.commandFailed': 'No saveable draft was produced',
|
|
309
|
+
'bindings.commandSaved': 'Draft saved as a disabled entry',
|
|
310
|
+
'bindings.commandSavedEnabled': 'Draft saved and enabled',
|
|
311
|
+
'bindings.commandDiscarded': 'Draft discarded',
|
|
312
|
+
'indicator.title': 'PTC Plus is active; view reusable REPL bindings',
|
|
313
|
+
'memory.title': 'Reusable REPL bindings',
|
|
314
|
+
'memory.count': '{count} reusable bindings',
|
|
315
|
+
'memory.globalCount': '{count} global entries',
|
|
316
|
+
'memory.empty': 'No reusable bindings',
|
|
317
|
+
'memory.unavailable': 'Current binding state cannot be confirmed',
|
|
318
|
+
'memory.more': '{count} more bindings not shown',
|
|
319
|
+
// Number-neutral so a single reuse stays grammatical without a plural rule.
|
|
320
|
+
'memory.reuseCount': 'reused {count}\u00d7',
|
|
321
|
+
'memory.reuseTotal': 'reused {count}\u00d7 total',
|
|
322
|
+
'memory.reuseHint': 'Times later cells referenced this binding in their source',
|
|
323
|
+
'memory.kind.variable': 'Variable',
|
|
324
|
+
'memory.kind.function': 'Function',
|
|
325
|
+
'memory.kind.class': 'Class',
|
|
326
|
+
'memory.kind.import': 'Import',
|
|
327
|
+
'memory.location': 'Line {line}, column {column}',
|
|
328
|
+
'memory.sessionTab': 'Reusable bindings',
|
|
329
|
+
'memory.globalTab': 'Global defaults',
|
|
330
|
+
'memory.globalEmpty': 'No global default bindings',
|
|
331
|
+
'memory.globalUnavailable': 'Global default bindings are unavailable',
|
|
332
|
+
'tool.code': 'Code',
|
|
333
|
+
'tool.codeEdit': 'Code edit',
|
|
334
|
+
'tool.running': 'Running',
|
|
335
|
+
'tool.completed': 'Completed',
|
|
336
|
+
'tool.failed': 'Failed',
|
|
337
|
+
'tool.stopped': 'Stopped',
|
|
338
|
+
'tool.source': 'Source',
|
|
339
|
+
'tool.result': 'Result',
|
|
340
|
+
'tool.inspect': 'Inspect call',
|
|
341
|
+
'feature.safeEdit': 'Safe edit execution',
|
|
342
|
+
'feature.codeRun': 'Isolated code.run execution',
|
|
343
|
+
'feature.stateSaved': 'Saved REPL state',
|
|
344
|
+
'feature.stateRestored': 'Restored REPL state',
|
|
345
|
+
'feature.stateDeleted': 'Deleted REPL state',
|
|
346
|
+
'tool.copy': 'Copy code',
|
|
347
|
+
'tool.copied': 'Copied',
|
|
348
|
+
}),
|
|
349
|
+
})
|
|
350
|
+
|
|
351
|
+
/** Project one field's copy into locale dictionary keys; an empty hint has no key. */
|
|
352
|
+
function fieldCopy(field, locale) {
|
|
353
|
+
const copy = { [`${field.key}.label`]: locale === 'en' ? field.labelEn : field.label }
|
|
354
|
+
const description = locale === 'en' ? field.descriptionEn : field.description
|
|
355
|
+
if (description !== '') copy[`${field.key}.description`] = description
|
|
356
|
+
return copy
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/** Complete dictionaries for both shipped locales, derived once from the spec. */
|
|
360
|
+
const SETTINGS_COPY = Object.freeze(Object.fromEntries(
|
|
361
|
+
['zh', 'en'].map(locale => [locale, Object.freeze({
|
|
362
|
+
...CHROME_COPY[locale],
|
|
363
|
+
...Object.assign({}, ...CONFIG_GROUPS.map(group => ({
|
|
364
|
+
[`group.${group.key}`]: locale === 'en' ? group.labelEn : group.label,
|
|
365
|
+
}))),
|
|
366
|
+
...Object.assign({}, ...CONFIG_FIELDS.map(field => fieldCopy(field, locale))),
|
|
367
|
+
})]),
|
|
368
|
+
))
|
|
369
|
+
|
|
370
|
+
export { LOCALE_NS, SETTINGS_COPY }
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Settings snapshot to feature eligibility. Each feature names the settings that
|
|
3
|
+
* gate exactly one contribution, so a new gated surface reads one table instead
|
|
4
|
+
* of copying a predicate. Session facts (preset, projections) and public
|
|
5
|
+
* capabilities stay with their own owners and are combined at the call site.
|
|
6
|
+
*/
|
|
7
|
+
const FEATURE_SETTINGS = Object.freeze({
|
|
8
|
+
// The plugin master switch plus every contribution that only needs it.
|
|
9
|
+
plugin: { required: [], defaultOn: [] },
|
|
10
|
+
// Global User Bindings: the workbench, its command renderer and the author menu.
|
|
11
|
+
bindings: { required: ['userBindingsEnabled'], defaultOn: [] },
|
|
12
|
+
// Enhanced run_code tool rows.
|
|
13
|
+
toolView: { required: [], defaultOn: ['enhancedToolView'] },
|
|
14
|
+
// The REPL view tab; the session preset condition is added by its registration.
|
|
15
|
+
replView: { required: [], defaultOn: ['replViewEnabled'] },
|
|
16
|
+
// The composer authoring menu.
|
|
17
|
+
authorButton: { required: ['userBindingsEnabled'], defaultOn: ['bindingAuthorButtonVisible'] },
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Pure settings projection: a feature is eligible only from a ready snapshot
|
|
22
|
+
* with the master switch on and every feature-specific setting met. Required
|
|
23
|
+
* settings must be explicitly true; default-on settings are on unless the user
|
|
24
|
+
* turned them off. Writability gates setting writes, not contribution presence.
|
|
25
|
+
*/
|
|
26
|
+
export function featureEnabled(snapshot, feature) {
|
|
27
|
+
const rule = FEATURE_SETTINGS[feature]
|
|
28
|
+
if (rule === undefined) throw new Error(`Unknown client feature: ${feature}`)
|
|
29
|
+
if (snapshot?.status !== 'ready' || snapshot.value?.enabled !== true) return false
|
|
30
|
+
const value = snapshot.value
|
|
31
|
+
return rule.required.every(key => value[key] === true)
|
|
32
|
+
&& rule.defaultOn.every(key => value[key] !== false)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Keep one slot registration in sync with an eligibility predicate: subscribe
|
|
37
|
+
* once, register on the first eligible evaluation, unregister on the next
|
|
38
|
+
* ineligible one, and dispose the registration when the owning effect is
|
|
39
|
+
* released. `register` returns its own disposer and must roll back internally
|
|
40
|
+
* when it fails part way; a throw leaves nothing registered.
|
|
41
|
+
*/
|
|
42
|
+
export function registerGated(scope, { subscribe, isEnabled, register }) {
|
|
43
|
+
return scope.effect(() => {
|
|
44
|
+
let dispose
|
|
45
|
+
const sync = () => {
|
|
46
|
+
const enabled = isEnabled()
|
|
47
|
+
if (enabled === (dispose !== undefined)) return
|
|
48
|
+
if (!enabled) {
|
|
49
|
+
dispose?.()
|
|
50
|
+
dispose = undefined
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
dispose = register()
|
|
54
|
+
}
|
|
55
|
+
sync()
|
|
56
|
+
const unsubscribe = subscribe(sync)
|
|
57
|
+
return () => {
|
|
58
|
+
unsubscribe?.()
|
|
59
|
+
dispose?.()
|
|
60
|
+
}
|
|
61
|
+
})
|
|
62
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { SETTINGS_NAMESPACE } from '../internal/config-spec.js'
|
|
2
|
+
|
|
3
|
+
/** The preset a session publishes, preferring the projection reader's evidence. */
|
|
4
|
+
function sessionPresetValue(projected, summary) {
|
|
5
|
+
if (projected !== undefined) return projected
|
|
6
|
+
const values = summary?.projectionValues
|
|
7
|
+
// A published key is authoritative even when its value is undefined: it says
|
|
8
|
+
// the projection exists, so the legacy summary field must not stand in.
|
|
9
|
+
return values !== undefined && Object.hasOwn(values, 'agentPreset') ? values.agentPreset : summary?.agentPreset
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The session the main view holds.
|
|
14
|
+
*
|
|
15
|
+
* The preceding DSH projects the current selection on the session list snapshot.
|
|
16
|
+
* The current one keeps view selection outside the controller and retains the
|
|
17
|
+
* session its main view shows instead, so `retainedBy.mainView` is that layer's
|
|
18
|
+
* own selection evidence. A switch retains the new session before releasing the
|
|
19
|
+
* old one, so the remembered selection wins while it is still held: that is the
|
|
20
|
+
* same rule the view layer applies to decide which session it shows.
|
|
21
|
+
*/
|
|
22
|
+
function currentSessionId(snapshot, remembered) {
|
|
23
|
+
if (snapshot?.current !== undefined) return snapshot.current
|
|
24
|
+
const held = id => id !== undefined && (snapshot?.byId?.[id]?.retainedBy?.mainView ?? 0) > 0
|
|
25
|
+
if (held(remembered)) return remembered
|
|
26
|
+
for (const row of Object.values(snapshot?.byId ?? {})) {
|
|
27
|
+
if ((row?.retainedBy?.mainView ?? 0) > 0) return row.id
|
|
28
|
+
}
|
|
29
|
+
return undefined
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function sessionUsesPtcPreset(preset) {
|
|
33
|
+
return preset === 'ptc' || preset === 'code'
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** Consume the renderer's public hooks; only preset selection has a summary fallback. */
|
|
37
|
+
export function useSessionPreset({ sessionId, useProjection, useSessions }) {
|
|
38
|
+
const projected = useProjection('agentPreset')
|
|
39
|
+
return typeof useSessions === 'function'
|
|
40
|
+
? useSessions(state => sessionPresetValue(projected, state.byId?.[sessionId]))
|
|
41
|
+
: projected
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Publish the current preset immediately and follow its public list/projection sources. */
|
|
45
|
+
export function watchCurrentSessionPreset(sessions, listener) {
|
|
46
|
+
let source
|
|
47
|
+
let unsubscribeProjection
|
|
48
|
+
let selected
|
|
49
|
+
const sync = () => {
|
|
50
|
+
const snapshot = sessions.list.getSnapshot()
|
|
51
|
+
const current = currentSessionId(snapshot, selected)
|
|
52
|
+
selected = current
|
|
53
|
+
const summary = current === undefined ? undefined : snapshot.byId?.[current]
|
|
54
|
+
const next = current === undefined
|
|
55
|
+
? undefined : sessions.binding?.(current)?.session?.projections?.faceOf?.('agentPreset')
|
|
56
|
+
if (source !== next) {
|
|
57
|
+
unsubscribeProjection?.()
|
|
58
|
+
source = next
|
|
59
|
+
unsubscribeProjection = source?.subscribe(sync)
|
|
60
|
+
}
|
|
61
|
+
listener(sessionPresetValue(source?.getSnapshot(), summary))
|
|
62
|
+
}
|
|
63
|
+
const unsubscribeList = sessions.list.subscribe(sync)
|
|
64
|
+
const dispose = () => {
|
|
65
|
+
unsubscribeList()
|
|
66
|
+
unsubscribeProjection?.()
|
|
67
|
+
}
|
|
68
|
+
try {
|
|
69
|
+
sync()
|
|
70
|
+
} catch (error) {
|
|
71
|
+
dispose()
|
|
72
|
+
throw error
|
|
73
|
+
}
|
|
74
|
+
return dispose
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Missing legacy interaction evidence never proves that the composer is idle. */
|
|
78
|
+
export function isIdleSessionComposer(owner, sessionId) {
|
|
79
|
+
return Object.hasOwn(owner, 'sessionId')
|
|
80
|
+
? owner.sessionId === sessionId && owner.pendingInteraction === undefined
|
|
81
|
+
: owner.session?.sessionId === sessionId && Array.isArray(owner.interactions) && owner.interactions.length === 0
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* The row this bundle's own patch declares for its Cordis entry in
|
|
86
|
+
* `cordis.patch.yml`; it is the row-id half of the row-configuration key below,
|
|
87
|
+
* so renaming one means renaming the other.
|
|
88
|
+
*/
|
|
89
|
+
const BUNDLE_PATCH_ROW_ID = 'ptc-plus'
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The slot seats one generation of DSH offers for a plugin's own settings card,
|
|
93
|
+
* oldest generation first:
|
|
94
|
+
*
|
|
95
|
+
* - DSH 0.1.5 and earlier: the Settings panel's Plugins section declares
|
|
96
|
+
* `settings.plugin.item` (keyed, root) as the child slot of its configurable
|
|
97
|
+
* tab and renders one card per settings namespace the Host serves, so this
|
|
98
|
+
* plugin's key is its namespace.
|
|
99
|
+
* - DSH 0.1.6-alpha.2 and later: that section is a read-only inventory, and a
|
|
100
|
+
* bundle's own configuration belongs to the side bar Plugins page, which
|
|
101
|
+
* declares `plugins.row.config` (keyed, root) and renders the entry's summary
|
|
102
|
+
* on the row's page with the entry's form below it. The key is
|
|
103
|
+
* `<bundle package name>#<row id>`. The same page's `plugins.item` list is its
|
|
104
|
+
* Official group, occupied by the host-plane configuration pages DSH itself
|
|
105
|
+
* ships, so it is not a seat for a third-party bundle.
|
|
106
|
+
*
|
|
107
|
+
* No generation declares both keys, and `ctx.slots.inject` waits rather than
|
|
108
|
+
* failing while a key is undeclared: the callback runs only after the declaring
|
|
109
|
+
* entry mounts, and nothing is registered until then. One publication therefore
|
|
110
|
+
* serves every generation without probing a version, and no card renders twice
|
|
111
|
+
* on a generation that exists.
|
|
112
|
+
*
|
|
113
|
+
* @param bundleName - this bundle's package name, as the profile installs it.
|
|
114
|
+
* @returns one `{ slot, identity }` per generation.
|
|
115
|
+
*/
|
|
116
|
+
export function settingsCardSeats(bundleName) {
|
|
117
|
+
return [
|
|
118
|
+
{ slot: 'settings.plugin.item', identity: { key: SETTINGS_NAMESPACE } },
|
|
119
|
+
{ slot: 'plugins.row.config', identity: { key: `${bundleName}#${BUNDLE_PATCH_ROW_ID}` } },
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Publish one settings card to every seat above and report which seat the
|
|
125
|
+
* installed generation declared.
|
|
126
|
+
*
|
|
127
|
+
* Only the declaring generation runs a seat's callback, so the card's location
|
|
128
|
+
* is observed rather than inferred: the seat that registered is where a user
|
|
129
|
+
* finds the card now, and that is what any copy pointing at it must say.
|
|
130
|
+
*
|
|
131
|
+
* @param ctx - browser plugin context carrying `slots`.
|
|
132
|
+
* @param options.bundleName - this bundle's package name, as the profile installs it.
|
|
133
|
+
* @param options.locale - locale namespace owning the card's copy.
|
|
134
|
+
* @param options.injectProps - inject face producing the card's props.
|
|
135
|
+
* @param options.component - the card component; it renders the summary view as
|
|
136
|
+
* one line and the card's other views as the full settings form.
|
|
137
|
+
* @returns `seat` reports the live seat's slot name, and `releases` holds one
|
|
138
|
+
* disposer per seat for callers that release them explicitly.
|
|
139
|
+
*/
|
|
140
|
+
export function publishSettingsCard(ctx, { bundleName, locale, injectProps, component }) {
|
|
141
|
+
let live
|
|
142
|
+
const releases = settingsCardSeats(bundleName).map(({ slot, identity }) => ctx.slots.inject(
|
|
143
|
+
slot,
|
|
144
|
+
() => {
|
|
145
|
+
live = slot
|
|
146
|
+
return ctx.slots.register({ name: slot, ...identity, locale, inject: injectProps }, component)
|
|
147
|
+
},
|
|
148
|
+
))
|
|
149
|
+
return { seat: () => live, releases }
|
|
150
|
+
}
|