@polka-codes/cli 0.9.35 → 0.9.37

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/dist/index.js +830 -32
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -58608,7 +58608,7 @@ var {
58608
58608
  Help
58609
58609
  } = import__.default;
58610
58610
  // package.json
58611
- var version = "0.9.35";
58611
+ var version = "0.9.37";
58612
58612
 
58613
58613
  // src/commands/chat.ts
58614
58614
  import { readFile as readFile3 } from "node:fs/promises";
@@ -72136,14 +72136,23 @@ var handler4 = async (provider, args) => {
72136
72136
  try {
72137
72137
  console.log("Executing command:", command, "Requires approval:", requiresApproval);
72138
72138
  const result = await provider.executeCommand(command, requiresApproval);
72139
- const message = `<command>${command}</command>
72139
+ let message = `<command>${command}</command>
72140
72140
  <command_exit_code>${result.exitCode}</command_exit_code>
72141
- <command_stdout>
72141
+ `;
72142
+ if (result.summary) {
72143
+ message += `<command_output_summary>
72144
+ ${result.summary}
72145
+ </command_output_summary>
72146
+ `;
72147
+ } else {
72148
+ message += `<command_stdout>
72142
72149
  ${result.stdout}
72143
72150
  </command_stdout>
72144
72151
  <command_stderr>
72145
72152
  ${result.stderr}
72146
- </command_stderr>`;
72153
+ </command_stderr>
72154
+ `;
72155
+ }
72147
72156
  if (result.exitCode === 0) {
72148
72157
  return {
72149
72158
  type: "Reply" /* Reply */,
@@ -73186,6 +73195,14 @@ class UsageMeter {
73186
73195
  get usage() {
73187
73196
  return { ...this.#totals };
73188
73197
  }
73198
+ merge(other) {
73199
+ const otherUsage = other.usage;
73200
+ this.#totals.input += otherUsage.input;
73201
+ this.#totals.output += otherUsage.output;
73202
+ this.#totals.cachedRead += otherUsage.cachedRead;
73203
+ this.#totals.cost += otherUsage.cost;
73204
+ this.#totals.messageCount += otherUsage.messageCount;
73205
+ }
73189
73206
  printUsage(customConsole = console) {
73190
73207
  const u = this.usage;
73191
73208
  customConsole.log(`Usage - messages: ${u.messageCount}, input: ${u.input}, cached: ${u.cachedRead}, ` + `output: ${u.output}, cost: $${u.cost.toFixed(4)}`);
@@ -81013,6 +81030,13 @@ function prepareRetries({
81013
81030
  })
81014
81031
  };
81015
81032
  }
81033
+ function extractTextContent(content) {
81034
+ const parts = content.filter((content2) => content2.type === "text");
81035
+ if (parts.length === 0) {
81036
+ return;
81037
+ }
81038
+ return parts.map((content2) => content2.text).join("");
81039
+ }
81016
81040
  var DefaultGeneratedFile = class {
81017
81041
  constructor({
81018
81042
  data,
@@ -81304,6 +81328,519 @@ var originalGenerateId = createIdGenerator({
81304
81328
  prefix: "aitxt",
81305
81329
  size: 24
81306
81330
  });
81331
+ async function generateText({
81332
+ model: modelArg,
81333
+ tools,
81334
+ toolChoice,
81335
+ system,
81336
+ prompt,
81337
+ messages,
81338
+ maxRetries: maxRetriesArg,
81339
+ abortSignal,
81340
+ headers,
81341
+ stopWhen = stepCountIs(1),
81342
+ experimental_output: output,
81343
+ experimental_telemetry: telemetry,
81344
+ providerOptions,
81345
+ experimental_activeTools,
81346
+ activeTools = experimental_activeTools,
81347
+ experimental_prepareStep,
81348
+ prepareStep = experimental_prepareStep,
81349
+ experimental_repairToolCall: repairToolCall,
81350
+ experimental_download: download2,
81351
+ experimental_context,
81352
+ _internal: {
81353
+ generateId: generateId3 = originalGenerateId,
81354
+ currentDate = () => /* @__PURE__ */ new Date
81355
+ } = {},
81356
+ onStepFinish,
81357
+ ...settings
81358
+ }) {
81359
+ const model = resolveLanguageModel(modelArg);
81360
+ const stopConditions = asArray(stopWhen);
81361
+ const { maxRetries, retry } = prepareRetries({
81362
+ maxRetries: maxRetriesArg,
81363
+ abortSignal
81364
+ });
81365
+ const callSettings = prepareCallSettings(settings);
81366
+ const baseTelemetryAttributes = getBaseTelemetryAttributes({
81367
+ model,
81368
+ telemetry,
81369
+ headers,
81370
+ settings: { ...callSettings, maxRetries }
81371
+ });
81372
+ const initialPrompt = await standardizePrompt({
81373
+ system,
81374
+ prompt,
81375
+ messages
81376
+ });
81377
+ const tracer = getTracer(telemetry);
81378
+ try {
81379
+ return await recordSpan({
81380
+ name: "ai.generateText",
81381
+ attributes: selectTelemetryAttributes({
81382
+ telemetry,
81383
+ attributes: {
81384
+ ...assembleOperationName({
81385
+ operationId: "ai.generateText",
81386
+ telemetry
81387
+ }),
81388
+ ...baseTelemetryAttributes,
81389
+ "ai.model.provider": model.provider,
81390
+ "ai.model.id": model.modelId,
81391
+ "ai.prompt": {
81392
+ input: () => JSON.stringify({ system, prompt, messages })
81393
+ }
81394
+ }
81395
+ }),
81396
+ tracer,
81397
+ fn: async (span) => {
81398
+ var _a172, _b8, _c, _d, _e, _f, _g;
81399
+ const callSettings2 = prepareCallSettings(settings);
81400
+ let currentModelResponse;
81401
+ let clientToolCalls = [];
81402
+ let clientToolOutputs = [];
81403
+ const responseMessages = [];
81404
+ const steps = [];
81405
+ do {
81406
+ const stepInputMessages = [
81407
+ ...initialPrompt.messages,
81408
+ ...responseMessages
81409
+ ];
81410
+ const prepareStepResult = await (prepareStep == null ? undefined : prepareStep({
81411
+ model,
81412
+ steps,
81413
+ stepNumber: steps.length,
81414
+ messages: stepInputMessages
81415
+ }));
81416
+ const promptMessages = await convertToLanguageModelPrompt({
81417
+ prompt: {
81418
+ system: (_a172 = prepareStepResult == null ? undefined : prepareStepResult.system) != null ? _a172 : initialPrompt.system,
81419
+ messages: (_b8 = prepareStepResult == null ? undefined : prepareStepResult.messages) != null ? _b8 : stepInputMessages
81420
+ },
81421
+ supportedUrls: await model.supportedUrls,
81422
+ download: download2
81423
+ });
81424
+ const stepModel = resolveLanguageModel((_c = prepareStepResult == null ? undefined : prepareStepResult.model) != null ? _c : model);
81425
+ const { toolChoice: stepToolChoice, tools: stepTools } = prepareToolsAndToolChoice({
81426
+ tools,
81427
+ toolChoice: (_d = prepareStepResult == null ? undefined : prepareStepResult.toolChoice) != null ? _d : toolChoice,
81428
+ activeTools: (_e = prepareStepResult == null ? undefined : prepareStepResult.activeTools) != null ? _e : activeTools
81429
+ });
81430
+ currentModelResponse = await retry(() => {
81431
+ var _a18;
81432
+ return recordSpan({
81433
+ name: "ai.generateText.doGenerate",
81434
+ attributes: selectTelemetryAttributes({
81435
+ telemetry,
81436
+ attributes: {
81437
+ ...assembleOperationName({
81438
+ operationId: "ai.generateText.doGenerate",
81439
+ telemetry
81440
+ }),
81441
+ ...baseTelemetryAttributes,
81442
+ "ai.model.provider": stepModel.provider,
81443
+ "ai.model.id": stepModel.modelId,
81444
+ "ai.prompt.messages": {
81445
+ input: () => stringifyForTelemetry(promptMessages)
81446
+ },
81447
+ "ai.prompt.tools": {
81448
+ input: () => stepTools == null ? undefined : stepTools.map((tool3) => JSON.stringify(tool3))
81449
+ },
81450
+ "ai.prompt.toolChoice": {
81451
+ input: () => stepToolChoice != null ? JSON.stringify(stepToolChoice) : undefined
81452
+ },
81453
+ "gen_ai.system": stepModel.provider,
81454
+ "gen_ai.request.model": stepModel.modelId,
81455
+ "gen_ai.request.frequency_penalty": settings.frequencyPenalty,
81456
+ "gen_ai.request.max_tokens": settings.maxOutputTokens,
81457
+ "gen_ai.request.presence_penalty": settings.presencePenalty,
81458
+ "gen_ai.request.stop_sequences": settings.stopSequences,
81459
+ "gen_ai.request.temperature": (_a18 = settings.temperature) != null ? _a18 : undefined,
81460
+ "gen_ai.request.top_k": settings.topK,
81461
+ "gen_ai.request.top_p": settings.topP
81462
+ }
81463
+ }),
81464
+ tracer,
81465
+ fn: async (span2) => {
81466
+ var _a19, _b22, _c2, _d2, _e2, _f2, _g2, _h;
81467
+ const result = await stepModel.doGenerate({
81468
+ ...callSettings2,
81469
+ tools: stepTools,
81470
+ toolChoice: stepToolChoice,
81471
+ responseFormat: output == null ? undefined : output.responseFormat,
81472
+ prompt: promptMessages,
81473
+ providerOptions,
81474
+ abortSignal,
81475
+ headers
81476
+ });
81477
+ const responseData = {
81478
+ id: (_b22 = (_a19 = result.response) == null ? undefined : _a19.id) != null ? _b22 : generateId3(),
81479
+ timestamp: (_d2 = (_c2 = result.response) == null ? undefined : _c2.timestamp) != null ? _d2 : currentDate(),
81480
+ modelId: (_f2 = (_e2 = result.response) == null ? undefined : _e2.modelId) != null ? _f2 : stepModel.modelId,
81481
+ headers: (_g2 = result.response) == null ? undefined : _g2.headers,
81482
+ body: (_h = result.response) == null ? undefined : _h.body
81483
+ };
81484
+ span2.setAttributes(selectTelemetryAttributes({
81485
+ telemetry,
81486
+ attributes: {
81487
+ "ai.response.finishReason": result.finishReason,
81488
+ "ai.response.text": {
81489
+ output: () => extractTextContent(result.content)
81490
+ },
81491
+ "ai.response.toolCalls": {
81492
+ output: () => {
81493
+ const toolCalls = asToolCalls(result.content);
81494
+ return toolCalls == null ? undefined : JSON.stringify(toolCalls);
81495
+ }
81496
+ },
81497
+ "ai.response.id": responseData.id,
81498
+ "ai.response.model": responseData.modelId,
81499
+ "ai.response.timestamp": responseData.timestamp.toISOString(),
81500
+ "ai.response.providerMetadata": JSON.stringify(result.providerMetadata),
81501
+ "ai.usage.promptTokens": result.usage.inputTokens,
81502
+ "ai.usage.completionTokens": result.usage.outputTokens,
81503
+ "gen_ai.response.finish_reasons": [result.finishReason],
81504
+ "gen_ai.response.id": responseData.id,
81505
+ "gen_ai.response.model": responseData.modelId,
81506
+ "gen_ai.usage.input_tokens": result.usage.inputTokens,
81507
+ "gen_ai.usage.output_tokens": result.usage.outputTokens
81508
+ }
81509
+ }));
81510
+ return { ...result, response: responseData };
81511
+ }
81512
+ });
81513
+ });
81514
+ const stepToolCalls = await Promise.all(currentModelResponse.content.filter((part) => part.type === "tool-call").map((toolCall) => parseToolCall({
81515
+ toolCall,
81516
+ tools,
81517
+ repairToolCall,
81518
+ system,
81519
+ messages: stepInputMessages
81520
+ })));
81521
+ for (const toolCall of stepToolCalls) {
81522
+ if (toolCall.invalid) {
81523
+ continue;
81524
+ }
81525
+ const tool3 = tools[toolCall.toolName];
81526
+ if ((tool3 == null ? undefined : tool3.onInputAvailable) != null) {
81527
+ await tool3.onInputAvailable({
81528
+ input: toolCall.input,
81529
+ toolCallId: toolCall.toolCallId,
81530
+ messages: stepInputMessages,
81531
+ abortSignal,
81532
+ experimental_context
81533
+ });
81534
+ }
81535
+ }
81536
+ const invalidToolCalls = stepToolCalls.filter((toolCall) => toolCall.invalid && toolCall.dynamic);
81537
+ clientToolOutputs = [];
81538
+ for (const toolCall of invalidToolCalls) {
81539
+ clientToolOutputs.push({
81540
+ type: "tool-error",
81541
+ toolCallId: toolCall.toolCallId,
81542
+ toolName: toolCall.toolName,
81543
+ input: toolCall.input,
81544
+ error: getErrorMessage2(toolCall.error),
81545
+ dynamic: true
81546
+ });
81547
+ }
81548
+ clientToolCalls = stepToolCalls.filter((toolCall) => !toolCall.providerExecuted);
81549
+ if (tools != null) {
81550
+ clientToolOutputs.push(...await executeTools({
81551
+ toolCalls: clientToolCalls.filter((toolCall) => !toolCall.invalid),
81552
+ tools,
81553
+ tracer,
81554
+ telemetry,
81555
+ messages: stepInputMessages,
81556
+ abortSignal,
81557
+ experimental_context
81558
+ }));
81559
+ }
81560
+ const stepContent = asContent({
81561
+ content: currentModelResponse.content,
81562
+ toolCalls: stepToolCalls,
81563
+ toolOutputs: clientToolOutputs
81564
+ });
81565
+ responseMessages.push(...toResponseMessages({
81566
+ content: stepContent,
81567
+ tools
81568
+ }));
81569
+ const currentStepResult = new DefaultStepResult({
81570
+ content: stepContent,
81571
+ finishReason: currentModelResponse.finishReason,
81572
+ usage: currentModelResponse.usage,
81573
+ warnings: currentModelResponse.warnings,
81574
+ providerMetadata: currentModelResponse.providerMetadata,
81575
+ request: (_f = currentModelResponse.request) != null ? _f : {},
81576
+ response: {
81577
+ ...currentModelResponse.response,
81578
+ messages: structuredClone(responseMessages)
81579
+ }
81580
+ });
81581
+ logWarnings((_g = currentModelResponse.warnings) != null ? _g : []);
81582
+ steps.push(currentStepResult);
81583
+ await (onStepFinish == null ? undefined : onStepFinish(currentStepResult));
81584
+ } while (clientToolCalls.length > 0 && clientToolOutputs.length === clientToolCalls.length && !await isStopConditionMet({ stopConditions, steps }));
81585
+ span.setAttributes(selectTelemetryAttributes({
81586
+ telemetry,
81587
+ attributes: {
81588
+ "ai.response.finishReason": currentModelResponse.finishReason,
81589
+ "ai.response.text": {
81590
+ output: () => extractTextContent(currentModelResponse.content)
81591
+ },
81592
+ "ai.response.toolCalls": {
81593
+ output: () => {
81594
+ const toolCalls = asToolCalls(currentModelResponse.content);
81595
+ return toolCalls == null ? undefined : JSON.stringify(toolCalls);
81596
+ }
81597
+ },
81598
+ "ai.response.providerMetadata": JSON.stringify(currentModelResponse.providerMetadata),
81599
+ "ai.usage.promptTokens": currentModelResponse.usage.inputTokens,
81600
+ "ai.usage.completionTokens": currentModelResponse.usage.outputTokens
81601
+ }
81602
+ }));
81603
+ const lastStep = steps[steps.length - 1];
81604
+ return new DefaultGenerateTextResult({
81605
+ steps,
81606
+ resolvedOutput: await (output == null ? undefined : output.parseOutput({ text: lastStep.text }, {
81607
+ response: lastStep.response,
81608
+ usage: lastStep.usage,
81609
+ finishReason: lastStep.finishReason
81610
+ }))
81611
+ });
81612
+ }
81613
+ });
81614
+ } catch (error43) {
81615
+ throw wrapGatewayError(error43);
81616
+ }
81617
+ }
81618
+ async function executeTools({
81619
+ toolCalls,
81620
+ tools,
81621
+ tracer,
81622
+ telemetry,
81623
+ messages,
81624
+ abortSignal,
81625
+ experimental_context
81626
+ }) {
81627
+ const toolOutputs = await Promise.all(toolCalls.map(async ({ toolCallId, toolName, input }) => {
81628
+ const tool3 = tools[toolName];
81629
+ if ((tool3 == null ? undefined : tool3.execute) == null) {
81630
+ return;
81631
+ }
81632
+ return recordSpan({
81633
+ name: "ai.toolCall",
81634
+ attributes: selectTelemetryAttributes({
81635
+ telemetry,
81636
+ attributes: {
81637
+ ...assembleOperationName({
81638
+ operationId: "ai.toolCall",
81639
+ telemetry
81640
+ }),
81641
+ "ai.toolCall.name": toolName,
81642
+ "ai.toolCall.id": toolCallId,
81643
+ "ai.toolCall.args": {
81644
+ output: () => JSON.stringify(input)
81645
+ }
81646
+ }
81647
+ }),
81648
+ tracer,
81649
+ fn: async (span) => {
81650
+ try {
81651
+ const stream = executeTool({
81652
+ execute: tool3.execute.bind(tool3),
81653
+ input,
81654
+ options: {
81655
+ toolCallId,
81656
+ messages,
81657
+ abortSignal,
81658
+ experimental_context
81659
+ }
81660
+ });
81661
+ let output;
81662
+ for await (const part of stream) {
81663
+ if (part.type === "final") {
81664
+ output = part.output;
81665
+ }
81666
+ }
81667
+ try {
81668
+ span.setAttributes(selectTelemetryAttributes({
81669
+ telemetry,
81670
+ attributes: {
81671
+ "ai.toolCall.result": {
81672
+ output: () => JSON.stringify(output)
81673
+ }
81674
+ }
81675
+ }));
81676
+ } catch (ignored) {}
81677
+ return {
81678
+ type: "tool-result",
81679
+ toolCallId,
81680
+ toolName,
81681
+ input,
81682
+ output,
81683
+ dynamic: tool3.type === "dynamic"
81684
+ };
81685
+ } catch (error43) {
81686
+ recordErrorOnSpan(span, error43);
81687
+ return {
81688
+ type: "tool-error",
81689
+ toolCallId,
81690
+ toolName,
81691
+ input,
81692
+ error: error43,
81693
+ dynamic: tool3.type === "dynamic"
81694
+ };
81695
+ }
81696
+ }
81697
+ });
81698
+ }));
81699
+ return toolOutputs.filter((output) => output != null);
81700
+ }
81701
+ var DefaultGenerateTextResult = class {
81702
+ constructor(options) {
81703
+ this.steps = options.steps;
81704
+ this.resolvedOutput = options.resolvedOutput;
81705
+ }
81706
+ get finalStep() {
81707
+ return this.steps[this.steps.length - 1];
81708
+ }
81709
+ get content() {
81710
+ return this.finalStep.content;
81711
+ }
81712
+ get text() {
81713
+ return this.finalStep.text;
81714
+ }
81715
+ get files() {
81716
+ return this.finalStep.files;
81717
+ }
81718
+ get reasoningText() {
81719
+ return this.finalStep.reasoningText;
81720
+ }
81721
+ get reasoning() {
81722
+ return this.finalStep.reasoning;
81723
+ }
81724
+ get toolCalls() {
81725
+ return this.finalStep.toolCalls;
81726
+ }
81727
+ get staticToolCalls() {
81728
+ return this.finalStep.staticToolCalls;
81729
+ }
81730
+ get dynamicToolCalls() {
81731
+ return this.finalStep.dynamicToolCalls;
81732
+ }
81733
+ get toolResults() {
81734
+ return this.finalStep.toolResults;
81735
+ }
81736
+ get staticToolResults() {
81737
+ return this.finalStep.staticToolResults;
81738
+ }
81739
+ get dynamicToolResults() {
81740
+ return this.finalStep.dynamicToolResults;
81741
+ }
81742
+ get sources() {
81743
+ return this.finalStep.sources;
81744
+ }
81745
+ get finishReason() {
81746
+ return this.finalStep.finishReason;
81747
+ }
81748
+ get warnings() {
81749
+ return this.finalStep.warnings;
81750
+ }
81751
+ get providerMetadata() {
81752
+ return this.finalStep.providerMetadata;
81753
+ }
81754
+ get response() {
81755
+ return this.finalStep.response;
81756
+ }
81757
+ get request() {
81758
+ return this.finalStep.request;
81759
+ }
81760
+ get usage() {
81761
+ return this.finalStep.usage;
81762
+ }
81763
+ get totalUsage() {
81764
+ return this.steps.reduce((totalUsage, step) => {
81765
+ return addLanguageModelUsage(totalUsage, step.usage);
81766
+ }, {
81767
+ inputTokens: undefined,
81768
+ outputTokens: undefined,
81769
+ totalTokens: undefined,
81770
+ reasoningTokens: undefined,
81771
+ cachedInputTokens: undefined
81772
+ });
81773
+ }
81774
+ get experimental_output() {
81775
+ if (this.resolvedOutput == null) {
81776
+ throw new NoOutputSpecifiedError;
81777
+ }
81778
+ return this.resolvedOutput;
81779
+ }
81780
+ };
81781
+ function asToolCalls(content) {
81782
+ const parts = content.filter((part) => part.type === "tool-call");
81783
+ if (parts.length === 0) {
81784
+ return;
81785
+ }
81786
+ return parts.map((toolCall) => ({
81787
+ toolCallId: toolCall.toolCallId,
81788
+ toolName: toolCall.toolName,
81789
+ input: toolCall.input
81790
+ }));
81791
+ }
81792
+ function asContent({
81793
+ content,
81794
+ toolCalls,
81795
+ toolOutputs
81796
+ }) {
81797
+ return [
81798
+ ...content.map((part) => {
81799
+ switch (part.type) {
81800
+ case "text":
81801
+ case "reasoning":
81802
+ case "source":
81803
+ return part;
81804
+ case "file": {
81805
+ return {
81806
+ type: "file",
81807
+ file: new DefaultGeneratedFile(part)
81808
+ };
81809
+ }
81810
+ case "tool-call": {
81811
+ return toolCalls.find((toolCall) => toolCall.toolCallId === part.toolCallId);
81812
+ }
81813
+ case "tool-result": {
81814
+ const toolCall = toolCalls.find((toolCall2) => toolCall2.toolCallId === part.toolCallId);
81815
+ if (toolCall == null) {
81816
+ throw new Error(`Tool call ${part.toolCallId} not found.`);
81817
+ }
81818
+ if (part.isError) {
81819
+ return {
81820
+ type: "tool-error",
81821
+ toolCallId: part.toolCallId,
81822
+ toolName: part.toolName,
81823
+ input: toolCall.input,
81824
+ error: part.result,
81825
+ providerExecuted: true,
81826
+ dynamic: toolCall.dynamic
81827
+ };
81828
+ }
81829
+ return {
81830
+ type: "tool-result",
81831
+ toolCallId: part.toolCallId,
81832
+ toolName: part.toolName,
81833
+ input: toolCall.input,
81834
+ output: part.result,
81835
+ providerExecuted: true,
81836
+ dynamic: toolCall.dynamic
81837
+ };
81838
+ }
81839
+ }
81840
+ }),
81841
+ ...toolOutputs
81842
+ ];
81843
+ }
81307
81844
  function prepareHeaders(headers, defaultHeaders) {
81308
81845
  const responseHeaders = new Headers(headers != null ? headers : {});
81309
81846
  for (const [key2, value] of Object.entries(defaultHeaders)) {
@@ -85084,6 +85621,7 @@ Request timeout after ${requestTimeoutSeconds} seconds. Canceling current reques
85084
85621
  };
85085
85622
  try {
85086
85623
  resetTimeout();
85624
+ const usageMeterOnFinishHandler = this.config.usageMeter.onFinishHandler(this.ai);
85087
85625
  const streamTextOptions = {
85088
85626
  model: this.ai,
85089
85627
  temperature: 0,
@@ -85102,7 +85640,10 @@ Request timeout after ${requestTimeoutSeconds} seconds. Canceling current reques
85102
85640
  break;
85103
85641
  }
85104
85642
  },
85105
- onFinish: this.config.usageMeter.onFinishHandler(this.ai),
85643
+ onFinish: (evt) => {
85644
+ usageMeterOnFinishHandler(evt);
85645
+ this.#callback({ kind: "Usage" /* Usage */, agent: this, usage: evt.totalUsage });
85646
+ },
85106
85647
  onError: async (error43) => {
85107
85648
  console.error("Error in stream:", error43);
85108
85649
  },
@@ -86177,6 +86718,7 @@ var configSchema = exports_external.object({
86177
86718
  budget: exports_external.number().positive().optional(),
86178
86719
  retryCount: exports_external.number().int().min(0).optional(),
86179
86720
  requestTimeoutSeconds: exports_external.number().int().positive().optional(),
86721
+ summaryThreshold: exports_external.number().int().positive().optional(),
86180
86722
  scripts: exports_external.record(exports_external.string(), exports_external.string().or(exports_external.object({
86181
86723
  command: exports_external.string(),
86182
86724
  description: exports_external.string()
@@ -105238,8 +105780,25 @@ var getProvider = (options = {}) => {
105238
105780
  options.command?.onStderr(dataStr);
105239
105781
  stderrText += dataStr;
105240
105782
  });
105241
- child.on("close", (code) => {
105783
+ child.on("close", async (code) => {
105242
105784
  options.command?.onExit(code ?? 0);
105785
+ const totalLength = stdoutText.length + stderrText.length;
105786
+ if (totalLength > (options.summaryThreshold ?? 5000) && options.summarizeOutput) {
105787
+ try {
105788
+ const summary = await options.summarizeOutput(stdoutText, stderrText);
105789
+ if (summary) {
105790
+ resolve7({
105791
+ summary,
105792
+ stdout: stdoutText,
105793
+ stderr: stderrText,
105794
+ exitCode: code ?? 0
105795
+ });
105796
+ return;
105797
+ }
105798
+ } catch (_e) {
105799
+ console.error("Summarization failed:", _e);
105800
+ }
105801
+ }
105243
105802
  resolve7({
105244
105803
  stdout: stdoutText,
105245
105804
  stderr: stderrText,
@@ -106029,6 +106588,201 @@ import { readFile as readFile2 } from "node:fs/promises";
106029
106588
  import os3 from "node:os";
106030
106589
  var import_lodash5 = __toESM(require_lodash(), 1);
106031
106590
 
106591
+ // src/commandSummarizer.ts
106592
+ var prompt3 = `
106593
+ System Prompt: Command Output Summarizer
106594
+
106595
+ Role
106596
+ - You are a coding agent that summarizes command execution results.
106597
+ - You receive raw stdout and stderr and must produce a concise, high-signal summary focused on what matters to developers.
106598
+
106599
+ Input
106600
+ - The input will ALWAYS be provided in this exact format:
106601
+ <stdout>
106602
+ \${stdout}
106603
+ </stdout>
106604
+ <stderr>
106605
+ \${stderr}
106606
+ </stderr>
106607
+ - Treat missing or empty sections as empty strings.
106608
+
106609
+ Core Objective
106610
+ - Extract and report ONLY the key lines that communicate failures, warnings, and actionable issues.
106611
+ - Ignore routine noise: progress bars, spinners, timestamps, banners, environment echoes, compilation start/finish messages, and other benign status lines.
106612
+ - Prefer brevity and accuracy. Do not ask questions. Do not repeat yourself.
106613
+
106614
+ General Rules
106615
+ 1) Preprocessing
106616
+ - Normalize newlines to "
106617
+ "; strip ANSI colors/escape codes.
106618
+ - Collapse repeated blank lines; trim trailing whitespace.
106619
+ - Deduplicate identical lines that appear many times; show one and append " (repeated N times)".
106620
+ - Truncate extremely long single lines to a reasonable width while preserving the essential portion (start and end), indicating truncation with "...".
106621
+ - Redact obvious secrets (tokens, passwords, keys) by masking the middle with "****", keeping at most the last 4 chars.
106622
+
106623
+ 2) Severity and Ordering
106624
+ - Prioritize in this order: Errors, Test Failures, Warnings, Important Notes.
106625
+ - Preserve original order within each section when helpful for debugging.
106626
+ - If an exit code is inferable (e.g., via error footers or phrases like "exit status 1"), include it in the Summary.
106627
+
106628
+ 3) Output Format (ASCII only, no tables)
106629
+ - Summary: one short line if any issues were found.
106630
+ Example: "Summary: exit_code=1; errors=3; warnings=2; failing_tests=4"
106631
+ - Then zero or more sections in this order, only if present:
106632
+ - Errors:
106633
+ - Test Failures:
106634
+ - Warnings:
106635
+ - Notes:
106636
+ - Within each section, use compact bullet points ("- ").
106637
+ - Quote key lines verbatim when they carry the signal (file:line:col, codes, rule names, assertion diffs).
106638
+ - Never include large code blocks; include at most 1-2 context lines around a key message when indispensable, marked with "...".
106639
+
106640
+ 4) What to Include vs Ignore (by tool/type)
106641
+ A) Test Runners (jest, mocha, vitest, pytest, nose, unittest, go test, rspec, junit, maven-surefire, gradle test)
106642
+ Include:
106643
+ - Names of failing test suites and test cases.
106644
+ - Assertion messages, diffs (Expected vs Received / AssertionError messages).
106645
+ - First 1-3 relevant stack frames pointing to user code (omit framework internals).
106646
+ - Summary counts: failed, skipped (if significant), total time if useful.
106647
+ Ignore:
106648
+ - Passed tests, pass counts, coverage success lines.
106649
+ - Test discovery notices, "OK"/"PASSED" banners, shard routing info.
106650
+ Example bullet:
106651
+ - tests/math.spec.ts: "adds numbers" FAILED: Expected 3, Received 4 at src/math.ts:12:7
106652
+
106653
+ B) Compilers/Build Tools (tsc, vite, webpack, esbuild, babel, gcc/clang, javac, kotlinc, rustc/cargo, go build, dotnet build, swiftc)
106654
+ Include:
106655
+ - Errors and warnings only (file:line:col if present, diagnostic code).
106656
+ - Linker errors and type mismatch details.
106657
+ Ignore:
106658
+ - Status/progress lines like "Compiling X", "Bundling Y", "Starting dev server...", "Note: some messages have been simplified".
106659
+ Example bullets:
106660
+ - src/foo.ts:42:13 TS2339 error: Property 'bar' does not exist on type 'Baz'.
106661
+ - lib/util.c:88:5 warning: unused variable 'tmp' [-Wunused-variable]
106662
+
106663
+ C) Linters/Formatters (eslint, flake8, pylint, rubocop, golangci-lint, stylelint, mypy, black/prettier)
106664
+ Include:
106665
+ - Violations with file:line:col, rule/id, brief message.
106666
+ - mypy type errors (treat as errors).
106667
+ Ignore:
106668
+ - "All matched files" summaries, formatter no-op messages.
106669
+ Example bullet:
106670
+ - src/app.tsx:17:9 eslint(no-unused-vars): 'user' is assigned a value but never used.
106671
+
106672
+ D) Runtime/Execution Errors (node, python, java, go, ruby, dotnet, shell)
106673
+ Include:
106674
+ - Error type/name and message.
106675
+ - Top 1-3 stack frames in user code; include "Caused by" chains.
106676
+ - Non-zero exit status if visible.
106677
+ Ignore:
106678
+ - Long internal/framework stacks unless they are the only frames available.
106679
+ Example bullet:
106680
+ - RuntimeError: connection refused at services/db.py:54 (exit status 1)
106681
+
106682
+ E) Package/Build Systems (npm/yarn/pnpm, pip/pipenv, poetry, cargo, maven, gradle)
106683
+ Include:
106684
+ - Install/build failures, script failures, postinstall errors.
106685
+ - Security advisories at high/critical severity (count + top advisory IDs).
106686
+ - Missing/invalid peer dependency errors that break install/build.
106687
+ Ignore:
106688
+ - Progress bars, fetch logs, cache hits, "up to date" lines.
106689
+ Example bullet:
106690
+ - npm ERR! test script failed: "jest --runInBand" (code 1)
106691
+
106692
+ F) VCS and CI (git, gh, svn; CI logs)
106693
+ Include:
106694
+ - Merge/rebase conflicts (files and conflict markers).
106695
+ - Push rejections (non-fast-forward, auth failures).
106696
+ - CI job failures (job name, failing step, error excerpt).
106697
+ Ignore:
106698
+ - Clean status, branch listings unless indicating a problem.
106699
+ Example bullet:
106700
+ - Merge conflict: src/index.ts (markers found around lines ~120-145)
106701
+
106702
+ G) Containers/Orchestration (docker, podman, kubectl, helm)
106703
+ Include:
106704
+ - Build failures (failed stages, missing files), run-time exit codes.
106705
+ - Kubernetes apply errors and crashloop events with reason.
106706
+ Ignore:
106707
+ - Layer download progress, pull status noise.
106708
+ Example bullet:
106709
+ - CrashLoopBackOff: pod api-7f6c... container "api" OOMKilled (restart 3/5)
106710
+
106711
+ H) Databases/SQL/Migrations (psql, mysql, sqlite, prisma, liquibase, flyway)
106712
+ Include:
106713
+ - SQLSTATE/error codes, constraint violations, migration failure details.
106714
+ Example bullet:
106715
+ - SQLSTATE 23505 unique_violation on users(email) at 2025-09-11T03:22Z
106716
+
106717
+ 5) Counts and Grouping
106718
+ - If 3+ similar diagnostics occur, summarize with a count and show 1-2 exemplars:
106719
+ Example: "Type errors (7): e.g., src/a.ts:10 TS2322: Type 'X' is not assignable to 'Y'."
106720
+ - When possible, group by file or rule to reduce noise.
106721
+
106722
+ 6) Stack Traces
106723
+ - Keep only the topmost relevant frames pointing to project files (e.g., paths under src/, app/, lib/).
106724
+ - Omit frames from node:internal, <anonymous>, site-packages/dist-packages unless they are the only frames.
106725
+
106726
+ 7) Timeouts/Resource Failures
106727
+ - If a timeout/OOM/segfault is detected, surface it prominently under Errors with the best short cause line.
106728
+
106729
+ 8) When There Is Nothing Noteworthy
106730
+ - If no errors, no warnings, and no failing tests are detected, output a single line:
106731
+ "No issues found."
106732
+ - Do NOT restate benign status like "build succeeded" or "all tests passed".
106733
+
106734
+ 9) Tone and Style
106735
+ - Be precise and unemotional.
106736
+ - Use short bullets; avoid prose paragraphs.
106737
+ - ASCII only; no emojis; no tables.
106738
+
106739
+ 10) Optional Next Actions
106740
+ - If and only if issues exist, append a short "Next actions:" section with up to 3 bullets of direct, obvious steps derived from the messages (e.g., "Fix missing import in src/foo.ts line 12").
106741
+
106742
+ Detection Heuristics (non-exhaustive)
106743
+ - Errors: lines containing "error", "ERR!", "E ", "fatal", "Traceback", "Exception", "undefined reference", "cannot find symbol", "not found", "Segmentation fault", "panic:", "stack overflow".
106744
+ - Warnings: lines containing "warning", "WARN", "deprecated", "note: this will be removed" (treat "note" as warning only if explicitly labeled).
106745
+ - Test failures: lines with "FAIL", "FAILED", "Error", "AssertionError", "expect(", "--- FAIL:", "not ok", "Tests failed", or junit/pytest summaries with non-zero failures.
106746
+
106747
+ Output Template
106748
+ - Follow this shape; omit empty sections:
106749
+
106750
+ Summary: exit_code=<code>; errors=<N>; warnings=<M>; failing_tests=<K>
106751
+ Errors:
106752
+ - <file:line:col> <diagnostic code if any> <short message>
106753
+ - <next...>
106754
+
106755
+ Test Failures:
106756
+ - <suite or file> "<test name>": <assertion message or diff>; at <file:line[:col]>
106757
+ - <next...>
106758
+
106759
+ Warnings:
106760
+ - <file:line:col> <rule/code>: <short message>
106761
+
106762
+ Notes:
106763
+ - <concise note if indispensable>
106764
+
106765
+ Next actions:
106766
+ - <up to 3 short, concrete steps>
106767
+
106768
+ Final Requirements
106769
+ - Be concise, avoid repeating the same information.
106770
+ - Ensure accuracy; never invent details not present in the input.
106771
+ - Do not output tables unless explicitly asked.`;
106772
+ var summarizeOutput = async (model, stdout, stderr) => {
106773
+ const resp = await generateText({
106774
+ model,
106775
+ system: prompt3,
106776
+ prompt: `<stdout>
106777
+ ${stdout}
106778
+ </stdout>
106779
+ <stderr>
106780
+ ${stderr}
106781
+ </stderr>`
106782
+ });
106783
+ return resp.text;
106784
+ };
106785
+
106032
106786
  // src/getProviderOptions.ts
106033
106787
  function getProviderOptions(provider3, modelId, thinkingBudgetTokens, supportThinking) {
106034
106788
  if (thinkingBudgetTokens <= 0 || !provider3 || !modelId) {
@@ -106108,7 +106862,8 @@ class Runner {
106108
106862
  console.log(`$ <<<< $ Command error: ${error43}`);
106109
106863
  }
106110
106864
  },
106111
- excludeFiles: options.config.excludeFiles
106865
+ excludeFiles: options.config.excludeFiles,
106866
+ summaryThreshold: options.config.summaryThreshold
106112
106867
  };
106113
106868
  const platform = os3.platform();
106114
106869
  const llms = {};
@@ -106161,6 +106916,12 @@ class Runner {
106161
106916
  if (this.#options.interactive) {
106162
106917
  additionalTools.push(askFollowupQuestion_default);
106163
106918
  }
106919
+ const newToolProviderOptions = {
106920
+ ...toolProviderOptions,
106921
+ summarizeOutput: async (stdout, stderr) => {
106922
+ return await summarizeOutput(ai, stdout, stderr);
106923
+ }
106924
+ };
106164
106925
  const args = {
106165
106926
  ai,
106166
106927
  os: platform,
@@ -106178,7 +106939,7 @@ class Runner {
106178
106939
  },
106179
106940
  usageMeter: this.usageMeter,
106180
106941
  additionalTools,
106181
- provider: getProvider(toolProviderOptions)
106942
+ provider: getProvider(newToolProviderOptions)
106182
106943
  };
106183
106944
  switch (agentName) {
106184
106945
  case coderAgentInfo.name:
@@ -108394,9 +109155,10 @@ var getChangeInfo = {
108394
109155
  id: "get-change-info",
108395
109156
  type: "custom",
108396
109157
  run: async (input, context, _resumedState) => {
108397
- const { pr, json: json2 } = input;
109158
+ const { pr, json: json2, yes } = input;
108398
109159
  const logger = context.logger ?? console;
108399
109160
  context.json = json2;
109161
+ context.yes = yes;
108400
109162
  const {
108401
109163
  ui: { spinner }
108402
109164
  } = context;
@@ -108540,6 +109302,7 @@ var handleResult3 = {
108540
109302
  run: async (input, context, _resumedState) => {
108541
109303
  const { overview, specificReviews } = input;
108542
109304
  const json2 = context.json;
109305
+ const yes = context.yes;
108543
109306
  const logger = context.logger ?? console;
108544
109307
  const {
108545
109308
  ui: { spinner }
@@ -108558,14 +109321,18 @@ var handleResult3 = {
108558
109321
  const formatted = formatReviewForConsole(reviewResult);
108559
109322
  logger.log(formatted);
108560
109323
  let shouldRunTask = false;
108561
- if (process.stdin.isTTY && reviewResult.specificReviews.length > 0) {
108562
- try {
108563
- shouldRunTask = await esm_default2({
108564
- message: "Do you wish polka-codes to address the review results?",
108565
- default: false
108566
- });
108567
- } catch {
108568
- process.exit(130);
109324
+ if (reviewResult.specificReviews.length > 0) {
109325
+ if (yes) {
109326
+ shouldRunTask = true;
109327
+ } else if (process.stdin.isTTY) {
109328
+ try {
109329
+ shouldRunTask = await esm_default2({
109330
+ message: "Do you wish polka-codes to address the review results?",
109331
+ default: false
109332
+ });
109333
+ } catch {
109334
+ process.exit(130);
109335
+ }
108569
109336
  }
108570
109337
  }
108571
109338
  const output = { shouldRunTask };
@@ -108831,31 +109598,62 @@ async function runTask(taskArg, _options, command2, opts = {}) {
108831
109598
  }
108832
109599
 
108833
109600
  // src/commands/review.ts
108834
- var reviewCommand = new Command("review").description("Review a GitHub pull request or local changes").option("--pr <pr>", "The pull request number or URL to review").option("--json", "Output the review in JSON format", false).action(async (options, command2) => {
108835
- const { json: json2, pr: pr2 } = options;
108836
- const input = { json: json2, ...pr2 && { pr: pr2 } };
108837
- let _willRunTask = false;
108838
- const handleSuccess = async (result, command3, usageMeter) => {
109601
+ var reviewCommand = new Command("review").description("Review a GitHub pull request or local changes").option("--pr <pr>", "The pull request number or URL to review").option("--json", "Output the review in JSON format", false).option("-y, --yes", "Automatically apply review feedback", false).option("--loop [count]", "Re-review after changes are applied.", (value) => {
109602
+ if (value === undefined || value === null) {
109603
+ return 1;
109604
+ }
109605
+ const parsedValue = parseInt(value, 10);
109606
+ if (Number.isNaN(parsedValue) || parsedValue < 1) {
109607
+ throw new InvalidOptionArgumentError("Must be a positive number.");
109608
+ }
109609
+ return parsedValue;
109610
+ }, 1).action(async (options, command2) => {
109611
+ const { json: json2, pr: pr2, loop: maxIterations, yes: yesOption } = options;
109612
+ const yes = maxIterations > 1 || yesOption;
109613
+ let usageMeter;
109614
+ let changesAppliedInThisIteration = false;
109615
+ const handleSuccess = async (result, cmd, um) => {
109616
+ if (um) {
109617
+ if (usageMeter) {
109618
+ usageMeter.merge(um);
109619
+ } else {
109620
+ usageMeter = um;
109621
+ }
109622
+ }
108839
109623
  if (result.type === "success" && result.output.shouldRunTask) {
108840
- _willRunTask = true;
108841
- if (!command3) {
109624
+ changesAppliedInThisIteration = true;
109625
+ if (!cmd) {
108842
109626
  throw new Error("Command object not available in handleSuccess");
108843
109627
  }
108844
109628
  const taskInstruction = `please address the review result:
108845
109629
 
108846
109630
  ${result.output.formattedReview}`;
108847
- await runTask(taskInstruction, {}, command3, {
109631
+ await runTask(taskInstruction, {}, cmd, {
108848
109632
  externalUsageMeter: usageMeter,
108849
- suppressUsagePrint: false
109633
+ suppressUsagePrint: true
108850
109634
  });
108851
- } else if (usageMeter && !json2) {
108852
- usageMeter.printUsage();
108853
109635
  }
108854
109636
  };
108855
- await runWorkflowCommand("review", reviewWorkflow, command2, input, handleSuccess, {
108856
- json: json2,
108857
- suppressUsagePrint: true
108858
- });
109637
+ for (let i = 0;i < maxIterations; i++) {
109638
+ changesAppliedInThisIteration = false;
109639
+ const input = { json: json2, ...pr2 && { pr: pr2 }, yes };
109640
+ if (i > 0) {
109641
+ command2.opts().silent || console.log(`
109642
+ Re-running review (iteration ${i + 1} of ${maxIterations})...`);
109643
+ }
109644
+ await runWorkflowCommand("review", reviewWorkflow, command2, input, handleSuccess, {
109645
+ json: json2,
109646
+ suppressUsagePrint: true
109647
+ });
109648
+ if (maxIterations > 1 && !changesAppliedInThisIteration) {
109649
+ command2.opts().silent || console.log(`
109650
+ No more review feedback to apply. Exiting loop.`);
109651
+ break;
109652
+ }
109653
+ }
109654
+ if (usageMeter && !json2) {
109655
+ usageMeter.printUsage();
109656
+ }
108859
109657
  });
108860
109658
 
108861
109659
  // src/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polka-codes/cli",
3
- "version": "0.9.35",
3
+ "version": "0.9.37",
4
4
  "license": "AGPL-3.0",
5
5
  "author": "github@polka.codes",
6
6
  "type": "module",