teapot-coding-agent 0.37.93 → 0.37.94

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.
@@ -1794,7 +1794,7 @@ export class Agent {
1794
1794
  reasoning: partial.reasoning,
1795
1795
  interrupted: true,
1796
1796
  });
1797
- this.messages.push({ role: "assistant", content: partial.text ?? "" });
1797
+ this.messages.push(assistantTurn({ role: "assistant", content: partial.text ?? "" }, partial.reasoning));
1798
1798
  }
1799
1799
  else if (this.stopRequested) {
1800
1800
  await this.log.append("system_note", this.currentSession, this.currentBranch, {
@@ -1861,16 +1861,8 @@ export class Agent {
1861
1861
  };
1862
1862
  await this.log.append("usage", this.currentSession, this.currentBranch, res.usage);
1863
1863
  }
1864
- const m = res.message;
1865
- /**
1866
- * Carry the thinking on the message itself, not only in the log.
1867
- *
1868
- * `res.reasoning` was written to `chat.jsonl` and then dropped: `this.messages.push(m)` stored a
1869
- * message with no reasoning, so the NEXT request sent back an assistant turn with its thinking
1870
- * missing. Providers that require it (Beam, #187) answered 400; the rest simply lost the thread.
1871
- */
1872
- if (res.reasoning && !m.reasoning)
1873
- m.reasoning = res.reasoning;
1864
+ // `assistantTurn` carries the thinking, which is what `reasoning_content` is sent from (#187)
1865
+ const m = assistantTurn(res.message, res.reasoning);
1874
1866
  const isPlaceholder = m.content === "(tool call)" || m.content === "(no content)";
1875
1867
  await this.log.append("message", this.currentSession, this.currentBranch, {
1876
1868
  role: "assistant",
@@ -2193,7 +2185,7 @@ export class Agent {
2193
2185
  await step({ step: "reply", text: text.slice(0, 400) });
2194
2186
  return text;
2195
2187
  }
2196
- messages.push({ role: "assistant", content: text, tool_calls: calls });
2188
+ messages.push(assistantTurn({ role: "assistant", content: text, tool_calls: calls }, res.reasoning));
2197
2189
  for (const call of calls) {
2198
2190
  await step({ step: "tool", name: call.function?.name, args: String(call.function?.arguments ?? "").slice(0, 200) });
2199
2191
  let out;
@@ -2226,6 +2218,22 @@ export class Agent {
2226
2218
  async handleFinish(argsJson) {
2227
2219
  const args = safeParse(argsJson);
2228
2220
  if (args.goalComplete === true && this.goal.status !== "done") {
2221
+ /**
2222
+ * A PAUSED goal is not the agent's to complete.
2223
+ *
2224
+ * `paused` means the operator took the goal off the agent's hands, so a `finish(goalComplete)`
2225
+ * must not run the audit — reported as "goal pausedでもgoal auditが動く". It also must not flip the
2226
+ * status to done: that would silently undo the pause. The final message is still appended, because
2227
+ * the work itself is real and the operator should see the summary.
2228
+ */
2229
+ if (this.goal.status === "paused") {
2230
+ await this.log.append("system_note", this.currentSession, this.currentBranch, {
2231
+ event: "finish-ignored-while-paused",
2232
+ detail: "the goal is paused, so a completion claim neither runs the audit nor marks it done",
2233
+ });
2234
+ await this.appendFinalMessage(args);
2235
+ return;
2236
+ }
2229
2237
  if (this.goal.verify?.trim()) {
2230
2238
  await this.log.append("goal", this.currentSession, this.currentBranch, {
2231
2239
  event: "audit-started",
@@ -2975,6 +2983,23 @@ function safeParse(json) {
2975
2983
  return {};
2976
2984
  }
2977
2985
  }
2986
+ /**
2987
+ * The conversation entry for a reply, with its thinking attached.
2988
+ *
2989
+ * THREE places used to build this by hand — the main loop, the AUDITOR's loop, and the interrupted-partial
2990
+ * path — and each independently forgot `reasoning`, which is what `reasoning_content` is derived from
2991
+ * (#187). MEASURED consequences: every audit attempt on `mizuki-rakutenai-3-205c7912` died with
2992
+ * `messages[1].reasoning_content` (index 1 IS the auditor's synthetic assistant turn) and the run ended
2993
+ * at `audit-unavailable-cap`, while the main loop had already been fixed.
2994
+ *
2995
+ * One builder means a fourth caller cannot be forgotten.
2996
+ */
2997
+ function assistantTurn(m, reasoning) {
2998
+ const out = { ...m };
2999
+ if (reasoning && !out.reasoning)
3000
+ out.reasoning = reasoning;
3001
+ return out;
3002
+ }
2978
3003
  function lineageOf(events) {
2979
3004
  if (events.length === 0)
2980
3005
  return [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "teapot-coding-agent",
3
- "version": "0.37.93",
3
+ "version": "0.37.94",
4
4
  "description": "A lightweight, always-on multi-agent harness for AI coding agents",
5
5
  "type": "module",
6
6
  "license": "AGPL-3.0-or-later",