@tiens.nguyen/gonext-local-worker 1.0.302 → 1.0.304

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.
@@ -1905,6 +1905,9 @@ async function runAgentChatJob(job) {
1905
1905
  agentModelId: payload?.agentModelId ?? "",
1906
1906
  codingBaseURL: payload?.codingBaseURL ?? "",
1907
1907
  codingModelId: payload?.codingModelId ?? "",
1908
+ // Task #107: when true, python emits a {type:code_response} event per code-model
1909
+ // call so the worker persists the full raw text to Mongo.
1910
+ saveFullResponse: payload?.saveFullResponse === true,
1908
1911
  // Dedicated SEARCH model (#105): when set, web_search synthesizes its results into a
1909
1912
  // cited answer with this model instead of returning raw read pages. Empty = no synth.
1910
1913
  searchBaseURL: payload?.searchBaseURL ?? "",
@@ -2170,6 +2173,20 @@ async function runAgentChatJob(job) {
2170
2173
  }),
2171
2174
  }).catch(() => {});
2172
2175
  }
2176
+ } else if (event.type === "code_response" && typeof event.text === "string") {
2177
+ // Task #107: the user's Save-Full-Response toggle is on — persist this code-model
2178
+ // response's full raw text to Mongo. Fire-and-forget; never blocks the turn.
2179
+ workerFetch(`/api/worker/agent-response`, {
2180
+ method: "POST",
2181
+ body: JSON.stringify({
2182
+ jobId,
2183
+ step: Number.isFinite(event.step) ? event.step : 0,
2184
+ text: event.text,
2185
+ inputTokens: Number.isFinite(event.inputTokens) ? event.inputTokens : 0,
2186
+ outputTokens: Number.isFinite(event.outputTokens) ? event.outputTokens : 0,
2187
+ codingUrl: payload?.codingBaseURL ?? "",
2188
+ }),
2189
+ }).catch(() => {});
2173
2190
  } else if (event.type === "final" && typeof event.text === "string") {
2174
2191
  closeStreamFence();
2175
2192
  if (inThink) {
package/gonext-repl.mjs CHANGED
@@ -2071,21 +2071,22 @@ async function main() {
2071
2071
  continue;
2072
2072
  }
2073
2073
  if (line === "/reset-output-token-global") {
2074
- // Task #104: zero the GLOBAL (user + coding-URL) output-token counter after confirm.
2074
+ // Task #104: zero the GLOBAL (user + coding-URL) output-token counter AND clear all
2075
+ // per-workspace counters, after confirm.
2075
2076
  const ok = await askYesNo(
2076
- `Reset the GLOBAL output-token total (currently ${fmtTokens(globalOutputTokens)}) to 0?`,
2077
+ `Reset the GLOBAL output-token total (currently ${fmtTokens(globalOutputTokens)}) to 0? This also clears every workspace's output-token total.`,
2077
2078
  false
2078
2079
  );
2079
2080
  if (!ok) {
2080
- console.log(dim("Cancelled — global output-token total unchanged.\n"));
2081
+ console.log(dim("Cancelled — output-token totals unchanged.\n"));
2081
2082
  continue;
2082
2083
  }
2083
2084
  const done = await resetGlobalOutputTokens();
2084
2085
  if (done) {
2085
2086
  globalOutputTokens = 0;
2086
- console.log(green("✓ global output-token total reset to 0.\n"));
2087
+ console.log(green("✓ global + workspace output-token totals reset to 0.\n"));
2087
2088
  } else {
2088
- console.log(dim("Could not reset the global output-token total (API error).\n"));
2089
+ console.log(dim("Could not reset the output-token totals (API error).\n"));
2089
2090
  }
2090
2091
  continue;
2091
2092
  }
@@ -3117,6 +3117,8 @@ def run_agent_chat(cfg):
3117
3117
  # also fixes an older API layer that appended /v1 after the native /api path).
3118
3118
  raw_coding_base = _normalize_openai_base(cfg.get("codingBaseURL") or "")
3119
3119
  raw_coding_model = (cfg.get("codingModelId") or "").strip()
3120
+ # Task #107: when on, emit each code-model response so the worker persists it to Mongo.
3121
+ save_full_response = bool(cfg.get("saveFullResponse"))
3120
3122
  if raw_coding_base:
3121
3123
  same_server = raw_coding_base.rstrip("/") == (agent_base_url or "").rstrip("/")
3122
3124
  if same_server and not raw_coding_model:
@@ -4878,7 +4880,7 @@ def run_agent_chat(cfg):
4878
4880
  # and any step memory it accumulates. completion_kwargs["messages"] here is the
4879
4881
  # literal messages array sent to /v1/chat/completions.
4880
4882
  class _LoggingModel(OpenAIServerModel):
4881
- def __init__(self, *a, stream_agent=False, **kw):
4883
+ def __init__(self, *a, stream_agent=False, save_full_response=False, **kw):
4882
4884
  # Running total of PROMPT (input) tokens sent to the CODE model across the
4883
4885
  # turn (task #83). Only this wrapper counts — the chat/brain helper calls
4884
4886
  # (_chat_completion) don't route through here, so this is "code model only".
@@ -4904,6 +4906,10 @@ def run_agent_chat(cfg):
4904
4906
  # idle timer never fires. smolagents still receives the COMPLETE text, so its
4905
4907
  # <code>/final_answer parsing is unaffected.
4906
4908
  self._stream_agent = bool(stream_agent)
4909
+ # Task #107: persist each code-model response's full text (opt-in) + a 1-based
4910
+ # per-turn call counter used as the stored `step`.
4911
+ self._save_full_response = bool(save_full_response)
4912
+ self._call_index = 0
4907
4913
  super().__init__(*a, **kw)
4908
4914
 
4909
4915
  def _generate_once(self, *args, **kwargs):
@@ -5246,6 +5252,24 @@ def run_agent_chat(cfg):
5246
5252
  })
5247
5253
  except Exception: # noqa: BLE001
5248
5254
  pass
5255
+ # Task #107: persist the full RAW code-model response (opt-in) with this call's
5256
+ # token counts, emitted BEFORE any think-stripping/normalization so it matches
5257
+ # exactly what the token counts were computed from. Worker forwards to Mongo.
5258
+ if self._save_full_response:
5259
+ try:
5260
+ self._call_index += 1
5261
+ _raw = getattr(msg, "content", None)
5262
+ _tu2 = getattr(msg, "token_usage", None)
5263
+ _emit({
5264
+ "type": "code_response",
5265
+ "step": self._call_index,
5266
+ "text": _raw if isinstance(_raw, str)
5267
+ else ("" if _raw is None else str(_raw)),
5268
+ "inputTokens": int(getattr(_tu2, "input_tokens", 0) or 0) if _tu2 else 0,
5269
+ "outputTokens": int(getattr(_tu2, "output_tokens", 0) or 0) if _tu2 else 0,
5270
+ })
5271
+ except Exception: # noqa: BLE001
5272
+ pass
5249
5273
  try:
5250
5274
  content = getattr(msg, "content", None)
5251
5275
  if content is None:
@@ -5515,6 +5539,8 @@ def run_agent_chat(cfg):
5515
5539
  # Stream for Ollama so a long generation keeps the connection warm and can't
5516
5540
  # trip a reverse-proxy idle read-timeout. smolagents still gets the full text.
5517
5541
  stream_agent=coding_is_ollama,
5542
+ # Task #107: persist each code-model response to Mongo when the user opted in.
5543
+ save_full_response=save_full_response,
5518
5544
  # Cap each HTTP attempt at 600s so a genuinely slow single call (a
5519
5545
  # remote M6000/Vulkan box doing a cold ~4-5min prompt-eval) can finish
5520
5546
  # on the first try, while a truly hung request still fails into OUR
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiens.nguyen/gonext-local-worker",
3
- "version": "1.0.302",
3
+ "version": "1.0.304",
4
4
  "description": "Polls GoNext cloud API for async local LLM jobs and runs them against Ollama/OpenAI-compatible servers on this Mac",
5
5
  "type": "module",
6
6
  "license": "MIT",