codeam-cli 2.4.38 → 2.4.39

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 +63 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1482,7 +1482,7 @@ var import_qrcode_terminal = __toESM(require("qrcode-terminal"));
1482
1482
  // package.json
1483
1483
  var package_default = {
1484
1484
  name: "codeam-cli",
1485
- version: "2.4.38",
1485
+ version: "2.4.39",
1486
1486
  description: "Remote control Claude Code (and other AI coding agents) from your mobile phone. Pair your device, send prompts, stream responses in real-time, and approve commands \u2014 from anywhere.",
1487
1487
  type: "commonjs",
1488
1488
  main: "dist/index.js",
@@ -5499,6 +5499,14 @@ var HistoryService = class {
5499
5499
  _rateLimitReset = null;
5500
5500
  _quotaPercent = null;
5501
5501
  _quotaFetchedAt = 0;
5502
+ /**
5503
+ * Per-conversation marker of the last message uuid we successfully
5504
+ * uploaded to the backend. `uploadDelta()` reads the JSONL,
5505
+ * filters out everything up to and including this uuid, and
5506
+ * uploads only the tail. Resets per conversation so a session
5507
+ * resume re-uploads the full transcript on first call.
5508
+ */
5509
+ lastUploadedUuid = /* @__PURE__ */ new Map();
5502
5510
  /** Store rate limit reset info detected from Claude Code output */
5503
5511
  setRateLimitReset(reset) {
5504
5512
  this._rateLimitReset = reset;
@@ -5775,6 +5783,54 @@ var HistoryService = class {
5775
5783
  throw new Error(`Failed to upload conversation batch ${i + 1}/${totalBatches} after all retries`);
5776
5784
  }
5777
5785
  }
5786
+ const last = messages[messages.length - 1];
5787
+ if (last) this.lastUploadedUuid.set(sessionId, last.id);
5788
+ }
5789
+ /**
5790
+ * Incremental upload — ships only the messages added since the last
5791
+ * `loadConversation` / `uploadDelta` call for this conversation.
5792
+ * Used by `onTurnComplete` after every turn so the backend's
5793
+ * conversation table stays fresh enough for the SSE consumers
5794
+ * (mobile + web dashboard) to fetch the canonical markdown via
5795
+ * `?last=N` and replace the streaming-from-PTY approximation —
5796
+ * which lacks the markdown ``` fences the parser needs to surface
5797
+ * the rich CodeBlock / DiffBlock / etc. components.
5798
+ *
5799
+ * Posts under `mode: 'append'` so the server merges by uuid
5800
+ * instead of replacing the full conversation. Idempotent — if
5801
+ * called twice in a row the second call sees zero new messages
5802
+ * and is a no-op.
5803
+ *
5804
+ * Returns the number of messages uploaded (0 means nothing new).
5805
+ */
5806
+ async uploadDelta() {
5807
+ if (!this.currentConversationId) return 0;
5808
+ const sessionId = this.currentConversationId;
5809
+ const filePath = path8.join(this.projectDir, `${sessionId}.jsonl`);
5810
+ const messages = parseJsonl(filePath);
5811
+ if (messages.length === 0) return 0;
5812
+ const marker = this.lastUploadedUuid.get(sessionId);
5813
+ let newMessages = messages;
5814
+ if (marker) {
5815
+ const idx = messages.findIndex((m) => m.id === marker);
5816
+ if (idx >= 0) {
5817
+ newMessages = messages.slice(idx + 1);
5818
+ }
5819
+ }
5820
+ if (newMessages.length === 0) return 0;
5821
+ const body = {
5822
+ pluginId: this.pluginId,
5823
+ sessionId,
5824
+ messages: newMessages,
5825
+ mode: "append"
5826
+ };
5827
+ const ok = await post("/api/sessions/claude-conversation", body);
5828
+ if (ok) {
5829
+ const last = newMessages[newMessages.length - 1];
5830
+ this.lastUploadedUuid.set(sessionId, last.id);
5831
+ return newMessages.length;
5832
+ }
5833
+ return 0;
5778
5834
  }
5779
5835
  };
5780
5836
 
@@ -6344,6 +6400,10 @@ except Exception:sys.exit(0)
6344
6400
  if (historySvc.isQuotaStale()) {
6345
6401
  fetchQuotaUsage();
6346
6402
  }
6403
+ setTimeout(() => {
6404
+ historySvc.uploadDelta().catch(() => {
6405
+ });
6406
+ }, 400);
6347
6407
  }, () => {
6348
6408
  const prevCount = historySvc.getCurrentMessageCount();
6349
6409
  historySvc.waitForNewUserMessage(prevCount).then((userText) => outputSvc.startTerminalTurn(userText ?? void 0)).catch(() => outputSvc.startTerminalTurn(void 0));
@@ -9041,7 +9101,7 @@ async function stopWorkspaceFromLocal(target) {
9041
9101
  // src/commands/version.ts
9042
9102
  var import_picocolors11 = __toESM(require("picocolors"));
9043
9103
  function version() {
9044
- const v = true ? "2.4.38" : "unknown";
9104
+ const v = true ? "2.4.39" : "unknown";
9045
9105
  console.log(`${import_picocolors11.default.bold("codeam-cli")} ${import_picocolors11.default.cyan(v)}`);
9046
9106
  }
9047
9107
 
@@ -9176,7 +9236,7 @@ function checkForUpdates() {
9176
9236
  if (process.env.CODEAM_DISABLE_UPDATE_CHECK === "1") return;
9177
9237
  if (process.env.CI) return;
9178
9238
  if (!process.stdout.isTTY) return;
9179
- const current = true ? "2.4.38" : null;
9239
+ const current = true ? "2.4.39" : null;
9180
9240
  if (!current) return;
9181
9241
  const cache = readCache();
9182
9242
  const fresh = cache && Date.now() - cache.fetchedAt < TTL_MS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codeam-cli",
3
- "version": "2.4.38",
3
+ "version": "2.4.39",
4
4
  "description": "Remote control Claude Code (and other AI coding agents) from your mobile phone. Pair your device, send prompts, stream responses in real-time, and approve commands — from anywhere.",
5
5
  "type": "commonjs",
6
6
  "main": "dist/index.js",