@q-agent/agent 0.1.24 → 0.1.26

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/dist/src/api.js CHANGED
@@ -58,6 +58,7 @@ exports.postExploreFinalize = postExploreFinalize;
58
58
  exports.postComplete = postComplete;
59
59
  exports.claimNextAuthoring = claimNextAuthoring;
60
60
  exports.postAuthoringEvent = postAuthoringEvent;
61
+ exports.postAuthoringEventAlive = postAuthoringEventAlive;
61
62
  exports.postAuthoringFinalize = postAuthoringFinalize;
62
63
  const fs = __importStar(require("fs"));
63
64
  /** Raised for any non-2xx/204 response; carries the HTTP status for callers that care (e.g. 409). */
@@ -311,6 +312,26 @@ async function postAuthoringEvent(cfg, sessionId, event, payload) {
311
312
  });
312
313
  await throwIfNotOk(res);
313
314
  }
315
+ /**
316
+ * Post an authoring progress event and report whether the session is still alive
317
+ * (#420). Returns false on a 404 — the server purged the session because the run
318
+ * was stopped — which the caller uses as a mid-flight abort signal to kill the
319
+ * local Claude run. Never throws: a transient network error returns true so a
320
+ * blip doesn't abort a live session.
321
+ */
322
+ async function postAuthoringEventAlive(cfg, sessionId, event, payload) {
323
+ try {
324
+ const res = await fetch(`${cfg.serverUrl}/agent/authoring/${sessionId}/events`, {
325
+ method: "POST",
326
+ headers: { ...authHeaders(cfg.deviceToken), "Content-Type": "application/json" },
327
+ body: JSON.stringify({ event, payload }),
328
+ });
329
+ return res.status !== 404;
330
+ }
331
+ catch {
332
+ return true;
333
+ }
334
+ }
314
335
  /** Finalize an authoring session: the server gates + persists the authored spec
315
336
  * and KB-merges the runtime-verified discovery. */
316
337
  async function postAuthoringFinalize(cfg, sessionId, body) {
@@ -76,6 +76,7 @@ async function ensureChromium() {
76
76
  const code = await new Promise((resolve) => {
77
77
  const child = (0, child_process_1.spawn)((0, paths_1.nodeBin)(), [(0, paths_1.playwrightCli)(), "install", "chromium"], {
78
78
  stdio: "inherit",
79
+ windowsHide: true,
79
80
  env: { ...process.env, ...(0, paths_1.childNodeEnv)() },
80
81
  });
81
82
  child.on("close", resolve);
@@ -68,7 +68,13 @@ function browserHarnessBinDir() {
68
68
  * Inherits stdio so first-run downloads/installs are visible in the agent log. */
69
69
  function run(cmd, args, env) {
70
70
  return new Promise((resolve) => {
71
- const child = (0, child_process_1.spawn)(cmd, args, { stdio: "inherit", env: { ...process.env, ...env } });
71
+ // windowsHide: don't pop a console window for the uv/tar/browser-harness probe
72
+ // when the agent runs as a GUI (Electron) process with no console of its own.
73
+ const child = (0, child_process_1.spawn)(cmd, args, {
74
+ stdio: "inherit",
75
+ windowsHide: true,
76
+ env: { ...process.env, ...env },
77
+ });
72
78
  child.on("close", resolve);
73
79
  child.on("error", () => resolve(null));
74
80
  });
@@ -1095,16 +1095,29 @@ async function processAuthoringJob(cfg, job) {
1095
1095
  });
1096
1096
  activeChild = claude;
1097
1097
  // Surface each step to the agent console + the run WebSocket so the operator
1098
- // can watch Claude drive browser-harness live.
1098
+ // can watch Claude drive browser-harness live. Each post also reports whether
1099
+ // the session is still alive: a 404 means the run was stopped server-side
1100
+ // (#420), so abort the local Claude run immediately instead of burning the
1101
+ // rest of the budget on work whose result will be rejected anyway.
1102
+ let aborted = false;
1099
1103
  const emitStep = (line) => {
1100
1104
  const trimmed = line.length > 300 ? line.slice(0, 300) + "…" : line;
1101
1105
  console.log(`[authoring ${job.caseId}] ${trimmed}`);
1102
1106
  (0, bus_1.emit)("authoring-step", { caseId: job.caseId, line: trimmed });
1103
1107
  void api
1104
- .postAuthoringEvent(cfg, job.sessionId, "authoring.progress", {
1108
+ .postAuthoringEventAlive(cfg, job.sessionId, "authoring.progress", {
1105
1109
  case: job.caseId, phase: "step", message: trimmed,
1106
1110
  })
1107
- .catch(() => { });
1111
+ .then((alive) => {
1112
+ if (!alive && !aborted) {
1113
+ aborted = true;
1114
+ console.log(`[authoring ${job.caseId}] session gone — run stopped; aborting Claude`);
1115
+ try {
1116
+ claude?.kill();
1117
+ }
1118
+ catch { /* already exited */ }
1119
+ }
1120
+ });
1108
1121
  };
1109
1122
  let cerr = "";
1110
1123
  let finalResult = "";
package/dist/src/ui.js CHANGED
@@ -503,6 +503,7 @@ function logColor(t){
503
503
  if (t === "auth-captured") return "#6ee7b7";
504
504
  if (t === "job-claimed") return "#c4b5fd";
505
505
  if (t === "job-complete") return "#6ee7b7";
506
+ if (t === "authoring-step") return "#c3c3d0";
506
507
  return "#8b8b9e";
507
508
  }
508
509
  function logMsg(ev){
@@ -516,6 +517,7 @@ function logMsg(ev){
516
517
  case "job-complete": return "execution #" + ev.executionId + " complete \\u00b7 " + ev.passed + " passed, " + ev.failed + " failed";
517
518
  case "error": return ev.message || "error";
518
519
  case "log": return ev.message || "";
520
+ case "authoring-step": return ev.line || null; // live authoring / self-heal steps (#400/#428)
519
521
  default: return null;
520
522
  }
521
523
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@q-agent/agent",
3
- "version": "0.1.24",
3
+ "version": "0.1.26",
4
4
  "description": "Q-Agent Local Agent — claims execution jobs from the Q-Agent server and runs Playwright locally, so manual login/MFA happens on the user's own machine and session credentials never leave it.",
5
5
  "license": "UNLICENSED",
6
6
  "bin": {