dsh-ptc-plus 0.3.1 → 0.4.1

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.
Files changed (200) hide show
  1. package/README.en.md +66 -73
  2. package/README.md +66 -73
  3. package/assets/ptc-plus-bindings-en.png +0 -0
  4. package/assets/ptc-plus-bindings-zh.png +0 -0
  5. package/assets/ptc-plus-repair-en.png +0 -0
  6. package/assets/ptc-plus-repair-zh.png +0 -0
  7. package/assets/ptc-plus-repl-workspace-en.png +0 -0
  8. package/assets/ptc-plus-repl-workspace-zh.png +0 -0
  9. package/assets/ptc-plus-settings-en.png +0 -0
  10. package/assets/ptc-plus-settings-zh.png +0 -0
  11. package/client.js +30610 -722
  12. package/compiler-amaro.cjs +5 -0
  13. package/compiler-amaro.cjs.map +6 -0
  14. package/compiler-asset-124f80c1bba92ff5fe79cfec6e8ad518f476de4a42514cae3919538887f510e8.txt +1 -0
  15. package/compiler-assets.json +3 -0
  16. package/compiler-core.cjs +554 -0
  17. package/compiler-core.cjs.map +6 -0
  18. package/compiler-platform.cjs +2 -0
  19. package/compiler-platform.cjs.map +6 -0
  20. package/compiler-typescript.cjs +388 -0
  21. package/compiler-typescript.cjs.map +6 -0
  22. package/docs/README.md +6 -0
  23. package/docs/adr/0004-declare-program-bindings-at-the-host.md +1 -1
  24. package/docs/adr/0006-rewrite-module-syntax-with-an-ast.md +6 -4
  25. package/docs/adr/0007-separate-worker-transport-from-session-semantics.md +15 -3
  26. package/docs/adr/0009-bound-expensive-acceptance-default.md +2 -0
  27. package/docs/adr/0010-session-log-derived-recovery-tips.md +59 -5
  28. package/docs/adr/0011-isolate-the-local-recovery-tip-provider.md +1 -1
  29. package/docs/adr/0012-preserve-mixed-destructuring-initialization.md +3 -1
  30. package/docs/adr/0013-isolate-repl-redeclaration-convenience.md +9 -3
  31. package/docs/adr/0014-persist-cell-rewrite-policy.md +11 -5
  32. package/docs/adr/0015-preserve-source-positions-through-rewrites.md +1 -1
  33. package/docs/adr/0016-archive-resolved-review-findings.md +1 -1
  34. package/docs/adr/0017-track-the-latest-dsh-public-surface.md +49 -0
  35. package/docs/adr/0018-use-versioned-fixture-for-ab-benchmark.md +3 -3
  36. package/docs/adr/0019-plugin-settings-and-kill-switch.md +8 -6
  37. package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -2
  38. package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +17 -3
  39. package/docs/adr/0023-global-user-bindings.md +104 -0
  40. package/docs/adr/0024-repl-console-observation.md +33 -0
  41. package/docs/adr/0025-use-versioned-logical-binding-identities.md +119 -0
  42. package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +21 -0
  43. package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +37 -0
  44. package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +103 -0
  45. package/docs/adr/0029-keep-plugin-unavailability-out-of-the-host-agent-lifecycle.md +27 -0
  46. package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +27 -0
  47. package/docs/architecture.md +82 -22
  48. package/docs/binding-review-placement-design.md +200 -0
  49. package/docs/capability-projection.md +1 -1
  50. package/docs/client-ui.md +96 -20
  51. package/docs/durability-design.md +61 -24
  52. package/docs/evaluation.md +78 -6
  53. package/docs/installation.md +41 -6
  54. package/docs/program-data-plane.md +6 -0
  55. package/docs/publishing.md +5 -3
  56. package/docs/runtime-reference.md +79 -25
  57. package/docs/semantic-validation.md +29 -0
  58. package/docs/stateful-binding-updates-proposal.md +755 -0
  59. package/docs/user-bindings.en.md +64 -0
  60. package/docs/user-bindings.md +64 -0
  61. package/docs/value-wire.md +3 -3
  62. package/docs/verification.md +57 -0
  63. package/index.js +374 -92
  64. package/internal/ast-traversal.js +5 -2
  65. package/internal/binding-descriptors.js +1 -0
  66. package/internal/binding-pattern-traversal.js +25 -0
  67. package/internal/binding-pattern.js +26 -29
  68. package/internal/binding-source-analysis.js +391 -0
  69. package/internal/binding-update-policy.js +66 -0
  70. package/internal/bounded-worker-round.js +56 -0
  71. package/internal/callable-definition-environment.js +42 -0
  72. package/internal/callable-source-catalog.js +129 -0
  73. package/internal/callable-source-encoding.js +47 -0
  74. package/internal/callable-source-facts.js +459 -0
  75. package/internal/callable-source-format.js +2 -0
  76. package/internal/callable-source-lowering.js +123 -0
  77. package/internal/cell-analysis-contract.js +25 -0
  78. package/internal/cell-analysis.js +252 -242
  79. package/internal/cell-completion.js +15 -0
  80. package/internal/cell-error.js +7 -0
  81. package/internal/cell-parser.js +66 -0
  82. package/internal/cell-rewriter.js +3 -553
  83. package/internal/commonjs-export-evidence.js +63 -0
  84. package/internal/commonjs-source-evidence.js +72 -0
  85. package/internal/compiler-amaro.cjs +2 -0
  86. package/internal/compiler-compression.js +12 -0
  87. package/internal/compiler-data.js +58 -0
  88. package/internal/compiler-descriptors.js +54 -0
  89. package/internal/compiler-dynamic-cache.js +48 -0
  90. package/internal/compiler-entry.js +35 -0
  91. package/internal/compiler-generated-names.js +17 -0
  92. package/internal/compiler-intrinsics.js +84 -0
  93. package/internal/compiler-module-links.js +34 -0
  94. package/internal/compiler-operations.js +61 -0
  95. package/internal/compiler-platform-factory.js +84 -0
  96. package/internal/compiler-platform.js +136 -0
  97. package/internal/compiler-record-roles.js +53 -0
  98. package/internal/compiler-region-output.js +259 -0
  99. package/internal/compiler-resource-lowering.js +103 -0
  100. package/internal/compiler-scope-facts.js +115 -0
  101. package/internal/compiler-service.js +109 -0
  102. package/internal/compiler-source-cache.js +32 -0
  103. package/internal/compiler-source-pieces.js +93 -0
  104. package/internal/compiler-source-regions.js +132 -0
  105. package/internal/compiler-storage-source.js +54 -0
  106. package/internal/compiler-text.js +15 -0
  107. package/internal/compiler-typescript.cjs +2 -0
  108. package/internal/config-spec.js +91 -25
  109. package/internal/cordis-tools-owner.js +130 -21
  110. package/internal/diagnostic.js +27 -1
  111. package/internal/direct-surface-owner.js +76 -23
  112. package/internal/dynamic-binding-evidence.js +16 -0
  113. package/internal/dynamic-environment-compiler.js +779 -0
  114. package/internal/dynamic-environment-integration.js +87 -0
  115. package/internal/dynamic-environment-runtime.js +362 -0
  116. package/internal/dynamic-native-calls.js +150 -0
  117. package/internal/dynamic-native-runtime.js +248 -0
  118. package/internal/dynamic-scope-analysis.js +90 -0
  119. package/internal/edit-transport-owner.js +28 -3
  120. package/internal/execution-seam-compat.js +193 -0
  121. package/internal/failure-reporting.js +118 -18
  122. package/internal/host-rpc.js +66 -0
  123. package/internal/isolated-worker.js +548 -0
  124. package/internal/kernel-child.js +139 -0
  125. package/internal/kernel-worker.js +911 -116
  126. package/internal/language-semantics.js +14 -0
  127. package/internal/legacy-binding-catalog.js +48 -0
  128. package/internal/legacy-cell-analysis.js +600 -0
  129. package/internal/legacy-cell-parser.js +50 -0
  130. package/internal/legacy-cell-rewriter.js +631 -0
  131. package/internal/legacy-repl-convenience.js +291 -0
  132. package/internal/managed-module-operations.js +170 -0
  133. package/internal/module-compilation.js +321 -0
  134. package/internal/module-runtime-platform.js +19 -0
  135. package/internal/module-transform-contract.js +12 -0
  136. package/internal/native-await-declarations.js +68 -0
  137. package/internal/native-root-compilation.js +54 -0
  138. package/internal/native-root-dynamic.js +67 -0
  139. package/internal/recovery-tips.js +27 -15
  140. package/internal/rejected-cell-editor.js +13 -8
  141. package/internal/repl-convenience.js +2 -201
  142. package/internal/repl-memory-projection.js +81 -12
  143. package/internal/repl-observation-interest.js +70 -0
  144. package/internal/repl-rewrite-contract.js +21 -0
  145. package/internal/repl-scope-normalizer.js +2091 -0
  146. package/internal/repl-value-observer.js +114 -0
  147. package/internal/rpc-contract.js +52 -0
  148. package/internal/runtime-bridge-owner.js +172 -28
  149. package/internal/runtime-config.js +48 -51
  150. package/internal/runtime-contexts.js +82 -10
  151. package/internal/runtime-messages.js +111 -0
  152. package/internal/session-cell-executor.js +455 -91
  153. package/internal/session-journal-recovery.js +684 -0
  154. package/internal/session-journal-schema.js +106 -0
  155. package/internal/session-journal.js +237 -440
  156. package/internal/session-log-view.js +42 -9
  157. package/internal/session-runtime.js +325 -80
  158. package/internal/session-state.js +249 -40
  159. package/internal/source-position-map.js +211 -71
  160. package/internal/stateful-module-compiler.js +154 -0
  161. package/internal/stateful-module-runtime.js +303 -0
  162. package/internal/stateful-root-compiler.js +598 -0
  163. package/internal/stateful-root-runtime.js +340 -0
  164. package/internal/typert-codec-compat.js +28 -0
  165. package/internal/typescript-transform.js +29 -0
  166. package/internal/user-binding-authoring.js +70 -0
  167. package/internal/user-binding-console-worker.js +184 -0
  168. package/internal/user-binding-console.js +148 -0
  169. package/internal/user-binding-draft-projection.js +335 -0
  170. package/internal/user-binding-model-context.js +31 -0
  171. package/internal/user-binding-runner.js +56 -0
  172. package/internal/user-bindings-owner.js +1065 -0
  173. package/internal/user-bindings-store.js +293 -0
  174. package/internal/user-bindings.js +353 -0
  175. package/internal/value-wire-schema.js +28 -0
  176. package/internal/value-wire.js +29 -20
  177. package/internal/worker-client.js +57 -67
  178. package/internal/worker-environment.js +45 -0
  179. package/internal/worker-output-relay.js +29 -0
  180. package/internal/worker-shutdown.js +14 -0
  181. package/package.json +81 -11
  182. package/src/client-activity.js +109 -45
  183. package/src/client-authoring-view.js +580 -0
  184. package/src/client-binding-review.js +230 -0
  185. package/src/client-bindings-data.js +29 -0
  186. package/src/client-catalog.js +127 -0
  187. package/src/client-code-editor.js +84 -0
  188. package/src/client-console.js +112 -0
  189. package/src/client-copy.js +370 -0
  190. package/src/client-feature-gates.js +62 -0
  191. package/src/client-host-compat.js +150 -0
  192. package/src/client-indicator-view.js +267 -0
  193. package/src/client-repl-view.js +292 -0
  194. package/src/client-rpc.js +20 -0
  195. package/src/client-settings-view.js +221 -0
  196. package/src/client-styles.js +106 -0
  197. package/src/client-tool-view.js +108 -0
  198. package/src/client-transport.js +159 -0
  199. package/src/client-workbench.js +521 -0
  200. package/src/client.js +233 -615
@@ -1,22 +1,17 @@
1
1
  import { assertFields, isRecord } from './record-utils.js'
2
+ import {
3
+ VALUE_CODEC,
4
+ DEFAULT_VALUE_LIMITS,
5
+ VALUE_ENVELOPE_FIELDS as ENVELOPE_FIELDS,
6
+ VALUE_OBJECT_FIELDS as OBJECT_NODE_FIELDS,
7
+ VALUE_ARRAY_FIELDS as ARRAY_NODE_FIELDS,
8
+ VALUE_UNDEFINED_FIELDS as UNDEFINED_FIELDS,
9
+ VALUE_NUMBER_FIELDS as NUMBER_FIELDS,
10
+ VALUE_BIGINT_FIELDS as BIGINT_FIELDS,
11
+ VALUE_REFERENCE_FIELDS as REFERENCE_FIELDS,
12
+ } from './value-wire-schema.js'
2
13
 
3
- export const VALUE_CODEC = 'ptc-value-graph/v1'
4
-
5
- export const DEFAULT_VALUE_LIMITS = Object.freeze({
6
- maxNodes: 100_000,
7
- maxEdges: 1_000_000,
8
- maxArrayLength: 1_000_000,
9
- maxBigIntDigits: 100_000,
10
- maxStringBytes: 64 * 1024 * 1024,
11
- })
12
-
13
- const ENVELOPE_FIELDS = new Set(['codec', 'root', 'nodes'])
14
- const OBJECT_NODE_FIELDS = new Set(['type', 'prototype', 'entries'])
15
- const ARRAY_NODE_FIELDS = new Set(['type', 'length', 'entries'])
16
- const UNDEFINED_FIELDS = new Set(['tag'])
17
- const NUMBER_FIELDS = new Set(['tag', 'value'])
18
- const BIGINT_FIELDS = new Set(['tag', 'value'])
19
- const REFERENCE_FIELDS = new Set(['tag', 'index'])
14
+ export { VALUE_CODEC, DEFAULT_VALUE_LIMITS } from './value-wire-schema.js'
20
15
  const IDENTIFIER = /^[A-Za-z_$][A-Za-z0-9_$]*$/
21
16
 
22
17
  function limitsOf(options = {}) {
@@ -338,7 +333,10 @@ function atomText(atom) {
338
333
  /** Deterministic bounded TS-like presentation. It is never a decode format. */
339
334
  export function renderValueWire(wire, options = {}) {
340
335
  const limits = limitsOf(options)
341
- const normalized = normalizeValueWire(wire, limits)
336
+ return renderCanonicalValue(decodeCanonicalValue(wire, limits).wire, limits)
337
+ }
338
+
339
+ function renderCanonicalValue(normalized, limits) {
342
340
  const references = new Array(normalized.nodes.length).fill(0)
343
341
  const count = (atom) => {
344
342
  if (isRecord(atom) && atom.tag === 'reference') references[atom.index] += 1
@@ -416,6 +414,17 @@ export function renderValueWire(wire, options = {}) {
416
414
  * text. The untagged ranges overlap because a plain JSON root may itself be a string.
417
415
  */
418
416
  export function projectValueWire(wire, options = {}) {
419
- const value = decodeValue(wire, options)
420
- return isPlainJsonTree(value) ? value : renderValueWire(wire, options)
417
+ return prepareValueWire(wire, options).projectedValue
418
+ }
419
+
420
+ /** Validate once when canonical storage and outer presentation are both required. */
421
+ export function prepareValueWire(wire, options = {}) {
422
+ const limits = limitsOf(options)
423
+ const canonical = decodeCanonicalValue(wire, limits)
424
+ return {
425
+ wire: canonical.wire,
426
+ projectedValue: isPlainJsonTree(canonical.value)
427
+ ? canonical.value
428
+ : renderCanonicalValue(canonical.wire, limits),
429
+ }
421
430
  }
@@ -1,65 +1,32 @@
1
1
  import { mkdtemp, rm } from 'node:fs/promises'
2
2
  import { tmpdir } from 'node:os'
3
3
  import { isAbsolute, join } from 'node:path'
4
- import { Worker } from 'node:worker_threads'
5
- import { messageOf } from './failure-reporting.js'
4
+ import { messageOf, processExitDescription } from './failure-reporting.js'
5
+ import { IsolatedOwner } from './isolated-worker.js'
6
+ import { normalizeWorkerEnvironment } from './worker-environment.js'
6
7
 
7
- const WINDOWS_ENVIRONMENT_NAMES = new Map([
8
- ['appdata', 'APPDATA'],
9
- ['comspec', 'ComSpec'],
10
- ['home', 'HOME'],
11
- ['homedrive', 'HOMEDRIVE'],
12
- ['homepath', 'HOMEPATH'],
13
- ['localappdata', 'LOCALAPPDATA'],
14
- ['path', 'PATH'],
15
- ['pathext', 'PATHEXT'],
16
- ['programdata', 'ProgramData'],
17
- ['programfiles', 'ProgramFiles'],
18
- ['programfiles(x86)', 'ProgramFiles(x86)'],
19
- ['systemdrive', 'SystemDrive'],
20
- ['systemroot', 'SystemRoot'],
21
- ['temp', 'TEMP'],
22
- ['tmp', 'TMP'],
23
- ['userprofile', 'USERPROFILE'],
24
- ['windir', 'windir'],
25
- ])
26
- const HOST_ONLY_ENVIRONMENT_NAMES = new Set(['node_test_context', 'node_v8_coverage'])
8
+ export { normalizeWorkerEnvironment }
27
9
 
28
- /** Project the host environment once without losing Windows case variants. */
29
- export function normalizeWorkerEnvironment(source, platform = process.platform) {
30
- if (platform !== 'win32') {
31
- return Object.fromEntries(Object.entries(source).filter(([name, value]) => (
32
- value !== undefined && !HOST_ONLY_ENVIRONMENT_NAMES.has(name.toLowerCase())
33
- )))
34
- }
35
- const normalized = new Map()
36
- for (const [name, value] of Object.entries(source)) {
37
- if (value === undefined) continue
38
- const key = name.toLowerCase()
39
- if (HOST_ONLY_ENVIRONMENT_NAMES.has(key)) continue
40
- const canonicalName = WINDOWS_ENVIRONMENT_NAMES.get(key) ?? name
41
- const current = normalized.get(key)
42
- if (current === undefined || name === canonicalName) {
43
- normalized.set(key, [canonicalName, value])
44
- }
45
- }
46
- return Object.fromEntries(normalized.values())
47
- }
10
+ const KERNEL_HELPER = new URL('./kernel-child.js', import.meta.url)
48
11
 
49
12
  /** Owns one session kernel's worker process, private port, and scratch directory. */
50
13
  export class WorkerClient {
51
- constructor({ workerUrl, cwd, onMessage, onFailure }) {
14
+ constructor({ workerUrl, cwd, onMessage, onFailure, compilerCache }) {
52
15
  this.workerUrl = workerUrl
53
16
  this.cwd = cwd
54
17
  this.onMessage = onMessage
55
18
  this.onFailure = onFailure
19
+ this.compilerCache = compilerCache
56
20
  this.worker = undefined
57
21
  this.workerLimit = undefined
58
22
  this.workerReady = undefined
59
23
  this.port = undefined
60
24
  this.scratchReady = undefined
61
25
  this.stderrTails = new WeakMap()
62
- this.terminations = new Set()
26
+ // One owner keeps every started kernel transport, including startup failures
27
+ // and closes that were refused, until its real exit is observed.
28
+ this.owner = new IsolatedOwner()
29
+ this.hostIds = new WeakMap()
63
30
  this.disposed = false
64
31
  }
65
32
 
@@ -101,19 +68,20 @@ export class WorkerClient {
101
68
  const environment = normalizeWorkerEnvironment(process.env)
102
69
  let worker
103
70
  try {
104
- worker = new Worker(this.workerUrl, {
71
+ const started = this.owner.start({
72
+ helper: KERNEL_HELPER,
73
+ entry: this.workerUrl,
74
+ workerData: { cwd: this.cwd, compilerCache: this.compilerCache?.() },
75
+ resourceLimits: { maxOldGenerationSizeMb: this.workerLimit },
105
76
  env: {
106
77
  ...environment,
107
78
  TEMP: scratchDirectory,
108
79
  TMP: scratchDirectory,
109
80
  TMPDIR: scratchDirectory,
110
81
  },
111
- execArgv: [],
112
- workerData: this.cwd === undefined ? {} : { cwd: this.cwd },
113
- resourceLimits: { maxOldGenerationSizeMb: this.workerLimit },
114
- stdout: true,
115
- stderr: true,
116
82
  })
83
+ worker = started.transport
84
+ this.hostIds.set(worker, started.id)
117
85
  } catch (error) {
118
86
  this.workerLimit = undefined
119
87
  throw error
@@ -129,15 +97,23 @@ export class WorkerClient {
129
97
  })
130
98
  this.stderrTails.set(worker, stderrTail)
131
99
  worker.on('error', error => this.fail(worker, `worker error: ${messageOf(error)}`))
132
- worker.on('exit', code => this.fail(worker, `worker exited with code ${code}`))
100
+ worker.on('exit', (code, signal) => {
101
+ this.fail(worker, `worker exited with ${processExitDescription(code, signal)}`)
102
+ })
133
103
  this.worker = worker
134
104
  this.workerReady = new Promise((resolve, reject) => {
135
- const onError = error => reject(error)
136
- const onExit = (code) => {
105
+ const onError = error => {
137
106
  const detail = this.stderrDetail(worker)
107
+ reject(detail === undefined
108
+ ? error
109
+ : new Error(`${messageOf(error)}; last stderr: ${detail}`, { cause: error }))
110
+ }
111
+ const onExit = (code, signal) => {
112
+ const detail = this.stderrDetail(worker)
113
+ const exit = processExitDescription(code, signal)
138
114
  reject(new Error(detail === undefined
139
- ? `worker exited with code ${code} before opening its private channel`
140
- : `worker exited with code ${code} before opening its private channel; last stderr: ${detail}`))
115
+ ? `worker exited with ${exit} before opening its private channel`
116
+ : `worker exited with ${exit} before opening its private channel; last stderr: ${detail}`))
141
117
  }
142
118
  worker.once('error', onError)
143
119
  worker.once('exit', onExit)
@@ -146,12 +122,16 @@ export class WorkerClient {
146
122
  worker.removeListener('exit', onExit)
147
123
  if (message?.type === 'startup-error' && typeof message.error === 'string') {
148
124
  reject(new Error(message.error))
149
- void this.reset(worker)
125
+ // The owner keeps a refused reclamation, so this must not surface as an
126
+ // unhandled rejection after the caller already handled the startup error.
127
+ void this.reset(worker).catch(() => {})
150
128
  return
151
129
  }
152
130
  if (message?.type !== 'ready' || typeof message.port?.postMessage !== 'function') {
153
131
  reject(new Error('kernel worker returned an invalid private channel'))
154
- void this.reset(worker)
132
+ // The owner keeps a refused reclamation, so this must not surface as an
133
+ // unhandled rejection after the caller already handled the startup error.
134
+ void this.reset(worker).catch(() => {})
155
135
  return
156
136
  }
157
137
  this.port = message.port
@@ -185,27 +165,37 @@ export class WorkerClient {
185
165
  }
186
166
 
187
167
  async reset(worker) {
168
+ const port = this.worker === worker ? this.port : undefined
188
169
  if (this.worker === worker) {
189
170
  this.worker = undefined
190
171
  this.workerLimit = undefined
191
172
  this.workerReady = undefined
192
- this.port?.close()
193
173
  this.port = undefined
194
174
  }
195
- const termination = worker.terminate()
196
- this.terminations.add(termination)
197
- try {
198
- await termination
199
- } finally {
200
- this.terminations.delete(termination)
201
- }
175
+ await this.owner.stop(this.hostIds.get(worker))
176
+ this.hostIds.delete(worker)
177
+ port?.close()
202
178
  }
203
179
 
204
180
  async dispose() {
205
181
  this.disposed = true
206
182
  const worker = this.worker
207
- if (worker !== undefined) await this.reset(worker)
208
- await Promise.all([...this.terminations])
183
+ const port = this.port
184
+ this.worker = undefined
185
+ this.workerLimit = undefined
186
+ this.workerReady = undefined
187
+ this.port = undefined
188
+ if (worker !== undefined) this.hostIds.delete(worker)
189
+ const failures = []
190
+ try {
191
+ port?.close()
192
+ } catch (error) {
193
+ failures.push(error)
194
+ }
195
+ failures.push(...await this.owner.dispose())
196
+ if (failures.length > 0) {
197
+ throw new AggregateError(failures, 'ptc-plus kernel worker disposal failed')
198
+ }
209
199
  if (this.scratchReady !== undefined) {
210
200
  try {
211
201
  const scratchDirectory = await this.scratchReady
@@ -0,0 +1,45 @@
1
+ const WINDOWS_ENVIRONMENT_NAMES = new Map([
2
+ ['appdata', 'APPDATA'],
3
+ ['comspec', 'ComSpec'],
4
+ ['home', 'HOME'],
5
+ ['homedrive', 'HOMEDRIVE'],
6
+ ['homepath', 'HOMEPATH'],
7
+ ['localappdata', 'LOCALAPPDATA'],
8
+ ['path', 'PATH'],
9
+ ['pathext', 'PATHEXT'],
10
+ ['programdata', 'ProgramData'],
11
+ ['programfiles', 'ProgramFiles'],
12
+ ['programfiles(x86)', 'ProgramFiles(x86)'],
13
+ ['systemdrive', 'SystemDrive'],
14
+ ['systemroot', 'SystemRoot'],
15
+ ['temp', 'TEMP'],
16
+ ['tmp', 'TMP'],
17
+ ['userprofile', 'USERPROFILE'],
18
+ ['windir', 'windir'],
19
+ ])
20
+ export const HOST_ONLY_ENVIRONMENT_NAMES = new Set([
21
+ 'node_test_context',
22
+ 'node_v8_coverage',
23
+ 'dsh_ptc_compiler_bytecode',
24
+ ])
25
+
26
+ /** Project the host environment once without losing Windows case variants. */
27
+ export function normalizeWorkerEnvironment(source, platform = process.platform) {
28
+ if (platform !== 'win32') {
29
+ return Object.fromEntries(Object.entries(source).filter(([name, value]) => (
30
+ value !== undefined && !HOST_ONLY_ENVIRONMENT_NAMES.has(name.toLowerCase())
31
+ )))
32
+ }
33
+ const normalized = new Map()
34
+ for (const [name, value] of Object.entries(source)) {
35
+ if (value === undefined) continue
36
+ const key = name.toLowerCase()
37
+ if (HOST_ONLY_ENVIRONMENT_NAMES.has(key)) continue
38
+ const canonicalName = WINDOWS_ENVIRONMENT_NAMES.get(key) ?? name
39
+ const current = normalized.get(key)
40
+ if (current === undefined || name === canonicalName) {
41
+ normalized.set(key, [canonicalName, value])
42
+ }
43
+ }
44
+ return Object.fromEntries(normalized.values())
45
+ }
@@ -0,0 +1,29 @@
1
+ /** Forward one worker output stream while honoring destination backpressure. */
2
+ export function relayWorkerOutput(source, destination) {
3
+ if (source === null || source === undefined) return Promise.resolve()
4
+ return new Promise((resolve, reject) => {
5
+ let ended = false
6
+ let pending = 0
7
+ let settled = false
8
+ let failure
9
+ const finish = error => {
10
+ if (error !== undefined) failure ??= error
11
+ if (settled || (!ended && failure === undefined) || pending > 0) return
12
+ settled = true
13
+ if (failure === undefined) resolve()
14
+ else reject(failure)
15
+ }
16
+ source.on('data', chunk => {
17
+ source.pause()
18
+ pending += 1
19
+ destination.write(chunk, error => {
20
+ pending -= 1
21
+ if (error !== null && error !== undefined) { finish(error); return }
22
+ if (failure === undefined) source.resume()
23
+ finish()
24
+ })
25
+ })
26
+ source.once('end', () => { ended = true; finish() })
27
+ source.once('error', error => { ended = true; finish(error) })
28
+ })
29
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Shutdown protocol shared by the plugin's worker entries.
3
+ *
4
+ * Each worker entry releases the machinery it owns when it receives the request
5
+ * and reports that release with the acknowledgement. The release, the real exit
6
+ * and the kill bound belong to the helper process boundary in
7
+ * isolated-worker.js; these two constants are the only part the worker entries
8
+ * themselves need.
9
+ */
10
+
11
+ /** Request that asks one worker to release everything it owns and stop. */
12
+ export const WORKER_SHUTDOWN_REQUEST = 'shutdown'
13
+ /** Reply a worker posts after releasing its own machinery, before it exits. */
14
+ export const WORKER_SHUTDOWN_ACKNOWLEDGEMENT = 'shutdown-released'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-ptc-plus",
3
- "version": "0.3.1",
3
+ "version": "0.4.1",
4
4
  "description": "A session-bound agent-native REPL for DeepSeek Harness PTC mode.",
5
5
  "type": "module",
6
6
  "main": "./index.js",
@@ -12,13 +12,27 @@
12
12
  "files": [
13
13
  "index.js",
14
14
  "client.js",
15
+ "compiler-core.cjs",
16
+ "compiler-core.cjs.map",
17
+ "compiler-platform.cjs",
18
+ "compiler-platform.cjs.map",
19
+ "compiler-typescript.cjs",
20
+ "compiler-typescript.cjs.map",
21
+ "compiler-amaro.cjs",
22
+ "compiler-amaro.cjs.map",
23
+ "compiler-assets.json",
24
+ "compiler-asset-*.txt",
15
25
  "src",
16
26
  "internal",
17
27
  "docs",
18
28
  "assets/dsh-ptc-plus-banner-en.webp",
19
29
  "assets/dsh-ptc-plus-banner-zh.webp",
30
+ "assets/ptc-plus-bindings-en.png",
31
+ "assets/ptc-plus-bindings-zh.png",
20
32
  "assets/ptc-plus-repair-zh.png",
21
33
  "assets/ptc-plus-repair-en.png",
34
+ "assets/ptc-plus-repl-workspace-en.png",
35
+ "assets/ptc-plus-repl-workspace-zh.png",
22
36
  "assets/ptc-plus-settings-en.png",
23
37
  "assets/ptc-plus-settings-zh.png",
24
38
  "cordis.patch.yml",
@@ -34,28 +48,55 @@
34
48
  },
35
49
  "dependencies": {
36
50
  "@babel/code-frame": "^7.29.7",
51
+ "@babel/core": "^7.29.7",
52
+ "@babel/generator": "^7.29.8",
53
+ "@babel/helper-create-class-features-plugin": "^7.29.7",
37
54
  "@babel/parser": "^7.29.0",
55
+ "@babel/plugin-proposal-decorators": "^7.29.7",
56
+ "@babel/plugin-transform-explicit-resource-management": "^7.29.7",
57
+ "@babel/plugin-transform-optional-chaining": "^7.29.7",
58
+ "@babel/plugin-transform-typescript": "^7.29.7",
38
59
  "@babel/traverse": "^7.29.0",
60
+ "@codemirror/lang-javascript": "^6.2.5",
61
+ "@codemirror/language": "^6.12.4",
62
+ "@codemirror/state": "^6.7.4",
63
+ "@codemirror/view": "^6.43.11",
39
64
  "@deepseek-ai/schemastery": "^3.18.1",
40
- "acorn": "^8.15.0"
65
+ "@jridgewell/trace-mapping": "^0.3.31",
66
+ "@lezer/highlight": "^1.2.3",
67
+ "acorn": "^8.15.0",
68
+ "amaro": "1.1.11",
69
+ "codemirror": "^6.0.2",
70
+ "fflate": "^0.8.3",
71
+ "pathe": "^2.0.3",
72
+ "tslib": "^2.8.1",
73
+ "typescript": "^6.0.3"
41
74
  },
42
75
  "peerDependencies": {
76
+ "@deepseek-ai/dsh-atomic-write": "*",
77
+ "@deepseek-ai/dsh-home-paths": "*",
78
+ "@deepseek-ai/dsh-llm": "*",
43
79
  "@deepseek-ai/dsh-settings": "*",
44
80
  "@deepseek-ai/dsh-skill-filesystem": "*",
45
81
  "@deepseek-ai/dsh-tool-cordis": "*",
46
- "@deepseek-ai/dsh-tools": "*"
82
+ "@deepseek-ai/dsh-tools": "*",
83
+ "@deepseek-ai/dsh-typert-protocol": "*"
47
84
  },
48
85
  "scripts": {
49
- "build": "node scripts/client-bundle.mjs build",
50
- "build:check": "node scripts/client-bundle.mjs check",
86
+ "build": "node scripts/client-bundle.mjs build && node scripts/compiler-bundle.mjs build",
87
+ "build:check": "node scripts/client-bundle.mjs check && node scripts/compiler-bundle.mjs check",
88
+ "test:client": "vitest run --config scripts/client-test.config.mjs",
89
+ "test:semantics": "node --test --test-concurrency=1 test/semantic-test262.test.js test/semantic-dialect.test.js test/semantic-boundaries.test.js",
90
+ "test:client:web": "node scripts/client-web-smoke.mjs",
91
+ "test:client:layout": "node scripts/client-binding-layout.mjs",
51
92
  "prepack": "npm run build:check",
52
93
  "hooks:install": "node scripts/review-findings.mjs install-hook",
53
94
  "review:new": "node scripts/review-findings.mjs create",
54
95
  "review:validate": "node scripts/review-findings.mjs validate",
55
96
  "review:gate": "node scripts/review-findings.mjs gate",
56
97
  "session:migrate": "node scripts/migrate-session-log.mjs",
57
- "coverage": "node --test --experimental-test-module-mocks --experimental-test-coverage --test-concurrency=1 --test-coverage-include=\"index.js\" --test-coverage-include=\"internal/*.js\" --test-coverage-lines=100 --test-coverage-branches=95 --test-coverage-functions=100 \"test/*.test.js\"",
58
- "verify": "npm run review:validate && npm run build:check && node --check index.js && node --check internal/kernel-worker.js && node --check scripts/migrate-session-log.mjs && node --check scripts/expensive-headless-acceptance.mjs && node --check scripts/ab-headless-trajectories.mjs && npm run coverage",
98
+ "coverage": "node scripts/coverage.mjs",
99
+ "verify": "npm run review:validate && npm run build:check && node --check index.js && node --check internal/kernel-worker.js && node --check scripts/migrate-session-log.mjs && node --check scripts/expensive-headless-acceptance.mjs && node --check scripts/ab-headless-trajectories.mjs && npm run test:client && npm run coverage",
59
100
  "check": "node scripts/review-findings.mjs check",
60
101
  "test:expensive": "node scripts/expensive-headless-acceptance.mjs",
61
102
  "test:ab": "node scripts/ab-headless-trajectories.mjs"
@@ -87,21 +128,50 @@
87
128
  "react"
88
129
  ],
89
130
  "inject": [
131
+ "@deepseek-ai/dsh-api-gateway",
132
+ "@deepseek-ai/dsh-api-remotes",
90
133
  "@deepseek-ai/dsh-client-runtime",
91
134
  "@deepseek-ai/dsh-client-locale",
92
135
  "@deepseek-ai/dsh-client-ui-settings",
93
136
  "@deepseek-ai/dsh-client-ui-settings-plugins",
137
+ "@deepseek-ai/dsh-client-ui-conversation",
94
138
  "@deepseek-ai/dsh-client-connection",
95
139
  "@deepseek-ai/dsh-client-ui-primitives"
96
140
  ]
97
141
  }
98
142
  },
99
143
  "devDependencies": {
100
- "@deepseek-ai/dsh-settings": "alpha",
101
- "@deepseek-ai/dsh-skill-filesystem": "alpha",
102
- "@deepseek-ai/dsh-tool-cordis": "alpha",
103
- "@deepseek-ai/dsh-tools": "alpha",
144
+ "@deepseek-ai/dsh-agent-loop": "next",
145
+ "@deepseek-ai/dsh-api-gateway": "next",
146
+ "@deepseek-ai/dsh-api-remotes": "next",
147
+ "@deepseek-ai/dsh-atomic-write": "next",
148
+ "@deepseek-ai/dsh-client-locale": "next",
149
+ "@deepseek-ai/dsh-client-store": "next",
150
+ "@deepseek-ai/dsh-client-test-runtime": "next",
151
+ "@deepseek-ai/dsh-client-ui-conversation": "next",
152
+ "@deepseek-ai/dsh-client-ui-primitives": "next",
153
+ "@deepseek-ai/dsh-client-ui-renderer": "next",
154
+ "@deepseek-ai/dsh-client-ui-session": "next",
155
+ "@deepseek-ai/dsh-client-ui-slots": "next",
156
+ "@deepseek-ai/dsh-commands": "next",
157
+ "@deepseek-ai/dsh-home-paths": "next",
158
+ "@deepseek-ai/dsh-llm": "next",
159
+ "@deepseek-ai/dsh-session-persistence-jsonl": "next",
160
+ "@deepseek-ai/dsh-settings": "next",
161
+ "@deepseek-ai/dsh-skill-filesystem": "next",
162
+ "@deepseek-ai/dsh-tool-cordis": "next",
163
+ "@deepseek-ai/dsh-tools": "next",
164
+ "@deepseek-ai/dsh-typert-protocol": "next",
165
+ "@deepseek-ai/dsh-typert-registry": "next",
166
+ "@testing-library/react": "^16.3.3",
167
+ "c8": "^12.0.0",
168
+ "convert-source-map": "^2.0.0",
104
169
  "esbuild": "0.28.2",
170
+ "jsdom": "^29.1.1",
171
+ "playwright": "^1.63.0",
172
+ "react": "^18.3.1",
173
+ "react-dom": "^18.3.1",
174
+ "vitest": "^5.0.0",
105
175
  "yaml": "^2.9.0"
106
176
  }
107
177
  }