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
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { types } from 'node:util'
|
|
2
|
+
import { isContext, runInContext, runInThisContext } from 'node:vm'
|
|
3
|
+
import { parse } from 'acorn'
|
|
4
|
+
import { randomUUID } from 'node:crypto'
|
|
5
|
+
import { walkAst, SKIP_AST_CHILDREN } from './ast-traversal.js'
|
|
6
|
+
import { bindingNodes } from './binding-pattern-traversal.js'
|
|
7
|
+
|
|
8
|
+
const MAX_ENTRIES = 128
|
|
9
|
+
const MAX_TEXT = 512
|
|
10
|
+
const MAX_PROPERTIES = 5
|
|
11
|
+
const ownDescriptor = Object.getOwnPropertyDescriptor
|
|
12
|
+
const isArray = Array.isArray
|
|
13
|
+
const isProxy = types.isProxy
|
|
14
|
+
const stringify = JSON.stringify
|
|
15
|
+
const now = Date.now
|
|
16
|
+
const bigintText = BigInt.prototype.toString
|
|
17
|
+
const BIGINT_LIMIT = 10n ** 128n
|
|
18
|
+
const unreadable = () => ({ status: 'unreadable', text: '', truncated: false })
|
|
19
|
+
const runInRealm = (source, context, options) => isContext(context)
|
|
20
|
+
? runInContext(source, context, options)
|
|
21
|
+
: runInThisContext(source, options)
|
|
22
|
+
|
|
23
|
+
function primitiveText(value) {
|
|
24
|
+
if (typeof value === 'string') return stringify(value.slice(0, MAX_TEXT))
|
|
25
|
+
if (typeof value === 'bigint') return value > -BIGINT_LIMIT && value < BIGINT_LIMIT
|
|
26
|
+
? `${bigintText.call(value)}n` : '[bigint: more than 128 digits]'
|
|
27
|
+
if (typeof value === 'symbol' || typeof value === 'function') return `[${typeof value}: unreadable]`
|
|
28
|
+
if (value === null) return 'null'
|
|
29
|
+
if (typeof value === 'object') return isProxy(value) ? '[proxy: unreadable]' : '[object]'
|
|
30
|
+
return Object.is(value, -0) ? '-0' : String(value)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/** Inspect own descriptors only, rejecting proxies before any reflective operation. */
|
|
34
|
+
export function previewBindingValue(value) {
|
|
35
|
+
if (['function', 'symbol'].includes(typeof value)) return unreadable()
|
|
36
|
+
if (value === null || typeof value !== 'object') {
|
|
37
|
+
const text = primitiveText(value)
|
|
38
|
+
return { status: 'readable', text: text.slice(0, MAX_TEXT), truncated: text.length > MAX_TEXT
|
|
39
|
+
|| (typeof value === 'bigint' && (value <= -BIGINT_LIMIT || value >= BIGINT_LIMIT)) }
|
|
40
|
+
}
|
|
41
|
+
// Only arrays provide a finite slot range without enumerating the whole object.
|
|
42
|
+
if (isProxy(value) || !isArray(value)) return unreadable()
|
|
43
|
+
const keys = Array.from({ length: Math.min(ownDescriptor(value, 'length').value, MAX_PROPERTIES) }, (_value, index) => String(index))
|
|
44
|
+
const properties = keys.map(key => {
|
|
45
|
+
const descriptor = ownDescriptor(value, key)
|
|
46
|
+
const text = descriptor === undefined ? '[empty]'
|
|
47
|
+
: Object.hasOwn(descriptor, 'value') ? primitiveText(descriptor.value) : '[accessor: unreadable]'
|
|
48
|
+
return `${stringify(key)}: ${text}`
|
|
49
|
+
})
|
|
50
|
+
const text = `array { ${properties.join(', ')} }`
|
|
51
|
+
// Uninspected own properties remain unknown even when all indexed slots fit.
|
|
52
|
+
return { status: 'readable', text: text.slice(0, MAX_TEXT), truncated: true }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Probe the actual evaluator without consulting a Node version or any session value. */
|
|
56
|
+
export async function supportsAwaitLexicals(context, evaluate) {
|
|
57
|
+
const prefix = `__ptc_observation_${randomUUID().replaceAll('-', '')}`
|
|
58
|
+
const names = [`${prefix}_let`, `${prefix}_const`]
|
|
59
|
+
try {
|
|
60
|
+
await evaluate(`let ${names[0]} = await Promise.resolve(41); const ${names[1]} = 42;`)
|
|
61
|
+
return names.every((name, index) => ownDescriptor(context, name) === undefined
|
|
62
|
+
&& runInRealm(name, context, { timeout: 25 }) === index + 41)
|
|
63
|
+
} catch {
|
|
64
|
+
return false
|
|
65
|
+
} finally {
|
|
66
|
+
// Lexical probe names are private and never enter the binding inventory.
|
|
67
|
+
for (const name of names) delete context[name]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/** Successful programs prove storage; await lexical reads additionally require a runtime probe. */
|
|
72
|
+
export function createReplValueObserver(context, { awaitLexicals = false } = {}) {
|
|
73
|
+
const lexicals = new Set()
|
|
74
|
+
const globals = new Set()
|
|
75
|
+
return {
|
|
76
|
+
record(program) {
|
|
77
|
+
try {
|
|
78
|
+
const tree = parse(program, { ecmaVersion: 'latest', allowAwaitOutsideFunction: true })
|
|
79
|
+
let awaits = false
|
|
80
|
+
walkAst(tree, node => {
|
|
81
|
+
if (['FunctionDeclaration', 'FunctionExpression', 'ArrowFunctionExpression'].includes(node.type)) return SKIP_AST_CHILDREN
|
|
82
|
+
if (node.type === 'AwaitExpression' || node.await === true) awaits = true
|
|
83
|
+
})
|
|
84
|
+
if (awaits && !awaitLexicals) return
|
|
85
|
+
for (const statement of tree.body) {
|
|
86
|
+
if (statement.type !== 'VariableDeclaration') continue
|
|
87
|
+
for (const declaration of statement.declarations) {
|
|
88
|
+
for (const binding of bindingNodes(declaration.id)) {
|
|
89
|
+
(statement.kind === 'var' ? globals : lexicals).add(binding.name)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
} catch {}
|
|
94
|
+
},
|
|
95
|
+
observe(names) {
|
|
96
|
+
const at = now()
|
|
97
|
+
const entries = names.slice(0, MAX_ENTRIES).map(name => {
|
|
98
|
+
let preview = unreadable()
|
|
99
|
+
try {
|
|
100
|
+
if (lexicals.has(name)) {
|
|
101
|
+
// Lexical storage shadows global properties, even while uninitialized.
|
|
102
|
+
if (/^[$_\p{ID_Start}][$\u200c\u200d\p{ID_Continue}]*$/u.test(name) && now() - at < 100) {
|
|
103
|
+
preview = previewBindingValue(runInRealm(name, context, { timeout: 25, displayErrors: false }))
|
|
104
|
+
}
|
|
105
|
+
} else if (globals.has(name)) {
|
|
106
|
+
const descriptor = ownDescriptor(context, name)
|
|
107
|
+
if (descriptor !== undefined && Object.hasOwn(descriptor, 'value')) {
|
|
108
|
+
preview = previewBindingValue(descriptor.value)
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
} catch {}
|
|
112
|
+
return { name, ...preview }
|
|
113
|
+
})
|
|
114
|
+
return { at, entries }
|
|
115
|
+
},
|
|
116
|
+
}
|
|
117
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import Schema from '@deepseek-ai/schemastery'
|
|
2
|
+
import { strictCodec } from './typert-codec-compat.js'
|
|
3
|
+
|
|
4
|
+
const resultSchema = Schema.union([
|
|
5
|
+
Schema.object({ ok: Schema.const(true).required(), value: Schema.any() }),
|
|
6
|
+
Schema.object({
|
|
7
|
+
ok: Schema.const(false).required(),
|
|
8
|
+
error: Schema.object({
|
|
9
|
+
code: Schema.string().required(),
|
|
10
|
+
message: Schema.string().required(),
|
|
11
|
+
details: Schema.any().required(),
|
|
12
|
+
}).required(),
|
|
13
|
+
}),
|
|
14
|
+
]).required()
|
|
15
|
+
|
|
16
|
+
/** Shared executable wire definitions; business payload validation stays with each owner. */
|
|
17
|
+
export const RPC_CONTRACTS = Object.freeze({
|
|
18
|
+
bindings: Object.freeze({ service: 'ptcPlusBindings' }),
|
|
19
|
+
repl: Object.freeze({ service: 'ptcPlusRepl' }),
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
export function rpcDescriptor({ service }) {
|
|
23
|
+
return {
|
|
24
|
+
id: `dsh-ptc-plus#${service}/invoke`,
|
|
25
|
+
service,
|
|
26
|
+
namespace: service,
|
|
27
|
+
method: 'invoke',
|
|
28
|
+
invocation: { kind: 'direct' },
|
|
29
|
+
parameters: [
|
|
30
|
+
{ name: 'operation', wire: 'operation', source: 'json',
|
|
31
|
+
codec: strictCodec({
|
|
32
|
+
typeSymbol: 'dsh-ptc-plus#RpcOperation',
|
|
33
|
+
schema: Schema.string().required(),
|
|
34
|
+
}) },
|
|
35
|
+
{ name: 'payload', wire: 'payload', source: 'json',
|
|
36
|
+
codec: strictCodec({
|
|
37
|
+
typeSymbol: 'dsh-ptc-plus#RpcPayload',
|
|
38
|
+
schema: Schema.any(),
|
|
39
|
+
}) },
|
|
40
|
+
],
|
|
41
|
+
cancellation: { parameter: 'signal' },
|
|
42
|
+
result: strictCodec({
|
|
43
|
+
typeSymbol: 'dsh-ptc-plus#RpcResult',
|
|
44
|
+
schema: resultSchema,
|
|
45
|
+
}),
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const RPC_REMOTE = Object.freeze({
|
|
50
|
+
package: 'dsh-ptc-plus',
|
|
51
|
+
descriptors: Object.values(RPC_CONTRACTS).map(rpcDescriptor),
|
|
52
|
+
})
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
/** Own the
|
|
1
|
+
/** Own the execution-seam takeover, per-cell lease, journal projection, and session settlement. */
|
|
2
2
|
import { AsyncLocalStorage } from 'node:async_hooks'
|
|
3
|
+
import { executionPolicies } from './binding-update-policy.js'
|
|
3
4
|
import { assertObjectJsonSchema, validateJsonSchemaValue } from '@deepseek-ai/dsh-tools'
|
|
4
5
|
import { normalizeBindingDescriptors } from './binding-descriptors.js'
|
|
5
6
|
import { SessionRuntime } from './session-runtime.js'
|
|
@@ -20,7 +21,14 @@ import {
|
|
|
20
21
|
} from './program-bindings.js'
|
|
21
22
|
import { deepFreeze } from './record-utils.js'
|
|
22
23
|
import { withReplMemorySnapshot } from './repl-memory-projection.js'
|
|
24
|
+
import { withUserBindingDraftCapability } from './user-binding-draft-projection.js'
|
|
23
25
|
import { generatedRunCodeDescriptionMeta } from './run-code-description.js'
|
|
26
|
+
import { BINDING_SUBMISSION } from './user-binding-authoring.js'
|
|
27
|
+
import {
|
|
28
|
+
USER_BINDINGS_META_KEY,
|
|
29
|
+
userBindingsSnapshotsEqual,
|
|
30
|
+
withUserBindingsSnapshot,
|
|
31
|
+
} from './user-bindings.js'
|
|
24
32
|
|
|
25
33
|
export const RUN_CODE = 'run_code'
|
|
26
34
|
|
|
@@ -63,12 +71,12 @@ const PROGRAM_CAPABILITY_METADATA = deepFreeze([
|
|
|
63
71
|
namespace: 'repl',
|
|
64
72
|
members: [{
|
|
65
73
|
name: 'state',
|
|
66
|
-
description: '
|
|
74
|
+
description: 'Manage named REPL checkpoints. list returns checkpoint names, not variable names. Save captures the final durable state of this cell, including subsequent mutations; it is lost if the cell becomes volatile or is discarded. Save, restore and delete take effect after cell settlement and journal confirmation, not when the receipt is awaited. Restore changes bindings for subsequent cells and does not undo external effects.',
|
|
67
75
|
parameters: {
|
|
68
76
|
type: 'object',
|
|
69
77
|
properties: {
|
|
70
|
-
action: { enum: ['list', 'save', 'restore', 'delete'] },
|
|
71
|
-
name: { type: 'string' },
|
|
78
|
+
action: { enum: ['list', 'save', 'restore', 'delete'], description: 'list reads the current cell control view, including tentative names; mutations are accepted for settlement.' },
|
|
79
|
+
name: { type: 'string', description: 'Required for save/delete; omit for restore to select the durable head.' },
|
|
72
80
|
},
|
|
73
81
|
oneOf: [
|
|
74
82
|
{ required: ['action'], properties: { action: { const: 'list' } } },
|
|
@@ -77,7 +85,19 @@ const PROGRAM_CAPABILITY_METADATA = deepFreeze([
|
|
|
77
85
|
{ required: ['action', 'name'], properties: { action: { const: 'delete' } } },
|
|
78
86
|
],
|
|
79
87
|
},
|
|
80
|
-
returns: {
|
|
88
|
+
returns: {
|
|
89
|
+
type: 'object',
|
|
90
|
+
properties: {
|
|
91
|
+
action: { enum: ['save', 'restore', 'delete'] },
|
|
92
|
+
name: { type: 'string' },
|
|
93
|
+
saved: { const: true, description: 'Save accepted for the final durable cell boundary, subject to settlement and confirmation.' },
|
|
94
|
+
restored: { const: true, description: 'Restore accepted; use a later cell to compute from restored bindings.' },
|
|
95
|
+
deleted: { const: true, description: 'Deletion accepted for settlement; removes the checkpoint name, not external effects.' },
|
|
96
|
+
names: { type: 'array', items: { type: 'string' }, description: 'Sorted checkpoint names in the current cell control view, including tentative operations.' },
|
|
97
|
+
mode: { enum: ['durable', 'volatile'] },
|
|
98
|
+
volatileReason: { type: 'string' },
|
|
99
|
+
},
|
|
100
|
+
},
|
|
81
101
|
effect: 'ptc-state',
|
|
82
102
|
authority: 'ptc-plus-program-binding',
|
|
83
103
|
completeness: 'complete',
|
|
@@ -123,26 +143,71 @@ const PROGRAM_CAPABILITY_METADATA = deepFreeze([
|
|
|
123
143
|
|
|
124
144
|
export function createRuntimeBridgeOwner({
|
|
125
145
|
ctx,
|
|
146
|
+
seam,
|
|
126
147
|
sessionConfig,
|
|
148
|
+
userBindingsCwd,
|
|
149
|
+
observeSession,
|
|
127
150
|
maxNestedRunCodeDepth,
|
|
128
151
|
presentationGeneration,
|
|
129
152
|
sessionId,
|
|
130
153
|
toolSchemasForAgent,
|
|
154
|
+
userBindingDraftForAgent,
|
|
155
|
+
bindingSubmissionForAgent,
|
|
131
156
|
}) {
|
|
132
157
|
const scope = new AsyncLocalStorage()
|
|
158
|
+
const childScope = new AsyncLocalStorage()
|
|
159
|
+
const childRuntimes = new Set()
|
|
160
|
+
const childDisposals = new WeakMap()
|
|
161
|
+
const childFinalizers = new WeakSet()
|
|
162
|
+
const disposeChildRuntime = (child) => {
|
|
163
|
+
let disposal = childDisposals.get(child)
|
|
164
|
+
if (disposal === undefined) {
|
|
165
|
+
disposal = child.dispose()
|
|
166
|
+
childDisposals.set(child, disposal)
|
|
167
|
+
}
|
|
168
|
+
return disposal
|
|
169
|
+
}
|
|
133
170
|
// AgentRegistry.withInitiator is AsyncLocalStorage-based. The arrow preserves
|
|
134
171
|
// its receiver when a worker callback re-enters the host tool pipeline.
|
|
135
172
|
const withInitiator = ctx.agents === undefined || typeof ctx.agents.withInitiator !== 'function'
|
|
136
173
|
? undefined
|
|
137
174
|
: (agent, operation) => ctx.agents.withInitiator(agent, operation)
|
|
138
|
-
const sessions = new SessionRuntime(sessionConfig, { withInitiator })
|
|
175
|
+
const sessions = new SessionRuntime(sessionConfig, { withInitiator, userBindingsCwd, observeSession })
|
|
139
176
|
let currentConfig = sessions.config
|
|
140
|
-
const runtime = ctx.codeRuntime
|
|
141
|
-
const ownRun = Object.getOwnPropertyDescriptor(runtime, 'run')
|
|
142
|
-
const upstreamRun = runtime.run
|
|
143
177
|
const patchedDefinitions = new Map()
|
|
144
178
|
const pending = new WeakMap()
|
|
179
|
+
const nativeRunCodeHandoffs = new Set()
|
|
145
180
|
let active = true
|
|
181
|
+
const runIsolated = async (request, executionToken, depth, cellConfig, inheritedTools) => {
|
|
182
|
+
const child = new SessionRuntime({ ...cellConfig, durableReplay: false, userBindingsEnabled: false,
|
|
183
|
+
replViewEnabled: false }, { withInitiator, userBindingsCwd })
|
|
184
|
+
childRuntimes.add(child)
|
|
185
|
+
const projected = projectBindings(request, depth, executionToken, inheritedTools, cellConfig)
|
|
186
|
+
childFinalizers.add(child)
|
|
187
|
+
try {
|
|
188
|
+
return await child.run({ id: 'isolated-cell', session: { header: {
|
|
189
|
+
cwd: executionToken?.session?.header?.cwd,
|
|
190
|
+
} } }, { ...projected.request, executionToken })
|
|
191
|
+
} finally {
|
|
192
|
+
projected.release()
|
|
193
|
+
try {
|
|
194
|
+
await disposeChildRuntime(child)
|
|
195
|
+
childRuntimes.delete(child)
|
|
196
|
+
} finally {
|
|
197
|
+
childDisposals.delete(child)
|
|
198
|
+
childFinalizers.delete(child)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const withDraftCapability = (meta, current) => currentConfig.userBindingsEnabled !== true
|
|
203
|
+
|| typeof userBindingDraftForAgent !== 'function'
|
|
204
|
+
? meta
|
|
205
|
+
: withUserBindingDraftCapability(
|
|
206
|
+
meta,
|
|
207
|
+
userBindingDraftForAgent(current.agent),
|
|
208
|
+
presentationGeneration,
|
|
209
|
+
current.bindingCandidate ?? null,
|
|
210
|
+
)
|
|
146
211
|
|
|
147
212
|
const projectBindings = (
|
|
148
213
|
request,
|
|
@@ -165,7 +230,7 @@ export function createRuntimeBridgeOwner({
|
|
|
165
230
|
toolsNamespace === undefined ? Object.create(null) : toolsNamespace.functions
|
|
166
231
|
)
|
|
167
232
|
const ensureLease = () => {
|
|
168
|
-
if (!lease.active) throw new Error('PTC execution lease expired')
|
|
233
|
+
if (!active || !lease.active) throw new Error('PTC execution lease expired')
|
|
169
234
|
}
|
|
170
235
|
const runCode = async (value) => {
|
|
171
236
|
ensureLease()
|
|
@@ -173,13 +238,42 @@ export function createRuntimeBridgeOwner({
|
|
|
173
238
|
if (depth >= cellConfig.maxNestedRunCodeDepth) {
|
|
174
239
|
throw new RangeError(`code.run recursion depth exceeds configured maximum ${cellConfig.maxNestedRunCodeDepth}`)
|
|
175
240
|
}
|
|
176
|
-
|
|
241
|
+
const languageSemantics = executionPolicies(cellConfig).languageSemantics
|
|
242
|
+
const nativeRunCode = functions[RUN_CODE]
|
|
243
|
+
if (typeof nativeRunCode === 'function') {
|
|
244
|
+
ensureLease()
|
|
245
|
+
let settleHandoff
|
|
246
|
+
const handoff = {
|
|
247
|
+
active: true,
|
|
248
|
+
executionToken,
|
|
249
|
+
depth: depth + 1,
|
|
250
|
+
cellConfig,
|
|
251
|
+
functions,
|
|
252
|
+
settled: new Promise(resolve => { settleHandoff = resolve }),
|
|
253
|
+
}
|
|
254
|
+
nativeRunCodeHandoffs.add(handoff)
|
|
255
|
+
try {
|
|
256
|
+
return await childScope.run(handoff, () => nativeRunCode.call(functions, args))
|
|
257
|
+
} finally {
|
|
258
|
+
handoff.active = false
|
|
259
|
+
nativeRunCodeHandoffs.delete(handoff)
|
|
260
|
+
settleHandoff()
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (languageSemantics !== 'legacy-v1') {
|
|
264
|
+
const child = await runIsolated({ ...request, program: args.code }, executionToken,
|
|
265
|
+
depth + 1, cellConfig, functions)
|
|
266
|
+
if (child.error !== undefined) {
|
|
267
|
+
throw new Error(`nested run_code failed (${child.error.kind}): ${child.error.message}`)
|
|
268
|
+
}
|
|
269
|
+
return { logs: child.logs, ...(child.value === undefined ? {} : { result: child.value }) }
|
|
270
|
+
}
|
|
177
271
|
const childProjected = projectBindings(
|
|
178
272
|
{ ...request, program: args.code }, depth + 1, executionToken, functions, cellConfig,
|
|
179
273
|
)
|
|
180
274
|
let child
|
|
181
275
|
try {
|
|
182
|
-
child = await
|
|
276
|
+
child = await seam.invokeUpstream(childProjected.request)
|
|
183
277
|
} finally {
|
|
184
278
|
childProjected.release()
|
|
185
279
|
}
|
|
@@ -224,7 +318,10 @@ export function createRuntimeBridgeOwner({
|
|
|
224
318
|
)))
|
|
225
319
|
const metadata = Object.freeze([
|
|
226
320
|
...toolCapabilityMetadata(schemas, annotations),
|
|
227
|
-
...PROGRAM_CAPABILITY_METADATA
|
|
321
|
+
...PROGRAM_CAPABILITY_METADATA.map(entry => entry.namespace === 'code'
|
|
322
|
+
&& cellConfig.userBindingsEnabled === true
|
|
323
|
+
? { ...entry, members: [...entry.members, BINDING_SUBMISSION] }
|
|
324
|
+
: entry),
|
|
228
325
|
])
|
|
229
326
|
projected.push(namespace('capabilities', {
|
|
230
327
|
tree: async value => {
|
|
@@ -246,7 +343,14 @@ export function createRuntimeBridgeOwner({
|
|
|
246
343
|
return capabilityInspect(metadata, value.symbols, value.budget)
|
|
247
344
|
},
|
|
248
345
|
}, 'CapabilityExplorationError', 'operation'))
|
|
249
|
-
projected.push(namespace('code', {
|
|
346
|
+
projected.push(namespace('code', {
|
|
347
|
+
run: runCode,
|
|
348
|
+
...(cellConfig.userBindingsEnabled === true ? {
|
|
349
|
+
submitBindingDraft: bindingSubmissionForAgent(executionToken?.agent, ensureLease, candidate => {
|
|
350
|
+
executionToken.bindingCandidate = candidate
|
|
351
|
+
}),
|
|
352
|
+
} : {}),
|
|
353
|
+
}, 'CodeExecutionError', 'operation'))
|
|
250
354
|
return { request: { ...request, bindings: projected }, release }
|
|
251
355
|
}
|
|
252
356
|
|
|
@@ -278,8 +382,12 @@ export function createRuntimeBridgeOwner({
|
|
|
278
382
|
meta = withRecoveryBoundaries(meta, settlement.recoveryBoundaries)
|
|
279
383
|
}
|
|
280
384
|
if (settlement.rewrites !== undefined) meta = withRewrites(meta, settlement.rewrites)
|
|
385
|
+
if (settlement.userBindings !== undefined) {
|
|
386
|
+
meta = withUserBindingsSnapshot(meta, settlement.userBindings)
|
|
387
|
+
}
|
|
281
388
|
meta = generatedRunCodeDescriptionMeta(args, meta)
|
|
282
|
-
|
|
389
|
+
meta = withReplMemorySnapshot(meta, settlement.replMemory, presentationGeneration)
|
|
390
|
+
return withDraftCapability(meta, current)
|
|
283
391
|
}
|
|
284
392
|
const ownExecute = Object.getOwnPropertyDescriptor(definition, 'execute')
|
|
285
393
|
const originalExecute = definition.execute
|
|
@@ -324,11 +432,22 @@ export function createRuntimeBridgeOwner({
|
|
|
324
432
|
}
|
|
325
433
|
|
|
326
434
|
const patchedRun = function (request) {
|
|
327
|
-
|
|
435
|
+
const child = childScope.getStore()
|
|
436
|
+
if (child !== undefined) {
|
|
437
|
+
if (!active || !child.active) return Promise.reject(new Error('PTC execution lease expired'))
|
|
438
|
+
if (executionPolicies(child.cellConfig).languageSemantics !== 'legacy-v1') {
|
|
439
|
+
return runIsolated(request, child.executionToken, child.depth, child.cellConfig, child.functions)
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
if (!active) return seam.invokeUpstream(request)
|
|
328
443
|
const current = scope.getStore()
|
|
329
|
-
if (current === undefined) return
|
|
444
|
+
if (current === undefined) return seam.invokeUpstream(request)
|
|
330
445
|
const projected = projectBindings(request, 0, current)
|
|
331
|
-
return sessions.runTentative(current, {
|
|
446
|
+
return sessions.runTentative(current, {
|
|
447
|
+
...projected.request,
|
|
448
|
+
executionToken: current,
|
|
449
|
+
...(current.userBindings === undefined ? {} : { userBindings: current.userBindings }),
|
|
450
|
+
})
|
|
332
451
|
.then((execution) => {
|
|
333
452
|
current.settlement = execution.settlement
|
|
334
453
|
return execution.result
|
|
@@ -336,11 +455,7 @@ export function createRuntimeBridgeOwner({
|
|
|
336
455
|
.finally(projected.release)
|
|
337
456
|
}
|
|
338
457
|
|
|
339
|
-
|
|
340
|
-
configurable: true,
|
|
341
|
-
writable: true,
|
|
342
|
-
value: patchedRun,
|
|
343
|
-
})
|
|
458
|
+
const releaseSeam = seam.takeOver(patchedRun)
|
|
344
459
|
|
|
345
460
|
return Object.freeze({
|
|
346
461
|
config: sessions.config,
|
|
@@ -348,6 +463,7 @@ export function createRuntimeBridgeOwner({
|
|
|
348
463
|
sessions.reconfigure(nextConfig)
|
|
349
464
|
currentConfig = sessions.config
|
|
350
465
|
},
|
|
466
|
+
observeRepl(id, memory, signal) { return sessions.observe(id, memory, signal) },
|
|
351
467
|
// A composite tool's outer result owns the final durability decision.
|
|
352
468
|
async executeTentative(callSeq, operation) {
|
|
353
469
|
const settlement = {
|
|
@@ -373,7 +489,7 @@ export function createRuntimeBridgeOwner({
|
|
|
373
489
|
throw error
|
|
374
490
|
}
|
|
375
491
|
},
|
|
376
|
-
handleExecute(exec, next, executionArguments = exec.arguments) {
|
|
492
|
+
handleExecute(exec, next, executionArguments = exec.arguments, userBindings = undefined) {
|
|
377
493
|
if (exec.parent !== undefined) return scope.run(undefined, next)
|
|
378
494
|
const id = sessionId(exec.agent)
|
|
379
495
|
if (id === undefined) return next()
|
|
@@ -390,6 +506,7 @@ export function createRuntimeBridgeOwner({
|
|
|
390
506
|
session: exec.agent?.session,
|
|
391
507
|
agent: exec.agent,
|
|
392
508
|
executionArguments,
|
|
509
|
+
...(userBindings === undefined ? {} : { userBindings }),
|
|
393
510
|
}
|
|
394
511
|
if (current.deferredSettlement !== undefined) {
|
|
395
512
|
current.deferredSettlement.current = current
|
|
@@ -404,7 +521,11 @@ export function createRuntimeBridgeOwner({
|
|
|
404
521
|
meta = withRecoveryBoundaries(meta, settlement.recoveryBoundaries)
|
|
405
522
|
}
|
|
406
523
|
if (settlement.rewrites !== undefined) meta = withRewrites(meta, settlement.rewrites)
|
|
524
|
+
if (settlement.userBindings !== undefined) {
|
|
525
|
+
meta = withUserBindingsSnapshot(meta, settlement.userBindings)
|
|
526
|
+
}
|
|
407
527
|
meta = withReplMemorySnapshot(meta, settlement.replMemory, presentationGeneration)
|
|
528
|
+
meta = withDraftCapability(meta, current)
|
|
408
529
|
return { ...result, meta }
|
|
409
530
|
}
|
|
410
531
|
return result
|
|
@@ -429,6 +550,12 @@ export function createRuntimeBridgeOwner({
|
|
|
429
550
|
Object.hasOwn(meta, RECOVERY_BOUNDARY_KEY) ? meta[RECOVERY_BOUNDARY_KEY] : undefined,
|
|
430
551
|
settlement.recoveryBoundaries,
|
|
431
552
|
)
|
|
553
|
+
&& userBindingsSnapshotsEqual(
|
|
554
|
+
Object.hasOwn(meta, USER_BINDINGS_META_KEY)
|
|
555
|
+
? meta[USER_BINDINGS_META_KEY]
|
|
556
|
+
: undefined,
|
|
557
|
+
settlement.userBindings,
|
|
558
|
+
)
|
|
432
559
|
if (current.deferredSettlement !== undefined) {
|
|
433
560
|
current.deferredSettlement.innerConfirmed = confirmed
|
|
434
561
|
return
|
|
@@ -443,10 +570,20 @@ export function createRuntimeBridgeOwner({
|
|
|
443
570
|
},
|
|
444
571
|
async dispose() {
|
|
445
572
|
active = false
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
573
|
+
const failures = []
|
|
574
|
+
const children = [...childRuntimes]
|
|
575
|
+
const childResultsPromise = Promise.allSettled(
|
|
576
|
+
children.map(child => disposeChildRuntime(child)),
|
|
577
|
+
)
|
|
578
|
+
await Promise.all([...nativeRunCodeHandoffs].map(handoff => handoff.settled))
|
|
579
|
+
const childResults = await childResultsPromise
|
|
580
|
+
for (const [index, result] of childResults.entries()) {
|
|
581
|
+
const child = children[index]
|
|
582
|
+
if (!childFinalizers.has(child)) childDisposals.delete(child)
|
|
583
|
+
if (result.status === 'rejected') failures.push(result.reason)
|
|
584
|
+
else childRuntimes.delete(child)
|
|
449
585
|
}
|
|
586
|
+
releaseSeam()
|
|
450
587
|
for (const patched of patchedDefinitions.values()) {
|
|
451
588
|
if (patched.output.presentationMeta === patched.patchedPresentationMeta) {
|
|
452
589
|
if (patched.originalPresentationMeta === undefined) delete patched.output.presentationMeta
|
|
@@ -459,7 +596,14 @@ export function createRuntimeBridgeOwner({
|
|
|
459
596
|
}
|
|
460
597
|
}
|
|
461
598
|
patchedDefinitions.clear()
|
|
462
|
-
|
|
599
|
+
try {
|
|
600
|
+
await sessions.dispose()
|
|
601
|
+
} catch (error) {
|
|
602
|
+
failures.push(error)
|
|
603
|
+
}
|
|
604
|
+
if (failures.length > 0) {
|
|
605
|
+
throw new AggregateError(failures, 'ptc-plus runtime bridge disposal failed')
|
|
606
|
+
}
|
|
463
607
|
},
|
|
464
608
|
})
|
|
465
609
|
}
|
|
@@ -1,65 +1,66 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CONFIG_DEFAULTS,
|
|
3
|
+
CONFIG_FIELDS,
|
|
3
4
|
MAX_TIMER_DELAY_MS,
|
|
4
5
|
} from './config-spec.js'
|
|
5
6
|
|
|
6
7
|
export { MAX_TIMER_DELAY_MS }
|
|
7
8
|
|
|
8
|
-
/**
|
|
9
|
-
const
|
|
10
|
-
'computeMs',
|
|
11
|
-
'maxOutputBytes',
|
|
12
|
-
'maxOldGenerationSizeMb',
|
|
13
|
-
'maxValueNodes',
|
|
14
|
-
'maxValueEdges',
|
|
15
|
-
'maxValueArrayLength',
|
|
16
|
-
'maxValueBigIntDigits',
|
|
17
|
-
])
|
|
9
|
+
/** The wall-clock ceiling field carries the platform timer limit as its maximum. */
|
|
10
|
+
const MAX_WALL_MS_FIELD = CONFIG_FIELDS.find(field => field.key === 'maxWallMs')
|
|
18
11
|
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
'autoRewriteImports',
|
|
29
|
-
'autoStripExports',
|
|
30
|
-
'autoSplitRedeclarations',
|
|
31
|
-
'tipsEnabled',
|
|
32
|
-
])
|
|
12
|
+
/** Validate one integer field against the bounds declared in CONFIG_FIELDS. */
|
|
13
|
+
function assertIntegerField(field, value) {
|
|
14
|
+
if (!Number.isSafeInteger(value) || value < field.min) {
|
|
15
|
+
throw new TypeError(`ptc-plus: ${field.key} must be a positive safe integer`)
|
|
16
|
+
}
|
|
17
|
+
if (value > field.max) {
|
|
18
|
+
throw new TypeError(`ptc-plus: ${field.key} must not exceed ${field.max}`)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
33
21
|
|
|
34
|
-
/**
|
|
35
|
-
|
|
36
|
-
'
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
22
|
+
/** Validate one field against its CONFIG_FIELDS declaration. */
|
|
23
|
+
function assertField(field, value) {
|
|
24
|
+
if (field.type === 'boolean') {
|
|
25
|
+
if (typeof value !== 'boolean') {
|
|
26
|
+
throw new TypeError(`ptc-plus: ${field.key} must be a boolean`)
|
|
27
|
+
}
|
|
28
|
+
return
|
|
29
|
+
}
|
|
30
|
+
if (field.type === 'enum') {
|
|
31
|
+
if (!field.options.includes(value)) {
|
|
32
|
+
throw new TypeError(`ptc-plus: ${field.key} must be one of ${field.options.join(', ')}`)
|
|
33
|
+
}
|
|
34
|
+
return
|
|
35
|
+
}
|
|
36
|
+
assertIntegerField(field, value)
|
|
37
|
+
}
|
|
40
38
|
|
|
41
39
|
/**
|
|
42
40
|
* Resolve plugin/runtime config from raw input, applying the shared defaults
|
|
43
|
-
* and
|
|
44
|
-
*
|
|
41
|
+
* and validating every declared field with the rules the Host Config schema
|
|
42
|
+
* exposes. Unknown keys are preserved for forwards compatibility.
|
|
43
|
+
* @param config - raw config object.
|
|
45
44
|
* @returns a resolved config object.
|
|
46
45
|
*/
|
|
47
46
|
export function resolveConfig(config = {}) {
|
|
48
47
|
const resolved = { ...CONFIG_DEFAULTS, ...config }
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if (
|
|
61
|
-
|
|
62
|
-
|
|
48
|
+
for (const field of CONFIG_FIELDS) assertField(field, resolved[field.key])
|
|
49
|
+
// Migrate complete old policies; mixed choices retain their explicit
|
|
50
|
+
// compatibility state until the user selects the unified language.
|
|
51
|
+
const legacyKeys = [
|
|
52
|
+
'looseTopLevelRedeclarations', 'looseTopLevelFunctionClassRedeclarations',
|
|
53
|
+
'autoRewriteImports', 'autoStripExports', 'autoSplitRedeclarations',
|
|
54
|
+
]
|
|
55
|
+
if (!Object.hasOwn(config, 'bindingUpdates')
|
|
56
|
+
&& legacyKeys.some(key => Object.hasOwn(config, key))) {
|
|
57
|
+
if (legacyKeys.every(key => resolved[key] === true)) {
|
|
58
|
+
resolved.bindingUpdates = 'stateful'
|
|
59
|
+
} else if (legacyKeys.slice(0, 2).every(key => resolved[key] === false)
|
|
60
|
+
&& resolved.autoSplitRedeclarations === false
|
|
61
|
+
&& resolved.autoRewriteImports && resolved.autoStripExports) {
|
|
62
|
+
resolved.bindingUpdates = 'protected'
|
|
63
|
+
} else resolved.legacyBindingSettings = true
|
|
63
64
|
}
|
|
64
65
|
return resolved
|
|
65
66
|
}
|
|
@@ -70,11 +71,6 @@ export function resolveConfig(config = {}) {
|
|
|
70
71
|
* @returns the validated value.
|
|
71
72
|
*/
|
|
72
73
|
export function validateMaxWallMs(value) {
|
|
73
|
-
|
|
74
|
-
throw new TypeError('ptc-plus: maxWallMs must be a positive safe integer')
|
|
75
|
-
}
|
|
76
|
-
if (value > MAX_TIMER_DELAY_MS) {
|
|
77
|
-
throw new TypeError(`ptc-plus: maxWallMs must not exceed ${MAX_TIMER_DELAY_MS}`)
|
|
78
|
-
}
|
|
74
|
+
assertIntegerField(MAX_WALL_MS_FIELD, value)
|
|
79
75
|
return value
|
|
80
76
|
}
|