dsh-ptc-plus 0.3.2 → 0.4.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 +63 -80
- package/README.md +63 -80
- 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 +30827 -742
- 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 +556 -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 +7 -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 +5 -3
- package/docs/adr/0007-separate-worker-transport-from-session-semantics.md +1 -1
- 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 +3 -1
- package/docs/adr/0014-persist-cell-rewrite-policy.md +6 -2
- 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 +5 -3
- package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -2
- package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +12 -0
- 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 +77 -21
- package/docs/binding-review-placement-design.md +200 -0
- package/docs/capability-projection.md +1 -1
- package/docs/client-ui.md +95 -19
- package/docs/durability-design.md +28 -10
- package/docs/evaluation.md +78 -6
- package/docs/installation.md +41 -6
- package/docs/publishing.md +5 -3
- package/docs/runtime-reference.md +76 -25
- package/docs/semantic-validation.md +29 -0
- package/docs/stateful-binding-updates-proposal.md +759 -0
- package/docs/user-bindings.en.md +66 -0
- package/docs/user-bindings.md +66 -0
- package/docs/value-wire.md +3 -3
- package/docs/verification-optimization-work.md +41 -0
- package/docs/verification.md +71 -0
- package/index.js +369 -92
- package/internal/ast-traversal.js +5 -2
- package/internal/async-local-storage-intrinsics.js +38 -0
- package/internal/binding-declaration-contract.js +8 -0
- 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 +708 -0
- package/internal/binding-update-policy.js +72 -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 +253 -290
- 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 -677
- 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 +50 -0
- package/internal/compiler-module-links.js +37 -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 +83 -27
- 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 +91 -0
- package/internal/dynamic-environment-runtime.js +383 -0
- package/internal/dynamic-native-calls.js +153 -0
- package/internal/dynamic-native-runtime.js +262 -0
- package/internal/dynamic-scope-analysis.js +90 -0
- package/internal/edit-transport-owner.js +27 -2
- package/internal/execution-seam-compat.js +193 -0
- package/internal/failure-reporting.js +136 -28
- package/internal/host-rpc.js +66 -0
- package/internal/isolated-worker.js +555 -0
- package/internal/kernel-child.js +139 -0
- package/internal/kernel-worker.js +1179 -233
- 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 +322 -0
- package/internal/module-runtime-platform.js +19 -0
- package/internal/module-transform-contract.js +42 -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/record-utils.js +24 -15
- package/internal/recovery-tips.js +27 -15
- package/internal/rejected-cell-editor.js +13 -8
- package/internal/repl-convenience.js +2 -289
- package/internal/repl-memory-projection.js +81 -12
- package/internal/repl-observation-interest.js +70 -0
- package/internal/repl-rewrite-contract.js +6 -0
- package/internal/repl-scope-normalizer.js +2091 -0
- package/internal/repl-value-observer.js +117 -0
- package/internal/rpc-contract.js +52 -0
- package/internal/runtime-bridge-owner.js +172 -28
- package/internal/runtime-config.js +48 -52
- package/internal/runtime-contexts.js +82 -10
- package/internal/runtime-intrinsics.js +101 -0
- package/internal/runtime-messages.js +111 -0
- package/internal/session-cell-executor.js +402 -87
- package/internal/session-journal-recovery.js +684 -0
- package/internal/session-journal-schema.js +123 -0
- package/internal/session-journal.js +199 -654
- package/internal/session-log-view.js +42 -9
- package/internal/session-runtime.js +257 -95
- package/internal/session-state.js +247 -71
- package/internal/source-position-map.js +230 -71
- package/internal/stateful-module-compiler.js +154 -0
- package/internal/stateful-module-runtime.js +303 -0
- package/internal/stateful-root-compiler.js +600 -0
- package/internal/stateful-root-runtime.js +340 -0
- package/internal/typert-codec-compat.js +28 -0
- package/internal/typescript-transform.js +31 -0
- package/internal/user-binding-authoring.js +70 -0
- package/internal/user-binding-console-worker.js +244 -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 +361 -0
- package/internal/value-wire-schema.js +28 -0
- package/internal/value-wire.js +130 -91
- package/internal/worker-client.js +57 -67
- package/internal/worker-cwd-virtualization.js +80 -53
- package/internal/worker-environment.js +65 -0
- package/internal/worker-output-relay.js +29 -0
- package/internal/worker-repl-realm.js +134 -0
- package/internal/worker-shutdown.js +14 -0
- package/package.json +76 -7
- package/src/client-activity.js +95 -53
- 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
|
@@ -7,6 +7,7 @@ import { RUN_CODE } from './runtime-bridge-owner.js'
|
|
|
7
7
|
const CORDIS_PRESET_ID = 'cordis'
|
|
8
8
|
const CORDIS_SKILL_NAME = 'cordis-plugin-development'
|
|
9
9
|
const CORDIS_SKILL_PROVIDER = 'ptc-plus-cordis'
|
|
10
|
+
const COMPANION_SKILL_TOOL = 'skill'
|
|
10
11
|
|
|
11
12
|
function exactCompanionCandidates(observation) {
|
|
12
13
|
if (Array.isArray(observation)) {
|
|
@@ -80,6 +81,40 @@ function requireFiberServices(agent, fiber, owner) {
|
|
|
80
81
|
}
|
|
81
82
|
}
|
|
82
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Companion surfaces the agent scope decides for itself.
|
|
86
|
+
*
|
|
87
|
+
* A scope composes its own tools, preset service and Skill service, so one that
|
|
88
|
+
* omits any of them is not a scope this plugin publishes in yet: the host keeps
|
|
89
|
+
* authority over the composition, and the missing member can appear later (a
|
|
90
|
+
* tool registered after this owner loaded, a service provided by a plugin that
|
|
91
|
+
* loads later). Such an agent therefore stays deferred instead of becoming a
|
|
92
|
+
* failure, which also keeps this plugin's unavailability out of the host
|
|
93
|
+
* operation that created it. `undefined` reports a scope without the public
|
|
94
|
+
* `Context.get` API, whose contradiction the activation guard owns.
|
|
95
|
+
*
|
|
96
|
+
* @param {object} agent - the DSH agent scope.
|
|
97
|
+
* @returns {string[]|undefined} the missing companion surfaces, if any.
|
|
98
|
+
*/
|
|
99
|
+
function absentCompanionSurfaces(agent) {
|
|
100
|
+
if (typeof agent?.ctx?.get !== 'function') return undefined
|
|
101
|
+
const missing = []
|
|
102
|
+
if (agent.ctx.tools?.get?.(RUN_CODE, agent) === undefined) missing.push(`the ${RUN_CODE} tool`)
|
|
103
|
+
if (agent.ctx.tools?.get?.(COMPANION_SKILL_TOOL, agent) === undefined) {
|
|
104
|
+
missing.push(`the ${COMPANION_SKILL_TOOL} tool`)
|
|
105
|
+
}
|
|
106
|
+
if (agent.ctx.get('agentPresets') === undefined) missing.push('the agentPresets service')
|
|
107
|
+
if (agent.ctx.get('skills') === undefined) missing.push('the skills service')
|
|
108
|
+
return missing
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Read the services the mount publishes through, and reject a scope whose
|
|
113
|
+
* exposed service contradicts their public contract. Whether a companion surface
|
|
114
|
+
* exists at all is decided before the mount ([`absentCompanionSurfaces`]): this
|
|
115
|
+
* guard owns the shapes, so a service that is present but does not expose the
|
|
116
|
+
* API the mount calls is a host contradiction rather than a deferred surface.
|
|
117
|
+
*/
|
|
83
118
|
function requireCompanionServices(agent) {
|
|
84
119
|
if (typeof agent?.ctx?.get !== 'function') {
|
|
85
120
|
throw new Error('ptc-plus: cordisToolsEnabled requires the DSH agent Context.get API')
|
|
@@ -93,9 +128,6 @@ function requireCompanionServices(agent) {
|
|
|
93
128
|
|| typeof skills.list !== 'function' || typeof skills.get !== 'function') {
|
|
94
129
|
throw new Error('ptc-plus: cordisToolsEnabled requires the DSH skills registerProvider/list/get APIs')
|
|
95
130
|
}
|
|
96
|
-
if (agent.ctx.tools?.get?.('skill', agent) === undefined) {
|
|
97
|
-
throw new Error('ptc-plus: cordisToolsEnabled requires the DSH skill tool in the PTC agent scope')
|
|
98
|
-
}
|
|
99
131
|
return { agentPresets, skills }
|
|
100
132
|
}
|
|
101
133
|
|
|
@@ -234,6 +266,8 @@ export function createCordisToolsOwner(
|
|
|
234
266
|
}
|
|
235
267
|
const mounts = new Map()
|
|
236
268
|
const pending = new Set()
|
|
269
|
+
// Agent scopes this owner withdrew from, keyed by the failure it reported.
|
|
270
|
+
const withdrawn = new Map()
|
|
237
271
|
const cordisInspectLeases = createCordisInspectLeases(ctx)
|
|
238
272
|
const scopedCordisPlugin = cordisInspectLeases.plugin(cordisPlugin)
|
|
239
273
|
const scopedSkillPlugin = exactCompanionSkillPlugin(skillFilesystemPlugin)
|
|
@@ -251,19 +285,34 @@ export function createCordisToolsOwner(
|
|
|
251
285
|
const disposeMount = (agent, mount) => {
|
|
252
286
|
mount.disposed = true
|
|
253
287
|
if (mount.disposal === undefined) {
|
|
254
|
-
|
|
288
|
+
const operation = (async () => {
|
|
255
289
|
const failures = []
|
|
256
|
-
|
|
290
|
+
const fibers = [...mount.fibers].reverse()
|
|
291
|
+
const results = await Promise.allSettled(fibers.map(fiber => {
|
|
257
292
|
try {
|
|
258
|
-
|
|
293
|
+
return Promise.resolve(fiber.dispose())
|
|
259
294
|
} catch (error) {
|
|
260
|
-
|
|
295
|
+
return Promise.reject(error)
|
|
296
|
+
}
|
|
297
|
+
}))
|
|
298
|
+
for (let index = 0; index < results.length; index += 1) {
|
|
299
|
+
const result = results[index]
|
|
300
|
+
const fiber = fibers[index]
|
|
301
|
+
if (result.status === 'rejected') failures.push(result.reason)
|
|
302
|
+
else {
|
|
303
|
+
const ownedIndex = mount.fibers.indexOf(fiber)
|
|
304
|
+
if (ownedIndex !== -1) mount.fibers.splice(ownedIndex, 1)
|
|
261
305
|
}
|
|
262
306
|
}
|
|
263
307
|
if (failures.length > 0) {
|
|
264
308
|
throw new AggregateError(failures, 'ptc-plus Cordis agent mount disposal failed')
|
|
265
309
|
}
|
|
266
310
|
})()
|
|
311
|
+
mount.disposal = operation
|
|
312
|
+
operation.then(
|
|
313
|
+
() => { if (mount.disposal === operation) mount.disposal = undefined },
|
|
314
|
+
() => { if (mount.disposal === operation) mount.disposal = undefined },
|
|
315
|
+
)
|
|
267
316
|
}
|
|
268
317
|
return mount.disposal.then(() => {
|
|
269
318
|
if (mounts.get(agent) === mount) mounts.delete(agent)
|
|
@@ -272,6 +321,7 @@ export function createCordisToolsOwner(
|
|
|
272
321
|
|
|
273
322
|
const disposeAgent = async (agent) => {
|
|
274
323
|
pending.delete(agent)
|
|
324
|
+
withdrawn.delete(agent)
|
|
275
325
|
const mount = mounts.get(agent)
|
|
276
326
|
if (mount === undefined) return
|
|
277
327
|
await disposeMount(agent, mount)
|
|
@@ -280,8 +330,11 @@ export function createCordisToolsOwner(
|
|
|
280
330
|
const installAgent = (agent) => {
|
|
281
331
|
if (disposed) return Promise.resolve()
|
|
282
332
|
const mounted = mounts.get(agent)
|
|
283
|
-
if (mounted !== undefined)
|
|
284
|
-
|
|
333
|
+
if (mounted !== undefined) {
|
|
334
|
+
return mounted.withdrawn === true ? Promise.resolve() : mounted.activation
|
|
335
|
+
}
|
|
336
|
+
const absent = absentCompanionSurfaces(agent)
|
|
337
|
+
if (absent !== undefined && absent.length > 0) {
|
|
285
338
|
pending.add(agent)
|
|
286
339
|
return Promise.resolve()
|
|
287
340
|
}
|
|
@@ -295,6 +348,7 @@ export function createCordisToolsOwner(
|
|
|
295
348
|
disposal: undefined,
|
|
296
349
|
activated: false,
|
|
297
350
|
disposed: false,
|
|
351
|
+
withdrawn: false,
|
|
298
352
|
}
|
|
299
353
|
mounts.set(agent, mount)
|
|
300
354
|
mount.activation = Promise.resolve().then(async () => {
|
|
@@ -340,10 +394,51 @@ export function createCordisToolsOwner(
|
|
|
340
394
|
return mount.activation
|
|
341
395
|
}
|
|
342
396
|
|
|
397
|
+
/**
|
|
398
|
+
* Report one agent scope this owner cannot serve and stop retrying it.
|
|
399
|
+
*
|
|
400
|
+
* A scope whose exposed preset, services, provider or fiber activation
|
|
401
|
+
* contradicts the DSH contract is not repaired by a later tool registration,
|
|
402
|
+
* and DSH sessions create many scopes, so the same failure is reported once
|
|
403
|
+
* per scope instead of once per turn. The mount is marked so later calls
|
|
404
|
+
* resolve immediately rather than repeating the attempt and its diagnostic.
|
|
405
|
+
*/
|
|
406
|
+
const withdraw = (agent, error) => {
|
|
407
|
+
const mount = mounts.get(agent)
|
|
408
|
+
if (mount !== undefined) mount.withdrawn = true
|
|
409
|
+
pending.delete(agent)
|
|
410
|
+
const message = error instanceof Error ? error.message : String(error)
|
|
411
|
+
if (withdrawn.get(agent) === message) return
|
|
412
|
+
withdrawn.set(agent, message)
|
|
413
|
+
ctx.logger?.warn?.('ptc-plus: Cordis companion tooling withdrew from an agent scope', error)
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Install for a call the host makes on its own behalf.
|
|
418
|
+
*
|
|
419
|
+
* DSH 0.1.6 announces `agent/created` serially and rejects `agents.create()`
|
|
420
|
+
* when a listener rejects, so a scope this owner cannot serve must withdraw
|
|
421
|
+
* instead of failing an operation another plugin asked for. Install-time
|
|
422
|
+
* enumeration stays strict: there the plugin speaks for what it claims to
|
|
423
|
+
* have published, and `ready` reports the same failure.
|
|
424
|
+
*/
|
|
425
|
+
const installForHost = (agent) => {
|
|
426
|
+
let activation
|
|
427
|
+
try {
|
|
428
|
+
activation = installAgent(agent)
|
|
429
|
+
} catch (error) {
|
|
430
|
+
withdraw(agent, error)
|
|
431
|
+
return Promise.resolve()
|
|
432
|
+
}
|
|
433
|
+
return Promise.resolve(activation).catch(error => {
|
|
434
|
+
withdraw(agent, error)
|
|
435
|
+
})
|
|
436
|
+
}
|
|
437
|
+
|
|
343
438
|
const promptAssembly = async (_assembly, context, next) => {
|
|
344
439
|
const agent = context?.scope
|
|
345
440
|
if (agent === undefined || mounts.get(agent)?.activated === true) return next()
|
|
346
|
-
await
|
|
441
|
+
await installForHost(agent)
|
|
347
442
|
if (disposed || mounts.get(agent)?.activated !== true) return next()
|
|
348
443
|
if (typeof ctx.systemPrompt?.assemble !== 'function') {
|
|
349
444
|
throw new Error('ptc-plus: cordisToolsEnabled requires the DSH systemPrompt.assemble API')
|
|
@@ -369,7 +464,7 @@ export function createCordisToolsOwner(
|
|
|
369
464
|
let initialActivations
|
|
370
465
|
try {
|
|
371
466
|
stopPromptAssembly = ctx.on('system-prompt/assemble', promptAssembly, { prepend: true })
|
|
372
|
-
stopCreated = ctx.on('agent/created', ({ agent }) =>
|
|
467
|
+
stopCreated = ctx.on('agent/created', ({ agent }) => installForHost(agent))
|
|
373
468
|
stopDisposed = ctx.on('agent/disposed', ({ agent }) => disposeAgent(agent))
|
|
374
469
|
stopToolsChange = ctx.on('tools/change', retryPending)
|
|
375
470
|
initialActivations = ctx.agents.list().map(installAgent)
|
|
@@ -387,26 +482,40 @@ export function createCordisToolsOwner(
|
|
|
387
482
|
}
|
|
388
483
|
|
|
389
484
|
let disposal
|
|
485
|
+
let leasesDisposed = false
|
|
390
486
|
const dispose = () => {
|
|
391
487
|
if (disposal !== undefined) return disposal
|
|
392
488
|
disposed = true
|
|
393
|
-
stopToolsChange()
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
489
|
+
stopToolsChange?.()
|
|
490
|
+
stopToolsChange = undefined
|
|
491
|
+
stopDisposed?.()
|
|
492
|
+
stopDisposed = undefined
|
|
493
|
+
stopCreated?.()
|
|
494
|
+
stopCreated = undefined
|
|
495
|
+
stopPromptAssembly?.()
|
|
496
|
+
stopPromptAssembly = undefined
|
|
397
497
|
pending.clear()
|
|
498
|
+
withdrawn.clear()
|
|
398
499
|
const owned = [...mounts.entries()]
|
|
399
500
|
const attempts = owned.map(([agent, mount]) => disposeMount(agent, mount))
|
|
400
|
-
|
|
501
|
+
const operation = Promise.allSettled(attempts).then(results => {
|
|
401
502
|
const failures = results.filter(result => result.status === 'rejected').map(result => result.reason)
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
503
|
+
if (!leasesDisposed) {
|
|
504
|
+
try {
|
|
505
|
+
cordisInspectLeases.dispose()
|
|
506
|
+
leasesDisposed = true
|
|
507
|
+
} catch (error) {
|
|
508
|
+
failures.push(error)
|
|
509
|
+
}
|
|
406
510
|
}
|
|
407
511
|
if (failures.length > 0) throw new AggregateError(failures, 'ptc-plus Cordis disposal failed')
|
|
408
512
|
})
|
|
409
|
-
|
|
513
|
+
disposal = operation
|
|
514
|
+
operation.then(
|
|
515
|
+
() => { if (disposal === operation) disposal = undefined },
|
|
516
|
+
() => { if (disposal === operation) disposal = undefined },
|
|
517
|
+
)
|
|
518
|
+
return operation
|
|
410
519
|
}
|
|
411
520
|
const ready = Promise.all(initialActivations).then(() => undefined).catch(async error => {
|
|
412
521
|
try {
|
package/internal/diagnostic.js
CHANGED
|
@@ -3,9 +3,10 @@ import { assertOwnFields, isRecord } from './record-utils.js'
|
|
|
3
3
|
|
|
4
4
|
const DIAGNOSTIC_FIELDS = new Set([
|
|
5
5
|
'code', 'severity', 'phase', 'message', 'stateEffect', 'dispatchState',
|
|
6
|
-
'source', 'cause', 'help',
|
|
6
|
+
'source', 'cause', 'help', 'collisions',
|
|
7
7
|
])
|
|
8
8
|
const SOURCE_FIELDS = new Set(['cell', 'start', 'end'])
|
|
9
|
+
const COLLISION_FIELDS = new Set(['name', 'kind', 'reason', 'start', 'end'])
|
|
9
10
|
const POSITION_FIELDS = new Set(['line', 'column'])
|
|
10
11
|
const CAUSE_FIELDS = new Set(['code', 'message'])
|
|
11
12
|
const SEVERITIES = new Set(['error', 'warning', 'note'])
|
|
@@ -26,6 +27,23 @@ function normalizePosition(value, label) {
|
|
|
26
27
|
return Object.freeze({ line: value.line, column: value.column })
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
/** One collision record as its compiler owner determined it: the colliding name, its
|
|
31
|
+
* declaration kind, the reason the producer rejected it, and the original source span. */
|
|
32
|
+
function normalizeCollision(value) {
|
|
33
|
+
if (!isRecord(value)) throw new Error('invalid dsh-ptc-plus diagnostic collision')
|
|
34
|
+
assertOwnFields(value, COLLISION_FIELDS, 'diagnostic collision')
|
|
35
|
+
if (!isLine(value.name) || !isLine(value.kind) || !isLine(value.reason)) {
|
|
36
|
+
throw new Error('invalid dsh-ptc-plus diagnostic collision')
|
|
37
|
+
}
|
|
38
|
+
return Object.freeze({
|
|
39
|
+
name: value.name,
|
|
40
|
+
kind: value.kind,
|
|
41
|
+
reason: value.reason,
|
|
42
|
+
start: normalizePosition(value.start, 'collision start'),
|
|
43
|
+
...(value.end === undefined ? {} : { end: normalizePosition(value.end, 'collision end') }),
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
29
47
|
function normalizeCause(value, depth) {
|
|
30
48
|
if (depth > 16) throw new Error('diagnostic cause chain is too deep')
|
|
31
49
|
if (!isRecord(value)) throw new Error('invalid diagnostic cause')
|
|
@@ -77,6 +95,13 @@ export function normalizeDiagnostic(value, depth = 0) {
|
|
|
77
95
|
}
|
|
78
96
|
let cause
|
|
79
97
|
if (value.cause !== undefined) cause = normalizeCause(value.cause, depth)
|
|
98
|
+
let collisions
|
|
99
|
+
if (value.collisions !== undefined) {
|
|
100
|
+
if (!Array.isArray(value.collisions) || value.collisions.length === 0) {
|
|
101
|
+
throw new Error('invalid dsh-ptc-plus diagnostic collisions')
|
|
102
|
+
}
|
|
103
|
+
collisions = Object.freeze(value.collisions.map(collision => normalizeCollision(collision)))
|
|
104
|
+
}
|
|
80
105
|
let help
|
|
81
106
|
if (value.help !== undefined) {
|
|
82
107
|
if (!Array.isArray(value.help) || value.help.length > 3
|
|
@@ -94,6 +119,7 @@ export function normalizeDiagnostic(value, depth = 0) {
|
|
|
94
119
|
...(value.dispatchState === undefined ? {} : { dispatchState: value.dispatchState }),
|
|
95
120
|
...(source === undefined ? {} : { source }),
|
|
96
121
|
...(cause === undefined ? {} : { cause }),
|
|
122
|
+
...(collisions === undefined ? {} : { collisions }),
|
|
97
123
|
...(help === undefined ? {} : { help }),
|
|
98
124
|
})
|
|
99
125
|
}
|
|
@@ -11,8 +11,10 @@ import {
|
|
|
11
11
|
generatedRunCodeExecutionArguments,
|
|
12
12
|
generatedRunCodeDescriptionMeta,
|
|
13
13
|
} from './run-code-description.js'
|
|
14
|
+
import { userBindingsConfiguredContext } from './user-bindings.js'
|
|
15
|
+
import { BINDING_AUTHORING_SDK } from './user-binding-authoring.js'
|
|
14
16
|
|
|
15
|
-
const RUN_CODE_TOOL_DESCRIPTION = 'Evaluate the next TypeScript cell in this session-bound persistent REPL
|
|
17
|
+
const RUN_CODE_TOOL_DESCRIPTION = 'Evaluate the next TypeScript cell in this session-bound persistent REPL, reusing earlier top-level bindings. Use `code` for the async-function body and `description` for its short UI summary. Successful image-bearing subtool results are attached after the cell.'
|
|
16
18
|
const RUN_CODE_CODE_DESCRIPTION = 'Code for the next REPL cell, parsed as the body of an async TypeScript function.'
|
|
17
19
|
const RUN_CODE_DESCRIPTION_DESCRIPTION = 'Short active-voice summary of what this cell does, 5-10 words (shown in the UI).'
|
|
18
20
|
const CODE_TRANSPORT_INSTRUCTION = '`run_code` and `edit_run_code` are the only tools callable directly. Call every native tool declared by the SDK from inside a program.'
|
|
@@ -42,11 +44,13 @@ function adaptRunCodeSchema(tool) {
|
|
|
42
44
|
}
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
function capabilitySdk(nativeSdk) {
|
|
47
|
+
function capabilitySdk(nativeSdk, userBindingsEnabled) {
|
|
46
48
|
return `${projectProgramSdk(nativeSdk)}
|
|
47
49
|
|
|
48
50
|
## PTC Plus program capabilities
|
|
49
51
|
|
|
52
|
+
Discover program APIs without calling them. \`tree()\` lists namespaces and members; \`inspect()\` describes selected \`namespace.member\` symbols. \`find()\` matches case-insensitive symbols or contiguous words, separating CamelCase and punctuation. Use short queries such as \`"read"\`; if none match, shorten the query or check \`tree()\`. Missing metadata is unknown.
|
|
53
|
+
|
|
50
54
|
\`\`\`ts
|
|
51
55
|
declare class CapabilityExplorationError extends Error { readonly operation: "tree" | "find" | "inspect" }
|
|
52
56
|
declare const capabilities: {
|
|
@@ -54,7 +58,7 @@ declare const capabilities: {
|
|
|
54
58
|
find(query: string): Promise<Array<{ symbol: string; description?: string; completeness: string; effect: string; replay: string }>>
|
|
55
59
|
inspect(args?: { symbols?: string[]; budget?: number }): Promise<{ symbols: unknown[]; omitted: number; unknown: string[]; budget: number }>
|
|
56
60
|
}
|
|
57
|
-
|
|
61
|
+
\`\`\`${userBindingsEnabled ? `\n${BINDING_AUTHORING_SDK}` : ''}`
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
function rejection(message) {
|
|
@@ -141,6 +145,8 @@ export function createDirectSurfaceOwner({
|
|
|
141
145
|
canonicalizeToolCalls,
|
|
142
146
|
sessionId,
|
|
143
147
|
toolSchemasForAgent,
|
|
148
|
+
userBindingsForAgent = async () => undefined,
|
|
149
|
+
setAgentPresentation = async () => {},
|
|
144
150
|
}) {
|
|
145
151
|
// Composition is anchored to Agent identity because DSH selects presentation
|
|
146
152
|
// once per composed agent. Request signals bind the exact assembly to stream
|
|
@@ -151,6 +157,7 @@ export function createDirectSurfaceOwner({
|
|
|
151
157
|
const canonicalRequests = new WeakMap()
|
|
152
158
|
const sessions = new Map()
|
|
153
159
|
const cordisRecovery = createCordisRecoveryPolicy(runtimeConfig.cordisToolsEnabled)
|
|
160
|
+
let disposed = false
|
|
154
161
|
let currentCanonicalizeToolCalls = canonicalizeToolCalls
|
|
155
162
|
let currentAutoDescribeRunCode = runtimeConfig.autoDescribeRunCode
|
|
156
163
|
const tipConfig = {
|
|
@@ -193,9 +200,31 @@ export function createDirectSurfaceOwner({
|
|
|
193
200
|
return undefined
|
|
194
201
|
}
|
|
195
202
|
|
|
196
|
-
|
|
203
|
+
// One dispatch resolves the policy captured for its exact call, then the
|
|
204
|
+
// request bound to its signal, then the session's latest request.
|
|
205
|
+
const dispatchPolicy = (exec) => {
|
|
206
|
+
const id = sessionId(exec.agent)
|
|
207
|
+
return executionPolicy(id, exec.callId) ?? requestPolicy(exec?.signal, id)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const rememberRequest = (
|
|
211
|
+
id,
|
|
212
|
+
signal,
|
|
213
|
+
presentation,
|
|
214
|
+
nativeSchemas,
|
|
215
|
+
autoDescribeRunCode,
|
|
216
|
+
userBindings,
|
|
217
|
+
contexts = [],
|
|
218
|
+
) => {
|
|
197
219
|
const owner = sessionOwner(id)
|
|
198
|
-
const request = {
|
|
220
|
+
const request = {
|
|
221
|
+
presentation,
|
|
222
|
+
nativeSchemas,
|
|
223
|
+
autoDescribeRunCode,
|
|
224
|
+
owner,
|
|
225
|
+
contexts,
|
|
226
|
+
...(userBindings === undefined ? {} : { userBindings }),
|
|
227
|
+
}
|
|
199
228
|
owner.latestRequest = request
|
|
200
229
|
if (signal !== undefined) canonicalRequests.set(signal, request)
|
|
201
230
|
}
|
|
@@ -228,6 +257,9 @@ export function createDirectSurfaceOwner({
|
|
|
228
257
|
const autoDescribeRunCode = currentAutoDescribeRunCode
|
|
229
258
|
const agent = context?.agent
|
|
230
259
|
const id = sessionId(agent)
|
|
260
|
+
const requestOwner = id === undefined ? undefined : sessionOwner(id)
|
|
261
|
+
const isCurrent = () => !disposed && (requestOwner === undefined
|
|
262
|
+
|| (requestOwner.active && sessions.get(id) === requestOwner))
|
|
231
263
|
const initialState = presentationState(initialAssembly)
|
|
232
264
|
let composition = compositions.get(agent)
|
|
233
265
|
if (composition === undefined && id !== undefined
|
|
@@ -239,6 +271,7 @@ export function createDirectSurfaceOwner({
|
|
|
239
271
|
}
|
|
240
272
|
|
|
241
273
|
const assembly = await next()
|
|
274
|
+
if (!isCurrent()) return assembly
|
|
242
275
|
const tools = assembly.tools
|
|
243
276
|
if (!Array.isArray(tools)) {
|
|
244
277
|
throw new Error('ptc-plus: incompatible prompt assembly; expected a tools array')
|
|
@@ -260,16 +293,22 @@ export function createDirectSurfaceOwner({
|
|
|
260
293
|
if (presentation !== 'native') {
|
|
261
294
|
throw new Error(`ptc-plus: ${presentation} agent composition assembled without run_code`)
|
|
262
295
|
}
|
|
296
|
+
await setAgentPresentation(agent, presentation)
|
|
297
|
+
if (!isCurrent()) return assembly
|
|
263
298
|
if (id !== undefined) {
|
|
264
|
-
rememberRequest(id, requestSignal, 'native', new Map(), autoDescribeRunCode)
|
|
299
|
+
rememberRequest(id, requestSignal, 'native', new Map(), autoDescribeRunCode, undefined)
|
|
265
300
|
}
|
|
266
301
|
return assembly
|
|
267
302
|
}
|
|
268
303
|
if (presentation === 'native') {
|
|
269
304
|
throw new Error('ptc-plus: native agent composition assembled with run_code')
|
|
270
305
|
}
|
|
306
|
+
await setAgentPresentation(agent, presentation)
|
|
307
|
+
if (!isCurrent()) return assembly
|
|
271
308
|
const sessionPtc = presentation !== 'native' && id !== undefined
|
|
272
309
|
const sessionPtcProjection = presentation === 'ptc' && id !== undefined
|
|
310
|
+
const userBindings = sessionPtc ? await userBindingsForAgent(agent) : undefined
|
|
311
|
+
if (!isCurrent()) return assembly
|
|
273
312
|
const runCode = tools.find(tool => tool?.name === RUN_CODE)
|
|
274
313
|
let directTools = tools
|
|
275
314
|
if (sessionPtcProjection) {
|
|
@@ -283,17 +322,18 @@ export function createDirectSurfaceOwner({
|
|
|
283
322
|
},
|
|
284
323
|
})
|
|
285
324
|
: { contexts: [] }
|
|
286
|
-
const
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
:
|
|
325
|
+
const bindingDefaults = userBindings === undefined ? undefined : userBindingsConfiguredContext(userBindings)
|
|
326
|
+
const contexts = [
|
|
327
|
+
...runtimeContexts.contexts,
|
|
328
|
+
...(bindingDefaults === undefined ? [] : [bindingDefaults]),
|
|
329
|
+
]
|
|
290
330
|
const projectsSections = presentation !== 'native' && Array.isArray(assembly.sections)
|
|
291
331
|
&& assembly.sections.some(section => section?.name === 'tools:sdk'
|
|
292
332
|
|| (sessionPtcProjection && section?.name === completedState.collapseSectionName))
|
|
293
333
|
const sections = projectsSections
|
|
294
334
|
? assembly.sections.map(section => {
|
|
295
335
|
if (section?.name === 'tools:sdk') {
|
|
296
|
-
return { ...section, text: capabilitySdk(section.text) }
|
|
336
|
+
return { ...section, text: capabilitySdk(section.text, userBindings !== undefined) }
|
|
297
337
|
}
|
|
298
338
|
if (sessionPtcProjection && section?.name === completedState.collapseSectionName) {
|
|
299
339
|
return { ...section, text: CODE_TRANSPORT_INSTRUCTION }
|
|
@@ -301,7 +341,6 @@ export function createDirectSurfaceOwner({
|
|
|
301
341
|
return section
|
|
302
342
|
})
|
|
303
343
|
: assembly.sections
|
|
304
|
-
|
|
305
344
|
if (id !== undefined) {
|
|
306
345
|
const nativeSchemas = presentation === 'ptc'
|
|
307
346
|
? new Map(toolSchemasForAgent(agent)
|
|
@@ -309,7 +348,15 @@ export function createDirectSurfaceOwner({
|
|
|
309
348
|
&& schema.name !== RUN_CODE && schema.name !== EDIT_RUN_CODE)
|
|
310
349
|
.map(schema => [schema.name, schema]))
|
|
311
350
|
: new Map()
|
|
312
|
-
rememberRequest(
|
|
351
|
+
rememberRequest(
|
|
352
|
+
id,
|
|
353
|
+
requestSignal,
|
|
354
|
+
presentation,
|
|
355
|
+
nativeSchemas,
|
|
356
|
+
autoDescribeRunCode,
|
|
357
|
+
userBindings,
|
|
358
|
+
contexts,
|
|
359
|
+
)
|
|
313
360
|
}
|
|
314
361
|
|
|
315
362
|
return {
|
|
@@ -320,9 +367,11 @@ export function createDirectSurfaceOwner({
|
|
|
320
367
|
? adaptRunCodeSchema(tool)
|
|
321
368
|
: tool),
|
|
322
369
|
sections,
|
|
323
|
-
contexts,
|
|
324
370
|
}
|
|
325
371
|
},
|
|
372
|
+
contextsForRequest(context) {
|
|
373
|
+
return requestPolicy(context.signal, sessionId(context.agent))?.contexts ?? []
|
|
374
|
+
},
|
|
326
375
|
stream(options, next) {
|
|
327
376
|
const optionSessionId = options.sessionId === undefined ? undefined : String(options.sessionId)
|
|
328
377
|
const policy = requestPolicy(options?.signal, optionSessionId)
|
|
@@ -340,9 +389,7 @@ export function createDirectSurfaceOwner({
|
|
|
340
389
|
if (exec.name === EDIT_RUN_CODE && exec.parent !== undefined) {
|
|
341
390
|
return rejection(`tool ${EDIT_RUN_CODE} is only callable directly in PTC mode; call native tools from inside run_code`)
|
|
342
391
|
}
|
|
343
|
-
const
|
|
344
|
-
const policy = executionPolicy(id, exec.callId)
|
|
345
|
-
?? requestPolicy(exec?.signal, id)
|
|
392
|
+
const policy = dispatchPolicy(exec)
|
|
346
393
|
if (exec.name === EDIT_RUN_CODE) {
|
|
347
394
|
return policy?.presentation === 'ptc'
|
|
348
395
|
? undefined
|
|
@@ -355,9 +402,7 @@ export function createDirectSurfaceOwner({
|
|
|
355
402
|
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`)
|
|
356
403
|
},
|
|
357
404
|
executionArguments(exec) {
|
|
358
|
-
const
|
|
359
|
-
const policy = executionPolicy(id, exec.callId)
|
|
360
|
-
?? requestPolicy(exec?.signal, id)
|
|
405
|
+
const policy = dispatchPolicy(exec)
|
|
361
406
|
const originalArguments = exec.arguments
|
|
362
407
|
if (exec.name !== RUN_CODE || exec.parent !== undefined
|
|
363
408
|
|| policy?.autoDescribeRunCode !== true || policy.presentation === 'native'
|
|
@@ -367,6 +412,10 @@ export function createDirectSurfaceOwner({
|
|
|
367
412
|
}
|
|
368
413
|
return generatedRunCodeExecutionArguments(originalArguments)
|
|
369
414
|
},
|
|
415
|
+
executionUserBindings(exec) {
|
|
416
|
+
const policy = dispatchPolicy(exec)
|
|
417
|
+
return policy?.presentation === 'native' ? undefined : policy?.userBindings
|
|
418
|
+
},
|
|
370
419
|
argumentDiagnostic(exec, result) {
|
|
371
420
|
// DSH uses success-result identity to avoid re-running output projectors
|
|
372
421
|
// after this middleware's settlement scope has ended.
|
|
@@ -377,9 +426,7 @@ export function createDirectSurfaceOwner({
|
|
|
377
426
|
: { ...result, ...(meta === undefined ? {} : { meta }) }
|
|
378
427
|
const missingPath = missingDescriptionPath(diagnosed.error)
|
|
379
428
|
if (missingPath === undefined) return diagnosed
|
|
380
|
-
const
|
|
381
|
-
const policy = executionPolicy(id, exec.callId)
|
|
382
|
-
?? requestPolicy(exec?.signal, id)
|
|
429
|
+
const policy = dispatchPolicy(exec)
|
|
383
430
|
const outer = missingPath === 'description'
|
|
384
431
|
&& policy?.autoDescribeRunCode !== true
|
|
385
432
|
&& !(isRecord(exec.arguments) && typeof exec.arguments.description === 'string')
|
|
@@ -410,7 +457,13 @@ export function createDirectSurfaceOwner({
|
|
|
410
457
|
clearCompositionsForSession(id)
|
|
411
458
|
clearSession(id)
|
|
412
459
|
},
|
|
460
|
+
resetSessionComposition(session) {
|
|
461
|
+
const id = String(session.id ?? session)
|
|
462
|
+
clearCompositionsForSession(id)
|
|
463
|
+
clearSession(id)
|
|
464
|
+
},
|
|
413
465
|
dispose() {
|
|
466
|
+
disposed = true
|
|
414
467
|
compositions.clear()
|
|
415
468
|
for (const owner of sessions.values()) owner.active = false
|
|
416
469
|
sessions.clear()
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { parseExpression } from '@babel/parser'
|
|
2
|
+
|
|
3
|
+
/** Dynamic names require both a native identifier and their exact source origin. */
|
|
4
|
+
export function dynamicBindingOrigin(target, name, origins) {
|
|
5
|
+
if (typeof target !== 'string' || typeof name !== 'string') return undefined
|
|
6
|
+
const suffix = `:${JSON.stringify(name)}`
|
|
7
|
+
if (!target.endsWith(suffix)) return undefined
|
|
8
|
+
const origin = target.slice(0, -suffix.length)
|
|
9
|
+
if (!origins.has(origin)) return undefined
|
|
10
|
+
try {
|
|
11
|
+
const identifier = parseExpression(name)
|
|
12
|
+
return identifier.type === 'Identifier' && identifier.name === name ? origin : undefined
|
|
13
|
+
} catch {
|
|
14
|
+
return undefined
|
|
15
|
+
}
|
|
16
|
+
}
|