@iinm/plain-agent 1.5.3 → 1.6.0
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/.config/config.predefined.json +90 -0
- package/package.json +1 -1
- package/src/cliFormatter.mjs +11 -18
- package/src/cliInteractive.mjs +202 -31
|
@@ -539,6 +539,15 @@
|
|
|
539
539
|
}
|
|
540
540
|
}
|
|
541
541
|
}
|
|
542
|
+
},
|
|
543
|
+
"cost": {
|
|
544
|
+
"currency": "USD",
|
|
545
|
+
"unit": "1M",
|
|
546
|
+
"costs": {
|
|
547
|
+
"promptTokenCount": 2,
|
|
548
|
+
"cachedContentTokenCount": -1.8,
|
|
549
|
+
"candidatesTokenCount": 12
|
|
550
|
+
}
|
|
542
551
|
}
|
|
543
552
|
},
|
|
544
553
|
{
|
|
@@ -565,6 +574,15 @@
|
|
|
565
574
|
}
|
|
566
575
|
}
|
|
567
576
|
}
|
|
577
|
+
},
|
|
578
|
+
"cost": {
|
|
579
|
+
"currency": "USD",
|
|
580
|
+
"unit": "1M",
|
|
581
|
+
"costs": {
|
|
582
|
+
"promptTokenCount": 2,
|
|
583
|
+
"cachedContentTokenCount": -1.8,
|
|
584
|
+
"candidatesTokenCount": 12
|
|
585
|
+
}
|
|
568
586
|
}
|
|
569
587
|
},
|
|
570
588
|
|
|
@@ -659,6 +677,15 @@
|
|
|
659
677
|
}
|
|
660
678
|
}
|
|
661
679
|
}
|
|
680
|
+
},
|
|
681
|
+
"cost": {
|
|
682
|
+
"currency": "USD",
|
|
683
|
+
"unit": "1M",
|
|
684
|
+
"costs": {
|
|
685
|
+
"promptTokenCount": 2,
|
|
686
|
+
"cachedContentTokenCount": -1.8,
|
|
687
|
+
"candidatesTokenCount": 12
|
|
688
|
+
}
|
|
662
689
|
}
|
|
663
690
|
},
|
|
664
691
|
{
|
|
@@ -684,6 +711,15 @@
|
|
|
684
711
|
}
|
|
685
712
|
}
|
|
686
713
|
}
|
|
714
|
+
},
|
|
715
|
+
"cost": {
|
|
716
|
+
"currency": "USD",
|
|
717
|
+
"unit": "1M",
|
|
718
|
+
"costs": {
|
|
719
|
+
"promptTokenCount": 2,
|
|
720
|
+
"cachedContentTokenCount": -1.8,
|
|
721
|
+
"candidatesTokenCount": 12
|
|
722
|
+
}
|
|
687
723
|
}
|
|
688
724
|
},
|
|
689
725
|
|
|
@@ -703,6 +739,15 @@
|
|
|
703
739
|
"store": false,
|
|
704
740
|
"include": ["reasoning.encrypted_content"]
|
|
705
741
|
}
|
|
742
|
+
},
|
|
743
|
+
"cost": {
|
|
744
|
+
"currency": "USD",
|
|
745
|
+
"unit": "1M",
|
|
746
|
+
"costs": {
|
|
747
|
+
"input_tokens": 0.75,
|
|
748
|
+
"cached_tokens": -0.675,
|
|
749
|
+
"output_tokens": 4.5
|
|
750
|
+
}
|
|
706
751
|
}
|
|
707
752
|
},
|
|
708
753
|
{
|
|
@@ -721,6 +766,15 @@
|
|
|
721
766
|
"store": false,
|
|
722
767
|
"include": ["reasoning.encrypted_content"]
|
|
723
768
|
}
|
|
769
|
+
},
|
|
770
|
+
"cost": {
|
|
771
|
+
"currency": "USD",
|
|
772
|
+
"unit": "1M",
|
|
773
|
+
"costs": {
|
|
774
|
+
"input_tokens": 0.75,
|
|
775
|
+
"cached_tokens": -0.675,
|
|
776
|
+
"output_tokens": 4.5
|
|
777
|
+
}
|
|
724
778
|
}
|
|
725
779
|
},
|
|
726
780
|
{
|
|
@@ -739,6 +793,15 @@
|
|
|
739
793
|
"store": false,
|
|
740
794
|
"include": ["reasoning.encrypted_content"]
|
|
741
795
|
}
|
|
796
|
+
},
|
|
797
|
+
"cost": {
|
|
798
|
+
"currency": "USD",
|
|
799
|
+
"unit": "1M",
|
|
800
|
+
"costs": {
|
|
801
|
+
"input_tokens": 0.75,
|
|
802
|
+
"cached_tokens": -0.675,
|
|
803
|
+
"output_tokens": 4.5
|
|
804
|
+
}
|
|
742
805
|
}
|
|
743
806
|
},
|
|
744
807
|
{
|
|
@@ -757,6 +820,15 @@
|
|
|
757
820
|
"store": false,
|
|
758
821
|
"include": ["reasoning.encrypted_content"]
|
|
759
822
|
}
|
|
823
|
+
},
|
|
824
|
+
"cost": {
|
|
825
|
+
"currency": "USD",
|
|
826
|
+
"unit": "1M",
|
|
827
|
+
"costs": {
|
|
828
|
+
"input_tokens": 2.5,
|
|
829
|
+
"cached_tokens": -2.25,
|
|
830
|
+
"output_tokens": 15
|
|
831
|
+
}
|
|
760
832
|
}
|
|
761
833
|
},
|
|
762
834
|
{
|
|
@@ -775,6 +847,15 @@
|
|
|
775
847
|
"store": false,
|
|
776
848
|
"include": ["reasoning.encrypted_content"]
|
|
777
849
|
}
|
|
850
|
+
},
|
|
851
|
+
"cost": {
|
|
852
|
+
"currency": "USD",
|
|
853
|
+
"unit": "1M",
|
|
854
|
+
"costs": {
|
|
855
|
+
"input_tokens": 2.5,
|
|
856
|
+
"cached_tokens": -2.25,
|
|
857
|
+
"output_tokens": 15
|
|
858
|
+
}
|
|
778
859
|
}
|
|
779
860
|
},
|
|
780
861
|
{
|
|
@@ -793,6 +874,15 @@
|
|
|
793
874
|
"store": false,
|
|
794
875
|
"include": ["reasoning.encrypted_content"]
|
|
795
876
|
}
|
|
877
|
+
},
|
|
878
|
+
"cost": {
|
|
879
|
+
"currency": "USD",
|
|
880
|
+
"unit": "1M",
|
|
881
|
+
"costs": {
|
|
882
|
+
"input_tokens": 2.5,
|
|
883
|
+
"cached_tokens": -2.25,
|
|
884
|
+
"output_tokens": 15
|
|
885
|
+
}
|
|
796
886
|
}
|
|
797
887
|
},
|
|
798
888
|
|
package/package.json
CHANGED
package/src/cliFormatter.mjs
CHANGED
|
@@ -219,12 +219,18 @@ export function formatCostSummary(summary) {
|
|
|
219
219
|
|
|
220
220
|
const lines = [];
|
|
221
221
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
222
|
+
if (summary.totalCost !== undefined) {
|
|
223
|
+
lines.push(
|
|
224
|
+
styleText(
|
|
225
|
+
"bold",
|
|
226
|
+
`\nTotal: ${summary.totalCost.toFixed(4)} ${summary.currency}`,
|
|
227
|
+
),
|
|
228
|
+
);
|
|
229
|
+
} else {
|
|
230
|
+
lines.push(styleText("yellow", "Total: N/A (no cost configuration)"));
|
|
231
|
+
}
|
|
227
232
|
|
|
233
|
+
lines.push(styleText("bold", "\nTokens:"));
|
|
228
234
|
for (const [key, { tokens, cost }] of Object.entries(summary.breakdown)) {
|
|
229
235
|
const tokenStr = `${key}: ${tokens.toLocaleString()}`;
|
|
230
236
|
|
|
@@ -236,19 +242,6 @@ export function formatCostSummary(summary) {
|
|
|
236
242
|
}
|
|
237
243
|
}
|
|
238
244
|
|
|
239
|
-
// Total
|
|
240
|
-
lines.push("");
|
|
241
|
-
if (summary.totalCost !== undefined) {
|
|
242
|
-
lines.push(
|
|
243
|
-
styleText(
|
|
244
|
-
"bold",
|
|
245
|
-
`Total: ${summary.totalCost.toFixed(4)} ${summary.currency}`,
|
|
246
|
-
),
|
|
247
|
-
);
|
|
248
|
-
} else {
|
|
249
|
-
lines.push(styleText("yellow", "Total: N/A (no cost configuration)"));
|
|
250
|
-
}
|
|
251
|
-
|
|
252
245
|
return lines.join("\n");
|
|
253
246
|
}
|
|
254
247
|
|
package/src/cliInteractive.mjs
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import { execFileSync } from "node:child_process";
|
|
8
8
|
import readline from "node:readline";
|
|
9
|
+
import { Transform } from "node:stream";
|
|
9
10
|
import { styleText } from "node:util";
|
|
10
11
|
import {
|
|
11
12
|
formatCostSummary,
|
|
@@ -189,6 +190,57 @@ const HELP_MESSAGE = [
|
|
|
189
190
|
.replace(/^ {2}\/.+?(?= - )/gm, (m) => styleText("cyan", m))
|
|
190
191
|
.replace(/^ {2}.+?(?= - )/gm, (m) => styleText("blue", m));
|
|
191
192
|
|
|
193
|
+
// Bracketed paste mode sequences
|
|
194
|
+
const BRACKETED_PASTE_START = "\x1b[200~";
|
|
195
|
+
const BRACKETED_PASTE_END = "\x1b[201~";
|
|
196
|
+
|
|
197
|
+
// Store for pasted content
|
|
198
|
+
const pastedContentStore = new Map();
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Generate a short hash for paste reference
|
|
202
|
+
* @param {string} content
|
|
203
|
+
* @returns {string}
|
|
204
|
+
*/
|
|
205
|
+
function generatePasteHash(content) {
|
|
206
|
+
let hash = 0;
|
|
207
|
+
for (let i = 0; i < content.length; i++) {
|
|
208
|
+
const char = content.charCodeAt(i);
|
|
209
|
+
hash = (hash << 5) - hash + char;
|
|
210
|
+
hash = hash & hash; // Convert to 32bit integer
|
|
211
|
+
}
|
|
212
|
+
return Math.abs(hash).toString(16).padStart(6, "0").slice(0, 6);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Resolve paste placeholders and append context tags
|
|
217
|
+
* @param {string} input
|
|
218
|
+
* @returns {string}
|
|
219
|
+
*/
|
|
220
|
+
function resolvePastePlaceholders(input) {
|
|
221
|
+
/** @type {string[]} */
|
|
222
|
+
const contexts = [];
|
|
223
|
+
|
|
224
|
+
// Collect paste content for context tags while keeping placeholders
|
|
225
|
+
const text = input.replace(/\[pasted#([a-f0-9]{6})\]/g, (match, hash) => {
|
|
226
|
+
const content = pastedContentStore.get(hash);
|
|
227
|
+
if (content !== undefined) {
|
|
228
|
+
pastedContentStore.delete(hash); // Clean up after use
|
|
229
|
+
contexts.push(
|
|
230
|
+
`<context location="pasted#${hash}">\n${content}\n</context>`,
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
return match; // Keep placeholder in text
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Append contexts to the end of input
|
|
237
|
+
if (contexts.length > 0) {
|
|
238
|
+
return [text, ...contexts].join("\n\n");
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return text;
|
|
242
|
+
}
|
|
243
|
+
|
|
192
244
|
/**
|
|
193
245
|
* @typedef {object} CliOptions
|
|
194
246
|
* @property {UserEventEmitter} userEventEmitter
|
|
@@ -232,13 +284,16 @@ export function startInteractiveSession({
|
|
|
232
284
|
const agentRoles = await loadAgentRoles(claudeCodePlugins);
|
|
233
285
|
const agent = agentRoles.get(id);
|
|
234
286
|
const name = agent ? id : `custom:${id}`;
|
|
235
|
-
const message = `Delegate to "${name}" agent with goal: ${goal}`;
|
|
236
287
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
288
|
+
const [goalTextContent, ...goalImages] = await loadUserMessageContext(goal);
|
|
289
|
+
const goalText =
|
|
290
|
+
goalTextContent?.type === "text" ? goalTextContent.text : goal;
|
|
240
291
|
|
|
241
|
-
|
|
292
|
+
const messageText = `Delegate to "${name}" agent with goal: ${goalText}`;
|
|
293
|
+
userEventEmitter.emit("userInput", [
|
|
294
|
+
{ type: "text", text: messageText },
|
|
295
|
+
...goalImages,
|
|
296
|
+
]);
|
|
242
297
|
}
|
|
243
298
|
|
|
244
299
|
/**
|
|
@@ -258,16 +313,21 @@ export function startInteractiveSession({
|
|
|
258
313
|
return;
|
|
259
314
|
}
|
|
260
315
|
|
|
261
|
-
const
|
|
316
|
+
const [argsTextContent, ...argsImages] = args
|
|
317
|
+
? await loadUserMessageContext(args)
|
|
318
|
+
: [];
|
|
319
|
+
const argsText =
|
|
320
|
+
argsTextContent?.type === "text" ? argsTextContent.text : args;
|
|
321
|
+
|
|
322
|
+
const invocation = `${displayInvocation}${argsText ? ` ${argsText}` : ""}`;
|
|
262
323
|
const message = prompt.isSkill
|
|
263
324
|
? `System: This prompt was invoked as "${invocation}".\nPrompt path: ${prompt.filePath}\n\n${prompt.content}`
|
|
264
325
|
: `System: This prompt was invoked as "${invocation}".\n\n${prompt.content}`;
|
|
265
326
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
userEventEmitter.emit("userInput", [{ type: "text", text: message }]);
|
|
327
|
+
userEventEmitter.emit("userInput", [
|
|
328
|
+
{ type: "text", text: message },
|
|
329
|
+
...argsImages,
|
|
330
|
+
]);
|
|
271
331
|
}
|
|
272
332
|
|
|
273
333
|
const getCliPrompt = (subagentName = "") =>
|
|
@@ -283,9 +343,89 @@ export function startInteractiveSession({
|
|
|
283
343
|
"> ",
|
|
284
344
|
].join("\n");
|
|
285
345
|
|
|
346
|
+
// Indirect reference for exit handler (assigned after confirmExit is defined)
|
|
347
|
+
let onExitRequest = () => {};
|
|
348
|
+
|
|
349
|
+
// Create a transform stream to handle bracketed paste before readline
|
|
350
|
+
let inPasteMode = false;
|
|
351
|
+
let pasteBuffer = "";
|
|
352
|
+
|
|
353
|
+
const pasteTransform = new Transform({
|
|
354
|
+
transform(chunk, _encoding, callback) {
|
|
355
|
+
let data = chunk.toString("utf8");
|
|
356
|
+
|
|
357
|
+
// Handle Ctrl-C and Ctrl-D
|
|
358
|
+
if (data.includes("\x03") || data.includes("\x04")) {
|
|
359
|
+
// Ctrl-C / Ctrl-D: request exit (handled by confirmExit)
|
|
360
|
+
onExitRequest();
|
|
361
|
+
callback();
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
while (data.length > 0) {
|
|
366
|
+
if (inPasteMode) {
|
|
367
|
+
const endIdx = data.indexOf(BRACKETED_PASTE_END);
|
|
368
|
+
if (endIdx !== -1) {
|
|
369
|
+
// End of paste
|
|
370
|
+
pasteBuffer += data.slice(0, endIdx);
|
|
371
|
+
data = data.slice(endIdx + BRACKETED_PASTE_END.length);
|
|
372
|
+
inPasteMode = false;
|
|
373
|
+
|
|
374
|
+
// Handle paste content
|
|
375
|
+
if (pasteBuffer) {
|
|
376
|
+
// Remove trailing newline for single-line paste detection
|
|
377
|
+
const trimmedPaste = pasteBuffer.replace(/\n$/, "");
|
|
378
|
+
|
|
379
|
+
// For single-line paste, insert directly without placeholder
|
|
380
|
+
if (!trimmedPaste.includes("\n")) {
|
|
381
|
+
this.push(trimmedPaste);
|
|
382
|
+
} else {
|
|
383
|
+
// For multi-line paste, use placeholder
|
|
384
|
+
const hash = generatePasteHash(pasteBuffer);
|
|
385
|
+
pastedContentStore.set(hash, pasteBuffer);
|
|
386
|
+
this.push(`[pasted#${hash}] `);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
pasteBuffer = "";
|
|
390
|
+
} else {
|
|
391
|
+
// Still in paste mode
|
|
392
|
+
pasteBuffer += data;
|
|
393
|
+
data = "";
|
|
394
|
+
}
|
|
395
|
+
} else {
|
|
396
|
+
const startIdx = data.indexOf(BRACKETED_PASTE_START);
|
|
397
|
+
if (startIdx !== -1) {
|
|
398
|
+
// Start of paste
|
|
399
|
+
// Output any data before the paste
|
|
400
|
+
if (startIdx > 0) {
|
|
401
|
+
this.push(data.slice(0, startIdx));
|
|
402
|
+
}
|
|
403
|
+
data = data.slice(startIdx + BRACKETED_PASTE_START.length);
|
|
404
|
+
inPasteMode = true;
|
|
405
|
+
pasteBuffer = "";
|
|
406
|
+
} else {
|
|
407
|
+
// Normal data
|
|
408
|
+
this.push(data);
|
|
409
|
+
data = "";
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
callback();
|
|
415
|
+
},
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
// Set up transformed stdin for readline
|
|
419
|
+
process.stdin.pipe(pasteTransform);
|
|
420
|
+
|
|
421
|
+
// Enable bracketed paste mode
|
|
422
|
+
if (process.stdout.isTTY) {
|
|
423
|
+
process.stdout.write("\x1b[?2004h");
|
|
424
|
+
}
|
|
425
|
+
|
|
286
426
|
let currentCliPrompt = getCliPrompt();
|
|
287
427
|
const cli = readline.createInterface({
|
|
288
|
-
input:
|
|
428
|
+
input: pasteTransform,
|
|
289
429
|
output: process.stdout,
|
|
290
430
|
prompt: currentCliPrompt,
|
|
291
431
|
/**
|
|
@@ -372,16 +512,46 @@ export function startInteractiveSession({
|
|
|
372
512
|
if (process.stdin.isTTY) {
|
|
373
513
|
process.stdin.setRawMode(true);
|
|
374
514
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
if (
|
|
378
|
-
|
|
515
|
+
// Cleanup handler to disable bracketed paste mode on exit
|
|
516
|
+
const cleanup = () => {
|
|
517
|
+
if (process.stdout.isTTY) {
|
|
518
|
+
process.stdout.write("\x1b[?2004l");
|
|
379
519
|
}
|
|
520
|
+
};
|
|
380
521
|
|
|
381
|
-
|
|
382
|
-
|
|
522
|
+
// Handle exit signals
|
|
523
|
+
let isExiting = false;
|
|
524
|
+
const handleExit = async () => {
|
|
525
|
+
if (isExiting) return;
|
|
526
|
+
isExiting = true;
|
|
527
|
+
|
|
528
|
+
cleanup();
|
|
529
|
+
const summary = agentCommands.getCostSummary();
|
|
530
|
+
console.log();
|
|
531
|
+
console.log(formatCostSummary(summary));
|
|
532
|
+
await onStop();
|
|
533
|
+
process.exit(0);
|
|
534
|
+
};
|
|
535
|
+
|
|
536
|
+
// Double-press exit confirmation
|
|
537
|
+
let lastExitAttempt = 0;
|
|
538
|
+
const EXIT_CONFIRM_TIMEOUT = 1500;
|
|
539
|
+
|
|
540
|
+
const confirmExit = () => {
|
|
541
|
+
const now = Date.now();
|
|
542
|
+
if (now - lastExitAttempt < EXIT_CONFIRM_TIMEOUT) {
|
|
543
|
+
handleExit();
|
|
544
|
+
return;
|
|
383
545
|
}
|
|
384
|
-
|
|
546
|
+
lastExitAttempt = now;
|
|
547
|
+
console.log(styleText("yellow", "\nPress Ctrl-C or Ctrl-D again to exit."));
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
// Wire up exit request handler for Ctrl-C / Ctrl-D
|
|
551
|
+
onExitRequest = confirmExit;
|
|
552
|
+
|
|
553
|
+
// Handle readline close (e.g., stdin closed externally)
|
|
554
|
+
cli.on("close", handleExit);
|
|
385
555
|
|
|
386
556
|
/**
|
|
387
557
|
* Process the complete user input.
|
|
@@ -392,7 +562,9 @@ export function startInteractiveSession({
|
|
|
392
562
|
// Prevent concurrent input processing from multi-line paste
|
|
393
563
|
state.turn = false;
|
|
394
564
|
|
|
395
|
-
|
|
565
|
+
// Resolve paste placeholders to original content
|
|
566
|
+
const resolvedInput = resolvePastePlaceholders(input);
|
|
567
|
+
const inputTrimmed = resolvedInput.trim();
|
|
396
568
|
|
|
397
569
|
if (inputTrimmed.length === 0) {
|
|
398
570
|
state.turn = true;
|
|
@@ -427,10 +599,6 @@ export function startInteractiveSession({
|
|
|
427
599
|
return;
|
|
428
600
|
}
|
|
429
601
|
|
|
430
|
-
console.log(styleText("gray", "\n<input>"));
|
|
431
|
-
console.log(fileContent);
|
|
432
|
-
console.log(styleText("gray", "</input>"));
|
|
433
|
-
|
|
434
602
|
const messageWithContext = await loadUserMessageContext(fileContent);
|
|
435
603
|
|
|
436
604
|
userEventEmitter.emit("userInput", messageWithContext);
|
|
@@ -501,7 +669,7 @@ export function startInteractiveSession({
|
|
|
501
669
|
}
|
|
502
670
|
|
|
503
671
|
if (inputTrimmed.startsWith("/prompts:")) {
|
|
504
|
-
const match = inputTrimmed.match(/^\/prompts:([^ ]+)(?:\s+(.*))?$/);
|
|
672
|
+
const match = inputTrimmed.match(/^\/prompts:([^ ]+)(?:\s+(.*))?$/s);
|
|
505
673
|
if (!match) {
|
|
506
674
|
console.log(styleText("red", "\nInvalid prompt invocation format."));
|
|
507
675
|
state.turn = true;
|
|
@@ -514,7 +682,7 @@ export function startInteractiveSession({
|
|
|
514
682
|
}
|
|
515
683
|
|
|
516
684
|
if (inputTrimmed.startsWith("/agents:")) {
|
|
517
|
-
const match = inputTrimmed.match(/^\/agents:([^ ]+)(?:\s+(.*))?$/);
|
|
685
|
+
const match = inputTrimmed.match(/^\/agents:([^ ]+)(?:\s+(.*))?$/s);
|
|
518
686
|
if (!match) {
|
|
519
687
|
console.log(styleText("red", "\nInvalid agent invocation format."));
|
|
520
688
|
state.turn = true;
|
|
@@ -561,10 +729,6 @@ export function startInteractiveSession({
|
|
|
561
729
|
|
|
562
730
|
const combinedInput = prompt ? `${prompt}\n\n${clipboard}` : clipboard;
|
|
563
731
|
|
|
564
|
-
console.log(styleText("gray", "\n<paste>"));
|
|
565
|
-
console.log(combinedInput);
|
|
566
|
-
console.log(styleText("gray", "</paste>"));
|
|
567
|
-
|
|
568
732
|
const messageWithContext = await loadUserMessageContext(combinedInput);
|
|
569
733
|
userEventEmitter.emit("userInput", messageWithContext);
|
|
570
734
|
return;
|
|
@@ -600,7 +764,7 @@ export function startInteractiveSession({
|
|
|
600
764
|
return;
|
|
601
765
|
}
|
|
602
766
|
|
|
603
|
-
//
|
|
767
|
+
// Check for multi-line delimiter
|
|
604
768
|
if (lineInput.trim() === '"""') {
|
|
605
769
|
if (state.multiLineBuffer === null) {
|
|
606
770
|
state.multiLineBuffer = [];
|
|
@@ -697,6 +861,10 @@ export function startInteractiveSession({
|
|
|
697
861
|
});
|
|
698
862
|
|
|
699
863
|
cli.prompt();
|
|
864
|
+
|
|
865
|
+
// Register cleanup handlers
|
|
866
|
+
process.on("exit", cleanup);
|
|
867
|
+
process.on("SIGTERM", cleanup);
|
|
700
868
|
}
|
|
701
869
|
|
|
702
870
|
/**
|
|
@@ -742,6 +910,9 @@ function printMessage(message) {
|
|
|
742
910
|
console.log(part.text);
|
|
743
911
|
break;
|
|
744
912
|
}
|
|
913
|
+
case "image": {
|
|
914
|
+
break;
|
|
915
|
+
}
|
|
745
916
|
default: {
|
|
746
917
|
console.log(styleText("bold", "\nUnknown Message Format:"));
|
|
747
918
|
console.log(JSON.stringify(part, null, 2));
|