antechamber 0.2.32 → 0.2.34

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
@@ -7,6 +7,21 @@ and this project uses [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.2.34] - 2026-10-19
11
+
12
+ ### Fixed
13
+
14
+ - Accept uploaded attachments other than images and text, such as PDFs, instead of failing the prompt with
15
+ `Unsupported inline attachment MIME type`. The file is saved under the state directory's `attachments/`
16
+ folder and passed to the agent as a file reference it can read with its own tools.
17
+
18
+ ## [0.2.33] - 2026-10-19
19
+
20
+ ### Fixed
21
+
22
+ - Restore subagent costs and token totals before listing sessions, so OpenChamber includes
23
+ retained child spend without requiring each child transcript to be opened.
24
+
10
25
  ## [0.2.32] - 2026-10-19
11
26
 
12
27
  ### Fixed
@@ -1,4 +1,9 @@
1
1
  /** Lossless user parts on the wire, adapted to the native text/images RPC. */
2
+ import { createHash } from "node:crypto";
3
+ import { existsSync, mkdirSync, renameSync, writeFileSync } from "node:fs";
4
+ import { basename, join, resolve } from "node:path";
5
+ import { pathToFileURL } from "node:url";
6
+ import { defaultStateDir, envSetting } from "./config.js";
2
7
  import { RequestBodyError } from "./http.js";
3
8
  export function isPromptPart(value) {
4
9
  if (typeof value !== "object" || value === null || !("type" in value))
@@ -121,6 +126,25 @@ export function contextMessageID(entry) {
121
126
  return undefined;
122
127
  return typeof entry.details.messageID === "string" ? entry.details.messageID : undefined;
123
128
  }
129
+ /**
130
+ * Saves inline attachment bytes the native RPC cannot carry under `<state dir>/attachments`.
131
+ * The path is content-addressed, so re-deriving a prompt (admission checks, history binding)
132
+ * names the same file and recreates it if it was removed.
133
+ */
134
+ function storeInlineAttachment(content, filename) {
135
+ const digest = createHash("sha256").update(content).digest("hex");
136
+ const root = join(resolve(envSetting("STATE_DIR") ?? defaultStateDir()), "attachments");
137
+ const dir = join(root, digest);
138
+ const name = basename(filename ?? "").replaceAll("\0", "");
139
+ const path = join(dir, name === "" || name === "." || name === ".." ? "attachment" : name);
140
+ if (!existsSync(path)) {
141
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
142
+ const partial = `${path}.${process.pid}.partial`;
143
+ writeFileSync(partial, content, { mode: 0o600 });
144
+ renameSync(partial, path);
145
+ }
146
+ return path;
147
+ }
124
148
  export function nativePromptInput(text, parts) {
125
149
  const chunks = [text];
126
150
  const images = [];
@@ -141,8 +165,12 @@ export function nativePromptInput(text, parts) {
141
165
  images.push({ type: "image", data: content.toString("base64"), mimeType: part.mime });
142
166
  else if (part.mime.startsWith("text/"))
143
167
  chunks.push(`${part.filename ?? "attachment"} (${part.mime}):\n${content.toString("utf8")}`);
144
- else
145
- throw new RequestBodyError(400, `Unsupported inline attachment MIME type: ${part.mime}`);
168
+ else {
169
+ // Native RPC has no generic FilePart: save the bytes and hand the agent a file
170
+ // reference, as for workspace files below, so its own tools can read e.g. a PDF.
171
+ const url = pathToFileURL(storeInlineAttachment(content, part.filename)).href;
172
+ chunks.push(JSON.stringify({ filename: part.filename, mime: part.mime, url }));
173
+ }
146
174
  }
147
175
  else {
148
176
  // Native RPC has no generic FilePart; retain the reference in model
package/dist/subagents.js CHANGED
@@ -446,6 +446,7 @@ export class SubagentBridge {
446
446
  return undefined;
447
447
  const child = this.create(this.detachedParent(entry.parentID, entry.directory, entry), entry.task);
448
448
  child.session.info.title = entry.title ?? child.session.info.title;
449
+ this.refresh(child, false);
449
450
  return child.session;
450
451
  }
451
452
  /**
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber-omo-compat",
3
- "version": "0.2.32",
3
+ "version": "0.2.34",
4
4
  "description": "OpenChamber extension: displays OmO tool calls the way OmO means them when OpenChamber runs on antechamber",
5
5
  "private": true,
6
6
  "type": "module",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber-omo-graph",
3
- "version": "0.2.32",
3
+ "version": "0.2.34",
4
4
  "description": "OpenChamber extension: live, interactive graph of the OmO sub-agents behind the current session",
5
5
  "private": true,
6
6
  "type": "module",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antechamber",
3
- "version": "0.2.32",
3
+ "version": "0.2.34",
4
4
  "description": "OpenCode-compatible HTTP/SSE server that lets OpenChamber drive the pi coding agent (and OmO) over RPC",
5
5
  "type": "module",
6
6
  "license": "MIT",