refactor(web): trim unrelated changes from Safari recovery fix

This commit is contained in:
gengruilin committed 2026-09-28 12:00:35 +08:00
1 parent aee3c39ee7
commit 9925ba721d
16 files changed
+20 -55

No files matched your search

+1 -1
View File
@@ -61,7 +61,7 @@
"electron-builder": "^26.15.3",
"extract-zip": "^2.0.1",
"js-yaml": "^4.2.0",
"koffi": "3.1.1",
"koffi": "^3.1.0",
"pnpm": "11.7.0",
"sharp": "^0.35.3",
"typescript": "^6.0.3",
-1
View File
@@ -122,7 +122,6 @@ describe('web e2e: requested SVG is explicitly delivered', () => {
expect(await page.getByText('产物', { exact: true }).count()).toBe(0)
// The scaffold workspace is not a git repository; the write call supplies its single changed file.
const changes = page.locator('[data-changed-files]')
await changes.waitFor({ state: 'visible' })
expect(await changes.count()).toBe(1)
expect(await changes.getByText(`已编辑 ${FILE}`, { exact: true }).count()).toBe(1)
expect(await changes.getByRole('list').count()).toBe(0)
@@ -21,8 +21,8 @@
en: 0be8b7f1580ca751
zh: 984c4757e9d6e094
/deepseek-ai-dsh-cordis-host-runner/use-this-package/what-a-run-does:
en: b904b715d5782825
zh: f1df53d98ced62d4
en: a3c86c081974a710
zh: 180e1b7824c070d4
/deepseek-ai-dsh-cordis-host-runner/use-this-package/what-happens-to-definitions:
en: d1a8777f171d22bb
zh: 7f6aa4c2680557b1
@@ -45,8 +45,6 @@ The generated [configuration catalog](../../../docs/config-catalog.md#deepseek-a
Programmatic callers use `define`, `run`, `stop`, and `undefine`; the browser panel operates existing definitions. Host-only packages activate in this process. A package with a browser half waits for approval or cancellation, then loads Host before Client. `mode: "run"` starts the current version; `mode: "update"` replaces it. Stop disposes the live effects and retains the definition; undefine also forgets it.
Dynamic tool schemas and JSON return values recognize intrinsic containers across realms using the current engine’s native constructor representation; return values are copied into the Host realm, and class instances and forged prototypes are rejected.
### What happens to definitions
Definitions are session-scoped and process-local: other sessions read them as absent, and restart clears them. Historical logs retain tool arguments and receipts but do not restore the registry. Reloading a browser page requires another explicit run to load its Client half.
@@ -45,8 +45,6 @@ kind: "package-reference"
程序调用方使用 `define`、`run`、`stop` 和 `undefine`;浏览器面板操作已有定义。仅含 Host 的包在本进程激活。带浏览器部分的包等待审批或取消,批准后先加载 Host 再加载 Client。`mode: "run"` 启动当前版本,`mode: "update"` 替换版本。Stop 释放运行中的 effect 并保留定义;undefine 还会移除定义。
动态工具的 schema 与 JSON 返回值使用当前引擎的原生构造器表示识别跨 realm 的内建容器;返回值会复制到 Host realm,类实例与伪造原型会被拒绝。
### 定义的去向
定义按会话隔离且仅在进程内存在:其他会话无法读取,重启会清空。历史日志保留工具参数和回执,但不会恢复注册表。浏览器页面重载后,需要再次显式运行才能加载 Client 部分。
@@ -38,8 +38,8 @@ function isPlainRecord(value: unknown): value is Record<string, unknown> {
&& hasIntrinsicConstructor(prototype, 'Object')
}
/* jscpd:ignore-start -- sandbox containers share util-values' intrinsic-prototype checks */
/** Whether a realm-owned intrinsic prototype has a native constructor matching this engine's representation. */
/* jscpd:ignore-start -- Node/V8 VM containers use native constructor text and intrinsic-prototype checks */
/** Whether a realm-owned intrinsic prototype is backed by its native constructor. */
function hasIntrinsicConstructor(prototype: object, name: 'Array' | 'Object'): boolean {
const descriptor = Object.getOwnPropertyDescriptor(prototype, 'constructor')
const constructor: unknown = descriptor?.value
@@ -47,7 +47,7 @@ function hasIntrinsicConstructor(prototype: object, name: 'Array' | 'Object'): b
try {
return constructor.name === name
&& constructor.prototype === prototype
&& Function.prototype.toString.call(constructor) === Function.prototype.toString.call(name === 'Array' ? Array : Object)
&& Function.prototype.toString.call(constructor) === `function ${name}() { [native code] }`
} catch {
return false
}
@@ -1,4 +1,3 @@
import { runInNewContext } from 'node:vm'
import { describe, expect, it, vi } from 'vitest'
import { sandboxDefineTool } from '../src/guard.ts'
import { syntaxErrorContext } from '../src/sandbox.ts'
@@ -13,35 +12,6 @@ import { AGENT_A, call, CONTENT_OUTPUT_CODE, mount, setup, text, running } from
*/
describe('dynamic tool declaration boundary', () => {
it('accepts dynamic schemas and renderer values with WebKit native constructor formatting', () => {
const foreign = runInNewContext(`({ Object, Array, options: {
name: 'sample', description: 'sample',
parameters: { value: { type: 'string', enum: ['x'] } },
output: { schema: { type: 'string' }, render: () => [{ type: 'text', text: 'ok' }] },
execute: async () => 'ok',
} })`) as { Object: ObjectConstructor; Array: ArrayConstructor; options: Record<string, unknown> }
const originalDescriptor = Object.getOwnPropertyDescriptor(Function.prototype, 'toString')!
const originalToString = originalDescriptor.value as (this: unknown) => string
const toString = vi.spyOn(Function.prototype, 'toString').mockImplementation(function (this: unknown) {
if (this === Object || this === foreign.Object) return 'function Object() {\n [native code]\n}'
if (this === Array || this === foreign.Array) return 'function Array() {\n [native code]\n}'
return originalToString.call(this)
})
try {
for (const options of [foreign.options, { ...foreign.options }]) {
const definition = sandboxDefineTool(options)
expect(definition.parameters.properties).toEqual({ value: { type: 'string', enum: ['x'] } })
const rendered = definition.output.render({ value: 'x' }, 'ok')
expect(rendered).toEqual([{ type: 'text', text: 'ok' }])
expect(Object.getPrototypeOf(rendered)).toBe(Array.prototype)
}
expect(() => sandboxDefineTool(new Date(0))).toThrow('options must be an object')
} finally {
toString.mockRestore()
}
expect(Object.getOwnPropertyDescriptor(Function.prototype, 'toString')).toEqual(originalDescriptor)
})
it.each([
[42, 'options must be an object'],
[{ parameters: {} }, 'output must declare { schema, render, presentationMeta? }'],
+1 -1
View File
@@ -32,7 +32,7 @@
},
"dependencies": {
"chokidar": "^4.0.3",
"koffi": "3.1.1",
"koffi": "^3.1.0",
"@deepseek-ai/schemastery": "workspace:~"
},
"devDependencies": {
@@ -34,7 +34,7 @@
"dependencies": {
"@deepseek-ai/dsh-host-directory-picker": "workspace:*",
"@deepseek-ai/dsh-native-command": "workspace:*",
"koffi": "3.1.1"
"koffi": "^3.1.0"
},
"peerDependencies": {
"@deepseek-ai/cordis": "workspace:~"
@@ -79,7 +79,7 @@ function setDelete<T>(target: Set<T>, value: T): void {
intrinsicReflectApply(intrinsicSetDelete, target, [value])
}
/** Check Node/V8's native constructor text through intrinsics captured before model code runs. */
/** Whether a realm-owned intrinsic prototype is backed by its native constructor. */
function hasIntrinsicConstructor(prototype: object, name: 'Array' | 'Object'): boolean {
const descriptor = intrinsicObjectGetOwnPropertyDescriptor(prototype, 'constructor')
const constructor: unknown = descriptor?.value
@@ -39,7 +39,7 @@
"dependencies": {
"@deepseek-ai/dsh-lazy-require": "workspace:*",
"@deepseek-ai/dsh-win32-process": "workspace:*",
"koffi": "3.1.1"
"koffi": "^3.1.0"
},
"devDependencies": {
"@deepseek-ai/dsh-pwsh-local": "workspace:*",
@@ -39,7 +39,7 @@
"@deepseek-ai/dsh-session-format-v3-to-v4": "workspace:*",
"@deepseek-ai/node-addon-system": "workspace:~",
"@deepseek-ai/schemastery": "workspace:~",
"koffi": "3.1.1"
"koffi": "^3.1.0"
},
"devDependencies": {
"@deepseek-ai/dsh-session": "workspace:*",
@@ -49,7 +49,7 @@
"dependencies": {
"@deepseek-ai/dsh-lazy-require": "workspace:*",
"@deepseek-ai/dsh-win32-process": "workspace:*",
"koffi": "3.1.1",
"koffi": "^3.1.0",
"node-pty": "1.2.0-beta.15"
},
"devDependencies": {
@@ -31,7 +31,7 @@
},
"dependencies": {
"@deepseek-ai/dsh-lazy-require": "workspace:*",
"koffi": "3.1.1"
"koffi": "^3.1.0"
},
"devDependencies": {
"@deepseek-ai/cordis": "workspace:~"
+7 -7
View File
@@ -667,7 +667,7 @@ importers:
specifier: ^4.2.0
version: 4.3.1
koffi:
specifier: 3.1.1
specifier: ^3.1.0
version: 3.1.1
pnpm:
specifier: 11.7.0
@@ -8389,7 +8389,7 @@ importers:
specifier: ^4.0.3
version: 4.0.3
koffi:
specifier: 3.1.1
specifier: ^3.1.0
version: 3.1.1
devDependencies:
'@deepseek-ai/cordis':
@@ -8991,7 +8991,7 @@ importers:
specifier: workspace:*
version: link:../../util/native-command
koffi:
specifier: 3.1.1
specifier: ^3.1.0
version: 3.1.1
devDependencies:
'@deepseek-ai/cordis':
@@ -10279,7 +10279,7 @@ importers:
specifier: workspace:*
version: link:../../subprocess/win32-process
koffi:
specifier: 3.1.1
specifier: ^3.1.0
version: 3.1.1
devDependencies:
'@deepseek-ai/cordis':
@@ -10889,7 +10889,7 @@ importers:
specifier: link:../../../vendor/schemastery
version: link:../../../vendor/schemastery
koffi:
specifier: 3.1.1
specifier: ^3.1.0
version: 3.1.1
devDependencies:
'@deepseek-ai/cordis':
@@ -12746,7 +12746,7 @@ importers:
specifier: workspace:*
version: link:../win32-process
koffi:
specifier: 3.1.1
specifier: ^3.1.0
version: 3.1.1
node-pty:
specifier: 1.2.0-beta.15
@@ -12771,7 +12771,7 @@ importers:
specifier: workspace:*
version: link:../../util/lazy-require
koffi:
specifier: 3.1.1
specifier: ^3.1.0
version: 3.1.1
devDependencies:
'@deepseek-ai/cordis':