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
|
@@ -1,27 +1,108 @@
|
|
|
1
1
|
import { diagnostic } from './diagnostic.js'
|
|
2
|
+
import { createHash } from 'node:crypto'
|
|
3
|
+
import { createPrivateAsyncLocalStorage } from './async-local-storage-intrinsics.js'
|
|
4
|
+
import { runtimeIntrinsics as internal } from './runtime-intrinsics.js'
|
|
2
5
|
|
|
6
|
+
const { Object, RegExp, isArray, numberIsSafeInteger, toNumber, toString,
|
|
7
|
+
splitString, startsWith, endsWith, sliceString, searchString, replaceString,
|
|
8
|
+
trimString, regexpExec, prependArray, join, bufferByteLength, bufferIsBuffer,
|
|
9
|
+
bufferSubarray, bufferToString } = internal
|
|
3
10
|
export const MAX_ERROR_LOG_BYTES = 4 * 1024
|
|
4
11
|
export const FAILURE_HINT_THRESHOLD = 3
|
|
5
12
|
export const LONG_CELL_CODE_UNITS = 2_000
|
|
6
13
|
const BINDING_FAILURE = Symbol('binding failure')
|
|
14
|
+
const PROGRAM_FAILURES = new internal.WeakMap()
|
|
15
|
+
const MAX_CAUSE_CODE_UNITS = 2048
|
|
16
|
+
const exceptionOrigins = createPrivateAsyncLocalStorage()
|
|
17
|
+
const runExceptionScope = exceptionOrigins.run.bind(exceptionOrigins)
|
|
18
|
+
const currentExceptionScope = exceptionOrigins.getStore.bind(exceptionOrigins)
|
|
7
19
|
|
|
8
|
-
|
|
9
|
-
|
|
20
|
+
/** Propagation facts belong to one execution, never to a user-thrown value. */
|
|
21
|
+
export function createExceptionOriginScope() {
|
|
22
|
+
const state = { origins: new internal.Map(), sourceFailures: new internal.Set(), open: true }
|
|
23
|
+
return {
|
|
24
|
+
run: callback => runExceptionScope(state, callback),
|
|
25
|
+
origins: error => internal.mapGet(state.origins, error),
|
|
26
|
+
sourceFailure: error => internal.setHas(state.sourceFailures, error),
|
|
27
|
+
close() { state.open = false; internal.mapClear(state.origins); internal.setClear(state.sourceFailures) },
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function recordExceptionOrigin(error, origin, { reset = false, sourceFailure = false } = {}) {
|
|
32
|
+
const state = currentExceptionScope()
|
|
33
|
+
if (state?.open !== true) return
|
|
34
|
+
if (reset) { internal.mapDelete(state.origins, error); internal.setDelete(state.sourceFailures, error) }
|
|
35
|
+
if (sourceFailure) internal.setAdd(state.sourceFailures, error)
|
|
36
|
+
if (typeof origin !== 'string') return
|
|
37
|
+
const origins = internal.mapGet(state.origins, error) ?? []
|
|
38
|
+
if (!internal.includes(origins, origin)) internal.appendArray(origins, origin)
|
|
39
|
+
internal.mapSet(state.origins, error, origins)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const SOURCE_LINE_BREAK = /\r\n|[\n\r\u2028\u2029]/
|
|
43
|
+
const sourceLines = source => splitString(source, SOURCE_LINE_BREAK)
|
|
44
|
+
|
|
45
|
+
/** A cell position is a 1-based line and column inside its source. The column
|
|
46
|
+
* may address the position just after the last character of a line. */
|
|
47
|
+
function boundedPosition(position, lines) {
|
|
48
|
+
if (position === null || typeof position !== 'object'
|
|
49
|
+
|| !numberIsSafeInteger(position.line) || position.line < 1
|
|
50
|
+
|| !numberIsSafeInteger(position.column) || position.column < 1
|
|
51
|
+
|| position.line > lines.length || position.column > lines[position.line - 1].length + 1) return undefined
|
|
52
|
+
return { line: position.line, column: position.column }
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Validate a candidate against the source that owns the reported cell. */
|
|
56
|
+
export function cellPosition(position, source) {
|
|
57
|
+
return boundedPosition(position, sourceLines(source))
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Only a fact belonging to the current original source can bypass its map. */
|
|
61
|
+
export function exceptionOriginPosition(origins, source) {
|
|
62
|
+
if (!isArray(origins)) return undefined
|
|
63
|
+
const prefix = `eval:${createHash('sha256').update(source).digest('hex')}:`
|
|
64
|
+
const lines = sourceLines(source)
|
|
65
|
+
for (let index = 0; index < origins.length; index += 1) {
|
|
66
|
+
const origin = origins[index]
|
|
67
|
+
if (typeof origin !== 'string' || !startsWith(origin, prefix)) continue
|
|
68
|
+
const match = regexpExec(/^(\d+):(\d+)$/, sliceString(origin, prefix.length))
|
|
69
|
+
if (match === null) continue
|
|
70
|
+
const position = boundedPosition({ line: toNumber(match[1]), column: toNumber(match[2]) }, lines)
|
|
71
|
+
if (position !== undefined) return position
|
|
72
|
+
}
|
|
73
|
+
return undefined
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function markBindingFailure(error, kind = 'lexical') {
|
|
77
|
+
Object.defineProperty(error, BINDING_FAILURE, { value: kind })
|
|
10
78
|
return error
|
|
11
79
|
}
|
|
12
80
|
|
|
13
|
-
|
|
14
|
-
|
|
81
|
+
/** Preserve worker-owned failure identity without trusting user exception text. */
|
|
82
|
+
export function programBindingError(kind, message) {
|
|
83
|
+
const error = new internal.Error(message)
|
|
84
|
+
internal.weakMapSet(PROGRAM_FAILURES, error, kind)
|
|
85
|
+
return error
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function repeatedFailureDiagnostic(kind, streak, stateEffect) {
|
|
89
|
+
if (kind === 'lexical' || kind === 'capability') {
|
|
90
|
+
const capability = kind === 'capability'
|
|
15
91
|
return diagnostic({
|
|
16
92
|
code: 'PTC-W001',
|
|
17
93
|
severity: 'warning',
|
|
18
94
|
phase: 'execute',
|
|
19
|
-
message: `this cell failed ${streak} times with the same
|
|
20
|
-
stateEffect
|
|
21
|
-
|
|
95
|
+
message: `this cell failed ${streak} times with the same ${capability ? 'capability' : 'lexical binding'} error; resolve the reported name before continuing`,
|
|
96
|
+
stateEffect,
|
|
97
|
+
cause: { code: capability ? 'PTC-CAPABILITY' : 'PTC-LOCAL', message: capability ? 'current program capability lookup failed' : 'local name or declaration conflict' },
|
|
98
|
+
help: capability ? [
|
|
22
99
|
'inspect live bindings with capabilities.tree(), capabilities.find(), or capabilities.inspect()',
|
|
23
100
|
'call available typed members through tools.*',
|
|
24
101
|
'do not repeat the same unresolved binding expression',
|
|
102
|
+
] : [
|
|
103
|
+
'inspect the visible cell source and results for the local declaration, scope, or initialization failure',
|
|
104
|
+
'correct the name or initialization; use a fresh name or block for a declaration conflict',
|
|
105
|
+
'capabilities describes program APIs, not session-local variables; discovery cannot prove local state',
|
|
25
106
|
],
|
|
26
107
|
})
|
|
27
108
|
}
|
|
@@ -30,7 +111,7 @@ function repeatedFailureDiagnostic(kind, streak) {
|
|
|
30
111
|
severity: 'warning',
|
|
31
112
|
phase: 'execute',
|
|
32
113
|
message: `this cell failed ${streak} times with the same error; inspect the reported cause and change the approach before retrying`,
|
|
33
|
-
stateEffect
|
|
114
|
+
stateEffect,
|
|
34
115
|
help: ['inspect the reported cause', 'change the inputs or approach before retrying'],
|
|
35
116
|
})
|
|
36
117
|
}
|
|
@@ -48,28 +129,36 @@ export function messageOf(error, fallback = 'Unprintable error') {
|
|
|
48
129
|
const message = safeProperty(error, 'message')
|
|
49
130
|
if (typeof message === 'string') return message
|
|
50
131
|
try {
|
|
51
|
-
return
|
|
132
|
+
return toString(error)
|
|
52
133
|
} catch {
|
|
53
134
|
return fallback
|
|
54
135
|
}
|
|
55
136
|
}
|
|
56
137
|
|
|
138
|
+
/** Preserve the child-process exit facts in every helper failure diagnostic. */
|
|
139
|
+
export function processExitDescription(code, signal) {
|
|
140
|
+
return signal === null || signal === undefined
|
|
141
|
+
? `code ${code}`
|
|
142
|
+
: `code ${code}, signal ${signal}`
|
|
143
|
+
}
|
|
144
|
+
|
|
57
145
|
export function firstLine(value, fallback = undefined) {
|
|
58
146
|
if (typeof value !== 'string') return fallback
|
|
59
|
-
const line = value
|
|
147
|
+
const line = splitString(value, /[\r\n]/, 1)[0]
|
|
60
148
|
return line.length > 0 ? line : fallback
|
|
61
149
|
}
|
|
62
150
|
|
|
63
151
|
export function oneLineMessage(error) {
|
|
64
|
-
return firstLine(messageOf(error), 'Unknown error')
|
|
152
|
+
return replaceString(firstLine(messageOf(error), 'Unknown error'), /\s+\(\d+:\d+\)$/, '')
|
|
65
153
|
}
|
|
66
154
|
|
|
67
155
|
/** Return DSH's reported missing-description property path when it is actionable. */
|
|
68
156
|
export function missingDescriptionPath(error) {
|
|
69
|
-
const
|
|
70
|
-
|
|
157
|
+
const pattern = /missing required property ["']([^"']+)["']/g
|
|
158
|
+
const message = messageOf(error)
|
|
159
|
+
for (let match = regexpExec(pattern, message); match !== null; match = regexpExec(pattern, message)) {
|
|
71
160
|
const path = match[1]
|
|
72
|
-
if (path === 'description' ||
|
|
161
|
+
if (path === 'description' || endsWith(path, '.description')) return path
|
|
73
162
|
}
|
|
74
163
|
return undefined
|
|
75
164
|
}
|
|
@@ -84,26 +173,34 @@ export function limitLogs(logs) {
|
|
|
84
173
|
let bytes = 0
|
|
85
174
|
const tail = []
|
|
86
175
|
for (let index = logs.length - 1; index >= 0; index -= 1) {
|
|
87
|
-
const size =
|
|
176
|
+
const size = bufferByteLength(logs[index], 'utf8') + 1
|
|
88
177
|
if (bytes + size > MAX_ERROR_LOG_BYTES) break
|
|
89
178
|
bytes += size
|
|
90
|
-
tail
|
|
179
|
+
prependArray(tail, logs[index])
|
|
91
180
|
}
|
|
92
181
|
return tail
|
|
93
182
|
}
|
|
94
183
|
|
|
95
|
-
|
|
184
|
+
/** A frame is only useful when its 1-based line and column are safe integers. */
|
|
185
|
+
function structuralPosition(position) {
|
|
186
|
+
return numberIsSafeInteger(position.line) && position.line >= 1
|
|
187
|
+
&& numberIsSafeInteger(position.column) && position.column >= 1 ? position : undefined
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** Extract the first frame for the active cell. The frame is reported in the
|
|
191
|
+
* executed text, so it is only a cell position when it lies inside the source
|
|
192
|
+
* that produced that text. */
|
|
193
|
+
export function errorPosition(error, filename, source) {
|
|
96
194
|
const stack = safeProperty(error, 'stack')
|
|
97
195
|
if (typeof stack !== 'string') return undefined
|
|
98
|
-
const escaped = filename
|
|
99
|
-
const match = new RegExp(`${escaped}:(\\d+):(\\d+)`)
|
|
196
|
+
const escaped = replaceString(filename, /[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
197
|
+
const match = regexpExec(new RegExp(`${escaped}:(\\d+):(\\d+)`), stack)
|
|
100
198
|
if (match === null) return undefined
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
return line >= 1 && column >= 1 ? { line, column } : undefined
|
|
199
|
+
const position = { line: toNumber(match[1]), column: toNumber(match[2]) }
|
|
200
|
+
return source === undefined ? structuralPosition(position) : cellPosition(position, source)
|
|
104
201
|
}
|
|
105
202
|
|
|
106
|
-
export function errorDetails(error, filename) {
|
|
203
|
+
export function errorDetails(error, filename, source) {
|
|
107
204
|
const message = messageOf(error, 'Unprintable thrown value')
|
|
108
205
|
const rawName = safeProperty(error, 'name')
|
|
109
206
|
const name = typeof rawName === 'string' && rawName.length > 0 ? rawName : 'Error'
|
|
@@ -114,19 +211,30 @@ export function errorDetails(error, filename) {
|
|
|
114
211
|
const candidate = safeProperty(error, 'ptcCause')
|
|
115
212
|
const causeMessage = firstLine(safeProperty(candidate, 'message'))
|
|
116
213
|
const causeCode = firstLine(safeProperty(candidate, 'code'))
|
|
214
|
+
const stderr = safeProperty(error, 'stderr')
|
|
215
|
+
const stderrText = typeof stderr === 'string' ? sliceString(stderr, 0, MAX_CAUSE_CODE_UNITS)
|
|
216
|
+
: bufferIsBuffer(stderr)
|
|
217
|
+
? bufferToString(bufferSubarray(stderr, 0, MAX_CAUSE_CODE_UNITS), 'utf8') : ''
|
|
218
|
+
const boundedMessage = sliceString(message, 0, MAX_CAUSE_CODE_UNITS)
|
|
219
|
+
const continuation = searchString(boundedMessage, /[\r\n]/)
|
|
220
|
+
const detailParts = [continuation < 0 ? '' : sliceString(boundedMessage, continuation + 1), stderrText]
|
|
221
|
+
const detail = trimString(replaceString(
|
|
222
|
+
sliceString(join(detailParts, ' '), 0, MAX_CAUSE_CODE_UNITS), /\s+/g, ' '))
|
|
117
223
|
const cause = causeMessage === undefined
|
|
118
|
-
? undefined
|
|
224
|
+
? detail.length === 0 ? undefined : { message: detail }
|
|
119
225
|
: {
|
|
120
226
|
...(causeCode === undefined ? {} : { code: causeCode }),
|
|
121
227
|
message: causeMessage,
|
|
122
228
|
}
|
|
123
|
-
const position = errorPosition(error, filename)
|
|
229
|
+
const position = errorPosition(error, filename, source)
|
|
230
|
+
const failureOrigin = internal.weakMapGet(PROGRAM_FAILURES, error)
|
|
124
231
|
return {
|
|
125
232
|
name,
|
|
126
233
|
message,
|
|
127
234
|
...(toolName === undefined ? {} : { toolName }),
|
|
128
235
|
...(position === undefined ? {} : { position }),
|
|
129
236
|
...(cause === undefined ? {} : { cause }),
|
|
237
|
+
...(failureOrigin === undefined ? {} : { failureOrigin }),
|
|
130
238
|
}
|
|
131
239
|
}
|
|
132
240
|
|
|
@@ -140,16 +248,16 @@ export function createFailureTracker() {
|
|
|
140
248
|
kind = undefined
|
|
141
249
|
streak = 0
|
|
142
250
|
},
|
|
143
|
-
hint(error) {
|
|
251
|
+
hint(error, stateEffect = 'unknown') {
|
|
144
252
|
const nextFingerprint = `${error.kind}\u0000${error.message}`
|
|
145
253
|
if (fingerprint === nextFingerprint) streak += 1
|
|
146
254
|
else {
|
|
147
255
|
fingerprint = nextFingerprint
|
|
148
|
-
kind = error[BINDING_FAILURE]
|
|
256
|
+
kind = error[BINDING_FAILURE] ?? 'generic'
|
|
149
257
|
streak = 1
|
|
150
258
|
}
|
|
151
259
|
if (streak !== FAILURE_HINT_THRESHOLD) return undefined
|
|
152
|
-
return repeatedFailureDiagnostic(kind, streak)
|
|
260
|
+
return repeatedFailureDiagnostic(kind, streak, stateEffect)
|
|
153
261
|
},
|
|
154
262
|
})
|
|
155
263
|
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { bindTypertRemote } from '@deepseek-ai/dsh-typert-protocol'
|
|
2
|
+
import { rpcDescriptor } from './rpc-contract.js'
|
|
3
|
+
|
|
4
|
+
/** Own Remote services and the package's Host invocation contribution. */
|
|
5
|
+
export function createHostRpc(ctx) {
|
|
6
|
+
const handlers = new Map()
|
|
7
|
+
let provider
|
|
8
|
+
let definition
|
|
9
|
+
let epoch
|
|
10
|
+
let disposed = false
|
|
11
|
+
const publish = () => {
|
|
12
|
+
// Registry withdrawal is synchronous, so replacement has no overlapping endpoints.
|
|
13
|
+
definition?.()
|
|
14
|
+
definition = undefined
|
|
15
|
+
if (provider === undefined || disposed || handlers.size === 0) return
|
|
16
|
+
definition = provider.effect(() => provider.typert.register({
|
|
17
|
+
package: 'dsh-ptc-plus', face: 'host', schemas: [],
|
|
18
|
+
model: { services: [], events: [], objects: [] },
|
|
19
|
+
invocations: [...handlers.keys()].map(rpcDescriptor),
|
|
20
|
+
}), 'ptc-plus: Remote definitions')
|
|
21
|
+
}
|
|
22
|
+
const port = {
|
|
23
|
+
register(contract, handler) {
|
|
24
|
+
if (disposed) throw new Error('PTC Plus RPC owner is disposed')
|
|
25
|
+
if (handlers.has(contract)) throw new Error(`PTC Plus RPC service ${contract.service} is already registered`)
|
|
26
|
+
const lifetime = new AbortController()
|
|
27
|
+
const service = {
|
|
28
|
+
invoke(operation, payload, signal) {
|
|
29
|
+
lifetime.signal.throwIfAborted()
|
|
30
|
+
if (epoch === undefined) throw new Error('PTC Plus RPC provider is unavailable')
|
|
31
|
+
return handler(operation, payload, AbortSignal.any([signal, lifetime.signal, epoch.signal]))
|
|
32
|
+
},
|
|
33
|
+
}
|
|
34
|
+
service.typertRemote = bindTypertRemote(service, contract.service)
|
|
35
|
+
const release = ctx.effect(function* () {
|
|
36
|
+
yield ctx.provide(contract.service, service)
|
|
37
|
+
handlers.set(contract, { release: () => release() })
|
|
38
|
+
yield () => {
|
|
39
|
+
lifetime.abort()
|
|
40
|
+
handlers.delete(contract)
|
|
41
|
+
publish()
|
|
42
|
+
}
|
|
43
|
+
publish()
|
|
44
|
+
}, 'ptc-plus: Remote service')
|
|
45
|
+
return release
|
|
46
|
+
},
|
|
47
|
+
}
|
|
48
|
+
const injection = ctx.inject?.(['typert'], scope => {
|
|
49
|
+
provider = scope
|
|
50
|
+
epoch = new AbortController()
|
|
51
|
+
publish()
|
|
52
|
+
scope.effect(() => scope.provide('ptcPlusRpc', port), 'ptc-plus: RPC registration port')
|
|
53
|
+
scope.effect(() => () => {
|
|
54
|
+
epoch.abort()
|
|
55
|
+
epoch = undefined
|
|
56
|
+
provider = undefined
|
|
57
|
+
definition = undefined
|
|
58
|
+
}, 'ptc-plus: RPC provider lifetime')
|
|
59
|
+
})
|
|
60
|
+
return { async dispose() {
|
|
61
|
+
disposed = true
|
|
62
|
+
for (const entry of [...handlers.values()]) await entry.release()
|
|
63
|
+
if (typeof injection === 'function') await injection()
|
|
64
|
+
else await injection?.dispose()
|
|
65
|
+
} }
|
|
66
|
+
}
|