@adhdev/daemon-core 0.8.65 → 0.8.66
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/index.js +937 -625
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +937 -625
- package/dist/index.mjs.map +1 -1
- package/dist/providers/extension-provider-instance.d.ts +5 -3
- package/dist/providers/provider-input-support.d.ts +9 -0
- package/dist/providers/read-chat-contract.d.ts +2 -0
- package/node_modules/@adhdev/session-host-core/package.json +2 -2
- package/package.json +2 -2
- package/src/agent-stream/provider-adapter.ts +15 -9
- package/src/cli-adapters/provider-cli-adapter.ts +4 -0
- package/src/commands/chat-commands.ts +75 -26
- package/src/commands/cli-manager.ts +7 -0
- package/src/commands/stream-commands.ts +2 -2
- package/src/providers/acp-provider-instance.ts +39 -55
- package/src/providers/cli-provider-instance.ts +2 -0
- package/src/providers/control-effects.ts +21 -29
- package/src/providers/extension-provider-instance.ts +35 -6
- package/src/providers/ide-provider-instance.ts +2 -1
- package/src/providers/provider-input-support.ts +71 -0
- package/src/providers/provider-schema.ts +60 -1
- package/src/providers/read-chat-contract.ts +136 -0
package/dist/index.js
CHANGED
|
@@ -458,6 +458,231 @@ var init_logger = __esm({
|
|
|
458
458
|
}
|
|
459
459
|
});
|
|
460
460
|
|
|
461
|
+
// src/providers/io-contracts.ts
|
|
462
|
+
function normalizeInputEnvelope(input) {
|
|
463
|
+
const normalized = normalizeInputEnvelopePayload(input);
|
|
464
|
+
const textFallback = normalized.textFallback ?? flattenInputParts(normalized.parts);
|
|
465
|
+
return {
|
|
466
|
+
parts: normalized.parts,
|
|
467
|
+
textFallback,
|
|
468
|
+
...normalized.metadata ? { metadata: normalized.metadata } : {}
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
function normalizeMessageParts(content) {
|
|
472
|
+
if (typeof content === "string") return [{ type: "text", text: content }];
|
|
473
|
+
if (!Array.isArray(content)) {
|
|
474
|
+
if (content && typeof content === "object" && typeof content.text === "string") {
|
|
475
|
+
return [{ type: "text", text: String(content.text) }];
|
|
476
|
+
}
|
|
477
|
+
return [];
|
|
478
|
+
}
|
|
479
|
+
const parts = [];
|
|
480
|
+
for (const raw of content) {
|
|
481
|
+
if (typeof raw === "string") {
|
|
482
|
+
parts.push({ type: "text", text: raw });
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
if (!raw || typeof raw !== "object") continue;
|
|
486
|
+
const part = normalizeMessagePartObject(raw);
|
|
487
|
+
if (part) parts.push(part);
|
|
488
|
+
}
|
|
489
|
+
return parts;
|
|
490
|
+
}
|
|
491
|
+
function flattenMessageParts(parts) {
|
|
492
|
+
return parts.map((part) => {
|
|
493
|
+
if (part.type === "text") return part.text;
|
|
494
|
+
if (part.type === "resource") return part.resource.text || "";
|
|
495
|
+
return "";
|
|
496
|
+
}).filter((value) => value.length > 0).join("\n");
|
|
497
|
+
}
|
|
498
|
+
function normalizeInputEnvelopePayload(input) {
|
|
499
|
+
if (typeof input === "string") {
|
|
500
|
+
return { parts: [{ type: "text", text: input }], textFallback: input };
|
|
501
|
+
}
|
|
502
|
+
if (!input || typeof input !== "object") {
|
|
503
|
+
return { parts: [], textFallback: "" };
|
|
504
|
+
}
|
|
505
|
+
const record = input;
|
|
506
|
+
const nestedInput = record.input;
|
|
507
|
+
if (nestedInput && typeof nestedInput === "object") {
|
|
508
|
+
const nested = nestedInput;
|
|
509
|
+
return {
|
|
510
|
+
parts: normalizeInputParts(nested.parts ?? nested.prompt),
|
|
511
|
+
textFallback: typeof nested.textFallback === "string" ? nested.textFallback : void 0,
|
|
512
|
+
metadata: normalizeInputMetadata(nested.metadata)
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
const directText = typeof record.text === "string" ? record.text : typeof record.message === "string" ? record.message : void 0;
|
|
516
|
+
if (directText !== void 0) {
|
|
517
|
+
return { parts: [{ type: "text", text: directText }], textFallback: directText };
|
|
518
|
+
}
|
|
519
|
+
const directParts = normalizeInputParts(record.parts ?? record.prompt);
|
|
520
|
+
return {
|
|
521
|
+
parts: directParts,
|
|
522
|
+
textFallback: typeof record.textFallback === "string" ? record.textFallback : void 0,
|
|
523
|
+
metadata: normalizeInputMetadata(record.metadata)
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
function normalizeInputMetadata(value) {
|
|
527
|
+
if (!value || typeof value !== "object") return void 0;
|
|
528
|
+
const record = value;
|
|
529
|
+
const metadata = {};
|
|
530
|
+
if (record.source === "dashboard" || record.source === "shortcut_api" || record.source === "provider_script" || record.source === "session_replay") {
|
|
531
|
+
metadata.source = record.source;
|
|
532
|
+
}
|
|
533
|
+
if (typeof record.clientTimestamp === "number" && Number.isFinite(record.clientTimestamp)) {
|
|
534
|
+
metadata.clientTimestamp = record.clientTimestamp;
|
|
535
|
+
}
|
|
536
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
537
|
+
}
|
|
538
|
+
function normalizeInputParts(value) {
|
|
539
|
+
if (!Array.isArray(value)) return [];
|
|
540
|
+
const parts = [];
|
|
541
|
+
for (const raw of value) {
|
|
542
|
+
if (typeof raw === "string") {
|
|
543
|
+
parts.push({ type: "text", text: raw });
|
|
544
|
+
continue;
|
|
545
|
+
}
|
|
546
|
+
if (!raw || typeof raw !== "object") continue;
|
|
547
|
+
const part = normalizeInputPartObject(raw);
|
|
548
|
+
if (part) parts.push(part);
|
|
549
|
+
}
|
|
550
|
+
return parts;
|
|
551
|
+
}
|
|
552
|
+
function normalizeInputPartObject(raw) {
|
|
553
|
+
const type = raw.type;
|
|
554
|
+
if (type === "text" && typeof raw.text === "string") {
|
|
555
|
+
return { type, text: raw.text };
|
|
556
|
+
}
|
|
557
|
+
if (type === "image" && typeof raw.mimeType === "string") {
|
|
558
|
+
return {
|
|
559
|
+
type,
|
|
560
|
+
mimeType: raw.mimeType,
|
|
561
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
562
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
563
|
+
...typeof raw.alt === "string" ? { alt: raw.alt } : {}
|
|
564
|
+
};
|
|
565
|
+
}
|
|
566
|
+
if (type === "audio" && typeof raw.mimeType === "string") {
|
|
567
|
+
return {
|
|
568
|
+
type,
|
|
569
|
+
mimeType: raw.mimeType,
|
|
570
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
571
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
572
|
+
...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
if (type === "video" && typeof raw.mimeType === "string") {
|
|
576
|
+
return {
|
|
577
|
+
type,
|
|
578
|
+
mimeType: raw.mimeType,
|
|
579
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
580
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
581
|
+
...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
|
|
582
|
+
};
|
|
583
|
+
}
|
|
584
|
+
if (type === "resource" && typeof raw.uri === "string") {
|
|
585
|
+
return {
|
|
586
|
+
type,
|
|
587
|
+
uri: raw.uri,
|
|
588
|
+
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
589
|
+
...typeof raw.name === "string" ? { name: raw.name } : {},
|
|
590
|
+
...typeof raw.text === "string" ? { text: raw.text } : {},
|
|
591
|
+
...typeof raw.data === "string" ? { data: raw.data } : {}
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
if (type === "resource_link" && typeof raw.uri === "string") {
|
|
595
|
+
return {
|
|
596
|
+
type: "resource",
|
|
597
|
+
uri: raw.uri,
|
|
598
|
+
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
599
|
+
...typeof raw.name === "string" ? { name: raw.name } : {}
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
return null;
|
|
603
|
+
}
|
|
604
|
+
function normalizeMessagePartObject(raw) {
|
|
605
|
+
const type = raw.type;
|
|
606
|
+
if (type === "text" && typeof raw.text === "string") {
|
|
607
|
+
return { type, text: raw.text };
|
|
608
|
+
}
|
|
609
|
+
if (type === "image" && typeof raw.mimeType === "string") {
|
|
610
|
+
return {
|
|
611
|
+
type,
|
|
612
|
+
mimeType: raw.mimeType,
|
|
613
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
614
|
+
...typeof raw.data === "string" ? { data: raw.data } : {}
|
|
615
|
+
};
|
|
616
|
+
}
|
|
617
|
+
if (type === "audio" && typeof raw.mimeType === "string") {
|
|
618
|
+
return {
|
|
619
|
+
type,
|
|
620
|
+
mimeType: raw.mimeType,
|
|
621
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
622
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
623
|
+
...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
if (type === "video" && typeof raw.mimeType === "string") {
|
|
627
|
+
return {
|
|
628
|
+
type,
|
|
629
|
+
mimeType: raw.mimeType,
|
|
630
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
631
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
632
|
+
...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
if (type === "resource_link" && typeof raw.uri === "string" && typeof raw.name === "string") {
|
|
636
|
+
return {
|
|
637
|
+
type,
|
|
638
|
+
uri: raw.uri,
|
|
639
|
+
name: raw.name,
|
|
640
|
+
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
641
|
+
...typeof raw.size === "number" ? { size: raw.size } : {}
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
if (type === "resource" && raw.resource && typeof raw.resource === "object") {
|
|
645
|
+
const resource = raw.resource;
|
|
646
|
+
if (typeof resource.uri !== "string") return null;
|
|
647
|
+
return {
|
|
648
|
+
type,
|
|
649
|
+
resource: {
|
|
650
|
+
uri: resource.uri,
|
|
651
|
+
...typeof resource.mimeType === "string" || resource.mimeType === null ? { mimeType: resource.mimeType } : {},
|
|
652
|
+
...typeof resource.text === "string" ? { text: resource.text } : {},
|
|
653
|
+
...typeof resource.blob === "string" ? { blob: resource.blob } : {}
|
|
654
|
+
}
|
|
655
|
+
};
|
|
656
|
+
}
|
|
657
|
+
return null;
|
|
658
|
+
}
|
|
659
|
+
function flattenInputParts(parts) {
|
|
660
|
+
return parts.map((part) => {
|
|
661
|
+
if (part.type === "text") return part.text;
|
|
662
|
+
if (part.type === "audio") return part.transcript || "";
|
|
663
|
+
if (part.type === "resource") return part.text || "";
|
|
664
|
+
return "";
|
|
665
|
+
}).filter((value) => value.length > 0).join("\n");
|
|
666
|
+
}
|
|
667
|
+
var init_io_contracts = __esm({
|
|
668
|
+
"src/providers/io-contracts.ts"() {
|
|
669
|
+
"use strict";
|
|
670
|
+
}
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
// src/providers/contracts.ts
|
|
674
|
+
function flattenContent(content) {
|
|
675
|
+
if (typeof content === "string") return content;
|
|
676
|
+
return flattenMessageParts(normalizeMessageParts(content));
|
|
677
|
+
}
|
|
678
|
+
var init_contracts = __esm({
|
|
679
|
+
"src/providers/contracts.ts"() {
|
|
680
|
+
"use strict";
|
|
681
|
+
init_io_contracts();
|
|
682
|
+
init_io_contracts();
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
|
|
461
686
|
// src/providers/chat-message-normalization.ts
|
|
462
687
|
function canonicalizeKindHint(value) {
|
|
463
688
|
return value.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
@@ -608,39 +833,161 @@ var init_chat_message_normalization = __esm({
|
|
|
608
833
|
}
|
|
609
834
|
});
|
|
610
835
|
|
|
611
|
-
// src/
|
|
612
|
-
function
|
|
613
|
-
|
|
614
|
-
const message = error.message || "";
|
|
615
|
-
const code = "code" in error ? error.code : void 0;
|
|
616
|
-
return code === "MODULE_NOT_FOUND" && message.includes(ref);
|
|
836
|
+
// src/providers/read-chat-contract.ts
|
|
837
|
+
function isPlainObject3(value) {
|
|
838
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
617
839
|
}
|
|
618
|
-
function
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
840
|
+
function isFiniteNumber(value) {
|
|
841
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
842
|
+
}
|
|
843
|
+
function validateStatus(status, source) {
|
|
844
|
+
if (typeof status !== "string" || !VALID_STATUSES.includes(status)) {
|
|
845
|
+
throw new Error(`${source}: status must be one of ${VALID_STATUSES.join(", ")}`);
|
|
622
846
|
}
|
|
623
|
-
return
|
|
847
|
+
return status;
|
|
624
848
|
}
|
|
625
|
-
function
|
|
626
|
-
|
|
627
|
-
|
|
849
|
+
function validateRole(role, source, index) {
|
|
850
|
+
if (typeof role !== "string" || !VALID_ROLES.includes(role)) {
|
|
851
|
+
throw new Error(`${source}: messages[${index}].role must be one of ${VALID_ROLES.join(", ")}`);
|
|
852
|
+
}
|
|
853
|
+
return role;
|
|
628
854
|
}
|
|
629
|
-
function
|
|
630
|
-
if (
|
|
631
|
-
|
|
632
|
-
|
|
855
|
+
function validateMessageContent(content, source, index) {
|
|
856
|
+
if (typeof content === "string") return content;
|
|
857
|
+
if (Array.isArray(content)) return normalizeMessageParts(content);
|
|
858
|
+
throw new Error(`${source}: messages[${index}].content must be a string or structured content array`);
|
|
859
|
+
}
|
|
860
|
+
function validateMessage(message, source, index) {
|
|
861
|
+
if (!isPlainObject3(message)) {
|
|
862
|
+
throw new Error(`${source}: messages[${index}] must be an object`);
|
|
863
|
+
}
|
|
864
|
+
const normalized = {
|
|
865
|
+
role: validateRole(message.role, source, index),
|
|
866
|
+
content: validateMessageContent(message.content, source, index)
|
|
867
|
+
};
|
|
868
|
+
if (typeof message.kind === "string") normalized.kind = message.kind;
|
|
869
|
+
if (typeof message.id === "string") normalized.id = message.id;
|
|
870
|
+
if (isFiniteNumber(message.index)) normalized.index = message.index;
|
|
871
|
+
if (isFiniteNumber(message.timestamp)) normalized.timestamp = message.timestamp;
|
|
872
|
+
if (isFiniteNumber(message.receivedAt)) normalized.receivedAt = message.receivedAt;
|
|
873
|
+
if (Array.isArray(message.toolCalls)) normalized.toolCalls = message.toolCalls;
|
|
874
|
+
if (isPlainObject3(message.meta)) normalized.meta = message.meta;
|
|
875
|
+
if (typeof message.senderName === "string") normalized.senderName = message.senderName;
|
|
876
|
+
if (typeof message._type === "string") normalized._type = message._type;
|
|
877
|
+
if (typeof message._sub === "string") normalized._sub = message._sub;
|
|
878
|
+
return normalized;
|
|
879
|
+
}
|
|
880
|
+
function validateModal(activeModal, status, source) {
|
|
881
|
+
if (activeModal == null) {
|
|
882
|
+
if (status === "waiting_approval") {
|
|
883
|
+
throw new Error(`${source}: waiting_approval status requires activeModal with buttons`);
|
|
633
884
|
}
|
|
634
|
-
return
|
|
885
|
+
return activeModal === null ? null : void 0;
|
|
635
886
|
}
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
}
|
|
887
|
+
if (!isPlainObject3(activeModal)) {
|
|
888
|
+
throw new Error(`${source}: activeModal must be an object when provided`);
|
|
889
|
+
}
|
|
890
|
+
if (typeof activeModal.message !== "string") {
|
|
891
|
+
throw new Error(`${source}: activeModal.message must be a string`);
|
|
892
|
+
}
|
|
893
|
+
if (!Array.isArray(activeModal.buttons) || activeModal.buttons.some((button) => typeof button !== "string" || !button.trim())) {
|
|
894
|
+
throw new Error(`${source}: activeModal.buttons must be a non-empty string array`);
|
|
895
|
+
}
|
|
896
|
+
const normalized = {
|
|
897
|
+
message: activeModal.message,
|
|
898
|
+
buttons: activeModal.buttons.map((button) => button.trim())
|
|
899
|
+
};
|
|
900
|
+
if (isFiniteNumber(activeModal.width)) normalized.width = activeModal.width;
|
|
901
|
+
if (isFiniteNumber(activeModal.height)) normalized.height = activeModal.height;
|
|
902
|
+
return normalized;
|
|
903
|
+
}
|
|
904
|
+
function validateControlValues(controlValues, source) {
|
|
905
|
+
if (controlValues === void 0) return void 0;
|
|
906
|
+
if (!isPlainObject3(controlValues)) {
|
|
907
|
+
throw new Error(`${source}: controlValues must be an object when provided`);
|
|
908
|
+
}
|
|
909
|
+
const normalized = {};
|
|
910
|
+
for (const [key, value] of Object.entries(controlValues)) {
|
|
911
|
+
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") {
|
|
912
|
+
throw new Error(`${source}: controlValues.${key} must be string, number, or boolean`);
|
|
913
|
+
}
|
|
914
|
+
normalized[key] = value;
|
|
915
|
+
}
|
|
916
|
+
return normalized;
|
|
917
|
+
}
|
|
918
|
+
function validateReadChatResultPayload(raw, source = "read_chat") {
|
|
919
|
+
if (!isPlainObject3(raw)) {
|
|
920
|
+
throw new Error(`${source}: payload must be an object`);
|
|
921
|
+
}
|
|
922
|
+
const status = validateStatus(raw.status, source);
|
|
923
|
+
if (!Array.isArray(raw.messages)) {
|
|
924
|
+
throw new Error(`${source}: messages must be an array`);
|
|
925
|
+
}
|
|
926
|
+
const messages = raw.messages.map((message, index) => validateMessage(message, source, index));
|
|
927
|
+
const activeModal = validateModal(raw.activeModal, status, source);
|
|
928
|
+
const controlValues = validateControlValues(raw.controlValues, source);
|
|
929
|
+
const normalized = {
|
|
930
|
+
status,
|
|
931
|
+
messages
|
|
932
|
+
};
|
|
933
|
+
if (activeModal !== void 0) normalized.activeModal = activeModal;
|
|
934
|
+
if (typeof raw.id === "string") normalized.id = raw.id;
|
|
935
|
+
if (typeof raw.title === "string") normalized.title = raw.title;
|
|
936
|
+
if (typeof raw.agentType === "string") normalized.agentType = raw.agentType;
|
|
937
|
+
if (typeof raw.agentName === "string") normalized.agentName = raw.agentName;
|
|
938
|
+
if (typeof raw.extensionId === "string") normalized.extensionId = raw.extensionId;
|
|
939
|
+
if (typeof raw.inputContent === "string") normalized.inputContent = raw.inputContent;
|
|
940
|
+
if (typeof raw.isVisible === "boolean") normalized.isVisible = raw.isVisible;
|
|
941
|
+
if (typeof raw.isWelcomeScreen === "boolean") normalized.isWelcomeScreen = raw.isWelcomeScreen;
|
|
942
|
+
if (controlValues) normalized.controlValues = controlValues;
|
|
943
|
+
if (raw.summaryMetadata !== void 0) normalized.summaryMetadata = raw.summaryMetadata;
|
|
944
|
+
if (Array.isArray(raw.effects)) normalized.effects = raw.effects;
|
|
945
|
+
if (typeof raw.providerSessionId === "string") normalized.providerSessionId = raw.providerSessionId;
|
|
946
|
+
return normalized;
|
|
947
|
+
}
|
|
948
|
+
var VALID_STATUSES, VALID_ROLES;
|
|
949
|
+
var init_read_chat_contract = __esm({
|
|
950
|
+
"src/providers/read-chat-contract.ts"() {
|
|
951
|
+
"use strict";
|
|
952
|
+
init_contracts();
|
|
953
|
+
VALID_STATUSES = ["idle", "generating", "waiting_approval", "error", "panel_hidden", "streaming", "long_generating"];
|
|
954
|
+
VALID_ROLES = ["user", "assistant", "system", "human"];
|
|
955
|
+
}
|
|
956
|
+
});
|
|
957
|
+
|
|
958
|
+
// src/cli-adapters/terminal-backends/ghostty-vt-backend.ts
|
|
959
|
+
function isModuleNotFoundError(error, ref) {
|
|
960
|
+
if (!(error instanceof Error)) return false;
|
|
961
|
+
const message = error.message || "";
|
|
962
|
+
const code = "code" in error ? error.code : void 0;
|
|
963
|
+
return code === "MODULE_NOT_FOUND" && message.includes(ref);
|
|
964
|
+
}
|
|
965
|
+
function normalizeBinding(mod, ref) {
|
|
966
|
+
const binding = mod?.default?.createTerminal ? mod.default : mod?.createTerminal ? mod : null;
|
|
967
|
+
if (!binding) {
|
|
968
|
+
throw new Error(`Ghostty VT binding "${ref}" does not export createTerminal()`);
|
|
969
|
+
}
|
|
970
|
+
return binding;
|
|
971
|
+
}
|
|
972
|
+
function getBindingCandidates() {
|
|
973
|
+
const explicit = process.env.ADHDEV_GHOSTTY_VT_BINDING?.trim();
|
|
974
|
+
return explicit ? [explicit] : DEFAULT_BINDING_CANDIDATES;
|
|
975
|
+
}
|
|
976
|
+
function loadGhosttyVtBinding(required) {
|
|
977
|
+
if (cachedBinding !== void 0) {
|
|
978
|
+
if (!cachedBinding && required && cachedBindingError) {
|
|
979
|
+
throw cachedBindingError;
|
|
980
|
+
}
|
|
981
|
+
return cachedBinding;
|
|
982
|
+
}
|
|
983
|
+
const errors = [];
|
|
984
|
+
for (const ref of getBindingCandidates()) {
|
|
985
|
+
try {
|
|
986
|
+
const mod = require(ref);
|
|
987
|
+
cachedBinding = normalizeBinding(mod, ref);
|
|
988
|
+
cachedBindingError = null;
|
|
989
|
+
return cachedBinding;
|
|
990
|
+
} catch (error) {
|
|
644
991
|
if (isModuleNotFoundError(error, ref)) {
|
|
645
992
|
errors.push(`${ref}: module not found`);
|
|
646
993
|
continue;
|
|
@@ -1463,6 +1810,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1463
1810
|
init_pty_transport();
|
|
1464
1811
|
init_provider_cli_shared();
|
|
1465
1812
|
init_chat_message_normalization();
|
|
1813
|
+
init_read_chat_contract();
|
|
1466
1814
|
init_provider_cli_parse();
|
|
1467
1815
|
init_provider_cli_config();
|
|
1468
1816
|
init_provider_cli_runtime();
|
|
@@ -2608,6 +2956,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
2608
2956
|
runtimeSettings: this.runtimeSettings
|
|
2609
2957
|
});
|
|
2610
2958
|
const parsed = this.cliScripts.parseOutput(input);
|
|
2959
|
+
if (parsed && typeof parsed === "object") {
|
|
2960
|
+
Object.assign(parsed, validateReadChatResultPayload(parsed, `${this.cliType} parseOutput`));
|
|
2961
|
+
}
|
|
2611
2962
|
const refinedStatus = this.refineDetectedStatus(typeof parsed?.status === "string" ? parsed.status : null, input.recentBuffer, input.screenText);
|
|
2612
2963
|
if (parsed && refinedStatus && parsed.status !== refinedStatus) {
|
|
2613
2964
|
parsed.status = refinedStatus;
|
|
@@ -5199,351 +5550,142 @@ var CdpDomHandlers = class {
|
|
|
5199
5550
|
* args:
|
|
5200
5551
|
* ideType?: string — IDE type hint
|
|
5201
5552
|
* sessionId?: string — agent webview session ID
|
|
5202
|
-
*/
|
|
5203
|
-
async handleDomDebug(args) {
|
|
5204
|
-
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
5205
|
-
const sessionId = args?.sessionId;
|
|
5206
|
-
const expression = `(() => {
|
|
5207
|
-
const result = {
|
|
5208
|
-
url: location.href,
|
|
5209
|
-
title: document.title,
|
|
5210
|
-
viewport: { w: window.innerWidth, h: window.innerHeight },
|
|
5211
|
-
|
|
5212
|
-
// Input field info
|
|
5213
|
-
inputs: [],
|
|
5214
|
-
// Textarea info
|
|
5215
|
-
textareas: [],
|
|
5216
|
-
// Contenteditable info
|
|
5217
|
-
editables: [],
|
|
5218
|
-
// Buttons (send, submit etc)
|
|
5219
|
-
buttons: [],
|
|
5220
|
-
// iframes (agent webviews)
|
|
5221
|
-
iframes: [],
|
|
5222
|
-
// role="textbox" info
|
|
5223
|
-
textboxes: [],
|
|
5224
|
-
};
|
|
5225
|
-
|
|
5226
|
-
// Input fields
|
|
5227
|
-
document.querySelectorAll('input[type="text"], input:not([type])').forEach((el, i) => {
|
|
5228
|
-
if (i >= 10) return;
|
|
5229
|
-
result.inputs.push({
|
|
5230
|
-
tag: 'input',
|
|
5231
|
-
id: el.id || null,
|
|
5232
|
-
class: (el.className || '').toString().slice(0, 150),
|
|
5233
|
-
placeholder: el.getAttribute('placeholder') || null,
|
|
5234
|
-
name: el.name || null,
|
|
5235
|
-
value: el.value?.slice(0, 100) || null,
|
|
5236
|
-
visible: el.offsetParent !== null,
|
|
5237
|
-
rect: (() => { try { const r = el.getBoundingClientRect(); return { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) }; } catch { return null; } })(),
|
|
5238
|
-
});
|
|
5239
|
-
});
|
|
5240
|
-
|
|
5241
|
-
// textarea
|
|
5242
|
-
document.querySelectorAll('textarea').forEach((el, i) => {
|
|
5243
|
-
if (i >= 10) return;
|
|
5244
|
-
result.textareas.push({
|
|
5245
|
-
id: el.id || null,
|
|
5246
|
-
class: (el.className || '').toString().slice(0, 150),
|
|
5247
|
-
placeholder: el.getAttribute('placeholder') || null,
|
|
5248
|
-
rows: el.rows,
|
|
5249
|
-
value: el.value?.slice(0, 100) || null,
|
|
5250
|
-
visible: el.offsetParent !== null,
|
|
5251
|
-
rect: (() => { try { const r = el.getBoundingClientRect(); return { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) }; } catch { return null; } })(),
|
|
5252
|
-
});
|
|
5253
|
-
});
|
|
5254
|
-
|
|
5255
|
-
// contenteditable
|
|
5256
|
-
document.querySelectorAll('[contenteditable="true"]').forEach((el, i) => {
|
|
5257
|
-
if (i >= 10) return;
|
|
5258
|
-
result.editables.push({
|
|
5259
|
-
tag: el.tagName?.toLowerCase(),
|
|
5260
|
-
id: el.id || null,
|
|
5261
|
-
class: (el.className || '').toString().slice(0, 150),
|
|
5262
|
-
role: el.getAttribute('role') || null,
|
|
5263
|
-
text: (el.textContent || '').trim().slice(0, 100),
|
|
5264
|
-
visible: el.offsetParent !== null,
|
|
5265
|
-
rect: (() => { try { const r = el.getBoundingClientRect(); return { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) }; } catch { return null; } })(),
|
|
5266
|
-
});
|
|
5267
|
-
});
|
|
5268
|
-
|
|
5269
|
-
// role="textbox"
|
|
5270
|
-
document.querySelectorAll('[role="textbox"]').forEach((el, i) => {
|
|
5271
|
-
if (i >= 10) return;
|
|
5272
|
-
result.textboxes.push({
|
|
5273
|
-
tag: el.tagName?.toLowerCase(),
|
|
5274
|
-
id: el.id || null,
|
|
5275
|
-
class: (el.className || '').toString().slice(0, 150),
|
|
5276
|
-
'aria-label': el.getAttribute('aria-label') || null,
|
|
5277
|
-
text: (el.textContent || '').trim().slice(0, 100),
|
|
5278
|
-
visible: el.offsetParent !== null,
|
|
5279
|
-
rect: (() => { try { const r = el.getBoundingClientRect(); return { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) }; } catch { return null; } })(),
|
|
5280
|
-
});
|
|
5281
|
-
});
|
|
5282
|
-
|
|
5283
|
-
// Buttons (send, submit, accept, reject, approve etc)
|
|
5284
|
-
const btnKeywords = /send|submit|accept|reject|approve|deny|cancel|confirm|run|execute|apply/i;
|
|
5285
|
-
document.querySelectorAll('button, [role="button"], input[type="submit"]').forEach((el, i) => {
|
|
5286
|
-
const text = (el.textContent || el.getAttribute('aria-label') || '').trim();
|
|
5287
|
-
if (i < 30 && (text.length < 30 || btnKeywords.test(text))) {
|
|
5288
|
-
result.buttons.push({
|
|
5289
|
-
tag: el.tagName?.toLowerCase(),
|
|
5290
|
-
id: el.id || null,
|
|
5291
|
-
class: (el.className || '').toString().slice(0, 150),
|
|
5292
|
-
text: text.slice(0, 80),
|
|
5293
|
-
'aria-label': el.getAttribute('aria-label') || null,
|
|
5294
|
-
disabled: el.disabled || el.getAttribute('disabled') !== null,
|
|
5295
|
-
visible: el.offsetParent !== null,
|
|
5296
|
-
rect: (() => { try { const r = el.getBoundingClientRect(); return { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) }; } catch { return null; } })(),
|
|
5297
|
-
});
|
|
5298
|
-
}
|
|
5299
|
-
});
|
|
5300
|
-
|
|
5301
|
-
// iframes
|
|
5302
|
-
document.querySelectorAll('iframe, webview').forEach((el, i) => {
|
|
5303
|
-
if (i >= 20) return;
|
|
5304
|
-
result.iframes.push({
|
|
5305
|
-
tag: el.tagName?.toLowerCase(),
|
|
5306
|
-
id: el.id || null,
|
|
5307
|
-
class: (el.className || '').toString().slice(0, 150),
|
|
5308
|
-
src: el.getAttribute('src')?.slice(0, 200) || null,
|
|
5309
|
-
title: el.getAttribute('title') || null,
|
|
5310
|
-
visible: el.offsetParent !== null,
|
|
5311
|
-
rect: (() => { try { const r = el.getBoundingClientRect(); return { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) }; } catch { return null; } })(),
|
|
5312
|
-
});
|
|
5313
|
-
});
|
|
5314
|
-
|
|
5315
|
-
return JSON.stringify(result);
|
|
5316
|
-
})()`;
|
|
5317
|
-
try {
|
|
5318
|
-
let raw;
|
|
5319
|
-
if (sessionId) {
|
|
5320
|
-
raw = await this.getCdp().evaluateInSessionFrame(sessionId, expression);
|
|
5321
|
-
} else {
|
|
5322
|
-
raw = await this.getCdp().evaluate(expression, 3e4);
|
|
5323
|
-
}
|
|
5324
|
-
const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
5325
|
-
return { success: true, ...parsed };
|
|
5326
|
-
} catch (e) {
|
|
5327
|
-
return { success: false, error: e.message };
|
|
5328
|
-
}
|
|
5329
|
-
}
|
|
5330
|
-
};
|
|
5331
|
-
|
|
5332
|
-
// src/providers/ide-provider-instance.ts
|
|
5333
|
-
var crypto2 = __toESM(require("crypto"));
|
|
5334
|
-
|
|
5335
|
-
// src/providers/io-contracts.ts
|
|
5336
|
-
function normalizeInputEnvelope(input) {
|
|
5337
|
-
const normalized = normalizeInputEnvelopePayload(input);
|
|
5338
|
-
const textFallback = normalized.textFallback ?? flattenInputParts(normalized.parts);
|
|
5339
|
-
return {
|
|
5340
|
-
parts: normalized.parts,
|
|
5341
|
-
textFallback,
|
|
5342
|
-
...normalized.metadata ? { metadata: normalized.metadata } : {}
|
|
5343
|
-
};
|
|
5344
|
-
}
|
|
5345
|
-
function normalizeMessageParts(content) {
|
|
5346
|
-
if (typeof content === "string") return [{ type: "text", text: content }];
|
|
5347
|
-
if (!Array.isArray(content)) {
|
|
5348
|
-
if (content && typeof content === "object" && typeof content.text === "string") {
|
|
5349
|
-
return [{ type: "text", text: String(content.text) }];
|
|
5350
|
-
}
|
|
5351
|
-
return [];
|
|
5352
|
-
}
|
|
5353
|
-
const parts = [];
|
|
5354
|
-
for (const raw of content) {
|
|
5355
|
-
if (typeof raw === "string") {
|
|
5356
|
-
parts.push({ type: "text", text: raw });
|
|
5357
|
-
continue;
|
|
5358
|
-
}
|
|
5359
|
-
if (!raw || typeof raw !== "object") continue;
|
|
5360
|
-
const part = normalizeMessagePartObject(raw);
|
|
5361
|
-
if (part) parts.push(part);
|
|
5362
|
-
}
|
|
5363
|
-
return parts;
|
|
5364
|
-
}
|
|
5365
|
-
function flattenMessageParts(parts) {
|
|
5366
|
-
return parts.map((part) => {
|
|
5367
|
-
if (part.type === "text") return part.text;
|
|
5368
|
-
if (part.type === "resource") return part.resource.text || "";
|
|
5369
|
-
return "";
|
|
5370
|
-
}).filter((value) => value.length > 0).join("\n");
|
|
5371
|
-
}
|
|
5372
|
-
function normalizeInputEnvelopePayload(input) {
|
|
5373
|
-
if (typeof input === "string") {
|
|
5374
|
-
return { parts: [{ type: "text", text: input }], textFallback: input };
|
|
5375
|
-
}
|
|
5376
|
-
if (!input || typeof input !== "object") {
|
|
5377
|
-
return { parts: [], textFallback: "" };
|
|
5378
|
-
}
|
|
5379
|
-
const record = input;
|
|
5380
|
-
const nestedInput = record.input;
|
|
5381
|
-
if (nestedInput && typeof nestedInput === "object") {
|
|
5382
|
-
const nested = nestedInput;
|
|
5383
|
-
return {
|
|
5384
|
-
parts: normalizeInputParts(nested.parts ?? nested.prompt),
|
|
5385
|
-
textFallback: typeof nested.textFallback === "string" ? nested.textFallback : void 0,
|
|
5386
|
-
metadata: normalizeInputMetadata(nested.metadata)
|
|
5387
|
-
};
|
|
5388
|
-
}
|
|
5389
|
-
const directText = typeof record.text === "string" ? record.text : typeof record.message === "string" ? record.message : void 0;
|
|
5390
|
-
if (directText !== void 0) {
|
|
5391
|
-
return { parts: [{ type: "text", text: directText }], textFallback: directText };
|
|
5392
|
-
}
|
|
5393
|
-
const directParts = normalizeInputParts(record.parts ?? record.prompt);
|
|
5394
|
-
return {
|
|
5395
|
-
parts: directParts,
|
|
5396
|
-
textFallback: typeof record.textFallback === "string" ? record.textFallback : void 0,
|
|
5397
|
-
metadata: normalizeInputMetadata(record.metadata)
|
|
5398
|
-
};
|
|
5399
|
-
}
|
|
5400
|
-
function normalizeInputMetadata(value) {
|
|
5401
|
-
if (!value || typeof value !== "object") return void 0;
|
|
5402
|
-
const record = value;
|
|
5403
|
-
const metadata = {};
|
|
5404
|
-
if (record.source === "dashboard" || record.source === "shortcut_api" || record.source === "provider_script" || record.source === "session_replay") {
|
|
5405
|
-
metadata.source = record.source;
|
|
5406
|
-
}
|
|
5407
|
-
if (typeof record.clientTimestamp === "number" && Number.isFinite(record.clientTimestamp)) {
|
|
5408
|
-
metadata.clientTimestamp = record.clientTimestamp;
|
|
5409
|
-
}
|
|
5410
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
5411
|
-
}
|
|
5412
|
-
function normalizeInputParts(value) {
|
|
5413
|
-
if (!Array.isArray(value)) return [];
|
|
5414
|
-
const parts = [];
|
|
5415
|
-
for (const raw of value) {
|
|
5416
|
-
if (typeof raw === "string") {
|
|
5417
|
-
parts.push({ type: "text", text: raw });
|
|
5418
|
-
continue;
|
|
5419
|
-
}
|
|
5420
|
-
if (!raw || typeof raw !== "object") continue;
|
|
5421
|
-
const part = normalizeInputPartObject(raw);
|
|
5422
|
-
if (part) parts.push(part);
|
|
5423
|
-
}
|
|
5424
|
-
return parts;
|
|
5425
|
-
}
|
|
5426
|
-
function normalizeInputPartObject(raw) {
|
|
5427
|
-
const type = raw.type;
|
|
5428
|
-
if (type === "text" && typeof raw.text === "string") {
|
|
5429
|
-
return { type, text: raw.text };
|
|
5430
|
-
}
|
|
5431
|
-
if (type === "image" && typeof raw.mimeType === "string") {
|
|
5432
|
-
return {
|
|
5433
|
-
type,
|
|
5434
|
-
mimeType: raw.mimeType,
|
|
5435
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
5436
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
5437
|
-
...typeof raw.alt === "string" ? { alt: raw.alt } : {}
|
|
5438
|
-
};
|
|
5439
|
-
}
|
|
5440
|
-
if (type === "audio" && typeof raw.mimeType === "string") {
|
|
5441
|
-
return {
|
|
5442
|
-
type,
|
|
5443
|
-
mimeType: raw.mimeType,
|
|
5444
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
5445
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
5446
|
-
...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
|
|
5447
|
-
};
|
|
5448
|
-
}
|
|
5449
|
-
if (type === "video" && typeof raw.mimeType === "string") {
|
|
5450
|
-
return {
|
|
5451
|
-
type,
|
|
5452
|
-
mimeType: raw.mimeType,
|
|
5453
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
5454
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
5455
|
-
...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
|
|
5456
|
-
};
|
|
5457
|
-
}
|
|
5458
|
-
if (type === "resource" && typeof raw.uri === "string") {
|
|
5459
|
-
return {
|
|
5460
|
-
type,
|
|
5461
|
-
uri: raw.uri,
|
|
5462
|
-
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
5463
|
-
...typeof raw.name === "string" ? { name: raw.name } : {},
|
|
5464
|
-
...typeof raw.text === "string" ? { text: raw.text } : {},
|
|
5465
|
-
...typeof raw.data === "string" ? { data: raw.data } : {}
|
|
5466
|
-
};
|
|
5467
|
-
}
|
|
5468
|
-
if (type === "resource_link" && typeof raw.uri === "string") {
|
|
5469
|
-
return {
|
|
5470
|
-
type: "resource",
|
|
5471
|
-
uri: raw.uri,
|
|
5472
|
-
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
5473
|
-
...typeof raw.name === "string" ? { name: raw.name } : {}
|
|
5474
|
-
};
|
|
5475
|
-
}
|
|
5476
|
-
return null;
|
|
5477
|
-
}
|
|
5478
|
-
function normalizeMessagePartObject(raw) {
|
|
5479
|
-
const type = raw.type;
|
|
5480
|
-
if (type === "text" && typeof raw.text === "string") {
|
|
5481
|
-
return { type, text: raw.text };
|
|
5482
|
-
}
|
|
5483
|
-
if (type === "image" && typeof raw.mimeType === "string") {
|
|
5484
|
-
return {
|
|
5485
|
-
type,
|
|
5486
|
-
mimeType: raw.mimeType,
|
|
5487
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
5488
|
-
...typeof raw.data === "string" ? { data: raw.data } : {}
|
|
5489
|
-
};
|
|
5490
|
-
}
|
|
5491
|
-
if (type === "audio" && typeof raw.mimeType === "string") {
|
|
5492
|
-
return {
|
|
5493
|
-
type,
|
|
5494
|
-
mimeType: raw.mimeType,
|
|
5495
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
5496
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
5497
|
-
...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
|
|
5498
|
-
};
|
|
5499
|
-
}
|
|
5500
|
-
if (type === "video" && typeof raw.mimeType === "string") {
|
|
5501
|
-
return {
|
|
5502
|
-
type,
|
|
5503
|
-
mimeType: raw.mimeType,
|
|
5504
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
5505
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
5506
|
-
...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
|
|
5507
|
-
};
|
|
5508
|
-
}
|
|
5509
|
-
if (type === "resource_link" && typeof raw.uri === "string" && typeof raw.name === "string") {
|
|
5510
|
-
return {
|
|
5511
|
-
type,
|
|
5512
|
-
uri: raw.uri,
|
|
5513
|
-
name: raw.name,
|
|
5514
|
-
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
5515
|
-
...typeof raw.size === "number" ? { size: raw.size } : {}
|
|
5516
|
-
};
|
|
5517
|
-
}
|
|
5518
|
-
if (type === "resource" && raw.resource && typeof raw.resource === "object") {
|
|
5519
|
-
const resource = raw.resource;
|
|
5520
|
-
if (typeof resource.uri !== "string") return null;
|
|
5521
|
-
return {
|
|
5522
|
-
type,
|
|
5523
|
-
resource: {
|
|
5524
|
-
uri: resource.uri,
|
|
5525
|
-
...typeof resource.mimeType === "string" || resource.mimeType === null ? { mimeType: resource.mimeType } : {},
|
|
5526
|
-
...typeof resource.text === "string" ? { text: resource.text } : {},
|
|
5527
|
-
...typeof resource.blob === "string" ? { blob: resource.blob } : {}
|
|
5553
|
+
*/
|
|
5554
|
+
async handleDomDebug(args) {
|
|
5555
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
5556
|
+
const sessionId = args?.sessionId;
|
|
5557
|
+
const expression = `(() => {
|
|
5558
|
+
const result = {
|
|
5559
|
+
url: location.href,
|
|
5560
|
+
title: document.title,
|
|
5561
|
+
viewport: { w: window.innerWidth, h: window.innerHeight },
|
|
5562
|
+
|
|
5563
|
+
// Input field info
|
|
5564
|
+
inputs: [],
|
|
5565
|
+
// Textarea info
|
|
5566
|
+
textareas: [],
|
|
5567
|
+
// Contenteditable info
|
|
5568
|
+
editables: [],
|
|
5569
|
+
// Buttons (send, submit etc)
|
|
5570
|
+
buttons: [],
|
|
5571
|
+
// iframes (agent webviews)
|
|
5572
|
+
iframes: [],
|
|
5573
|
+
// role="textbox" info
|
|
5574
|
+
textboxes: [],
|
|
5575
|
+
};
|
|
5576
|
+
|
|
5577
|
+
// Input fields
|
|
5578
|
+
document.querySelectorAll('input[type="text"], input:not([type])').forEach((el, i) => {
|
|
5579
|
+
if (i >= 10) return;
|
|
5580
|
+
result.inputs.push({
|
|
5581
|
+
tag: 'input',
|
|
5582
|
+
id: el.id || null,
|
|
5583
|
+
class: (el.className || '').toString().slice(0, 150),
|
|
5584
|
+
placeholder: el.getAttribute('placeholder') || null,
|
|
5585
|
+
name: el.name || null,
|
|
5586
|
+
value: el.value?.slice(0, 100) || null,
|
|
5587
|
+
visible: el.offsetParent !== null,
|
|
5588
|
+
rect: (() => { try { const r = el.getBoundingClientRect(); return { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) }; } catch { return null; } })(),
|
|
5589
|
+
});
|
|
5590
|
+
});
|
|
5591
|
+
|
|
5592
|
+
// textarea
|
|
5593
|
+
document.querySelectorAll('textarea').forEach((el, i) => {
|
|
5594
|
+
if (i >= 10) return;
|
|
5595
|
+
result.textareas.push({
|
|
5596
|
+
id: el.id || null,
|
|
5597
|
+
class: (el.className || '').toString().slice(0, 150),
|
|
5598
|
+
placeholder: el.getAttribute('placeholder') || null,
|
|
5599
|
+
rows: el.rows,
|
|
5600
|
+
value: el.value?.slice(0, 100) || null,
|
|
5601
|
+
visible: el.offsetParent !== null,
|
|
5602
|
+
rect: (() => { try { const r = el.getBoundingClientRect(); return { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) }; } catch { return null; } })(),
|
|
5603
|
+
});
|
|
5604
|
+
});
|
|
5605
|
+
|
|
5606
|
+
// contenteditable
|
|
5607
|
+
document.querySelectorAll('[contenteditable="true"]').forEach((el, i) => {
|
|
5608
|
+
if (i >= 10) return;
|
|
5609
|
+
result.editables.push({
|
|
5610
|
+
tag: el.tagName?.toLowerCase(),
|
|
5611
|
+
id: el.id || null,
|
|
5612
|
+
class: (el.className || '').toString().slice(0, 150),
|
|
5613
|
+
role: el.getAttribute('role') || null,
|
|
5614
|
+
text: (el.textContent || '').trim().slice(0, 100),
|
|
5615
|
+
visible: el.offsetParent !== null,
|
|
5616
|
+
rect: (() => { try { const r = el.getBoundingClientRect(); return { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) }; } catch { return null; } })(),
|
|
5617
|
+
});
|
|
5618
|
+
});
|
|
5619
|
+
|
|
5620
|
+
// role="textbox"
|
|
5621
|
+
document.querySelectorAll('[role="textbox"]').forEach((el, i) => {
|
|
5622
|
+
if (i >= 10) return;
|
|
5623
|
+
result.textboxes.push({
|
|
5624
|
+
tag: el.tagName?.toLowerCase(),
|
|
5625
|
+
id: el.id || null,
|
|
5626
|
+
class: (el.className || '').toString().slice(0, 150),
|
|
5627
|
+
'aria-label': el.getAttribute('aria-label') || null,
|
|
5628
|
+
text: (el.textContent || '').trim().slice(0, 100),
|
|
5629
|
+
visible: el.offsetParent !== null,
|
|
5630
|
+
rect: (() => { try { const r = el.getBoundingClientRect(); return { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) }; } catch { return null; } })(),
|
|
5631
|
+
});
|
|
5632
|
+
});
|
|
5633
|
+
|
|
5634
|
+
// Buttons (send, submit, accept, reject, approve etc)
|
|
5635
|
+
const btnKeywords = /send|submit|accept|reject|approve|deny|cancel|confirm|run|execute|apply/i;
|
|
5636
|
+
document.querySelectorAll('button, [role="button"], input[type="submit"]').forEach((el, i) => {
|
|
5637
|
+
const text = (el.textContent || el.getAttribute('aria-label') || '').trim();
|
|
5638
|
+
if (i < 30 && (text.length < 30 || btnKeywords.test(text))) {
|
|
5639
|
+
result.buttons.push({
|
|
5640
|
+
tag: el.tagName?.toLowerCase(),
|
|
5641
|
+
id: el.id || null,
|
|
5642
|
+
class: (el.className || '').toString().slice(0, 150),
|
|
5643
|
+
text: text.slice(0, 80),
|
|
5644
|
+
'aria-label': el.getAttribute('aria-label') || null,
|
|
5645
|
+
disabled: el.disabled || el.getAttribute('disabled') !== null,
|
|
5646
|
+
visible: el.offsetParent !== null,
|
|
5647
|
+
rect: (() => { try { const r = el.getBoundingClientRect(); return { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) }; } catch { return null; } })(),
|
|
5648
|
+
});
|
|
5649
|
+
}
|
|
5650
|
+
});
|
|
5651
|
+
|
|
5652
|
+
// iframes
|
|
5653
|
+
document.querySelectorAll('iframe, webview').forEach((el, i) => {
|
|
5654
|
+
if (i >= 20) return;
|
|
5655
|
+
result.iframes.push({
|
|
5656
|
+
tag: el.tagName?.toLowerCase(),
|
|
5657
|
+
id: el.id || null,
|
|
5658
|
+
class: (el.className || '').toString().slice(0, 150),
|
|
5659
|
+
src: el.getAttribute('src')?.slice(0, 200) || null,
|
|
5660
|
+
title: el.getAttribute('title') || null,
|
|
5661
|
+
visible: el.offsetParent !== null,
|
|
5662
|
+
rect: (() => { try { const r = el.getBoundingClientRect(); return { x: Math.round(r.x), y: Math.round(r.y), w: Math.round(r.width), h: Math.round(r.height) }; } catch { return null; } })(),
|
|
5663
|
+
});
|
|
5664
|
+
});
|
|
5665
|
+
|
|
5666
|
+
return JSON.stringify(result);
|
|
5667
|
+
})()`;
|
|
5668
|
+
try {
|
|
5669
|
+
let raw;
|
|
5670
|
+
if (sessionId) {
|
|
5671
|
+
raw = await this.getCdp().evaluateInSessionFrame(sessionId, expression);
|
|
5672
|
+
} else {
|
|
5673
|
+
raw = await this.getCdp().evaluate(expression, 3e4);
|
|
5528
5674
|
}
|
|
5529
|
-
|
|
5675
|
+
const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
5676
|
+
return { success: true, ...parsed };
|
|
5677
|
+
} catch (e) {
|
|
5678
|
+
return { success: false, error: e.message };
|
|
5679
|
+
}
|
|
5530
5680
|
}
|
|
5531
|
-
|
|
5532
|
-
}
|
|
5533
|
-
function flattenInputParts(parts) {
|
|
5534
|
-
return parts.map((part) => {
|
|
5535
|
-
if (part.type === "text") return part.text;
|
|
5536
|
-
if (part.type === "audio") return part.transcript || "";
|
|
5537
|
-
if (part.type === "resource") return part.text || "";
|
|
5538
|
-
return "";
|
|
5539
|
-
}).filter((value) => value.length > 0).join("\n");
|
|
5540
|
-
}
|
|
5681
|
+
};
|
|
5541
5682
|
|
|
5542
|
-
// src/providers/
|
|
5543
|
-
|
|
5544
|
-
|
|
5545
|
-
|
|
5546
|
-
|
|
5683
|
+
// src/providers/ide-provider-instance.ts
|
|
5684
|
+
var crypto2 = __toESM(require("crypto"));
|
|
5685
|
+
init_contracts();
|
|
5686
|
+
|
|
5687
|
+
// src/providers/extension-provider-instance.ts
|
|
5688
|
+
init_contracts();
|
|
5547
5689
|
|
|
5548
5690
|
// src/providers/status-monitor.ts
|
|
5549
5691
|
var DEFAULT_MONITOR_CONFIG = {
|
|
@@ -5658,6 +5800,7 @@ var StatusMonitor = class {
|
|
|
5658
5800
|
};
|
|
5659
5801
|
|
|
5660
5802
|
// src/providers/control-effects.ts
|
|
5803
|
+
init_contracts();
|
|
5661
5804
|
init_chat_message_normalization();
|
|
5662
5805
|
function extractProviderControlValues(controls, data) {
|
|
5663
5806
|
if (!data || typeof data !== "object") return void 0;
|
|
@@ -5779,38 +5922,37 @@ function buildPersistedProviderEffectMessage(effect) {
|
|
|
5779
5922
|
return null;
|
|
5780
5923
|
}
|
|
5781
5924
|
function normalizeControlListResult(data) {
|
|
5782
|
-
if (data
|
|
5783
|
-
|
|
5784
|
-
options: normalizeControlOptions(data.options),
|
|
5785
|
-
...isScalarControlValue(data.currentValue) ? { currentValue: data.currentValue } : {},
|
|
5786
|
-
...typeof data.error === "string" ? { error: data.error } : {}
|
|
5787
|
-
};
|
|
5925
|
+
if (!data || typeof data !== "object" || !Array.isArray(data.options)) {
|
|
5926
|
+
throw new Error("Provider control list results must use the typed shape { options, currentValue?, error? }");
|
|
5788
5927
|
}
|
|
5789
|
-
const rawOptions = Array.isArray(data?.models) ? data.models : Array.isArray(data?.modes) ? data.modes : Array.isArray(data?.options) ? data.options : [];
|
|
5790
|
-
const options = normalizeControlOptions(rawOptions);
|
|
5791
5928
|
return {
|
|
5792
|
-
options,
|
|
5793
|
-
...isScalarControlValue(data
|
|
5794
|
-
...
|
|
5795
|
-
...typeof data?.error === "string" ? { error: data.error } : {}
|
|
5929
|
+
options: normalizeControlOptions(data.options),
|
|
5930
|
+
...isScalarControlValue(data.currentValue) ? { currentValue: data.currentValue } : {},
|
|
5931
|
+
...typeof data.error === "string" ? { error: data.error } : {}
|
|
5796
5932
|
};
|
|
5797
5933
|
}
|
|
5798
5934
|
function normalizeControlSetResult(data) {
|
|
5799
|
-
|
|
5935
|
+
if (!data || typeof data !== "object" || typeof data.ok !== "boolean") {
|
|
5936
|
+
throw new Error("Provider control set results must use the typed shape { ok, currentValue?, effects?, error? }");
|
|
5937
|
+
}
|
|
5938
|
+
const currentValue = isScalarControlValue(data.currentValue) ? data.currentValue : isScalarControlValue(data.value) ? data.value : void 0;
|
|
5800
5939
|
return {
|
|
5801
|
-
ok: data
|
|
5940
|
+
ok: data.ok,
|
|
5802
5941
|
...currentValue !== void 0 ? { currentValue } : {},
|
|
5803
|
-
...Array.isArray(data
|
|
5804
|
-
...typeof data
|
|
5942
|
+
...Array.isArray(data.effects) ? { effects: normalizeProviderEffects(data) } : {},
|
|
5943
|
+
...typeof data.error === "string" ? { error: data.error } : {}
|
|
5805
5944
|
};
|
|
5806
5945
|
}
|
|
5807
5946
|
function normalizeControlInvokeResult(data) {
|
|
5808
|
-
|
|
5947
|
+
if (!data || typeof data !== "object" || typeof data.ok !== "boolean") {
|
|
5948
|
+
throw new Error("Provider control invoke results must use the typed shape { ok, currentValue?, effects?, error? }");
|
|
5949
|
+
}
|
|
5950
|
+
const currentValue = isScalarControlValue(data.currentValue) ? data.currentValue : isScalarControlValue(data.value) ? data.value : void 0;
|
|
5809
5951
|
return {
|
|
5810
|
-
ok: data
|
|
5952
|
+
ok: data.ok,
|
|
5811
5953
|
...currentValue !== void 0 ? { currentValue } : {},
|
|
5812
|
-
...Array.isArray(data
|
|
5813
|
-
...typeof data
|
|
5954
|
+
...Array.isArray(data.effects) ? { effects: normalizeProviderEffects(data) } : {},
|
|
5955
|
+
...typeof data.error === "string" ? { error: data.error } : {}
|
|
5814
5956
|
};
|
|
5815
5957
|
}
|
|
5816
5958
|
function normalizeControlOptions(options) {
|
|
@@ -6701,19 +6843,37 @@ var ExtensionProviderInstance = class {
|
|
|
6701
6843
|
);
|
|
6702
6844
|
}
|
|
6703
6845
|
}
|
|
6846
|
+
buildSyntheticTurnKey(message, occurrence) {
|
|
6847
|
+
const role = typeof message?.role === "string" ? message.role : "";
|
|
6848
|
+
const kind = typeof message?.kind === "string" ? message.kind : "";
|
|
6849
|
+
const senderName = typeof message?.senderName === "string" ? message.senderName : "";
|
|
6850
|
+
const content = flattenContent(message?.content).replace(/\s+/g, " ").trim().slice(0, 500);
|
|
6851
|
+
return `${role}|${kind}|${senderName}|${content}|${occurrence}`;
|
|
6852
|
+
}
|
|
6704
6853
|
/**
|
|
6705
|
-
* Assign stable receivedAt to extension messages.
|
|
6706
|
-
* Same
|
|
6707
|
-
*
|
|
6854
|
+
* Assign stable receivedAt / synthetic _turnKey to extension messages.
|
|
6855
|
+
* Same transcript should keep the same identity across polling cycles and
|
|
6856
|
+
* stream resets, while repeated identical text later in the transcript still
|
|
6857
|
+
* produces a distinct completion marker via the occurrence suffix.
|
|
6708
6858
|
*/
|
|
6709
6859
|
assignReceivedAt(messages) {
|
|
6710
6860
|
const now = Date.now();
|
|
6711
6861
|
const nextHashes = /* @__PURE__ */ new Map();
|
|
6862
|
+
const occurrenceByBaseKey = /* @__PURE__ */ new Map();
|
|
6712
6863
|
for (const msg of messages) {
|
|
6713
|
-
const
|
|
6714
|
-
const
|
|
6864
|
+
const explicitTurnKey = typeof msg?._turnKey === "string" && msg._turnKey.trim() ? msg._turnKey.trim() : "";
|
|
6865
|
+
const explicitId = typeof msg?.id === "string" && msg.id.trim() ? `id:${msg.id.trim()}` : "";
|
|
6866
|
+
const explicitIndex = typeof msg?.index === "number" && Number.isFinite(msg.index) ? `idx:${msg.index}` : "";
|
|
6867
|
+
const baseKey = explicitTurnKey || explicitId || explicitIndex || `${msg?.role || ""}:${flattenContent(msg?.content || "").slice(0, 500)}`;
|
|
6868
|
+
const occurrence = (occurrenceByBaseKey.get(baseKey) || 0) + 1;
|
|
6869
|
+
occurrenceByBaseKey.set(baseKey, occurrence);
|
|
6870
|
+
const syntheticTurnKey = explicitTurnKey || explicitId || explicitIndex || this.buildSyntheticTurnKey(msg, occurrence);
|
|
6871
|
+
if (!explicitTurnKey && !explicitId && !explicitIndex) {
|
|
6872
|
+
msg._turnKey = syntheticTurnKey;
|
|
6873
|
+
}
|
|
6874
|
+
const prevTime = this.prevMessageHashes.get(syntheticTurnKey);
|
|
6715
6875
|
msg.receivedAt = prevTime || now;
|
|
6716
|
-
nextHashes.set(
|
|
6876
|
+
nextHashes.set(syntheticTurnKey, msg.receivedAt);
|
|
6717
6877
|
}
|
|
6718
6878
|
this.prevMessageHashes = nextHashes;
|
|
6719
6879
|
return normalizeChatMessages(messages);
|
|
@@ -6790,6 +6950,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
6790
6950
|
|
|
6791
6951
|
// src/providers/ide-provider-instance.ts
|
|
6792
6952
|
init_logger();
|
|
6953
|
+
init_read_chat_contract();
|
|
6793
6954
|
|
|
6794
6955
|
// src/providers/approval-utils.ts
|
|
6795
6956
|
var DEFAULT_APPROVAL_POSITIVE_HINTS = [
|
|
@@ -7071,7 +7232,7 @@ var IdeProviderInstance = class {
|
|
|
7071
7232
|
}
|
|
7072
7233
|
}
|
|
7073
7234
|
if (!raw || typeof raw !== "object") return;
|
|
7074
|
-
const chat = raw;
|
|
7235
|
+
const chat = validateReadChatResultPayload(raw, `${this.type} readChat`);
|
|
7075
7236
|
let { activeModal } = chat;
|
|
7076
7237
|
if (activeModal) {
|
|
7077
7238
|
const w = activeModal.width ?? Infinity;
|
|
@@ -8216,6 +8377,65 @@ function reconcileIdeRuntimeSessions(instanceManager, sessionRegistry) {
|
|
|
8216
8377
|
init_logger();
|
|
8217
8378
|
|
|
8218
8379
|
// src/commands/chat-commands.ts
|
|
8380
|
+
init_contracts();
|
|
8381
|
+
|
|
8382
|
+
// src/providers/provider-input-support.ts
|
|
8383
|
+
var VALID_INPUT_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
|
|
8384
|
+
function getProviderLabel(provider) {
|
|
8385
|
+
return provider?.name || provider?.type || "This provider";
|
|
8386
|
+
}
|
|
8387
|
+
function hasNonEmptyFallbackText(input) {
|
|
8388
|
+
return typeof input.textFallback === "string" && input.textFallback.trim().length > 0;
|
|
8389
|
+
}
|
|
8390
|
+
function getRequestedInputMediaTypes(input) {
|
|
8391
|
+
const types = /* @__PURE__ */ new Set();
|
|
8392
|
+
if (hasNonEmptyFallbackText(input) && !input.parts.some((part) => part.type === "text")) {
|
|
8393
|
+
types.add("text");
|
|
8394
|
+
}
|
|
8395
|
+
for (const part of input.parts) {
|
|
8396
|
+
if (VALID_INPUT_MEDIA_TYPES.has(part.type)) {
|
|
8397
|
+
types.add(part.type);
|
|
8398
|
+
}
|
|
8399
|
+
}
|
|
8400
|
+
return Array.from(types);
|
|
8401
|
+
}
|
|
8402
|
+
function getEffectiveSemanticPartCount(input) {
|
|
8403
|
+
let count = input.parts.length;
|
|
8404
|
+
if (hasNonEmptyFallbackText(input) && !input.parts.some((part) => part.type === "text")) {
|
|
8405
|
+
count += 1;
|
|
8406
|
+
}
|
|
8407
|
+
return count;
|
|
8408
|
+
}
|
|
8409
|
+
function assertTextOnlyInput(provider, input) {
|
|
8410
|
+
const unsupported = getRequestedInputMediaTypes(input).filter((type) => type !== "text");
|
|
8411
|
+
if (unsupported.length === 0) return;
|
|
8412
|
+
const label = getProviderLabel(provider);
|
|
8413
|
+
const suffix = unsupported.length === 1 ? "" : "s";
|
|
8414
|
+
throw new Error(`${label} only supports text input; unsupported input type${suffix}: ${unsupported.join(", ")}`);
|
|
8415
|
+
}
|
|
8416
|
+
function getDeclaredProviderInputSupport(provider) {
|
|
8417
|
+
const rawMediaTypes = Array.isArray(provider?.capabilities?.input?.mediaTypes) ? provider?.capabilities?.input?.mediaTypes.filter((type) => VALID_INPUT_MEDIA_TYPES.has(type)) : [];
|
|
8418
|
+
return {
|
|
8419
|
+
multipart: provider?.capabilities?.input?.multipart === true,
|
|
8420
|
+
mediaTypes: new Set(rawMediaTypes.length > 0 ? rawMediaTypes : ["text"])
|
|
8421
|
+
};
|
|
8422
|
+
}
|
|
8423
|
+
function assertProviderSupportsDeclaredInput(provider, input) {
|
|
8424
|
+
const label = getProviderLabel(provider);
|
|
8425
|
+
const support = getDeclaredProviderInputSupport(provider);
|
|
8426
|
+
const requestedTypes = getRequestedInputMediaTypes(input);
|
|
8427
|
+
const unsupported = requestedTypes.filter((type) => !support.mediaTypes.has(type));
|
|
8428
|
+
if (unsupported.length > 0) {
|
|
8429
|
+
const suffix = unsupported.length === 1 ? "" : "s";
|
|
8430
|
+
throw new Error(`${label} does not support input type${suffix}: ${unsupported.join(", ")}`);
|
|
8431
|
+
}
|
|
8432
|
+
if (getEffectiveSemanticPartCount(input) > 1 && !support.multipart) {
|
|
8433
|
+
throw new Error(`${label} does not support multipart input`);
|
|
8434
|
+
}
|
|
8435
|
+
}
|
|
8436
|
+
|
|
8437
|
+
// src/commands/chat-commands.ts
|
|
8438
|
+
init_read_chat_contract();
|
|
8219
8439
|
init_logger();
|
|
8220
8440
|
|
|
8221
8441
|
// src/logging/debug-config.ts
|
|
@@ -8397,10 +8617,15 @@ function isCliLikeTransport(transport) {
|
|
|
8397
8617
|
function isExtensionTransport(transport) {
|
|
8398
8618
|
return transport === "cdp-webview";
|
|
8399
8619
|
}
|
|
8400
|
-
function buildRecentSendKey(h, args, provider,
|
|
8620
|
+
function buildRecentSendKey(h, args, provider, signature) {
|
|
8401
8621
|
const transport = getTargetTransport(h, provider) || "unknown";
|
|
8402
8622
|
const target = args?.targetSessionId || args?.agentType || h.currentSession?.providerType || h.currentProviderType || h.currentManagerKey || "unknown";
|
|
8403
|
-
return `${transport}:${target}:${
|
|
8623
|
+
return `${transport}:${target}:${signature.trim()}`;
|
|
8624
|
+
}
|
|
8625
|
+
function buildSendInputSignature(input) {
|
|
8626
|
+
const text = typeof input.textFallback === "string" ? input.textFallback.trim() : "";
|
|
8627
|
+
if (text) return text;
|
|
8628
|
+
return JSON.stringify(input.parts || []);
|
|
8404
8629
|
}
|
|
8405
8630
|
function getSendChatInputEnvelope(args) {
|
|
8406
8631
|
return normalizeInputEnvelope(args?.input ? { input: args.input } : args);
|
|
@@ -8553,14 +8778,20 @@ function computeReadChatSync(messages, cursor) {
|
|
|
8553
8778
|
};
|
|
8554
8779
|
}
|
|
8555
8780
|
function buildReadChatCommandResult(payload, args) {
|
|
8556
|
-
|
|
8781
|
+
let validatedPayload;
|
|
8782
|
+
try {
|
|
8783
|
+
validatedPayload = validateReadChatResultPayload(payload, "read_chat command result");
|
|
8784
|
+
} catch (error) {
|
|
8785
|
+
return { success: false, error: error?.message || String(error) };
|
|
8786
|
+
}
|
|
8787
|
+
const messages = normalizeReadChatMessages(validatedPayload);
|
|
8557
8788
|
const cursor = normalizeReadChatCursor(args);
|
|
8558
8789
|
if (!cursor.knownMessageCount && !cursor.lastMessageSignature && cursor.tailLimit > 0 && messages.length > cursor.tailLimit) {
|
|
8559
8790
|
const tailMessages = messages.slice(-cursor.tailLimit);
|
|
8560
8791
|
const lastMessageSignature = getChatMessageSignature(tailMessages[tailMessages.length - 1]);
|
|
8561
8792
|
return {
|
|
8562
8793
|
success: true,
|
|
8563
|
-
...
|
|
8794
|
+
...validatedPayload,
|
|
8564
8795
|
messages: tailMessages,
|
|
8565
8796
|
syncMode: "full",
|
|
8566
8797
|
replaceFrom: 0,
|
|
@@ -8571,7 +8802,7 @@ function buildReadChatCommandResult(payload, args) {
|
|
|
8571
8802
|
const sync = computeReadChatSync(messages, cursor);
|
|
8572
8803
|
return {
|
|
8573
8804
|
success: true,
|
|
8574
|
-
...
|
|
8805
|
+
...validatedPayload,
|
|
8575
8806
|
messages: sync.messages,
|
|
8576
8807
|
syncMode: sync.syncMode,
|
|
8577
8808
|
replaceFrom: sync.replaceFrom,
|
|
@@ -8650,12 +8881,18 @@ async function handleReadChat(h, args) {
|
|
|
8650
8881
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
8651
8882
|
if (adapter) {
|
|
8652
8883
|
_log(`${transport} adapter: ${adapter.cliType}`);
|
|
8653
|
-
const
|
|
8884
|
+
const parsedStatus = typeof adapter.getScriptParsedStatus === "function" ? parseMaybeJson(adapter.getScriptParsedStatus()) : null;
|
|
8885
|
+
const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
|
|
8886
|
+
const status = parsedRecord || adapter.getStatus();
|
|
8887
|
+
const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
|
|
8888
|
+
const providerSessionId = typeof parsedRecord?.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
|
|
8654
8889
|
if (status) {
|
|
8655
8890
|
return buildReadChatCommandResult({
|
|
8656
8891
|
messages: status.messages || [],
|
|
8657
8892
|
status: status.status,
|
|
8658
|
-
activeModal: status.activeModal
|
|
8893
|
+
activeModal: status.activeModal,
|
|
8894
|
+
...title ? { title } : {},
|
|
8895
|
+
...providerSessionId ? { providerSessionId } : {}
|
|
8659
8896
|
}, args);
|
|
8660
8897
|
}
|
|
8661
8898
|
}
|
|
@@ -8673,25 +8910,26 @@ async function handleReadChat(h, args) {
|
|
|
8673
8910
|
}
|
|
8674
8911
|
}
|
|
8675
8912
|
if (parsed && typeof parsed === "object") {
|
|
8676
|
-
|
|
8913
|
+
const validated = validateReadChatResultPayload(parsed, "extension read_chat");
|
|
8914
|
+
_log(`Extension OK: ${validated.messages?.length || 0} msgs`);
|
|
8677
8915
|
traceProviderEvent(args, "provider", "extension.read_chat.success", {
|
|
8678
8916
|
h,
|
|
8679
8917
|
provider,
|
|
8680
8918
|
payload: {
|
|
8681
8919
|
method: "evaluateProviderScript",
|
|
8682
8920
|
result: evalResult.result,
|
|
8683
|
-
parsed,
|
|
8684
|
-
messageCount: Array.isArray(
|
|
8921
|
+
parsed: validated,
|
|
8922
|
+
messageCount: Array.isArray(validated.messages) ? validated.messages.length : 0
|
|
8685
8923
|
}
|
|
8686
8924
|
});
|
|
8687
8925
|
h.historyWriter.appendNewMessages(
|
|
8688
8926
|
provider?.type || "unknown_extension",
|
|
8689
|
-
toHistoryPersistedMessages(normalizeReadChatMessages(
|
|
8690
|
-
|
|
8927
|
+
toHistoryPersistedMessages(normalizeReadChatMessages(validated)),
|
|
8928
|
+
validated.title,
|
|
8691
8929
|
args?.targetSessionId,
|
|
8692
8930
|
historySessionId
|
|
8693
8931
|
);
|
|
8694
|
-
return buildReadChatCommandResult(
|
|
8932
|
+
return buildReadChatCommandResult(validated, args);
|
|
8695
8933
|
}
|
|
8696
8934
|
}
|
|
8697
8935
|
} catch (e) {
|
|
@@ -8746,15 +8984,16 @@ async function handleReadChat(h, args) {
|
|
|
8746
8984
|
}
|
|
8747
8985
|
}
|
|
8748
8986
|
if (parsed && typeof parsed === "object") {
|
|
8749
|
-
|
|
8987
|
+
const validated = validateReadChatResultPayload(parsed, "webview read_chat");
|
|
8988
|
+
_log(`Webview OK: ${validated.messages?.length || 0} msgs`);
|
|
8750
8989
|
h.historyWriter.appendNewMessages(
|
|
8751
8990
|
provider?.type || getCurrentProviderType(h, "unknown_webview"),
|
|
8752
|
-
toHistoryPersistedMessages(normalizeReadChatMessages(
|
|
8753
|
-
|
|
8991
|
+
toHistoryPersistedMessages(normalizeReadChatMessages(validated)),
|
|
8992
|
+
validated.title,
|
|
8754
8993
|
args?.targetSessionId,
|
|
8755
8994
|
historySessionId
|
|
8756
8995
|
);
|
|
8757
|
-
return buildReadChatCommandResult(
|
|
8996
|
+
return buildReadChatCommandResult(validated, args);
|
|
8758
8997
|
}
|
|
8759
8998
|
}
|
|
8760
8999
|
} catch (e) {
|
|
@@ -8775,25 +9014,26 @@ async function handleReadChat(h, args) {
|
|
|
8775
9014
|
}
|
|
8776
9015
|
}
|
|
8777
9016
|
if (parsed && typeof parsed === "object" && parsed.messages?.length > 0) {
|
|
8778
|
-
|
|
9017
|
+
const validated = validateReadChatResultPayload(parsed, "ide read_chat");
|
|
9018
|
+
_log(`OK: ${validated.messages?.length} msgs`);
|
|
8779
9019
|
traceProviderEvent(args, "provider", "ide.read_chat.success", {
|
|
8780
9020
|
h,
|
|
8781
9021
|
provider,
|
|
8782
9022
|
payload: {
|
|
8783
9023
|
method: "evaluate",
|
|
8784
9024
|
result: evalResult.result,
|
|
8785
|
-
parsed,
|
|
8786
|
-
messageCount: Array.isArray(
|
|
9025
|
+
parsed: validated,
|
|
9026
|
+
messageCount: Array.isArray(validated.messages) ? validated.messages.length : 0
|
|
8787
9027
|
}
|
|
8788
9028
|
});
|
|
8789
9029
|
h.historyWriter.appendNewMessages(
|
|
8790
9030
|
provider?.type || getCurrentProviderType(h, "unknown_ide"),
|
|
8791
|
-
toHistoryPersistedMessages(normalizeReadChatMessages(
|
|
8792
|
-
|
|
9031
|
+
toHistoryPersistedMessages(normalizeReadChatMessages(validated)),
|
|
9032
|
+
validated.title,
|
|
8793
9033
|
args?.targetSessionId,
|
|
8794
9034
|
historySessionId
|
|
8795
9035
|
);
|
|
8796
|
-
return buildReadChatCommandResult(
|
|
9036
|
+
return buildReadChatCommandResult(validated, args);
|
|
8797
9037
|
}
|
|
8798
9038
|
}
|
|
8799
9039
|
} catch (e) {
|
|
@@ -8811,11 +9051,12 @@ async function handleReadChat(h, args) {
|
|
|
8811
9051
|
async function handleSendChat(h, args) {
|
|
8812
9052
|
const input = getSendChatInputEnvelope(args);
|
|
8813
9053
|
const text = input.textFallback;
|
|
8814
|
-
|
|
9054
|
+
const hasInput = input.parts.length > 0 || typeof text === "string" && text.trim().length > 0;
|
|
9055
|
+
if (!hasInput) return { success: false, error: "input required" };
|
|
8815
9056
|
const _log = (msg) => LOG.debug("Command", `[send_chat] ${msg}`);
|
|
8816
9057
|
const provider = h.getProvider(args?.agentType);
|
|
8817
9058
|
const transport = getTargetTransport(h, provider);
|
|
8818
|
-
const dedupeKey = buildRecentSendKey(h, args, provider,
|
|
9059
|
+
const dedupeKey = buildRecentSendKey(h, args, provider, buildSendInputSignature(input));
|
|
8819
9060
|
const _logSendSuccess = (method, targetAgent) => {
|
|
8820
9061
|
return { success: true, sent: true, method, targetAgent };
|
|
8821
9062
|
};
|
|
@@ -8823,11 +9064,26 @@ async function handleSendChat(h, args) {
|
|
|
8823
9064
|
_log(`Suppressed duplicate send for ${dedupeKey}`);
|
|
8824
9065
|
return { success: true, sent: false, deduplicated: true };
|
|
8825
9066
|
}
|
|
8826
|
-
if (
|
|
9067
|
+
if (transport === "acp") {
|
|
9068
|
+
const target = getTargetInstance(h, args);
|
|
9069
|
+
if (!target || target.category !== "acp") {
|
|
9070
|
+
return { success: false, error: `ACP instance not found for ${provider?.type || args?.agentType || "unknown"}` };
|
|
9071
|
+
}
|
|
9072
|
+
try {
|
|
9073
|
+
assertProviderSupportsDeclaredInput(provider, input);
|
|
9074
|
+
target.onEvent("send_message", { input });
|
|
9075
|
+
return _logSendSuccess("acp-instance", target.type);
|
|
9076
|
+
} catch (e) {
|
|
9077
|
+
return { success: false, error: `acp send failed: ${e.message}` };
|
|
9078
|
+
}
|
|
9079
|
+
}
|
|
9080
|
+
if (transport === "pty") {
|
|
8827
9081
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
8828
9082
|
if (adapter) {
|
|
8829
9083
|
_log(`${transport} adapter: ${adapter.cliType}`);
|
|
8830
9084
|
try {
|
|
9085
|
+
assertTextOnlyInput(provider, input);
|
|
9086
|
+
if (!text) return { success: false, error: "text required for PTY send" };
|
|
8831
9087
|
await adapter.sendMessage(text);
|
|
8832
9088
|
return _logSendSuccess(`${transport}-adapter`, adapter.cliType);
|
|
8833
9089
|
} catch (e) {
|
|
@@ -8835,6 +9091,8 @@ async function handleSendChat(h, args) {
|
|
|
8835
9091
|
}
|
|
8836
9092
|
}
|
|
8837
9093
|
}
|
|
9094
|
+
assertTextOnlyInput(provider, input);
|
|
9095
|
+
if (!text) return { success: false, error: "text required" };
|
|
8838
9096
|
if (isExtensionTransport(transport)) {
|
|
8839
9097
|
_log(`Extension: ${provider?.type || "unknown_extension"}`);
|
|
8840
9098
|
try {
|
|
@@ -9999,14 +10257,14 @@ function normalizeProviderScriptArgs(args, scriptName) {
|
|
|
9999
10257
|
}
|
|
10000
10258
|
function buildControlScriptResult(scriptName, payload) {
|
|
10001
10259
|
if (!payload || typeof payload !== "object") return {};
|
|
10002
|
-
if (Array.isArray(payload.options)
|
|
10260
|
+
if (Array.isArray(payload.options)) {
|
|
10003
10261
|
return { controlResult: normalizeControlListResult(payload) };
|
|
10004
10262
|
}
|
|
10005
10263
|
const looksLikeValueMutation = /^set|^change/i.test(scriptName) || payload.currentValue !== void 0 || payload.value !== void 0;
|
|
10006
10264
|
if (looksLikeValueMutation) {
|
|
10007
10265
|
return { controlResult: normalizeControlSetResult(payload) };
|
|
10008
10266
|
}
|
|
10009
|
-
if (payload.ok !== void 0 ||
|
|
10267
|
+
if (payload.ok !== void 0 || Array.isArray(payload.effects) || typeof payload.error === "string") {
|
|
10010
10268
|
return { controlResult: normalizeControlInvokeResult(payload) };
|
|
10011
10269
|
}
|
|
10012
10270
|
return {};
|
|
@@ -10809,7 +11067,7 @@ var DaemonCommandHandler = class {
|
|
|
10809
11067
|
|
|
10810
11068
|
// src/commands/cli-manager.ts
|
|
10811
11069
|
var os12 = __toESM(require("os"));
|
|
10812
|
-
var
|
|
11070
|
+
var path12 = __toESM(require("path"));
|
|
10813
11071
|
var crypto4 = __toESM(require("crypto"));
|
|
10814
11072
|
var import_chalk = __toESM(require("chalk"));
|
|
10815
11073
|
init_provider_cli_adapter();
|
|
@@ -10821,6 +11079,7 @@ var path11 = __toESM(require("path"));
|
|
|
10821
11079
|
var crypto3 = __toESM(require("crypto"));
|
|
10822
11080
|
var fs5 = __toESM(require("fs"));
|
|
10823
11081
|
var import_node_module = require("module");
|
|
11082
|
+
init_contracts();
|
|
10824
11083
|
init_provider_cli_adapter();
|
|
10825
11084
|
init_logger();
|
|
10826
11085
|
init_chat_message_normalization();
|
|
@@ -11119,6 +11378,7 @@ var CliProviderInstance = class {
|
|
|
11119
11378
|
onEvent(event, data) {
|
|
11120
11379
|
if (event === "send_message") {
|
|
11121
11380
|
const input = normalizeInputEnvelope(data);
|
|
11381
|
+
assertTextOnlyInput(this.provider, input);
|
|
11122
11382
|
if (input.textFallback) {
|
|
11123
11383
|
void this.adapter.sendMessage(input.textFallback).catch((e) => {
|
|
11124
11384
|
LOG.warn("CLI", `[${this.type}] send_message failed: ${e?.message || e}`);
|
|
@@ -11556,10 +11816,10 @@ ${effect.notification.body || ""}`.trim();
|
|
|
11556
11816
|
};
|
|
11557
11817
|
|
|
11558
11818
|
// src/providers/acp-provider-instance.ts
|
|
11559
|
-
var path12 = __toESM(require("path"));
|
|
11560
11819
|
var import_stream = require("stream");
|
|
11561
11820
|
var import_child_process5 = require("child_process");
|
|
11562
11821
|
var import_sdk = require("@agentclientprotocol/sdk");
|
|
11822
|
+
init_contracts();
|
|
11563
11823
|
init_chat_message_normalization();
|
|
11564
11824
|
init_logger();
|
|
11565
11825
|
function getPromptCapabilityFlags(agentCapabilities) {
|
|
@@ -11570,25 +11830,6 @@ function getPromptCapabilityFlags(agentCapabilities) {
|
|
|
11570
11830
|
embeddedContext: prompt.embeddedContext === true
|
|
11571
11831
|
};
|
|
11572
11832
|
}
|
|
11573
|
-
function getResourceNameFromUri(uri, fallback) {
|
|
11574
|
-
try {
|
|
11575
|
-
if (uri.startsWith("file://")) {
|
|
11576
|
-
return path12.basename(new URL(uri).pathname) || fallback;
|
|
11577
|
-
}
|
|
11578
|
-
return path12.basename(uri) || fallback;
|
|
11579
|
-
} catch {
|
|
11580
|
-
return fallback;
|
|
11581
|
-
}
|
|
11582
|
-
}
|
|
11583
|
-
function inputPartToResourceLink(part, fallbackName) {
|
|
11584
|
-
if (!part.uri) return null;
|
|
11585
|
-
return {
|
|
11586
|
-
type: "resource_link",
|
|
11587
|
-
uri: part.uri,
|
|
11588
|
-
name: getResourceNameFromUri(part.uri, fallbackName),
|
|
11589
|
-
...part.mimeType ? { mimeType: part.mimeType } : {}
|
|
11590
|
-
};
|
|
11591
|
-
}
|
|
11592
11833
|
function appendPromptText(promptParts, text) {
|
|
11593
11834
|
const normalized = typeof text === "string" ? text.trim() : "";
|
|
11594
11835
|
if (!normalized) return;
|
|
@@ -11605,55 +11846,60 @@ function buildAcpPromptParts(input, agentCapabilities) {
|
|
|
11605
11846
|
continue;
|
|
11606
11847
|
}
|
|
11607
11848
|
if (part.type === "image") {
|
|
11608
|
-
if (caps.image
|
|
11609
|
-
|
|
11610
|
-
|
|
11611
|
-
|
|
11612
|
-
|
|
11613
|
-
...part.uri ? { uri: part.uri } : {}
|
|
11614
|
-
});
|
|
11615
|
-
continue;
|
|
11849
|
+
if (!caps.image) {
|
|
11850
|
+
throw new Error("ACP agent does not support input type: image");
|
|
11851
|
+
}
|
|
11852
|
+
if (!part.data) {
|
|
11853
|
+
throw new Error("ACP image input requires inline image data");
|
|
11616
11854
|
}
|
|
11617
|
-
|
|
11618
|
-
|
|
11619
|
-
|
|
11855
|
+
promptParts.push({
|
|
11856
|
+
type: "image",
|
|
11857
|
+
data: part.data,
|
|
11858
|
+
mimeType: part.mimeType,
|
|
11859
|
+
...part.uri ? { uri: part.uri } : {}
|
|
11860
|
+
});
|
|
11620
11861
|
continue;
|
|
11621
11862
|
}
|
|
11622
11863
|
if (part.type === "audio") {
|
|
11623
|
-
if (caps.audio
|
|
11624
|
-
|
|
11625
|
-
|
|
11626
|
-
|
|
11627
|
-
|
|
11628
|
-
});
|
|
11629
|
-
continue;
|
|
11864
|
+
if (!caps.audio) {
|
|
11865
|
+
throw new Error("ACP agent does not support input type: audio");
|
|
11866
|
+
}
|
|
11867
|
+
if (!part.data) {
|
|
11868
|
+
throw new Error("ACP audio input requires inline audio data");
|
|
11630
11869
|
}
|
|
11631
|
-
|
|
11632
|
-
|
|
11633
|
-
|
|
11870
|
+
promptParts.push({
|
|
11871
|
+
type: "audio",
|
|
11872
|
+
data: part.data,
|
|
11873
|
+
mimeType: part.mimeType
|
|
11874
|
+
});
|
|
11634
11875
|
continue;
|
|
11635
11876
|
}
|
|
11636
11877
|
if (part.type === "resource") {
|
|
11637
|
-
if (caps.embeddedContext
|
|
11878
|
+
if (!caps.embeddedContext) {
|
|
11879
|
+
throw new Error("ACP agent does not support input type: resource");
|
|
11880
|
+
}
|
|
11881
|
+
if (part.text) {
|
|
11638
11882
|
promptParts.push({
|
|
11639
11883
|
type: "resource",
|
|
11640
|
-
resource:
|
|
11884
|
+
resource: { uri: part.uri, text: part.text, mimeType: part.mimeType ?? null }
|
|
11641
11885
|
});
|
|
11642
11886
|
continue;
|
|
11643
11887
|
}
|
|
11644
|
-
|
|
11645
|
-
|
|
11646
|
-
|
|
11647
|
-
|
|
11888
|
+
if (part.data) {
|
|
11889
|
+
promptParts.push({
|
|
11890
|
+
type: "resource",
|
|
11891
|
+
resource: { uri: part.uri, blob: part.data, mimeType: part.mimeType ?? null }
|
|
11892
|
+
});
|
|
11893
|
+
continue;
|
|
11894
|
+
}
|
|
11895
|
+
throw new Error("ACP resource input requires embedded text or binary data");
|
|
11648
11896
|
}
|
|
11649
11897
|
if (part.type === "video") {
|
|
11650
|
-
|
|
11651
|
-
if (fallback) promptParts.push(fallback);
|
|
11652
|
-
appendPromptText(promptParts, !part.uri ? `Attached video (${part.mimeType})` : void 0);
|
|
11898
|
+
throw new Error("ACP agent does not support input type: video");
|
|
11653
11899
|
}
|
|
11654
11900
|
}
|
|
11655
11901
|
if (!promptParts.some((part) => part.type === "text") && input.textFallback) {
|
|
11656
|
-
promptParts
|
|
11902
|
+
appendPromptText(promptParts, input.textFallback);
|
|
11657
11903
|
}
|
|
11658
11904
|
return promptParts;
|
|
11659
11905
|
}
|
|
@@ -11784,6 +12030,7 @@ var AcpProviderInstance = class {
|
|
|
11784
12030
|
onEvent(event, data) {
|
|
11785
12031
|
if (event === "send_message") {
|
|
11786
12032
|
const input = normalizeInputEnvelope(data);
|
|
12033
|
+
assertProviderSupportsDeclaredInput(this.provider, input);
|
|
11787
12034
|
const promptParts = buildAcpPromptParts(input, this.agentCapabilities);
|
|
11788
12035
|
this.sendPrompt(input.textFallback, promptParts.length > 0 ? promptParts : void 0).catch(
|
|
11789
12036
|
(e) => this.log.warn(`[${this.type}] sendPrompt error: ${e?.message}`)
|
|
@@ -12717,6 +12964,7 @@ ${rawInput}` : rawInput;
|
|
|
12717
12964
|
};
|
|
12718
12965
|
|
|
12719
12966
|
// src/commands/cli-manager.ts
|
|
12967
|
+
init_contracts();
|
|
12720
12968
|
init_logger();
|
|
12721
12969
|
|
|
12722
12970
|
// src/commands/hosted-runtime-restore.ts
|
|
@@ -12983,7 +13231,7 @@ var DaemonCliManager = class {
|
|
|
12983
13231
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
12984
13232
|
const trimmed = (workingDir || "").trim();
|
|
12985
13233
|
if (!trimmed) throw new Error("working directory required");
|
|
12986
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os12.homedir()) :
|
|
13234
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os12.homedir()) : path12.resolve(trimmed);
|
|
12987
13235
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
12988
13236
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
12989
13237
|
const key = crypto4.randomUUID();
|
|
@@ -13442,6 +13690,12 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
13442
13690
|
const { adapter, key } = found;
|
|
13443
13691
|
if (action === "send_chat") {
|
|
13444
13692
|
const input = normalizeInputEnvelope(args?.input ? { input: args.input } : args);
|
|
13693
|
+
const provider = this.providerLoader.resolve(agentType) || this.providerLoader.getMeta(agentType);
|
|
13694
|
+
if (provider?.category === "acp") {
|
|
13695
|
+
assertProviderSupportsDeclaredInput(provider, input);
|
|
13696
|
+
} else {
|
|
13697
|
+
assertTextOnlyInput(provider, input);
|
|
13698
|
+
}
|
|
13445
13699
|
const message = input.textFallback;
|
|
13446
13700
|
if (!message) throw new Error("message required for send_chat");
|
|
13447
13701
|
await adapter.sendMessage(message);
|
|
@@ -13464,16 +13718,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
13464
13718
|
var import_child_process6 = require("child_process");
|
|
13465
13719
|
var net = __toESM(require("net"));
|
|
13466
13720
|
var os14 = __toESM(require("os"));
|
|
13467
|
-
var
|
|
13721
|
+
var path14 = __toESM(require("path"));
|
|
13468
13722
|
|
|
13469
13723
|
// src/providers/provider-loader.ts
|
|
13470
13724
|
var fs6 = __toESM(require("fs"));
|
|
13471
|
-
var
|
|
13725
|
+
var path13 = __toESM(require("path"));
|
|
13472
13726
|
var os13 = __toESM(require("os"));
|
|
13473
13727
|
var chokidar = __toESM(require("chokidar"));
|
|
13474
13728
|
init_logger();
|
|
13475
13729
|
|
|
13476
13730
|
// src/providers/provider-schema.ts
|
|
13731
|
+
var VALID_CAPABILITY_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
|
|
13477
13732
|
var KNOWN_PROVIDER_FIELDS = /* @__PURE__ */ new Set([
|
|
13478
13733
|
"type",
|
|
13479
13734
|
"name",
|
|
@@ -13524,6 +13779,7 @@ var KNOWN_PROVIDER_FIELDS = /* @__PURE__ */ new Set([
|
|
|
13524
13779
|
"sendDelayMs",
|
|
13525
13780
|
"sendKey",
|
|
13526
13781
|
"submitStrategy",
|
|
13782
|
+
"timeouts",
|
|
13527
13783
|
"disableUpstream"
|
|
13528
13784
|
]);
|
|
13529
13785
|
var VALUE_CONTROL_TYPES = /* @__PURE__ */ new Set(["select", "toggle", "cycle", "slider"]);
|
|
@@ -13550,6 +13806,7 @@ function validateProviderDefinition(raw) {
|
|
|
13550
13806
|
warnings.push("disableUpstream is deprecated in provider definitions; use machine-level provider source policy instead");
|
|
13551
13807
|
}
|
|
13552
13808
|
const category = provider.category;
|
|
13809
|
+
const controls = Array.isArray(provider.controls) ? provider.controls : [];
|
|
13553
13810
|
if (category === "cli" || category === "acp") {
|
|
13554
13811
|
const spawn4 = provider.spawn;
|
|
13555
13812
|
const command = spawn4 && typeof spawn4 === "object" ? spawn4.command : void 0;
|
|
@@ -13567,11 +13824,61 @@ function validateProviderDefinition(raw) {
|
|
|
13567
13824
|
if (category === "extension" && !provider.extensionId) {
|
|
13568
13825
|
warnings.push("Extension providers should have extensionId");
|
|
13569
13826
|
}
|
|
13570
|
-
|
|
13827
|
+
validateCapabilities(provider, controls, errors);
|
|
13828
|
+
for (const control of controls) {
|
|
13571
13829
|
validateControl(control, errors);
|
|
13572
13830
|
}
|
|
13573
13831
|
return { errors, warnings };
|
|
13574
13832
|
}
|
|
13833
|
+
function validateCapabilities(provider, controls, errors) {
|
|
13834
|
+
const capabilities = provider.capabilities;
|
|
13835
|
+
if (provider.contractVersion === 2) {
|
|
13836
|
+
if (!capabilities || typeof capabilities !== "object") {
|
|
13837
|
+
errors.push("contractVersion 2 providers must declare capabilities");
|
|
13838
|
+
return;
|
|
13839
|
+
}
|
|
13840
|
+
}
|
|
13841
|
+
if (!capabilities || typeof capabilities !== "object") {
|
|
13842
|
+
return;
|
|
13843
|
+
}
|
|
13844
|
+
const input = capabilities.input;
|
|
13845
|
+
if (!input || typeof input !== "object") {
|
|
13846
|
+
errors.push("capabilities.input is required");
|
|
13847
|
+
} else {
|
|
13848
|
+
if (typeof input.multipart !== "boolean") {
|
|
13849
|
+
errors.push("capabilities.input.multipart must be boolean");
|
|
13850
|
+
}
|
|
13851
|
+
if (!Array.isArray(input.mediaTypes) || input.mediaTypes.length === 0) {
|
|
13852
|
+
errors.push("capabilities.input.mediaTypes must be a non-empty array");
|
|
13853
|
+
} else if (input.mediaTypes.some((type) => typeof type !== "string" || !VALID_CAPABILITY_MEDIA_TYPES.has(type))) {
|
|
13854
|
+
errors.push(`capabilities.input.mediaTypes must only include: ${Array.from(VALID_CAPABILITY_MEDIA_TYPES).join(", ")}`);
|
|
13855
|
+
}
|
|
13856
|
+
}
|
|
13857
|
+
const output = capabilities.output;
|
|
13858
|
+
if (!output || typeof output !== "object") {
|
|
13859
|
+
errors.push("capabilities.output is required");
|
|
13860
|
+
} else {
|
|
13861
|
+
if (typeof output.richContent !== "boolean") {
|
|
13862
|
+
errors.push("capabilities.output.richContent must be boolean");
|
|
13863
|
+
}
|
|
13864
|
+
if (!Array.isArray(output.mediaTypes) || output.mediaTypes.length === 0) {
|
|
13865
|
+
errors.push("capabilities.output.mediaTypes must be a non-empty array");
|
|
13866
|
+
} else if (output.mediaTypes.some((type) => typeof type !== "string" || !VALID_CAPABILITY_MEDIA_TYPES.has(type))) {
|
|
13867
|
+
errors.push(`capabilities.output.mediaTypes must only include: ${Array.from(VALID_CAPABILITY_MEDIA_TYPES).join(", ")}`);
|
|
13868
|
+
}
|
|
13869
|
+
}
|
|
13870
|
+
const controlCapabilities = capabilities.controls;
|
|
13871
|
+
if (!controlCapabilities || typeof controlCapabilities !== "object") {
|
|
13872
|
+
errors.push("capabilities.controls is required");
|
|
13873
|
+
return;
|
|
13874
|
+
}
|
|
13875
|
+
if (typeof controlCapabilities.typedResults !== "boolean") {
|
|
13876
|
+
errors.push("capabilities.controls.typedResults must be boolean");
|
|
13877
|
+
}
|
|
13878
|
+
if (controls.length > 0 && controlCapabilities.typedResults !== true) {
|
|
13879
|
+
errors.push("providers declaring controls must set capabilities.controls.typedResults=true");
|
|
13880
|
+
}
|
|
13881
|
+
}
|
|
13575
13882
|
function validateControl(control, errors) {
|
|
13576
13883
|
if (!control || typeof control !== "object") {
|
|
13577
13884
|
errors.push("controls: each control must be an object");
|
|
@@ -13626,9 +13933,9 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13626
13933
|
static META_FILE = ".meta.json";
|
|
13627
13934
|
constructor(options) {
|
|
13628
13935
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
13629
|
-
this.defaultProvidersDir =
|
|
13936
|
+
this.defaultProvidersDir = path13.join(os13.homedir(), ".adhdev", "providers");
|
|
13630
13937
|
this.userDir = this.defaultProvidersDir;
|
|
13631
|
-
this.upstreamDir =
|
|
13938
|
+
this.upstreamDir = path13.join(this.defaultProvidersDir, ".upstream");
|
|
13632
13939
|
this.disableUpstream = false;
|
|
13633
13940
|
this.applySourceConfig({
|
|
13634
13941
|
userDir: options?.userDir,
|
|
@@ -13676,7 +13983,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13676
13983
|
}
|
|
13677
13984
|
this.sourceMode = nextSourceMode;
|
|
13678
13985
|
this.userDir = this.explicitProviderDir || this.defaultProvidersDir;
|
|
13679
|
-
this.upstreamDir =
|
|
13986
|
+
this.upstreamDir = path13.join(this.defaultProvidersDir, ".upstream");
|
|
13680
13987
|
this.disableUpstream = this.sourceMode === "no-upstream";
|
|
13681
13988
|
if (this.explicitProviderDir) {
|
|
13682
13989
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
@@ -13690,7 +13997,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13690
13997
|
* Canonical provider directory shape for a given root.
|
|
13691
13998
|
*/
|
|
13692
13999
|
getProviderDir(root, category, type) {
|
|
13693
|
-
return
|
|
14000
|
+
return path13.join(root, category, type);
|
|
13694
14001
|
}
|
|
13695
14002
|
/**
|
|
13696
14003
|
* Canonical user override directory for a provider.
|
|
@@ -13717,7 +14024,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13717
14024
|
resolveProviderFile(type, ...segments) {
|
|
13718
14025
|
const dir = this.findProviderDirInternal(type);
|
|
13719
14026
|
if (!dir) return null;
|
|
13720
|
-
return
|
|
14027
|
+
return path13.join(dir, ...segments);
|
|
13721
14028
|
}
|
|
13722
14029
|
/**
|
|
13723
14030
|
* Load all providers (3-tier priority)
|
|
@@ -13756,7 +14063,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13756
14063
|
if (!fs6.existsSync(this.upstreamDir)) return false;
|
|
13757
14064
|
try {
|
|
13758
14065
|
return fs6.readdirSync(this.upstreamDir).some(
|
|
13759
|
-
(d) => fs6.statSync(
|
|
14066
|
+
(d) => fs6.statSync(path13.join(this.upstreamDir, d)).isDirectory()
|
|
13760
14067
|
);
|
|
13761
14068
|
} catch {
|
|
13762
14069
|
return false;
|
|
@@ -14071,8 +14378,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14071
14378
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
14072
14379
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
14073
14380
|
if (providerDir) {
|
|
14074
|
-
const fullDir =
|
|
14075
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
14381
|
+
const fullDir = path13.join(providerDir, entry.scriptDir);
|
|
14382
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
|
|
14076
14383
|
}
|
|
14077
14384
|
matched = true;
|
|
14078
14385
|
}
|
|
@@ -14087,8 +14394,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14087
14394
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
14088
14395
|
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
14089
14396
|
if (providerDir) {
|
|
14090
|
-
const fullDir =
|
|
14091
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
14397
|
+
const fullDir = path13.join(providerDir, base.defaultScriptDir);
|
|
14398
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
|
|
14092
14399
|
}
|
|
14093
14400
|
}
|
|
14094
14401
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
@@ -14105,8 +14412,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14105
14412
|
resolved._resolvedScriptDir = dirOverride;
|
|
14106
14413
|
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
14107
14414
|
if (providerDir) {
|
|
14108
|
-
const fullDir =
|
|
14109
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
14415
|
+
const fullDir = path13.join(providerDir, dirOverride);
|
|
14416
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
|
|
14110
14417
|
}
|
|
14111
14418
|
}
|
|
14112
14419
|
} else if (override.scripts) {
|
|
@@ -14122,8 +14429,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14122
14429
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
14123
14430
|
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
14124
14431
|
if (providerDir) {
|
|
14125
|
-
const fullDir =
|
|
14126
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
14432
|
+
const fullDir = path13.join(providerDir, base.defaultScriptDir);
|
|
14433
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
|
|
14127
14434
|
}
|
|
14128
14435
|
}
|
|
14129
14436
|
}
|
|
@@ -14148,14 +14455,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14148
14455
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
14149
14456
|
return null;
|
|
14150
14457
|
}
|
|
14151
|
-
const dir =
|
|
14458
|
+
const dir = path13.join(providerDir, scriptDir);
|
|
14152
14459
|
if (!fs6.existsSync(dir)) {
|
|
14153
14460
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
14154
14461
|
return null;
|
|
14155
14462
|
}
|
|
14156
14463
|
const cached = this.scriptsCache.get(dir);
|
|
14157
14464
|
if (cached) return cached;
|
|
14158
|
-
const scriptsJs =
|
|
14465
|
+
const scriptsJs = path13.join(dir, "scripts.js");
|
|
14159
14466
|
if (fs6.existsSync(scriptsJs)) {
|
|
14160
14467
|
try {
|
|
14161
14468
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -14197,7 +14504,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14197
14504
|
return;
|
|
14198
14505
|
}
|
|
14199
14506
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
14200
|
-
this.log(`File changed: ${
|
|
14507
|
+
this.log(`File changed: ${path13.basename(filePath)}, reloading...`);
|
|
14201
14508
|
this.reload();
|
|
14202
14509
|
}
|
|
14203
14510
|
};
|
|
@@ -14252,7 +14559,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14252
14559
|
}
|
|
14253
14560
|
const https = require("https");
|
|
14254
14561
|
const { execSync: execSync7 } = require("child_process");
|
|
14255
|
-
const metaPath =
|
|
14562
|
+
const metaPath = path13.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
14256
14563
|
let prevEtag = "";
|
|
14257
14564
|
let prevTimestamp = 0;
|
|
14258
14565
|
try {
|
|
@@ -14312,17 +14619,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14312
14619
|
return { updated: false };
|
|
14313
14620
|
}
|
|
14314
14621
|
this.log("Downloading latest providers from GitHub...");
|
|
14315
|
-
const tmpTar =
|
|
14316
|
-
const tmpExtract =
|
|
14622
|
+
const tmpTar = path13.join(os13.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
14623
|
+
const tmpExtract = path13.join(os13.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
14317
14624
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
14318
14625
|
fs6.mkdirSync(tmpExtract, { recursive: true });
|
|
14319
14626
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
14320
14627
|
const extracted = fs6.readdirSync(tmpExtract);
|
|
14321
14628
|
const rootDir = extracted.find(
|
|
14322
|
-
(d) => fs6.statSync(
|
|
14629
|
+
(d) => fs6.statSync(path13.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
14323
14630
|
);
|
|
14324
14631
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
14325
|
-
const sourceDir =
|
|
14632
|
+
const sourceDir = path13.join(tmpExtract, rootDir);
|
|
14326
14633
|
const backupDir = this.upstreamDir + ".bak";
|
|
14327
14634
|
if (fs6.existsSync(this.upstreamDir)) {
|
|
14328
14635
|
if (fs6.existsSync(backupDir)) fs6.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -14397,8 +14704,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14397
14704
|
copyDirRecursive(src, dest) {
|
|
14398
14705
|
fs6.mkdirSync(dest, { recursive: true });
|
|
14399
14706
|
for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
|
|
14400
|
-
const srcPath =
|
|
14401
|
-
const destPath =
|
|
14707
|
+
const srcPath = path13.join(src, entry.name);
|
|
14708
|
+
const destPath = path13.join(dest, entry.name);
|
|
14402
14709
|
if (entry.isDirectory()) {
|
|
14403
14710
|
this.copyDirRecursive(srcPath, destPath);
|
|
14404
14711
|
} else {
|
|
@@ -14409,7 +14716,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14409
14716
|
/** .meta.json save */
|
|
14410
14717
|
writeMeta(metaPath, etag, timestamp) {
|
|
14411
14718
|
try {
|
|
14412
|
-
fs6.mkdirSync(
|
|
14719
|
+
fs6.mkdirSync(path13.dirname(metaPath), { recursive: true });
|
|
14413
14720
|
fs6.writeFileSync(metaPath, JSON.stringify({
|
|
14414
14721
|
etag,
|
|
14415
14722
|
timestamp,
|
|
@@ -14426,7 +14733,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14426
14733
|
const scan = (d) => {
|
|
14427
14734
|
try {
|
|
14428
14735
|
for (const entry of fs6.readdirSync(d, { withFileTypes: true })) {
|
|
14429
|
-
if (entry.isDirectory()) scan(
|
|
14736
|
+
if (entry.isDirectory()) scan(path13.join(d, entry.name));
|
|
14430
14737
|
else if (entry.name === "provider.json") count++;
|
|
14431
14738
|
}
|
|
14432
14739
|
} catch {
|
|
@@ -14611,17 +14918,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14611
14918
|
for (const root of searchRoots) {
|
|
14612
14919
|
if (!fs6.existsSync(root)) continue;
|
|
14613
14920
|
const candidate = this.getProviderDir(root, cat, type);
|
|
14614
|
-
if (fs6.existsSync(
|
|
14615
|
-
const catDir =
|
|
14921
|
+
if (fs6.existsSync(path13.join(candidate, "provider.json"))) return candidate;
|
|
14922
|
+
const catDir = path13.join(root, cat);
|
|
14616
14923
|
if (fs6.existsSync(catDir)) {
|
|
14617
14924
|
try {
|
|
14618
14925
|
for (const entry of fs6.readdirSync(catDir, { withFileTypes: true })) {
|
|
14619
14926
|
if (!entry.isDirectory()) continue;
|
|
14620
|
-
const jsonPath =
|
|
14927
|
+
const jsonPath = path13.join(catDir, entry.name, "provider.json");
|
|
14621
14928
|
if (fs6.existsSync(jsonPath)) {
|
|
14622
14929
|
try {
|
|
14623
14930
|
const data = JSON.parse(fs6.readFileSync(jsonPath, "utf-8"));
|
|
14624
|
-
if (data.type === type) return
|
|
14931
|
+
if (data.type === type) return path13.join(catDir, entry.name);
|
|
14625
14932
|
} catch {
|
|
14626
14933
|
}
|
|
14627
14934
|
}
|
|
@@ -14638,7 +14945,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14638
14945
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
14639
14946
|
*/
|
|
14640
14947
|
buildScriptWrappersFromDir(dir) {
|
|
14641
|
-
const scriptsJs =
|
|
14948
|
+
const scriptsJs = path13.join(dir, "scripts.js");
|
|
14642
14949
|
if (fs6.existsSync(scriptsJs)) {
|
|
14643
14950
|
try {
|
|
14644
14951
|
delete require.cache[require.resolve(scriptsJs)];
|
|
@@ -14652,7 +14959,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14652
14959
|
for (const file of fs6.readdirSync(dir)) {
|
|
14653
14960
|
if (!file.endsWith(".js")) continue;
|
|
14654
14961
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
14655
|
-
const filePath =
|
|
14962
|
+
const filePath = path13.join(dir, file);
|
|
14656
14963
|
result[scriptName] = (...args) => {
|
|
14657
14964
|
try {
|
|
14658
14965
|
let content = fs6.readFileSync(filePath, "utf-8");
|
|
@@ -14712,7 +15019,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14712
15019
|
}
|
|
14713
15020
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
14714
15021
|
if (hasJson) {
|
|
14715
|
-
const jsonPath =
|
|
15022
|
+
const jsonPath = path13.join(d, "provider.json");
|
|
14716
15023
|
try {
|
|
14717
15024
|
const raw = fs6.readFileSync(jsonPath, "utf-8");
|
|
14718
15025
|
const mod = JSON.parse(raw);
|
|
@@ -14733,7 +15040,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14733
15040
|
this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
|
|
14734
15041
|
} else {
|
|
14735
15042
|
const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
|
|
14736
|
-
const scriptsPath =
|
|
15043
|
+
const scriptsPath = path13.join(d, "scripts.js");
|
|
14737
15044
|
if (!hasCompatibility && fs6.existsSync(scriptsPath)) {
|
|
14738
15045
|
try {
|
|
14739
15046
|
delete require.cache[require.resolve(scriptsPath)];
|
|
@@ -14759,7 +15066,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14759
15066
|
if (!entry.isDirectory()) continue;
|
|
14760
15067
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
14761
15068
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
14762
|
-
scan(
|
|
15069
|
+
scan(path13.join(d, entry.name));
|
|
14763
15070
|
}
|
|
14764
15071
|
}
|
|
14765
15072
|
};
|
|
@@ -15017,8 +15324,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
15017
15324
|
const appNameMap = getMacAppIdentifiers();
|
|
15018
15325
|
const appName = appNameMap[ideId];
|
|
15019
15326
|
if (appName) {
|
|
15020
|
-
const storagePath =
|
|
15021
|
-
process.env.APPDATA ||
|
|
15327
|
+
const storagePath = path14.join(
|
|
15328
|
+
process.env.APPDATA || path14.join(os14.homedir(), "AppData", "Roaming"),
|
|
15022
15329
|
appName,
|
|
15023
15330
|
"storage.json"
|
|
15024
15331
|
);
|
|
@@ -15196,9 +15503,9 @@ init_logger();
|
|
|
15196
15503
|
|
|
15197
15504
|
// src/logging/command-log.ts
|
|
15198
15505
|
var fs7 = __toESM(require("fs"));
|
|
15199
|
-
var
|
|
15506
|
+
var path15 = __toESM(require("path"));
|
|
15200
15507
|
var os15 = __toESM(require("os"));
|
|
15201
|
-
var LOG_DIR2 = process.platform === "win32" ?
|
|
15508
|
+
var LOG_DIR2 = process.platform === "win32" ? path15.join(process.env.LOCALAPPDATA || process.env.APPDATA || path15.join(os15.homedir(), "AppData", "Local"), "adhdev", "logs") : process.platform === "darwin" ? path15.join(os15.homedir(), "Library", "Logs", "adhdev") : path15.join(os15.homedir(), ".local", "share", "adhdev", "logs");
|
|
15202
15509
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
15203
15510
|
var MAX_DAYS = 7;
|
|
15204
15511
|
try {
|
|
@@ -15236,13 +15543,13 @@ function getDateStr2() {
|
|
|
15236
15543
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
15237
15544
|
}
|
|
15238
15545
|
var currentDate2 = getDateStr2();
|
|
15239
|
-
var currentFile =
|
|
15546
|
+
var currentFile = path15.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
15240
15547
|
var writeCount2 = 0;
|
|
15241
15548
|
function checkRotation() {
|
|
15242
15549
|
const today = getDateStr2();
|
|
15243
15550
|
if (today !== currentDate2) {
|
|
15244
15551
|
currentDate2 = today;
|
|
15245
|
-
currentFile =
|
|
15552
|
+
currentFile = path15.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
15246
15553
|
cleanOldFiles();
|
|
15247
15554
|
}
|
|
15248
15555
|
}
|
|
@@ -15256,7 +15563,7 @@ function cleanOldFiles() {
|
|
|
15256
15563
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
15257
15564
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
15258
15565
|
try {
|
|
15259
|
-
fs7.unlinkSync(
|
|
15566
|
+
fs7.unlinkSync(path15.join(LOG_DIR2, file));
|
|
15260
15567
|
} catch {
|
|
15261
15568
|
}
|
|
15262
15569
|
}
|
|
@@ -15669,13 +15976,13 @@ var import_child_process7 = require("child_process");
|
|
|
15669
15976
|
var import_child_process8 = require("child_process");
|
|
15670
15977
|
var fs8 = __toESM(require("fs"));
|
|
15671
15978
|
var os17 = __toESM(require("os"));
|
|
15672
|
-
var
|
|
15979
|
+
var path16 = __toESM(require("path"));
|
|
15673
15980
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
15674
15981
|
function getUpgradeLogPath() {
|
|
15675
15982
|
const home = os17.homedir();
|
|
15676
|
-
const dir =
|
|
15983
|
+
const dir = path16.join(home, ".adhdev");
|
|
15677
15984
|
fs8.mkdirSync(dir, { recursive: true });
|
|
15678
|
-
return
|
|
15985
|
+
return path16.join(dir, "daemon-upgrade.log");
|
|
15679
15986
|
}
|
|
15680
15987
|
function appendUpgradeLog(message) {
|
|
15681
15988
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
@@ -15715,7 +16022,7 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
15715
16022
|
}
|
|
15716
16023
|
}
|
|
15717
16024
|
function stopSessionHostProcesses(appName) {
|
|
15718
|
-
const pidFile =
|
|
16025
|
+
const pidFile = path16.join(os17.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
15719
16026
|
try {
|
|
15720
16027
|
if (fs8.existsSync(pidFile)) {
|
|
15721
16028
|
const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -15744,7 +16051,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
15744
16051
|
}
|
|
15745
16052
|
}
|
|
15746
16053
|
function removeDaemonPidFile() {
|
|
15747
|
-
const pidFile =
|
|
16054
|
+
const pidFile = path16.join(os17.homedir(), ".adhdev", "daemon.pid");
|
|
15748
16055
|
try {
|
|
15749
16056
|
fs8.unlinkSync(pidFile);
|
|
15750
16057
|
} catch {
|
|
@@ -15755,7 +16062,7 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
|
15755
16062
|
const npmRoot = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["root", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
15756
16063
|
if (!npmRoot) return;
|
|
15757
16064
|
const npmPrefix = (0, import_child_process7.execFileSync)(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
15758
|
-
const binDir = process.platform === "win32" ? npmPrefix :
|
|
16065
|
+
const binDir = process.platform === "win32" ? npmPrefix : path16.join(npmPrefix, "bin");
|
|
15759
16066
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
15760
16067
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
15761
16068
|
if (pkgName === "@adhdev/daemon-standalone") {
|
|
@@ -15763,25 +16070,25 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
|
15763
16070
|
}
|
|
15764
16071
|
if (pkgName.startsWith("@")) {
|
|
15765
16072
|
const [scope, name] = pkgName.split("/");
|
|
15766
|
-
const scopeDir =
|
|
16073
|
+
const scopeDir = path16.join(npmRoot, scope);
|
|
15767
16074
|
if (!fs8.existsSync(scopeDir)) return;
|
|
15768
16075
|
for (const entry of fs8.readdirSync(scopeDir)) {
|
|
15769
16076
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
15770
|
-
fs8.rmSync(
|
|
15771
|
-
appendUpgradeLog(`Removed stale scoped staging dir: ${
|
|
16077
|
+
fs8.rmSync(path16.join(scopeDir, entry), { recursive: true, force: true });
|
|
16078
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path16.join(scopeDir, entry)}`);
|
|
15772
16079
|
}
|
|
15773
16080
|
} else {
|
|
15774
16081
|
for (const entry of fs8.readdirSync(npmRoot)) {
|
|
15775
16082
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
15776
|
-
fs8.rmSync(
|
|
15777
|
-
appendUpgradeLog(`Removed stale staging dir: ${
|
|
16083
|
+
fs8.rmSync(path16.join(npmRoot, entry), { recursive: true, force: true });
|
|
16084
|
+
appendUpgradeLog(`Removed stale staging dir: ${path16.join(npmRoot, entry)}`);
|
|
15778
16085
|
}
|
|
15779
16086
|
}
|
|
15780
16087
|
if (fs8.existsSync(binDir)) {
|
|
15781
16088
|
for (const entry of fs8.readdirSync(binDir)) {
|
|
15782
16089
|
if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
15783
|
-
fs8.rmSync(
|
|
15784
|
-
appendUpgradeLog(`Removed stale bin staging entry: ${
|
|
16090
|
+
fs8.rmSync(path16.join(binDir, entry), { recursive: true, force: true });
|
|
16091
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path16.join(binDir, entry)}`);
|
|
15785
16092
|
}
|
|
15786
16093
|
}
|
|
15787
16094
|
}
|
|
@@ -16811,6 +17118,7 @@ var DEFAULT_DAEMON_PORT = 19222;
|
|
|
16811
17118
|
var DAEMON_WS_PATH = "/ipc";
|
|
16812
17119
|
|
|
16813
17120
|
// src/agent-stream/provider-adapter.ts
|
|
17121
|
+
init_read_chat_contract();
|
|
16814
17122
|
init_chat_message_normalization();
|
|
16815
17123
|
var ProviderStreamAdapter = class {
|
|
16816
17124
|
agentType;
|
|
@@ -16916,26 +17224,29 @@ var ProviderStreamAdapter = class {
|
|
|
16916
17224
|
}
|
|
16917
17225
|
return state2;
|
|
16918
17226
|
}
|
|
17227
|
+
const validated = validateReadChatResultPayload(data, `${this.agentType} readChat`);
|
|
17228
|
+
const validatedStatus = validated.status;
|
|
17229
|
+
const streamStatus = validatedStatus === "generating" || validatedStatus === "long_generating" ? "streaming" : validatedStatus;
|
|
16919
17230
|
const state = {
|
|
16920
17231
|
agentType: this.agentType,
|
|
16921
17232
|
agentName: this.agentName,
|
|
16922
17233
|
extensionId: this.extensionId,
|
|
16923
|
-
status:
|
|
16924
|
-
messages: normalizeChatMessages(
|
|
16925
|
-
inputContent:
|
|
16926
|
-
activeModal:
|
|
17234
|
+
status: streamStatus,
|
|
17235
|
+
messages: normalizeChatMessages(validated.messages),
|
|
17236
|
+
inputContent: typeof validated.inputContent === "string" ? validated.inputContent : "",
|
|
17237
|
+
...validated.activeModal ? { activeModal: validated.activeModal } : {}
|
|
16927
17238
|
};
|
|
16928
|
-
if (typeof
|
|
16929
|
-
state.title =
|
|
17239
|
+
if (typeof validated.title === "string" && validated.title.trim()) {
|
|
17240
|
+
state.title = validated.title.trim();
|
|
16930
17241
|
}
|
|
16931
|
-
const controlValues = extractProviderControlValues(this.provider.controls,
|
|
17242
|
+
const controlValues = extractProviderControlValues(this.provider.controls, validated);
|
|
16932
17243
|
const surface = resolveProviderStateSurface({
|
|
16933
17244
|
controlValues,
|
|
16934
|
-
summaryMetadata:
|
|
17245
|
+
summaryMetadata: validated.summaryMetadata
|
|
16935
17246
|
});
|
|
16936
17247
|
if (surface.controlValues) state.controlValues = surface.controlValues;
|
|
16937
17248
|
if (surface.summaryMetadata) state.summaryMetadata = surface.summaryMetadata;
|
|
16938
|
-
const effects = normalizeProviderEffects(
|
|
17249
|
+
const effects = normalizeProviderEffects(validated);
|
|
16939
17250
|
if (effects.length > 0) state.effects = effects;
|
|
16940
17251
|
if (state.messages.length > 0) {
|
|
16941
17252
|
this.lastSuccessState = state;
|
|
@@ -17774,15 +18085,16 @@ var ProviderInstanceManager = class {
|
|
|
17774
18085
|
};
|
|
17775
18086
|
|
|
17776
18087
|
// src/index.ts
|
|
18088
|
+
init_io_contracts();
|
|
17777
18089
|
init_chat_message_normalization();
|
|
17778
18090
|
|
|
17779
18091
|
// src/providers/version-archive.ts
|
|
17780
18092
|
var fs10 = __toESM(require("fs"));
|
|
17781
|
-
var
|
|
18093
|
+
var path17 = __toESM(require("path"));
|
|
17782
18094
|
var os18 = __toESM(require("os"));
|
|
17783
18095
|
var import_child_process9 = require("child_process");
|
|
17784
18096
|
var import_os3 = require("os");
|
|
17785
|
-
var ARCHIVE_PATH =
|
|
18097
|
+
var ARCHIVE_PATH = path17.join(os18.homedir(), ".adhdev", "version-history.json");
|
|
17786
18098
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
17787
18099
|
var VersionArchive = class {
|
|
17788
18100
|
history = {};
|
|
@@ -17829,7 +18141,7 @@ var VersionArchive = class {
|
|
|
17829
18141
|
}
|
|
17830
18142
|
save() {
|
|
17831
18143
|
try {
|
|
17832
|
-
fs10.mkdirSync(
|
|
18144
|
+
fs10.mkdirSync(path17.dirname(ARCHIVE_PATH), { recursive: true });
|
|
17833
18145
|
fs10.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
17834
18146
|
} catch {
|
|
17835
18147
|
}
|
|
@@ -17886,7 +18198,7 @@ function checkPathExists2(paths) {
|
|
|
17886
18198
|
for (const p of paths) {
|
|
17887
18199
|
if (p.includes("*")) {
|
|
17888
18200
|
const home = os18.homedir();
|
|
17889
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
18201
|
+
const resolved = p.replace(/\*/g, home.split(path17.sep).pop() || "");
|
|
17890
18202
|
if (fs10.existsSync(resolved)) return resolved;
|
|
17891
18203
|
} else {
|
|
17892
18204
|
if (fs10.existsSync(p)) return p;
|
|
@@ -17896,7 +18208,7 @@ function checkPathExists2(paths) {
|
|
|
17896
18208
|
}
|
|
17897
18209
|
function getMacAppVersion(appPath) {
|
|
17898
18210
|
if ((0, import_os3.platform)() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
17899
|
-
const plistPath =
|
|
18211
|
+
const plistPath = path17.join(appPath, "Contents", "Info.plist");
|
|
17900
18212
|
if (!fs10.existsSync(plistPath)) return null;
|
|
17901
18213
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
17902
18214
|
return raw || null;
|
|
@@ -17922,7 +18234,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
17922
18234
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
17923
18235
|
let resolvedBin = cliBin;
|
|
17924
18236
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
17925
|
-
const bundled =
|
|
18237
|
+
const bundled = path17.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
17926
18238
|
if (provider.cli && fs10.existsSync(bundled)) resolvedBin = bundled;
|
|
17927
18239
|
}
|
|
17928
18240
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -17963,7 +18275,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
17963
18275
|
// src/daemon/dev-server.ts
|
|
17964
18276
|
var http2 = __toESM(require("http"));
|
|
17965
18277
|
var fs14 = __toESM(require("fs"));
|
|
17966
|
-
var
|
|
18278
|
+
var path21 = __toESM(require("path"));
|
|
17967
18279
|
init_config();
|
|
17968
18280
|
|
|
17969
18281
|
// src/daemon/scaffold-template.ts
|
|
@@ -18307,7 +18619,7 @@ init_logger();
|
|
|
18307
18619
|
|
|
18308
18620
|
// src/daemon/dev-cdp-handlers.ts
|
|
18309
18621
|
var fs11 = __toESM(require("fs"));
|
|
18310
|
-
var
|
|
18622
|
+
var path18 = __toESM(require("path"));
|
|
18311
18623
|
init_logger();
|
|
18312
18624
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
18313
18625
|
const body = await ctx.readBody(req);
|
|
@@ -18486,17 +18798,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
18486
18798
|
return;
|
|
18487
18799
|
}
|
|
18488
18800
|
let scriptsPath = "";
|
|
18489
|
-
const directScripts =
|
|
18801
|
+
const directScripts = path18.join(dir, "scripts.js");
|
|
18490
18802
|
if (fs11.existsSync(directScripts)) {
|
|
18491
18803
|
scriptsPath = directScripts;
|
|
18492
18804
|
} else {
|
|
18493
|
-
const scriptsDir =
|
|
18805
|
+
const scriptsDir = path18.join(dir, "scripts");
|
|
18494
18806
|
if (fs11.existsSync(scriptsDir)) {
|
|
18495
18807
|
const versions = fs11.readdirSync(scriptsDir).filter((d) => {
|
|
18496
|
-
return fs11.statSync(
|
|
18808
|
+
return fs11.statSync(path18.join(scriptsDir, d)).isDirectory();
|
|
18497
18809
|
}).sort().reverse();
|
|
18498
18810
|
for (const ver of versions) {
|
|
18499
|
-
const p =
|
|
18811
|
+
const p = path18.join(scriptsDir, ver, "scripts.js");
|
|
18500
18812
|
if (fs11.existsSync(p)) {
|
|
18501
18813
|
scriptsPath = p;
|
|
18502
18814
|
break;
|
|
@@ -19325,7 +19637,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
19325
19637
|
|
|
19326
19638
|
// src/daemon/dev-cli-debug.ts
|
|
19327
19639
|
var fs12 = __toESM(require("fs"));
|
|
19328
|
-
var
|
|
19640
|
+
var path19 = __toESM(require("path"));
|
|
19329
19641
|
function slugifyFixtureName(value) {
|
|
19330
19642
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
19331
19643
|
return normalized || `fixture-${Date.now()}`;
|
|
@@ -19335,11 +19647,11 @@ function getCliFixtureDir(ctx, type) {
|
|
|
19335
19647
|
if (!providerDir) {
|
|
19336
19648
|
throw new Error(`Provider directory not found for '${type}'`);
|
|
19337
19649
|
}
|
|
19338
|
-
return
|
|
19650
|
+
return path19.join(providerDir, "fixtures");
|
|
19339
19651
|
}
|
|
19340
19652
|
function readCliFixture(ctx, type, name) {
|
|
19341
19653
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
19342
|
-
const filePath =
|
|
19654
|
+
const filePath = path19.join(fixtureDir, `${name}.json`);
|
|
19343
19655
|
if (!fs12.existsSync(filePath)) {
|
|
19344
19656
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
19345
19657
|
}
|
|
@@ -20106,7 +20418,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
20106
20418
|
},
|
|
20107
20419
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
20108
20420
|
};
|
|
20109
|
-
const filePath =
|
|
20421
|
+
const filePath = path19.join(fixtureDir, `${name}.json`);
|
|
20110
20422
|
fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
20111
20423
|
ctx.json(res, 200, {
|
|
20112
20424
|
saved: true,
|
|
@@ -20130,7 +20442,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
|
|
|
20130
20442
|
return;
|
|
20131
20443
|
}
|
|
20132
20444
|
const fixtures = fs12.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
|
|
20133
|
-
const fullPath =
|
|
20445
|
+
const fullPath = path19.join(fixtureDir, file);
|
|
20134
20446
|
try {
|
|
20135
20447
|
const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
|
|
20136
20448
|
return {
|
|
@@ -20266,7 +20578,7 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
20266
20578
|
|
|
20267
20579
|
// src/daemon/dev-auto-implement.ts
|
|
20268
20580
|
var fs13 = __toESM(require("fs"));
|
|
20269
|
-
var
|
|
20581
|
+
var path20 = __toESM(require("path"));
|
|
20270
20582
|
var os19 = __toESM(require("os"));
|
|
20271
20583
|
function getAutoImplPid(ctx) {
|
|
20272
20584
|
const pid = ctx.autoImplProcess?.pid;
|
|
@@ -20323,22 +20635,22 @@ function getLatestScriptVersionDir(scriptsDir) {
|
|
|
20323
20635
|
if (!fs13.existsSync(scriptsDir)) return null;
|
|
20324
20636
|
const versions = fs13.readdirSync(scriptsDir).filter((d) => {
|
|
20325
20637
|
try {
|
|
20326
|
-
return fs13.statSync(
|
|
20638
|
+
return fs13.statSync(path20.join(scriptsDir, d)).isDirectory();
|
|
20327
20639
|
} catch {
|
|
20328
20640
|
return false;
|
|
20329
20641
|
}
|
|
20330
20642
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
20331
20643
|
if (versions.length === 0) return null;
|
|
20332
|
-
return
|
|
20644
|
+
return path20.join(scriptsDir, versions[0]);
|
|
20333
20645
|
}
|
|
20334
20646
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
20335
|
-
const canonicalUserDir =
|
|
20336
|
-
const desiredDir = requestedDir ?
|
|
20337
|
-
const upstreamRoot =
|
|
20338
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
20647
|
+
const canonicalUserDir = path20.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
20648
|
+
const desiredDir = requestedDir ? path20.resolve(requestedDir) : canonicalUserDir;
|
|
20649
|
+
const upstreamRoot = path20.resolve(ctx.providerLoader.getUpstreamDir());
|
|
20650
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path20.sep}`)) {
|
|
20339
20651
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
20340
20652
|
}
|
|
20341
|
-
if (
|
|
20653
|
+
if (path20.basename(desiredDir) !== type) {
|
|
20342
20654
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
20343
20655
|
}
|
|
20344
20656
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -20346,11 +20658,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
20346
20658
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
20347
20659
|
}
|
|
20348
20660
|
if (!fs13.existsSync(desiredDir)) {
|
|
20349
|
-
fs13.mkdirSync(
|
|
20661
|
+
fs13.mkdirSync(path20.dirname(desiredDir), { recursive: true });
|
|
20350
20662
|
fs13.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
20351
20663
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
20352
20664
|
}
|
|
20353
|
-
const providerJson =
|
|
20665
|
+
const providerJson = path20.join(desiredDir, "provider.json");
|
|
20354
20666
|
if (!fs13.existsSync(providerJson)) {
|
|
20355
20667
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
20356
20668
|
}
|
|
@@ -20361,13 +20673,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
20361
20673
|
const refDir = ctx.findProviderDir(referenceType);
|
|
20362
20674
|
if (!refDir || !fs13.existsSync(refDir)) return {};
|
|
20363
20675
|
const referenceScripts = {};
|
|
20364
|
-
const scriptsDir =
|
|
20676
|
+
const scriptsDir = path20.join(refDir, "scripts");
|
|
20365
20677
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
20366
20678
|
if (!latestDir) return referenceScripts;
|
|
20367
20679
|
for (const file of fs13.readdirSync(latestDir)) {
|
|
20368
20680
|
if (!file.endsWith(".js")) continue;
|
|
20369
20681
|
try {
|
|
20370
|
-
referenceScripts[file] = fs13.readFileSync(
|
|
20682
|
+
referenceScripts[file] = fs13.readFileSync(path20.join(latestDir, file), "utf-8");
|
|
20371
20683
|
} catch {
|
|
20372
20684
|
}
|
|
20373
20685
|
}
|
|
@@ -20475,9 +20787,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
20475
20787
|
});
|
|
20476
20788
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
20477
20789
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
20478
|
-
const tmpDir =
|
|
20790
|
+
const tmpDir = path20.join(os19.tmpdir(), "adhdev-autoimpl");
|
|
20479
20791
|
if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
|
|
20480
|
-
const promptFile =
|
|
20792
|
+
const promptFile = path20.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
20481
20793
|
fs13.writeFileSync(promptFile, prompt, "utf-8");
|
|
20482
20794
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
20483
20795
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -20914,7 +21226,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
20914
21226
|
setMode: "set_mode.js"
|
|
20915
21227
|
};
|
|
20916
21228
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
20917
|
-
const scriptsDir =
|
|
21229
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
20918
21230
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
20919
21231
|
if (latestScriptsDir) {
|
|
20920
21232
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -20925,7 +21237,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
20925
21237
|
for (const file of fs13.readdirSync(latestScriptsDir)) {
|
|
20926
21238
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
20927
21239
|
try {
|
|
20928
|
-
const content = fs13.readFileSync(
|
|
21240
|
+
const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
20929
21241
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
20930
21242
|
lines.push("```javascript");
|
|
20931
21243
|
lines.push(content);
|
|
@@ -20942,7 +21254,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
20942
21254
|
lines.push("");
|
|
20943
21255
|
for (const file of refFiles) {
|
|
20944
21256
|
try {
|
|
20945
|
-
const content = fs13.readFileSync(
|
|
21257
|
+
const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
20946
21258
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
20947
21259
|
lines.push("```javascript");
|
|
20948
21260
|
lines.push(content);
|
|
@@ -20983,10 +21295,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
20983
21295
|
lines.push("");
|
|
20984
21296
|
}
|
|
20985
21297
|
}
|
|
20986
|
-
const docsDir =
|
|
21298
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
20987
21299
|
const loadGuide = (name) => {
|
|
20988
21300
|
try {
|
|
20989
|
-
const p =
|
|
21301
|
+
const p = path20.join(docsDir, name);
|
|
20990
21302
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
20991
21303
|
} catch {
|
|
20992
21304
|
}
|
|
@@ -21223,7 +21535,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
21223
21535
|
parseApproval: "parse_approval.js"
|
|
21224
21536
|
};
|
|
21225
21537
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
21226
|
-
const scriptsDir =
|
|
21538
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
21227
21539
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
21228
21540
|
if (latestScriptsDir) {
|
|
21229
21541
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -21235,7 +21547,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
21235
21547
|
if (!file.endsWith(".js")) continue;
|
|
21236
21548
|
if (!targetFileNames.has(file)) continue;
|
|
21237
21549
|
try {
|
|
21238
|
-
const content = fs13.readFileSync(
|
|
21550
|
+
const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
21239
21551
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
21240
21552
|
lines.push("```javascript");
|
|
21241
21553
|
lines.push(content);
|
|
@@ -21251,7 +21563,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
21251
21563
|
lines.push("");
|
|
21252
21564
|
for (const file of refFiles) {
|
|
21253
21565
|
try {
|
|
21254
|
-
const content = fs13.readFileSync(
|
|
21566
|
+
const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
21255
21567
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
21256
21568
|
lines.push("```javascript");
|
|
21257
21569
|
lines.push(content);
|
|
@@ -21284,10 +21596,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
21284
21596
|
lines.push("");
|
|
21285
21597
|
}
|
|
21286
21598
|
}
|
|
21287
|
-
const docsDir =
|
|
21599
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
21288
21600
|
const loadGuide = (name) => {
|
|
21289
21601
|
try {
|
|
21290
|
-
const p =
|
|
21602
|
+
const p = path20.join(docsDir, name);
|
|
21291
21603
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
21292
21604
|
} catch {
|
|
21293
21605
|
}
|
|
@@ -21734,8 +22046,8 @@ var DevServer = class _DevServer {
|
|
|
21734
22046
|
}
|
|
21735
22047
|
getEndpointList() {
|
|
21736
22048
|
return this.routes.map((r) => {
|
|
21737
|
-
const
|
|
21738
|
-
return `${r.method.padEnd(5)} ${
|
|
22049
|
+
const path22 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
22050
|
+
return `${r.method.padEnd(5)} ${path22}`;
|
|
21739
22051
|
});
|
|
21740
22052
|
}
|
|
21741
22053
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -22016,12 +22328,12 @@ var DevServer = class _DevServer {
|
|
|
22016
22328
|
// ─── DevConsole SPA ───
|
|
22017
22329
|
getConsoleDistDir() {
|
|
22018
22330
|
const candidates = [
|
|
22019
|
-
|
|
22020
|
-
|
|
22021
|
-
|
|
22331
|
+
path21.resolve(__dirname, "../../web-devconsole/dist"),
|
|
22332
|
+
path21.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
22333
|
+
path21.join(process.cwd(), "packages/web-devconsole/dist")
|
|
22022
22334
|
];
|
|
22023
22335
|
for (const dir of candidates) {
|
|
22024
|
-
if (fs14.existsSync(
|
|
22336
|
+
if (fs14.existsSync(path21.join(dir, "index.html"))) return dir;
|
|
22025
22337
|
}
|
|
22026
22338
|
return null;
|
|
22027
22339
|
}
|
|
@@ -22031,7 +22343,7 @@ var DevServer = class _DevServer {
|
|
|
22031
22343
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
22032
22344
|
return;
|
|
22033
22345
|
}
|
|
22034
|
-
const htmlPath =
|
|
22346
|
+
const htmlPath = path21.join(distDir, "index.html");
|
|
22035
22347
|
try {
|
|
22036
22348
|
const html = fs14.readFileSync(htmlPath, "utf-8");
|
|
22037
22349
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -22056,15 +22368,15 @@ var DevServer = class _DevServer {
|
|
|
22056
22368
|
this.json(res, 404, { error: "Not found" });
|
|
22057
22369
|
return;
|
|
22058
22370
|
}
|
|
22059
|
-
const safePath =
|
|
22060
|
-
const filePath =
|
|
22371
|
+
const safePath = path21.normalize(pathname).replace(/^\.\.\//, "");
|
|
22372
|
+
const filePath = path21.join(distDir, safePath);
|
|
22061
22373
|
if (!filePath.startsWith(distDir)) {
|
|
22062
22374
|
this.json(res, 403, { error: "Forbidden" });
|
|
22063
22375
|
return;
|
|
22064
22376
|
}
|
|
22065
22377
|
try {
|
|
22066
22378
|
const content = fs14.readFileSync(filePath);
|
|
22067
|
-
const ext =
|
|
22379
|
+
const ext = path21.extname(filePath);
|
|
22068
22380
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
22069
22381
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
22070
22382
|
res.end(content);
|
|
@@ -22177,9 +22489,9 @@ var DevServer = class _DevServer {
|
|
|
22177
22489
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
22178
22490
|
if (entry.isDirectory()) {
|
|
22179
22491
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
22180
|
-
scan(
|
|
22492
|
+
scan(path21.join(d, entry.name), rel);
|
|
22181
22493
|
} else {
|
|
22182
|
-
const stat = fs14.statSync(
|
|
22494
|
+
const stat = fs14.statSync(path21.join(d, entry.name));
|
|
22183
22495
|
files.push({ path: rel, size: stat.size, type: "file" });
|
|
22184
22496
|
}
|
|
22185
22497
|
}
|
|
@@ -22202,7 +22514,7 @@ var DevServer = class _DevServer {
|
|
|
22202
22514
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
22203
22515
|
return;
|
|
22204
22516
|
}
|
|
22205
|
-
const fullPath =
|
|
22517
|
+
const fullPath = path21.resolve(dir, path21.normalize(filePath));
|
|
22206
22518
|
if (!fullPath.startsWith(dir)) {
|
|
22207
22519
|
this.json(res, 403, { error: "Forbidden" });
|
|
22208
22520
|
return;
|
|
@@ -22227,14 +22539,14 @@ var DevServer = class _DevServer {
|
|
|
22227
22539
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
22228
22540
|
return;
|
|
22229
22541
|
}
|
|
22230
|
-
const fullPath =
|
|
22542
|
+
const fullPath = path21.resolve(dir, path21.normalize(filePath));
|
|
22231
22543
|
if (!fullPath.startsWith(dir)) {
|
|
22232
22544
|
this.json(res, 403, { error: "Forbidden" });
|
|
22233
22545
|
return;
|
|
22234
22546
|
}
|
|
22235
22547
|
try {
|
|
22236
22548
|
if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
|
|
22237
|
-
fs14.mkdirSync(
|
|
22549
|
+
fs14.mkdirSync(path21.dirname(fullPath), { recursive: true });
|
|
22238
22550
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
22239
22551
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
22240
22552
|
this.providerLoader.reload();
|
|
@@ -22251,7 +22563,7 @@ var DevServer = class _DevServer {
|
|
|
22251
22563
|
return;
|
|
22252
22564
|
}
|
|
22253
22565
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
22254
|
-
const p =
|
|
22566
|
+
const p = path21.join(dir, name);
|
|
22255
22567
|
if (fs14.existsSync(p)) {
|
|
22256
22568
|
const source = fs14.readFileSync(p, "utf-8");
|
|
22257
22569
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -22272,8 +22584,8 @@ var DevServer = class _DevServer {
|
|
|
22272
22584
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
22273
22585
|
return;
|
|
22274
22586
|
}
|
|
22275
|
-
const target = fs14.existsSync(
|
|
22276
|
-
const targetPath =
|
|
22587
|
+
const target = fs14.existsSync(path21.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
22588
|
+
const targetPath = path21.join(dir, target);
|
|
22277
22589
|
try {
|
|
22278
22590
|
if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
|
|
22279
22591
|
fs14.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -22420,7 +22732,7 @@ var DevServer = class _DevServer {
|
|
|
22420
22732
|
}
|
|
22421
22733
|
let targetDir;
|
|
22422
22734
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
22423
|
-
const jsonPath =
|
|
22735
|
+
const jsonPath = path21.join(targetDir, "provider.json");
|
|
22424
22736
|
if (fs14.existsSync(jsonPath)) {
|
|
22425
22737
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
22426
22738
|
return;
|
|
@@ -22432,8 +22744,8 @@ var DevServer = class _DevServer {
|
|
|
22432
22744
|
const createdFiles = ["provider.json"];
|
|
22433
22745
|
if (result.files) {
|
|
22434
22746
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
22435
|
-
const fullPath =
|
|
22436
|
-
fs14.mkdirSync(
|
|
22747
|
+
const fullPath = path21.join(targetDir, relPath);
|
|
22748
|
+
fs14.mkdirSync(path21.dirname(fullPath), { recursive: true });
|
|
22437
22749
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
22438
22750
|
createdFiles.push(relPath);
|
|
22439
22751
|
}
|
|
@@ -22486,22 +22798,22 @@ var DevServer = class _DevServer {
|
|
|
22486
22798
|
if (!fs14.existsSync(scriptsDir)) return null;
|
|
22487
22799
|
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
22488
22800
|
try {
|
|
22489
|
-
return fs14.statSync(
|
|
22801
|
+
return fs14.statSync(path21.join(scriptsDir, d)).isDirectory();
|
|
22490
22802
|
} catch {
|
|
22491
22803
|
return false;
|
|
22492
22804
|
}
|
|
22493
22805
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
22494
22806
|
if (versions.length === 0) return null;
|
|
22495
|
-
return
|
|
22807
|
+
return path21.join(scriptsDir, versions[0]);
|
|
22496
22808
|
}
|
|
22497
22809
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
22498
|
-
const canonicalUserDir =
|
|
22499
|
-
const desiredDir = requestedDir ?
|
|
22500
|
-
const upstreamRoot =
|
|
22501
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
22810
|
+
const canonicalUserDir = path21.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
22811
|
+
const desiredDir = requestedDir ? path21.resolve(requestedDir) : canonicalUserDir;
|
|
22812
|
+
const upstreamRoot = path21.resolve(this.providerLoader.getUpstreamDir());
|
|
22813
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path21.sep}`)) {
|
|
22502
22814
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
22503
22815
|
}
|
|
22504
|
-
if (
|
|
22816
|
+
if (path21.basename(desiredDir) !== type) {
|
|
22505
22817
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
22506
22818
|
}
|
|
22507
22819
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -22509,11 +22821,11 @@ var DevServer = class _DevServer {
|
|
|
22509
22821
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
22510
22822
|
}
|
|
22511
22823
|
if (!fs14.existsSync(desiredDir)) {
|
|
22512
|
-
fs14.mkdirSync(
|
|
22824
|
+
fs14.mkdirSync(path21.dirname(desiredDir), { recursive: true });
|
|
22513
22825
|
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
22514
22826
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
22515
22827
|
}
|
|
22516
|
-
const providerJson =
|
|
22828
|
+
const providerJson = path21.join(desiredDir, "provider.json");
|
|
22517
22829
|
if (!fs14.existsSync(providerJson)) {
|
|
22518
22830
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
22519
22831
|
}
|
|
@@ -22549,7 +22861,7 @@ var DevServer = class _DevServer {
|
|
|
22549
22861
|
setMode: "set_mode.js"
|
|
22550
22862
|
};
|
|
22551
22863
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
22552
|
-
const scriptsDir =
|
|
22864
|
+
const scriptsDir = path21.join(providerDir, "scripts");
|
|
22553
22865
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
22554
22866
|
if (latestScriptsDir) {
|
|
22555
22867
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -22560,7 +22872,7 @@ var DevServer = class _DevServer {
|
|
|
22560
22872
|
for (const file of fs14.readdirSync(latestScriptsDir)) {
|
|
22561
22873
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
22562
22874
|
try {
|
|
22563
|
-
const content = fs14.readFileSync(
|
|
22875
|
+
const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
|
|
22564
22876
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
22565
22877
|
lines.push("```javascript");
|
|
22566
22878
|
lines.push(content);
|
|
@@ -22577,7 +22889,7 @@ var DevServer = class _DevServer {
|
|
|
22577
22889
|
lines.push("");
|
|
22578
22890
|
for (const file of refFiles) {
|
|
22579
22891
|
try {
|
|
22580
|
-
const content = fs14.readFileSync(
|
|
22892
|
+
const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
|
|
22581
22893
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
22582
22894
|
lines.push("```javascript");
|
|
22583
22895
|
lines.push(content);
|
|
@@ -22618,10 +22930,10 @@ var DevServer = class _DevServer {
|
|
|
22618
22930
|
lines.push("");
|
|
22619
22931
|
}
|
|
22620
22932
|
}
|
|
22621
|
-
const docsDir =
|
|
22933
|
+
const docsDir = path21.join(providerDir, "../../docs");
|
|
22622
22934
|
const loadGuide = (name) => {
|
|
22623
22935
|
try {
|
|
22624
|
-
const p =
|
|
22936
|
+
const p = path21.join(docsDir, name);
|
|
22625
22937
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
22626
22938
|
} catch {
|
|
22627
22939
|
}
|
|
@@ -22795,7 +23107,7 @@ var DevServer = class _DevServer {
|
|
|
22795
23107
|
parseApproval: "parse_approval.js"
|
|
22796
23108
|
};
|
|
22797
23109
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
22798
|
-
const scriptsDir =
|
|
23110
|
+
const scriptsDir = path21.join(providerDir, "scripts");
|
|
22799
23111
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
22800
23112
|
if (latestScriptsDir) {
|
|
22801
23113
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -22807,7 +23119,7 @@ var DevServer = class _DevServer {
|
|
|
22807
23119
|
if (!file.endsWith(".js")) continue;
|
|
22808
23120
|
if (!targetFileNames.has(file)) continue;
|
|
22809
23121
|
try {
|
|
22810
|
-
const content = fs14.readFileSync(
|
|
23122
|
+
const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
|
|
22811
23123
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
22812
23124
|
lines.push("```javascript");
|
|
22813
23125
|
lines.push(content);
|
|
@@ -22823,7 +23135,7 @@ var DevServer = class _DevServer {
|
|
|
22823
23135
|
lines.push("");
|
|
22824
23136
|
for (const file of refFiles) {
|
|
22825
23137
|
try {
|
|
22826
|
-
const content = fs14.readFileSync(
|
|
23138
|
+
const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
|
|
22827
23139
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
22828
23140
|
lines.push("```javascript");
|
|
22829
23141
|
lines.push(content);
|
|
@@ -22856,10 +23168,10 @@ var DevServer = class _DevServer {
|
|
|
22856
23168
|
lines.push("");
|
|
22857
23169
|
}
|
|
22858
23170
|
}
|
|
22859
|
-
const docsDir =
|
|
23171
|
+
const docsDir = path21.join(providerDir, "../../docs");
|
|
22860
23172
|
const loadGuide = (name) => {
|
|
22861
23173
|
try {
|
|
22862
|
-
const p =
|
|
23174
|
+
const p = path21.join(docsDir, name);
|
|
22863
23175
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
22864
23176
|
} catch {
|
|
22865
23177
|
}
|