nexrall-code 0.5.73 → 0.5.74

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 (2) hide show
  1. package/dist/index.js +50 -17
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -9873,6 +9873,7 @@ var require_client = __commonJS({
9873
9873
  exports.streamChat = streamChat;
9874
9874
  exports.cancelTurn = cancelTurn;
9875
9875
  exports.revokeRefreshToken = revokeRefreshToken2;
9876
+ exports.describeAttachment = describeAttachment2;
9876
9877
  exports.getBalance = getBalance3;
9877
9878
  exports.exchangeVscodeCode = exchangeVscodeCode;
9878
9879
  exports.login = login2;
@@ -10596,6 +10597,37 @@ var require_client = __commonJS({
10596
10597
  } catch {
10597
10598
  }
10598
10599
  }
10600
+ async function describeAttachment2(kind, data, mediaType, name) {
10601
+ const fetchOnce = () => (0, node_fetch_1.default)(`${exports.API_BASE}/api/code/assets/describe`, {
10602
+ method: "POST",
10603
+ headers: { ...authHeaders(), "Content-Type": "application/json" },
10604
+ body: JSON.stringify({ kind, data, media_type: mediaType, name })
10605
+ });
10606
+ let response = await fetchOnce();
10607
+ if (response.status === 401 || response.status === 403) {
10608
+ const body = await response.text().catch(() => "");
10609
+ if (isExpiredTokenResponse(response.status, body) && await refreshAccessToken()) {
10610
+ response = await fetchOnce();
10611
+ } else {
10612
+ throw new Error(`API error ${response.status}: ${body}`);
10613
+ }
10614
+ }
10615
+ if (!response.ok) {
10616
+ let message = `API error ${response.status}`;
10617
+ try {
10618
+ const body = await response.json();
10619
+ if (body?.error)
10620
+ message = body.error;
10621
+ } catch {
10622
+ }
10623
+ throw new Error(message);
10624
+ }
10625
+ const json = await response.json();
10626
+ return {
10627
+ text: typeof json.text === "string" ? json.text : "",
10628
+ balance: typeof json.balance === "number" ? json.balance : 0
10629
+ };
10630
+ }
10599
10631
  async function getBalance3() {
10600
10632
  const fetchOnce = () => (0, node_fetch_1.default)(`${exports.API_BASE}/api/code/balance`, { method: "GET", headers: authHeaders() });
10601
10633
  let response = await fetchOnce();
@@ -66113,20 +66145,6 @@ ${content}
66113
66145
  return;
66114
66146
  }
66115
66147
  const model = normaliseModelId(modelAlias);
66116
- if (isPdf && NO_PDF_MODELS.has(model)) {
66117
- console.log(source_default.red(
66118
- ` ${resolveModelLabel(modelAlias)} does not support PDF attachments. Switch models with /model (Claude models support PDFs), or extract the text yourself and use /add instead.`
66119
- ));
66120
- rl.prompt();
66121
- return;
66122
- }
66123
- if (!isPdf && NO_VISION_MODELS.has(model)) {
66124
- console.log(source_default.red(
66125
- ` ${resolveModelLabel(modelAlias)} does not support image input. Switch models with /model, or attach as text with /add instead.`
66126
- ));
66127
- rl.prompt();
66128
- return;
66129
- }
66130
66148
  let buf;
66131
66149
  try {
66132
66150
  buf = fs8.readFileSync(filePath);
@@ -66146,9 +66164,24 @@ ${content}
66146
66164
  const label = caption ? `[Attached: ${rel}]
66147
66165
  ${caption}` : `[Attached: ${rel}]`;
66148
66166
  const content = [{ type: "text", text: label }];
66149
- content.push(
66150
- isPdf ? { type: "document", source: { type: "base64", media_type: "application/pdf", data } } : { type: "image", source: { type: "base64", media_type: mimeType, data } }
66151
- );
66167
+ const needsSidecar = isPdf ? NO_PDF_MODELS.has(model) : NO_VISION_MODELS.has(model);
66168
+ if (needsSidecar) {
66169
+ console.log(source_default.dim(` ${resolveModelLabel(modelAlias)} can't read ${isPdf ? "PDFs" : "images"} directly \u2014 describing ${rel} with Claude Sonnet 5 first\u2026`));
66170
+ try {
66171
+ const { text } = await (0, import_code_core3.describeAttachment)(isPdf ? "pdf" : "image", data, mimeType, rel);
66172
+ content.push({ type: "text", text: `<attachment_description>
66173
+ ${text}
66174
+ </attachment_description>` });
66175
+ } catch (err) {
66176
+ console.log(source_default.red(` Could not describe ${rel}: ${err.message}`));
66177
+ rl.prompt();
66178
+ return;
66179
+ }
66180
+ } else {
66181
+ content.push(
66182
+ isPdf ? { type: "document", source: { type: "base64", media_type: "application/pdf", data } } : { type: "image", source: { type: "base64", media_type: mimeType, data } }
66183
+ );
66184
+ }
66152
66185
  console.log(source_default.dim(` Attached ${rel} (${(buf.length / 1024).toFixed(0)}KB) \u2014 sending\u2026`));
66153
66186
  checkpoints.beginTurn(`/image ${rel}${caption ? " " + caption : ""}`, messages.length);
66154
66187
  messages.push({ role: "user", content });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nexrall-code",
3
- "version": "0.5.73",
3
+ "version": "0.5.74",
4
4
  "description": "Nexrall Code — AI coding assistant for your terminal (headless agent for scripts, CI and automation)",
5
5
  "keywords": [
6
6
  "ai",
@@ -39,7 +39,7 @@
39
39
  "release": "node build.js && node scripts/upload-release.cjs"
40
40
  },
41
41
  "dependencies": {
42
- "@nexrall/code-core": "^1.4.43",
42
+ "@nexrall/code-core": "^1.4.44",
43
43
  "chalk": "^5.3.0",
44
44
  "commander": "^12.0.0",
45
45
  "diff": "^5.2.0",