@deepseek-ai/dsh-tmux-context 0.1.2-alpha.5 → 0.1.3-alpha.2

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.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/context/tmux-context/README.md
5
- README.md: df94e309839a8ecdae902def8531856071269d20
6
- README.zh.md: da69791cb96cd4ef13b5fa31ddaf4e6470e08d60
5
+ README.md: 18509f5ab7666dd58f048e618f2874db921f044a
6
+ README.zh.md: 1eb7feb5eebde6a7c1fd7cdde391de2b9c556d11
package/README.md CHANGED
@@ -85,7 +85,7 @@ At the first step of a turn, the listener checks whether an injection is due, qu
85
85
 
86
86
  Read these pages when the package-level contract is not enough. They move from the design decision to the executor the query runs through and the exhaustive configuration.
87
87
 
88
- - [Tmux location context decision record](../../../.agents/notes/implemented/feature/2026-07-27-tmux-location-context.md) — design rationale for the tty-based detection and reading shape.
88
+ - [Tmux location context decision record](../../../.agents/notes/archived/feature/2026-07-27-tmux-location-context.md) — design rationale for the tty-based detection and reading shape.
89
89
  - [Shell subsystem](../../../docs/subsystems/shell.md) — the executor service the read-only query runs through.
90
90
  - [Context group map](../README.md) — sibling request-context packages.
91
91
  - [Generated configuration catalog](../../../docs/config-catalog.md#deepseek-aidsh-tmux-context) — every accepted config field and its source declaration.
package/README.zh.md CHANGED
@@ -85,7 +85,7 @@ kind: "package-reference"
85
85
 
86
86
  包级约定不够用时阅读以下页面。它们从设计决策进入查询所经由的执行器与穷尽式配置。
87
87
 
88
- - [tmux 位置上下文决策记录](../../../.agents/notes/implemented/feature/2026-07-27-tmux-location-context.zh.md)——基于 tty 的检测与读数形状的设计理由。
88
+ - [tmux 位置上下文决策记录](../../../.agents/notes/archived/feature/2026-07-27-tmux-location-context.md)——基于 tty 的检测与读数形状的设计理由。
89
89
  - [shell 子系统](../../../docs/subsystems/shell.zh.md)——只读查询所经由的执行器服务。
90
90
  - [context 组地图](../README.zh.md)——相邻的请求上下文包。
91
91
  - [生成的配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-tmux-context)——每个受支持配置字段及其源声明。
package/lib/index.js CHANGED
@@ -496,6 +496,9 @@ function harnessErrorCode(error) {
496
496
  }
497
497
  //#endregion
498
498
  //#region ../../llm/llm/src/content.ts
499
+ function quoted(value) {
500
+ return JSON.stringify(value);
501
+ }
499
502
  /**
500
503
  * Stable text shown to a model that cannot accept one durable image reference.
501
504
  * @param ref - durable normalized attachment omitted from the request.
@@ -515,6 +518,74 @@ function textOnlyImageText(ref) {
515
518
  function contentHasImage(content) {
516
519
  return content.some((block) => block.type === "image" || block.type === "tool-result" && contentHasImage(block.content));
517
520
  }
521
+ /**
522
+ * True when typed model content contains a file block, walking nested
523
+ * tool-result content on the same recursion every file policy shares.
524
+ * @param content - typed model content blocks.
525
+ * @returns whether any nested block is a file.
526
+ */
527
+ function contentHasFile(content) {
528
+ return content.some((block) => block.type === "file" || block.type === "tool-result" && contentHasFile(block.content));
529
+ }
530
+ /**
531
+ * Stable model-facing handle for one durable file reference: the address of
532
+ * the verbatim stored copy and the instruction to read it on demand. This is
533
+ * the only representation a provider ever receives for a file.
534
+ * @param ref - durable verbatim file reference.
535
+ * @param readonlyPath - execution-world path of the stored copy, when resolvable.
536
+ * @returns deterministic handle text naming the file, its size, and its address.
537
+ */
538
+ function fileHandleText(ref, readonlyPath) {
539
+ const digest = String(ref.attachmentId).slice(7, 15);
540
+ const identity = `File ${quoted(ref.name)} (${ref.bytes} bytes, sha256:${digest})`;
541
+ if (readonlyPath === void 0) return `[${identity} was uploaded, but the current execution environment cannot access a readable path. Report that limitation if its contents are needed; do not claim to have read it.]`;
542
+ return `[${identity}: verbatim read-only copy saved at ${quoted(readonlyPath)}. Read that path with your file tools when its contents are needed; copy it to a writable location before modifying it. When delegating file work, include this saved path in the delegation prompt; only subagents sharing this execution environment can read it.]`;
543
+ }
544
+ /** Replace every file occurrence, including nested tool results, with handle text. */
545
+ function replaceFilesWithHandles(blocks, resolvePath) {
546
+ let next;
547
+ for (const [index, block] of blocks.entries()) {
548
+ if (block.type === "file") {
549
+ next ??= blocks.slice(0, index);
550
+ next.push({
551
+ type: "text",
552
+ text: fileHandleText(block.attachment, resolvePath(block.attachment))
553
+ });
554
+ continue;
555
+ }
556
+ if (block.type === "tool-result") {
557
+ const content = replaceFilesWithHandles(block.content, resolvePath);
558
+ if (content !== block.content) {
559
+ next ??= blocks.slice(0, index);
560
+ next.push({
561
+ ...block,
562
+ content
563
+ });
564
+ continue;
565
+ }
566
+ }
567
+ next?.push(block);
568
+ }
569
+ return next ?? blocks;
570
+ }
571
+ /**
572
+ * Project durable file history into deterministic handle text for every model
573
+ * route. Unlike images, no provider receives file blocks natively, so this
574
+ * projection is unconditional in request assembly.
575
+ * @param messages - complete request history.
576
+ * @param resolvePath - resolve one reference's current execution-world read path.
577
+ * @returns the original list without files, otherwise shallow message copies with handle text.
578
+ */
579
+ function projectFilesToText(messages, resolvePath) {
580
+ if (!messages.some((message) => contentHasFile(message.content))) return messages;
581
+ return messages.map((message) => {
582
+ const content = replaceFilesWithHandles(message.content, resolvePath);
583
+ return content === message.content ? message : {
584
+ ...message,
585
+ content
586
+ };
587
+ });
588
+ }
518
589
  /** Replace every image occurrence, including nested tool results, for a text-only model. */
519
590
  function replaceImagesForTextModel(blocks) {
520
591
  let next;
@@ -951,6 +1022,15 @@ var LlmError = class extends HarnessError {
951
1022
  imageRequestPricing(provider, model) {
952
1023
  return this.adapters.get(provider)?.adapter.imageRequestPricing(provider, model);
953
1024
  }
1025
+ /**
1026
+ * Resolve the exact text one durable file occurrence contributes to every
1027
+ * provider request in the current execution environment.
1028
+ * @param ref - durable verbatim file reference from model history.
1029
+ * @returns the same deterministic handle text used at adapter dispatch.
1030
+ */
1031
+ fileRequestText(ref) {
1032
+ return fileHandleText(ref, this.fileReadPath(ref));
1033
+ }
954
1034
  /** Detach typed adapter-owned modality metadata. */
955
1035
  detachedModalities(modalities) {
956
1036
  return modalities === void 0 ? void 0 : [...modalities];
@@ -1144,6 +1224,20 @@ var LlmError = class extends HarnessError {
1144
1224
  return Object.isFrozen(options) ? deepFreeze(filtered) : filtered;
1145
1225
  }
1146
1226
  /**
1227
+ * Resolve the current execution-world read path of one durable file
1228
+ * reference through the mounted attachment and filesystem providers.
1229
+ */
1230
+ fileReadPath(ref) {
1231
+ let hostPath;
1232
+ try {
1233
+ hostPath = this.ctx.get("attachments")?.fileHostPath(ref);
1234
+ } catch {
1235
+ return;
1236
+ }
1237
+ if (hostPath === void 0) return void 0;
1238
+ return this.ctx.get("fs")?.processPathFromHostPath(hostPath);
1239
+ }
1240
+ /**
1147
1241
  * Final adapter boundary. Adapter selection, dispatch, iterator construction,
1148
1242
  * and iteration failures become one terminal failure chunk. Middleware and
1149
1243
  * downstream consumer failures remain thrown plugin or consumer errors.
@@ -1174,13 +1268,16 @@ var LlmError = class extends HarnessError {
1174
1268
  ...options,
1175
1269
  ...resolvedConfig
1176
1270
  };
1177
- const projectedOptions = modelInfo.inputModalities !== void 0 && !modelInfo.inputModalities.includes("image") && resolvedOptions.messages.some((message) => contentHasImage(message.content)) ? Object.isFrozen(resolvedOptions) ? deepFreeze({
1271
+ let projectedMessages = resolvedOptions.messages;
1272
+ if (projectedMessages.some((message) => contentHasFile(message.content))) projectedMessages = projectFilesToText(projectedMessages, (ref) => this.fileReadPath(ref));
1273
+ if (modelInfo.inputModalities !== void 0 && !modelInfo.inputModalities.includes("image") && projectedMessages.some((message) => contentHasImage(message.content))) projectedMessages = projectImagesForTextModel(projectedMessages);
1274
+ const projectedOptions = projectedMessages === resolvedOptions.messages ? resolvedOptions : Object.isFrozen(resolvedOptions) ? deepFreeze({
1178
1275
  ...resolvedOptions,
1179
- messages: projectImagesForTextModel(resolvedOptions.messages)
1276
+ messages: projectedMessages
1180
1277
  }) : {
1181
1278
  ...resolvedOptions,
1182
- messages: projectImagesForTextModel(resolvedOptions.messages)
1183
- } : resolvedOptions;
1279
+ messages: projectedMessages
1280
+ };
1184
1281
  iterator = dispatch(this.forAdapter(projectedOptions, adapter))[Symbol.asyncIterator]();
1185
1282
  } catch (error) {
1186
1283
  yield adapterFailureChunk(error, options.signal);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-tmux-context",
3
3
  "description": "Opt-in durable per-step context with this agent's tmux pane and window location",
4
- "version": "0.1.2-alpha.5",
4
+ "version": "0.1.3-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -31,19 +31,19 @@
31
31
  "@deepseek-ai/schemastery": "^3.18.2"
32
32
  },
33
33
  "peerDependencies": {
34
- "@deepseek-ai/dsh-agent": "^0.1.2-alpha.5",
35
- "@deepseek-ai/dsh-shell": "^0.1.2-alpha.5",
36
- "@deepseek-ai/dsh-session": "^0.1.2-alpha.5",
34
+ "@deepseek-ai/dsh-agent": "^0.1.3-alpha.2",
35
+ "@deepseek-ai/dsh-shell": "^0.1.3-alpha.2",
36
+ "@deepseek-ai/dsh-session": "^0.1.3-alpha.2",
37
37
  "@deepseek-ai/cordis": "^4.0.2",
38
- "@deepseek-ai/dsh-session-projection": "^0.1.2-alpha.5"
38
+ "@deepseek-ai/dsh-session-projection": "^0.1.3-alpha.2"
39
39
  },
40
40
  "devDependencies": {
41
- "@deepseek-ai/dsh-agent": "^0.1.2-alpha.5",
42
- "@deepseek-ai/dsh-shell": "^0.1.2-alpha.5",
43
- "@deepseek-ai/dsh-llm": "^0.1.2-alpha.5",
44
- "@deepseek-ai/dsh-session": "^0.1.2-alpha.5",
45
- "@deepseek-ai/dsh-system-prompt": "^0.1.2-alpha.5",
46
- "@deepseek-ai/cordis": "^4.0.2",
47
- "@deepseek-ai/dsh-session-projection": "^0.1.2-alpha.5"
41
+ "@deepseek-ai/dsh-agent": "^0.1.3-alpha.2",
42
+ "@deepseek-ai/dsh-shell": "^0.1.3-alpha.2",
43
+ "@deepseek-ai/dsh-llm": "^0.1.3-alpha.2",
44
+ "@deepseek-ai/dsh-session": "^0.1.3-alpha.2",
45
+ "@deepseek-ai/dsh-system-prompt": "^0.1.3-alpha.2",
46
+ "@deepseek-ai/dsh-session-projection": "^0.1.3-alpha.2",
47
+ "@deepseek-ai/cordis": "^4.0.2"
48
48
  }
49
49
  }