@adhdev/daemon-core 0.9.64 → 0.9.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat/chat-signatures.d.ts +0 -4
- package/dist/chat/chat-signatures.js +0 -4
- package/dist/chat/chat-signatures.js.map +1 -1
- package/dist/chat/chat-signatures.mjs +0 -4
- package/dist/chat/chat-signatures.mjs.map +1 -1
- package/dist/chat/subscription-updates.d.ts +0 -2
- package/dist/cli-adapters/provider-cli-adapter.d.ts +2 -30
- package/dist/cli-adapters/provider-cli-parse.d.ts +1 -8
- package/dist/cli-adapters/provider-cli-shared.d.ts +8 -3
- package/dist/commands/chat-commands.d.ts +0 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +646 -1712
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +646 -1712
- package/dist/index.mjs.map +1 -1
- package/dist/shared-types.d.ts +0 -7
- package/node_modules/@adhdev/session-host-core/package.json +1 -1
- package/package.json +1 -1
- package/src/chat/chat-signatures.ts +0 -8
- package/src/chat/subscription-updates.ts +7 -46
- package/src/cli-adapters/provider-cli-adapter.d.ts +2 -10
- package/src/cli-adapters/provider-cli-adapter.ts +66 -692
- package/src/cli-adapters/provider-cli-parse.d.ts +0 -7
- package/src/cli-adapters/provider-cli-parse.ts +2 -226
- package/src/cli-adapters/provider-cli-shared.d.ts +0 -1
- package/src/cli-adapters/provider-cli-shared.ts +8 -3
- package/src/commands/chat-commands.ts +54 -366
- package/src/daemon/dev-auto-implement.ts +3 -3
- package/src/daemon/dev-server.ts +3 -3
- package/src/index.d.ts +1 -1
- package/src/index.ts +0 -1
- package/src/launch.ts +10 -3
- package/src/providers/cli-provider-instance.ts +2 -39
- package/src/shared-types.d.ts +0 -7
- package/src/shared-types.ts +0 -8
package/dist/index.mjs
CHANGED
|
@@ -477,525 +477,6 @@ var init_logger = __esm({
|
|
|
477
477
|
}
|
|
478
478
|
});
|
|
479
479
|
|
|
480
|
-
// src/providers/io-contracts.ts
|
|
481
|
-
function normalizeInputEnvelope(input) {
|
|
482
|
-
const normalized = normalizeInputEnvelopePayload(input);
|
|
483
|
-
const textFallback = normalized.textFallback ?? flattenInputParts(normalized.parts);
|
|
484
|
-
return {
|
|
485
|
-
parts: normalized.parts,
|
|
486
|
-
textFallback,
|
|
487
|
-
...normalized.metadata ? { metadata: normalized.metadata } : {}
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
function normalizeMessageParts(content) {
|
|
491
|
-
if (typeof content === "string") return [{ type: "text", text: content }];
|
|
492
|
-
if (!Array.isArray(content)) {
|
|
493
|
-
if (content && typeof content === "object" && typeof content.text === "string") {
|
|
494
|
-
return [{ type: "text", text: String(content.text) }];
|
|
495
|
-
}
|
|
496
|
-
return [];
|
|
497
|
-
}
|
|
498
|
-
const parts = [];
|
|
499
|
-
for (const raw of content) {
|
|
500
|
-
if (typeof raw === "string") {
|
|
501
|
-
parts.push({ type: "text", text: raw });
|
|
502
|
-
continue;
|
|
503
|
-
}
|
|
504
|
-
if (!raw || typeof raw !== "object") continue;
|
|
505
|
-
const part = normalizeMessagePartObject(raw);
|
|
506
|
-
if (part) parts.push(part);
|
|
507
|
-
}
|
|
508
|
-
return parts;
|
|
509
|
-
}
|
|
510
|
-
function flattenMessageParts(parts) {
|
|
511
|
-
return parts.map((part) => {
|
|
512
|
-
if (part.type === "text") return part.text;
|
|
513
|
-
if (part.type === "resource") return part.resource.text || "";
|
|
514
|
-
return "";
|
|
515
|
-
}).filter((value) => value.length > 0).join("\n");
|
|
516
|
-
}
|
|
517
|
-
function normalizeInputEnvelopePayload(input) {
|
|
518
|
-
if (typeof input === "string") {
|
|
519
|
-
return { parts: [{ type: "text", text: input }], textFallback: input };
|
|
520
|
-
}
|
|
521
|
-
if (!input || typeof input !== "object") {
|
|
522
|
-
return { parts: [], textFallback: "" };
|
|
523
|
-
}
|
|
524
|
-
const record = input;
|
|
525
|
-
const nestedInput = record.input;
|
|
526
|
-
if (nestedInput && typeof nestedInput === "object") {
|
|
527
|
-
const nested = nestedInput;
|
|
528
|
-
return {
|
|
529
|
-
parts: normalizeInputParts(nested.parts ?? nested.prompt),
|
|
530
|
-
textFallback: typeof nested.textFallback === "string" ? nested.textFallback : void 0,
|
|
531
|
-
metadata: normalizeInputMetadata(nested.metadata)
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
const directText = typeof record.text === "string" ? record.text : typeof record.message === "string" ? record.message : void 0;
|
|
535
|
-
if (directText !== void 0) {
|
|
536
|
-
return { parts: [{ type: "text", text: directText }], textFallback: directText };
|
|
537
|
-
}
|
|
538
|
-
const directParts = normalizeInputParts(record.parts ?? record.prompt);
|
|
539
|
-
return {
|
|
540
|
-
parts: directParts,
|
|
541
|
-
textFallback: typeof record.textFallback === "string" ? record.textFallback : void 0,
|
|
542
|
-
metadata: normalizeInputMetadata(record.metadata)
|
|
543
|
-
};
|
|
544
|
-
}
|
|
545
|
-
function normalizeInputMetadata(value) {
|
|
546
|
-
if (!value || typeof value !== "object") return void 0;
|
|
547
|
-
const record = value;
|
|
548
|
-
const metadata = {};
|
|
549
|
-
if (record.source === "dashboard" || record.source === "shortcut_api" || record.source === "provider_script" || record.source === "session_replay") {
|
|
550
|
-
metadata.source = record.source;
|
|
551
|
-
}
|
|
552
|
-
if (typeof record.clientTimestamp === "number" && Number.isFinite(record.clientTimestamp)) {
|
|
553
|
-
metadata.clientTimestamp = record.clientTimestamp;
|
|
554
|
-
}
|
|
555
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
556
|
-
}
|
|
557
|
-
function normalizeInputParts(value) {
|
|
558
|
-
if (!Array.isArray(value)) return [];
|
|
559
|
-
const parts = [];
|
|
560
|
-
for (const raw of value) {
|
|
561
|
-
if (typeof raw === "string") {
|
|
562
|
-
parts.push({ type: "text", text: raw });
|
|
563
|
-
continue;
|
|
564
|
-
}
|
|
565
|
-
if (!raw || typeof raw !== "object") continue;
|
|
566
|
-
const part = normalizeInputPartObject(raw);
|
|
567
|
-
if (part) parts.push(part);
|
|
568
|
-
}
|
|
569
|
-
return parts;
|
|
570
|
-
}
|
|
571
|
-
function normalizeInputPartObject(raw) {
|
|
572
|
-
const type = raw.type;
|
|
573
|
-
if (type === "text" && typeof raw.text === "string") {
|
|
574
|
-
return { type, text: raw.text };
|
|
575
|
-
}
|
|
576
|
-
if (type === "image" && typeof raw.mimeType === "string") {
|
|
577
|
-
return {
|
|
578
|
-
type,
|
|
579
|
-
mimeType: raw.mimeType,
|
|
580
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
581
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
582
|
-
...typeof raw.alt === "string" ? { alt: raw.alt } : {}
|
|
583
|
-
};
|
|
584
|
-
}
|
|
585
|
-
if (type === "audio" && typeof raw.mimeType === "string") {
|
|
586
|
-
return {
|
|
587
|
-
type,
|
|
588
|
-
mimeType: raw.mimeType,
|
|
589
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
590
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
591
|
-
...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
|
|
592
|
-
};
|
|
593
|
-
}
|
|
594
|
-
if (type === "video" && typeof raw.mimeType === "string") {
|
|
595
|
-
return {
|
|
596
|
-
type,
|
|
597
|
-
mimeType: raw.mimeType,
|
|
598
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
599
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
600
|
-
...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
|
|
601
|
-
};
|
|
602
|
-
}
|
|
603
|
-
if (type === "resource" && typeof raw.uri === "string") {
|
|
604
|
-
return {
|
|
605
|
-
type,
|
|
606
|
-
uri: raw.uri,
|
|
607
|
-
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
608
|
-
...typeof raw.name === "string" ? { name: raw.name } : {},
|
|
609
|
-
...typeof raw.text === "string" ? { text: raw.text } : {},
|
|
610
|
-
...typeof raw.data === "string" ? { data: raw.data } : {}
|
|
611
|
-
};
|
|
612
|
-
}
|
|
613
|
-
if (type === "resource_link" && typeof raw.uri === "string") {
|
|
614
|
-
return {
|
|
615
|
-
type: "resource",
|
|
616
|
-
uri: raw.uri,
|
|
617
|
-
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
618
|
-
...typeof raw.name === "string" ? { name: raw.name } : {}
|
|
619
|
-
};
|
|
620
|
-
}
|
|
621
|
-
return null;
|
|
622
|
-
}
|
|
623
|
-
function normalizeMessagePartObject(raw) {
|
|
624
|
-
const type = raw.type;
|
|
625
|
-
if (type === "text" && typeof raw.text === "string") {
|
|
626
|
-
return { type, text: raw.text };
|
|
627
|
-
}
|
|
628
|
-
if (type === "image" && typeof raw.mimeType === "string") {
|
|
629
|
-
return {
|
|
630
|
-
type,
|
|
631
|
-
mimeType: raw.mimeType,
|
|
632
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
633
|
-
...typeof raw.data === "string" ? { data: raw.data } : {}
|
|
634
|
-
};
|
|
635
|
-
}
|
|
636
|
-
if (type === "audio" && typeof raw.mimeType === "string") {
|
|
637
|
-
return {
|
|
638
|
-
type,
|
|
639
|
-
mimeType: raw.mimeType,
|
|
640
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
641
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
642
|
-
...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
|
|
643
|
-
};
|
|
644
|
-
}
|
|
645
|
-
if (type === "video" && typeof raw.mimeType === "string") {
|
|
646
|
-
return {
|
|
647
|
-
type,
|
|
648
|
-
mimeType: raw.mimeType,
|
|
649
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
650
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
651
|
-
...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
|
|
652
|
-
};
|
|
653
|
-
}
|
|
654
|
-
if (type === "resource_link" && typeof raw.uri === "string" && typeof raw.name === "string") {
|
|
655
|
-
return {
|
|
656
|
-
type,
|
|
657
|
-
uri: raw.uri,
|
|
658
|
-
name: raw.name,
|
|
659
|
-
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
660
|
-
...typeof raw.size === "number" ? { size: raw.size } : {}
|
|
661
|
-
};
|
|
662
|
-
}
|
|
663
|
-
if (type === "resource" && raw.resource && typeof raw.resource === "object") {
|
|
664
|
-
const resource = raw.resource;
|
|
665
|
-
if (typeof resource.uri !== "string") return null;
|
|
666
|
-
return {
|
|
667
|
-
type,
|
|
668
|
-
resource: {
|
|
669
|
-
uri: resource.uri,
|
|
670
|
-
...typeof resource.mimeType === "string" || resource.mimeType === null ? { mimeType: resource.mimeType } : {},
|
|
671
|
-
...typeof resource.text === "string" ? { text: resource.text } : {},
|
|
672
|
-
...typeof resource.blob === "string" ? { blob: resource.blob } : {}
|
|
673
|
-
}
|
|
674
|
-
};
|
|
675
|
-
}
|
|
676
|
-
return null;
|
|
677
|
-
}
|
|
678
|
-
function flattenInputParts(parts) {
|
|
679
|
-
return parts.map((part) => {
|
|
680
|
-
if (part.type === "text") return part.text;
|
|
681
|
-
if (part.type === "audio") return part.transcript || "";
|
|
682
|
-
if (part.type === "resource") return part.text || "";
|
|
683
|
-
return "";
|
|
684
|
-
}).filter((value) => value.length > 0).join("\n");
|
|
685
|
-
}
|
|
686
|
-
var init_io_contracts = __esm({
|
|
687
|
-
"src/providers/io-contracts.ts"() {
|
|
688
|
-
"use strict";
|
|
689
|
-
}
|
|
690
|
-
});
|
|
691
|
-
|
|
692
|
-
// src/providers/contracts.ts
|
|
693
|
-
function flattenContent(content) {
|
|
694
|
-
if (typeof content === "string") return content;
|
|
695
|
-
return flattenMessageParts(normalizeMessageParts(content));
|
|
696
|
-
}
|
|
697
|
-
var init_contracts = __esm({
|
|
698
|
-
"src/providers/contracts.ts"() {
|
|
699
|
-
"use strict";
|
|
700
|
-
init_io_contracts();
|
|
701
|
-
init_io_contracts();
|
|
702
|
-
}
|
|
703
|
-
});
|
|
704
|
-
|
|
705
|
-
// src/providers/chat-message-normalization.ts
|
|
706
|
-
function canonicalizeKindHint(value) {
|
|
707
|
-
return value.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
708
|
-
}
|
|
709
|
-
function resolveBuiltinOrAliasKind(kind) {
|
|
710
|
-
if (typeof kind !== "string") return null;
|
|
711
|
-
const normalizedKind = canonicalizeKindHint(kind);
|
|
712
|
-
if (!normalizedKind) return null;
|
|
713
|
-
if (KNOWN_CHAT_MESSAGE_KINDS.has(normalizedKind)) return normalizedKind;
|
|
714
|
-
return CHAT_MESSAGE_KIND_ALIASES[normalizedKind] || null;
|
|
715
|
-
}
|
|
716
|
-
function inferHintKind(value) {
|
|
717
|
-
const direct = resolveBuiltinOrAliasKind(value);
|
|
718
|
-
if (direct) return direct;
|
|
719
|
-
if (typeof value !== "string") return null;
|
|
720
|
-
const normalized = canonicalizeKindHint(value);
|
|
721
|
-
if (!normalized) return null;
|
|
722
|
-
if (/thought|thinking|reasoning/.test(normalized)) return "thought";
|
|
723
|
-
if (/tool/.test(normalized)) return "tool";
|
|
724
|
-
if (/terminal|command|shell|console/.test(normalized)) return "terminal";
|
|
725
|
-
return null;
|
|
726
|
-
}
|
|
727
|
-
function inferKindFromToolCalls(message) {
|
|
728
|
-
const toolCalls = Array.isArray(message?.toolCalls) ? message.toolCalls : [];
|
|
729
|
-
if (toolCalls.length === 0) return null;
|
|
730
|
-
if (toolCalls.some((toolCall) => toolCall?.kind === "think")) return "thought";
|
|
731
|
-
if (toolCalls.some((toolCall) => toolCall?.kind === "execute")) return "terminal";
|
|
732
|
-
if (toolCalls.some((toolCall) => Array.isArray(toolCall?.content) && toolCall.content.some((entry) => entry?.type === "terminal"))) {
|
|
733
|
-
return "terminal";
|
|
734
|
-
}
|
|
735
|
-
return "tool";
|
|
736
|
-
}
|
|
737
|
-
function inferMissingChatMessageKind(message) {
|
|
738
|
-
const role = typeof message?.role === "string" ? message.role.trim().toLowerCase() : "";
|
|
739
|
-
if (role === "system") return "system";
|
|
740
|
-
const meta = message?.meta && typeof message.meta === "object" ? message.meta : void 0;
|
|
741
|
-
const hintCandidates = [
|
|
742
|
-
message?._sub,
|
|
743
|
-
message?._type,
|
|
744
|
-
meta?.label,
|
|
745
|
-
typeof message?.senderName === "string" ? message.senderName : void 0
|
|
746
|
-
];
|
|
747
|
-
for (const candidate of hintCandidates) {
|
|
748
|
-
const inferred = inferHintKind(candidate);
|
|
749
|
-
if (inferred) return inferred;
|
|
750
|
-
}
|
|
751
|
-
const inferredFromToolCalls = inferKindFromToolCalls(message);
|
|
752
|
-
if (inferredFromToolCalls) return inferredFromToolCalls;
|
|
753
|
-
return null;
|
|
754
|
-
}
|
|
755
|
-
function isBuiltinChatMessageKind(kind) {
|
|
756
|
-
return resolveBuiltinOrAliasKind(kind) !== null;
|
|
757
|
-
}
|
|
758
|
-
function normalizeChatMessageKind(kind, role) {
|
|
759
|
-
const resolvedKind = resolveBuiltinOrAliasKind(kind);
|
|
760
|
-
if (resolvedKind) return resolvedKind;
|
|
761
|
-
const normalizedRole = typeof role === "string" ? role.trim().toLowerCase() : "";
|
|
762
|
-
return normalizedRole === "system" ? "system" : "standard";
|
|
763
|
-
}
|
|
764
|
-
function resolveChatMessageKind(message) {
|
|
765
|
-
const explicitKind = resolveBuiltinOrAliasKind(message?.kind);
|
|
766
|
-
if (explicitKind) return explicitKind;
|
|
767
|
-
const inferredKind = inferMissingChatMessageKind(message);
|
|
768
|
-
if (inferredKind) return inferredKind;
|
|
769
|
-
return normalizeChatMessageKind(message?.kind, message?.role);
|
|
770
|
-
}
|
|
771
|
-
function buildChatMessage(message) {
|
|
772
|
-
return {
|
|
773
|
-
...message,
|
|
774
|
-
kind: resolveChatMessageKind(message)
|
|
775
|
-
};
|
|
776
|
-
}
|
|
777
|
-
function buildSystemChatMessage(message) {
|
|
778
|
-
return buildChatMessage({
|
|
779
|
-
...message,
|
|
780
|
-
role: "system",
|
|
781
|
-
kind: message?.kind || "system"
|
|
782
|
-
});
|
|
783
|
-
}
|
|
784
|
-
function buildRuntimeSystemChatMessage(message) {
|
|
785
|
-
return buildSystemChatMessage({
|
|
786
|
-
...message,
|
|
787
|
-
senderName: typeof message?.senderName === "string" && message.senderName.trim() ? message.senderName : "System"
|
|
788
|
-
});
|
|
789
|
-
}
|
|
790
|
-
function buildAssistantChatMessage(message) {
|
|
791
|
-
return buildChatMessage({
|
|
792
|
-
...message,
|
|
793
|
-
role: "assistant",
|
|
794
|
-
kind: message?.kind || "standard"
|
|
795
|
-
});
|
|
796
|
-
}
|
|
797
|
-
function buildThoughtChatMessage(message) {
|
|
798
|
-
return buildAssistantChatMessage({
|
|
799
|
-
...message,
|
|
800
|
-
kind: message?.kind || "thought"
|
|
801
|
-
});
|
|
802
|
-
}
|
|
803
|
-
function buildToolChatMessage(message) {
|
|
804
|
-
return buildAssistantChatMessage({
|
|
805
|
-
...message,
|
|
806
|
-
kind: message?.kind || "tool"
|
|
807
|
-
});
|
|
808
|
-
}
|
|
809
|
-
function buildTerminalChatMessage(message) {
|
|
810
|
-
return buildAssistantChatMessage({
|
|
811
|
-
...message,
|
|
812
|
-
kind: message?.kind || "terminal"
|
|
813
|
-
});
|
|
814
|
-
}
|
|
815
|
-
function buildUserChatMessage(message) {
|
|
816
|
-
return buildChatMessage({
|
|
817
|
-
...message,
|
|
818
|
-
role: "user",
|
|
819
|
-
kind: message?.kind || "standard"
|
|
820
|
-
});
|
|
821
|
-
}
|
|
822
|
-
function normalizeChatMessage(message) {
|
|
823
|
-
return buildChatMessage(message);
|
|
824
|
-
}
|
|
825
|
-
function normalizeChatMessages(messages) {
|
|
826
|
-
return (Array.isArray(messages) ? messages : []).map((message) => normalizeChatMessage(message));
|
|
827
|
-
}
|
|
828
|
-
var BUILTIN_CHAT_MESSAGE_KINDS, KNOWN_CHAT_MESSAGE_KINDS, CHAT_MESSAGE_KIND_ALIASES;
|
|
829
|
-
var init_chat_message_normalization = __esm({
|
|
830
|
-
"src/providers/chat-message-normalization.ts"() {
|
|
831
|
-
"use strict";
|
|
832
|
-
BUILTIN_CHAT_MESSAGE_KINDS = ["standard", "thought", "tool", "terminal", "system"];
|
|
833
|
-
KNOWN_CHAT_MESSAGE_KINDS = new Set(BUILTIN_CHAT_MESSAGE_KINDS);
|
|
834
|
-
CHAT_MESSAGE_KIND_ALIASES = {
|
|
835
|
-
text: "standard",
|
|
836
|
-
message: "standard",
|
|
837
|
-
assistant: "standard",
|
|
838
|
-
thinking: "thought",
|
|
839
|
-
think: "thought",
|
|
840
|
-
reasoning: "thought",
|
|
841
|
-
reason: "thought",
|
|
842
|
-
toolcall: "tool",
|
|
843
|
-
tool_call: "tool",
|
|
844
|
-
tooluse: "tool",
|
|
845
|
-
tool_use: "tool",
|
|
846
|
-
action: "tool",
|
|
847
|
-
command: "terminal",
|
|
848
|
-
cmd: "terminal",
|
|
849
|
-
shell: "terminal",
|
|
850
|
-
console: "terminal"
|
|
851
|
-
};
|
|
852
|
-
}
|
|
853
|
-
});
|
|
854
|
-
|
|
855
|
-
// src/providers/read-chat-contract.ts
|
|
856
|
-
function isPlainObject3(value) {
|
|
857
|
-
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
858
|
-
}
|
|
859
|
-
function isFiniteNumber(value) {
|
|
860
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
861
|
-
}
|
|
862
|
-
function validateStatus(status, source) {
|
|
863
|
-
if (typeof status !== "string" || !VALID_STATUSES.includes(status)) {
|
|
864
|
-
throw new Error(`${source}: status must be one of ${VALID_STATUSES.join(", ")}`);
|
|
865
|
-
}
|
|
866
|
-
return status;
|
|
867
|
-
}
|
|
868
|
-
function validateRole(role, source, index) {
|
|
869
|
-
if (typeof role !== "string" || !VALID_ROLES.includes(role)) {
|
|
870
|
-
throw new Error(`${source}: messages[${index}].role must be one of ${VALID_ROLES.join(", ")}`);
|
|
871
|
-
}
|
|
872
|
-
return role;
|
|
873
|
-
}
|
|
874
|
-
function validateBubbleState(state, source, index) {
|
|
875
|
-
if (typeof state !== "string" || !VALID_BUBBLE_STATES.includes(state)) {
|
|
876
|
-
throw new Error(`${source}: messages[${index}].bubbleState must be one of ${VALID_BUBBLE_STATES.join(", ")}`);
|
|
877
|
-
}
|
|
878
|
-
return state;
|
|
879
|
-
}
|
|
880
|
-
function validateTurnStatus(turnStatus, source) {
|
|
881
|
-
if (typeof turnStatus !== "string" || !VALID_TURN_STATUSES.includes(turnStatus)) {
|
|
882
|
-
throw new Error(`${source}: turnStatus must be one of ${VALID_TURN_STATUSES.join(", ")}`);
|
|
883
|
-
}
|
|
884
|
-
return turnStatus;
|
|
885
|
-
}
|
|
886
|
-
function validateMessageContent(content, source, index) {
|
|
887
|
-
if (typeof content === "string") return content;
|
|
888
|
-
if (Array.isArray(content)) return normalizeMessageParts(content);
|
|
889
|
-
throw new Error(`${source}: messages[${index}].content must be a string or structured content array`);
|
|
890
|
-
}
|
|
891
|
-
function validateMessage(message, source, index) {
|
|
892
|
-
if (!isPlainObject3(message)) {
|
|
893
|
-
throw new Error(`${source}: messages[${index}] must be an object`);
|
|
894
|
-
}
|
|
895
|
-
const normalized = {
|
|
896
|
-
role: validateRole(message.role, source, index),
|
|
897
|
-
content: validateMessageContent(message.content, source, index)
|
|
898
|
-
};
|
|
899
|
-
if (typeof message.kind === "string") normalized.kind = message.kind;
|
|
900
|
-
if (typeof message.id === "string") normalized.id = message.id;
|
|
901
|
-
if (typeof message.bubbleId === "string") normalized.bubbleId = message.bubbleId;
|
|
902
|
-
if (typeof message.providerUnitKey === "string") normalized.providerUnitKey = message.providerUnitKey;
|
|
903
|
-
if (message.bubbleState !== void 0) normalized.bubbleState = validateBubbleState(message.bubbleState, source, index);
|
|
904
|
-
if (isFiniteNumber(message.index)) normalized.index = message.index;
|
|
905
|
-
if (isFiniteNumber(message.timestamp)) normalized.timestamp = message.timestamp;
|
|
906
|
-
if (isFiniteNumber(message.receivedAt)) normalized.receivedAt = message.receivedAt;
|
|
907
|
-
if (typeof message._turnKey === "string") normalized._turnKey = message._turnKey;
|
|
908
|
-
if (Array.isArray(message.toolCalls)) normalized.toolCalls = message.toolCalls;
|
|
909
|
-
if (isPlainObject3(message.meta)) normalized.meta = message.meta;
|
|
910
|
-
if (typeof message.senderName === "string") normalized.senderName = message.senderName;
|
|
911
|
-
if (typeof message._type === "string") normalized._type = message._type;
|
|
912
|
-
if (typeof message._sub === "string") normalized._sub = message._sub;
|
|
913
|
-
return normalized;
|
|
914
|
-
}
|
|
915
|
-
function validateModal(activeModal, status, source) {
|
|
916
|
-
if (activeModal == null) {
|
|
917
|
-
if (status === "waiting_approval") {
|
|
918
|
-
throw new Error(`${source}: waiting_approval status requires activeModal with buttons`);
|
|
919
|
-
}
|
|
920
|
-
return activeModal === null ? null : void 0;
|
|
921
|
-
}
|
|
922
|
-
if (!isPlainObject3(activeModal)) {
|
|
923
|
-
throw new Error(`${source}: activeModal must be an object when provided`);
|
|
924
|
-
}
|
|
925
|
-
if (typeof activeModal.message !== "string") {
|
|
926
|
-
throw new Error(`${source}: activeModal.message must be a string`);
|
|
927
|
-
}
|
|
928
|
-
if (!Array.isArray(activeModal.buttons) || activeModal.buttons.some((button) => typeof button !== "string" || !button.trim())) {
|
|
929
|
-
throw new Error(`${source}: activeModal.buttons must be a non-empty string array`);
|
|
930
|
-
}
|
|
931
|
-
const normalized = {
|
|
932
|
-
message: activeModal.message,
|
|
933
|
-
buttons: activeModal.buttons.map((button) => button.trim())
|
|
934
|
-
};
|
|
935
|
-
if (isFiniteNumber(activeModal.width)) normalized.width = activeModal.width;
|
|
936
|
-
if (isFiniteNumber(activeModal.height)) normalized.height = activeModal.height;
|
|
937
|
-
return normalized;
|
|
938
|
-
}
|
|
939
|
-
function validateControlValues(controlValues, source) {
|
|
940
|
-
if (controlValues === void 0) return void 0;
|
|
941
|
-
if (!isPlainObject3(controlValues)) {
|
|
942
|
-
throw new Error(`${source}: controlValues must be an object when provided`);
|
|
943
|
-
}
|
|
944
|
-
const normalized = {};
|
|
945
|
-
for (const [key, value] of Object.entries(controlValues)) {
|
|
946
|
-
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") {
|
|
947
|
-
throw new Error(`${source}: controlValues.${key} must be string, number, or boolean`);
|
|
948
|
-
}
|
|
949
|
-
normalized[key] = value;
|
|
950
|
-
}
|
|
951
|
-
return normalized;
|
|
952
|
-
}
|
|
953
|
-
function validateReadChatResultPayload(raw, source = "read_chat") {
|
|
954
|
-
if (!isPlainObject3(raw)) {
|
|
955
|
-
throw new Error(`${source}: payload must be an object`);
|
|
956
|
-
}
|
|
957
|
-
const status = validateStatus(raw.status, source);
|
|
958
|
-
if (!Array.isArray(raw.messages)) {
|
|
959
|
-
throw new Error(`${source}: messages must be an array`);
|
|
960
|
-
}
|
|
961
|
-
const messages = raw.messages.map((message, index) => validateMessage(message, source, index));
|
|
962
|
-
const activeModal = validateModal(raw.activeModal, status, source);
|
|
963
|
-
const controlValues = validateControlValues(raw.controlValues, source);
|
|
964
|
-
const normalized = {
|
|
965
|
-
status,
|
|
966
|
-
messages
|
|
967
|
-
};
|
|
968
|
-
if (activeModal !== void 0) normalized.activeModal = activeModal;
|
|
969
|
-
if (typeof raw.id === "string") normalized.id = raw.id;
|
|
970
|
-
if (typeof raw.title === "string") normalized.title = raw.title;
|
|
971
|
-
if (typeof raw.currentTurnId === "string") normalized.currentTurnId = raw.currentTurnId;
|
|
972
|
-
if (raw.turnStatus !== void 0) normalized.turnStatus = validateTurnStatus(raw.turnStatus, source);
|
|
973
|
-
if (typeof raw.agentType === "string") normalized.agentType = raw.agentType;
|
|
974
|
-
if (typeof raw.agentName === "string") normalized.agentName = raw.agentName;
|
|
975
|
-
if (typeof raw.extensionId === "string") normalized.extensionId = raw.extensionId;
|
|
976
|
-
if (typeof raw.inputContent === "string") normalized.inputContent = raw.inputContent;
|
|
977
|
-
if (typeof raw.isVisible === "boolean") normalized.isVisible = raw.isVisible;
|
|
978
|
-
if (typeof raw.isWelcomeScreen === "boolean") normalized.isWelcomeScreen = raw.isWelcomeScreen;
|
|
979
|
-
if (controlValues) normalized.controlValues = controlValues;
|
|
980
|
-
if (raw.summaryMetadata !== void 0) normalized.summaryMetadata = raw.summaryMetadata;
|
|
981
|
-
if (Array.isArray(raw.effects)) normalized.effects = raw.effects;
|
|
982
|
-
if (typeof raw.providerSessionId === "string") normalized.providerSessionId = raw.providerSessionId;
|
|
983
|
-
if (raw.transcriptAuthority === "provider" || raw.transcriptAuthority === "daemon") normalized.transcriptAuthority = raw.transcriptAuthority;
|
|
984
|
-
if (raw.coverage === "full" || raw.coverage === "tail" || raw.coverage === "current-turn") normalized.coverage = raw.coverage;
|
|
985
|
-
return normalized;
|
|
986
|
-
}
|
|
987
|
-
var VALID_STATUSES, VALID_ROLES, VALID_BUBBLE_STATES, VALID_TURN_STATUSES;
|
|
988
|
-
var init_read_chat_contract = __esm({
|
|
989
|
-
"src/providers/read-chat-contract.ts"() {
|
|
990
|
-
"use strict";
|
|
991
|
-
init_contracts();
|
|
992
|
-
VALID_STATUSES = ["idle", "generating", "waiting_approval", "error", "panel_hidden", "streaming", "long_generating"];
|
|
993
|
-
VALID_ROLES = ["user", "assistant", "system", "human"];
|
|
994
|
-
VALID_BUBBLE_STATES = ["draft", "streaming", "final", "removed"];
|
|
995
|
-
VALID_TURN_STATUSES = ["open", "waiting_approval", "complete", "error"];
|
|
996
|
-
}
|
|
997
|
-
});
|
|
998
|
-
|
|
999
480
|
// src/logging/debug-config.ts
|
|
1000
481
|
function normalizeCategories(categories) {
|
|
1001
482
|
if (!Array.isArray(categories)) return [];
|
|
@@ -1563,67 +1044,6 @@ function promptLikelyVisible(screenText, promptSnippet) {
|
|
|
1563
1044
|
function normalizeScreenSnapshot(text) {
|
|
1564
1045
|
return sanitizeTerminalText(String(text || "")).replace(/\s+/g, " ").trim();
|
|
1565
1046
|
}
|
|
1566
|
-
function shouldReflowComparableMessageLines(lines) {
|
|
1567
|
-
return Array.isArray(lines) && lines.length > 1 && lines.slice(0, -1).every((line) => String(line || "").trim().length >= 48) && !lines.some((line) => /^```/.test(line)) && !lines.some((line) => /^\|/.test(line)) && !lines.some((line) => /^\s*(?:[-*+] |\d+\.\s)/.test(line));
|
|
1568
|
-
}
|
|
1569
|
-
function joinComparableMessageLines(lines) {
|
|
1570
|
-
return lines.reduce((acc, line) => {
|
|
1571
|
-
const next = String(line || "").trim();
|
|
1572
|
-
if (!next) return acc;
|
|
1573
|
-
if (!acc) return next;
|
|
1574
|
-
if (/[,\d]$/.test(acc) && /^\d/.test(next)) {
|
|
1575
|
-
return `${acc}${next}`;
|
|
1576
|
-
}
|
|
1577
|
-
if (/[A-Za-z]$/.test(acc) && /^\d/.test(next)) {
|
|
1578
|
-
return `${acc}${next}`;
|
|
1579
|
-
}
|
|
1580
|
-
const fragmentMatch = acc.match(/([A-Za-z]{1,4})$/);
|
|
1581
|
-
const fragment = fragmentMatch ? fragmentMatch[1].toLowerCase() : "";
|
|
1582
|
-
if (/^[a-z]/.test(next) && fragment && !COMMON_COMPARABLE_WRAP_WORDS.has(fragment)) {
|
|
1583
|
-
return `${acc}${next}`;
|
|
1584
|
-
}
|
|
1585
|
-
return `${acc} ${next}`;
|
|
1586
|
-
}, "").replace(/\s+([,.;:!?])/g, "$1").replace(/(\d)\s+,/g, "$1,").replace(/\s+/g, " ").trim();
|
|
1587
|
-
}
|
|
1588
|
-
function normalizeComparableMessageContent(text) {
|
|
1589
|
-
const lines = String(text || "").split(/\r\n|\n|\r/g).map((line) => line.trim()).filter(Boolean);
|
|
1590
|
-
if (lines.length === 0) return "";
|
|
1591
|
-
if (shouldReflowComparableMessageLines(lines)) {
|
|
1592
|
-
return joinComparableMessageLines(lines);
|
|
1593
|
-
}
|
|
1594
|
-
return lines.join(" ").replace(/\s+/g, " ").trim();
|
|
1595
|
-
}
|
|
1596
|
-
function trimPromptEchoPrefix(text, promptText) {
|
|
1597
|
-
const prompt = normalizeComparableMessageContent(String(promptText || ""));
|
|
1598
|
-
if (!prompt) return String(text || "");
|
|
1599
|
-
const lines = String(text || "").split(/\r\n|\n|\r/g);
|
|
1600
|
-
let dropCount = 0;
|
|
1601
|
-
for (let index = 0; index < Math.min(lines.length, 6); index += 1) {
|
|
1602
|
-
const fragment = normalizeComparableMessageContent(lines[index].replace(/^[.…]+\s*/, ""));
|
|
1603
|
-
if (!fragment) {
|
|
1604
|
-
if (dropCount === index) dropCount = index + 1;
|
|
1605
|
-
continue;
|
|
1606
|
-
}
|
|
1607
|
-
const fragmentWordCount = fragment ? fragment.split(/\s+/).filter(Boolean).length : 0;
|
|
1608
|
-
const canBePromptEcho = fragment.length >= 16 || fragmentWordCount >= 4;
|
|
1609
|
-
if (canBePromptEcho && prompt.includes(fragment)) {
|
|
1610
|
-
dropCount = index + 1;
|
|
1611
|
-
continue;
|
|
1612
|
-
}
|
|
1613
|
-
break;
|
|
1614
|
-
}
|
|
1615
|
-
return lines.slice(dropCount).join("\n").trim();
|
|
1616
|
-
}
|
|
1617
|
-
function getLastUserPromptText(messages) {
|
|
1618
|
-
const items = Array.isArray(messages) ? messages : [];
|
|
1619
|
-
for (let index = items.length - 1; index >= 0; index -= 1) {
|
|
1620
|
-
const message = items[index];
|
|
1621
|
-
if (message?.role === "user" && typeof message.content === "string" && message.content.trim()) {
|
|
1622
|
-
return message.content;
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
return "";
|
|
1626
|
-
}
|
|
1627
1047
|
function parsePatternEntry(x) {
|
|
1628
1048
|
if (x instanceof RegExp) return x;
|
|
1629
1049
|
if (x && typeof x === "object" && typeof x.source === "string") {
|
|
@@ -1650,38 +1070,12 @@ function normalizeCliProviderForRuntime(raw) {
|
|
|
1650
1070
|
}
|
|
1651
1071
|
};
|
|
1652
1072
|
}
|
|
1653
|
-
var buildCliSpawnEnv
|
|
1073
|
+
var buildCliSpawnEnv;
|
|
1654
1074
|
var init_provider_cli_shared = __esm({
|
|
1655
1075
|
"src/cli-adapters/provider-cli-shared.ts"() {
|
|
1656
1076
|
"use strict";
|
|
1657
1077
|
init_spawn_env();
|
|
1658
1078
|
buildCliSpawnEnv = sanitizeSpawnEnv;
|
|
1659
|
-
COMMON_COMPARABLE_WRAP_WORDS = /* @__PURE__ */ new Set([
|
|
1660
|
-
"a",
|
|
1661
|
-
"an",
|
|
1662
|
-
"and",
|
|
1663
|
-
"as",
|
|
1664
|
-
"at",
|
|
1665
|
-
"but",
|
|
1666
|
-
"by",
|
|
1667
|
-
"for",
|
|
1668
|
-
"from",
|
|
1669
|
-
"in",
|
|
1670
|
-
"into",
|
|
1671
|
-
"is",
|
|
1672
|
-
"it",
|
|
1673
|
-
"of",
|
|
1674
|
-
"on",
|
|
1675
|
-
"or",
|
|
1676
|
-
"that",
|
|
1677
|
-
"the",
|
|
1678
|
-
"their",
|
|
1679
|
-
"then",
|
|
1680
|
-
"this",
|
|
1681
|
-
"to",
|
|
1682
|
-
"was",
|
|
1683
|
-
"with"
|
|
1684
|
-
]);
|
|
1685
1079
|
}
|
|
1686
1080
|
});
|
|
1687
1081
|
|
|
@@ -1692,169 +1086,8 @@ function sliceFromOffset(text, start) {
|
|
|
1692
1086
|
if (start >= text.length) return "";
|
|
1693
1087
|
return text.slice(start);
|
|
1694
1088
|
}
|
|
1695
|
-
function
|
|
1696
|
-
|
|
1697
|
-
const referenceMessages = [...committedMessages];
|
|
1698
|
-
const referenceComparables = new Array(referenceMessages.length);
|
|
1699
|
-
const usedReferenceIndexes = /* @__PURE__ */ new Set();
|
|
1700
|
-
const now = options.now ?? Date.now();
|
|
1701
|
-
let exactReferenceIndexesByKey = null;
|
|
1702
|
-
const exactReferenceCursorByKey = /* @__PURE__ */ new Map();
|
|
1703
|
-
const hasFiniteTimestamp = (message) => typeof message?.timestamp === "number" && Number.isFinite(message.timestamp);
|
|
1704
|
-
const getReferenceComparable = (index) => {
|
|
1705
|
-
if (typeof referenceComparables[index] === "string") return referenceComparables[index] || "";
|
|
1706
|
-
const comparable = normalizeComparableMessageContent(referenceMessages[index]?.content || "");
|
|
1707
|
-
referenceComparables[index] = comparable;
|
|
1708
|
-
return comparable;
|
|
1709
|
-
};
|
|
1710
|
-
const messagesShareStableIdentity = (parsed, reference) => {
|
|
1711
|
-
if (!parsed || !reference) return false;
|
|
1712
|
-
const parsedId = typeof parsed.id === "string" ? parsed.id.trim() : "";
|
|
1713
|
-
const referenceId = typeof reference.id === "string" ? reference.id.trim() : "";
|
|
1714
|
-
if (parsedId && referenceId && parsedId === referenceId) return true;
|
|
1715
|
-
return typeof parsed.index === "number" && Number.isFinite(parsed.index) && typeof reference.index === "number" && Number.isFinite(reference.index) && parsed.index === reference.index;
|
|
1716
|
-
};
|
|
1717
|
-
const exactReferenceKey = (role, comparable) => `${role}\0${comparable}`;
|
|
1718
|
-
const ensureExactReferenceIndex = () => {
|
|
1719
|
-
if (exactReferenceIndexesByKey) return exactReferenceIndexesByKey;
|
|
1720
|
-
const byKey = /* @__PURE__ */ new Map();
|
|
1721
|
-
for (let i = 0; i < referenceMessages.length; i++) {
|
|
1722
|
-
const candidate = referenceMessages[i];
|
|
1723
|
-
if (!candidate || candidate.role !== "user" && candidate.role !== "assistant" || !hasFiniteTimestamp(candidate)) continue;
|
|
1724
|
-
const comparable = getReferenceComparable(i);
|
|
1725
|
-
if (!comparable) continue;
|
|
1726
|
-
const key = exactReferenceKey(candidate.role, comparable);
|
|
1727
|
-
const indexes = byKey.get(key);
|
|
1728
|
-
if (indexes) {
|
|
1729
|
-
indexes.push(i);
|
|
1730
|
-
} else {
|
|
1731
|
-
byKey.set(key, [i]);
|
|
1732
|
-
}
|
|
1733
|
-
}
|
|
1734
|
-
exactReferenceIndexesByKey = byKey;
|
|
1735
|
-
return byKey;
|
|
1736
|
-
};
|
|
1737
|
-
const takeExactReferenceTimestamp = (role, normalizedContent) => {
|
|
1738
|
-
const key = exactReferenceKey(role, normalizedContent);
|
|
1739
|
-
const indexes = ensureExactReferenceIndex().get(key);
|
|
1740
|
-
if (!indexes) return void 0;
|
|
1741
|
-
let cursor = exactReferenceCursorByKey.get(key) || 0;
|
|
1742
|
-
while (cursor < indexes.length) {
|
|
1743
|
-
const candidateIndex = indexes[cursor];
|
|
1744
|
-
cursor += 1;
|
|
1745
|
-
if (usedReferenceIndexes.has(candidateIndex)) continue;
|
|
1746
|
-
const candidate = referenceMessages[candidateIndex];
|
|
1747
|
-
if (!candidate || candidate.role !== role || !hasFiniteTimestamp(candidate)) continue;
|
|
1748
|
-
usedReferenceIndexes.add(candidateIndex);
|
|
1749
|
-
exactReferenceCursorByKey.set(key, cursor);
|
|
1750
|
-
return candidate.timestamp;
|
|
1751
|
-
}
|
|
1752
|
-
exactReferenceCursorByKey.set(key, cursor);
|
|
1753
|
-
return void 0;
|
|
1754
|
-
};
|
|
1755
|
-
const findReferenceTimestamp = (message, role, content, parsedIndex) => {
|
|
1756
|
-
const sameIndex = referenceMessages[parsedIndex];
|
|
1757
|
-
if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && hasFiniteTimestamp(sameIndex) && messagesShareStableIdentity(message, sameIndex)) {
|
|
1758
|
-
usedReferenceIndexes.add(parsedIndex);
|
|
1759
|
-
return sameIndex.timestamp;
|
|
1760
|
-
}
|
|
1761
|
-
const normalizedContent = normalizeComparableMessageContent(content);
|
|
1762
|
-
if (!normalizedContent) return void 0;
|
|
1763
|
-
if (sameIndex && !usedReferenceIndexes.has(parsedIndex) && sameIndex.role === role && getReferenceComparable(parsedIndex) === normalizedContent && hasFiniteTimestamp(sameIndex)) {
|
|
1764
|
-
usedReferenceIndexes.add(parsedIndex);
|
|
1765
|
-
return sameIndex.timestamp;
|
|
1766
|
-
}
|
|
1767
|
-
const exactTimestamp = takeExactReferenceTimestamp(role, normalizedContent);
|
|
1768
|
-
if (typeof exactTimestamp === "number") return exactTimestamp;
|
|
1769
|
-
for (let i = 0; i < referenceMessages.length; i++) {
|
|
1770
|
-
if (usedReferenceIndexes.has(i)) continue;
|
|
1771
|
-
const candidate = referenceMessages[i];
|
|
1772
|
-
if (!candidate || candidate.role !== role) continue;
|
|
1773
|
-
const candidateContent = getReferenceComparable(i);
|
|
1774
|
-
if (!candidateContent) continue;
|
|
1775
|
-
const fuzzyMatch = candidateContent.includes(normalizedContent) || normalizedContent.includes(candidateContent);
|
|
1776
|
-
if (!fuzzyMatch) continue;
|
|
1777
|
-
if (hasFiniteTimestamp(candidate)) {
|
|
1778
|
-
usedReferenceIndexes.add(i);
|
|
1779
|
-
return candidate.timestamp;
|
|
1780
|
-
}
|
|
1781
|
-
}
|
|
1782
|
-
return void 0;
|
|
1783
|
-
};
|
|
1784
|
-
return parsedMessages.filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message, index) => {
|
|
1785
|
-
const role = message.role;
|
|
1786
|
-
const content = typeof message.content === "string" ? message.content : String(message.content || "");
|
|
1787
|
-
const parsedTimestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0;
|
|
1788
|
-
const referenceTimestamp = parsedTimestamp ?? findReferenceTimestamp(message, role, content, index);
|
|
1789
|
-
const fallbackTimestamp = role === "user" ? scope?.startedAt || now : lastOutputAt || scope?.startedAt || now;
|
|
1790
|
-
const timestamp = referenceTimestamp ?? fallbackTimestamp;
|
|
1791
|
-
return {
|
|
1792
|
-
...message,
|
|
1793
|
-
role,
|
|
1794
|
-
content,
|
|
1795
|
-
timestamp,
|
|
1796
|
-
receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp
|
|
1797
|
-
};
|
|
1798
|
-
});
|
|
1799
|
-
}
|
|
1800
|
-
function chooseMoreComparableCliMessage(left, right, leftComparable = normalizeComparableMessageContent(left.content || ""), rightComparable = normalizeComparableMessageContent(right.content || "")) {
|
|
1801
|
-
if (leftComparable && leftComparable === rightComparable) {
|
|
1802
|
-
const leftNewlines = String(left.content || "").split(/\r\n|\n|\r/g).length - 1;
|
|
1803
|
-
const rightNewlines = String(right.content || "").split(/\r\n|\n|\r/g).length - 1;
|
|
1804
|
-
return rightNewlines < leftNewlines ? right : left;
|
|
1805
|
-
}
|
|
1806
|
-
return rightComparable.length > leftComparable.length ? right : left;
|
|
1807
|
-
}
|
|
1808
|
-
function dedupeConsecutiveComparableCliMessages(messages) {
|
|
1809
|
-
const deduped = [];
|
|
1810
|
-
for (const message of messages) {
|
|
1811
|
-
const current = {
|
|
1812
|
-
...message,
|
|
1813
|
-
content: typeof message.content === "string" ? message.content : String(message.content || "")
|
|
1814
|
-
};
|
|
1815
|
-
const currentComparable = normalizeComparableMessageContent(current.content || "");
|
|
1816
|
-
const previous = deduped[deduped.length - 1];
|
|
1817
|
-
if (!previous) {
|
|
1818
|
-
deduped.push({ message: current, comparable: currentComparable });
|
|
1819
|
-
continue;
|
|
1820
|
-
}
|
|
1821
|
-
const sameRole = previous.message.role === current.role;
|
|
1822
|
-
const sameKind = (previous.message.kind || "standard") === (current.kind || "standard");
|
|
1823
|
-
const sameSender = (previous.message.senderName || "") === (current.senderName || "");
|
|
1824
|
-
const comparableMatch = previous.comparable && previous.comparable === currentComparable;
|
|
1825
|
-
if (sameRole && sameKind && sameSender && comparableMatch) {
|
|
1826
|
-
const selected = chooseMoreComparableCliMessage(
|
|
1827
|
-
previous.message,
|
|
1828
|
-
current,
|
|
1829
|
-
previous.comparable,
|
|
1830
|
-
currentComparable
|
|
1831
|
-
);
|
|
1832
|
-
deduped[deduped.length - 1] = {
|
|
1833
|
-
message: selected,
|
|
1834
|
-
comparable: selected === current ? currentComparable : previous.comparable
|
|
1835
|
-
};
|
|
1836
|
-
continue;
|
|
1837
|
-
}
|
|
1838
|
-
deduped.push({ message: current, comparable: currentComparable });
|
|
1839
|
-
}
|
|
1840
|
-
return deduped.map((entry) => entry.message);
|
|
1841
|
-
}
|
|
1842
|
-
function normalizeCliParsedMessages(parsedMessages, options) {
|
|
1843
|
-
return dedupeConsecutiveComparableCliMessages(hydrateCliParsedMessages(parsedMessages, options).map((message) => ({
|
|
1844
|
-
role: message.role,
|
|
1845
|
-
content: message.content,
|
|
1846
|
-
timestamp: message.timestamp,
|
|
1847
|
-
receivedAt: message.receivedAt,
|
|
1848
|
-
kind: message.kind,
|
|
1849
|
-
id: message.id,
|
|
1850
|
-
index: message.index,
|
|
1851
|
-
providerUnitKey: message.providerUnitKey,
|
|
1852
|
-
bubbleId: message.bubbleId,
|
|
1853
|
-
bubbleState: message.bubbleState,
|
|
1854
|
-
_turnKey: message._turnKey,
|
|
1855
|
-
meta: message.meta,
|
|
1856
|
-
senderName: message.senderName
|
|
1857
|
-
})));
|
|
1089
|
+
function normalizeCliParsedMessages(parsedMessages, _options) {
|
|
1090
|
+
return Array.isArray(parsedMessages) ? parsedMessages : [];
|
|
1858
1091
|
}
|
|
1859
1092
|
function buildCliParseInput(options) {
|
|
1860
1093
|
const {
|
|
@@ -2063,41 +1296,9 @@ var provider_cli_adapter_exports = {};
|
|
|
2063
1296
|
__export(provider_cli_adapter_exports, {
|
|
2064
1297
|
ProviderCliAdapter: () => ProviderCliAdapter,
|
|
2065
1298
|
appendBoundedText: () => appendBoundedText,
|
|
2066
|
-
normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
|
|
2067
|
-
sanitizeCliStandardMessageContent: () => sanitizeCliStandardMessageContent,
|
|
2068
|
-
trimLastAssistantEchoForCliMessages: () => trimLastAssistantEchoForCliMessages
|
|
1299
|
+
normalizeCliProviderForRuntime: () => normalizeCliProviderForRuntime
|
|
2069
1300
|
});
|
|
2070
1301
|
import * as os11 from "os";
|
|
2071
|
-
function normalizeComparableTranscriptText(value) {
|
|
2072
|
-
return sanitizeTerminalText(String(value || "")).replace(/\s+/g, " ").trim();
|
|
2073
|
-
}
|
|
2074
|
-
function hasVisibleInterruptPrompt(text) {
|
|
2075
|
-
const interruptCopyPattern = /\bEnter\s+to\s+interrupt\b(?:\s*,?\s*Ctrl\s*(?:\+|-)?\s*C\s+to\s+cancel)?/i;
|
|
2076
|
-
return sanitizeTerminalText(text || "").split(/\r?\n/g).some((line) => {
|
|
2077
|
-
const trimmed = line.trim();
|
|
2078
|
-
if (!interruptCopyPattern.test(trimmed)) return false;
|
|
2079
|
-
return /^(?:[^A-Za-z0-9\s]{1,8}\s+)?[❯›>]\s+/.test(trimmed);
|
|
2080
|
-
});
|
|
2081
|
-
}
|
|
2082
|
-
function parsedTranscriptIsRicherThanCommitted(parsedMessages, committedMessages) {
|
|
2083
|
-
if (!Array.isArray(parsedMessages) || !Array.isArray(committedMessages)) return false;
|
|
2084
|
-
if (parsedMessages.length > committedMessages.length) return true;
|
|
2085
|
-
if (parsedMessages.length !== committedMessages.length) return false;
|
|
2086
|
-
for (let index = 0; index < parsedMessages.length; index += 1) {
|
|
2087
|
-
const parsed = parsedMessages[index];
|
|
2088
|
-
const committed = committedMessages[index];
|
|
2089
|
-
if (!parsed || !committed) return false;
|
|
2090
|
-
if ((parsed.role || "") !== (committed.role || "")) return false;
|
|
2091
|
-
if (parsed.id && committed.id && String(parsed.id) !== String(committed.id)) return false;
|
|
2092
|
-
if (typeof parsed.index === "number" && typeof committed.index === "number" && parsed.index !== committed.index) return false;
|
|
2093
|
-
const parsedText = normalizeComparableTranscriptText(parsed.content);
|
|
2094
|
-
const committedText = normalizeComparableTranscriptText(committed.content);
|
|
2095
|
-
if (!parsedText || !committedText || parsedText === committedText) continue;
|
|
2096
|
-
if (parsedText.length > committedText.length && parsedText.startsWith(committedText)) return true;
|
|
2097
|
-
return false;
|
|
2098
|
-
}
|
|
2099
|
-
return false;
|
|
2100
|
-
}
|
|
2101
1302
|
function appendBoundedText(current, chunk, maxChars) {
|
|
2102
1303
|
if (!chunk) return current.length <= maxChars ? current : current.slice(-maxChars);
|
|
2103
1304
|
if (maxChars <= 0) return "";
|
|
@@ -2106,76 +1307,7 @@ function appendBoundedText(current, chunk, maxChars) {
|
|
|
2106
1307
|
if (current.length <= keepFromCurrent) return current + chunk;
|
|
2107
1308
|
return current.slice(-keepFromCurrent) + chunk;
|
|
2108
1309
|
}
|
|
2109
|
-
|
|
2110
|
-
const trimmed = String(line || "").trim();
|
|
2111
|
-
if (!trimmed) return false;
|
|
2112
|
-
if (COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(trimmed)) return false;
|
|
2113
|
-
if (/\s/.test(trimmed)) return false;
|
|
2114
|
-
if (/[가-힣]/.test(trimmed)) return false;
|
|
2115
|
-
if (trimmed.length > 96) return false;
|
|
2116
|
-
return /^[A-Za-z0-9_./:@+%=-]+$/.test(trimmed);
|
|
2117
|
-
}
|
|
2118
|
-
function parseCommittedActivityPrefixBlock(lines, index) {
|
|
2119
|
-
const first = String(lines[index] || "").trim();
|
|
2120
|
-
if (!COMMITTED_ACTIVITY_PREFIX_BLOCK_RE.test(first)) return null;
|
|
2121
|
-
const parts = [first];
|
|
2122
|
-
let nextIndex = index + 1;
|
|
2123
|
-
while (nextIndex < lines.length && isLikelyCommittedActivityPrefixContinuation(lines[nextIndex])) {
|
|
2124
|
-
parts.push(String(lines[nextIndex] || "").trim());
|
|
2125
|
-
nextIndex += 1;
|
|
2126
|
-
}
|
|
2127
|
-
return { label: parts.join(""), nextIndex };
|
|
2128
|
-
}
|
|
2129
|
-
function sanitizeCliStandardMessageContent(content) {
|
|
2130
|
-
const source = String(content || "").trim();
|
|
2131
|
-
if (!source) return "";
|
|
2132
|
-
const lines = source.split(/\r?\n/);
|
|
2133
|
-
if (lines.length < 4) return source;
|
|
2134
|
-
const counts = /* @__PURE__ */ new Map();
|
|
2135
|
-
for (let index = 0; index < lines.length; index += 1) {
|
|
2136
|
-
const block = parseCommittedActivityPrefixBlock(lines, index);
|
|
2137
|
-
if (!block) continue;
|
|
2138
|
-
counts.set(block.label, (counts.get(block.label) || 0) + 1);
|
|
2139
|
-
index = block.nextIndex - 1;
|
|
2140
|
-
}
|
|
2141
|
-
const repeatedLabels = new Set(
|
|
2142
|
-
Array.from(counts.entries()).filter(([, count]) => count >= 3).map(([label]) => label)
|
|
2143
|
-
);
|
|
2144
|
-
if (repeatedLabels.size === 0) return source;
|
|
2145
|
-
const stripped = [];
|
|
2146
|
-
let removed = 0;
|
|
2147
|
-
for (let index = 0; index < lines.length; index += 1) {
|
|
2148
|
-
const block = parseCommittedActivityPrefixBlock(lines, index);
|
|
2149
|
-
if (block && repeatedLabels.has(block.label)) {
|
|
2150
|
-
removed += 1;
|
|
2151
|
-
index = block.nextIndex - 1;
|
|
2152
|
-
continue;
|
|
2153
|
-
}
|
|
2154
|
-
stripped.push(lines[index]);
|
|
2155
|
-
}
|
|
2156
|
-
const next = stripped.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
2157
|
-
return removed >= 3 && next.length >= 80 ? next : source;
|
|
2158
|
-
}
|
|
2159
|
-
function sanitizeCommittedMessageForDisplay(message) {
|
|
2160
|
-
if (!message || message.role !== "assistant" || (message.kind || "standard") !== "standard") return message;
|
|
2161
|
-
const content = sanitizeCliStandardMessageContent(message.content);
|
|
2162
|
-
if (content === message.content) return message;
|
|
2163
|
-
return { ...message, content };
|
|
2164
|
-
}
|
|
2165
|
-
function trimLastAssistantEchoForCliMessages(messages, prompt) {
|
|
2166
|
-
if (!prompt) return;
|
|
2167
|
-
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
2168
|
-
const message = messages[index];
|
|
2169
|
-
if (!message || message.role !== "assistant" || typeof message.content !== "string") continue;
|
|
2170
|
-
if ((message.kind || "standard") !== "standard") continue;
|
|
2171
|
-
message.content = trimPromptEchoPrefix(message.content, prompt);
|
|
2172
|
-
if (!message.content.trim()) {
|
|
2173
|
-
messages.splice(index, 1);
|
|
2174
|
-
}
|
|
2175
|
-
return;
|
|
2176
|
-
}
|
|
2177
|
-
}
|
|
2178
|
-
var COMMITTED_ACTIVITY_PREFIX_BLOCK_RE, ProviderCliAdapter;
|
|
1310
|
+
var ProviderCliAdapter;
|
|
2179
1311
|
var init_provider_cli_adapter = __esm({
|
|
2180
1312
|
"src/cli-adapters/provider-cli-adapter.ts"() {
|
|
2181
1313
|
"use strict";
|
|
@@ -2184,13 +1316,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
2184
1316
|
init_terminal_screen();
|
|
2185
1317
|
init_pty_transport();
|
|
2186
1318
|
init_provider_cli_shared();
|
|
2187
|
-
init_chat_message_normalization();
|
|
2188
|
-
init_read_chat_contract();
|
|
2189
1319
|
init_provider_cli_parse();
|
|
2190
1320
|
init_provider_cli_config();
|
|
2191
1321
|
init_provider_cli_runtime();
|
|
2192
1322
|
init_provider_cli_shared();
|
|
2193
|
-
COMMITTED_ACTIVITY_PREFIX_BLOCK_RE = /^(?:📖|💻|🔎|📚|📋|✏️|📝|🔧|🛠️|⚙️)\s+(.+)$/;
|
|
2194
1323
|
ProviderCliAdapter = class _ProviderCliAdapter {
|
|
2195
1324
|
constructor(provider, workingDir, extraArgs = [], transportFactory = new NodePtyTransportFactory()) {
|
|
2196
1325
|
this.extraArgs = extraArgs;
|
|
@@ -2233,11 +1362,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
2233
1362
|
provider;
|
|
2234
1363
|
ptyProcess = null;
|
|
2235
1364
|
transportFactory;
|
|
2236
|
-
messages = [];
|
|
2237
|
-
committedMessages = [];
|
|
2238
|
-
structuredMessages = [];
|
|
2239
|
-
committedMessagesActivitySignature = "";
|
|
2240
|
-
committedMessagesChangedAt = 0;
|
|
2241
1365
|
currentStatus = "starting";
|
|
2242
1366
|
onStatusChange = null;
|
|
2243
1367
|
responseBuffer = "";
|
|
@@ -2317,11 +1441,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
2317
1441
|
traceSeq = 0;
|
|
2318
1442
|
traceSessionId = "";
|
|
2319
1443
|
parsedStatusCache = null;
|
|
2320
|
-
lastStatusHotPathParseAt = Number.NEGATIVE_INFINITY;
|
|
2321
|
-
static STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS = 1e3;
|
|
2322
1444
|
static SCREEN_SNAPSHOT_MIN_INTERVAL_MS = 250;
|
|
2323
1445
|
static MAX_TRACE_ENTRIES = 250;
|
|
2324
|
-
static PARSE_MESSAGE_TAIL_LIMIT = 100;
|
|
2325
1446
|
providerResolutionMeta;
|
|
2326
1447
|
static FINISH_RETRY_DELAY_MS = 300;
|
|
2327
1448
|
static MAX_FINISH_RETRIES = 2;
|
|
@@ -2342,35 +1463,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
2342
1463
|
recordBoundedAppendDrop(previousLength, appendedLength, nextLength) {
|
|
2343
1464
|
return Math.max(0, previousLength + appendedLength - nextLength);
|
|
2344
1465
|
}
|
|
2345
|
-
buildCommittedMessagesActivitySignature() {
|
|
2346
|
-
const last = this.committedMessages[this.committedMessages.length - 1];
|
|
2347
|
-
return [
|
|
2348
|
-
String(this.committedMessages.length),
|
|
2349
|
-
String(last?.role || ""),
|
|
2350
|
-
String(last?.kind || ""),
|
|
2351
|
-
String(last?.senderName || ""),
|
|
2352
|
-
String(last?.timestamp || ""),
|
|
2353
|
-
String(last?.receivedAt || ""),
|
|
2354
|
-
normalizeComparableMessageContent(last?.content || "").slice(-240)
|
|
2355
|
-
].join("|");
|
|
2356
|
-
}
|
|
2357
|
-
syncMessageViews() {
|
|
2358
|
-
const signature = this.buildCommittedMessagesActivitySignature();
|
|
2359
|
-
if (signature !== this.committedMessagesActivitySignature) {
|
|
2360
|
-
this.committedMessagesActivitySignature = signature;
|
|
2361
|
-
this.committedMessagesChangedAt = Date.now();
|
|
2362
|
-
}
|
|
2363
|
-
this.messages = [...this.committedMessages];
|
|
2364
|
-
this.structuredMessages = [...this.committedMessages];
|
|
2365
|
-
}
|
|
2366
|
-
getLastCommittedMessageActivityAt() {
|
|
2367
|
-
const last = this.committedMessages[this.committedMessages.length - 1];
|
|
2368
|
-
const messageTime = Math.max(
|
|
2369
|
-
typeof last?.receivedAt === "number" && Number.isFinite(last.receivedAt) ? last.receivedAt : 0,
|
|
2370
|
-
typeof last?.timestamp === "number" && Number.isFinite(last.timestamp) ? last.timestamp : 0
|
|
2371
|
-
);
|
|
2372
|
-
return Math.max(messageTime, this.committedMessagesChangedAt || 0);
|
|
2373
|
-
}
|
|
2374
1466
|
readTerminalScreenText(now = Date.now()) {
|
|
2375
1467
|
const screenText = this.terminalScreen.getText() || "";
|
|
2376
1468
|
this.lastScreenText = screenText;
|
|
@@ -2390,7 +1482,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
2390
1482
|
}
|
|
2391
1483
|
getFreshParsedStatusCache() {
|
|
2392
1484
|
const cached = this.parsedStatusCache;
|
|
2393
|
-
if (cached && cached.
|
|
1485
|
+
if (cached && cached.responseBuffer === this.responseBuffer && cached.currentTurnScope === this.currentTurnScope && cached.recentOutputBuffer === this.recentOutputBuffer && cached.accumulatedBuffer === this.accumulatedBuffer && cached.screenText === this.lastScreenText && cached.currentStatus === this.currentStatus && cached.activeModal === this.activeModal && cached.cliName === this.cliName) {
|
|
2394
1486
|
return cached.result;
|
|
2395
1487
|
}
|
|
2396
1488
|
return null;
|
|
@@ -2401,45 +1493,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
2401
1493
|
shouldUseFullProviderTranscriptContext() {
|
|
2402
1494
|
return this.providerOwnsTranscript() && this.provider.transcriptContext === "full";
|
|
2403
1495
|
}
|
|
2404
|
-
selectParseBaseMessages(baseMessages) {
|
|
2405
|
-
if (this.shouldUseFullProviderTranscriptContext()) return baseMessages;
|
|
2406
|
-
if (baseMessages.length <= _ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT) return baseMessages;
|
|
2407
|
-
return baseMessages.slice(-_ProviderCliAdapter.PARSE_MESSAGE_TAIL_LIMIT);
|
|
2408
|
-
}
|
|
2409
|
-
messagesShareStableIdentity(left, right) {
|
|
2410
|
-
if (left === right) return true;
|
|
2411
|
-
if (!left || !right) return false;
|
|
2412
|
-
if ((left.role || "") !== (right.role || "")) return false;
|
|
2413
|
-
if (left.id && right.id && String(left.id) === String(right.id)) return true;
|
|
2414
|
-
if (typeof left.index === "number" && typeof right.index === "number" && left.index === right.index) return true;
|
|
2415
|
-
return false;
|
|
2416
|
-
}
|
|
2417
|
-
messagesComparable(left, right) {
|
|
2418
|
-
if (this.messagesShareStableIdentity(left, right)) return true;
|
|
2419
|
-
if (!left || !right) return false;
|
|
2420
|
-
if ((left.role || "") !== (right.role || "")) return false;
|
|
2421
|
-
const leftText = normalizeComparableTranscriptText(left.content);
|
|
2422
|
-
const rightText = normalizeComparableTranscriptText(right.content);
|
|
2423
|
-
return !!leftText && leftText === rightText;
|
|
2424
|
-
}
|
|
2425
|
-
stitchParsedMessagesWithCommittedBase(parsedMessages, fullBaseMessages, parseBaseMessages) {
|
|
2426
|
-
if (!Array.isArray(parsedMessages) || parsedMessages.length === 0) return parsedMessages;
|
|
2427
|
-
if (fullBaseMessages.length <= parseBaseMessages.length) return parsedMessages;
|
|
2428
|
-
const parsedFirst = parsedMessages[0];
|
|
2429
|
-
const fullFirst = fullBaseMessages[0];
|
|
2430
|
-
if (parsedMessages.length >= fullBaseMessages.length && this.messagesComparable(parsedFirst, fullFirst)) {
|
|
2431
|
-
return parsedMessages;
|
|
2432
|
-
}
|
|
2433
|
-
const tailFirst = parseBaseMessages[0];
|
|
2434
|
-
if (tailFirst && this.messagesComparable(parsedFirst, tailFirst)) {
|
|
2435
|
-
const prefixLength = fullBaseMessages.length - parseBaseMessages.length;
|
|
2436
|
-
const prefix = fullBaseMessages.slice(0, prefixLength);
|
|
2437
|
-
const shouldSanitizePrefix = !!this.currentTurnScope || this.currentStatus !== "idle" || !!this.activeModal;
|
|
2438
|
-
const nextPrefix = shouldSanitizePrefix ? prefix.map((message) => sanitizeCommittedMessageForDisplay(message)) : prefix;
|
|
2439
|
-
return [...nextPrefix, ...parsedMessages];
|
|
2440
|
-
}
|
|
2441
|
-
return [...fullBaseMessages, ...parsedMessages];
|
|
2442
|
-
}
|
|
2443
1496
|
getIdleFinishConfirmMs() {
|
|
2444
1497
|
return this.timeouts.idleFinishConfirm;
|
|
2445
1498
|
}
|
|
@@ -2892,9 +1945,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
2892
1945
|
`[${this.cliType}] Interactive prompt wait timed out after ${maxWaitMs}ms; proceeding with screen=${JSON.stringify(summarizeCliTraceText(finalScreenText, 240)).slice(0, 280)}`
|
|
2893
1946
|
);
|
|
2894
1947
|
}
|
|
2895
|
-
trimLastAssistantEcho(messages, prompt) {
|
|
2896
|
-
trimLastAssistantEchoForCliMessages(messages, prompt);
|
|
2897
|
-
}
|
|
2898
1948
|
clearAllTimers() {
|
|
2899
1949
|
if (this.responseTimeout) {
|
|
2900
1950
|
clearTimeout(this.responseTimeout);
|
|
@@ -2990,10 +2040,10 @@ var init_provider_cli_adapter = __esm({
|
|
|
2990
2040
|
}
|
|
2991
2041
|
const session = this.runParseSession();
|
|
2992
2042
|
if (!session) return;
|
|
2993
|
-
const { status, messages,
|
|
2043
|
+
const { status, messages, parsedStatus } = session;
|
|
2044
|
+
const modal = session.activeModal ?? session.modal ?? null;
|
|
2994
2045
|
const parsedMessages = normalizeCliParsedMessages(messages, {
|
|
2995
|
-
|
|
2996
|
-
scope: this.currentTurnScope,
|
|
2046
|
+
scope: null,
|
|
2997
2047
|
lastOutputAt: this.lastOutputAt
|
|
2998
2048
|
});
|
|
2999
2049
|
if (this.maybeCommitVisibleIdleTranscript(session, parsedMessages)) return;
|
|
@@ -3173,7 +2223,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
3173
2223
|
const effectiveScreenText = screenText || this.accumulatedBuffer;
|
|
3174
2224
|
const noActiveTurn = !this.currentTurnScope;
|
|
3175
2225
|
const looksIdleChrome = /(^|\n)\s*[❯›>]\s*(?:\n|$)/m.test(effectiveScreenText);
|
|
3176
|
-
const parsedShowsLiveAssistantProgress = parsedStatus === "generating" && !!lastParsedAssistant
|
|
2226
|
+
const parsedShowsLiveAssistantProgress = parsedStatus === "generating" && !!lastParsedAssistant;
|
|
3177
2227
|
if (prevStatus === "idle" && !this.isWaitingForResponse && noActiveTurn && !modal && looksIdleChrome && !parsedShowsLiveAssistantProgress) {
|
|
3178
2228
|
return;
|
|
3179
2229
|
}
|
|
@@ -3330,10 +2380,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
3330
2380
|
}
|
|
3331
2381
|
const visibleAssistant = [...parsedMessages].reverse().find((m) => m.role === "assistant" && m.content.trim());
|
|
3332
2382
|
if (!visibleAssistant) return false;
|
|
3333
|
-
this.committedMessages = parsedMessages;
|
|
3334
|
-
this.trimLastAssistantEcho(this.committedMessages, this.currentTurnScope?.prompt || getLastUserPromptText(this.committedMessages));
|
|
3335
2383
|
this.clearAllTimers();
|
|
3336
|
-
this.syncMessageViews();
|
|
3337
2384
|
this.responseBuffer = "";
|
|
3338
2385
|
this.isWaitingForResponse = false;
|
|
3339
2386
|
this.responseSettleIgnoreUntil = 0;
|
|
@@ -3345,37 +2392,34 @@ var init_provider_cli_adapter = __esm({
|
|
|
3345
2392
|
this.setStatus("idle", "script_idle_commit");
|
|
3346
2393
|
this.onStatusChange?.();
|
|
3347
2394
|
this.recordTrace("script_idle_commit", {
|
|
3348
|
-
messageCount:
|
|
2395
|
+
messageCount: parsedMessages.length,
|
|
3349
2396
|
lastAssistant: summarizeCliTraceText(visibleAssistant.content, 320)
|
|
3350
2397
|
});
|
|
3351
2398
|
return true;
|
|
3352
2399
|
}
|
|
3353
2400
|
commitCurrentTranscript() {
|
|
3354
2401
|
const parsed = this.parseCurrentTranscript(
|
|
3355
|
-
|
|
2402
|
+
[],
|
|
3356
2403
|
this.responseBuffer,
|
|
3357
2404
|
this.currentTurnScope
|
|
3358
2405
|
);
|
|
3359
2406
|
if (parsed && Array.isArray(parsed.messages)) {
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
scope: this.currentTurnScope,
|
|
2407
|
+
const parsedMessages = normalizeCliParsedMessages(parsed.messages, {
|
|
2408
|
+
scope: null,
|
|
3363
2409
|
lastOutputAt: this.lastOutputAt
|
|
3364
2410
|
});
|
|
3365
|
-
|
|
3366
|
-
this.syncMessageViews();
|
|
3367
|
-
const lastAssistant = [...this.committedMessages].reverse().find((message) => message.role === "assistant");
|
|
2411
|
+
const lastAssistant = [...parsedMessages].reverse().find((message) => message.role === "assistant");
|
|
3368
2412
|
if (this.currentTurnScope) {
|
|
3369
2413
|
LOG.info(
|
|
3370
2414
|
"CLI",
|
|
3371
|
-
`[${this.cliType}] commitCurrentTranscript
|
|
2415
|
+
`[${this.cliType}] commitCurrentTranscript parserMessages=${parsedMessages.length} finalLastAssistant=${JSON.stringify(summarizeCliTraceText(lastAssistant?.content || "", 220)).slice(0, 260)}`
|
|
3372
2416
|
);
|
|
3373
2417
|
}
|
|
3374
2418
|
this.recordTrace("commit_transcript", {
|
|
3375
2419
|
parsedStatus: parsed.status || null,
|
|
3376
|
-
messageCount:
|
|
2420
|
+
messageCount: parsedMessages.length,
|
|
3377
2421
|
lastAssistant: lastAssistant ? summarizeCliTraceText(lastAssistant.content, 320) : "",
|
|
3378
|
-
messages: summarizeCliTraceMessages(
|
|
2422
|
+
messages: summarizeCliTraceMessages(parsedMessages),
|
|
3379
2423
|
...buildCliTraceParseSnapshot({
|
|
3380
2424
|
accumulatedBuffer: this.accumulatedBuffer,
|
|
3381
2425
|
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
@@ -3409,63 +2453,31 @@ var init_provider_cli_adapter = __esm({
|
|
|
3409
2453
|
}
|
|
3410
2454
|
// ─── Script Execution ──────────────────────────
|
|
3411
2455
|
runParseSession() {
|
|
3412
|
-
if (typeof this.cliScripts?.parseSession
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
const tail = this.recentOutputBuffer.slice(-500);
|
|
3416
|
-
const parseBaseMessages = this.selectParseBaseMessages(this.committedMessages);
|
|
3417
|
-
const input = buildCliParseInput({
|
|
3418
|
-
accumulatedBuffer: this.accumulatedBuffer,
|
|
3419
|
-
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
3420
|
-
recentOutputBuffer: this.recentOutputBuffer,
|
|
3421
|
-
terminalScreenText: screenText,
|
|
3422
|
-
baseMessages: parseBaseMessages,
|
|
3423
|
-
partialResponse: this.responseBuffer,
|
|
3424
|
-
isWaitingForResponse: this.isWaitingForResponse,
|
|
3425
|
-
scope: this.currentTurnScope,
|
|
3426
|
-
runtimeSettings: this.runtimeSettings
|
|
3427
|
-
});
|
|
3428
|
-
const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
|
|
3429
|
-
if (session && typeof session === "object" && Array.isArray(session.messages)) {
|
|
3430
|
-
session.messages = this.stitchParsedMessagesWithCommittedBase(
|
|
3431
|
-
session.messages,
|
|
3432
|
-
this.committedMessages,
|
|
3433
|
-
parseBaseMessages
|
|
3434
|
-
);
|
|
3435
|
-
}
|
|
3436
|
-
this.parseErrorMessage = null;
|
|
3437
|
-
return session && typeof session === "object" ? session : null;
|
|
3438
|
-
} catch (e) {
|
|
3439
|
-
const message = e?.message || String(e);
|
|
3440
|
-
this.parseErrorMessage = message;
|
|
3441
|
-
LOG.warn("CLI", `[${this.cliType}] parseSession error: ${message}`);
|
|
3442
|
-
return null;
|
|
3443
|
-
}
|
|
2456
|
+
if (typeof this.cliScripts?.parseSession !== "function") {
|
|
2457
|
+
this.parseErrorMessage = `${this.cliType} parseSession unavailable`;
|
|
2458
|
+
return null;
|
|
3444
2459
|
}
|
|
3445
|
-
if (!this.cliScripts?.detectStatus && !this.cliScripts?.parseOutput) return null;
|
|
3446
2460
|
try {
|
|
3447
|
-
const
|
|
3448
|
-
const
|
|
3449
|
-
|
|
3450
|
-
this.
|
|
3451
|
-
this.
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
parsedStatus
|
|
3464
|
-
};
|
|
2461
|
+
const screenText = this.terminalScreen.getText();
|
|
2462
|
+
const tail = this.recentOutputBuffer.slice(-500);
|
|
2463
|
+
const input = buildCliParseInput({
|
|
2464
|
+
accumulatedBuffer: this.accumulatedBuffer,
|
|
2465
|
+
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
2466
|
+
recentOutputBuffer: this.recentOutputBuffer,
|
|
2467
|
+
terminalScreenText: screenText,
|
|
2468
|
+
baseMessages: [],
|
|
2469
|
+
partialResponse: this.responseBuffer,
|
|
2470
|
+
isWaitingForResponse: this.isWaitingForResponse,
|
|
2471
|
+
scope: this.currentTurnScope,
|
|
2472
|
+
runtimeSettings: this.runtimeSettings
|
|
2473
|
+
});
|
|
2474
|
+
const session = this.cliScripts.parseSession({ ...input, tail, tailScreen: buildCliScreenSnapshot(tail) });
|
|
2475
|
+
this.parseErrorMessage = null;
|
|
2476
|
+
return session && typeof session === "object" ? session : null;
|
|
3465
2477
|
} catch (e) {
|
|
3466
2478
|
const message = e?.message || String(e);
|
|
3467
2479
|
this.parseErrorMessage = message;
|
|
3468
|
-
LOG.warn("CLI", `[${this.cliType}] parseSession
|
|
2480
|
+
LOG.warn("CLI", `[${this.cliType}] parseSession error: ${message}`);
|
|
3469
2481
|
return null;
|
|
3470
2482
|
}
|
|
3471
2483
|
}
|
|
@@ -3515,45 +2527,14 @@ var init_provider_cli_adapter = __esm({
|
|
|
3515
2527
|
if (this.isWaitingForResponse && this.currentTurnScope && this.currentStatus !== "stopped") return "generating";
|
|
3516
2528
|
return this.currentStatus;
|
|
3517
2529
|
}
|
|
3518
|
-
suppressStaleParsedApproval(parsed, recentBuffer, screenText) {
|
|
3519
|
-
const actionableParsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
|
|
3520
|
-
if (!parsed || parsed?.status !== "waiting_approval" || !actionableParsedModal) {
|
|
3521
|
-
return parsed;
|
|
3522
|
-
}
|
|
3523
|
-
const inApprovalCooldown = this.lastApprovalResolvedAt > 0 && Date.now() - this.lastApprovalResolvedAt < this.timeouts.approvalCooldown;
|
|
3524
|
-
if (!inApprovalCooldown) {
|
|
3525
|
-
return parsed;
|
|
3526
|
-
}
|
|
3527
|
-
const visibleModal = this.runParseApproval(recentBuffer);
|
|
3528
|
-
if (visibleModal) {
|
|
3529
|
-
return parsed;
|
|
3530
|
-
}
|
|
3531
|
-
const detectedStatus = this.runDetectStatus(recentBuffer);
|
|
3532
|
-
const resolvedStatus = detectedStatus && detectedStatus !== "waiting_approval" ? detectedStatus : this.isWaitingForResponse || this.currentTurnScope ? "generating" : this.currentStatus === "waiting_approval" ? "idle" : this.currentStatus;
|
|
3533
|
-
return {
|
|
3534
|
-
...parsed,
|
|
3535
|
-
status: resolvedStatus,
|
|
3536
|
-
activeModal: null
|
|
3537
|
-
};
|
|
3538
|
-
}
|
|
3539
2530
|
// ─── Public API (CliAdapter) ───────────────────
|
|
3540
2531
|
getStatus(options = {}) {
|
|
3541
2532
|
const allowParse = options.allowParse !== false;
|
|
3542
2533
|
const startupModal = allowParse && this.startupParseGate ? this.runParseApproval(this.recentOutputBuffer) : null;
|
|
3543
2534
|
let effectiveStatus = this.projectEffectiveStatus(startupModal);
|
|
3544
2535
|
let effectiveModal = startupModal || this.activeModal;
|
|
3545
|
-
if (allowParse && !startupModal && !effectiveModal
|
|
3546
|
-
|
|
3547
|
-
if (!parsed && effectiveStatus !== "idle") {
|
|
3548
|
-
const now = Date.now();
|
|
3549
|
-
if (now - this.lastStatusHotPathParseAt >= _ProviderCliAdapter.STATUS_HOT_PATH_PARSE_MIN_INTERVAL_MS) {
|
|
3550
|
-
this.lastStatusHotPathParseAt = now;
|
|
3551
|
-
try {
|
|
3552
|
-
parsed = this.getScriptParsedStatus();
|
|
3553
|
-
} catch {
|
|
3554
|
-
}
|
|
3555
|
-
}
|
|
3556
|
-
}
|
|
2536
|
+
if (allowParse && !startupModal && !effectiveModal) {
|
|
2537
|
+
const parsed = this.getFreshParsedStatusCache();
|
|
3557
2538
|
const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
|
|
3558
2539
|
if (parsed?.status === "waiting_approval" && parsedModal) {
|
|
3559
2540
|
effectiveStatus = "waiting_approval";
|
|
@@ -3563,7 +2544,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
3563
2544
|
const bufferState = this.getBufferState();
|
|
3564
2545
|
return {
|
|
3565
2546
|
status: effectiveStatus,
|
|
3566
|
-
messages: [
|
|
2547
|
+
messages: [],
|
|
3567
2548
|
workingDir: this.workingDir,
|
|
3568
2549
|
activeModal: effectiveModal,
|
|
3569
2550
|
errorMessage: this.parseErrorMessage || void 0,
|
|
@@ -3571,98 +2552,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
3571
2552
|
...bufferState ? { bufferState } : {}
|
|
3572
2553
|
};
|
|
3573
2554
|
}
|
|
3574
|
-
seedCommittedMessages(messages) {
|
|
3575
|
-
const normalized = (Array.isArray(messages) ? messages : []).filter((message) => message && (message.role === "user" || message.role === "assistant")).map((message) => ({
|
|
3576
|
-
role: message.role,
|
|
3577
|
-
content: typeof message.content === "string" ? message.content : String(message.content || ""),
|
|
3578
|
-
timestamp: typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : void 0,
|
|
3579
|
-
receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : void 0,
|
|
3580
|
-
kind: typeof message.kind === "string" ? message.kind : void 0,
|
|
3581
|
-
id: typeof message.id === "string" ? message.id : void 0,
|
|
3582
|
-
index: typeof message.index === "number" ? message.index : void 0,
|
|
3583
|
-
providerUnitKey: typeof message.providerUnitKey === "string" ? message.providerUnitKey : void 0,
|
|
3584
|
-
bubbleId: typeof message.bubbleId === "string" ? message.bubbleId : void 0,
|
|
3585
|
-
bubbleState: typeof message.bubbleState === "string" ? message.bubbleState : void 0,
|
|
3586
|
-
_turnKey: typeof message._turnKey === "string" ? message._turnKey : void 0,
|
|
3587
|
-
meta: message.meta && typeof message.meta === "object" ? { ...message.meta } : void 0,
|
|
3588
|
-
senderName: typeof message.senderName === "string" ? message.senderName : void 0
|
|
3589
|
-
}));
|
|
3590
|
-
this.committedMessages = normalized;
|
|
3591
|
-
this.syncMessageViews();
|
|
3592
|
-
}
|
|
3593
|
-
getSharedCommittedPrefixLength(parsedMessages) {
|
|
3594
|
-
const committedMessages = this.committedMessages;
|
|
3595
|
-
const max = Math.min(parsedMessages.length, committedMessages.length);
|
|
3596
|
-
let index = 0;
|
|
3597
|
-
while (index < max && this.messagesShareStableIdentity(parsedMessages[index], committedMessages[index])) {
|
|
3598
|
-
index += 1;
|
|
3599
|
-
}
|
|
3600
|
-
return index;
|
|
3601
|
-
}
|
|
3602
|
-
hydrateCommittedPrefixForParsedStatus(parsedMessages) {
|
|
3603
|
-
const sharedPrefixLength = this.getSharedCommittedPrefixLength(parsedMessages);
|
|
3604
|
-
if (sharedPrefixLength !== this.committedMessages.length) return null;
|
|
3605
|
-
const committedHydratedMessages = this.committedMessages.map((message, index) => {
|
|
3606
|
-
const timestamp = typeof message.timestamp === "number" && Number.isFinite(message.timestamp) ? message.timestamp : this.lastOutputAt || this.currentTurnScope?.startedAt || Date.now();
|
|
3607
|
-
const contentValue = message.content;
|
|
3608
|
-
return {
|
|
3609
|
-
role: message.role,
|
|
3610
|
-
content: typeof contentValue === "string" ? contentValue : String(contentValue || ""),
|
|
3611
|
-
timestamp,
|
|
3612
|
-
receivedAt: typeof message.receivedAt === "number" && Number.isFinite(message.receivedAt) ? message.receivedAt : timestamp,
|
|
3613
|
-
kind: message.kind,
|
|
3614
|
-
id: message.id || `msg_${index}`,
|
|
3615
|
-
index: typeof message.index === "number" ? message.index : index,
|
|
3616
|
-
providerUnitKey: message.providerUnitKey,
|
|
3617
|
-
bubbleId: message.bubbleId,
|
|
3618
|
-
bubbleState: message.bubbleState,
|
|
3619
|
-
_turnKey: message._turnKey,
|
|
3620
|
-
meta: message.meta,
|
|
3621
|
-
senderName: message.senderName
|
|
3622
|
-
};
|
|
3623
|
-
});
|
|
3624
|
-
const extraMessages = parsedMessages.slice(sharedPrefixLength);
|
|
3625
|
-
if (extraMessages.length === 0) return committedHydratedMessages;
|
|
3626
|
-
const extraHydratedMessages = hydrateCliParsedMessages(extraMessages, {
|
|
3627
|
-
committedMessages: [],
|
|
3628
|
-
scope: this.currentTurnScope,
|
|
3629
|
-
lastOutputAt: this.lastOutputAt
|
|
3630
|
-
}).map((message, offset) => ({
|
|
3631
|
-
...message,
|
|
3632
|
-
id: message.id || `msg_${sharedPrefixLength + offset}`,
|
|
3633
|
-
index: typeof message.index === "number" ? message.index : sharedPrefixLength + offset
|
|
3634
|
-
}));
|
|
3635
|
-
return [...committedHydratedMessages, ...extraHydratedMessages];
|
|
3636
|
-
}
|
|
3637
|
-
hydrateParsedMessagesForStatus(parsedMessages) {
|
|
3638
|
-
return this.hydrateCommittedPrefixForParsedStatus(parsedMessages) || hydrateCliParsedMessages(parsedMessages, {
|
|
3639
|
-
committedMessages: this.committedMessages,
|
|
3640
|
-
scope: this.currentTurnScope,
|
|
3641
|
-
lastOutputAt: this.lastOutputAt
|
|
3642
|
-
});
|
|
3643
|
-
}
|
|
3644
|
-
buildCommittedChatMessages() {
|
|
3645
|
-
return this.committedMessages.map((message, index) => {
|
|
3646
|
-
const rawContentValue = message.content;
|
|
3647
|
-
const rawContent = typeof rawContentValue === "string" ? rawContentValue : String(rawContentValue || "");
|
|
3648
|
-
const content = message.role === "assistant" && (message.kind || "standard") === "standard" ? sanitizeCliStandardMessageContent(rawContent) : rawContent;
|
|
3649
|
-
return buildChatMessage({
|
|
3650
|
-
role: message.role,
|
|
3651
|
-
content,
|
|
3652
|
-
timestamp: message.timestamp,
|
|
3653
|
-
kind: message.kind,
|
|
3654
|
-
meta: message.meta,
|
|
3655
|
-
senderName: message.senderName,
|
|
3656
|
-
id: message.id || `msg_${index}`,
|
|
3657
|
-
index: typeof message.index === "number" ? message.index : index,
|
|
3658
|
-
providerUnitKey: message.providerUnitKey,
|
|
3659
|
-
bubbleId: message.bubbleId,
|
|
3660
|
-
bubbleState: message.bubbleState,
|
|
3661
|
-
_turnKey: message._turnKey,
|
|
3662
|
-
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
3663
|
-
});
|
|
3664
|
-
});
|
|
3665
|
-
}
|
|
3666
2555
|
/**
|
|
3667
2556
|
* Script-based full parse — returns ReadChatResult.
|
|
3668
2557
|
* Called by command handler / dashboard for rich content rendering.
|
|
@@ -3670,125 +2559,30 @@ var init_provider_cli_adapter = __esm({
|
|
|
3670
2559
|
getScriptParsedStatus() {
|
|
3671
2560
|
const screenText = this.readTerminalScreenText();
|
|
3672
2561
|
const cached = this.parsedStatusCache;
|
|
3673
|
-
if (cached && cached.
|
|
2562
|
+
if (cached && cached.responseBuffer === this.responseBuffer && cached.currentTurnScope === this.currentTurnScope && cached.recentOutputBuffer === this.recentOutputBuffer && cached.accumulatedBuffer === this.accumulatedBuffer && cached.screenText === screenText && cached.currentStatus === this.currentStatus && cached.activeModal === this.activeModal && cached.cliName === this.cliName) {
|
|
3674
2563
|
return cached.result;
|
|
3675
2564
|
}
|
|
3676
|
-
const parsed = this.
|
|
3677
|
-
|
|
3678
|
-
this.
|
|
3679
|
-
this.currentTurnScope,
|
|
3680
|
-
screenText
|
|
3681
|
-
);
|
|
3682
|
-
const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
|
|
3683
|
-
if (parsedModal && parsed?.status === "waiting_approval") {
|
|
3684
|
-
this.activeModal = parsedModal;
|
|
3685
|
-
this.isWaitingForResponse = true;
|
|
3686
|
-
if (this.currentStatus !== "waiting_approval") {
|
|
3687
|
-
this.setStatus("waiting_approval", "parsed_waiting_approval");
|
|
3688
|
-
this.onStatusChange?.();
|
|
3689
|
-
}
|
|
2565
|
+
const parsed = this.runParseSession();
|
|
2566
|
+
if (!parsed || !Array.isArray(parsed.messages)) {
|
|
2567
|
+
throw new Error(this.parseErrorMessage || `${this.cliType} parseSession did not return messages`);
|
|
3690
2568
|
}
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
2569
|
+
const activeModal = parsed.activeModal ?? parsed.modal ?? null;
|
|
2570
|
+
const bufferState = this.getBufferState();
|
|
2571
|
+
const result = {
|
|
2572
|
+
id: parsed.id || "cli_session",
|
|
2573
|
+
status: parsed.status || this.currentStatus,
|
|
2574
|
+
title: parsed.title || this.cliName,
|
|
2575
|
+
messages: normalizeCliParsedMessages(parsed.messages, {
|
|
2576
|
+
scope: null,
|
|
3695
2577
|
lastOutputAt: this.lastOutputAt
|
|
3696
|
-
})
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
if (this.maybeCommitVisibleIdleTranscript(fakeSession, hydratedForCommit)) {
|
|
3704
|
-
return this.getScriptParsedStatus();
|
|
3705
|
-
}
|
|
3706
|
-
}
|
|
3707
|
-
const shouldPreferCommittedMessages = !this.currentTurnScope && !this.activeModal && this.currentStatus === "idle";
|
|
3708
|
-
let result;
|
|
3709
|
-
if (parsed && Array.isArray(parsed.messages)) {
|
|
3710
|
-
const parsedHydratedMessages = this.hydrateParsedMessagesForStatus(parsed.messages);
|
|
3711
|
-
const parsedLastAssistant = [...parsedHydratedMessages].reverse().find((message) => message.role === "assistant" && typeof message.content === "string" && message.content.trim());
|
|
3712
|
-
const shouldAdoptParsedIdleReplay = !this.currentTurnScope && !this.activeModal && !!parsedLastAssistant && parsedTranscriptIsRicherThanCommitted(parsedHydratedMessages, this.committedMessages) && (this.currentStatus === "idle" || this.currentStatus === "generating" && this.isWaitingForResponse && parsed.status === "idle" && this.runDetectStatus(this.recentOutputBuffer) === "idle");
|
|
3713
|
-
if (shouldAdoptParsedIdleReplay) {
|
|
3714
|
-
this.committedMessages = this.getSharedCommittedPrefixLength(parsed.messages) === this.committedMessages.length ? parsedHydratedMessages.map((message) => ({
|
|
3715
|
-
role: message.role,
|
|
3716
|
-
content: typeof message.content === "string" ? message.content : String(message.content || ""),
|
|
3717
|
-
timestamp: message.timestamp,
|
|
3718
|
-
receivedAt: message.receivedAt,
|
|
3719
|
-
kind: message.kind,
|
|
3720
|
-
id: message.id,
|
|
3721
|
-
index: message.index,
|
|
3722
|
-
meta: message.meta,
|
|
3723
|
-
senderName: message.senderName
|
|
3724
|
-
})) : normalizeCliParsedMessages(parsed.messages, {
|
|
3725
|
-
committedMessages: this.committedMessages,
|
|
3726
|
-
scope: this.currentTurnScope,
|
|
3727
|
-
lastOutputAt: this.lastOutputAt
|
|
3728
|
-
});
|
|
3729
|
-
this.syncMessageViews();
|
|
3730
|
-
if (this.currentStatus !== "idle" || this.isWaitingForResponse) {
|
|
3731
|
-
this.responseBuffer = "";
|
|
3732
|
-
this.isWaitingForResponse = false;
|
|
3733
|
-
this.responseSettleIgnoreUntil = 0;
|
|
3734
|
-
this.submitRetryUsed = false;
|
|
3735
|
-
this.submitRetryPromptSnippet = "";
|
|
3736
|
-
this.finishRetryCount = 0;
|
|
3737
|
-
this.currentTurnScope = null;
|
|
3738
|
-
this.activeModal = null;
|
|
3739
|
-
this.setStatus("idle", "parsed_idle_replay_commit");
|
|
3740
|
-
this.onStatusChange?.();
|
|
3741
|
-
}
|
|
3742
|
-
}
|
|
3743
|
-
const shouldPreferCommittedHistoryReplay = !this.currentTurnScope && !this.activeModal && this.committedMessages.length > parsedHydratedMessages.length;
|
|
3744
|
-
const shouldPreferCommittedIdleReplay = shouldPreferCommittedMessages && !shouldAdoptParsedIdleReplay;
|
|
3745
|
-
const hydratedMessages = shouldPreferCommittedIdleReplay || shouldPreferCommittedHistoryReplay ? this.buildCommittedChatMessages() : parsedHydratedMessages;
|
|
3746
|
-
result = {
|
|
3747
|
-
id: parsed.id || "cli_session",
|
|
3748
|
-
status: parsed.status || this.currentStatus,
|
|
3749
|
-
title: parsed.title || this.cliName,
|
|
3750
|
-
messages: hydratedMessages,
|
|
3751
|
-
activeModal: parsed.activeModal ?? this.activeModal,
|
|
3752
|
-
providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
|
|
3753
|
-
...this.getBufferState() ? { bufferState: this.getBufferState() } : {},
|
|
3754
|
-
...this.providerOwnsTranscript() ? { transcriptAuthority: "provider", coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
|
|
3755
|
-
};
|
|
3756
|
-
} else {
|
|
3757
|
-
const messages = [...this.committedMessages];
|
|
3758
|
-
const bufferState = this.getBufferState();
|
|
3759
|
-
result = {
|
|
3760
|
-
id: "cli_session",
|
|
3761
|
-
status: this.currentStatus,
|
|
3762
|
-
title: this.cliName,
|
|
3763
|
-
messages: messages.map((message, index) => buildChatMessage({
|
|
3764
|
-
...message,
|
|
3765
|
-
id: message.id || `msg_${index}`,
|
|
3766
|
-
index: typeof message.index === "number" ? message.index : index,
|
|
3767
|
-
receivedAt: typeof message.receivedAt === "number" ? message.receivedAt : message.timestamp
|
|
3768
|
-
})),
|
|
3769
|
-
activeModal: this.activeModal,
|
|
3770
|
-
...bufferState ? { bufferState } : {}
|
|
3771
|
-
};
|
|
3772
|
-
}
|
|
3773
|
-
const hasVisibleAssistantMessage = Array.isArray(result?.messages) && result.messages.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
|
|
3774
|
-
const shouldClampStaleGeneratingToIdle = result?.status === "generating" && this.currentStatus === "idle" && !this.currentTurnScope && !result?.activeModal && hasVisibleAssistantMessage && !hasVisibleInterruptPrompt(screenText);
|
|
3775
|
-
if (shouldClampStaleGeneratingToIdle) {
|
|
3776
|
-
result = {
|
|
3777
|
-
...result,
|
|
3778
|
-
status: "idle",
|
|
3779
|
-
messages: Array.isArray(result.messages) ? result.messages.map((message) => {
|
|
3780
|
-
if (message?.role !== "assistant" || !message?.meta?.streaming) return message;
|
|
3781
|
-
const nextMeta = { ...message.meta || {} };
|
|
3782
|
-
delete nextMeta.streaming;
|
|
3783
|
-
return {
|
|
3784
|
-
...message,
|
|
3785
|
-
...Object.keys(nextMeta).length > 0 ? { meta: nextMeta } : { meta: void 0 }
|
|
3786
|
-
};
|
|
3787
|
-
}) : result.messages
|
|
3788
|
-
};
|
|
3789
|
-
}
|
|
2578
|
+
}),
|
|
2579
|
+
activeModal,
|
|
2580
|
+
providerSessionId: typeof parsed.providerSessionId === "string" ? parsed.providerSessionId : void 0,
|
|
2581
|
+
...bufferState ? { bufferState } : {},
|
|
2582
|
+
...parsed.transcriptAuthority === "provider" || parsed.transcriptAuthority === "daemon" ? { transcriptAuthority: parsed.transcriptAuthority } : this.providerOwnsTranscript() ? { transcriptAuthority: "provider" } : {},
|
|
2583
|
+
...parsed.coverage === "full" || parsed.coverage === "tail" || parsed.coverage === "current-turn" ? { coverage: parsed.coverage } : this.providerOwnsTranscript() ? { coverage: this.shouldUseFullProviderTranscriptContext() ? "full" : "tail" } : {}
|
|
2584
|
+
};
|
|
3790
2585
|
this.parsedStatusCache = {
|
|
3791
|
-
committedMessagesRef: this.committedMessages,
|
|
3792
2586
|
responseBuffer: this.responseBuffer,
|
|
3793
2587
|
currentTurnScope: this.currentTurnScope,
|
|
3794
2588
|
recentOutputBuffer: this.recentOutputBuffer,
|
|
@@ -3811,7 +2605,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
3811
2605
|
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
3812
2606
|
recentOutputBuffer: this.recentOutputBuffer,
|
|
3813
2607
|
terminalScreenText: this.terminalScreen.getText(),
|
|
3814
|
-
baseMessages:
|
|
2608
|
+
baseMessages: [],
|
|
3815
2609
|
partialResponse: this.responseBuffer,
|
|
3816
2610
|
isWaitingForResponse: this.isWaitingForResponse,
|
|
3817
2611
|
scope: this.currentTurnScope,
|
|
@@ -3822,46 +2616,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
3822
2616
|
args: args && typeof args === "object" ? { ...args } : {}
|
|
3823
2617
|
}));
|
|
3824
2618
|
}
|
|
3825
|
-
parseCurrentTranscript(
|
|
3826
|
-
|
|
3827
|
-
this.parseErrorMessage = null;
|
|
3828
|
-
return null;
|
|
3829
|
-
}
|
|
3830
|
-
try {
|
|
3831
|
-
const screenText = typeof screenTextOverride === "string" ? screenTextOverride : this.terminalScreen.getText();
|
|
3832
|
-
const parseBaseMessages = this.selectParseBaseMessages(baseMessages);
|
|
3833
|
-
const input = buildCliParseInput({
|
|
3834
|
-
accumulatedBuffer: this.accumulatedBuffer,
|
|
3835
|
-
accumulatedRawBuffer: this.accumulatedRawBuffer,
|
|
3836
|
-
recentOutputBuffer: this.recentOutputBuffer,
|
|
3837
|
-
terminalScreenText: screenText,
|
|
3838
|
-
baseMessages: parseBaseMessages,
|
|
3839
|
-
partialResponse,
|
|
3840
|
-
isWaitingForResponse: this.isWaitingForResponse,
|
|
3841
|
-
scope,
|
|
3842
|
-
runtimeSettings: this.runtimeSettings
|
|
3843
|
-
});
|
|
3844
|
-
const parsed = this.cliScripts.parseOutput(input);
|
|
3845
|
-
if (parsed && typeof parsed === "object") {
|
|
3846
|
-
Object.assign(parsed, validateReadChatResultPayload(parsed, `${this.cliType} parseOutput`));
|
|
3847
|
-
}
|
|
3848
|
-
const normalizedParsed = this.suppressStaleParsedApproval(parsed, input.recentBuffer, input.screenText);
|
|
3849
|
-
if (normalizedParsed && Array.isArray(normalizedParsed.messages)) {
|
|
3850
|
-
normalizedParsed.messages = this.stitchParsedMessagesWithCommittedBase(
|
|
3851
|
-
normalizedParsed.messages,
|
|
3852
|
-
baseMessages,
|
|
3853
|
-
parseBaseMessages
|
|
3854
|
-
);
|
|
3855
|
-
this.trimLastAssistantEcho(normalizedParsed.messages, scope?.prompt || getLastUserPromptText(baseMessages));
|
|
3856
|
-
}
|
|
3857
|
-
this.parseErrorMessage = null;
|
|
3858
|
-
return normalizedParsed;
|
|
3859
|
-
} catch (e) {
|
|
3860
|
-
const message = e?.message || String(e);
|
|
3861
|
-
this.parseErrorMessage = message;
|
|
3862
|
-
LOG.warn("CLI", `[${this.cliType}] parseOutput error: ${message}`);
|
|
3863
|
-
throw e;
|
|
3864
|
-
}
|
|
2619
|
+
parseCurrentTranscript(_baseMessages, _partialResponse, _scope, _screenTextOverride) {
|
|
2620
|
+
return this.runParseSession();
|
|
3865
2621
|
}
|
|
3866
2622
|
/** Whether this adapter has CLI scripts loaded */
|
|
3867
2623
|
hasCliScripts() {
|
|
@@ -3923,8 +2679,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
3923
2679
|
commitSendUserTurn(state) {
|
|
3924
2680
|
if (state.didCommitUserTurn) return;
|
|
3925
2681
|
state.didCommitUserTurn = true;
|
|
3926
|
-
this.committedMessages.push({ role: "user", content: state.text, timestamp: Date.now() });
|
|
3927
|
-
this.syncMessageViews();
|
|
3928
2682
|
}
|
|
3929
2683
|
armResponseTimeout() {
|
|
3930
2684
|
if (this.responseTimeout) clearTimeout(this.responseTimeout);
|
|
@@ -4116,11 +2870,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
4116
2870
|
}
|
|
4117
2871
|
})() : null;
|
|
4118
2872
|
const parsedSessionStatus = typeof parsedStatusBeforeSend?.status === "string" ? String(parsedStatusBeforeSend.status) : "";
|
|
4119
|
-
const parsedMessagesBeforeSend = Array.isArray(parsedStatusBeforeSend?.messages) ? parsedStatusBeforeSend.messages.filter((message) => message && (message.role === "user" || message.role === "assistant")) : [];
|
|
4120
|
-
const shouldCommitParsedIdleBeforeSend = !allowInputDuringGeneration && parsedSessionStatus === "idle" && parsedMessagesBeforeSend.length > this.committedMessages.length && parsedMessagesBeforeSend.some((message) => message?.role === "assistant" && typeof message?.content === "string" && message.content.trim());
|
|
4121
|
-
if (shouldCommitParsedIdleBeforeSend) {
|
|
4122
|
-
this.commitCurrentTranscript();
|
|
4123
|
-
}
|
|
4124
2873
|
if (!allowInputDuringGeneration && (parsedSessionStatus === "generating" || parsedSessionStatus === "long_generating")) {
|
|
4125
2874
|
throw new Error(`${this.cliName} is still processing the previous prompt`);
|
|
4126
2875
|
}
|
|
@@ -4226,9 +2975,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
4226
2975
|
activeModal: this.activeModal,
|
|
4227
2976
|
parseErrorMessage: this.parseErrorMessage,
|
|
4228
2977
|
messageCounts: {
|
|
4229
|
-
committed: this.committedMessages.length,
|
|
4230
|
-
structured: this.structuredMessages.length,
|
|
4231
|
-
visible: this.messages.length,
|
|
4232
2978
|
parsedCache: Array.isArray(parsedResult?.messages) ? parsedResult.messages.length : void 0
|
|
4233
2979
|
},
|
|
4234
2980
|
buffers: {
|
|
@@ -4279,8 +3025,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
4279
3025
|
responseSettleIgnoreUntil: this.responseSettleIgnoreUntil,
|
|
4280
3026
|
responseEpoch: this.responseEpoch,
|
|
4281
3027
|
resizeSuppressUntil: this.resizeSuppressUntil,
|
|
4282
|
-
lastApprovalResolvedAt: this.lastApprovalResolvedAt
|
|
4283
|
-
committedMessagesChangedAt: this.committedMessagesChangedAt
|
|
3028
|
+
lastApprovalResolvedAt: this.lastApprovalResolvedAt
|
|
4284
3029
|
},
|
|
4285
3030
|
finish: {
|
|
4286
3031
|
idleFinishCandidate: this.idleFinishCandidate,
|
|
@@ -4405,8 +3150,6 @@ var init_provider_cli_adapter = __esm({
|
|
|
4405
3150
|
}
|
|
4406
3151
|
clearHistory() {
|
|
4407
3152
|
this.clearIdleFinishCandidate("clear_history");
|
|
4408
|
-
this.committedMessages = [];
|
|
4409
|
-
this.syncMessageViews();
|
|
4410
3153
|
this.accumulatedBuffer = "";
|
|
4411
3154
|
this.accumulatedRawBuffer = "";
|
|
4412
3155
|
this.currentTurnScope = null;
|
|
@@ -4447,7 +3190,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
4447
3190
|
}
|
|
4448
3191
|
resolveModal(buttonIndex) {
|
|
4449
3192
|
let modal = this.activeModal || this.runParseApproval(this.recentOutputBuffer);
|
|
4450
|
-
if (!modal && typeof this.cliScripts?.
|
|
3193
|
+
if (!modal && typeof this.cliScripts?.parseSession === "function") {
|
|
4451
3194
|
try {
|
|
4452
3195
|
const parsed = this.getScriptParsedStatus();
|
|
4453
3196
|
const parsedModal = parsed?.activeModal && Array.isArray(parsed.activeModal.buttons) && parsed.activeModal.buttons.some((button) => typeof button === "string" && button.trim()) ? parsed.activeModal : null;
|
|
@@ -4514,10 +3257,8 @@ var init_provider_cli_adapter = __esm({
|
|
|
4514
3257
|
startupParseGate: this.startupParseGate,
|
|
4515
3258
|
spawnAt: this.spawnAt,
|
|
4516
3259
|
workingDir: this.workingDir,
|
|
4517
|
-
messages:
|
|
4518
|
-
|
|
4519
|
-
structuredMessages: this.structuredMessages,
|
|
4520
|
-
messageCount: this.committedMessages.length,
|
|
3260
|
+
messages: [],
|
|
3261
|
+
messageCount: 0,
|
|
4521
3262
|
screenText: screenText.slice(-4e3),
|
|
4522
3263
|
currentTurnScope: this.currentTurnScope,
|
|
4523
3264
|
startupBuffer: this.startupBuffer.slice(-4e3),
|
|
@@ -4569,7 +3310,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
4569
3310
|
lifecycleStatus: this.isWaitingForResponse ? "awaiting_response" : "idle",
|
|
4570
3311
|
activeModal: this.activeModal,
|
|
4571
3312
|
currentTurnScope: this.currentTurnScope,
|
|
4572
|
-
messages:
|
|
3313
|
+
messages: []
|
|
4573
3314
|
};
|
|
4574
3315
|
}
|
|
4575
3316
|
getProviderResolutionMeta() {
|
|
@@ -8182,14 +6923,223 @@ var CdpDomHandlers = class {
|
|
|
8182
6923
|
return { success: false, error: e.message };
|
|
8183
6924
|
}
|
|
8184
6925
|
}
|
|
8185
|
-
};
|
|
8186
|
-
|
|
8187
|
-
// src/providers/ide-provider-instance.ts
|
|
8188
|
-
|
|
8189
|
-
|
|
6926
|
+
};
|
|
6927
|
+
|
|
6928
|
+
// src/providers/ide-provider-instance.ts
|
|
6929
|
+
import * as crypto2 from "crypto";
|
|
6930
|
+
|
|
6931
|
+
// src/providers/io-contracts.ts
|
|
6932
|
+
function normalizeInputEnvelope(input) {
|
|
6933
|
+
const normalized = normalizeInputEnvelopePayload(input);
|
|
6934
|
+
const textFallback = normalized.textFallback ?? flattenInputParts(normalized.parts);
|
|
6935
|
+
return {
|
|
6936
|
+
parts: normalized.parts,
|
|
6937
|
+
textFallback,
|
|
6938
|
+
...normalized.metadata ? { metadata: normalized.metadata } : {}
|
|
6939
|
+
};
|
|
6940
|
+
}
|
|
6941
|
+
function normalizeMessageParts(content) {
|
|
6942
|
+
if (typeof content === "string") return [{ type: "text", text: content }];
|
|
6943
|
+
if (!Array.isArray(content)) {
|
|
6944
|
+
if (content && typeof content === "object" && typeof content.text === "string") {
|
|
6945
|
+
return [{ type: "text", text: String(content.text) }];
|
|
6946
|
+
}
|
|
6947
|
+
return [];
|
|
6948
|
+
}
|
|
6949
|
+
const parts = [];
|
|
6950
|
+
for (const raw of content) {
|
|
6951
|
+
if (typeof raw === "string") {
|
|
6952
|
+
parts.push({ type: "text", text: raw });
|
|
6953
|
+
continue;
|
|
6954
|
+
}
|
|
6955
|
+
if (!raw || typeof raw !== "object") continue;
|
|
6956
|
+
const part = normalizeMessagePartObject(raw);
|
|
6957
|
+
if (part) parts.push(part);
|
|
6958
|
+
}
|
|
6959
|
+
return parts;
|
|
6960
|
+
}
|
|
6961
|
+
function flattenMessageParts(parts) {
|
|
6962
|
+
return parts.map((part) => {
|
|
6963
|
+
if (part.type === "text") return part.text;
|
|
6964
|
+
if (part.type === "resource") return part.resource.text || "";
|
|
6965
|
+
return "";
|
|
6966
|
+
}).filter((value) => value.length > 0).join("\n");
|
|
6967
|
+
}
|
|
6968
|
+
function normalizeInputEnvelopePayload(input) {
|
|
6969
|
+
if (typeof input === "string") {
|
|
6970
|
+
return { parts: [{ type: "text", text: input }], textFallback: input };
|
|
6971
|
+
}
|
|
6972
|
+
if (!input || typeof input !== "object") {
|
|
6973
|
+
return { parts: [], textFallback: "" };
|
|
6974
|
+
}
|
|
6975
|
+
const record = input;
|
|
6976
|
+
const nestedInput = record.input;
|
|
6977
|
+
if (nestedInput && typeof nestedInput === "object") {
|
|
6978
|
+
const nested = nestedInput;
|
|
6979
|
+
return {
|
|
6980
|
+
parts: normalizeInputParts(nested.parts ?? nested.prompt),
|
|
6981
|
+
textFallback: typeof nested.textFallback === "string" ? nested.textFallback : void 0,
|
|
6982
|
+
metadata: normalizeInputMetadata(nested.metadata)
|
|
6983
|
+
};
|
|
6984
|
+
}
|
|
6985
|
+
const directText = typeof record.text === "string" ? record.text : typeof record.message === "string" ? record.message : void 0;
|
|
6986
|
+
if (directText !== void 0) {
|
|
6987
|
+
return { parts: [{ type: "text", text: directText }], textFallback: directText };
|
|
6988
|
+
}
|
|
6989
|
+
const directParts = normalizeInputParts(record.parts ?? record.prompt);
|
|
6990
|
+
return {
|
|
6991
|
+
parts: directParts,
|
|
6992
|
+
textFallback: typeof record.textFallback === "string" ? record.textFallback : void 0,
|
|
6993
|
+
metadata: normalizeInputMetadata(record.metadata)
|
|
6994
|
+
};
|
|
6995
|
+
}
|
|
6996
|
+
function normalizeInputMetadata(value) {
|
|
6997
|
+
if (!value || typeof value !== "object") return void 0;
|
|
6998
|
+
const record = value;
|
|
6999
|
+
const metadata = {};
|
|
7000
|
+
if (record.source === "dashboard" || record.source === "shortcut_api" || record.source === "provider_script" || record.source === "session_replay") {
|
|
7001
|
+
metadata.source = record.source;
|
|
7002
|
+
}
|
|
7003
|
+
if (typeof record.clientTimestamp === "number" && Number.isFinite(record.clientTimestamp)) {
|
|
7004
|
+
metadata.clientTimestamp = record.clientTimestamp;
|
|
7005
|
+
}
|
|
7006
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
7007
|
+
}
|
|
7008
|
+
function normalizeInputParts(value) {
|
|
7009
|
+
if (!Array.isArray(value)) return [];
|
|
7010
|
+
const parts = [];
|
|
7011
|
+
for (const raw of value) {
|
|
7012
|
+
if (typeof raw === "string") {
|
|
7013
|
+
parts.push({ type: "text", text: raw });
|
|
7014
|
+
continue;
|
|
7015
|
+
}
|
|
7016
|
+
if (!raw || typeof raw !== "object") continue;
|
|
7017
|
+
const part = normalizeInputPartObject(raw);
|
|
7018
|
+
if (part) parts.push(part);
|
|
7019
|
+
}
|
|
7020
|
+
return parts;
|
|
7021
|
+
}
|
|
7022
|
+
function normalizeInputPartObject(raw) {
|
|
7023
|
+
const type = raw.type;
|
|
7024
|
+
if (type === "text" && typeof raw.text === "string") {
|
|
7025
|
+
return { type, text: raw.text };
|
|
7026
|
+
}
|
|
7027
|
+
if (type === "image" && typeof raw.mimeType === "string") {
|
|
7028
|
+
return {
|
|
7029
|
+
type,
|
|
7030
|
+
mimeType: raw.mimeType,
|
|
7031
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
7032
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
7033
|
+
...typeof raw.alt === "string" ? { alt: raw.alt } : {}
|
|
7034
|
+
};
|
|
7035
|
+
}
|
|
7036
|
+
if (type === "audio" && typeof raw.mimeType === "string") {
|
|
7037
|
+
return {
|
|
7038
|
+
type,
|
|
7039
|
+
mimeType: raw.mimeType,
|
|
7040
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
7041
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
7042
|
+
...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
|
|
7043
|
+
};
|
|
7044
|
+
}
|
|
7045
|
+
if (type === "video" && typeof raw.mimeType === "string") {
|
|
7046
|
+
return {
|
|
7047
|
+
type,
|
|
7048
|
+
mimeType: raw.mimeType,
|
|
7049
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
7050
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
7051
|
+
...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
|
|
7052
|
+
};
|
|
7053
|
+
}
|
|
7054
|
+
if (type === "resource" && typeof raw.uri === "string") {
|
|
7055
|
+
return {
|
|
7056
|
+
type,
|
|
7057
|
+
uri: raw.uri,
|
|
7058
|
+
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
7059
|
+
...typeof raw.name === "string" ? { name: raw.name } : {},
|
|
7060
|
+
...typeof raw.text === "string" ? { text: raw.text } : {},
|
|
7061
|
+
...typeof raw.data === "string" ? { data: raw.data } : {}
|
|
7062
|
+
};
|
|
7063
|
+
}
|
|
7064
|
+
if (type === "resource_link" && typeof raw.uri === "string") {
|
|
7065
|
+
return {
|
|
7066
|
+
type: "resource",
|
|
7067
|
+
uri: raw.uri,
|
|
7068
|
+
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
7069
|
+
...typeof raw.name === "string" ? { name: raw.name } : {}
|
|
7070
|
+
};
|
|
7071
|
+
}
|
|
7072
|
+
return null;
|
|
7073
|
+
}
|
|
7074
|
+
function normalizeMessagePartObject(raw) {
|
|
7075
|
+
const type = raw.type;
|
|
7076
|
+
if (type === "text" && typeof raw.text === "string") {
|
|
7077
|
+
return { type, text: raw.text };
|
|
7078
|
+
}
|
|
7079
|
+
if (type === "image" && typeof raw.mimeType === "string") {
|
|
7080
|
+
return {
|
|
7081
|
+
type,
|
|
7082
|
+
mimeType: raw.mimeType,
|
|
7083
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
7084
|
+
...typeof raw.data === "string" ? { data: raw.data } : {}
|
|
7085
|
+
};
|
|
7086
|
+
}
|
|
7087
|
+
if (type === "audio" && typeof raw.mimeType === "string") {
|
|
7088
|
+
return {
|
|
7089
|
+
type,
|
|
7090
|
+
mimeType: raw.mimeType,
|
|
7091
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
7092
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
7093
|
+
...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
|
|
7094
|
+
};
|
|
7095
|
+
}
|
|
7096
|
+
if (type === "video" && typeof raw.mimeType === "string") {
|
|
7097
|
+
return {
|
|
7098
|
+
type,
|
|
7099
|
+
mimeType: raw.mimeType,
|
|
7100
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
7101
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
7102
|
+
...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
|
|
7103
|
+
};
|
|
7104
|
+
}
|
|
7105
|
+
if (type === "resource_link" && typeof raw.uri === "string" && typeof raw.name === "string") {
|
|
7106
|
+
return {
|
|
7107
|
+
type,
|
|
7108
|
+
uri: raw.uri,
|
|
7109
|
+
name: raw.name,
|
|
7110
|
+
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
7111
|
+
...typeof raw.size === "number" ? { size: raw.size } : {}
|
|
7112
|
+
};
|
|
7113
|
+
}
|
|
7114
|
+
if (type === "resource" && raw.resource && typeof raw.resource === "object") {
|
|
7115
|
+
const resource = raw.resource;
|
|
7116
|
+
if (typeof resource.uri !== "string") return null;
|
|
7117
|
+
return {
|
|
7118
|
+
type,
|
|
7119
|
+
resource: {
|
|
7120
|
+
uri: resource.uri,
|
|
7121
|
+
...typeof resource.mimeType === "string" || resource.mimeType === null ? { mimeType: resource.mimeType } : {},
|
|
7122
|
+
...typeof resource.text === "string" ? { text: resource.text } : {},
|
|
7123
|
+
...typeof resource.blob === "string" ? { blob: resource.blob } : {}
|
|
7124
|
+
}
|
|
7125
|
+
};
|
|
7126
|
+
}
|
|
7127
|
+
return null;
|
|
7128
|
+
}
|
|
7129
|
+
function flattenInputParts(parts) {
|
|
7130
|
+
return parts.map((part) => {
|
|
7131
|
+
if (part.type === "text") return part.text;
|
|
7132
|
+
if (part.type === "audio") return part.transcript || "";
|
|
7133
|
+
if (part.type === "resource") return part.text || "";
|
|
7134
|
+
return "";
|
|
7135
|
+
}).filter((value) => value.length > 0).join("\n");
|
|
7136
|
+
}
|
|
8190
7137
|
|
|
8191
|
-
// src/providers/
|
|
8192
|
-
|
|
7138
|
+
// src/providers/contracts.ts
|
|
7139
|
+
function flattenContent(content) {
|
|
7140
|
+
if (typeof content === "string") return content;
|
|
7141
|
+
return flattenMessageParts(normalizeMessageParts(content));
|
|
7142
|
+
}
|
|
8193
7143
|
|
|
8194
7144
|
// src/providers/status-monitor.ts
|
|
8195
7145
|
var DEFAULT_MONITOR_CONFIG = {
|
|
@@ -8303,9 +7253,151 @@ var StatusMonitor = class {
|
|
|
8303
7253
|
}
|
|
8304
7254
|
};
|
|
8305
7255
|
|
|
7256
|
+
// src/providers/chat-message-normalization.ts
|
|
7257
|
+
var BUILTIN_CHAT_MESSAGE_KINDS = ["standard", "thought", "tool", "terminal", "system"];
|
|
7258
|
+
var KNOWN_CHAT_MESSAGE_KINDS = new Set(BUILTIN_CHAT_MESSAGE_KINDS);
|
|
7259
|
+
var CHAT_MESSAGE_KIND_ALIASES = {
|
|
7260
|
+
text: "standard",
|
|
7261
|
+
message: "standard",
|
|
7262
|
+
assistant: "standard",
|
|
7263
|
+
thinking: "thought",
|
|
7264
|
+
think: "thought",
|
|
7265
|
+
reasoning: "thought",
|
|
7266
|
+
reason: "thought",
|
|
7267
|
+
toolcall: "tool",
|
|
7268
|
+
tool_call: "tool",
|
|
7269
|
+
tooluse: "tool",
|
|
7270
|
+
tool_use: "tool",
|
|
7271
|
+
action: "tool",
|
|
7272
|
+
command: "terminal",
|
|
7273
|
+
cmd: "terminal",
|
|
7274
|
+
shell: "terminal",
|
|
7275
|
+
console: "terminal"
|
|
7276
|
+
};
|
|
7277
|
+
function canonicalizeKindHint(value) {
|
|
7278
|
+
return value.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
7279
|
+
}
|
|
7280
|
+
function resolveBuiltinOrAliasKind(kind) {
|
|
7281
|
+
if (typeof kind !== "string") return null;
|
|
7282
|
+
const normalizedKind = canonicalizeKindHint(kind);
|
|
7283
|
+
if (!normalizedKind) return null;
|
|
7284
|
+
if (KNOWN_CHAT_MESSAGE_KINDS.has(normalizedKind)) return normalizedKind;
|
|
7285
|
+
return CHAT_MESSAGE_KIND_ALIASES[normalizedKind] || null;
|
|
7286
|
+
}
|
|
7287
|
+
function inferHintKind(value) {
|
|
7288
|
+
const direct = resolveBuiltinOrAliasKind(value);
|
|
7289
|
+
if (direct) return direct;
|
|
7290
|
+
if (typeof value !== "string") return null;
|
|
7291
|
+
const normalized = canonicalizeKindHint(value);
|
|
7292
|
+
if (!normalized) return null;
|
|
7293
|
+
if (/thought|thinking|reasoning/.test(normalized)) return "thought";
|
|
7294
|
+
if (/tool/.test(normalized)) return "tool";
|
|
7295
|
+
if (/terminal|command|shell|console/.test(normalized)) return "terminal";
|
|
7296
|
+
return null;
|
|
7297
|
+
}
|
|
7298
|
+
function inferKindFromToolCalls(message) {
|
|
7299
|
+
const toolCalls = Array.isArray(message?.toolCalls) ? message.toolCalls : [];
|
|
7300
|
+
if (toolCalls.length === 0) return null;
|
|
7301
|
+
if (toolCalls.some((toolCall) => toolCall?.kind === "think")) return "thought";
|
|
7302
|
+
if (toolCalls.some((toolCall) => toolCall?.kind === "execute")) return "terminal";
|
|
7303
|
+
if (toolCalls.some((toolCall) => Array.isArray(toolCall?.content) && toolCall.content.some((entry) => entry?.type === "terminal"))) {
|
|
7304
|
+
return "terminal";
|
|
7305
|
+
}
|
|
7306
|
+
return "tool";
|
|
7307
|
+
}
|
|
7308
|
+
function inferMissingChatMessageKind(message) {
|
|
7309
|
+
const role = typeof message?.role === "string" ? message.role.trim().toLowerCase() : "";
|
|
7310
|
+
if (role === "system") return "system";
|
|
7311
|
+
const meta = message?.meta && typeof message.meta === "object" ? message.meta : void 0;
|
|
7312
|
+
const hintCandidates = [
|
|
7313
|
+
message?._sub,
|
|
7314
|
+
message?._type,
|
|
7315
|
+
meta?.label,
|
|
7316
|
+
typeof message?.senderName === "string" ? message.senderName : void 0
|
|
7317
|
+
];
|
|
7318
|
+
for (const candidate of hintCandidates) {
|
|
7319
|
+
const inferred = inferHintKind(candidate);
|
|
7320
|
+
if (inferred) return inferred;
|
|
7321
|
+
}
|
|
7322
|
+
const inferredFromToolCalls = inferKindFromToolCalls(message);
|
|
7323
|
+
if (inferredFromToolCalls) return inferredFromToolCalls;
|
|
7324
|
+
return null;
|
|
7325
|
+
}
|
|
7326
|
+
function isBuiltinChatMessageKind(kind) {
|
|
7327
|
+
return resolveBuiltinOrAliasKind(kind) !== null;
|
|
7328
|
+
}
|
|
7329
|
+
function normalizeChatMessageKind(kind, role) {
|
|
7330
|
+
const resolvedKind = resolveBuiltinOrAliasKind(kind);
|
|
7331
|
+
if (resolvedKind) return resolvedKind;
|
|
7332
|
+
const normalizedRole = typeof role === "string" ? role.trim().toLowerCase() : "";
|
|
7333
|
+
return normalizedRole === "system" ? "system" : "standard";
|
|
7334
|
+
}
|
|
7335
|
+
function resolveChatMessageKind(message) {
|
|
7336
|
+
const explicitKind = resolveBuiltinOrAliasKind(message?.kind);
|
|
7337
|
+
if (explicitKind) return explicitKind;
|
|
7338
|
+
const inferredKind = inferMissingChatMessageKind(message);
|
|
7339
|
+
if (inferredKind) return inferredKind;
|
|
7340
|
+
return normalizeChatMessageKind(message?.kind, message?.role);
|
|
7341
|
+
}
|
|
7342
|
+
function buildChatMessage(message) {
|
|
7343
|
+
return {
|
|
7344
|
+
...message,
|
|
7345
|
+
kind: resolveChatMessageKind(message)
|
|
7346
|
+
};
|
|
7347
|
+
}
|
|
7348
|
+
function buildSystemChatMessage(message) {
|
|
7349
|
+
return buildChatMessage({
|
|
7350
|
+
...message,
|
|
7351
|
+
role: "system",
|
|
7352
|
+
kind: message?.kind || "system"
|
|
7353
|
+
});
|
|
7354
|
+
}
|
|
7355
|
+
function buildRuntimeSystemChatMessage(message) {
|
|
7356
|
+
return buildSystemChatMessage({
|
|
7357
|
+
...message,
|
|
7358
|
+
senderName: typeof message?.senderName === "string" && message.senderName.trim() ? message.senderName : "System"
|
|
7359
|
+
});
|
|
7360
|
+
}
|
|
7361
|
+
function buildAssistantChatMessage(message) {
|
|
7362
|
+
return buildChatMessage({
|
|
7363
|
+
...message,
|
|
7364
|
+
role: "assistant",
|
|
7365
|
+
kind: message?.kind || "standard"
|
|
7366
|
+
});
|
|
7367
|
+
}
|
|
7368
|
+
function buildThoughtChatMessage(message) {
|
|
7369
|
+
return buildAssistantChatMessage({
|
|
7370
|
+
...message,
|
|
7371
|
+
kind: message?.kind || "thought"
|
|
7372
|
+
});
|
|
7373
|
+
}
|
|
7374
|
+
function buildToolChatMessage(message) {
|
|
7375
|
+
return buildAssistantChatMessage({
|
|
7376
|
+
...message,
|
|
7377
|
+
kind: message?.kind || "tool"
|
|
7378
|
+
});
|
|
7379
|
+
}
|
|
7380
|
+
function buildTerminalChatMessage(message) {
|
|
7381
|
+
return buildAssistantChatMessage({
|
|
7382
|
+
...message,
|
|
7383
|
+
kind: message?.kind || "terminal"
|
|
7384
|
+
});
|
|
7385
|
+
}
|
|
7386
|
+
function buildUserChatMessage(message) {
|
|
7387
|
+
return buildChatMessage({
|
|
7388
|
+
...message,
|
|
7389
|
+
role: "user",
|
|
7390
|
+
kind: message?.kind || "standard"
|
|
7391
|
+
});
|
|
7392
|
+
}
|
|
7393
|
+
function normalizeChatMessage(message) {
|
|
7394
|
+
return buildChatMessage(message);
|
|
7395
|
+
}
|
|
7396
|
+
function normalizeChatMessages(messages) {
|
|
7397
|
+
return (Array.isArray(messages) ? messages : []).map((message) => normalizeChatMessage(message));
|
|
7398
|
+
}
|
|
7399
|
+
|
|
8306
7400
|
// src/providers/control-effects.ts
|
|
8307
|
-
init_contracts();
|
|
8308
|
-
init_chat_message_normalization();
|
|
8309
7401
|
function extractProviderControlValues(controls, data) {
|
|
8310
7402
|
if (!data || typeof data !== "object") return void 0;
|
|
8311
7403
|
const values = {};
|
|
@@ -8499,7 +7591,6 @@ ${cleanBody}`;
|
|
|
8499
7591
|
}
|
|
8500
7592
|
|
|
8501
7593
|
// src/config/chat-history.ts
|
|
8502
|
-
init_chat_message_normalization();
|
|
8503
7594
|
import * as fs3 from "fs";
|
|
8504
7595
|
import * as path10 from "path";
|
|
8505
7596
|
import * as os5 from "os";
|
|
@@ -9781,9 +8872,6 @@ function resolveProviderStateSurface(params) {
|
|
|
9781
8872
|
};
|
|
9782
8873
|
}
|
|
9783
8874
|
|
|
9784
|
-
// src/providers/extension-provider-instance.ts
|
|
9785
|
-
init_chat_message_normalization();
|
|
9786
|
-
|
|
9787
8875
|
// src/providers/open-panel-support.ts
|
|
9788
8876
|
var IDE_PROVIDER_SESSION_CAPABILITIES_BASE = [
|
|
9789
8877
|
"read_chat",
|
|
@@ -10217,7 +9305,143 @@ ${effect.notification.body || ""}`.trim();
|
|
|
10217
9305
|
|
|
10218
9306
|
// src/providers/ide-provider-instance.ts
|
|
10219
9307
|
init_logger();
|
|
10220
|
-
|
|
9308
|
+
|
|
9309
|
+
// src/providers/read-chat-contract.ts
|
|
9310
|
+
var VALID_STATUSES = ["idle", "generating", "waiting_approval", "error", "panel_hidden", "streaming", "long_generating"];
|
|
9311
|
+
var VALID_ROLES = ["user", "assistant", "system", "human"];
|
|
9312
|
+
var VALID_BUBBLE_STATES = ["draft", "streaming", "final", "removed"];
|
|
9313
|
+
var VALID_TURN_STATUSES = ["open", "waiting_approval", "complete", "error"];
|
|
9314
|
+
function isPlainObject3(value) {
|
|
9315
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
9316
|
+
}
|
|
9317
|
+
function isFiniteNumber(value) {
|
|
9318
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
9319
|
+
}
|
|
9320
|
+
function validateStatus(status, source) {
|
|
9321
|
+
if (typeof status !== "string" || !VALID_STATUSES.includes(status)) {
|
|
9322
|
+
throw new Error(`${source}: status must be one of ${VALID_STATUSES.join(", ")}`);
|
|
9323
|
+
}
|
|
9324
|
+
return status;
|
|
9325
|
+
}
|
|
9326
|
+
function validateRole(role, source, index) {
|
|
9327
|
+
if (typeof role !== "string" || !VALID_ROLES.includes(role)) {
|
|
9328
|
+
throw new Error(`${source}: messages[${index}].role must be one of ${VALID_ROLES.join(", ")}`);
|
|
9329
|
+
}
|
|
9330
|
+
return role;
|
|
9331
|
+
}
|
|
9332
|
+
function validateBubbleState(state, source, index) {
|
|
9333
|
+
if (typeof state !== "string" || !VALID_BUBBLE_STATES.includes(state)) {
|
|
9334
|
+
throw new Error(`${source}: messages[${index}].bubbleState must be one of ${VALID_BUBBLE_STATES.join(", ")}`);
|
|
9335
|
+
}
|
|
9336
|
+
return state;
|
|
9337
|
+
}
|
|
9338
|
+
function validateTurnStatus(turnStatus, source) {
|
|
9339
|
+
if (typeof turnStatus !== "string" || !VALID_TURN_STATUSES.includes(turnStatus)) {
|
|
9340
|
+
throw new Error(`${source}: turnStatus must be one of ${VALID_TURN_STATUSES.join(", ")}`);
|
|
9341
|
+
}
|
|
9342
|
+
return turnStatus;
|
|
9343
|
+
}
|
|
9344
|
+
function validateMessageContent(content, source, index) {
|
|
9345
|
+
if (typeof content === "string") return content;
|
|
9346
|
+
if (Array.isArray(content)) return normalizeMessageParts(content);
|
|
9347
|
+
throw new Error(`${source}: messages[${index}].content must be a string or structured content array`);
|
|
9348
|
+
}
|
|
9349
|
+
function validateMessage(message, source, index) {
|
|
9350
|
+
if (!isPlainObject3(message)) {
|
|
9351
|
+
throw new Error(`${source}: messages[${index}] must be an object`);
|
|
9352
|
+
}
|
|
9353
|
+
const normalized = {
|
|
9354
|
+
role: validateRole(message.role, source, index),
|
|
9355
|
+
content: validateMessageContent(message.content, source, index)
|
|
9356
|
+
};
|
|
9357
|
+
if (typeof message.kind === "string") normalized.kind = message.kind;
|
|
9358
|
+
if (typeof message.id === "string") normalized.id = message.id;
|
|
9359
|
+
if (typeof message.bubbleId === "string") normalized.bubbleId = message.bubbleId;
|
|
9360
|
+
if (typeof message.providerUnitKey === "string") normalized.providerUnitKey = message.providerUnitKey;
|
|
9361
|
+
if (message.bubbleState !== void 0) normalized.bubbleState = validateBubbleState(message.bubbleState, source, index);
|
|
9362
|
+
if (isFiniteNumber(message.index)) normalized.index = message.index;
|
|
9363
|
+
if (isFiniteNumber(message.timestamp)) normalized.timestamp = message.timestamp;
|
|
9364
|
+
if (isFiniteNumber(message.receivedAt)) normalized.receivedAt = message.receivedAt;
|
|
9365
|
+
if (typeof message._turnKey === "string") normalized._turnKey = message._turnKey;
|
|
9366
|
+
if (Array.isArray(message.toolCalls)) normalized.toolCalls = message.toolCalls;
|
|
9367
|
+
if (isPlainObject3(message.meta)) normalized.meta = message.meta;
|
|
9368
|
+
if (typeof message.senderName === "string") normalized.senderName = message.senderName;
|
|
9369
|
+
if (typeof message._type === "string") normalized._type = message._type;
|
|
9370
|
+
if (typeof message._sub === "string") normalized._sub = message._sub;
|
|
9371
|
+
return normalized;
|
|
9372
|
+
}
|
|
9373
|
+
function validateModal(activeModal, status, source) {
|
|
9374
|
+
if (activeModal == null) {
|
|
9375
|
+
if (status === "waiting_approval") {
|
|
9376
|
+
throw new Error(`${source}: waiting_approval status requires activeModal with buttons`);
|
|
9377
|
+
}
|
|
9378
|
+
return activeModal === null ? null : void 0;
|
|
9379
|
+
}
|
|
9380
|
+
if (!isPlainObject3(activeModal)) {
|
|
9381
|
+
throw new Error(`${source}: activeModal must be an object when provided`);
|
|
9382
|
+
}
|
|
9383
|
+
if (typeof activeModal.message !== "string") {
|
|
9384
|
+
throw new Error(`${source}: activeModal.message must be a string`);
|
|
9385
|
+
}
|
|
9386
|
+
if (!Array.isArray(activeModal.buttons) || activeModal.buttons.some((button) => typeof button !== "string" || !button.trim())) {
|
|
9387
|
+
throw new Error(`${source}: activeModal.buttons must be a non-empty string array`);
|
|
9388
|
+
}
|
|
9389
|
+
const normalized = {
|
|
9390
|
+
message: activeModal.message,
|
|
9391
|
+
buttons: activeModal.buttons.map((button) => button.trim())
|
|
9392
|
+
};
|
|
9393
|
+
if (isFiniteNumber(activeModal.width)) normalized.width = activeModal.width;
|
|
9394
|
+
if (isFiniteNumber(activeModal.height)) normalized.height = activeModal.height;
|
|
9395
|
+
return normalized;
|
|
9396
|
+
}
|
|
9397
|
+
function validateControlValues(controlValues, source) {
|
|
9398
|
+
if (controlValues === void 0) return void 0;
|
|
9399
|
+
if (!isPlainObject3(controlValues)) {
|
|
9400
|
+
throw new Error(`${source}: controlValues must be an object when provided`);
|
|
9401
|
+
}
|
|
9402
|
+
const normalized = {};
|
|
9403
|
+
for (const [key, value] of Object.entries(controlValues)) {
|
|
9404
|
+
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") {
|
|
9405
|
+
throw new Error(`${source}: controlValues.${key} must be string, number, or boolean`);
|
|
9406
|
+
}
|
|
9407
|
+
normalized[key] = value;
|
|
9408
|
+
}
|
|
9409
|
+
return normalized;
|
|
9410
|
+
}
|
|
9411
|
+
function validateReadChatResultPayload(raw, source = "read_chat") {
|
|
9412
|
+
if (!isPlainObject3(raw)) {
|
|
9413
|
+
throw new Error(`${source}: payload must be an object`);
|
|
9414
|
+
}
|
|
9415
|
+
const status = validateStatus(raw.status, source);
|
|
9416
|
+
if (!Array.isArray(raw.messages)) {
|
|
9417
|
+
throw new Error(`${source}: messages must be an array`);
|
|
9418
|
+
}
|
|
9419
|
+
const messages = raw.messages.map((message, index) => validateMessage(message, source, index));
|
|
9420
|
+
const activeModal = validateModal(raw.activeModal, status, source);
|
|
9421
|
+
const controlValues = validateControlValues(raw.controlValues, source);
|
|
9422
|
+
const normalized = {
|
|
9423
|
+
status,
|
|
9424
|
+
messages
|
|
9425
|
+
};
|
|
9426
|
+
if (activeModal !== void 0) normalized.activeModal = activeModal;
|
|
9427
|
+
if (typeof raw.id === "string") normalized.id = raw.id;
|
|
9428
|
+
if (typeof raw.title === "string") normalized.title = raw.title;
|
|
9429
|
+
if (typeof raw.currentTurnId === "string") normalized.currentTurnId = raw.currentTurnId;
|
|
9430
|
+
if (raw.turnStatus !== void 0) normalized.turnStatus = validateTurnStatus(raw.turnStatus, source);
|
|
9431
|
+
if (typeof raw.agentType === "string") normalized.agentType = raw.agentType;
|
|
9432
|
+
if (typeof raw.agentName === "string") normalized.agentName = raw.agentName;
|
|
9433
|
+
if (typeof raw.extensionId === "string") normalized.extensionId = raw.extensionId;
|
|
9434
|
+
if (typeof raw.inputContent === "string") normalized.inputContent = raw.inputContent;
|
|
9435
|
+
if (typeof raw.isVisible === "boolean") normalized.isVisible = raw.isVisible;
|
|
9436
|
+
if (typeof raw.isWelcomeScreen === "boolean") normalized.isWelcomeScreen = raw.isWelcomeScreen;
|
|
9437
|
+
if (controlValues) normalized.controlValues = controlValues;
|
|
9438
|
+
if (raw.summaryMetadata !== void 0) normalized.summaryMetadata = raw.summaryMetadata;
|
|
9439
|
+
if (Array.isArray(raw.effects)) normalized.effects = raw.effects;
|
|
9440
|
+
if (typeof raw.providerSessionId === "string") normalized.providerSessionId = raw.providerSessionId;
|
|
9441
|
+
if (raw.transcriptAuthority === "provider" || raw.transcriptAuthority === "daemon") normalized.transcriptAuthority = raw.transcriptAuthority;
|
|
9442
|
+
if (raw.coverage === "full" || raw.coverage === "tail" || raw.coverage === "current-turn") normalized.coverage = raw.coverage;
|
|
9443
|
+
return normalized;
|
|
9444
|
+
}
|
|
10221
9445
|
|
|
10222
9446
|
// src/providers/approval-utils.ts
|
|
10223
9447
|
var DEFAULT_APPROVAL_POSITIVE_HINTS = [
|
|
@@ -10267,7 +9491,6 @@ function formatAutoApprovalMessage(modalMessage, buttonLabel) {
|
|
|
10267
9491
|
}
|
|
10268
9492
|
|
|
10269
9493
|
// src/providers/ide-provider-instance.ts
|
|
10270
|
-
init_chat_message_normalization();
|
|
10271
9494
|
var IdeProviderInstance = class {
|
|
10272
9495
|
type;
|
|
10273
9496
|
category = "ide";
|
|
@@ -11726,7 +10949,6 @@ function resolveLegacyProviderScript(fn, scriptName, params) {
|
|
|
11726
10949
|
}
|
|
11727
10950
|
|
|
11728
10951
|
// src/commands/chat-commands.ts
|
|
11729
|
-
init_contracts();
|
|
11730
10952
|
import * as fs4 from "fs";
|
|
11731
10953
|
import * as os6 from "os";
|
|
11732
10954
|
import * as path11 from "path";
|
|
@@ -11788,7 +11010,6 @@ function assertProviderSupportsDeclaredInput(provider, input) {
|
|
|
11788
11010
|
}
|
|
11789
11011
|
|
|
11790
11012
|
// src/commands/chat-commands.ts
|
|
11791
|
-
init_read_chat_contract();
|
|
11792
11013
|
init_logger();
|
|
11793
11014
|
|
|
11794
11015
|
// src/logging/debug-trace.ts
|
|
@@ -11916,10 +11137,6 @@ function buildChatTailDeliverySignature(payload) {
|
|
|
11916
11137
|
payload.historySessionId || "",
|
|
11917
11138
|
payload.status,
|
|
11918
11139
|
payload.title || "",
|
|
11919
|
-
payload.syncMode,
|
|
11920
|
-
String(payload.replaceFrom),
|
|
11921
|
-
String(payload.totalMessages),
|
|
11922
|
-
payload.lastMessageSignature,
|
|
11923
11140
|
payload.activeModal ? `${payload.activeModal.message}|${payload.activeModal.buttons.join("")}` : "",
|
|
11924
11141
|
stringifySignatureMessages(payload.messages)
|
|
11925
11142
|
]);
|
|
@@ -11935,7 +11152,6 @@ function buildSessionModalDeliverySignature(payload) {
|
|
|
11935
11152
|
}
|
|
11936
11153
|
|
|
11937
11154
|
// src/commands/chat-commands.ts
|
|
11938
|
-
init_chat_message_normalization();
|
|
11939
11155
|
var RECENT_SEND_WINDOW_MS = 1200;
|
|
11940
11156
|
var READ_CHAT_PROVIDER_EVAL_TIMEOUT_MS = 25e3;
|
|
11941
11157
|
var recentSendByTarget = /* @__PURE__ */ new Map();
|
|
@@ -12036,99 +11252,13 @@ function parseMaybeJson(value) {
|
|
|
12036
11252
|
return value;
|
|
12037
11253
|
}
|
|
12038
11254
|
}
|
|
12039
|
-
function
|
|
12040
|
-
|
|
12041
|
-
|
|
12042
|
-
function normalizeReadChatCursor(args) {
|
|
12043
|
-
const knownMessageCount = Math.max(0, Number(args?.knownMessageCount || 0));
|
|
12044
|
-
const lastMessageSignature = typeof args?.lastMessageSignature === "string" ? args.lastMessageSignature : "";
|
|
12045
|
-
const tailLimit = Math.max(0, Number(args?.tailLimit || 0));
|
|
12046
|
-
return { knownMessageCount, lastMessageSignature, tailLimit };
|
|
11255
|
+
function normalizeReadChatTailLimit(args) {
|
|
11256
|
+
const value = Number(args?.tailLimit || 0);
|
|
11257
|
+
return Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
12047
11258
|
}
|
|
12048
11259
|
function normalizeReadChatMessages(payload) {
|
|
12049
11260
|
const messages = Array.isArray(payload.messages) ? payload.messages : [];
|
|
12050
|
-
return
|
|
12051
|
-
}
|
|
12052
|
-
function normalizeReadChatReplayTextContent(content) {
|
|
12053
|
-
return flattenContent(content || "").replace(/\s+/g, " ").trim();
|
|
12054
|
-
}
|
|
12055
|
-
function getReadChatReplayCollapseInfo(message) {
|
|
12056
|
-
if (!message) return null;
|
|
12057
|
-
const role = typeof message.role === "string" ? message.role.trim().toLowerCase() : "";
|
|
12058
|
-
const kind = typeof message.kind === "string" ? message.kind.trim().toLowerCase() : "standard";
|
|
12059
|
-
const senderName = typeof message.senderName === "string" ? message.senderName.trim().toLowerCase() : "";
|
|
12060
|
-
const collapsible = role === "assistant" || role === "system";
|
|
12061
|
-
if (!collapsible) return { role, kind, senderName, content: "", signature: "", collapsible };
|
|
12062
|
-
const content = normalizeReadChatReplayTextContent(message.content);
|
|
12063
|
-
return {
|
|
12064
|
-
role,
|
|
12065
|
-
kind,
|
|
12066
|
-
senderName,
|
|
12067
|
-
content,
|
|
12068
|
-
signature: `${role}:${kind}:${senderName}:${content}`,
|
|
12069
|
-
collapsible
|
|
12070
|
-
};
|
|
12071
|
-
}
|
|
12072
|
-
function isStableReadChatAssistantAnswerInfo(info) {
|
|
12073
|
-
if (!info) return false;
|
|
12074
|
-
if (info.role !== "assistant") return false;
|
|
12075
|
-
if (info.kind && info.kind !== "standard") return false;
|
|
12076
|
-
if (info.content.length < 160) return false;
|
|
12077
|
-
if (/^(bash|shell|terminal) command\b/i.test(info.content)) return false;
|
|
12078
|
-
return true;
|
|
12079
|
-
}
|
|
12080
|
-
function isReplayedAssistantAnswerAfterStableAnswerInfo(info, stableContent) {
|
|
12081
|
-
if (!info || !stableContent) return false;
|
|
12082
|
-
if (info.role !== "assistant") return false;
|
|
12083
|
-
if (info.kind && info.kind !== "standard") return false;
|
|
12084
|
-
const content = info.content;
|
|
12085
|
-
if (content.length < 80 || stableContent.length < 80) return false;
|
|
12086
|
-
return content === stableContent || content.startsWith(stableContent) || stableContent.startsWith(content);
|
|
12087
|
-
}
|
|
12088
|
-
function collapseReplayDuplicatesFromReadChat(messages) {
|
|
12089
|
-
const collapsed = [];
|
|
12090
|
-
const replaySignaturesInCurrentTurn = /* @__PURE__ */ new Set();
|
|
12091
|
-
let stableAssistantAnswerContentInCurrentTurn = "";
|
|
12092
|
-
let stableAssistantAnswerCollapsedIndex = -1;
|
|
12093
|
-
let stableAssistantAnswerHadInterveningActivity = false;
|
|
12094
|
-
let previousReplaySignature = "";
|
|
12095
|
-
for (const message of messages) {
|
|
12096
|
-
const info = getReadChatReplayCollapseInfo(message);
|
|
12097
|
-
if (info?.role === "user") {
|
|
12098
|
-
replaySignaturesInCurrentTurn.clear();
|
|
12099
|
-
stableAssistantAnswerContentInCurrentTurn = "";
|
|
12100
|
-
stableAssistantAnswerCollapsedIndex = -1;
|
|
12101
|
-
stableAssistantAnswerHadInterveningActivity = false;
|
|
12102
|
-
previousReplaySignature = "";
|
|
12103
|
-
}
|
|
12104
|
-
if (info?.collapsible && info.signature) {
|
|
12105
|
-
if (previousReplaySignature === info.signature) continue;
|
|
12106
|
-
if (replaySignaturesInCurrentTurn.has(info.signature)) continue;
|
|
12107
|
-
if (isReplayedAssistantAnswerAfterStableAnswerInfo(info, stableAssistantAnswerContentInCurrentTurn)) {
|
|
12108
|
-
const isAdjacentFullerAssistantAnswer = info.role === "assistant" && (!info.kind || info.kind === "standard") && stableAssistantAnswerCollapsedIndex >= 0 && stableAssistantAnswerCollapsedIndex === collapsed.length - 1 && !stableAssistantAnswerHadInterveningActivity && info.content.length > stableAssistantAnswerContentInCurrentTurn.length && info.content.startsWith(stableAssistantAnswerContentInCurrentTurn);
|
|
12109
|
-
if (isAdjacentFullerAssistantAnswer) {
|
|
12110
|
-
collapsed[stableAssistantAnswerCollapsedIndex] = message;
|
|
12111
|
-
replaySignaturesInCurrentTurn.add(info.signature);
|
|
12112
|
-
stableAssistantAnswerContentInCurrentTurn = info.content;
|
|
12113
|
-
previousReplaySignature = info.signature;
|
|
12114
|
-
}
|
|
12115
|
-
continue;
|
|
12116
|
-
}
|
|
12117
|
-
}
|
|
12118
|
-
collapsed.push(message);
|
|
12119
|
-
previousReplaySignature = info?.collapsible ? info.signature : "";
|
|
12120
|
-
if (info?.collapsible && info.signature) {
|
|
12121
|
-
replaySignaturesInCurrentTurn.add(info.signature);
|
|
12122
|
-
}
|
|
12123
|
-
if (isStableReadChatAssistantAnswerInfo(info)) {
|
|
12124
|
-
stableAssistantAnswerContentInCurrentTurn = info?.content || "";
|
|
12125
|
-
stableAssistantAnswerCollapsedIndex = collapsed.length - 1;
|
|
12126
|
-
stableAssistantAnswerHadInterveningActivity = false;
|
|
12127
|
-
} else if (stableAssistantAnswerContentInCurrentTurn && info?.role === "assistant" && (!info.kind || info.kind !== "standard")) {
|
|
12128
|
-
stableAssistantAnswerHadInterveningActivity = true;
|
|
12129
|
-
}
|
|
12130
|
-
}
|
|
12131
|
-
return collapsed;
|
|
11261
|
+
return messages;
|
|
12132
11262
|
}
|
|
12133
11263
|
function deriveHistoryDedupKey(message) {
|
|
12134
11264
|
const unitKey = typeof message._unitKey === "string" ? message._unitKey.trim() : "";
|
|
@@ -12153,127 +11283,12 @@ function toHistoryPersistedMessages(messages) {
|
|
|
12153
11283
|
historyDedupKey: deriveHistoryDedupKey(message)
|
|
12154
11284
|
}));
|
|
12155
11285
|
}
|
|
12156
|
-
function
|
|
12157
|
-
if (!signature) return -1;
|
|
12158
|
-
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
12159
|
-
if (getChatMessageSignature(messages[index]) === signature) {
|
|
12160
|
-
return index;
|
|
12161
|
-
}
|
|
12162
|
-
}
|
|
12163
|
-
return -1;
|
|
12164
|
-
}
|
|
12165
|
-
function isReadChatConversationAnchorMessage(message) {
|
|
12166
|
-
if (!message) return false;
|
|
12167
|
-
const role = String(message.role || "").trim().toLowerCase();
|
|
12168
|
-
if (role !== "user" && role !== "assistant") return false;
|
|
12169
|
-
const kind = String(message.kind || "standard").trim().toLowerCase();
|
|
12170
|
-
return !kind || kind === "standard";
|
|
12171
|
-
}
|
|
12172
|
-
function buildVisibleReadChatTailMessages(messages, tailLimit) {
|
|
11286
|
+
function buildFullTail(messages, tailLimit) {
|
|
12173
11287
|
const totalMessages = messages.length;
|
|
12174
|
-
|
|
12175
|
-
const tailMessages = messages.slice(-tailLimit);
|
|
12176
|
-
if (tailMessages.some(isReadChatConversationAnchorMessage)) return tailMessages;
|
|
12177
|
-
const hiddenMessages = messages.slice(0, totalMessages - tailLimit);
|
|
12178
|
-
const anchors = [];
|
|
12179
|
-
const seenRoles = /* @__PURE__ */ new Set();
|
|
12180
|
-
for (let index = hiddenMessages.length - 1; index >= 0 && anchors.length < 2; index -= 1) {
|
|
12181
|
-
const message = hiddenMessages[index];
|
|
12182
|
-
if (!isReadChatConversationAnchorMessage(message)) continue;
|
|
12183
|
-
const role = String(message.role || "").trim().toLowerCase();
|
|
12184
|
-
if (seenRoles.has(role)) continue;
|
|
12185
|
-
seenRoles.add(role);
|
|
12186
|
-
anchors.unshift(message);
|
|
12187
|
-
}
|
|
12188
|
-
return anchors.length > 0 ? [...anchors, ...tailMessages] : tailMessages;
|
|
12189
|
-
}
|
|
12190
|
-
function buildBoundedTailSync(messages, cursor) {
|
|
12191
|
-
const totalMessages = messages.length;
|
|
12192
|
-
const tailMessages = buildVisibleReadChatTailMessages(messages, cursor.tailLimit);
|
|
11288
|
+
const tailMessages = tailLimit > 0 ? messages.slice(-tailLimit) : messages;
|
|
12193
11289
|
return {
|
|
12194
|
-
syncMode: "full",
|
|
12195
|
-
replaceFrom: 0,
|
|
12196
11290
|
messages: tailMessages,
|
|
12197
|
-
totalMessages
|
|
12198
|
-
lastMessageSignature: getChatMessageSignature(messages[totalMessages - 1])
|
|
12199
|
-
};
|
|
12200
|
-
}
|
|
12201
|
-
function computeReadChatSync(messages, cursor) {
|
|
12202
|
-
const totalMessages = messages.length;
|
|
12203
|
-
const lastMessageSignature = getChatMessageSignature(messages[totalMessages - 1]);
|
|
12204
|
-
const { knownMessageCount, lastMessageSignature: knownSignature } = cursor;
|
|
12205
|
-
if (!knownMessageCount || !knownSignature) {
|
|
12206
|
-
return {
|
|
12207
|
-
syncMode: "full",
|
|
12208
|
-
replaceFrom: 0,
|
|
12209
|
-
messages,
|
|
12210
|
-
totalMessages,
|
|
12211
|
-
lastMessageSignature
|
|
12212
|
-
};
|
|
12213
|
-
}
|
|
12214
|
-
if (knownMessageCount > totalMessages) {
|
|
12215
|
-
return {
|
|
12216
|
-
syncMode: "full",
|
|
12217
|
-
replaceFrom: 0,
|
|
12218
|
-
messages,
|
|
12219
|
-
totalMessages,
|
|
12220
|
-
lastMessageSignature
|
|
12221
|
-
};
|
|
12222
|
-
}
|
|
12223
|
-
if (knownMessageCount === totalMessages && knownSignature === lastMessageSignature) {
|
|
12224
|
-
return {
|
|
12225
|
-
syncMode: "noop",
|
|
12226
|
-
replaceFrom: totalMessages,
|
|
12227
|
-
messages: [],
|
|
12228
|
-
totalMessages,
|
|
12229
|
-
lastMessageSignature
|
|
12230
|
-
};
|
|
12231
|
-
}
|
|
12232
|
-
if (cursor.tailLimit > 0 && knownSignature === lastMessageSignature) {
|
|
12233
|
-
const requestedTailCount = Math.min(totalMessages, cursor.tailLimit);
|
|
12234
|
-
if (knownMessageCount >= requestedTailCount) {
|
|
12235
|
-
return {
|
|
12236
|
-
syncMode: "noop",
|
|
12237
|
-
replaceFrom: totalMessages,
|
|
12238
|
-
messages: [],
|
|
12239
|
-
totalMessages,
|
|
12240
|
-
lastMessageSignature
|
|
12241
|
-
};
|
|
12242
|
-
}
|
|
12243
|
-
return buildBoundedTailSync(messages, cursor);
|
|
12244
|
-
}
|
|
12245
|
-
if (knownMessageCount < totalMessages) {
|
|
12246
|
-
const anchorSignature = getChatMessageSignature(messages[knownMessageCount - 1]);
|
|
12247
|
-
if (anchorSignature === knownSignature) {
|
|
12248
|
-
return {
|
|
12249
|
-
syncMode: "append",
|
|
12250
|
-
replaceFrom: knownMessageCount,
|
|
12251
|
-
messages: messages.slice(knownMessageCount),
|
|
12252
|
-
totalMessages,
|
|
12253
|
-
lastMessageSignature
|
|
12254
|
-
};
|
|
12255
|
-
}
|
|
12256
|
-
if (cursor.tailLimit > 0) {
|
|
12257
|
-
const signatureIndex = findLastMessageIndexBySignature(messages, knownSignature);
|
|
12258
|
-
if (signatureIndex >= 0) {
|
|
12259
|
-
return {
|
|
12260
|
-
syncMode: "append",
|
|
12261
|
-
replaceFrom: knownMessageCount,
|
|
12262
|
-
messages: messages.slice(signatureIndex + 1),
|
|
12263
|
-
totalMessages,
|
|
12264
|
-
lastMessageSignature
|
|
12265
|
-
};
|
|
12266
|
-
}
|
|
12267
|
-
return buildBoundedTailSync(messages, cursor);
|
|
12268
|
-
}
|
|
12269
|
-
}
|
|
12270
|
-
const replaceFrom = Math.max(0, Math.min(knownMessageCount - 1, totalMessages));
|
|
12271
|
-
return {
|
|
12272
|
-
syncMode: replaceFrom === 0 ? "full" : "replace_tail",
|
|
12273
|
-
replaceFrom,
|
|
12274
|
-
messages: replaceFrom === 0 ? messages : messages.slice(replaceFrom),
|
|
12275
|
-
totalMessages,
|
|
12276
|
-
lastMessageSignature
|
|
11291
|
+
totalMessages
|
|
12277
11292
|
};
|
|
12278
11293
|
}
|
|
12279
11294
|
function hasNonEmptyModalButtons(activeModal) {
|
|
@@ -12308,31 +11323,13 @@ function buildReadChatCommandResult(payload, args) {
|
|
|
12308
11323
|
} catch (error) {
|
|
12309
11324
|
return { success: false, error: error?.message || String(error) };
|
|
12310
11325
|
}
|
|
12311
|
-
const messages =
|
|
12312
|
-
const
|
|
12313
|
-
if (!cursor.knownMessageCount && !cursor.lastMessageSignature && cursor.tailLimit > 0 && messages.length > cursor.tailLimit) {
|
|
12314
|
-
const tailMessages = buildVisibleReadChatTailMessages(messages, cursor.tailLimit);
|
|
12315
|
-
const lastMessageSignature = getChatMessageSignature(messages[messages.length - 1]);
|
|
12316
|
-
return {
|
|
12317
|
-
success: true,
|
|
12318
|
-
...validatedPayload,
|
|
12319
|
-
messages: tailMessages,
|
|
12320
|
-
syncMode: "full",
|
|
12321
|
-
replaceFrom: 0,
|
|
12322
|
-
totalMessages: messages.length,
|
|
12323
|
-
lastMessageSignature,
|
|
12324
|
-
...debugReadChat ? { debugReadChat } : {}
|
|
12325
|
-
};
|
|
12326
|
-
}
|
|
12327
|
-
const sync = computeReadChatSync(messages, cursor);
|
|
11326
|
+
const messages = normalizeReadChatMessages(validatedPayload);
|
|
11327
|
+
const sync = buildFullTail(messages, normalizeReadChatTailLimit(args));
|
|
12328
11328
|
return {
|
|
12329
11329
|
success: true,
|
|
12330
11330
|
...validatedPayload,
|
|
12331
11331
|
messages: sync.messages,
|
|
12332
|
-
syncMode: sync.syncMode,
|
|
12333
|
-
replaceFrom: sync.replaceFrom,
|
|
12334
11332
|
totalMessages: sync.totalMessages,
|
|
12335
|
-
lastMessageSignature: sync.lastMessageSignature,
|
|
12336
11333
|
...debugReadChat ? { debugReadChat } : {}
|
|
12337
11334
|
};
|
|
12338
11335
|
}
|
|
@@ -12557,10 +11554,6 @@ async function handleGetChatDebugBundle(h, args) {
|
|
|
12557
11554
|
status: readResult.status,
|
|
12558
11555
|
title: readResult.title,
|
|
12559
11556
|
totalMessages: readResult.totalMessages,
|
|
12560
|
-
returnedMessages: Array.isArray(readResult.messages) ? readResult.messages.length : void 0,
|
|
12561
|
-
syncMode: readResult.syncMode,
|
|
12562
|
-
replaceFrom: readResult.replaceFrom,
|
|
12563
|
-
lastMessageSignature: readResult.lastMessageSignature,
|
|
12564
11557
|
providerSessionId: readResult.providerSessionId,
|
|
12565
11558
|
transcriptAuthority: readResult.transcriptAuthority,
|
|
12566
11559
|
coverage: readResult.coverage,
|
|
@@ -12670,22 +11663,13 @@ function toNonNegativeNumber(value) {
|
|
|
12670
11663
|
return Number.isFinite(numeric) ? Math.max(0, numeric) : 0;
|
|
12671
11664
|
}
|
|
12672
11665
|
function getCliVisibleTranscriptCount(adapter) {
|
|
12673
|
-
|
|
12674
|
-
|
|
12675
|
-
|
|
12676
|
-
|
|
12677
|
-
|
|
12678
|
-
|
|
12679
|
-
parsedRecord = parsed && typeof parsed === "object" ? parsed : null;
|
|
12680
|
-
} catch {
|
|
12681
|
-
parsedRecord = null;
|
|
12682
|
-
}
|
|
11666
|
+
if (typeof adapter?.getScriptParsedStatus !== "function") return 0;
|
|
11667
|
+
try {
|
|
11668
|
+
const parsed = parseMaybeJson(adapter.getScriptParsedStatus());
|
|
11669
|
+
return Array.isArray(parsed?.messages) ? parsed.messages.length : 0;
|
|
11670
|
+
} catch {
|
|
11671
|
+
return 0;
|
|
12683
11672
|
}
|
|
12684
|
-
const parsedMessages = Array.isArray(parsedRecord?.messages) ? parsedRecord.messages : [];
|
|
12685
|
-
if (!parsedRecord) return adapterMessages.length;
|
|
12686
|
-
const parsedIsProviderAuthoritative = parsedRecord.transcriptAuthority === "provider" || parsedRecord.coverage === "full";
|
|
12687
|
-
const shouldPreferAdapterMessages = !parsedIsProviderAuthoritative && adapterMessages.length > 0 && adapterMessages.length > parsedMessages.length;
|
|
12688
|
-
return shouldPreferAdapterMessages ? adapterMessages.length : parsedMessages.length;
|
|
12689
11673
|
}
|
|
12690
11674
|
async function getStableExtensionBaseline(h) {
|
|
12691
11675
|
const first = await readExtensionChatState(h);
|
|
@@ -12747,52 +11731,46 @@ async function handleReadChat(h, args) {
|
|
|
12747
11731
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
12748
11732
|
if (adapter) {
|
|
12749
11733
|
_log(`${transport} adapter: ${adapter.cliType}`);
|
|
11734
|
+
if (typeof adapter.getScriptParsedStatus !== "function") {
|
|
11735
|
+
return { success: false, error: `${transport} adapter parseSession unavailable` };
|
|
11736
|
+
}
|
|
12750
11737
|
let parsedStatus = null;
|
|
12751
|
-
|
|
12752
|
-
|
|
12753
|
-
|
|
12754
|
-
|
|
12755
|
-
return { success: false, error: error?.message || String(error) };
|
|
12756
|
-
}
|
|
11738
|
+
try {
|
|
11739
|
+
parsedStatus = parseMaybeJson(adapter.getScriptParsedStatus());
|
|
11740
|
+
} catch (error) {
|
|
11741
|
+
return { success: false, error: error?.message || String(error) };
|
|
12757
11742
|
}
|
|
12758
11743
|
const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
|
|
12759
|
-
|
|
12760
|
-
|
|
12761
|
-
|
|
12762
|
-
const
|
|
12763
|
-
const
|
|
12764
|
-
|
|
12765
|
-
|
|
12766
|
-
|
|
12767
|
-
|
|
12768
|
-
|
|
12769
|
-
|
|
12770
|
-
|
|
12771
|
-
|
|
12772
|
-
|
|
12773
|
-
|
|
12774
|
-
|
|
12775
|
-
|
|
12776
|
-
|
|
12777
|
-
|
|
12778
|
-
|
|
12779
|
-
|
|
12780
|
-
|
|
12781
|
-
|
|
12782
|
-
|
|
12783
|
-
|
|
12784
|
-
|
|
12785
|
-
|
|
12786
|
-
|
|
12787
|
-
|
|
12788
|
-
|
|
12789
|
-
},
|
|
12790
|
-
...title ? { title } : {},
|
|
12791
|
-
...providerSessionId ? { providerSessionId } : {},
|
|
12792
|
-
...transcriptAuthority ? { transcriptAuthority } : {},
|
|
12793
|
-
...coverage ? { coverage } : {}
|
|
12794
|
-
}, args);
|
|
12795
|
-
}
|
|
11744
|
+
if (!parsedRecord || !Array.isArray(parsedRecord.messages)) {
|
|
11745
|
+
return { success: false, error: `${transport} parser did not return messages` };
|
|
11746
|
+
}
|
|
11747
|
+
const adapterStatus = typeof adapter.getStatus === "function" ? adapter.getStatus() : {};
|
|
11748
|
+
const title = typeof parsedRecord.title === "string" ? parsedRecord.title : void 0;
|
|
11749
|
+
const providerSessionId = typeof parsedRecord.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
|
|
11750
|
+
const transcriptAuthority = parsedRecord.transcriptAuthority === "provider" || parsedRecord.transcriptAuthority === "daemon" ? parsedRecord.transcriptAuthority : void 0;
|
|
11751
|
+
const coverage = parsedRecord.coverage === "full" || parsedRecord.coverage === "tail" || parsedRecord.coverage === "current-turn" ? parsedRecord.coverage : void 0;
|
|
11752
|
+
const activeModal = parsedRecord.activeModal ?? parsedRecord.modal ?? null;
|
|
11753
|
+
const returnedStatus = parsedRecord.status || "idle";
|
|
11754
|
+
LOG.debug("Command", `[read_chat] cli-like parsed provider=${adapter.cliType} target=${String(args?.targetSessionId || "")} adapterStatus=${String(adapterStatus.status || "")} parsedStatus=${String(parsedRecord.status || "")} parsedMsgCount=${parsedRecord.messages.length}`);
|
|
11755
|
+
return buildReadChatCommandResult({
|
|
11756
|
+
messages: parsedRecord.messages,
|
|
11757
|
+
status: returnedStatus,
|
|
11758
|
+
activeModal,
|
|
11759
|
+
debugReadChat: {
|
|
11760
|
+
provider: adapter.cliType,
|
|
11761
|
+
targetSessionId: String(args?.targetSessionId || ""),
|
|
11762
|
+
adapterStatus: String(adapterStatus.status || ""),
|
|
11763
|
+
parsedStatus: String(parsedRecord.status || ""),
|
|
11764
|
+
returnedStatus: String(returnedStatus || ""),
|
|
11765
|
+
shouldPreferAdapterMessages: false,
|
|
11766
|
+
parsedMsgCount: parsedRecord.messages.length,
|
|
11767
|
+
returnedMsgCount: parsedRecord.messages.length
|
|
11768
|
+
},
|
|
11769
|
+
...title ? { title } : {},
|
|
11770
|
+
...providerSessionId ? { providerSessionId } : {},
|
|
11771
|
+
...transcriptAuthority ? { transcriptAuthority } : {},
|
|
11772
|
+
...coverage ? { coverage } : {}
|
|
11773
|
+
}, args);
|
|
12796
11774
|
}
|
|
12797
11775
|
return { success: false, error: `${transport} adapter not found` };
|
|
12798
11776
|
}
|
|
@@ -15091,7 +14069,6 @@ import chalk from "chalk";
|
|
|
15091
14069
|
init_config();
|
|
15092
14070
|
|
|
15093
14071
|
// src/providers/cli-provider-instance.ts
|
|
15094
|
-
init_contracts();
|
|
15095
14072
|
import * as os12 from "os";
|
|
15096
14073
|
import * as path15 from "path";
|
|
15097
14074
|
import * as crypto3 from "crypto";
|
|
@@ -15118,7 +14095,6 @@ function normalizeProviderSessionId(provider, providerSessionId) {
|
|
|
15118
14095
|
}
|
|
15119
14096
|
|
|
15120
14097
|
// src/providers/cli-provider-instance.ts
|
|
15121
|
-
init_chat_message_normalization();
|
|
15122
14098
|
function normalizePersistableCliHistoryContent(content) {
|
|
15123
14099
|
return flattenContent(content).replace(/\s+/g, " ").trim();
|
|
15124
14100
|
}
|
|
@@ -15358,17 +14334,11 @@ var CliProviderInstance = class {
|
|
|
15358
14334
|
}
|
|
15359
14335
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
15360
14336
|
this.maybeAppendRuntimeRecoveryMessage(runtime);
|
|
15361
|
-
let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages :
|
|
14337
|
+
let parsedMessages = Array.isArray(parsedStatus?.messages) ? parsedStatus.messages : [];
|
|
15362
14338
|
const historyMessageCount = Number.isFinite(parsedStatus?.historyMessageCount) ? Math.max(0, Number(parsedStatus.historyMessageCount)) : null;
|
|
15363
14339
|
if (historyMessageCount !== null) {
|
|
15364
14340
|
parsedMessages = historyMessageCount > 0 ? parsedMessages.slice(-historyMessageCount) : [];
|
|
15365
14341
|
}
|
|
15366
|
-
const committedMessages = Array.isArray(adapterStatus.messages) ? adapterStatus.messages : [];
|
|
15367
|
-
const isActiveNonIdle = adapterStatus.status !== "idle";
|
|
15368
|
-
const shouldApplyCommittedFloor = parsedMessages.length < committedMessages.length && (adapterStatus.status === "waiting_approval" || isActiveNonIdle && historyMessageCount === null);
|
|
15369
|
-
if (shouldApplyCommittedFloor) {
|
|
15370
|
-
parsedMessages = normalizeChatMessages(committedMessages);
|
|
15371
|
-
}
|
|
15372
14342
|
const mergedMessages = this.mergeConversationMessages(parsedMessages);
|
|
15373
14343
|
const canonicalBackedHistory = this.syncCanonicalSavedHistoryIfNeeded();
|
|
15374
14344
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
@@ -15461,11 +14431,9 @@ var CliProviderInstance = class {
|
|
|
15461
14431
|
const autoApproveActive = adapterStatus.status === "waiting_approval" && this.shouldAutoApprove();
|
|
15462
14432
|
const visibleStatus = autoApproveActive ? "generating" : adapterStatus.status;
|
|
15463
14433
|
const runtime = this.adapter.getRuntimeMetadata();
|
|
15464
|
-
const lastCommittedMessageActivityAt = typeof this.adapter.getLastCommittedMessageActivityAt === "function" ? this.adapter.getLastCommittedMessageActivityAt() : 0;
|
|
15465
14434
|
return {
|
|
15466
14435
|
id: this.instanceId,
|
|
15467
14436
|
status: visibleStatus,
|
|
15468
|
-
lastMessageAt: lastCommittedMessageActivityAt || void 0,
|
|
15469
14437
|
runtimeLifecycle: runtime?.lifecycle ?? null,
|
|
15470
14438
|
runtimeSurfaceKind: runtime?.surfaceKind,
|
|
15471
14439
|
runtimeRestoredFromStorage: runtime?.restoredFromStorage === true,
|
|
@@ -15571,7 +14539,7 @@ var CliProviderInstance = class {
|
|
|
15571
14539
|
const dirName = this.workingDir.split("/").filter(Boolean).pop() || "session";
|
|
15572
14540
|
const chatTitle = `${this.provider.name} \xB7 ${dirName}`;
|
|
15573
14541
|
const partial = this.adapter.getPartialResponse();
|
|
15574
|
-
const progressFingerprint = newStatus === "generating" ? `${partial || ""}
|
|
14542
|
+
const progressFingerprint = newStatus === "generating" ? `${partial || ""}`.slice(-2e3) : void 0;
|
|
15575
14543
|
const previousStatus = this.lastStatus;
|
|
15576
14544
|
if (newStatus !== this.lastStatus) {
|
|
15577
14545
|
LOG.info("CLI", `[${this.type}] status: ${this.lastStatus} \u2192 ${newStatus}`);
|
|
@@ -16017,18 +14985,6 @@ ${effect.notification.body || ""}`.trim();
|
|
|
16017
14985
|
receivedAt: message.receivedAt
|
|
16018
14986
|
}));
|
|
16019
14987
|
this.suppressIdleHistoryReplay = restoredHistory.messages.length > 0;
|
|
16020
|
-
if (restoredHistory.messages.length > 0) {
|
|
16021
|
-
this.adapter.seedCommittedMessages(
|
|
16022
|
-
restoredHistory.messages.map((message) => ({
|
|
16023
|
-
role: message.role,
|
|
16024
|
-
content: message.content,
|
|
16025
|
-
timestamp: message.receivedAt,
|
|
16026
|
-
receivedAt: message.receivedAt,
|
|
16027
|
-
kind: message.kind,
|
|
16028
|
-
senderName: message.senderName
|
|
16029
|
-
}))
|
|
16030
|
-
);
|
|
16031
|
-
}
|
|
16032
14988
|
}
|
|
16033
14989
|
getProbeDirectories() {
|
|
16034
14990
|
const dirs = /* @__PURE__ */ new Set();
|
|
@@ -16075,7 +15031,6 @@ ${effect.notification.body || ""}`.trim();
|
|
|
16075
15031
|
};
|
|
16076
15032
|
|
|
16077
15033
|
// src/providers/acp-provider-instance.ts
|
|
16078
|
-
init_contracts();
|
|
16079
15034
|
import { Readable, Writable } from "stream";
|
|
16080
15035
|
import { spawn } from "child_process";
|
|
16081
15036
|
import {
|
|
@@ -16084,7 +15039,6 @@ import {
|
|
|
16084
15039
|
RequestError,
|
|
16085
15040
|
PROTOCOL_VERSION
|
|
16086
15041
|
} from "@agentclientprotocol/sdk";
|
|
16087
|
-
init_chat_message_normalization();
|
|
16088
15042
|
init_logger();
|
|
16089
15043
|
function getPromptCapabilityFlags(agentCapabilities) {
|
|
16090
15044
|
const prompt = agentCapabilities?.promptCapabilities || {};
|
|
@@ -17228,7 +16182,6 @@ ${rawInput}` : rawInput;
|
|
|
17228
16182
|
};
|
|
17229
16183
|
|
|
17230
16184
|
// src/commands/cli-manager.ts
|
|
17231
|
-
init_contracts();
|
|
17232
16185
|
init_logger();
|
|
17233
16186
|
|
|
17234
16187
|
// src/commands/hosted-runtime-restore.ts
|
|
@@ -20162,13 +19115,24 @@ async function launchWithCdp(options = {}) {
|
|
|
20162
19115
|
break;
|
|
20163
19116
|
}
|
|
20164
19117
|
}
|
|
19118
|
+
if (!cdpReady) {
|
|
19119
|
+
return {
|
|
19120
|
+
success: false,
|
|
19121
|
+
ideId: targetIde.id,
|
|
19122
|
+
ideName: targetIde.displayName,
|
|
19123
|
+
port,
|
|
19124
|
+
action: "failed",
|
|
19125
|
+
message: "",
|
|
19126
|
+
error: `${targetIde.displayName} launched but CDP did not become available on port ${port}`
|
|
19127
|
+
};
|
|
19128
|
+
}
|
|
20165
19129
|
return {
|
|
20166
19130
|
success: true,
|
|
20167
19131
|
ideId: targetIde.id,
|
|
20168
19132
|
ideName: targetIde.displayName,
|
|
20169
19133
|
port,
|
|
20170
19134
|
action: alreadyRunning ? "restarted" : "started",
|
|
20171
|
-
message:
|
|
19135
|
+
message: `${targetIde.displayName} launched with CDP on port ${port}`
|
|
20172
19136
|
};
|
|
20173
19137
|
} catch (e) {
|
|
20174
19138
|
return {
|
|
@@ -22096,9 +21060,6 @@ var DEFAULT_DAEMON_PORT = 19222;
|
|
|
22096
21060
|
var DAEMON_WS_PATH = "/ipc";
|
|
22097
21061
|
|
|
22098
21062
|
// src/chat/subscription-updates.ts
|
|
22099
|
-
function normalizeSyncMode(syncMode) {
|
|
22100
|
-
return syncMode === "append" || syncMode === "replace_tail" || syncMode === "noop" || syncMode === "full" ? syncMode : "full";
|
|
22101
|
-
}
|
|
22102
21063
|
function normalizeModalButtons(value) {
|
|
22103
21064
|
return Array.isArray(value) ? value.filter((button) => typeof button === "string") : [];
|
|
22104
21065
|
}
|
|
@@ -22125,55 +21086,39 @@ function normalizeSessionModalFields(activeModal) {
|
|
|
22125
21086
|
modalButtons: normalizeModalButtons(activeModal.buttons)
|
|
22126
21087
|
};
|
|
22127
21088
|
}
|
|
22128
|
-
function buildNextChatCursor(cursor, result) {
|
|
22129
|
-
return {
|
|
22130
|
-
knownMessageCount: Math.max(0, Number(result.totalMessages || cursor.knownMessageCount)),
|
|
22131
|
-
lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : cursor.lastMessageSignature,
|
|
22132
|
-
tailLimit: cursor.tailLimit
|
|
22133
|
-
};
|
|
22134
|
-
}
|
|
22135
21089
|
function prepareSessionChatTailUpdate(input) {
|
|
22136
21090
|
const result = input.result;
|
|
22137
|
-
if (!result?.success
|
|
21091
|
+
if (!result?.success) {
|
|
22138
21092
|
return {
|
|
22139
|
-
cursor:
|
|
21093
|
+
cursor: input.cursor,
|
|
22140
21094
|
seq: input.seq,
|
|
22141
21095
|
lastDeliveredSignature: input.lastDeliveredSignature,
|
|
22142
21096
|
update: null
|
|
22143
21097
|
};
|
|
22144
21098
|
}
|
|
22145
|
-
const
|
|
22146
|
-
const cursor = {
|
|
22147
|
-
knownMessageCount: Math.max(0, Number(result.totalMessages || 0)),
|
|
22148
|
-
lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : "",
|
|
22149
|
-
tailLimit: input.cursor.tailLimit
|
|
22150
|
-
};
|
|
21099
|
+
const messages = Array.isArray(result.messages) ? result.messages : [];
|
|
22151
21100
|
const title = typeof result.title === "string" ? result.title : void 0;
|
|
22152
21101
|
const activeModal = normalizeChatTailActiveModal(result.activeModal);
|
|
22153
21102
|
const status = typeof result.status === "string" ? result.status : "idle";
|
|
22154
21103
|
const deliverySignature = buildChatTailDeliverySignature({
|
|
22155
21104
|
sessionId: input.sessionId,
|
|
22156
21105
|
...input.historySessionId ? { historySessionId: input.historySessionId } : {},
|
|
22157
|
-
messages
|
|
21106
|
+
messages,
|
|
22158
21107
|
status,
|
|
22159
21108
|
...title ? { title } : {},
|
|
22160
|
-
...activeModal ? { activeModal } : {}
|
|
22161
|
-
syncMode,
|
|
22162
|
-
replaceFrom: Number(result.replaceFrom || 0),
|
|
22163
|
-
totalMessages: Number(result.totalMessages || 0),
|
|
22164
|
-
lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
|
|
21109
|
+
...activeModal ? { activeModal } : {}
|
|
22165
21110
|
});
|
|
22166
21111
|
const seq = input.seq + 1;
|
|
22167
21112
|
if (deliverySignature === input.lastDeliveredSignature) {
|
|
22168
21113
|
return {
|
|
22169
|
-
cursor,
|
|
21114
|
+
cursor: input.cursor,
|
|
22170
21115
|
seq,
|
|
22171
21116
|
lastDeliveredSignature: input.lastDeliveredSignature,
|
|
22172
21117
|
update: null
|
|
22173
21118
|
};
|
|
22174
21119
|
}
|
|
22175
21120
|
return {
|
|
22176
|
-
cursor,
|
|
21121
|
+
cursor: input.cursor,
|
|
22177
21122
|
seq,
|
|
22178
21123
|
lastDeliveredSignature: deliverySignature,
|
|
22179
21124
|
update: {
|
|
@@ -22184,14 +21129,10 @@ function prepareSessionChatTailUpdate(input) {
|
|
|
22184
21129
|
...input.interactionId ? { interactionId: input.interactionId } : {},
|
|
22185
21130
|
seq,
|
|
22186
21131
|
timestamp: input.timestamp,
|
|
22187
|
-
messages
|
|
21132
|
+
messages,
|
|
22188
21133
|
status,
|
|
22189
21134
|
...title ? { title } : {},
|
|
22190
|
-
...activeModal ? { activeModal } : {}
|
|
22191
|
-
syncMode,
|
|
22192
|
-
replaceFrom: Number(result.replaceFrom || 0),
|
|
22193
|
-
totalMessages: Number(result.totalMessages || 0),
|
|
22194
|
-
lastMessageSignature: typeof result.lastMessageSignature === "string" ? result.lastMessageSignature : ""
|
|
21135
|
+
...activeModal ? { activeModal } : {}
|
|
22195
21136
|
}
|
|
22196
21137
|
};
|
|
22197
21138
|
}
|
|
@@ -22251,8 +21192,6 @@ async function runAsyncBatch(items, worker, options = {}) {
|
|
|
22251
21192
|
}
|
|
22252
21193
|
|
|
22253
21194
|
// src/agent-stream/provider-adapter.ts
|
|
22254
|
-
init_read_chat_contract();
|
|
22255
|
-
init_chat_message_normalization();
|
|
22256
21195
|
var ProviderStreamAdapter = class {
|
|
22257
21196
|
agentType;
|
|
22258
21197
|
agentName;
|
|
@@ -22937,7 +21876,6 @@ var DaemonAgentStreamManager = class {
|
|
|
22937
21876
|
|
|
22938
21877
|
// src/agent-stream/poller.ts
|
|
22939
21878
|
init_logger();
|
|
22940
|
-
init_chat_message_normalization();
|
|
22941
21879
|
var AgentStreamPoller = class {
|
|
22942
21880
|
deps;
|
|
22943
21881
|
timer = null;
|
|
@@ -23416,10 +22354,6 @@ var ProviderInstanceManager = class {
|
|
|
23416
22354
|
}
|
|
23417
22355
|
};
|
|
23418
22356
|
|
|
23419
|
-
// src/index.ts
|
|
23420
|
-
init_io_contracts();
|
|
23421
|
-
init_chat_message_normalization();
|
|
23422
|
-
|
|
23423
22357
|
// src/providers/version-archive.ts
|
|
23424
22358
|
import * as fs11 from "fs";
|
|
23425
22359
|
import * as path21 from "path";
|
|
@@ -26857,7 +25791,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26857
25791
|
lines.push("Provider category: `cli`");
|
|
26858
25792
|
lines.push("");
|
|
26859
25793
|
const funcToFile = {
|
|
26860
|
-
|
|
25794
|
+
parseSession: "parse_session.js",
|
|
26861
25795
|
detectStatus: "detect_status.js",
|
|
26862
25796
|
parseApproval: "parse_approval.js"
|
|
26863
25797
|
};
|
|
@@ -26946,7 +25880,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
26946
25880
|
lines.push("");
|
|
26947
25881
|
lines.push("| Function | Input | Return |");
|
|
26948
25882
|
lines.push("|---|---|---|");
|
|
26949
|
-
lines.push("| `
|
|
25883
|
+
lines.push("| `parseSession` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |");
|
|
26950
25884
|
lines.push("| `detectStatus` | `{ tail, screenText, rawBuffer }` | `idle`, `generating`, `waiting_approval`, or `error` |");
|
|
26951
25885
|
lines.push("| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |");
|
|
26952
25886
|
lines.push("");
|
|
@@ -27166,7 +26100,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
27166
26100
|
lines.push("");
|
|
27167
26101
|
lines.push("## Required Validation");
|
|
27168
26102
|
lines.push("1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.");
|
|
27169
|
-
lines.push("2. Confirm `
|
|
26103
|
+
lines.push("2. Confirm `parseSession` produces a stable transcript without duplicating past turns when the PTY redraws.");
|
|
27170
26104
|
lines.push("3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.");
|
|
27171
26105
|
lines.push("4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.");
|
|
27172
26106
|
lines.push("5. Confirm the Python file was actually created and executed, not just described in chat text.");
|
|
@@ -28436,7 +27370,7 @@ var DevServer = class _DevServer {
|
|
|
28436
27370
|
lines.push("Provider category: `cli`");
|
|
28437
27371
|
lines.push("");
|
|
28438
27372
|
const funcToFile = {
|
|
28439
|
-
|
|
27373
|
+
parseSession: "parse_session.js",
|
|
28440
27374
|
detectStatus: "detect_status.js",
|
|
28441
27375
|
parseApproval: "parse_approval.js"
|
|
28442
27376
|
};
|
|
@@ -28525,7 +27459,7 @@ var DevServer = class _DevServer {
|
|
|
28525
27459
|
lines.push("");
|
|
28526
27460
|
lines.push("| Function | Input | Return |");
|
|
28527
27461
|
lines.push("|---|---|---|");
|
|
28528
|
-
lines.push("| `
|
|
27462
|
+
lines.push("| `parseSession` | `{ buffer, rawBuffer, recentBuffer, screenText, messages, partialResponse }` | `{ id, status, title, messages, activeModal }` |");
|
|
28529
27463
|
lines.push("| `detectStatus` | `{ tail, screenText, rawBuffer }` | `idle`, `generating`, `waiting_approval`, or `error` |");
|
|
28530
27464
|
lines.push("| `parseApproval` | `{ buffer, rawBuffer, tail }` | `{ message, buttons }` or `null` |");
|
|
28531
27465
|
lines.push("");
|
|
@@ -28620,7 +27554,7 @@ var DevServer = class _DevServer {
|
|
|
28620
27554
|
lines.push("");
|
|
28621
27555
|
lines.push("## Required Validation");
|
|
28622
27556
|
lines.push("1. Confirm `detectStatus` changes sensibly between startup, generating, approval, and idle.");
|
|
28623
|
-
lines.push("2. Confirm `
|
|
27557
|
+
lines.push("2. Confirm `parseSession` produces a stable transcript without duplicating past turns when the PTY redraws.");
|
|
28624
27558
|
lines.push("3. Confirm the latest assistant message streams through `partialResponse` while generation is in progress.");
|
|
28625
27559
|
lines.push("4. Confirm approval parsing returns meaningful button labels when the CLI requests permission.");
|
|
28626
27560
|
lines.push("5. Confirm the Python file was actually created and executed, not just described in chat text.");
|