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
|
@@ -19,6 +19,8 @@ import {
|
|
|
19
19
|
toolCapabilityMetadata,
|
|
20
20
|
} from './program-bindings.js'
|
|
21
21
|
import { deepFreeze } from './record-utils.js'
|
|
22
|
+
import { withReplMemorySnapshot } from './repl-memory-projection.js'
|
|
23
|
+
import { generatedRunCodeDescriptionMeta } from './run-code-description.js'
|
|
22
24
|
|
|
23
25
|
export const RUN_CODE = 'run_code'
|
|
24
26
|
|
|
@@ -123,6 +125,7 @@ export function createRuntimeBridgeOwner({
|
|
|
123
125
|
ctx,
|
|
124
126
|
sessionConfig,
|
|
125
127
|
maxNestedRunCodeDepth,
|
|
128
|
+
presentationGeneration,
|
|
126
129
|
sessionId,
|
|
127
130
|
toolSchemasForAgent,
|
|
128
131
|
}) {
|
|
@@ -247,7 +250,7 @@ export function createRuntimeBridgeOwner({
|
|
|
247
250
|
return { request: { ...request, bindings: projected }, release }
|
|
248
251
|
}
|
|
249
252
|
|
|
250
|
-
const
|
|
253
|
+
const patchRunCodeDefinition = (agent) => {
|
|
251
254
|
const definition = ctx.tools.get(RUN_CODE, agent)
|
|
252
255
|
if (definition === undefined) {
|
|
253
256
|
throw new Error('ptc-plus: run_code definition is unavailable for the owning session')
|
|
@@ -257,28 +260,65 @@ export function createRuntimeBridgeOwner({
|
|
|
257
260
|
}
|
|
258
261
|
if (patchedDefinitions.has(definition)) return
|
|
259
262
|
const output = definition.output
|
|
260
|
-
const
|
|
261
|
-
const
|
|
262
|
-
if (!active)
|
|
263
|
-
|
|
263
|
+
const originalPresentationMeta = output.presentationMeta
|
|
264
|
+
const patchedPresentationMeta = (args, value) => {
|
|
265
|
+
if (!active) {
|
|
266
|
+
return originalPresentationMeta === undefined
|
|
267
|
+
? undefined
|
|
268
|
+
: originalPresentationMeta(args, value)
|
|
269
|
+
}
|
|
270
|
+
const base = originalPresentationMeta === undefined
|
|
271
|
+
? undefined
|
|
272
|
+
: originalPresentationMeta(args, value)
|
|
264
273
|
const current = scope.getStore()
|
|
265
274
|
const settlement = current?.settlement
|
|
266
|
-
if (settlement === undefined) return base
|
|
275
|
+
if (settlement === undefined) return generatedRunCodeDescriptionMeta(args, base)
|
|
267
276
|
let meta = withJournal(base, settlement.journal)
|
|
268
277
|
if (settlement.recoveryBoundaries !== undefined) {
|
|
269
278
|
meta = withRecoveryBoundaries(meta, settlement.recoveryBoundaries)
|
|
270
279
|
}
|
|
271
|
-
|
|
280
|
+
if (settlement.rewrites !== undefined) meta = withRewrites(meta, settlement.rewrites)
|
|
281
|
+
meta = generatedRunCodeDescriptionMeta(args, meta)
|
|
282
|
+
return withReplMemorySnapshot(meta, settlement.replMemory, presentationGeneration)
|
|
272
283
|
}
|
|
284
|
+
const ownExecute = Object.getOwnPropertyDescriptor(definition, 'execute')
|
|
285
|
+
const originalExecute = definition.execute
|
|
286
|
+
const patchedExecute = typeof originalExecute !== 'function'
|
|
287
|
+
? undefined
|
|
288
|
+
: function (args, exec) {
|
|
289
|
+
const executionArguments = scope.getStore()?.executionArguments ?? args
|
|
290
|
+
return originalExecute.call(this, executionArguments, exec)
|
|
291
|
+
}
|
|
292
|
+
let presentationPatched = false
|
|
273
293
|
try {
|
|
274
294
|
Object.defineProperty(output, 'presentationMeta', {
|
|
275
295
|
configurable: true,
|
|
276
296
|
enumerable: true,
|
|
277
297
|
writable: true,
|
|
278
|
-
value:
|
|
298
|
+
value: patchedPresentationMeta,
|
|
299
|
+
})
|
|
300
|
+
presentationPatched = true
|
|
301
|
+
if (patchedExecute !== undefined) {
|
|
302
|
+
Object.defineProperty(definition, 'execute', {
|
|
303
|
+
configurable: true,
|
|
304
|
+
enumerable: ownExecute?.enumerable ?? true,
|
|
305
|
+
writable: true,
|
|
306
|
+
value: patchedExecute,
|
|
307
|
+
})
|
|
308
|
+
}
|
|
309
|
+
patchedDefinitions.set(definition, {
|
|
310
|
+
definition,
|
|
311
|
+
output,
|
|
312
|
+
originalPresentationMeta,
|
|
313
|
+
patchedPresentationMeta,
|
|
314
|
+
ownExecute,
|
|
315
|
+
patchedExecute,
|
|
279
316
|
})
|
|
280
|
-
patchedDefinitions.set(definition, { output, original, patched })
|
|
281
317
|
} catch (error) {
|
|
318
|
+
if (presentationPatched && output.presentationMeta === patchedPresentationMeta) {
|
|
319
|
+
if (originalPresentationMeta === undefined) delete output.presentationMeta
|
|
320
|
+
else output.presentationMeta = originalPresentationMeta
|
|
321
|
+
}
|
|
282
322
|
throw new Error(`ptc-plus: cannot attach the session journal to run_code results: ${error.message}`)
|
|
283
323
|
}
|
|
284
324
|
}
|
|
@@ -333,11 +373,11 @@ export function createRuntimeBridgeOwner({
|
|
|
333
373
|
throw error
|
|
334
374
|
}
|
|
335
375
|
},
|
|
336
|
-
handleExecute(exec, next) {
|
|
376
|
+
handleExecute(exec, next, executionArguments = exec.arguments) {
|
|
337
377
|
if (exec.parent !== undefined) return scope.run(undefined, next)
|
|
338
378
|
const id = sessionId(exec.agent)
|
|
339
379
|
if (id === undefined) return next()
|
|
340
|
-
|
|
380
|
+
patchRunCodeDefinition(exec.agent)
|
|
341
381
|
const inherited = scope.getStore()
|
|
342
382
|
const persistedCallSeq = inherited?.persistedCallSeq
|
|
343
383
|
const current = {
|
|
@@ -349,6 +389,7 @@ export function createRuntimeBridgeOwner({
|
|
|
349
389
|
: { deferredSettlement: inherited.deferredSettlement }),
|
|
350
390
|
session: exec.agent?.session,
|
|
351
391
|
agent: exec.agent,
|
|
392
|
+
executionArguments,
|
|
352
393
|
}
|
|
353
394
|
if (current.deferredSettlement !== undefined) {
|
|
354
395
|
current.deferredSettlement.current = current
|
|
@@ -363,6 +404,7 @@ export function createRuntimeBridgeOwner({
|
|
|
363
404
|
meta = withRecoveryBoundaries(meta, settlement.recoveryBoundaries)
|
|
364
405
|
}
|
|
365
406
|
if (settlement.rewrites !== undefined) meta = withRewrites(meta, settlement.rewrites)
|
|
407
|
+
meta = withReplMemorySnapshot(meta, settlement.replMemory, presentationGeneration)
|
|
366
408
|
return { ...result, meta }
|
|
367
409
|
}
|
|
368
410
|
return result
|
|
@@ -405,10 +447,16 @@ export function createRuntimeBridgeOwner({
|
|
|
405
447
|
if (ownRun === undefined) delete runtime.run
|
|
406
448
|
else Object.defineProperty(runtime, 'run', ownRun)
|
|
407
449
|
}
|
|
408
|
-
for (const
|
|
409
|
-
if (output.presentationMeta
|
|
410
|
-
|
|
411
|
-
|
|
450
|
+
for (const patched of patchedDefinitions.values()) {
|
|
451
|
+
if (patched.output.presentationMeta === patched.patchedPresentationMeta) {
|
|
452
|
+
if (patched.originalPresentationMeta === undefined) delete patched.output.presentationMeta
|
|
453
|
+
else patched.output.presentationMeta = patched.originalPresentationMeta
|
|
454
|
+
}
|
|
455
|
+
if (patched.patchedExecute !== undefined
|
|
456
|
+
&& patched.definition.execute === patched.patchedExecute) {
|
|
457
|
+
if (patched.ownExecute === undefined) delete patched.definition.execute
|
|
458
|
+
else Object.defineProperty(patched.definition, 'execute', patched.ownExecute)
|
|
459
|
+
}
|
|
412
460
|
}
|
|
413
461
|
patchedDefinitions.clear()
|
|
414
462
|
await sessions.dispose()
|
|
@@ -18,9 +18,12 @@ const BUDGET_KEYS = Object.freeze([
|
|
|
18
18
|
|
|
19
19
|
/** Boolean runtime behavior switches. */
|
|
20
20
|
const BOOLEAN_KEYS = Object.freeze([
|
|
21
|
+
'enhancedToolView',
|
|
22
|
+
'autoDescribeRunCode',
|
|
21
23
|
'cordisToolsEnabled',
|
|
22
24
|
'canonicalizeToolCalls',
|
|
23
25
|
'looseTopLevelRedeclarations',
|
|
26
|
+
'looseTopLevelFunctionClassRedeclarations',
|
|
24
27
|
'durableReplay',
|
|
25
28
|
'autoRewriteImports',
|
|
26
29
|
'autoStripExports',
|
|
@@ -12,11 +12,13 @@ import {
|
|
|
12
12
|
LONG_CELL_CODE_UNITS,
|
|
13
13
|
markBindingFailure,
|
|
14
14
|
messageOf,
|
|
15
|
+
missingDescriptionPath,
|
|
15
16
|
oneLineMessage,
|
|
16
17
|
safeProperty,
|
|
17
18
|
} from './failure-reporting.js'
|
|
18
19
|
import { assertStateName } from './session-journal.js'
|
|
19
20
|
import { PreflightError, prepareProgram } from './cell-analysis.js'
|
|
21
|
+
import { LIVE_DEFAULT_EXPORT_BINDING } from './repl-rewrite-contract.js'
|
|
20
22
|
import { ModuleRewriteError } from './cell-rewriter.js'
|
|
21
23
|
import { mapSourcePosition } from './source-position-map.js'
|
|
22
24
|
import { durabilityState, transitionDurability } from './session-state.js'
|
|
@@ -104,9 +106,47 @@ function preflightDiagnostic(error) {
|
|
|
104
106
|
})
|
|
105
107
|
}
|
|
106
108
|
|
|
109
|
+
function committedRedeclarationSet(message, prepared) {
|
|
110
|
+
if (!Array.isArray(message.committedRedeclarations)) {
|
|
111
|
+
throw new Error('kernel returned an invalid committed redeclaration set')
|
|
112
|
+
}
|
|
113
|
+
const allowed = prepared.commitTargets
|
|
114
|
+
const committed = new Set()
|
|
115
|
+
for (const name of message.committedRedeclarations) {
|
|
116
|
+
if (typeof name !== 'string' || committed.has(name) || !allowed.has(name)) {
|
|
117
|
+
throw new Error('kernel returned an invalid committed redeclaration set')
|
|
118
|
+
}
|
|
119
|
+
committed.add(name)
|
|
120
|
+
}
|
|
121
|
+
return committed
|
|
122
|
+
}
|
|
123
|
+
|
|
107
124
|
function collisionDiagnostic(collisions) {
|
|
108
125
|
const names = [...new Set(collisions.map(item => item.name))]
|
|
126
|
+
const reasons = new Set(collisions.map(item => item.reason).filter(Boolean))
|
|
127
|
+
const disabledKinds = new Set(collisions
|
|
128
|
+
.filter(item => item.reason === 'function-class-redeclarations-disabled')
|
|
129
|
+
.map(item => item.kind))
|
|
109
130
|
const first = collisions[0]
|
|
131
|
+
const alternatives = [
|
|
132
|
+
...(disabledKinds.size === 2
|
|
133
|
+
? ['assign function or class expressions to the existing writable bindings']
|
|
134
|
+
: disabledKinds.has('function')
|
|
135
|
+
? ['assign a function expression to the existing writable binding']
|
|
136
|
+
: disabledKinds.has('class')
|
|
137
|
+
? ['assign a class expression to the existing writable binding']
|
|
138
|
+
: []),
|
|
139
|
+
...((reasons.size === 0 || reasons.has('variable-redeclarations-disabled'))
|
|
140
|
+
? ['reuse the existing bindings']
|
|
141
|
+
: []),
|
|
142
|
+
]
|
|
143
|
+
const help = [
|
|
144
|
+
...(reasons.has('binding-not-writable')
|
|
145
|
+
? ['use a fresh name because the existing binding is immutable']
|
|
146
|
+
: []),
|
|
147
|
+
...(alternatives.length === 0 ? [] : [alternatives.join('; ')]),
|
|
148
|
+
'place one-off declarations inside a block',
|
|
149
|
+
]
|
|
110
150
|
return diagnostic({
|
|
111
151
|
code: 'PTC-N001',
|
|
112
152
|
severity: 'error',
|
|
@@ -114,10 +154,7 @@ function collisionDiagnostic(collisions) {
|
|
|
114
154
|
message: `top-level bindings already exist: ${names.join(', ')}. This cell was not executed; the REPL state is unchanged.`,
|
|
115
155
|
stateEffect: 'unchanged',
|
|
116
156
|
source: { cell: 'current', start: first.start, end: first.end },
|
|
117
|
-
help
|
|
118
|
-
'reuse the existing bindings',
|
|
119
|
-
'place one-off declarations inside a block',
|
|
120
|
-
],
|
|
157
|
+
help,
|
|
121
158
|
})
|
|
122
159
|
}
|
|
123
160
|
|
|
@@ -128,7 +165,11 @@ function exceptionDiagnostic({
|
|
|
128
165
|
declared,
|
|
129
166
|
longCellFailure = false,
|
|
130
167
|
}) {
|
|
131
|
-
const
|
|
168
|
+
const missingPath = error.name === 'ToolCallError' ? missingDescriptionPath(error) : undefined
|
|
169
|
+
const missingDescription = missingPath !== undefined
|
|
170
|
+
const message = missingDescription
|
|
171
|
+
? `nested native tool arguments are missing required \`description\` at JSON path $.${missingPath} (${error.toolName ?? 'unknown tool'}); this does not satisfy the outer run_code transport`
|
|
172
|
+
: firstLine(error.message, 'Unknown exception')
|
|
132
173
|
const rawName = typeof error.name === 'string' && error.name.length > 0
|
|
133
174
|
? error.name
|
|
134
175
|
/* c8 ignore next */
|
|
@@ -147,7 +188,9 @@ function exceptionDiagnostic({
|
|
|
147
188
|
...(cause === undefined ? {} : { cause }),
|
|
148
189
|
...(source === undefined ? {} : { source }),
|
|
149
190
|
help: [
|
|
150
|
-
|
|
191
|
+
...(missingDescription
|
|
192
|
+
? ['add a string `description` property to the nested native-tool argument object']
|
|
193
|
+
: ['inspect existing bindings and retry only the failing expression']),
|
|
151
194
|
...(error.name === 'ToolCallError'
|
|
152
195
|
&& typeof error.toolName === 'string'
|
|
153
196
|
&& error.toolName.startsWith('cordis_')
|
|
@@ -211,22 +254,28 @@ export class SessionCellExecutor {
|
|
|
211
254
|
}
|
|
212
255
|
|
|
213
256
|
const catalog = kernel.bindingCatalog.inputs()
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
:
|
|
257
|
+
const bindingPolicy = replayRecord === undefined ? {
|
|
258
|
+
variableRedeclarations: config.looseTopLevelRedeclarations,
|
|
259
|
+
functionClassRedeclarations: config.looseTopLevelFunctionClassRedeclarations,
|
|
260
|
+
} : replayRecord.bindingPolicy
|
|
217
261
|
const rewritesEnabled = replayRecord === undefined ? {
|
|
218
262
|
autoRewriteImports: config.autoRewriteImports,
|
|
219
263
|
autoStripExports: config.autoStripExports,
|
|
220
264
|
autoSplitRedeclarations: config.autoSplitRedeclarations,
|
|
221
265
|
} : replayRecord.rewritePolicy
|
|
266
|
+
const moduleSemantics = replayRecord === undefined ? {
|
|
267
|
+
defaultExportBinding: LIVE_DEFAULT_EXPORT_BINDING,
|
|
268
|
+
} : replayRecord.moduleSemantics
|
|
222
269
|
const prepareCell = program => prepareProgram(
|
|
223
270
|
program,
|
|
224
271
|
catalog.knownBindings,
|
|
225
|
-
|
|
272
|
+
bindingPolicy,
|
|
226
273
|
request.bindingDescriptors.reservedNames,
|
|
227
274
|
rewritesEnabled,
|
|
228
275
|
catalog.importBindings,
|
|
229
276
|
catalog.importNamespaces,
|
|
277
|
+
catalog.writableBindings,
|
|
278
|
+
moduleSemantics,
|
|
230
279
|
)
|
|
231
280
|
let prepared
|
|
232
281
|
try {
|
|
@@ -341,6 +390,7 @@ export class SessionCellExecutor {
|
|
|
341
390
|
type: 'run', id, program: prepared.code, namespaces: bindings.workerDescriptors,
|
|
342
391
|
moduleLoads: prepared.moduleLoads,
|
|
343
392
|
returnSignal: prepared.returnSignal,
|
|
393
|
+
commitSignal: prepared.commitSignal,
|
|
344
394
|
maxOutputBytes: config.maxOutputBytes,
|
|
345
395
|
valueLimits,
|
|
346
396
|
durability,
|
|
@@ -473,6 +523,20 @@ export class SessionCellExecutor {
|
|
|
473
523
|
}, true)
|
|
474
524
|
return
|
|
475
525
|
}
|
|
526
|
+
let committed
|
|
527
|
+
try {
|
|
528
|
+
committed = committedRedeclarationSet(message, active.prepared)
|
|
529
|
+
} catch (error) {
|
|
530
|
+
active.resolve(earlyResult('worker-exit', messageOf(error)), true)
|
|
531
|
+
return
|
|
532
|
+
}
|
|
533
|
+
active.appliedBindingCatalog = message.moduleLoadFailed === true
|
|
534
|
+
? active.priorBindingCatalog
|
|
535
|
+
: active.priorBindingCatalog.advance(
|
|
536
|
+
active.prepared,
|
|
537
|
+
active.request.program,
|
|
538
|
+
committed,
|
|
539
|
+
)
|
|
476
540
|
if (typeof message.error === 'string') {
|
|
477
541
|
const rawError = {
|
|
478
542
|
kind: 'exception',
|
|
@@ -494,9 +558,6 @@ export class SessionCellExecutor {
|
|
|
494
558
|
declared: message.moduleLoadFailed === true ? new Set() : active.prepared.declared,
|
|
495
559
|
longCellFailure: active.request.program.length >= LONG_CELL_CODE_UNITS,
|
|
496
560
|
})
|
|
497
|
-
active.appliedBindingCatalog = message.moduleLoadFailed === true
|
|
498
|
-
? active.priorBindingCatalog
|
|
499
|
-
: active.priorBindingCatalog.advance(active.prepared)
|
|
500
561
|
const recordedFailure = active.replay?.diagnostics?.find(item => item.code === 'PTC-X001')
|
|
501
562
|
const failure = recordedFailure?.message === actualFailure.message ? recordedFailure : actualFailure
|
|
502
563
|
const error = {
|
|
@@ -525,7 +586,6 @@ export class SessionCellExecutor {
|
|
|
525
586
|
hasValue: message.hasValue,
|
|
526
587
|
...(message.hasValue ? { value } : {}),
|
|
527
588
|
}
|
|
528
|
-
active.appliedBindingCatalog = active.priorBindingCatalog.advance(active.prepared)
|
|
529
589
|
if (active.replay?.completion?.kind === 'return'
|
|
530
590
|
&& (active.replay.completion.hasValue !== message.hasValue
|
|
531
591
|
|| (message.hasValue && !valueWiresEqual(active.replay.completion.value, value, active.valueLimits)))) {
|