manualofme-bridge 0.2.0 → 0.2.1

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/cli.js +47 -20
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -4257,6 +4257,11 @@ var init_session = __esm({
4257
4257
  }
4258
4258
  sdk;
4259
4259
  abort = null;
4260
+ /**
4261
+ * Query của lượt đã xong nhưng chưa đóng: Claude bật tác vụ nền (server, tunnel...) thì SDK
4262
+ * còn chạy tiếp tới khi tác vụ đó tắt. Gửi tin mới / đổi session thì đóng nó trước.
4263
+ */
4264
+ tail = null;
4260
4265
  pending = /* @__PURE__ */ new Map();
4261
4266
  get sessionId() {
4262
4267
  return this.deps.state.sessionId;
@@ -4311,6 +4316,7 @@ var init_session = __esm({
4311
4316
  }
4312
4317
  async open(sessionId) {
4313
4318
  if (this.busy) throw new BridgeError("Claude \u0111ang ch\u1EA1y, d\u1EEBng l\u01B0\u1EE3t n\xE0y tr\u01B0\u1EDBc khi \u0111\u1ED5i session");
4319
+ this.closeTail();
4314
4320
  this.deps.state.sessionId = sessionId;
4315
4321
  this.deps.broadcast(this.stateMessage());
4316
4322
  const history = await this.historyMessage();
@@ -4327,6 +4333,7 @@ var init_session = __esm({
4327
4333
  throw new BridgeError("Kh\xF4ng l\u01B0u \u0111\u01B0\u1EE3c t\u1EC7p \u0111\xEDnh k\xE8m tr\xEAn PC");
4328
4334
  }
4329
4335
  const text = promptWithFiles(input, paths);
4336
+ this.closeTail();
4330
4337
  const abort = new AbortController();
4331
4338
  this.abort = abort;
4332
4339
  this.deps.broadcast(this.stateMessage());
@@ -4350,6 +4357,11 @@ var init_session = __esm({
4350
4357
  this.setOptions({ permissionMode: "default" });
4351
4358
  }
4352
4359
  }
4360
+ closeTail() {
4361
+ const tail = this.tail;
4362
+ this.tail = null;
4363
+ tail?.close();
4364
+ }
4353
4365
  async run(text, abort) {
4354
4366
  const { config: config2, broadcast, push } = this.deps;
4355
4367
  const started = Date.now();
@@ -4357,9 +4369,31 @@ var init_session = __esm({
4357
4369
  let resultText = "";
4358
4370
  let costUsd = 0;
4359
4371
  let durationMs = 0;
4372
+ let ended = false;
4360
4373
  const mode = this.permissionMode;
4374
+ const endTurn = () => {
4375
+ if (ended) return;
4376
+ ended = true;
4377
+ if (this.abort === abort) this.abort = null;
4378
+ for (const p of this.pending.values())
4379
+ p.finish({ behavior: "deny", message: "L\u01B0\u1EE3t \u0111\xE3 k\u1EBFt th\xFAc" });
4380
+ if (!durationMs) durationMs = Date.now() - started;
4381
+ if (!ok && !resultText) resultText = abort.signal.aborted ? "\u0110\xE3 d\u1EEBng" : "L\u1ED7i kh\xF4ng r\xF5";
4382
+ const sessionId = this.sessionId;
4383
+ broadcast({ type: "turn_end", sessionId, ok, text: resultText, costUsd, durationMs });
4384
+ broadcast(this.stateMessage());
4385
+ if (!abort.signal.aborted) {
4386
+ void push({
4387
+ event: "turn_end",
4388
+ title: ok ? "Claude xong vi\u1EC7c" : "Claude g\u1EB7p l\u1ED7i",
4389
+ body: resultText || "(kh\xF4ng c\xF3 n\u1ED9i dung)",
4390
+ sessionId
4391
+ });
4392
+ }
4393
+ };
4394
+ let q = null;
4361
4395
  try {
4362
- const q = this.sdk.query({
4396
+ q = this.sdk.query({
4363
4397
  prompt: text,
4364
4398
  options: {
4365
4399
  cwd: config2.cwd,
@@ -4376,6 +4410,7 @@ var init_session = __esm({
4376
4410
  systemPrompt: { type: "preset", preset: "claude_code", append: APPEND_PROMPT }
4377
4411
  }
4378
4412
  });
4413
+ this.tail = q;
4379
4414
  for await (const msg of q) {
4380
4415
  if (msg.type === "system" && msg.subtype === "init") {
4381
4416
  if (msg.session_id !== this.sessionId) {
@@ -4385,33 +4420,25 @@ var init_session = __esm({
4385
4420
  } else if (msg.type === "assistant") {
4386
4421
  for (const item of toChatItems(msg))
4387
4422
  broadcast({ type: "item", sessionId: this.sessionId, item });
4388
- } else if (msg.type === "result") {
4423
+ } else if (msg.type === "result" && !ended) {
4389
4424
  ok = msg.subtype === "success" && !msg.is_error;
4390
4425
  resultText = msg.subtype === "success" ? msg.result : msg.errors.join("\n") || msg.subtype;
4391
4426
  costUsd = msg.total_cost_usd;
4392
4427
  durationMs = msg.duration_ms;
4428
+ endTurn();
4393
4429
  }
4394
4430
  }
4395
4431
  } catch (e) {
4396
- ok = false;
4397
- resultText = abort.signal.aborted ? "\u0110\xE3 d\u1EEBng" : errorText(e);
4432
+ if (!ended) {
4433
+ ok = false;
4434
+ resultText = abort.signal.aborted ? "\u0110\xE3 d\u1EEBng" : errorText(e);
4435
+ }
4398
4436
  } finally {
4399
- this.abort = null;
4400
- for (const p of this.pending.values())
4401
- p.finish({ behavior: "deny", message: "L\u01B0\u1EE3t \u0111\xE3 k\u1EBFt th\xFAc" });
4402
- }
4403
- if (!durationMs) durationMs = Date.now() - started;
4404
- if (!ok && !resultText) resultText = abort.signal.aborted ? "\u0110\xE3 d\u1EEBng" : "L\u1ED7i kh\xF4ng r\xF5";
4405
- const sessionId = this.sessionId;
4406
- broadcast({ type: "turn_end", sessionId, ok, text: resultText, costUsd, durationMs });
4407
- broadcast(this.stateMessage());
4408
- if (!abort.signal.aborted) {
4409
- void push({
4410
- event: "turn_end",
4411
- title: ok ? "Claude xong vi\u1EC7c" : "Claude g\u1EB7p l\u1ED7i",
4412
- body: resultText || "(kh\xF4ng c\xF3 n\u1ED9i dung)",
4413
- sessionId
4414
- });
4437
+ if (q && this.tail === q) this.tail = null;
4438
+ endTurn();
4439
+ if (!this.busy)
4440
+ for (const p of this.pending.values())
4441
+ p.finish({ behavior: "deny", message: "L\u01B0\u1EE3t \u0111\xE3 k\u1EBFt th\xFAc" });
4415
4442
  }
4416
4443
  }
4417
4444
  canUseTool = (toolName, input, opts) => new Promise((resolve) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "manualofme-bridge",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Điều khiển Claude Code trên máy từ web/app ManualOfMe",
5
5
  "type": "module",
6
6
  "bin": {