@polka-codes/cli 0.9.35 → 0.9.36

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 +825 -31
  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.36";
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)) {
@@ -86177,6 +86714,7 @@ var configSchema = exports_external.object({
86177
86714
  budget: exports_external.number().positive().optional(),
86178
86715
  retryCount: exports_external.number().int().min(0).optional(),
86179
86716
  requestTimeoutSeconds: exports_external.number().int().positive().optional(),
86717
+ summaryThreshold: exports_external.number().int().positive().optional(),
86180
86718
  scripts: exports_external.record(exports_external.string(), exports_external.string().or(exports_external.object({
86181
86719
  command: exports_external.string(),
86182
86720
  description: exports_external.string()
@@ -105238,8 +105776,25 @@ var getProvider = (options = {}) => {
105238
105776
  options.command?.onStderr(dataStr);
105239
105777
  stderrText += dataStr;
105240
105778
  });
105241
- child.on("close", (code) => {
105779
+ child.on("close", async (code) => {
105242
105780
  options.command?.onExit(code ?? 0);
105781
+ const totalLength = stdoutText.length + stderrText.length;
105782
+ if (totalLength > (options.summaryThreshold ?? 5000) && options.summarizeOutput) {
105783
+ try {
105784
+ const summary = await options.summarizeOutput(stdoutText, stderrText);
105785
+ if (summary) {
105786
+ resolve7({
105787
+ summary,
105788
+ stdout: stdoutText,
105789
+ stderr: stderrText,
105790
+ exitCode: code ?? 0
105791
+ });
105792
+ return;
105793
+ }
105794
+ } catch (_e) {
105795
+ console.error("Summarization failed:", _e);
105796
+ }
105797
+ }
105243
105798
  resolve7({
105244
105799
  stdout: stdoutText,
105245
105800
  stderr: stderrText,
@@ -106029,6 +106584,201 @@ import { readFile as readFile2 } from "node:fs/promises";
106029
106584
  import os3 from "node:os";
106030
106585
  var import_lodash5 = __toESM(require_lodash(), 1);
106031
106586
 
106587
+ // src/commandSummarizer.ts
106588
+ var prompt3 = `
106589
+ System Prompt: Command Output Summarizer
106590
+
106591
+ Role
106592
+ - You are a coding agent that summarizes command execution results.
106593
+ - You receive raw stdout and stderr and must produce a concise, high-signal summary focused on what matters to developers.
106594
+
106595
+ Input
106596
+ - The input will ALWAYS be provided in this exact format:
106597
+ <stdout>
106598
+ \${stdout}
106599
+ </stdout>
106600
+ <stderr>
106601
+ \${stderr}
106602
+ </stderr>
106603
+ - Treat missing or empty sections as empty strings.
106604
+
106605
+ Core Objective
106606
+ - Extract and report ONLY the key lines that communicate failures, warnings, and actionable issues.
106607
+ - Ignore routine noise: progress bars, spinners, timestamps, banners, environment echoes, compilation start/finish messages, and other benign status lines.
106608
+ - Prefer brevity and accuracy. Do not ask questions. Do not repeat yourself.
106609
+
106610
+ General Rules
106611
+ 1) Preprocessing
106612
+ - Normalize newlines to "
106613
+ "; strip ANSI colors/escape codes.
106614
+ - Collapse repeated blank lines; trim trailing whitespace.
106615
+ - Deduplicate identical lines that appear many times; show one and append " (repeated N times)".
106616
+ - Truncate extremely long single lines to a reasonable width while preserving the essential portion (start and end), indicating truncation with "...".
106617
+ - Redact obvious secrets (tokens, passwords, keys) by masking the middle with "****", keeping at most the last 4 chars.
106618
+
106619
+ 2) Severity and Ordering
106620
+ - Prioritize in this order: Errors, Test Failures, Warnings, Important Notes.
106621
+ - Preserve original order within each section when helpful for debugging.
106622
+ - If an exit code is inferable (e.g., via error footers or phrases like "exit status 1"), include it in the Summary.
106623
+
106624
+ 3) Output Format (ASCII only, no tables)
106625
+ - Summary: one short line if any issues were found.
106626
+ Example: "Summary: exit_code=1; errors=3; warnings=2; failing_tests=4"
106627
+ - Then zero or more sections in this order, only if present:
106628
+ - Errors:
106629
+ - Test Failures:
106630
+ - Warnings:
106631
+ - Notes:
106632
+ - Within each section, use compact bullet points ("- ").
106633
+ - Quote key lines verbatim when they carry the signal (file:line:col, codes, rule names, assertion diffs).
106634
+ - Never include large code blocks; include at most 1-2 context lines around a key message when indispensable, marked with "...".
106635
+
106636
+ 4) What to Include vs Ignore (by tool/type)
106637
+ A) Test Runners (jest, mocha, vitest, pytest, nose, unittest, go test, rspec, junit, maven-surefire, gradle test)
106638
+ Include:
106639
+ - Names of failing test suites and test cases.
106640
+ - Assertion messages, diffs (Expected vs Received / AssertionError messages).
106641
+ - First 1-3 relevant stack frames pointing to user code (omit framework internals).
106642
+ - Summary counts: failed, skipped (if significant), total time if useful.
106643
+ Ignore:
106644
+ - Passed tests, pass counts, coverage success lines.
106645
+ - Test discovery notices, "OK"/"PASSED" banners, shard routing info.
106646
+ Example bullet:
106647
+ - tests/math.spec.ts: "adds numbers" FAILED: Expected 3, Received 4 at src/math.ts:12:7
106648
+
106649
+ B) Compilers/Build Tools (tsc, vite, webpack, esbuild, babel, gcc/clang, javac, kotlinc, rustc/cargo, go build, dotnet build, swiftc)
106650
+ Include:
106651
+ - Errors and warnings only (file:line:col if present, diagnostic code).
106652
+ - Linker errors and type mismatch details.
106653
+ Ignore:
106654
+ - Status/progress lines like "Compiling X", "Bundling Y", "Starting dev server...", "Note: some messages have been simplified".
106655
+ Example bullets:
106656
+ - src/foo.ts:42:13 TS2339 error: Property 'bar' does not exist on type 'Baz'.
106657
+ - lib/util.c:88:5 warning: unused variable 'tmp' [-Wunused-variable]
106658
+
106659
+ C) Linters/Formatters (eslint, flake8, pylint, rubocop, golangci-lint, stylelint, mypy, black/prettier)
106660
+ Include:
106661
+ - Violations with file:line:col, rule/id, brief message.
106662
+ - mypy type errors (treat as errors).
106663
+ Ignore:
106664
+ - "All matched files" summaries, formatter no-op messages.
106665
+ Example bullet:
106666
+ - src/app.tsx:17:9 eslint(no-unused-vars): 'user' is assigned a value but never used.
106667
+
106668
+ D) Runtime/Execution Errors (node, python, java, go, ruby, dotnet, shell)
106669
+ Include:
106670
+ - Error type/name and message.
106671
+ - Top 1-3 stack frames in user code; include "Caused by" chains.
106672
+ - Non-zero exit status if visible.
106673
+ Ignore:
106674
+ - Long internal/framework stacks unless they are the only frames available.
106675
+ Example bullet:
106676
+ - RuntimeError: connection refused at services/db.py:54 (exit status 1)
106677
+
106678
+ E) Package/Build Systems (npm/yarn/pnpm, pip/pipenv, poetry, cargo, maven, gradle)
106679
+ Include:
106680
+ - Install/build failures, script failures, postinstall errors.
106681
+ - Security advisories at high/critical severity (count + top advisory IDs).
106682
+ - Missing/invalid peer dependency errors that break install/build.
106683
+ Ignore:
106684
+ - Progress bars, fetch logs, cache hits, "up to date" lines.
106685
+ Example bullet:
106686
+ - npm ERR! test script failed: "jest --runInBand" (code 1)
106687
+
106688
+ F) VCS and CI (git, gh, svn; CI logs)
106689
+ Include:
106690
+ - Merge/rebase conflicts (files and conflict markers).
106691
+ - Push rejections (non-fast-forward, auth failures).
106692
+ - CI job failures (job name, failing step, error excerpt).
106693
+ Ignore:
106694
+ - Clean status, branch listings unless indicating a problem.
106695
+ Example bullet:
106696
+ - Merge conflict: src/index.ts (markers found around lines ~120-145)
106697
+
106698
+ G) Containers/Orchestration (docker, podman, kubectl, helm)
106699
+ Include:
106700
+ - Build failures (failed stages, missing files), run-time exit codes.
106701
+ - Kubernetes apply errors and crashloop events with reason.
106702
+ Ignore:
106703
+ - Layer download progress, pull status noise.
106704
+ Example bullet:
106705
+ - CrashLoopBackOff: pod api-7f6c... container "api" OOMKilled (restart 3/5)
106706
+
106707
+ H) Databases/SQL/Migrations (psql, mysql, sqlite, prisma, liquibase, flyway)
106708
+ Include:
106709
+ - SQLSTATE/error codes, constraint violations, migration failure details.
106710
+ Example bullet:
106711
+ - SQLSTATE 23505 unique_violation on users(email) at 2025-09-11T03:22Z
106712
+
106713
+ 5) Counts and Grouping
106714
+ - If 3+ similar diagnostics occur, summarize with a count and show 1-2 exemplars:
106715
+ Example: "Type errors (7): e.g., src/a.ts:10 TS2322: Type 'X' is not assignable to 'Y'."
106716
+ - When possible, group by file or rule to reduce noise.
106717
+
106718
+ 6) Stack Traces
106719
+ - Keep only the topmost relevant frames pointing to project files (e.g., paths under src/, app/, lib/).
106720
+ - Omit frames from node:internal, <anonymous>, site-packages/dist-packages unless they are the only frames.
106721
+
106722
+ 7) Timeouts/Resource Failures
106723
+ - If a timeout/OOM/segfault is detected, surface it prominently under Errors with the best short cause line.
106724
+
106725
+ 8) When There Is Nothing Noteworthy
106726
+ - If no errors, no warnings, and no failing tests are detected, output a single line:
106727
+ "No issues found."
106728
+ - Do NOT restate benign status like "build succeeded" or "all tests passed".
106729
+
106730
+ 9) Tone and Style
106731
+ - Be precise and unemotional.
106732
+ - Use short bullets; avoid prose paragraphs.
106733
+ - ASCII only; no emojis; no tables.
106734
+
106735
+ 10) Optional Next Actions
106736
+ - 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").
106737
+
106738
+ Detection Heuristics (non-exhaustive)
106739
+ - Errors: lines containing "error", "ERR!", "E ", "fatal", "Traceback", "Exception", "undefined reference", "cannot find symbol", "not found", "Segmentation fault", "panic:", "stack overflow".
106740
+ - Warnings: lines containing "warning", "WARN", "deprecated", "note: this will be removed" (treat "note" as warning only if explicitly labeled).
106741
+ - Test failures: lines with "FAIL", "FAILED", "Error", "AssertionError", "expect(", "--- FAIL:", "not ok", "Tests failed", or junit/pytest summaries with non-zero failures.
106742
+
106743
+ Output Template
106744
+ - Follow this shape; omit empty sections:
106745
+
106746
+ Summary: exit_code=<code>; errors=<N>; warnings=<M>; failing_tests=<K>
106747
+ Errors:
106748
+ - <file:line:col> <diagnostic code if any> <short message>
106749
+ - <next...>
106750
+
106751
+ Test Failures:
106752
+ - <suite or file> "<test name>": <assertion message or diff>; at <file:line[:col]>
106753
+ - <next...>
106754
+
106755
+ Warnings:
106756
+ - <file:line:col> <rule/code>: <short message>
106757
+
106758
+ Notes:
106759
+ - <concise note if indispensable>
106760
+
106761
+ Next actions:
106762
+ - <up to 3 short, concrete steps>
106763
+
106764
+ Final Requirements
106765
+ - Be concise, avoid repeating the same information.
106766
+ - Ensure accuracy; never invent details not present in the input.
106767
+ - Do not output tables unless explicitly asked.`;
106768
+ var summarizeOutput = async (model, stdout, stderr) => {
106769
+ const resp = await generateText({
106770
+ model,
106771
+ system: prompt3,
106772
+ prompt: `<stdout>
106773
+ ${stdout}
106774
+ </stdout>
106775
+ <stderr>
106776
+ ${stderr}
106777
+ </stderr>`
106778
+ });
106779
+ return resp.text;
106780
+ };
106781
+
106032
106782
  // src/getProviderOptions.ts
106033
106783
  function getProviderOptions(provider3, modelId, thinkingBudgetTokens, supportThinking) {
106034
106784
  if (thinkingBudgetTokens <= 0 || !provider3 || !modelId) {
@@ -106108,7 +106858,8 @@ class Runner {
106108
106858
  console.log(`$ <<<< $ Command error: ${error43}`);
106109
106859
  }
106110
106860
  },
106111
- excludeFiles: options.config.excludeFiles
106861
+ excludeFiles: options.config.excludeFiles,
106862
+ summaryThreshold: options.config.summaryThreshold
106112
106863
  };
106113
106864
  const platform = os3.platform();
106114
106865
  const llms = {};
@@ -106161,6 +106912,12 @@ class Runner {
106161
106912
  if (this.#options.interactive) {
106162
106913
  additionalTools.push(askFollowupQuestion_default);
106163
106914
  }
106915
+ const newToolProviderOptions = {
106916
+ ...toolProviderOptions,
106917
+ summarizeOutput: async (stdout, stderr) => {
106918
+ return await summarizeOutput(ai, stdout, stderr);
106919
+ }
106920
+ };
106164
106921
  const args = {
106165
106922
  ai,
106166
106923
  os: platform,
@@ -106178,7 +106935,7 @@ class Runner {
106178
106935
  },
106179
106936
  usageMeter: this.usageMeter,
106180
106937
  additionalTools,
106181
- provider: getProvider(toolProviderOptions)
106938
+ provider: getProvider(newToolProviderOptions)
106182
106939
  };
106183
106940
  switch (agentName) {
106184
106941
  case coderAgentInfo.name:
@@ -108394,9 +109151,10 @@ var getChangeInfo = {
108394
109151
  id: "get-change-info",
108395
109152
  type: "custom",
108396
109153
  run: async (input, context, _resumedState) => {
108397
- const { pr, json: json2 } = input;
109154
+ const { pr, json: json2, yes } = input;
108398
109155
  const logger = context.logger ?? console;
108399
109156
  context.json = json2;
109157
+ context.yes = yes;
108400
109158
  const {
108401
109159
  ui: { spinner }
108402
109160
  } = context;
@@ -108540,6 +109298,7 @@ var handleResult3 = {
108540
109298
  run: async (input, context, _resumedState) => {
108541
109299
  const { overview, specificReviews } = input;
108542
109300
  const json2 = context.json;
109301
+ const yes = context.yes;
108543
109302
  const logger = context.logger ?? console;
108544
109303
  const {
108545
109304
  ui: { spinner }
@@ -108558,14 +109317,18 @@ var handleResult3 = {
108558
109317
  const formatted = formatReviewForConsole(reviewResult);
108559
109318
  logger.log(formatted);
108560
109319
  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);
109320
+ if (reviewResult.specificReviews.length > 0) {
109321
+ if (yes) {
109322
+ shouldRunTask = true;
109323
+ } else if (process.stdin.isTTY) {
109324
+ try {
109325
+ shouldRunTask = await esm_default2({
109326
+ message: "Do you wish polka-codes to address the review results?",
109327
+ default: false
109328
+ });
109329
+ } catch {
109330
+ process.exit(130);
109331
+ }
108569
109332
  }
108570
109333
  }
108571
109334
  const output = { shouldRunTask };
@@ -108831,31 +109594,62 @@ async function runTask(taskArg, _options, command2, opts = {}) {
108831
109594
  }
108832
109595
 
108833
109596
  // 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) => {
109597
+ 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) => {
109598
+ if (value === undefined || value === null) {
109599
+ return 1;
109600
+ }
109601
+ const parsedValue = parseInt(value, 10);
109602
+ if (Number.isNaN(parsedValue) || parsedValue < 1) {
109603
+ throw new InvalidOptionArgumentError("Must be a positive number.");
109604
+ }
109605
+ return parsedValue;
109606
+ }, 1).action(async (options, command2) => {
109607
+ const { json: json2, pr: pr2, loop: maxIterations, yes: yesOption } = options;
109608
+ const yes = maxIterations > 1 || yesOption;
109609
+ let usageMeter;
109610
+ let changesAppliedInThisIteration = false;
109611
+ const handleSuccess = async (result, cmd, um) => {
109612
+ if (um) {
109613
+ if (usageMeter) {
109614
+ usageMeter.merge(um);
109615
+ } else {
109616
+ usageMeter = um;
109617
+ }
109618
+ }
108839
109619
  if (result.type === "success" && result.output.shouldRunTask) {
108840
- _willRunTask = true;
108841
- if (!command3) {
109620
+ changesAppliedInThisIteration = true;
109621
+ if (!cmd) {
108842
109622
  throw new Error("Command object not available in handleSuccess");
108843
109623
  }
108844
109624
  const taskInstruction = `please address the review result:
108845
109625
 
108846
109626
  ${result.output.formattedReview}`;
108847
- await runTask(taskInstruction, {}, command3, {
109627
+ await runTask(taskInstruction, {}, cmd, {
108848
109628
  externalUsageMeter: usageMeter,
108849
- suppressUsagePrint: false
109629
+ suppressUsagePrint: true
108850
109630
  });
108851
- } else if (usageMeter && !json2) {
108852
- usageMeter.printUsage();
108853
109631
  }
108854
109632
  };
108855
- await runWorkflowCommand("review", reviewWorkflow, command2, input, handleSuccess, {
108856
- json: json2,
108857
- suppressUsagePrint: true
108858
- });
109633
+ for (let i = 0;i < maxIterations; i++) {
109634
+ changesAppliedInThisIteration = false;
109635
+ const input = { json: json2, ...pr2 && { pr: pr2 }, yes };
109636
+ if (i > 0) {
109637
+ command2.opts().silent || console.log(`
109638
+ Re-running review (iteration ${i + 1} of ${maxIterations})...`);
109639
+ }
109640
+ await runWorkflowCommand("review", reviewWorkflow, command2, input, handleSuccess, {
109641
+ json: json2,
109642
+ suppressUsagePrint: true
109643
+ });
109644
+ if (maxIterations > 1 && !changesAppliedInThisIteration) {
109645
+ command2.opts().silent || console.log(`
109646
+ No more review feedback to apply. Exiting loop.`);
109647
+ break;
109648
+ }
109649
+ }
109650
+ if (usageMeter && !json2) {
109651
+ usageMeter.printUsage();
109652
+ }
108859
109653
  });
108860
109654
 
108861
109655
  // 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.36",
4
4
  "license": "AGPL-3.0",
5
5
  "author": "github@polka.codes",
6
6
  "type": "module",