nolo-cli 0.1.37 → 0.1.38
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/cli/client/agentRun.ts +68 -17
- package/client/agentRun.ts +68 -17
- package/package.json +1 -1
package/cli/client/agentRun.ts
CHANGED
|
@@ -73,6 +73,47 @@ export type RunAgentTurnResult = {
|
|
|
73
73
|
streamInterrupted?: boolean;
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
+
class Spinner {
|
|
77
|
+
private timer: any = null;
|
|
78
|
+
private frameIndex = 0;
|
|
79
|
+
private frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
80
|
+
private isTTY: boolean;
|
|
81
|
+
|
|
82
|
+
constructor(
|
|
83
|
+
private output: OutputLike,
|
|
84
|
+
private text: string
|
|
85
|
+
) {
|
|
86
|
+
this.isTTY = Boolean((output as any).isTTY ?? process.stdout.isTTY);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
start() {
|
|
90
|
+
if (!this.isTTY) {
|
|
91
|
+
this.output.write(`\n${this.text}...\n`);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this.frameIndex = 0;
|
|
96
|
+
this.output.write(`\x1b[36m${this.frames[0]}\x1b[39m ${this.text}...`);
|
|
97
|
+
|
|
98
|
+
this.timer = setInterval(() => {
|
|
99
|
+
this.frameIndex = (this.frameIndex + 1) % this.frames.length;
|
|
100
|
+
this.output.write(`\r\x1b[36m${this.frames[this.frameIndex]}\x1b[39m ${this.text}...`);
|
|
101
|
+
}, 80);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
stop() {
|
|
105
|
+
if (this.timer) {
|
|
106
|
+
clearInterval(this.timer);
|
|
107
|
+
this.timer = null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (this.isTTY) {
|
|
111
|
+
this.output.write("\r\x1b[K");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
76
117
|
const SERVER_PLATFORM_TOOL_NAMES = new Set([
|
|
77
118
|
"addTableRow",
|
|
78
119
|
"addTableRows",
|
|
@@ -502,7 +543,8 @@ function buildTransportErrorHint(serverUrl: string, error: unknown) {
|
|
|
502
543
|
}
|
|
503
544
|
|
|
504
545
|
async function runHttpAgentTurn(options: RunAgentTurnOptions, authToken: string) {
|
|
505
|
-
options.output
|
|
546
|
+
const spinner = new Spinner(options.output, `${options.agentName} -> working`);
|
|
547
|
+
spinner.start();
|
|
506
548
|
|
|
507
549
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
508
550
|
let res: Response;
|
|
@@ -556,14 +598,16 @@ async function runHttpAgentTurn(options: RunAgentTurnOptions, authToken: string)
|
|
|
556
598
|
...(typeof options.timeoutMs === "number" ? { timeoutMs: options.timeoutMs } : {}),
|
|
557
599
|
stream: !options.noStream && !options.background,
|
|
558
600
|
}),
|
|
559
|
-
});
|
|
560
|
-
} catch (error) {
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
601
|
+
});
|
|
602
|
+
} catch (error) {
|
|
603
|
+
spinner.stop();
|
|
604
|
+
options.output.write(buildTransportErrorHint(options.serverUrl, error));
|
|
605
|
+
return { exitCode: 1 };
|
|
606
|
+
}
|
|
607
|
+
|
|
565
608
|
const contentType = res.headers.get("content-type") || "";
|
|
566
609
|
if (contentType.includes("text/event-stream") && res.body) {
|
|
610
|
+
spinner.stop();
|
|
567
611
|
const result = await readStreamingAgentRun(options, res);
|
|
568
612
|
await recordTaskRunOutcome({
|
|
569
613
|
options,
|
|
@@ -577,14 +621,15 @@ async function runHttpAgentTurn(options: RunAgentTurnOptions, authToken: string)
|
|
|
577
621
|
});
|
|
578
622
|
return result;
|
|
579
623
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
624
|
+
|
|
625
|
+
spinner.stop();
|
|
626
|
+
let data: any = {};
|
|
627
|
+
try {
|
|
628
|
+
data = await res.json();
|
|
629
|
+
} catch {
|
|
630
|
+
data = {};
|
|
631
|
+
}
|
|
632
|
+
|
|
588
633
|
if (!res.ok) {
|
|
589
634
|
options.output.write(`[nolo] Agent request failed: HTTP ${res.status}\n`);
|
|
590
635
|
if (data?.error || data?.message) {
|
|
@@ -691,7 +736,8 @@ async function runLocalAgentTurnForCli(
|
|
|
691
736
|
return { exitCode: 1 };
|
|
692
737
|
}
|
|
693
738
|
|
|
694
|
-
options.output
|
|
739
|
+
const spinner = new Spinner(options.output, `${options.agentName} -> working locally`);
|
|
740
|
+
spinner.start();
|
|
695
741
|
const toolEvents: LocalAgentToolEvent[] = [];
|
|
696
742
|
try {
|
|
697
743
|
const traceLocalTools = shouldTraceLocalTools(options);
|
|
@@ -716,11 +762,15 @@ async function runLocalAgentTurnForCli(
|
|
|
716
762
|
? {
|
|
717
763
|
onToolEvent: (event) => {
|
|
718
764
|
if (collectToolEvidence) toolEvents.push(event);
|
|
719
|
-
if (traceLocalTools)
|
|
765
|
+
if (traceLocalTools) {
|
|
766
|
+
spinner.stop();
|
|
767
|
+
options.output.write(formatToolTraceEvent(event));
|
|
768
|
+
}
|
|
720
769
|
},
|
|
721
770
|
}
|
|
722
771
|
: {}),
|
|
723
772
|
});
|
|
773
|
+
spinner.stop();
|
|
724
774
|
const content = result.content.trim();
|
|
725
775
|
if (content) {
|
|
726
776
|
options.output.write(`\n${options.agentName} > ${content}\n`);
|
|
@@ -736,6 +786,7 @@ async function runLocalAgentTurnForCli(
|
|
|
736
786
|
});
|
|
737
787
|
return { exitCode: 0, dialogId: result.dialogId };
|
|
738
788
|
} catch (error) {
|
|
789
|
+
spinner.stop();
|
|
739
790
|
if (settings.reportFailure) {
|
|
740
791
|
options.output.write(
|
|
741
792
|
`[nolo] Local agent run failed: ${
|
package/client/agentRun.ts
CHANGED
|
@@ -73,6 +73,47 @@ export type RunAgentTurnResult = {
|
|
|
73
73
|
streamInterrupted?: boolean;
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
+
class Spinner {
|
|
77
|
+
private timer: any = null;
|
|
78
|
+
private frameIndex = 0;
|
|
79
|
+
private frames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
80
|
+
private isTTY: boolean;
|
|
81
|
+
|
|
82
|
+
constructor(
|
|
83
|
+
private output: OutputLike,
|
|
84
|
+
private text: string
|
|
85
|
+
) {
|
|
86
|
+
this.isTTY = Boolean((output as any).isTTY ?? process.stdout.isTTY);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
start() {
|
|
90
|
+
if (!this.isTTY) {
|
|
91
|
+
this.output.write(`\n${this.text}...\n`);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
this.frameIndex = 0;
|
|
96
|
+
this.output.write(`\x1b[36m${this.frames[0]}\x1b[39m ${this.text}...`);
|
|
97
|
+
|
|
98
|
+
this.timer = setInterval(() => {
|
|
99
|
+
this.frameIndex = (this.frameIndex + 1) % this.frames.length;
|
|
100
|
+
this.output.write(`\r\x1b[36m${this.frames[this.frameIndex]}\x1b[39m ${this.text}...`);
|
|
101
|
+
}, 80);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
stop() {
|
|
105
|
+
if (this.timer) {
|
|
106
|
+
clearInterval(this.timer);
|
|
107
|
+
this.timer = null;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (this.isTTY) {
|
|
111
|
+
this.output.write("\r\x1b[K");
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
76
117
|
const SERVER_PLATFORM_TOOL_NAMES = new Set([
|
|
77
118
|
"addTableRow",
|
|
78
119
|
"addTableRows",
|
|
@@ -502,7 +543,8 @@ function buildTransportErrorHint(serverUrl: string, error: unknown) {
|
|
|
502
543
|
}
|
|
503
544
|
|
|
504
545
|
async function runHttpAgentTurn(options: RunAgentTurnOptions, authToken: string) {
|
|
505
|
-
options.output
|
|
546
|
+
const spinner = new Spinner(options.output, `${options.agentName} -> working`);
|
|
547
|
+
spinner.start();
|
|
506
548
|
|
|
507
549
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
508
550
|
let res: Response;
|
|
@@ -556,14 +598,16 @@ async function runHttpAgentTurn(options: RunAgentTurnOptions, authToken: string)
|
|
|
556
598
|
...(typeof options.timeoutMs === "number" ? { timeoutMs: options.timeoutMs } : {}),
|
|
557
599
|
stream: !options.noStream && !options.background,
|
|
558
600
|
}),
|
|
559
|
-
});
|
|
560
|
-
} catch (error) {
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
601
|
+
});
|
|
602
|
+
} catch (error) {
|
|
603
|
+
spinner.stop();
|
|
604
|
+
options.output.write(buildTransportErrorHint(options.serverUrl, error));
|
|
605
|
+
return { exitCode: 1 };
|
|
606
|
+
}
|
|
607
|
+
|
|
565
608
|
const contentType = res.headers.get("content-type") || "";
|
|
566
609
|
if (contentType.includes("text/event-stream") && res.body) {
|
|
610
|
+
spinner.stop();
|
|
567
611
|
const result = await readStreamingAgentRun(options, res);
|
|
568
612
|
await recordTaskRunOutcome({
|
|
569
613
|
options,
|
|
@@ -577,14 +621,15 @@ async function runHttpAgentTurn(options: RunAgentTurnOptions, authToken: string)
|
|
|
577
621
|
});
|
|
578
622
|
return result;
|
|
579
623
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
624
|
+
|
|
625
|
+
spinner.stop();
|
|
626
|
+
let data: any = {};
|
|
627
|
+
try {
|
|
628
|
+
data = await res.json();
|
|
629
|
+
} catch {
|
|
630
|
+
data = {};
|
|
631
|
+
}
|
|
632
|
+
|
|
588
633
|
if (!res.ok) {
|
|
589
634
|
options.output.write(`[nolo] Agent request failed: HTTP ${res.status}\n`);
|
|
590
635
|
if (data?.error || data?.message) {
|
|
@@ -691,7 +736,8 @@ async function runLocalAgentTurnForCli(
|
|
|
691
736
|
return { exitCode: 1 };
|
|
692
737
|
}
|
|
693
738
|
|
|
694
|
-
options.output
|
|
739
|
+
const spinner = new Spinner(options.output, `${options.agentName} -> working locally`);
|
|
740
|
+
spinner.start();
|
|
695
741
|
const toolEvents: LocalAgentToolEvent[] = [];
|
|
696
742
|
try {
|
|
697
743
|
const traceLocalTools = shouldTraceLocalTools(options);
|
|
@@ -716,11 +762,15 @@ async function runLocalAgentTurnForCli(
|
|
|
716
762
|
? {
|
|
717
763
|
onToolEvent: (event) => {
|
|
718
764
|
if (collectToolEvidence) toolEvents.push(event);
|
|
719
|
-
if (traceLocalTools)
|
|
765
|
+
if (traceLocalTools) {
|
|
766
|
+
spinner.stop();
|
|
767
|
+
options.output.write(formatToolTraceEvent(event));
|
|
768
|
+
}
|
|
720
769
|
},
|
|
721
770
|
}
|
|
722
771
|
: {}),
|
|
723
772
|
});
|
|
773
|
+
spinner.stop();
|
|
724
774
|
const content = result.content.trim();
|
|
725
775
|
if (content) {
|
|
726
776
|
options.output.write(`\n${options.agentName} > ${content}\n`);
|
|
@@ -736,6 +786,7 @@ async function runLocalAgentTurnForCli(
|
|
|
736
786
|
});
|
|
737
787
|
return { exitCode: 0, dialogId: result.dialogId };
|
|
738
788
|
} catch (error) {
|
|
789
|
+
spinner.stop();
|
|
739
790
|
if (settings.reportFailure) {
|
|
740
791
|
options.output.write(
|
|
741
792
|
`[nolo] Local agent run failed: ${
|