dsh-ptc-plus 0.2.4 → 0.3.2
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 +177 -0
- package/README.md +85 -69
- 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-settings-en.png +0 -0
- package/assets/ptc-plus-settings-zh.png +0 -0
- package/client.js +1168 -144
- package/docs/adr/0006-rewrite-module-syntax-with-an-ast.md +1 -1
- package/docs/adr/0007-separate-worker-transport-from-session-semantics.md +15 -3
- package/docs/adr/0013-isolate-repl-redeclaration-convenience.md +7 -3
- package/docs/adr/0014-persist-cell-rewrite-policy.md +7 -5
- package/docs/adr/0019-plugin-settings-and-kill-switch.md +19 -4
- package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -2
- package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +5 -3
- package/docs/adr/0022-stage-npm-releases-with-oidc.md +2 -2
- package/docs/architecture.md +23 -14
- package/docs/client-ui.md +29 -11
- package/docs/durability-design.md +42 -20
- package/docs/installation.md +11 -3
- package/docs/program-data-plane.md +6 -0
- package/docs/runtime-reference.md +27 -14
- package/docs/value-wire.md +1 -1
- package/index.js +38 -4
- package/internal/cell-analysis.js +89 -12
- package/internal/cell-rewriter.js +162 -4
- package/internal/config-spec.js +192 -117
- package/internal/direct-surface-owner.js +56 -5
- package/internal/edit-transport-owner.js +11 -2
- package/internal/failure-reporting.js +15 -0
- package/internal/kernel-worker.js +11 -0
- package/internal/rejected-cell-editor.js +21 -12
- package/internal/repl-convenience.js +94 -6
- package/internal/repl-memory-projection.js +277 -0
- package/internal/repl-rewrite-contract.js +15 -0
- package/internal/run-code-description.js +34 -0
- package/internal/runtime-bridge-owner.js +63 -15
- package/internal/runtime-config.js +3 -0
- package/internal/session-cell-executor.js +74 -14
- package/internal/session-events.js +7 -0
- package/internal/session-journal.js +331 -63
- package/internal/session-log-view.js +2 -1
- package/internal/session-runtime.js +110 -9
- package/internal/session-state.js +116 -4
- package/package.json +10 -7
- package/src/client-activity.js +501 -0
- package/src/client.js +456 -20
- package/README.zh.md +0 -161
- /package/assets/{ptc-plus-repair.png → ptc-plus-repair-zh.png} +0 -0
package/internal/config-spec.js
CHANGED
|
@@ -20,14 +20,104 @@ export const CONFIG_FIELDS = Object.freeze([
|
|
|
20
20
|
description: '',
|
|
21
21
|
descriptionEn: '',
|
|
22
22
|
},
|
|
23
|
+
{
|
|
24
|
+
key: 'enhancedToolView',
|
|
25
|
+
type: 'boolean',
|
|
26
|
+
default: true,
|
|
27
|
+
label: '使用 PTC Plus 增强工具卡片',
|
|
28
|
+
labelEn: 'Use enhanced PTC Plus tool cards',
|
|
29
|
+
description: '开启时使用增强工具卡片;关闭后使用 DSH 原生工具卡片。',
|
|
30
|
+
descriptionEn: 'Uses enhanced tool cards when enabled and DSH native tool cards when disabled.',
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
key: 'autoDescribeRunCode',
|
|
34
|
+
type: 'boolean',
|
|
35
|
+
default: true,
|
|
36
|
+
label: '允许执行缺少摘要的 run_code',
|
|
37
|
+
labelEn: 'Allow run_code execution without a summary',
|
|
38
|
+
description: '允许 run_code 缺少外层 description;关闭后恢复 DSH 校验。模型请求和原始调用参数保持不变。',
|
|
39
|
+
descriptionEn: 'Allows run_code to omit its outer description; disabling restores DSH validation. Model requests and original call arguments remain unchanged.',
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
key: 'canonicalizeToolCalls',
|
|
43
|
+
type: 'boolean',
|
|
44
|
+
default: true,
|
|
45
|
+
label: '修复可识别的顶层 native 工具误调用',
|
|
46
|
+
labelEn: 'Repair recognizable top-level native tool mis-calls',
|
|
47
|
+
description: '仅当当前 schema 能唯一确认目标工具且参数有效时,才把顶层 native 工具误调用修复为对应的 run_code 调用。',
|
|
48
|
+
descriptionEn: 'Repairs a top-level native tool mis-call as the corresponding run_code call only when the current schema uniquely identifies the tool and validates its arguments.',
|
|
49
|
+
},
|
|
23
50
|
{
|
|
24
51
|
key: 'cordisToolsEnabled',
|
|
25
52
|
type: 'boolean',
|
|
26
53
|
default: false,
|
|
27
|
-
label: '在 PTC
|
|
28
|
-
labelEn: 'Enable Cordis tools in PTC mode',
|
|
29
|
-
description: '
|
|
30
|
-
descriptionEn: '
|
|
54
|
+
label: '在 PTC 模式中启用官方 Cordis 工具',
|
|
55
|
+
labelEn: 'Enable official Cordis tools in PTC mode',
|
|
56
|
+
description: '开启后,PTC agent 可使用官方 Cordis 工具、配套指引和开发 Skill;关闭后移除这些能力。Cordis 工具以 DSH 进程权限运行。',
|
|
57
|
+
descriptionEn: 'When enabled, PTC agents can use the official Cordis tools, guidance, and development Skill; disabling removes them. Cordis tools run with the DSH process permissions.',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
key: 'looseTopLevelRedeclarations',
|
|
61
|
+
type: 'boolean',
|
|
62
|
+
default: true,
|
|
63
|
+
label: '允许顶层变量重声明',
|
|
64
|
+
labelEn: 'Allow top-level variable redeclarations',
|
|
65
|
+
description: '允许顶层 const 或 let 声明替换已有变量;关闭后,重声明会在执行前被拒绝。',
|
|
66
|
+
descriptionEn: 'Allows top-level const or let declarations to replace existing variables; disabling rejects redeclarations before execution.',
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
key: 'looseTopLevelFunctionClassRedeclarations',
|
|
70
|
+
type: 'boolean',
|
|
71
|
+
default: false,
|
|
72
|
+
label: '允许顶层函数/类重声明',
|
|
73
|
+
labelEn: 'Allow top-level function/class redeclarations',
|
|
74
|
+
description: '允许顶层 function 或 class 声明替换已有的可写 binding;不可写或保留 binding 仍会在执行前被拒绝。',
|
|
75
|
+
descriptionEn: 'Allows top-level function or class declarations to replace existing writable bindings; immutable and reserved bindings are still rejected before execution.',
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
key: 'autoRewriteImports',
|
|
79
|
+
type: 'boolean',
|
|
80
|
+
default: true,
|
|
81
|
+
label: '支持静态 import 声明',
|
|
82
|
+
labelEn: 'Support static import declarations',
|
|
83
|
+
description: '允许在 run_code 中使用静态 import,并保留模块解析和只读 binding 语义。',
|
|
84
|
+
descriptionEn: 'Allows static import declarations in run_code while preserving module resolution and read-only binding semantics.',
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
key: 'autoStripExports',
|
|
88
|
+
type: 'boolean',
|
|
89
|
+
default: true,
|
|
90
|
+
label: '支持顶层 export 修饰符',
|
|
91
|
+
labelEn: 'Support top-level export modifiers',
|
|
92
|
+
description: '允许在 run_code 中使用顶层 export,并保留对应的本地声明或模块副作用。',
|
|
93
|
+
descriptionEn: 'Allows top-level export syntax in run_code while preserving the corresponding local declaration or module side effect.',
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
key: 'autoSplitRedeclarations',
|
|
97
|
+
type: 'boolean',
|
|
98
|
+
default: true,
|
|
99
|
+
label: '支持混合解构重声明',
|
|
100
|
+
labelEn: 'Support mixed destructuring redeclarations',
|
|
101
|
+
description: '允许顶层解构声明同时包含新变量和已有变量。',
|
|
102
|
+
descriptionEn: 'Allows top-level destructuring declarations to contain both new and existing variables.',
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
key: 'durableReplay',
|
|
106
|
+
type: 'boolean',
|
|
107
|
+
default: true,
|
|
108
|
+
label: '启用持久 REPL 恢复',
|
|
109
|
+
labelEn: 'Enable durable REPL recovery',
|
|
110
|
+
description: 'worker 重启后从 session journal 重建可恢复的 REPL 状态。',
|
|
111
|
+
descriptionEn: 'Rebuilds recoverable REPL state from the session journal after a worker restart.',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
key: 'tipsEnabled',
|
|
115
|
+
type: 'boolean',
|
|
116
|
+
default: true,
|
|
117
|
+
label: '启用失败恢复提示',
|
|
118
|
+
labelEn: 'Enable failure recovery tips',
|
|
119
|
+
description: '在符合条件的失败后显示有冷却间隔的恢复提示。',
|
|
120
|
+
descriptionEn: 'Shows recovery tips with a cooldown after qualifying failures.',
|
|
31
121
|
},
|
|
32
122
|
{
|
|
33
123
|
key: 'computeMs',
|
|
@@ -35,10 +125,10 @@ export const CONFIG_FIELDS = Object.freeze([
|
|
|
35
125
|
default: 60_000,
|
|
36
126
|
min: 1,
|
|
37
127
|
max: Number.MAX_SAFE_INTEGER,
|
|
38
|
-
label: '单 cell
|
|
39
|
-
labelEn: '
|
|
40
|
-
description: '
|
|
41
|
-
descriptionEn: '
|
|
128
|
+
label: '单 cell CPU 时间上限 (ms)',
|
|
129
|
+
labelEn: 'CPU time limit per cell (ms)',
|
|
130
|
+
description: '同步计算超过该上限时中断当前 cell。',
|
|
131
|
+
descriptionEn: 'Interrupts the current cell when synchronous computation exceeds this limit.',
|
|
42
132
|
},
|
|
43
133
|
{
|
|
44
134
|
key: 'maxWallMs',
|
|
@@ -46,32 +136,43 @@ export const CONFIG_FIELDS = Object.freeze([
|
|
|
46
136
|
default: 600_000,
|
|
47
137
|
min: 1,
|
|
48
138
|
max: MAX_TIMER_DELAY_MS,
|
|
49
|
-
label: '单 cell
|
|
50
|
-
labelEn: '
|
|
51
|
-
description: '
|
|
52
|
-
descriptionEn: '
|
|
139
|
+
label: '单 cell 总耗时上限 (ms)',
|
|
140
|
+
labelEn: 'Elapsed time limit per cell (ms)',
|
|
141
|
+
description: '限制完整 cell 执行的耗时,包括异步等待。',
|
|
142
|
+
descriptionEn: 'Limits the complete cell execution time, including asynchronous waits.',
|
|
53
143
|
},
|
|
54
144
|
{
|
|
55
|
-
key: '
|
|
145
|
+
key: 'maxOldGenerationSizeMb',
|
|
56
146
|
type: 'integer',
|
|
57
|
-
default:
|
|
147
|
+
default: 512,
|
|
58
148
|
min: 1,
|
|
59
149
|
max: Number.MAX_SAFE_INTEGER,
|
|
60
|
-
label: '
|
|
61
|
-
labelEn: '
|
|
62
|
-
description: '
|
|
63
|
-
descriptionEn: '
|
|
150
|
+
label: '每个 worker 旧生代内存上限 (MiB)',
|
|
151
|
+
labelEn: 'Old-generation memory limit per worker (MiB)',
|
|
152
|
+
description: '限制每个 worker 的 V8 旧生代;活动 worker 存在时不能修改。',
|
|
153
|
+
descriptionEn: 'Limits the V8 old generation for each worker; this setting cannot change while a worker is active.',
|
|
64
154
|
},
|
|
65
155
|
{
|
|
66
|
-
key: '
|
|
156
|
+
key: 'maxNestedRunCodeDepth',
|
|
67
157
|
type: 'integer',
|
|
68
|
-
default:
|
|
158
|
+
default: 8,
|
|
159
|
+
min: 1,
|
|
160
|
+
max: Number.MAX_SAFE_INTEGER,
|
|
161
|
+
label: 'code.run 嵌套层数上限',
|
|
162
|
+
labelEn: 'code.run nesting depth limit',
|
|
163
|
+
description: '限制单个顶层 cell 中 code.run 的最大嵌套层数。',
|
|
164
|
+
descriptionEn: 'Limits the maximum code.run nesting depth within one top-level cell.',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
key: 'maxOutputBytes',
|
|
168
|
+
type: 'integer',
|
|
169
|
+
default: 64 * 1024 * 1024,
|
|
69
170
|
min: 1,
|
|
70
171
|
max: Number.MAX_SAFE_INTEGER,
|
|
71
|
-
label: '
|
|
72
|
-
labelEn: '
|
|
73
|
-
description: '
|
|
74
|
-
descriptionEn: '
|
|
172
|
+
label: '单 cell 输出上限 (bytes)',
|
|
173
|
+
labelEn: 'Output limit per cell (bytes)',
|
|
174
|
+
description: '限制单个 cell 的日志和返回结果的合计大小。',
|
|
175
|
+
descriptionEn: 'Limits the combined size of one cell\'s logs and returned result.',
|
|
75
176
|
},
|
|
76
177
|
{
|
|
77
178
|
key: 'maxValueNodes',
|
|
@@ -79,10 +180,10 @@ export const CONFIG_FIELDS = Object.freeze([
|
|
|
79
180
|
default: 100_000,
|
|
80
181
|
min: 1,
|
|
81
182
|
max: Number.MAX_SAFE_INTEGER,
|
|
82
|
-
label: '
|
|
83
|
-
labelEn: '
|
|
84
|
-
description: '
|
|
85
|
-
descriptionEn: '
|
|
183
|
+
label: '返回值节点数上限',
|
|
184
|
+
labelEn: 'Returned-value node limit',
|
|
185
|
+
description: '限制单次返回值的 Value Graph 节点数。',
|
|
186
|
+
descriptionEn: 'Limits the Value Graph node count for one returned value.',
|
|
86
187
|
},
|
|
87
188
|
{
|
|
88
189
|
key: 'maxValueEdges',
|
|
@@ -90,10 +191,10 @@ export const CONFIG_FIELDS = Object.freeze([
|
|
|
90
191
|
default: 1_000_000,
|
|
91
192
|
min: 1,
|
|
92
193
|
max: Number.MAX_SAFE_INTEGER,
|
|
93
|
-
label: '
|
|
94
|
-
labelEn: '
|
|
95
|
-
description: '
|
|
96
|
-
descriptionEn: '
|
|
194
|
+
label: '返回值引用边数上限',
|
|
195
|
+
labelEn: 'Returned-value reference-edge limit',
|
|
196
|
+
description: '限制单次返回值的 Value Graph 引用边数。',
|
|
197
|
+
descriptionEn: 'Limits the Value Graph reference-edge count for one returned value.',
|
|
97
198
|
},
|
|
98
199
|
{
|
|
99
200
|
key: 'maxValueArrayLength',
|
|
@@ -101,10 +202,10 @@ export const CONFIG_FIELDS = Object.freeze([
|
|
|
101
202
|
default: 1_000_000,
|
|
102
203
|
min: 1,
|
|
103
204
|
max: Number.MAX_SAFE_INTEGER,
|
|
104
|
-
label: '
|
|
105
|
-
labelEn: '
|
|
106
|
-
description: '
|
|
107
|
-
descriptionEn: '
|
|
205
|
+
label: '返回数组长度上限',
|
|
206
|
+
labelEn: 'Returned-array length limit',
|
|
207
|
+
description: '限制返回数组的最大声明长度。',
|
|
208
|
+
descriptionEn: 'Limits the maximum declared length of a returned array.',
|
|
108
209
|
},
|
|
109
210
|
{
|
|
110
211
|
key: 'maxValueBigIntDigits',
|
|
@@ -112,84 +213,10 @@ export const CONFIG_FIELDS = Object.freeze([
|
|
|
112
213
|
default: 100_000,
|
|
113
214
|
min: 1,
|
|
114
215
|
max: Number.MAX_SAFE_INTEGER,
|
|
115
|
-
label: 'BigInt
|
|
116
|
-
labelEn: '
|
|
216
|
+
label: '返回值 BigInt 十进制位数上限',
|
|
217
|
+
labelEn: 'Returned-value BigInt decimal-digit limit',
|
|
117
218
|
description: '限制返回值中 BigInt 的十进制位数。',
|
|
118
|
-
descriptionEn: '
|
|
119
|
-
},
|
|
120
|
-
{
|
|
121
|
-
key: 'maxNestedRunCodeDepth',
|
|
122
|
-
type: 'integer',
|
|
123
|
-
default: 8,
|
|
124
|
-
min: 1,
|
|
125
|
-
max: Number.MAX_SAFE_INTEGER,
|
|
126
|
-
label: 'code.run 最大递归深度',
|
|
127
|
-
labelEn: 'Max code.run recursion depth',
|
|
128
|
-
description: '限制 code.run 的嵌套层数。',
|
|
129
|
-
descriptionEn: 'Caps how deeply code.run may nest.',
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
key: 'canonicalizeToolCalls',
|
|
133
|
-
type: 'boolean',
|
|
134
|
-
default: true,
|
|
135
|
-
label: '规范顶层 native 误调',
|
|
136
|
-
labelEn: 'Canonicalize top-level native mis-calls',
|
|
137
|
-
description: '修正可以明确识别的顶层 native 误调。',
|
|
138
|
-
descriptionEn: 'Repairs top-level native mis-calls that can be identified unambiguously.',
|
|
139
|
-
},
|
|
140
|
-
{
|
|
141
|
-
key: 'looseTopLevelRedeclarations',
|
|
142
|
-
type: 'boolean',
|
|
143
|
-
default: true,
|
|
144
|
-
label: '宽松顶层重声明',
|
|
145
|
-
labelEn: 'Loose top-level redeclarations',
|
|
146
|
-
description: '允许顶层 const/let 重声明已有变量。',
|
|
147
|
-
descriptionEn: 'Allows top-level const/let to redeclare existing variables.',
|
|
148
|
-
},
|
|
149
|
-
{
|
|
150
|
-
key: 'durableReplay',
|
|
151
|
-
type: 'boolean',
|
|
152
|
-
default: true,
|
|
153
|
-
label: '持久重放',
|
|
154
|
-
labelEn: 'Durable replay',
|
|
155
|
-
description: 'worker 重启后恢复可以重建的 REPL 状态。',
|
|
156
|
-
descriptionEn: 'Rebuilds recoverable REPL state after a worker restart.',
|
|
157
|
-
},
|
|
158
|
-
{
|
|
159
|
-
key: 'autoRewriteImports',
|
|
160
|
-
type: 'boolean',
|
|
161
|
-
default: true,
|
|
162
|
-
label: '自动改写 import',
|
|
163
|
-
labelEn: 'Auto-rewrite import',
|
|
164
|
-
description: '允许在 run_code 中使用静态 import。',
|
|
165
|
-
descriptionEn: 'Allows static import declarations inside run_code.',
|
|
166
|
-
},
|
|
167
|
-
{
|
|
168
|
-
key: 'autoStripExports',
|
|
169
|
-
type: 'boolean',
|
|
170
|
-
default: true,
|
|
171
|
-
label: '自动剥离 export',
|
|
172
|
-
labelEn: 'Auto-strip export',
|
|
173
|
-
description: '允许在 run_code 中使用顶层 export。',
|
|
174
|
-
descriptionEn: 'Allows top-level export modifiers inside run_code.',
|
|
175
|
-
},
|
|
176
|
-
{
|
|
177
|
-
key: 'autoSplitRedeclarations',
|
|
178
|
-
type: 'boolean',
|
|
179
|
-
default: true,
|
|
180
|
-
label: '自动拆分混合重声明',
|
|
181
|
-
labelEn: 'Auto-split mixed redeclarations',
|
|
182
|
-
description: '允许顶层解构声明同时包含新旧变量。',
|
|
183
|
-
descriptionEn: 'Allows top-level destructuring declarations that mix new and existing variables.',
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
key: 'tipsEnabled',
|
|
187
|
-
type: 'boolean',
|
|
188
|
-
default: true,
|
|
189
|
-
label: '启用恢复提示',
|
|
190
|
-
labelEn: 'Enable recovery tips',
|
|
191
|
-
description: '在符合条件的失败后显示恢复提示。',
|
|
192
|
-
descriptionEn: 'Shows recovery tips after qualifying failures.',
|
|
219
|
+
descriptionEn: 'Limits the decimal-digit count of BigInt values in one returned value.',
|
|
193
220
|
},
|
|
194
221
|
{
|
|
195
222
|
key: 'tipCooldownMessages',
|
|
@@ -197,8 +224,8 @@ export const CONFIG_FIELDS = Object.freeze([
|
|
|
197
224
|
default: 3,
|
|
198
225
|
min: 1,
|
|
199
226
|
max: Number.MAX_SAFE_INTEGER,
|
|
200
|
-
label: '
|
|
201
|
-
labelEn: '
|
|
227
|
+
label: '同类恢复提示间隔 (messages)',
|
|
228
|
+
labelEn: 'Same-kind recovery tip interval (messages)',
|
|
202
229
|
description: '同类恢复提示之间的最小间隔。',
|
|
203
230
|
descriptionEn: 'The minimum gap between recovery tips of the same kind.',
|
|
204
231
|
},
|
|
@@ -208,13 +235,61 @@ export const CONFIG_FIELDS = Object.freeze([
|
|
|
208
235
|
default: 2,
|
|
209
236
|
min: 1,
|
|
210
237
|
max: Number.MAX_SAFE_INTEGER,
|
|
211
|
-
label: '
|
|
212
|
-
labelEn: '
|
|
238
|
+
label: '详细恢复提示阈值 (failures)',
|
|
239
|
+
labelEn: 'Detailed recovery tip threshold (failures)',
|
|
213
240
|
description: '连续失败达到此次数后显示更详细的恢复提示。',
|
|
214
241
|
descriptionEn: 'After this many consecutive failures, a more detailed recovery tip is shown.',
|
|
215
242
|
},
|
|
216
243
|
])
|
|
217
244
|
|
|
245
|
+
/** Presentation groups keep high-attention decisions separate from advanced policy and limits. */
|
|
246
|
+
export const CONFIG_GROUPS = Object.freeze([
|
|
247
|
+
{
|
|
248
|
+
key: 'core',
|
|
249
|
+
label: '常用与兼容性',
|
|
250
|
+
labelEn: 'Common and compatibility',
|
|
251
|
+
fields: Object.freeze(['enabled', 'enhancedToolView', 'autoDescribeRunCode', 'canonicalizeToolCalls']),
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
key: 'optional',
|
|
255
|
+
label: '可选能力',
|
|
256
|
+
labelEn: 'Optional capabilities',
|
|
257
|
+
fields: Object.freeze(['cordisToolsEnabled']),
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
key: 'advanced',
|
|
261
|
+
label: '高级行为',
|
|
262
|
+
labelEn: 'Advanced behavior',
|
|
263
|
+
fields: Object.freeze([
|
|
264
|
+
'looseTopLevelRedeclarations',
|
|
265
|
+
'looseTopLevelFunctionClassRedeclarations',
|
|
266
|
+
'autoRewriteImports',
|
|
267
|
+
'autoStripExports',
|
|
268
|
+
'autoSplitRedeclarations',
|
|
269
|
+
'durableReplay',
|
|
270
|
+
'tipsEnabled',
|
|
271
|
+
]),
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
key: 'limits',
|
|
275
|
+
label: '资源限制',
|
|
276
|
+
labelEn: 'Resource limits',
|
|
277
|
+
fields: Object.freeze([
|
|
278
|
+
'computeMs',
|
|
279
|
+
'maxWallMs',
|
|
280
|
+
'maxOldGenerationSizeMb',
|
|
281
|
+
'maxNestedRunCodeDepth',
|
|
282
|
+
'maxOutputBytes',
|
|
283
|
+
'maxValueNodes',
|
|
284
|
+
'maxValueEdges',
|
|
285
|
+
'maxValueArrayLength',
|
|
286
|
+
'maxValueBigIntDigits',
|
|
287
|
+
'tipCooldownMessages',
|
|
288
|
+
'tipEscalationFailures',
|
|
289
|
+
]),
|
|
290
|
+
},
|
|
291
|
+
])
|
|
292
|
+
|
|
218
293
|
/** Resolved defaults, derived once from the field definitions. */
|
|
219
294
|
export const CONFIG_DEFAULTS = Object.freeze(
|
|
220
295
|
Object.fromEntries(CONFIG_FIELDS.map(field => [field.key, field.default])),
|
|
@@ -6,6 +6,11 @@ import { projectProgramSdk } from './sdk-projection.js'
|
|
|
6
6
|
import { EDIT_RUN_CODE } from './edit-transport-owner.js'
|
|
7
7
|
import { RUN_CODE } from './runtime-bridge-owner.js'
|
|
8
8
|
import { isRecord } from './record-utils.js'
|
|
9
|
+
import { missingDescriptionPath } from './failure-reporting.js'
|
|
10
|
+
import {
|
|
11
|
+
generatedRunCodeExecutionArguments,
|
|
12
|
+
generatedRunCodeDescriptionMeta,
|
|
13
|
+
} from './run-code-description.js'
|
|
9
14
|
|
|
10
15
|
const RUN_CODE_TOOL_DESCRIPTION = 'Evaluate the next TypeScript cell in this session-bound persistent REPL. Earlier top-level bindings remain available, so this call extends the current environment instead of creating a fresh one. Use `code` for the async-function body and `description` for its short UI summary. Successful image-bearing subtool results are attached after the cell.'
|
|
11
16
|
const RUN_CODE_CODE_DESCRIPTION = 'Code for the next REPL cell, parsed as the body of an async TypeScript function.'
|
|
@@ -147,6 +152,7 @@ export function createDirectSurfaceOwner({
|
|
|
147
152
|
const sessions = new Map()
|
|
148
153
|
const cordisRecovery = createCordisRecoveryPolicy(runtimeConfig.cordisToolsEnabled)
|
|
149
154
|
let currentCanonicalizeToolCalls = canonicalizeToolCalls
|
|
155
|
+
let currentAutoDescribeRunCode = runtimeConfig.autoDescribeRunCode
|
|
150
156
|
const tipConfig = {
|
|
151
157
|
enabled: runtimeConfig.tipsEnabled,
|
|
152
158
|
cooldownMessages: runtimeConfig.tipCooldownMessages,
|
|
@@ -187,9 +193,9 @@ export function createDirectSurfaceOwner({
|
|
|
187
193
|
return undefined
|
|
188
194
|
}
|
|
189
195
|
|
|
190
|
-
const rememberRequest = (id, signal, presentation, nativeSchemas) => {
|
|
196
|
+
const rememberRequest = (id, signal, presentation, nativeSchemas, autoDescribeRunCode) => {
|
|
191
197
|
const owner = sessionOwner(id)
|
|
192
|
-
const request = { presentation, nativeSchemas, owner }
|
|
198
|
+
const request = { presentation, nativeSchemas, autoDescribeRunCode, owner }
|
|
193
199
|
owner.latestRequest = request
|
|
194
200
|
if (signal !== undefined) canonicalRequests.set(signal, request)
|
|
195
201
|
}
|
|
@@ -211,12 +217,15 @@ export function createDirectSurfaceOwner({
|
|
|
211
217
|
return Object.freeze({
|
|
212
218
|
reconfigure(nextConfig) {
|
|
213
219
|
currentCanonicalizeToolCalls = nextConfig.canonicalizeToolCalls
|
|
220
|
+
currentAutoDescribeRunCode = nextConfig.autoDescribeRunCode
|
|
214
221
|
cordisRecovery.reconfigure(nextConfig.cordisToolsEnabled)
|
|
215
222
|
tipConfig.enabled = nextConfig.tipsEnabled
|
|
216
223
|
tipConfig.cooldownMessages = nextConfig.tipCooldownMessages
|
|
217
224
|
tipConfig.escalationFailures = nextConfig.tipEscalationFailures
|
|
218
225
|
},
|
|
219
226
|
async assemble(initialAssembly, context, next) {
|
|
227
|
+
// Keep schema projection and later execution on one configuration snapshot.
|
|
228
|
+
const autoDescribeRunCode = currentAutoDescribeRunCode
|
|
220
229
|
const agent = context?.agent
|
|
221
230
|
const id = sessionId(agent)
|
|
222
231
|
const initialState = presentationState(initialAssembly)
|
|
@@ -252,7 +261,7 @@ export function createDirectSurfaceOwner({
|
|
|
252
261
|
throw new Error(`ptc-plus: ${presentation} agent composition assembled without run_code`)
|
|
253
262
|
}
|
|
254
263
|
if (id !== undefined) {
|
|
255
|
-
rememberRequest(id, requestSignal, 'native', new Map())
|
|
264
|
+
rememberRequest(id, requestSignal, 'native', new Map(), autoDescribeRunCode)
|
|
256
265
|
}
|
|
257
266
|
return assembly
|
|
258
267
|
}
|
|
@@ -300,14 +309,16 @@ export function createDirectSurfaceOwner({
|
|
|
300
309
|
&& schema.name !== RUN_CODE && schema.name !== EDIT_RUN_CODE)
|
|
301
310
|
.map(schema => [schema.name, schema]))
|
|
302
311
|
: new Map()
|
|
303
|
-
rememberRequest(id, requestSignal, presentation, nativeSchemas)
|
|
312
|
+
rememberRequest(id, requestSignal, presentation, nativeSchemas, autoDescribeRunCode)
|
|
304
313
|
}
|
|
305
314
|
|
|
306
315
|
return {
|
|
307
316
|
...assembly,
|
|
308
317
|
tools: sessionPtcProjection
|
|
309
318
|
? directTools
|
|
310
|
-
: directTools.map(tool => tool?.name === RUN_CODE
|
|
319
|
+
: directTools.map(tool => tool?.name === RUN_CODE
|
|
320
|
+
? adaptRunCodeSchema(tool)
|
|
321
|
+
: tool),
|
|
311
322
|
sections,
|
|
312
323
|
contexts,
|
|
313
324
|
}
|
|
@@ -343,6 +354,46 @@ export function createDirectSurfaceOwner({
|
|
|
343
354
|
if (policy?.presentation !== 'ptc') return undefined
|
|
344
355
|
return rejection(`tool ${exec.name} is not a direct PTC tool; use run_code or edit_run_code directly, and call native tools from inside run_code`)
|
|
345
356
|
},
|
|
357
|
+
executionArguments(exec) {
|
|
358
|
+
const id = sessionId(exec.agent)
|
|
359
|
+
const policy = executionPolicy(id, exec.callId)
|
|
360
|
+
?? requestPolicy(exec?.signal, id)
|
|
361
|
+
const originalArguments = exec.arguments
|
|
362
|
+
if (exec.name !== RUN_CODE || exec.parent !== undefined
|
|
363
|
+
|| policy?.autoDescribeRunCode !== true || policy.presentation === 'native'
|
|
364
|
+
|| !isRecord(originalArguments) || Object.hasOwn(originalArguments, 'description')
|
|
365
|
+
|| typeof originalArguments.code !== 'string') {
|
|
366
|
+
return originalArguments
|
|
367
|
+
}
|
|
368
|
+
return generatedRunCodeExecutionArguments(originalArguments)
|
|
369
|
+
},
|
|
370
|
+
argumentDiagnostic(exec, result) {
|
|
371
|
+
// DSH uses success-result identity to avoid re-running output projectors
|
|
372
|
+
// after this middleware's settlement scope has ended.
|
|
373
|
+
if (exec?.name !== RUN_CODE || result?.isError !== true) return result
|
|
374
|
+
const meta = generatedRunCodeDescriptionMeta(exec.arguments, result.meta)
|
|
375
|
+
const diagnosed = meta === result.meta
|
|
376
|
+
? result
|
|
377
|
+
: { ...result, ...(meta === undefined ? {} : { meta }) }
|
|
378
|
+
const missingPath = missingDescriptionPath(diagnosed.error)
|
|
379
|
+
if (missingPath === undefined) return diagnosed
|
|
380
|
+
const id = sessionId(exec.agent)
|
|
381
|
+
const policy = executionPolicy(id, exec.callId)
|
|
382
|
+
?? requestPolicy(exec?.signal, id)
|
|
383
|
+
const outer = missingPath === 'description'
|
|
384
|
+
&& policy?.autoDescribeRunCode !== true
|
|
385
|
+
&& !(isRecord(exec.arguments) && typeof exec.arguments.description === 'string')
|
|
386
|
+
const context = {
|
|
387
|
+
name: 'tools:ptc-plus-run-code-arguments',
|
|
388
|
+
text: outer
|
|
389
|
+
? 'The run_code outer transport arguments are invalid at JSON path $.description. Add a sibling string `description` field to run_code; a description nested inside a native-tool argument does not satisfy this outer requirement.'
|
|
390
|
+
: `A nested native-tool argument is missing required property "${missingPath}". Add a string description at that path in the native-tool arguments; the outer run_code description does not satisfy this nested requirement.`,
|
|
391
|
+
}
|
|
392
|
+
return {
|
|
393
|
+
...diagnosed,
|
|
394
|
+
additionalContexts: [...diagnosed.additionalContexts ?? [], context],
|
|
395
|
+
}
|
|
396
|
+
},
|
|
346
397
|
handleResult(exec) {
|
|
347
398
|
const id = sessionId(exec.agent)
|
|
348
399
|
if (id === undefined || typeof exec.callId !== 'string') return
|
|
@@ -20,6 +20,10 @@ import {
|
|
|
20
20
|
import { editTargetForCall, projectSessionLog } from './session-log-view.js'
|
|
21
21
|
import { RUN_CODE } from './runtime-bridge-owner.js'
|
|
22
22
|
import { isRecord } from './record-utils.js'
|
|
23
|
+
import {
|
|
24
|
+
validatedReplMemorySnapshot,
|
|
25
|
+
withReplMemorySnapshot,
|
|
26
|
+
} from './repl-memory-projection.js'
|
|
23
27
|
|
|
24
28
|
export const EDIT_RUN_CODE = 'edit_run_code'
|
|
25
29
|
|
|
@@ -52,6 +56,7 @@ function derivedEditResult(inner) {
|
|
|
52
56
|
export function createEditTransportOwner(ctx, {
|
|
53
57
|
durableReplay,
|
|
54
58
|
executeTentative,
|
|
59
|
+
presentationGeneration,
|
|
55
60
|
sessionId,
|
|
56
61
|
toolSchemasForAgent,
|
|
57
62
|
}) {
|
|
@@ -91,7 +96,9 @@ export function createEditTransportOwner(ctx, {
|
|
|
91
96
|
if (derived.recoveryBoundaries !== undefined) {
|
|
92
97
|
meta[RECOVERY_BOUNDARY_KEY] = normalizeRecoveryBoundaries(derived.recoveryBoundaries)
|
|
93
98
|
}
|
|
94
|
-
return
|
|
99
|
+
return derived.replMemory === undefined
|
|
100
|
+
? meta
|
|
101
|
+
: withReplMemorySnapshot(meta, derived.replMemory, presentationGeneration)
|
|
95
102
|
}
|
|
96
103
|
definition.output = {
|
|
97
104
|
schema: {
|
|
@@ -140,7 +147,7 @@ export function createEditTransportOwner(ctx, {
|
|
|
140
147
|
if (typeof ctx.tools.execute !== 'function') {
|
|
141
148
|
throw new Error('ptc-plus: DSH tools.execute is required for derived edit execution')
|
|
142
149
|
}
|
|
143
|
-
const persistedCallSeq =
|
|
150
|
+
const persistedCallSeq = persistedTargetCallSeq
|
|
144
151
|
const id = sessionId(agent)
|
|
145
152
|
let claims = editClaims.get(id)
|
|
146
153
|
if (claims === undefined) {
|
|
@@ -178,12 +185,14 @@ export function createEditTransportOwner(ctx, {
|
|
|
178
185
|
&& Object.hasOwn(inner.meta, RECOVERY_BOUNDARY_KEY)
|
|
179
186
|
? normalizeRecoveryBoundaries(inner.meta[RECOVERY_BOUNDARY_KEY])
|
|
180
187
|
: undefined
|
|
188
|
+
const replMemory = validatedReplMemorySnapshot(inner?.meta, presentationGeneration)
|
|
181
189
|
const value = derivedEditResult(inner)
|
|
182
190
|
const derived = {
|
|
183
191
|
targetCallSeq: target.callSeq,
|
|
184
192
|
journal,
|
|
185
193
|
rewrites,
|
|
186
194
|
recoveryBoundaries,
|
|
195
|
+
replMemory,
|
|
187
196
|
code: edited.code,
|
|
188
197
|
description: edited.description,
|
|
189
198
|
}
|
|
@@ -64,6 +64,21 @@ export function oneLineMessage(error) {
|
|
|
64
64
|
return firstLine(messageOf(error), 'Unknown error').replace(/\s+\(\d+:\d+\)$/, '')
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
/** Return DSH's reported missing-description property path when it is actionable. */
|
|
68
|
+
export function missingDescriptionPath(error) {
|
|
69
|
+
const violations = messageOf(error).matchAll(/missing required property ["']([^"']+)["']/g)
|
|
70
|
+
for (const match of violations) {
|
|
71
|
+
const path = match[1]
|
|
72
|
+
if (path === 'description' || path.endsWith('.description')) return path
|
|
73
|
+
}
|
|
74
|
+
return undefined
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** Identify DSH's stable missing-description validation fact without parsing arbitrary errors. */
|
|
78
|
+
export function hasMissingDescriptionError(error) {
|
|
79
|
+
return missingDescriptionPath(error) !== undefined
|
|
80
|
+
}
|
|
81
|
+
|
|
67
82
|
/** Keep only the newest log entries so an output-limit error cannot flood the model. */
|
|
68
83
|
export function limitLogs(logs) {
|
|
69
84
|
let bytes = 0
|
|
@@ -366,6 +366,7 @@ async function runCell(message) {
|
|
|
366
366
|
pendingVolatileReason = undefined
|
|
367
367
|
activeExecution = execution
|
|
368
368
|
const cellGlobals = []
|
|
369
|
+
const committedRedeclarations = new Set()
|
|
369
370
|
|
|
370
371
|
try {
|
|
371
372
|
let completion
|
|
@@ -376,6 +377,13 @@ async function runCell(message) {
|
|
|
376
377
|
value: CellReturn,
|
|
377
378
|
})
|
|
378
379
|
cellGlobals.push(message.returnSignal)
|
|
380
|
+
Object.defineProperty(context, message.commitSignal, {
|
|
381
|
+
configurable: true,
|
|
382
|
+
value(name) {
|
|
383
|
+
committedRedeclarations.add(name)
|
|
384
|
+
},
|
|
385
|
+
})
|
|
386
|
+
cellGlobals.push(message.commitSignal)
|
|
379
387
|
for (const load of message.moduleLoads ?? []) {
|
|
380
388
|
let namespace
|
|
381
389
|
try {
|
|
@@ -421,6 +429,7 @@ async function runCell(message) {
|
|
|
421
429
|
...(position === undefined ? {} : { position }),
|
|
422
430
|
...(detail.cause === undefined ? {} : { cause: detail.cause }),
|
|
423
431
|
...completionDurability(execution),
|
|
432
|
+
committedRedeclarations: [...committedRedeclarations],
|
|
424
433
|
})
|
|
425
434
|
return
|
|
426
435
|
}
|
|
@@ -437,6 +446,7 @@ async function runCell(message) {
|
|
|
437
446
|
hasValue: completion.hasValue,
|
|
438
447
|
...(encodedValue === undefined ? {} : { value: encodedValue }),
|
|
439
448
|
...completionDurability(execution),
|
|
449
|
+
committedRedeclarations: [...committedRedeclarations],
|
|
440
450
|
}
|
|
441
451
|
} catch (error) {
|
|
442
452
|
const detail = messageOf(error)
|
|
@@ -446,6 +456,7 @@ async function runCell(message) {
|
|
|
446
456
|
logs: execution.logs,
|
|
447
457
|
invalidOutput: detail,
|
|
448
458
|
...completionDurability(execution),
|
|
459
|
+
committedRedeclarations: [...committedRedeclarations],
|
|
449
460
|
}
|
|
450
461
|
}
|
|
451
462
|
channel.postMessage(response)
|