dsh-cindy-host 0.1.28 → 0.1.30

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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.30 — 2026-10-29
4
+
5
+ - Match Cindy native local media fetching: baseDir/workdir constraints are optional; absolute file references no longer fail with no-root. Explicit constraints, sensitive-path checks, regular-file checks and byte limits remain enforced.
6
+ - Fix the shared parser/resolver for all file types and original, thumbnail, prepareOnly and file-peer reads; no PNG-specific workaround or controller changes.
7
+ - Add contract regressions for 15 extensions, POSIX/Windows paths, both file/audio schemes, real filesystem preparation and rootless peer bytes/EOF.
8
+ - Minimal patch on published 0.1.29; preserves its runtime and queue/input-delivery behavior. Requires the same DSH 0.2.1-rc.3 carrier and Node >=22.16. Linux handset end-to-end acceptance requires deployment and is not implied by publication.
9
+
10
+ ## 0.1.29 — 2026-10-29
11
+
12
+ - Publish from a clean, committed Git source tree; preserve the accepted 0.1.28 runtime behavior.
13
+ - Make native Android queue/ACK and durable-outbox regression tests offline and repository-contained.
14
+ - Pin upstream Cindy test sources with Apache-2.0 LICENSE and NOTICE; exclude all fixtures from the npm package.
15
+ - Synchronize the dependency lock and version-aware isolated smoke helper; retain current DSH SDK peers without forced upgrades.
16
+
3
17
  ## 0.1.28 — 2026-10-28
4
18
 
5
19
  - Fix busy input confirmation on both controllers: DSH admission no longer removes an actual pending inbox row from later projections.
package/README.md CHANGED
@@ -4,14 +4,18 @@ A Host-side adapter connecting current Cindy clients to DeepSeek Harness.
4
4
 
5
5
  ## Requirements and installation
6
6
 
7
- Version 0.1.27 targets the verified **DSH 0.2.1-rc.3** service contracts, with **Node.js >=22.16**. Its DSH peer versions are pinned to this carrier to prevent an installer from mixing a newer prerelease SDK into the running host. The verified Desktop runtime includes Node.js 24.21. Install through the Desktop DSH plugin manager. CLI-managed profiles can use:
7
+ Version 0.1.29 targets the verified **DSH 0.2.1-rc.3** service contracts, with **Node.js >=22.16**. Its DSH peer versions are pinned to this carrier to prevent an installer from mixing a newer prerelease SDK into the running host. The verified Desktop runtime includes Node.js 24.21. Install through the Desktop DSH plugin manager. CLI-managed profiles can use:
8
8
 
9
9
  ```sh
10
- dsh plugin --profile <profile> add dsh-cindy-host@0.1.28
10
+ dsh plugin --profile <profile> add dsh-cindy-host@0.1.29
11
11
  ```
12
12
 
13
13
  Reload the Host plugin after installation. A full DSH restart is separate. Keep existing Cindy sign-in, device identity and settings; do not run two Host processes with the same identity.
14
14
 
15
+ ## 0.1.29: reproducible repository release
16
+
17
+ Runtime behavior is unchanged from the phone- and desktop-accepted 0.1.28. This release synchronizes the verified source, dependency lock and offline native-client contract fixtures into Git. The pinned third-party fixtures are test-only and excluded from the npm package.
18
+
15
19
  ## 0.1.28: busy enqueue confirmation
16
20
 
17
21
  A real DSH pending inbox occurrence remains in pendingQueue (or steeringQueueClientIds) in enqueue replies, pushes and polling until it is actually claimed or committed. Handing input to DSH is not delivery to the user turn. This fixes 0.1.27 empty follow-up projections overwriting the busy-queue acknowledgment on Android and desktop. Regression tests execute the current Android parser and stale-ACK authority handling, not just the durable outbox state machine.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-cindy-host",
3
- "version": "0.1.28",
3
+ "version": "0.1.30",
4
4
  "private": false,
5
5
  "description": "Cindy 手机客户端连接 DSH 的 Host 侧插件:会话/消息/审批/todo/goal 的手机通道,以及配套的设置卡片",
6
6
  "license": "MIT",
@@ -8,19 +8,14 @@
8
8
  * (`apps/desktop/src/main/device-link/mediaFetch.ts`: 解析本机媒体 → 上传 OSS → 返回引用):
9
9
  *
10
10
  * ```
11
- * request { url: 'xdt-file://open?path=<abs>&workdir=<abs>&maxBytes=<n>', thumbnail?, skipCache?, prepareOnly? }
11
+ * request { url: 'xdt-file://open?path=<abs>', thumbnail?, skipCache?, prepareOnly? }
12
12
  * response { ossKey, mimeType, size } // the controller presign-gets the key
13
13
  * ```
14
14
  *
15
- * Two things are deliberately **stricter** than the reference, because this Host is a
16
- * process on somebody's desktop rather than an app with its own cache directory:
17
- *
18
- * 1. **A containment root is mandatory.** The desktop treats a missing `baseDir` as "no
19
- * constraint" for old controllers; here a request that names no root (neither `baseDir`
20
- * nor the `workdir` a chat image carries) is refused. Without that, any absolute path
21
- * on this machine would be servable by anyone who can reach the Host.
22
- * 2. **Realpath on both sides.** A symlink inside the workspace must not become a way out
23
- * of it, and `/tmp` vs `/private/tmp` must not make a legitimate file look outside.
15
+ * Directory constraints are optional, matching Cindy's native media-fetch contract.
16
+ * A plain absolute `path` is accepted; when `baseDir` or `workdir` is supplied, both
17
+ * the file and the root are realpath'd before containment checks. This prevents a
18
+ * symlink from escaping a supplied root and handles `/tmp` vs `/private/tmp` aliases.
24
19
  *
25
20
  * Malformed constraint parameters are refused rather than ignored: silently degrading to
26
21
  * "unconstrained" is how a constraint gets removed by a typo.
@@ -266,7 +261,6 @@ export function parseMediaFetchRequest(url) {
266
261
  if (value.trim() === '' || !isAbsoluteMediaPath(value)) return { ok: false, reason: `invalid-${key}` };
267
262
  roots.push(value);
268
263
  }
269
- if (roots.length === 0) return { ok: false, reason: 'no-root' };
270
264
 
271
265
  let maxBytes = null;
272
266
  const rawMaxBytes = parsed.searchParams.get('maxBytes');
@@ -316,7 +310,7 @@ export function createLocalFileResolver({
316
310
  // A root that does not resolve cannot authorise anything; the others still can.
317
311
  }
318
312
  }
319
- if (allowedRoots.length === 0 || !allowedRoots.some((root) => isInsideDirectory(real, root))) {
313
+ if (request.roots.length > 0 && !allowedRoots.some((root) => isInsideDirectory(real, root))) {
320
314
  return { ok: false, code: 'FORBIDDEN', message: 'the requested file is outside the directory the controller named' };
321
315
  }
322
316
  if (isBlockedMediaPath(real, blocked)) {
@@ -4,4 +4,4 @@
4
4
  */
5
5
  export const HOST_APP_VERSION = '0.1.82';
6
6
  /** Actual npm release, separate from the Cindy compatibility identity. */
7
- export const HOST_PLUGIN_VERSION = '0.1.28';
7
+ export const HOST_PLUGIN_VERSION = '0.1.30';
package/src/host.js CHANGED
@@ -227,8 +227,8 @@ export async function startHost(initialSource, settings = DEFAULT_HOST_SETTINGS,
227
227
  *
228
228
  * The chat-image path: a picture the agent produced is referenced by path in the
229
229
  * transcript, and the controller resolves it through `device-link:media:fetch`. Same
230
- * uploader as the file browser's export ops, stricter request handling
231
- * (`host-media-fetch.js`): a containment root is mandatory and both sides are realpath'd.
230
+ * uploader as the file browser's export ops. Directory constraints are optional, as
231
+ * in Cindy; when supplied, both the file and the root are realpath'd before checking.
232
232
  */
233
233
  const fetchLocalMedia = createLocalMediaFetcher({ uploader: uploadMedia });
234
234
  const resolvePeerFile = createLocalFileResolver({ maxBytes: FILE_PEER_MAX_BYTES });