@gaberrb/polypus 0.4.12 → 0.4.14

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/index.js CHANGED
@@ -910,15 +910,33 @@ var OpenAICompatibleProvider = class {
910
910
  parameters: t2.parameters
911
911
  }
912
912
  }));
913
+ const base = {
914
+ model: this.model,
915
+ messages,
916
+ ...tools && tools.length > 0 ? { tools } : {},
917
+ temperature: req.params?.temperature,
918
+ // Generous default so large files aren't truncated mid tool-call.
919
+ max_tokens: req.params?.maxTokens ?? 8192
920
+ };
921
+ if (req.onDelta) {
922
+ const stream = await this.client.chat.completions.create(
923
+ { ...base, stream: true, stream_options: { include_usage: true } },
924
+ { signal: req.signal }
925
+ );
926
+ const agg = await aggregateStream(stream, req.onDelta);
927
+ return {
928
+ content: agg.content,
929
+ toolCalls: agg.toolCalls.map((tc, i) => ({
930
+ id: tc.id || `call_${i}`,
931
+ name: tc.name,
932
+ arguments: safeParseArgs(tc.arguments)
933
+ })),
934
+ finishReason: agg.finishReason || "stop",
935
+ usage: agg.usage
936
+ };
937
+ }
913
938
  const completion = await this.client.chat.completions.create(
914
- {
915
- model: this.model,
916
- messages,
917
- ...tools && tools.length > 0 ? { tools } : {},
918
- temperature: req.params?.temperature,
919
- // Generous default so large files aren't truncated mid tool-call.
920
- max_tokens: req.params?.maxTokens ?? 8192
921
- },
939
+ { ...base },
922
940
  { signal: req.signal }
923
941
  );
924
942
  const choice = completion.choices[0];
@@ -939,6 +957,34 @@ var OpenAICompatibleProvider = class {
939
957
  };
940
958
  }
941
959
  };
960
+ async function aggregateStream(stream, onDelta) {
961
+ let content = "";
962
+ let finishReason = "";
963
+ let usage2;
964
+ const toolAcc = [];
965
+ for await (const chunk of stream) {
966
+ const choice = chunk.choices?.[0];
967
+ const delta = choice?.delta;
968
+ if (delta?.content) {
969
+ content += delta.content;
970
+ onDelta?.(delta.content);
971
+ }
972
+ for (const tc of delta?.tool_calls ?? []) {
973
+ const slot = toolAcc[tc.index] ??= { id: "", name: "", arguments: "" };
974
+ if (tc.id) slot.id = tc.id;
975
+ if (tc.function?.name) slot.name = tc.function.name;
976
+ if (tc.function?.arguments) slot.arguments += tc.function.arguments;
977
+ }
978
+ if (choice?.finish_reason) finishReason = choice.finish_reason;
979
+ if (chunk.usage) {
980
+ usage2 = {
981
+ promptTokens: chunk.usage.prompt_tokens,
982
+ completionTokens: chunk.usage.completion_tokens
983
+ };
984
+ }
985
+ }
986
+ return { content, finishReason, usage: usage2, toolCalls: toolAcc.filter(Boolean) };
987
+ }
942
988
  function toOpenAIMessage(m) {
943
989
  switch (m.role) {
944
990
  case "tool":
@@ -2284,13 +2330,15 @@ async function runAgent(opts) {
2284
2330
  }
2285
2331
  }
2286
2332
  }
2333
+ const wantDelta = driver.kind === "native" && typeof events?.onAssistantDelta === "function";
2287
2334
  let response;
2288
2335
  try {
2289
2336
  response = await agent.provider.chat({
2290
2337
  messages,
2291
2338
  tools: driver.providerTools(),
2292
2339
  params: opts.params,
2293
- signal: opts.signal
2340
+ signal: opts.signal,
2341
+ onDelta: wantDelta ? (chunk) => events.onAssistantDelta(chunk) : void 0
2294
2342
  });
2295
2343
  } catch (err) {
2296
2344
  if (opts.signal?.aborted) return { finished: false, reason: "cancelled", steps: step, messages, usage: usage2 };
@@ -4406,16 +4454,27 @@ function renderDiff(hunks) {
4406
4454
  }
4407
4455
  }
4408
4456
  function renderEvents(spinner3) {
4457
+ let streamed = false;
4409
4458
  return {
4410
4459
  onStep() {
4460
+ streamed = false;
4411
4461
  spinner3.start(t("ui.thinking"));
4412
4462
  },
4413
4463
  onUsage(usage2) {
4414
4464
  const total = usage2.promptTokens + usage2.completionTokens;
4415
4465
  if (total > 0) spinner3.setSuffix(t("ui.tokensShort", { total: fmtTokens(total) }));
4416
4466
  },
4467
+ onAssistantDelta(chunk) {
4468
+ spinner3.stop();
4469
+ process.stdout.write(pc8.cyan(chunk));
4470
+ streamed = true;
4471
+ },
4417
4472
  onAssistantText(text2) {
4418
4473
  spinner3.stop();
4474
+ if (streamed) {
4475
+ process.stdout.write("\n");
4476
+ return;
4477
+ }
4419
4478
  if (text2.trim()) console.log(pc8.cyan(text2.trim()));
4420
4479
  },
4421
4480
  onToolCall(call) {