@anionex/dsh-computer-use 0.3.2 → 0.3.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/README.md +4 -1
  3. package/README.zh.md +4 -1
  4. package/lib/client.js +1 -1
  5. package/lib/client.js.map +1 -1
  6. package/lib/config.js +37 -17
  7. package/lib/config.js.map +1 -1
  8. package/lib/confirmations.js.map +1 -1
  9. package/lib/exposure.js +4 -4
  10. package/lib/exposure.js.map +1 -1
  11. package/lib/index.js +5 -1
  12. package/lib/index.js.map +1 -1
  13. package/lib/leases.js.map +1 -1
  14. package/lib/providers/macos.js +27 -11
  15. package/lib/providers/macos.js.map +1 -1
  16. package/lib/skill.js +13 -2
  17. package/lib/skill.js.map +1 -1
  18. package/lib/tools.js +1 -1
  19. package/lib/tools.js.map +1 -1
  20. package/lib/types/client/index.d.ts +1 -1
  21. package/lib/types/client/index.d.ts.map +1 -1
  22. package/lib/types/config.d.ts +2 -0
  23. package/lib/types/config.d.ts.map +1 -1
  24. package/lib/types/confirmations.d.ts +1 -1
  25. package/lib/types/confirmations.d.ts.map +1 -1
  26. package/lib/types/index.d.ts.map +1 -1
  27. package/lib/types/leases.d.ts +2 -1
  28. package/lib/types/leases.d.ts.map +1 -1
  29. package/lib/types/providers/macos.d.ts +0 -1
  30. package/lib/types/providers/macos.d.ts.map +1 -1
  31. package/lib/types/skill.d.ts +7 -2
  32. package/lib/types/skill.d.ts.map +1 -1
  33. package/lib/types/tools.d.ts.map +1 -1
  34. package/lib/types/types.d.ts +3 -1
  35. package/lib/types/types.d.ts.map +1 -1
  36. package/lib/types/web.d.ts +2 -1
  37. package/lib/types/web.d.ts.map +1 -1
  38. package/lib/types.js.map +1 -1
  39. package/lib/web.js +18 -8
  40. package/lib/web.js.map +1 -1
  41. package/native/macos/Sources/Helper/CursorOverlay.swift +3 -0
  42. package/native/macos/Sources/Helper/main.swift +35 -19
  43. package/native/macos/bin/dsh-computer-use-helper +0 -0
  44. package/native/macos/manifest.json +3 -3
  45. package/package.json +64 -24
  46. package/scripts/model-e2e.mjs +7 -3
  47. package/scripts/session-transcript.mjs +4 -3
  48. package/src/client/index.tsx +4 -2
  49. package/src/config.ts +40 -18
  50. package/src/confirmations.ts +1 -1
  51. package/src/exposure.ts +5 -5
  52. package/src/index.ts +5 -1
  53. package/src/leases.ts +3 -2
  54. package/src/providers/macos.ts +31 -11
  55. package/src/skill.ts +14 -2
  56. package/src/tools.ts +3 -2
  57. package/src/types.ts +2 -1
  58. package/src/web.ts +21 -6
package/lib/web.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"web.js","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"web.js","sourceRoot":"","sources":["../src/web.ts"],"names":[],"mappings":"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"}
@@ -204,6 +204,9 @@ private final class CursorOverlayController: NSObject {
204
204
  window.isOpaque = false
205
205
  window.backgroundColor = .clear
206
206
  window.hasShadow = false
207
+ // Target loss must remove the indicator immediately, without AppKit's
208
+ // panel fade leaving it visible over an unrelated foreground app.
209
+ window.animationBehavior = .none
207
210
  window.ignoresMouseEvents = true
208
211
  window.hidesOnDeactivate = false
209
212
  window.becomesKeyOnlyIfNeeded = true
@@ -6,7 +6,7 @@ import Darwin
6
6
  import Foundation
7
7
  import ScreenCaptureKit
8
8
 
9
- private let helperVersion = "0.3.2"
9
+ private let helperVersion = "0.3.3"
10
10
 
11
11
  private struct HelperError: Error {
12
12
  let code: String
@@ -501,22 +501,27 @@ private func captureWindow(_ snapshot: ObservationSnapshot, path: String, requir
501
501
  return nil
502
502
  }
503
503
  let expectedId = (snapshot.windowJSON?["id"] as? NSNumber)?.uint32Value
504
- let expectedTitle = snapshot.windowJSON?["title"] as? String
504
+ let expectedFrame = (snapshot.windowJSON?["frame"] as? [String: Any]).flatMap { try? cgRect($0) }
505
505
  let windows = content.windows.filter { $0.owningApplication?.processID == snapshot.app.processIdentifier }
506
506
  let selected = windows.first { window in
507
- if let expectedId, window.windowID == expectedId { return true }
508
- if let expectedTitle, !expectedTitle.isEmpty, window.title == expectedTitle { return true }
509
- return false
510
- } ?? windows.max { $0.frame.width * $0.frame.height < $1.frame.width * $1.frame.height }
507
+ if let expectedId { return window.windowID == expectedId }
508
+ guard let expectedFrame else { return false }
509
+ let tolerance: CGFloat = 2
510
+ return abs(window.frame.minX - expectedFrame.minX) <= tolerance
511
+ && abs(window.frame.minY - expectedFrame.minY) <= tolerance
512
+ && abs(window.frame.width - expectedFrame.width) <= tolerance
513
+ && abs(window.frame.height - expectedFrame.height) <= tolerance
514
+ }
511
515
  guard let selected else {
512
- if required { throw fail("COMPUTER_TARGET_UNAVAILABLE", "no capturable window belongs to the selected application") }
516
+ if required { throw fail("COMPUTER_TARGET_UNAVAILABLE", "the observed window is not available for capture") }
513
517
  return nil
514
518
  }
519
+ let filter = SCContentFilter(desktopIndependentWindow: selected)
515
520
  let configuration = SCStreamConfiguration()
516
- configuration.width = max(1, Int(selected.frame.width.rounded()))
517
- configuration.height = max(1, Int(selected.frame.height.rounded()))
521
+ let pixelScale = CGFloat(filter.pointPixelScale)
522
+ configuration.width = max(1, Int((selected.frame.width * pixelScale).rounded()))
523
+ configuration.height = max(1, Int((selected.frame.height * pixelScale).rounded()))
518
524
  configuration.showsCursor = false
519
- let filter = SCContentFilter(desktopIndependentWindow: selected)
520
525
  let image: CGImage
521
526
  do {
522
527
  image = try await SCScreenshotManager.captureImage(contentFilter: filter, configuration: configuration)
@@ -583,25 +588,36 @@ private func cgRect(_ frame: [String: Any]) throws -> CGRect {
583
588
 
584
589
  private func windowAtPoint(app: NSRunningApplication, point: CGPoint) throws -> (windowNumber: Int64, frame: CGRect) {
585
590
  guard let windows = CGWindowListCopyWindowInfo(
586
- [.optionOnScreenOnly, .excludeDesktopElements],
591
+ [.optionAll, .excludeDesktopElements],
587
592
  kCGNullWindowID
588
593
  ) as? [[String: Any]] else {
589
594
  throw fail("COMPUTER_TARGET_UNAVAILABLE", "CoreGraphics window list is unavailable")
590
595
  }
591
- // CGWindowListCopyWindowInfo orders on-screen windows front to back, so the
592
- // first match is the topmost window of the selected app at the point.
593
- guard let window = windows.first(where: { candidate in
596
+ let appWindows = windows.filter { candidate in
594
597
  guard (candidate[kCGWindowOwnerPID as String] as? NSNumber)?.int32Value == app.processIdentifier,
595
- (candidate[kCGWindowLayer as String] as? NSNumber)?.intValue == 0,
596
- let bounds = candidate[kCGWindowBounds as String] as? [String: Any],
597
- let frame = CGRect(dictionaryRepresentation: bounds as CFDictionary),
598
- frame.contains(point) else { return false }
598
+ (candidate[kCGWindowLayer as String] as? NSNumber)?.intValue == 0 else { return false }
599
599
  return true
600
+ }
601
+ let containing = appWindows.filter { candidate in
602
+ guard let bounds = candidate[kCGWindowBounds as String] as? [String: Any],
603
+ let frame = CGRect(dictionaryRepresentation: bounds as CFDictionary) else { return false }
604
+ return frame.contains(point)
605
+ }
606
+ // optionAll can recover windows omitted by optionOnScreenOnly on some
607
+ // multi-display layouts. Never route pointer input to a hidden window.
608
+ guard let window = containing.first(where: {
609
+ ($0[kCGWindowIsOnscreen as String] as? NSNumber)?.boolValue == true
600
610
  }),
601
611
  let windowNumber = (window[kCGWindowNumber as String] as? NSNumber)?.int64Value,
602
612
  let bounds = window[kCGWindowBounds as String] as? [String: Any],
603
613
  let frame = CGRect(dictionaryRepresentation: bounds as CFDictionary) else {
604
- throw fail("COMPUTER_TARGET_UNAVAILABLE", "no on-screen window of the selected app contains the requested coordinate")
614
+ if !containing.isEmpty {
615
+ throw fail("COMPUTER_TARGET_UNAVAILABLE", "the selected app window contains the coordinate but CoreGraphics does not mark it on-screen")
616
+ }
617
+ if appWindows.isEmpty {
618
+ throw fail("COMPUTER_TARGET_UNAVAILABLE", "the selected app has no enumerable layer-zero window in CoreGraphics")
619
+ }
620
+ throw fail("COMPUTER_TARGET_UNAVAILABLE", "coordinate is outside the selected app's enumerable windows")
605
621
  }
606
622
  return (windowNumber, frame)
607
623
  }
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "helperVersion": "0.3.2",
4
- "sourceSha256": "d2e06ecd7ce38128a9e376e6f48add51e6df4fd138719902cd92cbfe9f16f344",
3
+ "helperVersion": "0.3.3",
4
+ "sourceSha256": "b5de65a33e53689c5b490d8f6641a6577ba61a6f6f45798210b0df65bd0ced07",
5
5
  "binary": {
6
6
  "path": "bin/dsh-computer-use-helper",
7
- "sha256": "4ee97330877ab794122e5caf10b5ff3e4edbc23578b4188311928e596a37237b",
7
+ "sha256": "55325e0008d755bf2b1d408bcfd5cdb80842ec2a0fa5312da6961eb65d7d6dd3",
8
8
  "architectures": [
9
9
  "arm64",
10
10
  "x86_64"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anionex/dsh-computer-use",
3
- "version": "0.3.2",
3
+ "version": "0.3.3",
4
4
  "description": "Accessibility-first macOS Computer Use capability for DeepSeek Harness with stale-observation protection, app leases, confirmations, screenshots, and Web diagnostics",
5
5
  "keywords": [
6
6
  "deepseek",
@@ -56,7 +56,8 @@
56
56
  "cordis.patch.yml",
57
57
  "README.md",
58
58
  "README.zh.md",
59
- "LICENSE"
59
+ "LICENSE",
60
+ "CHANGELOG.md"
60
61
  ],
61
62
  "scripts": {
62
63
  "native:build": "node scripts/build-native.mjs",
@@ -87,7 +88,7 @@
87
88
  "platform": "web"
88
89
  },
89
90
  "compatibility": {
90
- "dsh": ">=0.1.0-rc.8 <0.2.0 || >=0.1.1-rc.1 <0.2.0 || >=0.1.2-alpha.3 <0.2.0 || >=0.1.5-rc.1 <0.2.0",
91
+ "dsh": ">=0.1.0-rc.8 <0.2.0 || >=0.1.1-rc.1 <0.2.0 || >=0.1.2-alpha.3 <0.2.0 || >=0.1.5-rc.1 <0.2.0 || 0.1.7-rc.2 || 0.2.0-rc.2",
91
92
  "dshReleases": {
92
93
  "0.1.0-rc.8": "compatible",
93
94
  "0.1.1-rc.1": "compatible",
@@ -97,7 +98,9 @@
97
98
  "0.1.2-alpha.5": "compatible",
98
99
  "0.1.5-alpha.1": "compatible",
99
100
  "0.1.5-alpha.2": "compatible",
100
- "0.1.5-rc.1": "compatible"
101
+ "0.1.5-rc.1": "compatible",
102
+ "0.1.7-rc.2": "compatible",
103
+ "0.2.0-rc.2": "compatible"
101
104
  },
102
105
  "profiles": [
103
106
  "web"
@@ -105,26 +108,27 @@
105
108
  }
106
109
  },
107
110
  "peerDependencies": {
108
- "@deepseek-ai/dsh-agent": "^0.1.0-rc.6",
109
- "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6",
110
- "@deepseek-ai/dsh-brand": "^0.1.0-rc.6",
111
- "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6",
112
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
113
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6",
114
- "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
115
- "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
116
- "@deepseek-ai/dsh-llm": "^0.1.0-rc.6",
117
- "@deepseek-ai/dsh-session": "^0.1.0-rc.6",
118
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
119
- "@deepseek-ai/dsh-skill": "^0.1.0-rc.6",
120
- "@deepseek-ai/dsh-storage-domain": "^0.1.0-rc.6",
121
- "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.6",
122
- "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
123
- "@deepseek-ai/dsh-tools": "^0.1.0-rc.6",
124
- "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6",
111
+ "@deepseek-ai/dsh-agent": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
112
+ "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
113
+ "@deepseek-ai/dsh-brand": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
114
+ "@deepseek-ai/dsh-client-locale": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
115
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
116
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
117
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
118
+ "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
119
+ "@deepseek-ai/dsh-llm": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
120
+ "@deepseek-ai/dsh-session": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
121
+ "@deepseek-ai/dsh-settings": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
122
+ "@deepseek-ai/dsh-skill": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
123
+ "@deepseek-ai/dsh-storage-domain": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
124
+ "@deepseek-ai/dsh-subprocess": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
125
+ "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
126
+ "@deepseek-ai/dsh-tools": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
127
+ "@deepseek-ai/dsh-user-approval": "^0.1.0-rc.6 || 0.1.7-rc.2 || 0.2.0-rc.2",
125
128
  "@deepseek-ai/cordis": "^4.0.1",
126
129
  "react": "^18.2.0",
127
- "@deepseek-ai/schemastery": "^3.18.1"
130
+ "@deepseek-ai/schemastery": "^3.18.1",
131
+ "@deepseek-ai/dsh-util-values": "^0.1.0-rc.6 || 0.2.0-rc.2"
128
132
  },
129
133
  "peerDependenciesMeta": {
130
134
  "@deepseek-ai/dsh-host-webserver": {
@@ -136,10 +140,46 @@
136
140
  "@types/react": "~18.3.1",
137
141
  "@types/react-dom": "~18.3.0",
138
142
  "typescript": "^6.0.3",
139
- "vitest": "^4.1.10"
143
+ "vitest": "^4.1.10",
144
+ "@deepseek-ai/dsh-agent": "0.2.0-rc.2",
145
+ "@deepseek-ai/dsh-api-remotes": "0.2.0-rc.2",
146
+ "@deepseek-ai/dsh-brand": "0.2.0-rc.2",
147
+ "@deepseek-ai/dsh-client-locale": "0.2.0-rc.2",
148
+ "@deepseek-ai/dsh-client-ui-primitives": "0.2.0-rc.2",
149
+ "@deepseek-ai/dsh-client-ui-settings": "0.2.0-rc.2",
150
+ "@deepseek-ai/dsh-client-ui-slots": "0.2.0-rc.2",
151
+ "@deepseek-ai/dsh-host-webserver": "0.2.0-rc.2",
152
+ "@deepseek-ai/dsh-llm": "0.2.0-rc.2",
153
+ "@deepseek-ai/dsh-session": "0.2.0-rc.2",
154
+ "@deepseek-ai/dsh-settings": "0.2.0-rc.2",
155
+ "@deepseek-ai/dsh-skill": "0.2.0-rc.2",
156
+ "@deepseek-ai/dsh-storage-domain": "0.2.0-rc.2",
157
+ "@deepseek-ai/dsh-subprocess": "0.2.0-rc.2",
158
+ "@deepseek-ai/dsh-system-prompt": "0.2.0-rc.2",
159
+ "@deepseek-ai/dsh-tools": "0.2.0-rc.2",
160
+ "@deepseek-ai/dsh-user-approval": "0.2.0-rc.2",
161
+ "@deepseek-ai/cordis": "4.0.4",
162
+ "@deepseek-ai/schemastery": "3.18.4",
163
+ "@deepseek-ai/dsh-util-values": "0.2.0-rc.2",
164
+ "@deepseek-ai/dsh-client-ui-renderer": "0.2.0-rc.2",
165
+ "@deepseek-ai/dsh-client-connection": "0.2.0-rc.2",
166
+ "@deepseek-ai/dsh-scope": "0.2.0-rc.2",
167
+ "@deepseek-ai/dsh-storage": "0.2.0-rc.2",
168
+ "@deepseek-ai/cosmokit": "1.8.5",
169
+ "@deepseek-ai/dsh-credentials": "0.2.0-rc.2",
170
+ "@deepseek-ai/dsh-typert-protocol": "0.2.0-rc.2",
171
+ "@deepseek-ai/dsh-util-crypto": "0.2.0-rc.2",
172
+ "@deepseek-ai/dsh-timeout": "0.2.0-rc.2",
173
+ "@deepseek-ai/dsh-sandbox": "0.2.0-rc.2",
174
+ "@deepseek-ai/dsh-http-proxy": "0.2.0-rc.2",
175
+ "@deepseek-ai/cordis-plugin-loader": "1.0.5",
176
+ "@deepseek-ai/dsh-util-workspace-path": "0.2.0-rc.2",
177
+ "@deepseek-ai/dsh-client-store": "0.2.0-rc.2",
178
+ "@deepseek-ai/dsh-util-code-language": "0.2.0-rc.2",
179
+ "@deepseek-ai/dsh-deque": "0.2.0-rc.2"
140
180
  },
141
181
  "dependencies": {
142
- "zod": "^4.4.3"
182
+ "zod": "4.4.3"
143
183
  },
144
184
  "license": "MIT"
145
185
  }
@@ -45,8 +45,8 @@ function externalCommand(command, args) {
45
45
  // A long-running Node harness can leave DSH without its internal ESM loader.
46
46
  // A login shell matches the real CLI entry and keeps profile package resolution isolated.
47
47
  return command === 'dsh' && process.platform === 'darwin'
48
- ? { command: '/bin/bash', args: ['-lc', 'exec dsh "$@"', 'dsh', ...args] }
49
- : { command, args }
48
+ ? { command: '/bin/bash', args: ['-lc', 'exec "$@"', 'dsh', process.env.DSH_TEST_CLI ?? 'dsh', ...args] }
49
+ : { command: command === 'dsh' ? process.env.DSH_TEST_CLI ?? command : command, args }
50
50
  }
51
51
 
52
52
  async function runCommand(name, command, args, options = {}) {
@@ -180,6 +180,8 @@ async function realModelWorkflow() {
180
180
  }
181
181
 
182
182
  const tarball = await findTarball(packing)
183
+ await mkdir(join(home, 'profiles', 'headless'), { recursive: true })
184
+ await writeFile(join(home, 'profiles', 'headless', 'pnpm-workspace.yaml'), 'nodeLinker: hoisted\nautoInstallPeers: false\n')
183
185
  await runCommand(
184
186
  'install dsh-computer-use tarball',
185
187
  'dsh',
@@ -215,6 +217,8 @@ async function realModelWorkflow() {
215
217
  ].join('\n'))
216
218
 
217
219
  const prompt = `/computer-use\n\nUse the dsh-computer-use capability to operate the running deterministic macOS fixture whose bundle id is ${BUNDLE_ID}. Load the Skill, list running applications, select the exact fixture process, observe it with a required screenshot and full Accessibility state, locate the element labelled "Targeted pointer probe", and click that current element using its observation id and element index with allowCoordinateFallback=true. Confirm from the fresh post-action observation that the status reads "Status: pointer click". Use only the focused computer-use Tools for UI observation and input; do not use shell, AppleScript, JXA, direct file edits, or coordinate guessing. Finish immediately after confirming the pointer-click state.`
220
+ const hostVersion = await runCommand('target DSH version', 'dsh', ['--version'])
221
+ const defaultBaseURL = hostVersion.stdout.includes('0.2.') ? 'https://api.deepseek.com/anthropic' : 'https://api.deepseek.com/v1'
218
222
  const result = await runCommand(
219
223
  'DeepSeek V4 computer-use fixture workflow',
220
224
  'dsh',
@@ -226,7 +230,7 @@ async function realModelWorkflow() {
226
230
  DSH_TELEMETRY_DISABLED: '1',
227
231
  DSH_PERMISSION_MODE: 'workspace-write',
228
232
  DEEPSEEK_API_KEY: requiredEnvironment('DEEPSEEK_API_KEY'),
229
- DEEPSEEK_BASE_URL: process.env.DEEPSEEK_BASE_URL?.trim() || 'https://api.deepseek.com/v1',
233
+ DEEPSEEK_BASE_URL: process.env.DEEPSEEK_BASE_URL?.trim() || defaultBaseURL,
230
234
  },
231
235
  timeoutMs: 600_000,
232
236
  },
@@ -53,7 +53,7 @@ async function sessionLogs(directory) {
53
53
  for (const entry of await readdir(directory, { withFileTypes: true }).catch(() => [])) {
54
54
  const path = join(directory, entry.name)
55
55
  if (entry.isDirectory()) result.push(...await sessionLogs(path))
56
- else if (entry.isFile() && (entry.name === 'session.jsonl' || entry.name === 'session.jsonl.zstd')) result.push(path)
56
+ else if (entry.isFile() && /^session(?:\.v\d+)?\.jsonl(?:\.zstd)?$/u.test(entry.name)) result.push(path)
57
57
  }
58
58
  return result
59
59
  }
@@ -71,8 +71,9 @@ function resultValue(event) {
71
71
  const outer = event?.data?.message?.content
72
72
  if (!Array.isArray(outer)) return undefined
73
73
  for (const block of outer) {
74
- if (block?.type !== 'tool-result' || !Array.isArray(block.content)) continue
75
- for (const content of block.content) {
74
+ // Session v4 stores tool-role text directly; earlier logs wrap it.
75
+ const contents = block?.type === 'tool-result' && Array.isArray(block.content) ? block.content : [block]
76
+ for (const content of contents) {
76
77
  if (content?.type !== 'text' || typeof content.text !== 'string') continue
77
78
  try { return JSON.parse(content.text) }
78
79
  catch { return undefined }
@@ -2,7 +2,9 @@
2
2
 
3
3
  import { useEffect, useState, useSyncExternalStore, type ReactNode } from 'react'
4
4
  import { Button, Input } from '@deepseek-ai/dsh-client-ui-primitives'
5
- import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client'
5
+ import type { Context as ClientContext } from '@deepseek-ai/cordis'
6
+ import type {} from '@deepseek-ai/dsh-client-ui-renderer/client'
7
+ import type {} from '@deepseek-ai/dsh-client-connection/client'
6
8
  import type {} from '@deepseek-ai/dsh-api-remotes/client'
7
9
  import type {} from '@deepseek-ai/dsh-client-ui-settings/client'
8
10
  import type {} from '@deepseek-ai/dsh-client-locale/client'
@@ -561,7 +563,7 @@ export function apply(ctx: ClientContext): void {
561
563
  const controller = new ComputerUseSettingsController()
562
564
  ctx.effect(() => {
563
565
  const disposers = [
564
- ctx.remote.$on('settings/document-updated', ns => { if (ns === NS) controller.refreshIfLoaded() }),
566
+ ctx.remote.$on('settings/document-updated', (ns: string) => { if (ns === NS) controller.refreshIfLoaded() }),
565
567
  ctx.on('connection/reset', () => { controller.refreshIfLoaded() }),
566
568
  ]
567
569
  return () => { for (const dispose of disposers) dispose() }
package/src/config.ts CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  import z from '@deepseek-ai/schemastery'
4
4
  import type Schema from '@deepseek-ai/schemastery'
5
+ import * as SettingsModule from '@deepseek-ai/dsh-settings'
5
6
  import type { SettingsNamespace } from '@deepseek-ai/dsh-settings'
6
7
  import { ComputerUseError } from './errors.ts'
7
8
 
@@ -60,23 +61,44 @@ export interface ComputerUseConfig {
60
61
  grants?: ComputerUseAppGrant[]
61
62
  }
62
63
 
64
+ /** DSH 0.1.7 derives editable Settings fields from volatile Config fields.
65
+ * Legacy Settings can coexist with a newer Schemastery installation. Only
66
+ * enable references when the host Settings service uses Config-derived forms.
67
+ */
68
+ function live<T>(field: Schema<T>): Schema<T> {
69
+ const candidate = field as Schema<T> & { volatile?: () => Schema<T> }
70
+ return 'SettingsForms' in SettingsModule && typeof candidate.volatile === 'function'
71
+ ? candidate.volatile() as unknown as Schema<T>
72
+ : field
73
+ }
74
+
75
+ /** Read the newer Loader's stable references without changing the legacy shape. */
76
+ export function readComputerUseConfig(config: ComputerUseConfig): ComputerUseConfig {
77
+ return Object.fromEntries(Object.entries(config).map(([key, value]) => [
78
+ key,
79
+ value !== null && typeof value === 'object' && 'get' in value && typeof value.get === 'function'
80
+ ? value.get()
81
+ : value,
82
+ ])) as ComputerUseConfig
83
+ }
84
+
63
85
  /** Configuration schema used by Cordis and the Settings provider. */
64
86
  export const Config: Schema<ComputerUseConfig> = z.object({
65
- observationTtlMs: z.number().default(0),
66
- confirmationTtlMs: z.number().default(300000),
67
- actionTimeoutMs: z.number().default(15000),
68
- settleMs: z.number().default(250),
69
- maxSettleMs: z.number().default(5000),
70
- maxNodes: z.number().default(500),
71
- maxDepth: z.number().default(14),
72
- maxTextBytes: z.number().default(64000),
73
- maxScreenshotBytes: z.number().default(33554432),
74
- artifactRoot: z.string().default('.dsh-computer-use/artifacts'),
75
- helper: z.object({
87
+ observationTtlMs: live(z.number().default(0)),
88
+ confirmationTtlMs: live(z.number().default(300000)),
89
+ actionTimeoutMs: live(z.number().default(15000)),
90
+ settleMs: live(z.number().default(250)),
91
+ maxSettleMs: live(z.number().default(5000)),
92
+ maxNodes: live(z.number().default(500)),
93
+ maxDepth: live(z.number().default(14)),
94
+ maxTextBytes: live(z.number().default(64000)),
95
+ maxScreenshotBytes: live(z.number().default(33554432)),
96
+ artifactRoot: live(z.string().default('.dsh-computer-use/artifacts')),
97
+ helper: live(z.object({
76
98
  path: z.string(),
77
99
  allowSourceBuild: z.boolean().default(false),
78
- }),
79
- interaction: z.object({
100
+ })),
101
+ interaction: live(z.object({
80
102
  focusPolicy: z.union(['preserve', 'activate']).default('preserve'),
81
103
  keyboardPolicy: z.union(['preserve', 'activate']).default('preserve'),
82
104
  pointerInputPolicy: z.union(['deny', 'targeted']).default('targeted'),
@@ -86,14 +108,14 @@ export const Config: Schema<ComputerUseConfig> = z.object({
86
108
  cursorAccelerationPxPerSecondSquared: z.number().default(6000),
87
109
  cursorClickDelayMs: z.number().default(90),
88
110
  cursorAutoHideMs: z.number().default(0),
89
- }),
90
- allowAllApps: z.boolean().default(false),
91
- grants: z.array(z.object({
111
+ })),
112
+ allowAllApps: live(z.boolean().default(false)),
113
+ grants: live(z.array(z.object({
92
114
  bundleId: z.string(),
93
115
  read: z.boolean().default(false),
94
116
  control: z.boolean().default(false),
95
- })).default([]),
96
- })
117
+ })).default([])),
118
+ }) as unknown as Schema<ComputerUseConfig>
97
119
 
98
120
  /** Fully defaulted configuration consumed at runtime. */
99
121
  export interface ResolvedComputerUseConfig {
@@ -48,7 +48,7 @@ export class ComputerConfirmationManager {
48
48
  agent: Agent,
49
49
  app: ComputerAppIdentity,
50
50
  request: ComputerConfirmRequest,
51
- callId: import('@deepseek-ai/dsh-llm').CallId | undefined,
51
+ callId: import('@deepseek-ai/dsh-tools').ToolRunContext['callId'] | undefined,
52
52
  signal: AbortSignal,
53
53
  ): Promise<ComputerConfirmation> {
54
54
  if (approvalPolicy(this.ctx, agent) === 'never') {
package/src/exposure.ts CHANGED
@@ -5,7 +5,7 @@ import type { ContentBlock } from '@deepseek-ai/dsh-llm'
5
5
  import type { Session } from '@deepseek-ai/dsh-session'
6
6
  import { defineTool, type ToolDefinition } from '@deepseek-ai/dsh-tools'
7
7
  import type { Context } from '@deepseek-ai/cordis'
8
- import { COMPUTER_USE_SKILL_CONTENT, COMPUTER_USE_SKILL_NAME } from './skill.ts'
8
+ import { COMPUTER_USE_SKILL_CONTENT, COMPUTER_USE_SKILL_NAME, COMPUTER_USE_SKILL_NAMES } from './skill.ts'
9
9
 
10
10
  /** One global bootstrap retained until the current Agent loads the Skill. */
11
11
  export const COMPUTER_USE_ACTIVATE = 'computer_use_activate'
@@ -60,7 +60,7 @@ function adHocOcrCommand(value: unknown): boolean {
60
60
  }
61
61
 
62
62
  function isSkillArguments(value: unknown): boolean {
63
- return isRecord(value) && value.name === COMPUTER_USE_SKILL_NAME
63
+ return isRecord(value) && COMPUTER_USE_SKILL_NAMES.has(value.name as string)
64
64
  }
65
65
 
66
66
  function nativeSkillCall(raw: string): boolean {
@@ -76,7 +76,7 @@ function containsSkillContent(blocks: readonly unknown[]): boolean {
76
76
 
77
77
  function isSkillResult(value: unknown): boolean {
78
78
  return isRecord(value)
79
- && value.name === COMPUTER_USE_SKILL_NAME
79
+ && COMPUTER_USE_SKILL_NAMES.has(value.name as string)
80
80
  && value.content === COMPUTER_USE_SKILL_CONTENT
81
81
  }
82
82
 
@@ -96,12 +96,12 @@ export function hasLoadedComputerUseSkill(session: Session): boolean {
96
96
  const nativeCalls = new Set<string>()
97
97
  const events = typeof (session as any).snapshotEvents === 'function'
98
98
  ? (session as any).snapshotEvents()
99
- : session.events ?? []
99
+ : (session as unknown as { events?: readonly import('@deepseek-ai/dsh-session').SessionEvent[] }).events ?? []
100
100
  for (const event of events) {
101
101
  if (event.type === 'user/message') {
102
102
  const source = event.data.source
103
103
  if (source.kind === 'skill-invocation'
104
- && source.name === COMPUTER_USE_SKILL_NAME
104
+ && COMPUTER_USE_SKILL_NAMES.has(source.name)
105
105
  && containsSkillContent(event.data.content)) return true
106
106
  continue
107
107
  }
package/src/index.ts CHANGED
@@ -8,7 +8,7 @@ import type {} from '@deepseek-ai/dsh-tools'
8
8
  import { Config, type ComputerUseConfig } from './config.ts'
9
9
  import { ComputerUseExposure } from './exposure.ts'
10
10
  import { MacOSComputerUseProvider } from './providers/macos.ts'
11
- import { COMPUTER_USE_SKILL } from './skill.ts'
11
+ import { COMPUTER_USE_SKILL, LEGACY_COMPUTER_USE_SKILL } from './skill.ts'
12
12
  import { createComputerUseTools } from './tools.ts'
13
13
  import { installComputerUseWeb } from './web.ts'
14
14
 
@@ -22,14 +22,17 @@ export function installComputerUseConsumer(ctx: Context): () => void {
22
22
  const exposure = new ComputerUseExposure(ctx, () => createComputerUseTools(ctx.computerUse))
23
23
  let activation: (() => void) | undefined
24
24
  let skill: (() => void) | undefined
25
+ let legacySkill: (() => void) | undefined
25
26
  let exposureDispose: (() => void) | undefined
26
27
  try {
27
28
  activation = ctx.tools.register(exposure.activationTool)
28
29
  skill = ctx.skills.register(COMPUTER_USE_SKILL)
30
+ legacySkill = ctx.skills.register(LEGACY_COMPUTER_USE_SKILL)
29
31
  exposureDispose = exposure.install()
30
32
  installComputerUseWeb(ctx)
31
33
  } catch (error) {
32
34
  exposureDispose?.()
35
+ legacySkill?.()
33
36
  skill?.()
34
37
  activation?.()
35
38
  throw error
@@ -37,6 +40,7 @@ export function installComputerUseConsumer(ctx: Context): () => void {
37
40
  return () => {
38
41
  exposureDispose?.()
39
42
  activation?.()
43
+ legacySkill?.()
40
44
  skill?.()
41
45
  }
42
46
  }
package/src/leases.ts CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  import { z } from 'zod'
4
4
  import type { Agent } from '@deepseek-ai/dsh-agent'
5
- import type { CallId } from '@deepseek-ai/dsh-llm'
5
+ import type { ToolRunContext } from '@deepseek-ai/dsh-tools'
6
+ type CallId = ToolRunContext['callId']
6
7
  import type { SessionEvent, SessionHeader, SessionId } from '@deepseek-ai/dsh-session'
7
8
  import { defineDomain, domainTable } from '@deepseek-ai/dsh-storage-domain'
8
9
  import type { KvTable } from '@deepseek-ai/dsh-storage-domain'
@@ -187,7 +188,7 @@ export class ComputerLeaseManager {
187
188
  await this.prepareStorage()
188
189
  const sessionEvents = typeof (agent.session as any).snapshotEvents === 'function'
189
190
  ? (agent.session as any).snapshotEvents()
190
- : agent.session.events ?? []
191
+ : (agent.session as unknown as { events?: readonly SessionEvent[] }).events ?? []
191
192
  const turn = currentTurn(sessionEvents)
192
193
  if (turn === undefined) {
193
194
  throw new ComputerUseError('COMPUTER_PERMISSION_REQUIRED', `${scope} access for ${app.name} must be requested inside an open Agent turn`)
@@ -21,6 +21,7 @@ import type {
21
21
  import {
22
22
  Config,
23
23
  COMPUTER_USE_SETTINGS_NAMESPACE,
24
+ readComputerUseConfig,
24
25
  resolveConfig,
25
26
  type ComputerUseConfig,
26
27
  type ResolvedComputerUseConfig,
@@ -253,21 +254,26 @@ export class MacOSComputerUseProvider extends ComputerUseService {
253
254
  static inject = ['subprocess', 'approval', 'settings', 'sessions', 'agents']
254
255
  static Config = Config
255
256
 
256
- private readonly settings
257
-
258
257
  constructor(ctx: Context, config: ComputerUseConfig = {}) {
259
- const settings = ctx.settings.register(COMPUTER_USE_SETTINGS_NAMESPACE, Config, {
260
- base: config,
261
- applies: 'live',
262
- validate: (value) => { resolveConfig(value) },
263
- })
264
- const resolved = resolveConfig(settings.get())
258
+ const legacySettings = ctx.settings as typeof ctx.settings & {
259
+ register?: (ns: typeof COMPUTER_USE_SETTINGS_NAMESPACE, schema: typeof Config, options: object) => {
260
+ get(): ComputerUseConfig
261
+ watch(listener: (value: ComputerUseConfig) => Promise<void>): () => void
262
+ }
263
+ }
264
+ const settings = typeof legacySettings.register === 'function'
265
+ ? legacySettings.register(COMPUTER_USE_SETTINGS_NAMESPACE, Config, {
266
+ base: config,
267
+ applies: 'live',
268
+ validate: (value: ComputerUseConfig) => { resolveConfig(value) },
269
+ })
270
+ : undefined
271
+ const resolved = resolveConfig(settings?.get() ?? readComputerUseConfig(config))
265
272
  super(ctx, createBackend(ctx, resolved), resolved)
266
- this.settings = settings
267
273
  if (process.platform !== 'darwin') {
268
274
  ctx.logger.warn('dsh-computer-use: supports macOS only; Computer Use Tools are disabled on %s', process.platform)
269
275
  }
270
- ctx.effect(() => this.settings.watch(async (next) => {
276
+ const reconfigure = async (next: ComputerUseConfig): Promise<void> => {
271
277
  const candidate = resolveConfig(next)
272
278
  const backend = createBackend(ctx, candidate)
273
279
  try {
@@ -276,7 +282,21 @@ export class MacOSComputerUseProvider extends ComputerUseService {
276
282
  await backend.dispose()
277
283
  throw error
278
284
  }
279
- }), 'dsh-computer-use: Settings watch')
285
+ }
286
+ if (settings) {
287
+ ctx.effect(() => settings.watch(reconfigure), 'dsh-computer-use: Settings watch')
288
+ } else {
289
+ // DSH 0.1.7 projects Settings from Config and commits volatile fields in
290
+ // place. The Loader emits this event after its references have changed.
291
+ ctx.effect(() => {
292
+ const onVolatileUpdate = ctx.on as unknown as (name: string, listener: () => void) => () => void
293
+ return onVolatileUpdate.call(ctx, 'loader/volatile-update', () => {
294
+ void reconfigure(readComputerUseConfig(config)).catch(error => {
295
+ ctx.logger.warn('dsh-computer-use: live config update failed: %s', error)
296
+ })
297
+ })
298
+ }, 'dsh-computer-use: Loader volatile update')
299
+ }
280
300
  ctx.effect(() => ctx.on('agent/disposed', ({ agent }) => { this.releaseAgent(agent) }), 'dsh-computer-use: Agent cleanup')
281
301
  }
282
302