dsh-ptc-plus 0.4.1 → 0.4.3
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 +164 -78
- package/README.md +165 -79
- package/assets/dsh-ptc-plus-banner-en.webp +0 -0
- package/assets/dsh-ptc-plus-banner-zh.webp +0 -0
- package/assets/ptc-plus-icon.svg +5 -0
- package/client.js +854 -336
- package/compiler-core.cjs +161 -157
- package/compiler-core.cjs.map +3 -3
- package/docs/README.md +4 -1
- package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +8 -7
- package/docs/adr/0008-define-agent-operating-contract.md +2 -2
- package/docs/adr/0010-session-log-derived-recovery-tips.md +7 -0
- package/docs/adr/0016-archive-resolved-review-findings.md +3 -3
- package/docs/adr/0019-plugin-settings-and-kill-switch.md +3 -3
- package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -0
- package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +14 -3
- package/docs/adr/0023-global-user-bindings.md +7 -7
- package/docs/adr/0025-use-versioned-logical-binding-identities.md +3 -3
- package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +23 -7
- package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +9 -5
- package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +26 -6
- package/docs/adr/0031-close-semantic-obligations-by-owner.md +29 -0
- package/docs/adr/README.md +4 -4
- package/docs/architecture.md +15 -10
- package/docs/binding-review-placement-design.md +1 -1
- package/docs/client-ui.md +9 -5
- package/docs/durability-design.md +12 -9
- package/docs/installation.md +27 -9
- package/docs/runtime-reference.md +23 -12
- package/docs/semantic-validation.md +7 -3
- package/docs/stateful-binding-updates-proposal.md +8 -4
- package/docs/user-bindings.en.md +10 -7
- package/docs/user-bindings.md +9 -6
- package/docs/value-wire.md +1 -1
- package/docs/verification-optimization-work.md +41 -0
- package/docs/verification.md +53 -2
- package/index.js +39 -34
- package/internal/async-local-storage-intrinsics.js +43 -0
- package/internal/binding-declaration-contract.js +8 -0
- package/internal/binding-source-analysis.js +381 -64
- package/internal/binding-update-policy.js +7 -1
- package/internal/callable-source-facts.js +37 -1
- package/internal/cell-analysis.js +85 -17
- package/internal/compiler-intrinsics.js +9 -43
- package/internal/compiler-module-links.js +7 -4
- package/internal/config-spec.js +1 -1
- package/internal/cordis-tools-owner.js +20 -10
- package/internal/dynamic-environment-integration.js +8 -4
- package/internal/dynamic-environment-runtime.js +24 -3
- package/internal/dynamic-native-calls.js +4 -1
- package/internal/dynamic-native-runtime.js +15 -1
- package/internal/edit-transport-owner.js +80 -20
- package/internal/execution-seam-compat.js +192 -30
- package/internal/failure-reporting.js +38 -30
- package/internal/isolated-worker.js +17 -10
- package/internal/kernel-worker.js +645 -393
- package/internal/message-sources.js +14 -0
- package/internal/module-compilation.js +7 -5
- package/internal/module-transform-contract.js +32 -2
- package/internal/record-utils.js +24 -15
- package/internal/repl-memory-projection.js +10 -0
- package/internal/repl-scope-normalizer.js +72 -35
- package/internal/repl-value-observer.js +145 -46
- package/internal/runtime-config.js +62 -2
- package/internal/runtime-intrinsics.js +104 -0
- package/internal/runtime-messages.js +6 -4
- package/internal/session-cell-executor.js +26 -2
- package/internal/session-journal-recovery.js +267 -67
- package/internal/session-journal-schema.js +30 -13
- package/internal/session-journal.js +485 -44
- package/internal/session-log-view.js +5 -4
- package/internal/session-runtime.js +46 -21
- package/internal/session-state.js +7 -29
- package/internal/settings-compat.js +66 -1
- package/internal/source-position-map.js +38 -0
- package/internal/stateful-root-compiler.js +3 -1
- package/internal/typescript-transform.js +4 -2
- package/internal/user-binding-console-worker.js +115 -41
- package/internal/user-binding-draft-projection.js +3 -2
- package/internal/user-bindings-owner.js +2 -1
- package/internal/user-bindings.js +16 -3
- package/internal/validated-parse-repair.js +6 -2
- package/internal/value-wire.js +189 -94
- package/internal/worker-client.js +99 -8
- package/internal/worker-cwd-virtualization.js +82 -54
- package/internal/worker-environment.js +20 -0
- package/internal/worker-output-capture.js +187 -0
- package/internal/worker-output-fence.js +26 -0
- package/internal/worker-realm-surfaces.js +197 -0
- package/internal/worker-repl-realm.js +140 -0
- package/package.json +37 -4
- package/src/client-activity.js +12 -2
- package/src/client-authoring-view.js +121 -62
- package/src/client-console.js +4 -2
- package/src/client-copy.js +4 -2
- package/src/client-feature-gates.js +7 -9
- package/src/client-host-compat.js +104 -27
- package/src/client-repl-view.js +3 -1
- package/src/client-styles.js +12 -1
- package/src/client-tool-view.js +3 -1
- package/src/client-transport.js +2 -2
- package/src/client-workbench.js +4 -3
- package/src/client.js +56 -17
|
@@ -43,8 +43,36 @@ function assertField(field, value) {
|
|
|
43
43
|
* @param config - raw config object.
|
|
44
44
|
* @returns a resolved config object.
|
|
45
45
|
*/
|
|
46
|
+
/**
|
|
47
|
+
* A volatile schema field validates to a live `{ get }` handle. A field that
|
|
48
|
+
* has no schema default arrives as a handle with an undefined live value and
|
|
49
|
+
* keeps the runtime default.
|
|
50
|
+
*/
|
|
51
|
+
function liveConfigValue(value, fallback) {
|
|
52
|
+
if (value !== null && typeof value === 'object'
|
|
53
|
+
&& typeof value.get === 'function' && Object.keys(value).length === 1) {
|
|
54
|
+
const live = value.get()
|
|
55
|
+
return live === undefined ? fallback : live
|
|
56
|
+
}
|
|
57
|
+
return value
|
|
58
|
+
}
|
|
59
|
+
|
|
46
60
|
export function resolveConfig(config = {}) {
|
|
61
|
+
const provided = new Set()
|
|
62
|
+
for (const field of CONFIG_FIELDS) {
|
|
63
|
+
if (!Object.hasOwn(config, field.key)) continue
|
|
64
|
+
const value = config[field.key]
|
|
65
|
+
if (value !== null && typeof value === 'object'
|
|
66
|
+
&& typeof value.get === 'function' && Object.keys(value).length === 1) {
|
|
67
|
+
if (value.get() !== undefined) provided.add(field.key)
|
|
68
|
+
} else {
|
|
69
|
+
provided.add(field.key)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
47
72
|
const resolved = { ...CONFIG_DEFAULTS, ...config }
|
|
73
|
+
for (const field of CONFIG_FIELDS) {
|
|
74
|
+
resolved[field.key] = liveConfigValue(resolved[field.key], CONFIG_DEFAULTS[field.key])
|
|
75
|
+
}
|
|
48
76
|
for (const field of CONFIG_FIELDS) assertField(field, resolved[field.key])
|
|
49
77
|
// Migrate complete old policies; mixed choices retain their explicit
|
|
50
78
|
// compatibility state until the user selects the unified language.
|
|
@@ -52,8 +80,8 @@ export function resolveConfig(config = {}) {
|
|
|
52
80
|
'looseTopLevelRedeclarations', 'looseTopLevelFunctionClassRedeclarations',
|
|
53
81
|
'autoRewriteImports', 'autoStripExports', 'autoSplitRedeclarations',
|
|
54
82
|
]
|
|
55
|
-
if (!
|
|
56
|
-
&& legacyKeys.some(key =>
|
|
83
|
+
if (!provided.has('bindingUpdates')
|
|
84
|
+
&& legacyKeys.some(key => provided.has(key))) {
|
|
57
85
|
if (legacyKeys.every(key => resolved[key] === true)) {
|
|
58
86
|
resolved.bindingUpdates = 'stateful'
|
|
59
87
|
} else if (legacyKeys.slice(0, 2).every(key => resolved[key] === false)
|
|
@@ -65,6 +93,38 @@ export function resolveConfig(config = {}) {
|
|
|
65
93
|
return resolved
|
|
66
94
|
}
|
|
67
95
|
|
|
96
|
+
/** Whether a validated config carries live volatile field handles. */
|
|
97
|
+
export function hasVolatileFields(config) {
|
|
98
|
+
if (config === null || typeof config !== 'object') return false
|
|
99
|
+
return Object.values(config).some(value => value !== null && typeof value === 'object'
|
|
100
|
+
&& typeof value.get === 'function' && Object.keys(value).length === 1)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Follow the host's volatile-only commit into the running fiber.
|
|
105
|
+
*
|
|
106
|
+
* The loader updates the retained handles in place and emits
|
|
107
|
+
* `loader/volatile-update` on the owning fiber; listeners on a child scope are
|
|
108
|
+
* filtered out, so the listener belongs to the plugin's own context and is
|
|
109
|
+
* released with the runtime scope it serves.
|
|
110
|
+
*
|
|
111
|
+
* @param host - the plugin's own context, owning the loader event listener.
|
|
112
|
+
* @param scope - the runtime scope whose disposal removes the listener.
|
|
113
|
+
* @param config - the validated config carrying the volatile handles.
|
|
114
|
+
* @param listener - receives the newly resolved plain configuration.
|
|
115
|
+
* @returns whether a volatile listener was installed.
|
|
116
|
+
*/
|
|
117
|
+
export function watchVolatileConfig(host, scope, config, listener) {
|
|
118
|
+
if (!hasVolatileFields(config) || typeof host?.on !== 'function') return false
|
|
119
|
+
const update = () => listener(resolveConfig(config))
|
|
120
|
+
if (typeof scope?.effect === 'function') {
|
|
121
|
+
scope.effect(() => host.on('loader/volatile-update', update), 'ptc-plus volatile settings lifecycle')
|
|
122
|
+
} else {
|
|
123
|
+
host.on('loader/volatile-update', update)
|
|
124
|
+
}
|
|
125
|
+
return true
|
|
126
|
+
}
|
|
127
|
+
|
|
68
128
|
/**
|
|
69
129
|
* Validate one wall-clock ceiling against the platform timer limit.
|
|
70
130
|
* @param value - the configured maximum wall time in milliseconds.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { compilerDescriptors } from './compiler-descriptors.js'
|
|
2
|
+
|
|
3
|
+
const uncurry = Function.prototype.bind.bind(Function.prototype.call)
|
|
4
|
+
const mapKeys = uncurry(Map.prototype.keys)
|
|
5
|
+
const mapIteratorNext = uncurry(Object.getPrototypeOf(new Map().keys()).next)
|
|
6
|
+
const weakMapGet = uncurry(WeakMap.prototype.get)
|
|
7
|
+
const weakMapSet = uncurry(WeakMap.prototype.set)
|
|
8
|
+
|
|
9
|
+
function appendArray(target, value) {
|
|
10
|
+
compilerDescriptors.defineProperty(target, target.length,
|
|
11
|
+
{ value, writable: true, enumerable: true, configurable: true })
|
|
12
|
+
return target
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function copyArray(source, start = 0, end = source.length, target = []) {
|
|
16
|
+
for (let index = start; index < end; index++) appendArray(target, source[index])
|
|
17
|
+
return target
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Host-private operations captured before any owned realm executes user code. */
|
|
21
|
+
export const runtimeIntrinsics = {
|
|
22
|
+
Object: compilerDescriptors.Object,
|
|
23
|
+
Reflect: {
|
|
24
|
+
apply: Reflect.apply,
|
|
25
|
+
construct: Reflect.construct,
|
|
26
|
+
deleteProperty: Reflect.deleteProperty,
|
|
27
|
+
defineProperty: compilerDescriptors.reflectDefineProperty,
|
|
28
|
+
has: Reflect.has,
|
|
29
|
+
ownKeys: Reflect.ownKeys,
|
|
30
|
+
set: Reflect.set,
|
|
31
|
+
},
|
|
32
|
+
Error, TypeError, Array, Map, Set, WeakMap, WeakSet, RegExp, Proxy,
|
|
33
|
+
objectCreate: Object.create,
|
|
34
|
+
objectDefineProperty: Object.defineProperty,
|
|
35
|
+
objectEntries: Object.entries,
|
|
36
|
+
objectFreeze: Object.freeze,
|
|
37
|
+
objectGetOwnPropertyDescriptor: Object.getOwnPropertyDescriptor,
|
|
38
|
+
objectGetPrototypeOf: Object.getPrototypeOf,
|
|
39
|
+
objectHasOwn: Object.hasOwn,
|
|
40
|
+
objectIs: Object.is,
|
|
41
|
+
objectKeys: Object.keys,
|
|
42
|
+
objectPropertyIsEnumerable: uncurry(Object.prototype.propertyIsEnumerable),
|
|
43
|
+
reflectOwnKeys: Reflect.ownKeys,
|
|
44
|
+
numberIsFinite: Number.isFinite,
|
|
45
|
+
numberIsNaN: Number.isNaN,
|
|
46
|
+
numberIsSafeInteger: Number.isSafeInteger,
|
|
47
|
+
toBigInt: BigInt,
|
|
48
|
+
toNumber: Number,
|
|
49
|
+
toString: String,
|
|
50
|
+
bigintToString: uncurry(BigInt.prototype.toString),
|
|
51
|
+
jsonStringify: JSON.stringify,
|
|
52
|
+
mapGet: uncurry(Map.prototype.get),
|
|
53
|
+
mapHas: uncurry(Map.prototype.has),
|
|
54
|
+
mapSet: uncurry(Map.prototype.set),
|
|
55
|
+
mapDelete: uncurry(Map.prototype.delete),
|
|
56
|
+
mapClear: uncurry(Map.prototype.clear),
|
|
57
|
+
mapSize: uncurry(Object.getOwnPropertyDescriptor(Map.prototype, 'size').get),
|
|
58
|
+
mapFirstKey: value => mapIteratorNext(mapKeys(value)).value,
|
|
59
|
+
mapForEach: uncurry(Map.prototype.forEach),
|
|
60
|
+
setHas: uncurry(Set.prototype.has),
|
|
61
|
+
setAdd: uncurry(Set.prototype.add),
|
|
62
|
+
setDelete: uncurry(Set.prototype.delete),
|
|
63
|
+
setClear: uncurry(Set.prototype.clear),
|
|
64
|
+
setSize: uncurry(Object.getOwnPropertyDescriptor(Set.prototype, 'size').get),
|
|
65
|
+
setForEach: uncurry(Set.prototype.forEach),
|
|
66
|
+
weakMapHas: uncurry(WeakMap.prototype.has),
|
|
67
|
+
weakMapGet,
|
|
68
|
+
weakMapSet,
|
|
69
|
+
weakSetHas: uncurry(WeakSet.prototype.has),
|
|
70
|
+
weakSetAdd: uncurry(WeakSet.prototype.add),
|
|
71
|
+
isArray: Array.isArray,
|
|
72
|
+
everyArray: uncurry(Array.prototype.every),
|
|
73
|
+
includes: uncurry(Array.prototype.includes),
|
|
74
|
+
join: uncurry(Array.prototype.join),
|
|
75
|
+
popArray: uncurry(Array.prototype.pop),
|
|
76
|
+
prependArray: uncurry(Array.prototype.unshift),
|
|
77
|
+
someArray: uncurry(Array.prototype.some),
|
|
78
|
+
sliceString: uncurry(String.prototype.slice),
|
|
79
|
+
splitString: uncurry(String.prototype.split),
|
|
80
|
+
searchString: uncurry(String.prototype.search),
|
|
81
|
+
replaceString: uncurry(String.prototype.replace),
|
|
82
|
+
trimString: uncurry(String.prototype.trim),
|
|
83
|
+
replaceAllString: uncurry(String.prototype.replaceAll),
|
|
84
|
+
includesString: uncurry(String.prototype.includes),
|
|
85
|
+
startsWith: uncurry(String.prototype.startsWith),
|
|
86
|
+
endsWith: uncurry(String.prototype.endsWith),
|
|
87
|
+
regexpExec: uncurry(RegExp.prototype.exec),
|
|
88
|
+
regexpTest: uncurry(RegExp.prototype.test),
|
|
89
|
+
floor: Math.floor,
|
|
90
|
+
min: Math.min,
|
|
91
|
+
max: Math.max,
|
|
92
|
+
appendArray,
|
|
93
|
+
copyArray,
|
|
94
|
+
sort: uncurry(Array.prototype.sort),
|
|
95
|
+
compare: uncurry(String.prototype.localeCompare),
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (typeof Buffer === 'function') {
|
|
99
|
+
runtimeIntrinsics.bufferByteLength = Buffer.byteLength
|
|
100
|
+
runtimeIntrinsics.bufferConcat = Buffer.concat
|
|
101
|
+
runtimeIntrinsics.bufferIsBuffer = Buffer.isBuffer
|
|
102
|
+
runtimeIntrinsics.bufferSubarray = uncurry(Buffer.prototype.subarray)
|
|
103
|
+
runtimeIntrinsics.bufferToString = uncurry(Buffer.prototype.toString)
|
|
104
|
+
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { createUserMessage } from '@deepseek-ai/dsh-llm'
|
|
2
2
|
|
|
3
|
+
import { isPtcMessageSource, PTC_MESSAGE_SOURCE_KIND } from './message-sources.js'
|
|
4
|
+
|
|
3
5
|
export const PTC_DELIVERY_CONTEXT = 'tools:ptc-plus-message-delivery'
|
|
4
6
|
export const PTC_BINDING_CATALOG = 'tools:ptc-plus-user-binding-defaults'
|
|
5
7
|
export const PTC_STATE_NAMES = Object.freeze([
|
|
@@ -54,7 +56,7 @@ function stateText(sections, prefix = STATE_PREFIX) {
|
|
|
54
56
|
/** Recognize only bounded, formed PTC records, never authoring tasks or Skills. */
|
|
55
57
|
export function readRuntimeMessage(message) {
|
|
56
58
|
const source = message?.source
|
|
57
|
-
if (source
|
|
59
|
+
if (!isPtcMessageSource(source)
|
|
58
60
|
|| !Array.isArray(message.content) || message.content.length !== 1
|
|
59
61
|
|| message.content[0]?.type !== 'text') return undefined
|
|
60
62
|
const text = message.content[0].text
|
|
@@ -87,7 +89,7 @@ export function runtimeBindingCatalogMessage(context) {
|
|
|
87
89
|
throw new Error('invalid PTC binding catalog')
|
|
88
90
|
}
|
|
89
91
|
return createUserMessage({
|
|
90
|
-
source: { kind:
|
|
92
|
+
source: { kind: PTC_MESSAGE_SOURCE_KIND, form: 'catalog' },
|
|
91
93
|
content: [{ type: 'text', text: `${CATALOG_PREFIX}\n\n${context?.text ?? EMPTY_CATALOG}` }],
|
|
92
94
|
})
|
|
93
95
|
}
|
|
@@ -96,14 +98,14 @@ export function runtimeStateMessage(value) {
|
|
|
96
98
|
const sections = stateSections(value)
|
|
97
99
|
if (sections === undefined) throw new Error('invalid PTC runtime state sections')
|
|
98
100
|
return createUserMessage({
|
|
99
|
-
source: { kind:
|
|
101
|
+
source: { kind: PTC_MESSAGE_SOURCE_KIND, form: 'snapshot', sections },
|
|
100
102
|
content: [{ type: 'text', text: stateText(sections) }],
|
|
101
103
|
})
|
|
102
104
|
}
|
|
103
105
|
|
|
104
106
|
export function runtimeNoticeMessage(tip) {
|
|
105
107
|
const message = createUserMessage({
|
|
106
|
-
source: { kind:
|
|
108
|
+
source: { kind: PTC_MESSAGE_SOURCE_KIND, form: 'notice', summary: tip.name },
|
|
107
109
|
content: [{ type: 'text', text: tip.text }],
|
|
108
110
|
})
|
|
109
111
|
if (readRuntimeMessage(message) === undefined) throw new Error('invalid PTC recovery notice')
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { resolve } from 'node:path'
|
|
2
|
+
import { pathToFileURL } from 'node:url'
|
|
1
3
|
import {
|
|
2
4
|
decodeValue,
|
|
3
5
|
encodeValue,
|
|
@@ -414,7 +416,9 @@ export class SessionCellExecutor {
|
|
|
414
416
|
}
|
|
415
417
|
const priorBindingCatalog = userBindingPlan.catalog
|
|
416
418
|
const catalog = priorBindingCatalog.inputs()
|
|
417
|
-
const { bindingPolicy, rewritesEnabled, moduleSemantics, languageSemantics } = executionPolicies(config, replayRecord)
|
|
419
|
+
const { bindingPolicy, rewritesEnabled, moduleSemantics, languageSemantics, moduleTransform } = executionPolicies(config, replayRecord)
|
|
420
|
+
const moduleDirectory = kernel.cwd ?? process.cwd()
|
|
421
|
+
const moduleFilename = resolve(moduleDirectory, 'repl')
|
|
418
422
|
const prepareCell = program => prepareProgram(program, {
|
|
419
423
|
knownBindings: catalog.knownBindings,
|
|
420
424
|
bindingPolicy,
|
|
@@ -430,6 +434,11 @@ export class SessionCellExecutor {
|
|
|
430
434
|
dynamicOrigins: catalog.dynamicOrigins,
|
|
431
435
|
establishedRoots: catalog.establishedRoots,
|
|
432
436
|
moduleSemantics,
|
|
437
|
+
importMeta: {
|
|
438
|
+
url: pathToFileURL(moduleFilename).href,
|
|
439
|
+
filename: moduleFilename,
|
|
440
|
+
dirname: moduleDirectory,
|
|
441
|
+
},
|
|
433
442
|
})
|
|
434
443
|
let prepared
|
|
435
444
|
try {
|
|
@@ -576,6 +585,7 @@ export class SessionCellExecutor {
|
|
|
576
585
|
type: 'run', id, program: prepared.code, namespaces: bindings.workerDescriptors,
|
|
577
586
|
moduleLoads: prepared.moduleLoads,
|
|
578
587
|
languageSemantics,
|
|
588
|
+
moduleTransform,
|
|
579
589
|
rootRuntimeName: prepared.rootRuntimeName,
|
|
580
590
|
rootBindings: prepared.rootBindings,
|
|
581
591
|
importBindingNamespaces: new Map([...catalog.importBindings].map(([name, binding]) => [name, binding.namespace])),
|
|
@@ -711,9 +721,10 @@ export class SessionCellExecutor {
|
|
|
711
721
|
volatile: this.handleVolatile,
|
|
712
722
|
call: this.handleCall,
|
|
713
723
|
'output-limit': this.handleOutputLimit,
|
|
724
|
+
'worker-output-error': this.handleWorkerOutputError,
|
|
714
725
|
done: this.handleDone,
|
|
715
726
|
}[message.type]
|
|
716
|
-
handler?.call(this, message)
|
|
727
|
+
return handler?.call(this, message)
|
|
717
728
|
}
|
|
718
729
|
|
|
719
730
|
handleVolatile(message) {
|
|
@@ -741,6 +752,19 @@ export class SessionCellExecutor {
|
|
|
741
752
|
}, true)
|
|
742
753
|
}
|
|
743
754
|
|
|
755
|
+
handleWorkerOutputError(message) {
|
|
756
|
+
const active = this.kernel.active
|
|
757
|
+
if (active?.id !== message.id) return false
|
|
758
|
+
const detail = typeof message.message === 'string'
|
|
759
|
+
? message.message
|
|
760
|
+
: 'the kernel returned an invalid output-attribution event'
|
|
761
|
+
active.resolve({
|
|
762
|
+
logs: [],
|
|
763
|
+
error: { kind: 'worker-exit', message: `worker output attribution failed: ${detail}` },
|
|
764
|
+
}, true)
|
|
765
|
+
return true
|
|
766
|
+
}
|
|
767
|
+
|
|
744
768
|
handleDone(message) {
|
|
745
769
|
const kernel = this.kernel
|
|
746
770
|
if (kernel.active?.id !== message.id) return
|