@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.mjs
CHANGED
|
@@ -453,6 +453,231 @@ var init_logger = __esm({
|
|
|
453
453
|
}
|
|
454
454
|
});
|
|
455
455
|
|
|
456
|
+
// src/providers/io-contracts.ts
|
|
457
|
+
function normalizeInputEnvelope(input) {
|
|
458
|
+
const normalized = normalizeInputEnvelopePayload(input);
|
|
459
|
+
const textFallback = normalized.textFallback ?? flattenInputParts(normalized.parts);
|
|
460
|
+
return {
|
|
461
|
+
parts: normalized.parts,
|
|
462
|
+
textFallback,
|
|
463
|
+
...normalized.metadata ? { metadata: normalized.metadata } : {}
|
|
464
|
+
};
|
|
465
|
+
}
|
|
466
|
+
function normalizeMessageParts(content) {
|
|
467
|
+
if (typeof content === "string") return [{ type: "text", text: content }];
|
|
468
|
+
if (!Array.isArray(content)) {
|
|
469
|
+
if (content && typeof content === "object" && typeof content.text === "string") {
|
|
470
|
+
return [{ type: "text", text: String(content.text) }];
|
|
471
|
+
}
|
|
472
|
+
return [];
|
|
473
|
+
}
|
|
474
|
+
const parts = [];
|
|
475
|
+
for (const raw of content) {
|
|
476
|
+
if (typeof raw === "string") {
|
|
477
|
+
parts.push({ type: "text", text: raw });
|
|
478
|
+
continue;
|
|
479
|
+
}
|
|
480
|
+
if (!raw || typeof raw !== "object") continue;
|
|
481
|
+
const part = normalizeMessagePartObject(raw);
|
|
482
|
+
if (part) parts.push(part);
|
|
483
|
+
}
|
|
484
|
+
return parts;
|
|
485
|
+
}
|
|
486
|
+
function flattenMessageParts(parts) {
|
|
487
|
+
return parts.map((part) => {
|
|
488
|
+
if (part.type === "text") return part.text;
|
|
489
|
+
if (part.type === "resource") return part.resource.text || "";
|
|
490
|
+
return "";
|
|
491
|
+
}).filter((value) => value.length > 0).join("\n");
|
|
492
|
+
}
|
|
493
|
+
function normalizeInputEnvelopePayload(input) {
|
|
494
|
+
if (typeof input === "string") {
|
|
495
|
+
return { parts: [{ type: "text", text: input }], textFallback: input };
|
|
496
|
+
}
|
|
497
|
+
if (!input || typeof input !== "object") {
|
|
498
|
+
return { parts: [], textFallback: "" };
|
|
499
|
+
}
|
|
500
|
+
const record = input;
|
|
501
|
+
const nestedInput = record.input;
|
|
502
|
+
if (nestedInput && typeof nestedInput === "object") {
|
|
503
|
+
const nested = nestedInput;
|
|
504
|
+
return {
|
|
505
|
+
parts: normalizeInputParts(nested.parts ?? nested.prompt),
|
|
506
|
+
textFallback: typeof nested.textFallback === "string" ? nested.textFallback : void 0,
|
|
507
|
+
metadata: normalizeInputMetadata(nested.metadata)
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
const directText = typeof record.text === "string" ? record.text : typeof record.message === "string" ? record.message : void 0;
|
|
511
|
+
if (directText !== void 0) {
|
|
512
|
+
return { parts: [{ type: "text", text: directText }], textFallback: directText };
|
|
513
|
+
}
|
|
514
|
+
const directParts = normalizeInputParts(record.parts ?? record.prompt);
|
|
515
|
+
return {
|
|
516
|
+
parts: directParts,
|
|
517
|
+
textFallback: typeof record.textFallback === "string" ? record.textFallback : void 0,
|
|
518
|
+
metadata: normalizeInputMetadata(record.metadata)
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
function normalizeInputMetadata(value) {
|
|
522
|
+
if (!value || typeof value !== "object") return void 0;
|
|
523
|
+
const record = value;
|
|
524
|
+
const metadata = {};
|
|
525
|
+
if (record.source === "dashboard" || record.source === "shortcut_api" || record.source === "provider_script" || record.source === "session_replay") {
|
|
526
|
+
metadata.source = record.source;
|
|
527
|
+
}
|
|
528
|
+
if (typeof record.clientTimestamp === "number" && Number.isFinite(record.clientTimestamp)) {
|
|
529
|
+
metadata.clientTimestamp = record.clientTimestamp;
|
|
530
|
+
}
|
|
531
|
+
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
532
|
+
}
|
|
533
|
+
function normalizeInputParts(value) {
|
|
534
|
+
if (!Array.isArray(value)) return [];
|
|
535
|
+
const parts = [];
|
|
536
|
+
for (const raw of value) {
|
|
537
|
+
if (typeof raw === "string") {
|
|
538
|
+
parts.push({ type: "text", text: raw });
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
if (!raw || typeof raw !== "object") continue;
|
|
542
|
+
const part = normalizeInputPartObject(raw);
|
|
543
|
+
if (part) parts.push(part);
|
|
544
|
+
}
|
|
545
|
+
return parts;
|
|
546
|
+
}
|
|
547
|
+
function normalizeInputPartObject(raw) {
|
|
548
|
+
const type = raw.type;
|
|
549
|
+
if (type === "text" && typeof raw.text === "string") {
|
|
550
|
+
return { type, text: raw.text };
|
|
551
|
+
}
|
|
552
|
+
if (type === "image" && typeof raw.mimeType === "string") {
|
|
553
|
+
return {
|
|
554
|
+
type,
|
|
555
|
+
mimeType: raw.mimeType,
|
|
556
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
557
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
558
|
+
...typeof raw.alt === "string" ? { alt: raw.alt } : {}
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
if (type === "audio" && typeof raw.mimeType === "string") {
|
|
562
|
+
return {
|
|
563
|
+
type,
|
|
564
|
+
mimeType: raw.mimeType,
|
|
565
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
566
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
567
|
+
...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
|
|
568
|
+
};
|
|
569
|
+
}
|
|
570
|
+
if (type === "video" && typeof raw.mimeType === "string") {
|
|
571
|
+
return {
|
|
572
|
+
type,
|
|
573
|
+
mimeType: raw.mimeType,
|
|
574
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
575
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
576
|
+
...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
|
|
577
|
+
};
|
|
578
|
+
}
|
|
579
|
+
if (type === "resource" && typeof raw.uri === "string") {
|
|
580
|
+
return {
|
|
581
|
+
type,
|
|
582
|
+
uri: raw.uri,
|
|
583
|
+
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
584
|
+
...typeof raw.name === "string" ? { name: raw.name } : {},
|
|
585
|
+
...typeof raw.text === "string" ? { text: raw.text } : {},
|
|
586
|
+
...typeof raw.data === "string" ? { data: raw.data } : {}
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
if (type === "resource_link" && typeof raw.uri === "string") {
|
|
590
|
+
return {
|
|
591
|
+
type: "resource",
|
|
592
|
+
uri: raw.uri,
|
|
593
|
+
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
594
|
+
...typeof raw.name === "string" ? { name: raw.name } : {}
|
|
595
|
+
};
|
|
596
|
+
}
|
|
597
|
+
return null;
|
|
598
|
+
}
|
|
599
|
+
function normalizeMessagePartObject(raw) {
|
|
600
|
+
const type = raw.type;
|
|
601
|
+
if (type === "text" && typeof raw.text === "string") {
|
|
602
|
+
return { type, text: raw.text };
|
|
603
|
+
}
|
|
604
|
+
if (type === "image" && typeof raw.mimeType === "string") {
|
|
605
|
+
return {
|
|
606
|
+
type,
|
|
607
|
+
mimeType: raw.mimeType,
|
|
608
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
609
|
+
...typeof raw.data === "string" ? { data: raw.data } : {}
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
if (type === "audio" && typeof raw.mimeType === "string") {
|
|
613
|
+
return {
|
|
614
|
+
type,
|
|
615
|
+
mimeType: raw.mimeType,
|
|
616
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
617
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
618
|
+
...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
if (type === "video" && typeof raw.mimeType === "string") {
|
|
622
|
+
return {
|
|
623
|
+
type,
|
|
624
|
+
mimeType: raw.mimeType,
|
|
625
|
+
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
626
|
+
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
627
|
+
...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
if (type === "resource_link" && typeof raw.uri === "string" && typeof raw.name === "string") {
|
|
631
|
+
return {
|
|
632
|
+
type,
|
|
633
|
+
uri: raw.uri,
|
|
634
|
+
name: raw.name,
|
|
635
|
+
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
636
|
+
...typeof raw.size === "number" ? { size: raw.size } : {}
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
if (type === "resource" && raw.resource && typeof raw.resource === "object") {
|
|
640
|
+
const resource = raw.resource;
|
|
641
|
+
if (typeof resource.uri !== "string") return null;
|
|
642
|
+
return {
|
|
643
|
+
type,
|
|
644
|
+
resource: {
|
|
645
|
+
uri: resource.uri,
|
|
646
|
+
...typeof resource.mimeType === "string" || resource.mimeType === null ? { mimeType: resource.mimeType } : {},
|
|
647
|
+
...typeof resource.text === "string" ? { text: resource.text } : {},
|
|
648
|
+
...typeof resource.blob === "string" ? { blob: resource.blob } : {}
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
}
|
|
652
|
+
return null;
|
|
653
|
+
}
|
|
654
|
+
function flattenInputParts(parts) {
|
|
655
|
+
return parts.map((part) => {
|
|
656
|
+
if (part.type === "text") return part.text;
|
|
657
|
+
if (part.type === "audio") return part.transcript || "";
|
|
658
|
+
if (part.type === "resource") return part.text || "";
|
|
659
|
+
return "";
|
|
660
|
+
}).filter((value) => value.length > 0).join("\n");
|
|
661
|
+
}
|
|
662
|
+
var init_io_contracts = __esm({
|
|
663
|
+
"src/providers/io-contracts.ts"() {
|
|
664
|
+
"use strict";
|
|
665
|
+
}
|
|
666
|
+
});
|
|
667
|
+
|
|
668
|
+
// src/providers/contracts.ts
|
|
669
|
+
function flattenContent(content) {
|
|
670
|
+
if (typeof content === "string") return content;
|
|
671
|
+
return flattenMessageParts(normalizeMessageParts(content));
|
|
672
|
+
}
|
|
673
|
+
var init_contracts = __esm({
|
|
674
|
+
"src/providers/contracts.ts"() {
|
|
675
|
+
"use strict";
|
|
676
|
+
init_io_contracts();
|
|
677
|
+
init_io_contracts();
|
|
678
|
+
}
|
|
679
|
+
});
|
|
680
|
+
|
|
456
681
|
// src/providers/chat-message-normalization.ts
|
|
457
682
|
function canonicalizeKindHint(value) {
|
|
458
683
|
return value.trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
@@ -603,39 +828,161 @@ var init_chat_message_normalization = __esm({
|
|
|
603
828
|
}
|
|
604
829
|
});
|
|
605
830
|
|
|
606
|
-
// src/
|
|
607
|
-
function
|
|
608
|
-
|
|
609
|
-
const message = error.message || "";
|
|
610
|
-
const code = "code" in error ? error.code : void 0;
|
|
611
|
-
return code === "MODULE_NOT_FOUND" && message.includes(ref);
|
|
831
|
+
// src/providers/read-chat-contract.ts
|
|
832
|
+
function isPlainObject3(value) {
|
|
833
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
612
834
|
}
|
|
613
|
-
function
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
835
|
+
function isFiniteNumber(value) {
|
|
836
|
+
return typeof value === "number" && Number.isFinite(value);
|
|
837
|
+
}
|
|
838
|
+
function validateStatus(status, source) {
|
|
839
|
+
if (typeof status !== "string" || !VALID_STATUSES.includes(status)) {
|
|
840
|
+
throw new Error(`${source}: status must be one of ${VALID_STATUSES.join(", ")}`);
|
|
617
841
|
}
|
|
618
|
-
return
|
|
842
|
+
return status;
|
|
619
843
|
}
|
|
620
|
-
function
|
|
621
|
-
|
|
622
|
-
|
|
844
|
+
function validateRole(role, source, index) {
|
|
845
|
+
if (typeof role !== "string" || !VALID_ROLES.includes(role)) {
|
|
846
|
+
throw new Error(`${source}: messages[${index}].role must be one of ${VALID_ROLES.join(", ")}`);
|
|
847
|
+
}
|
|
848
|
+
return role;
|
|
623
849
|
}
|
|
624
|
-
function
|
|
625
|
-
if (
|
|
626
|
-
|
|
627
|
-
|
|
850
|
+
function validateMessageContent(content, source, index) {
|
|
851
|
+
if (typeof content === "string") return content;
|
|
852
|
+
if (Array.isArray(content)) return normalizeMessageParts(content);
|
|
853
|
+
throw new Error(`${source}: messages[${index}].content must be a string or structured content array`);
|
|
854
|
+
}
|
|
855
|
+
function validateMessage(message, source, index) {
|
|
856
|
+
if (!isPlainObject3(message)) {
|
|
857
|
+
throw new Error(`${source}: messages[${index}] must be an object`);
|
|
858
|
+
}
|
|
859
|
+
const normalized = {
|
|
860
|
+
role: validateRole(message.role, source, index),
|
|
861
|
+
content: validateMessageContent(message.content, source, index)
|
|
862
|
+
};
|
|
863
|
+
if (typeof message.kind === "string") normalized.kind = message.kind;
|
|
864
|
+
if (typeof message.id === "string") normalized.id = message.id;
|
|
865
|
+
if (isFiniteNumber(message.index)) normalized.index = message.index;
|
|
866
|
+
if (isFiniteNumber(message.timestamp)) normalized.timestamp = message.timestamp;
|
|
867
|
+
if (isFiniteNumber(message.receivedAt)) normalized.receivedAt = message.receivedAt;
|
|
868
|
+
if (Array.isArray(message.toolCalls)) normalized.toolCalls = message.toolCalls;
|
|
869
|
+
if (isPlainObject3(message.meta)) normalized.meta = message.meta;
|
|
870
|
+
if (typeof message.senderName === "string") normalized.senderName = message.senderName;
|
|
871
|
+
if (typeof message._type === "string") normalized._type = message._type;
|
|
872
|
+
if (typeof message._sub === "string") normalized._sub = message._sub;
|
|
873
|
+
return normalized;
|
|
874
|
+
}
|
|
875
|
+
function validateModal(activeModal, status, source) {
|
|
876
|
+
if (activeModal == null) {
|
|
877
|
+
if (status === "waiting_approval") {
|
|
878
|
+
throw new Error(`${source}: waiting_approval status requires activeModal with buttons`);
|
|
628
879
|
}
|
|
629
|
-
return
|
|
880
|
+
return activeModal === null ? null : void 0;
|
|
630
881
|
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
}
|
|
882
|
+
if (!isPlainObject3(activeModal)) {
|
|
883
|
+
throw new Error(`${source}: activeModal must be an object when provided`);
|
|
884
|
+
}
|
|
885
|
+
if (typeof activeModal.message !== "string") {
|
|
886
|
+
throw new Error(`${source}: activeModal.message must be a string`);
|
|
887
|
+
}
|
|
888
|
+
if (!Array.isArray(activeModal.buttons) || activeModal.buttons.some((button) => typeof button !== "string" || !button.trim())) {
|
|
889
|
+
throw new Error(`${source}: activeModal.buttons must be a non-empty string array`);
|
|
890
|
+
}
|
|
891
|
+
const normalized = {
|
|
892
|
+
message: activeModal.message,
|
|
893
|
+
buttons: activeModal.buttons.map((button) => button.trim())
|
|
894
|
+
};
|
|
895
|
+
if (isFiniteNumber(activeModal.width)) normalized.width = activeModal.width;
|
|
896
|
+
if (isFiniteNumber(activeModal.height)) normalized.height = activeModal.height;
|
|
897
|
+
return normalized;
|
|
898
|
+
}
|
|
899
|
+
function validateControlValues(controlValues, source) {
|
|
900
|
+
if (controlValues === void 0) return void 0;
|
|
901
|
+
if (!isPlainObject3(controlValues)) {
|
|
902
|
+
throw new Error(`${source}: controlValues must be an object when provided`);
|
|
903
|
+
}
|
|
904
|
+
const normalized = {};
|
|
905
|
+
for (const [key, value] of Object.entries(controlValues)) {
|
|
906
|
+
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean") {
|
|
907
|
+
throw new Error(`${source}: controlValues.${key} must be string, number, or boolean`);
|
|
908
|
+
}
|
|
909
|
+
normalized[key] = value;
|
|
910
|
+
}
|
|
911
|
+
return normalized;
|
|
912
|
+
}
|
|
913
|
+
function validateReadChatResultPayload(raw, source = "read_chat") {
|
|
914
|
+
if (!isPlainObject3(raw)) {
|
|
915
|
+
throw new Error(`${source}: payload must be an object`);
|
|
916
|
+
}
|
|
917
|
+
const status = validateStatus(raw.status, source);
|
|
918
|
+
if (!Array.isArray(raw.messages)) {
|
|
919
|
+
throw new Error(`${source}: messages must be an array`);
|
|
920
|
+
}
|
|
921
|
+
const messages = raw.messages.map((message, index) => validateMessage(message, source, index));
|
|
922
|
+
const activeModal = validateModal(raw.activeModal, status, source);
|
|
923
|
+
const controlValues = validateControlValues(raw.controlValues, source);
|
|
924
|
+
const normalized = {
|
|
925
|
+
status,
|
|
926
|
+
messages
|
|
927
|
+
};
|
|
928
|
+
if (activeModal !== void 0) normalized.activeModal = activeModal;
|
|
929
|
+
if (typeof raw.id === "string") normalized.id = raw.id;
|
|
930
|
+
if (typeof raw.title === "string") normalized.title = raw.title;
|
|
931
|
+
if (typeof raw.agentType === "string") normalized.agentType = raw.agentType;
|
|
932
|
+
if (typeof raw.agentName === "string") normalized.agentName = raw.agentName;
|
|
933
|
+
if (typeof raw.extensionId === "string") normalized.extensionId = raw.extensionId;
|
|
934
|
+
if (typeof raw.inputContent === "string") normalized.inputContent = raw.inputContent;
|
|
935
|
+
if (typeof raw.isVisible === "boolean") normalized.isVisible = raw.isVisible;
|
|
936
|
+
if (typeof raw.isWelcomeScreen === "boolean") normalized.isWelcomeScreen = raw.isWelcomeScreen;
|
|
937
|
+
if (controlValues) normalized.controlValues = controlValues;
|
|
938
|
+
if (raw.summaryMetadata !== void 0) normalized.summaryMetadata = raw.summaryMetadata;
|
|
939
|
+
if (Array.isArray(raw.effects)) normalized.effects = raw.effects;
|
|
940
|
+
if (typeof raw.providerSessionId === "string") normalized.providerSessionId = raw.providerSessionId;
|
|
941
|
+
return normalized;
|
|
942
|
+
}
|
|
943
|
+
var VALID_STATUSES, VALID_ROLES;
|
|
944
|
+
var init_read_chat_contract = __esm({
|
|
945
|
+
"src/providers/read-chat-contract.ts"() {
|
|
946
|
+
"use strict";
|
|
947
|
+
init_contracts();
|
|
948
|
+
VALID_STATUSES = ["idle", "generating", "waiting_approval", "error", "panel_hidden", "streaming", "long_generating"];
|
|
949
|
+
VALID_ROLES = ["user", "assistant", "system", "human"];
|
|
950
|
+
}
|
|
951
|
+
});
|
|
952
|
+
|
|
953
|
+
// src/cli-adapters/terminal-backends/ghostty-vt-backend.ts
|
|
954
|
+
function isModuleNotFoundError(error, ref) {
|
|
955
|
+
if (!(error instanceof Error)) return false;
|
|
956
|
+
const message = error.message || "";
|
|
957
|
+
const code = "code" in error ? error.code : void 0;
|
|
958
|
+
return code === "MODULE_NOT_FOUND" && message.includes(ref);
|
|
959
|
+
}
|
|
960
|
+
function normalizeBinding(mod, ref) {
|
|
961
|
+
const binding = mod?.default?.createTerminal ? mod.default : mod?.createTerminal ? mod : null;
|
|
962
|
+
if (!binding) {
|
|
963
|
+
throw new Error(`Ghostty VT binding "${ref}" does not export createTerminal()`);
|
|
964
|
+
}
|
|
965
|
+
return binding;
|
|
966
|
+
}
|
|
967
|
+
function getBindingCandidates() {
|
|
968
|
+
const explicit = process.env.ADHDEV_GHOSTTY_VT_BINDING?.trim();
|
|
969
|
+
return explicit ? [explicit] : DEFAULT_BINDING_CANDIDATES;
|
|
970
|
+
}
|
|
971
|
+
function loadGhosttyVtBinding(required) {
|
|
972
|
+
if (cachedBinding !== void 0) {
|
|
973
|
+
if (!cachedBinding && required && cachedBindingError) {
|
|
974
|
+
throw cachedBindingError;
|
|
975
|
+
}
|
|
976
|
+
return cachedBinding;
|
|
977
|
+
}
|
|
978
|
+
const errors = [];
|
|
979
|
+
for (const ref of getBindingCandidates()) {
|
|
980
|
+
try {
|
|
981
|
+
const mod = __require(ref);
|
|
982
|
+
cachedBinding = normalizeBinding(mod, ref);
|
|
983
|
+
cachedBindingError = null;
|
|
984
|
+
return cachedBinding;
|
|
985
|
+
} catch (error) {
|
|
639
986
|
if (isModuleNotFoundError(error, ref)) {
|
|
640
987
|
errors.push(`${ref}: module not found`);
|
|
641
988
|
continue;
|
|
@@ -1460,6 +1807,7 @@ var init_provider_cli_adapter = __esm({
|
|
|
1460
1807
|
init_pty_transport();
|
|
1461
1808
|
init_provider_cli_shared();
|
|
1462
1809
|
init_chat_message_normalization();
|
|
1810
|
+
init_read_chat_contract();
|
|
1463
1811
|
init_provider_cli_parse();
|
|
1464
1812
|
init_provider_cli_config();
|
|
1465
1813
|
init_provider_cli_runtime();
|
|
@@ -2605,6 +2953,9 @@ var init_provider_cli_adapter = __esm({
|
|
|
2605
2953
|
runtimeSettings: this.runtimeSettings
|
|
2606
2954
|
});
|
|
2607
2955
|
const parsed = this.cliScripts.parseOutput(input);
|
|
2956
|
+
if (parsed && typeof parsed === "object") {
|
|
2957
|
+
Object.assign(parsed, validateReadChatResultPayload(parsed, `${this.cliType} parseOutput`));
|
|
2958
|
+
}
|
|
2608
2959
|
const refinedStatus = this.refineDetectedStatus(typeof parsed?.status === "string" ? parsed.status : null, input.recentBuffer, input.screenText);
|
|
2609
2960
|
if (parsed && refinedStatus && parsed.status !== refinedStatus) {
|
|
2610
2961
|
parsed.status = refinedStatus;
|
|
@@ -5070,351 +5421,142 @@ var CdpDomHandlers = class {
|
|
|
5070
5421
|
* args:
|
|
5071
5422
|
* ideType?: string — IDE type hint
|
|
5072
5423
|
* sessionId?: string — agent webview session ID
|
|
5073
|
-
*/
|
|
5074
|
-
async handleDomDebug(args) {
|
|
5075
|
-
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
5076
|
-
const sessionId = args?.sessionId;
|
|
5077
|
-
const expression = `(() => {
|
|
5078
|
-
const result = {
|
|
5079
|
-
url: location.href,
|
|
5080
|
-
title: document.title,
|
|
5081
|
-
viewport: { w: window.innerWidth, h: window.innerHeight },
|
|
5082
|
-
|
|
5083
|
-
// Input field info
|
|
5084
|
-
inputs: [],
|
|
5085
|
-
// Textarea info
|
|
5086
|
-
textareas: [],
|
|
5087
|
-
// Contenteditable info
|
|
5088
|
-
editables: [],
|
|
5089
|
-
// Buttons (send, submit etc)
|
|
5090
|
-
buttons: [],
|
|
5091
|
-
// iframes (agent webviews)
|
|
5092
|
-
iframes: [],
|
|
5093
|
-
// role="textbox" info
|
|
5094
|
-
textboxes: [],
|
|
5095
|
-
};
|
|
5096
|
-
|
|
5097
|
-
// Input fields
|
|
5098
|
-
document.querySelectorAll('input[type="text"], input:not([type])').forEach((el, i) => {
|
|
5099
|
-
if (i >= 10) return;
|
|
5100
|
-
result.inputs.push({
|
|
5101
|
-
tag: 'input',
|
|
5102
|
-
id: el.id || null,
|
|
5103
|
-
class: (el.className || '').toString().slice(0, 150),
|
|
5104
|
-
placeholder: el.getAttribute('placeholder') || null,
|
|
5105
|
-
name: el.name || null,
|
|
5106
|
-
value: el.value?.slice(0, 100) || null,
|
|
5107
|
-
visible: el.offsetParent !== null,
|
|
5108
|
-
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; } })(),
|
|
5109
|
-
});
|
|
5110
|
-
});
|
|
5111
|
-
|
|
5112
|
-
// textarea
|
|
5113
|
-
document.querySelectorAll('textarea').forEach((el, i) => {
|
|
5114
|
-
if (i >= 10) return;
|
|
5115
|
-
result.textareas.push({
|
|
5116
|
-
id: el.id || null,
|
|
5117
|
-
class: (el.className || '').toString().slice(0, 150),
|
|
5118
|
-
placeholder: el.getAttribute('placeholder') || null,
|
|
5119
|
-
rows: el.rows,
|
|
5120
|
-
value: el.value?.slice(0, 100) || null,
|
|
5121
|
-
visible: el.offsetParent !== null,
|
|
5122
|
-
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; } })(),
|
|
5123
|
-
});
|
|
5124
|
-
});
|
|
5125
|
-
|
|
5126
|
-
// contenteditable
|
|
5127
|
-
document.querySelectorAll('[contenteditable="true"]').forEach((el, i) => {
|
|
5128
|
-
if (i >= 10) return;
|
|
5129
|
-
result.editables.push({
|
|
5130
|
-
tag: el.tagName?.toLowerCase(),
|
|
5131
|
-
id: el.id || null,
|
|
5132
|
-
class: (el.className || '').toString().slice(0, 150),
|
|
5133
|
-
role: el.getAttribute('role') || null,
|
|
5134
|
-
text: (el.textContent || '').trim().slice(0, 100),
|
|
5135
|
-
visible: el.offsetParent !== null,
|
|
5136
|
-
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; } })(),
|
|
5137
|
-
});
|
|
5138
|
-
});
|
|
5139
|
-
|
|
5140
|
-
// role="textbox"
|
|
5141
|
-
document.querySelectorAll('[role="textbox"]').forEach((el, i) => {
|
|
5142
|
-
if (i >= 10) return;
|
|
5143
|
-
result.textboxes.push({
|
|
5144
|
-
tag: el.tagName?.toLowerCase(),
|
|
5145
|
-
id: el.id || null,
|
|
5146
|
-
class: (el.className || '').toString().slice(0, 150),
|
|
5147
|
-
'aria-label': el.getAttribute('aria-label') || null,
|
|
5148
|
-
text: (el.textContent || '').trim().slice(0, 100),
|
|
5149
|
-
visible: el.offsetParent !== null,
|
|
5150
|
-
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; } })(),
|
|
5151
|
-
});
|
|
5152
|
-
});
|
|
5153
|
-
|
|
5154
|
-
// Buttons (send, submit, accept, reject, approve etc)
|
|
5155
|
-
const btnKeywords = /send|submit|accept|reject|approve|deny|cancel|confirm|run|execute|apply/i;
|
|
5156
|
-
document.querySelectorAll('button, [role="button"], input[type="submit"]').forEach((el, i) => {
|
|
5157
|
-
const text = (el.textContent || el.getAttribute('aria-label') || '').trim();
|
|
5158
|
-
if (i < 30 && (text.length < 30 || btnKeywords.test(text))) {
|
|
5159
|
-
result.buttons.push({
|
|
5160
|
-
tag: el.tagName?.toLowerCase(),
|
|
5161
|
-
id: el.id || null,
|
|
5162
|
-
class: (el.className || '').toString().slice(0, 150),
|
|
5163
|
-
text: text.slice(0, 80),
|
|
5164
|
-
'aria-label': el.getAttribute('aria-label') || null,
|
|
5165
|
-
disabled: el.disabled || el.getAttribute('disabled') !== null,
|
|
5166
|
-
visible: el.offsetParent !== null,
|
|
5167
|
-
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; } })(),
|
|
5168
|
-
});
|
|
5169
|
-
}
|
|
5170
|
-
});
|
|
5171
|
-
|
|
5172
|
-
// iframes
|
|
5173
|
-
document.querySelectorAll('iframe, webview').forEach((el, i) => {
|
|
5174
|
-
if (i >= 20) return;
|
|
5175
|
-
result.iframes.push({
|
|
5176
|
-
tag: el.tagName?.toLowerCase(),
|
|
5177
|
-
id: el.id || null,
|
|
5178
|
-
class: (el.className || '').toString().slice(0, 150),
|
|
5179
|
-
src: el.getAttribute('src')?.slice(0, 200) || null,
|
|
5180
|
-
title: el.getAttribute('title') || null,
|
|
5181
|
-
visible: el.offsetParent !== null,
|
|
5182
|
-
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; } })(),
|
|
5183
|
-
});
|
|
5184
|
-
});
|
|
5185
|
-
|
|
5186
|
-
return JSON.stringify(result);
|
|
5187
|
-
})()`;
|
|
5188
|
-
try {
|
|
5189
|
-
let raw;
|
|
5190
|
-
if (sessionId) {
|
|
5191
|
-
raw = await this.getCdp().evaluateInSessionFrame(sessionId, expression);
|
|
5192
|
-
} else {
|
|
5193
|
-
raw = await this.getCdp().evaluate(expression, 3e4);
|
|
5194
|
-
}
|
|
5195
|
-
const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
5196
|
-
return { success: true, ...parsed };
|
|
5197
|
-
} catch (e) {
|
|
5198
|
-
return { success: false, error: e.message };
|
|
5199
|
-
}
|
|
5200
|
-
}
|
|
5201
|
-
};
|
|
5202
|
-
|
|
5203
|
-
// src/providers/ide-provider-instance.ts
|
|
5204
|
-
import * as crypto2 from "crypto";
|
|
5205
|
-
|
|
5206
|
-
// src/providers/io-contracts.ts
|
|
5207
|
-
function normalizeInputEnvelope(input) {
|
|
5208
|
-
const normalized = normalizeInputEnvelopePayload(input);
|
|
5209
|
-
const textFallback = normalized.textFallback ?? flattenInputParts(normalized.parts);
|
|
5210
|
-
return {
|
|
5211
|
-
parts: normalized.parts,
|
|
5212
|
-
textFallback,
|
|
5213
|
-
...normalized.metadata ? { metadata: normalized.metadata } : {}
|
|
5214
|
-
};
|
|
5215
|
-
}
|
|
5216
|
-
function normalizeMessageParts(content) {
|
|
5217
|
-
if (typeof content === "string") return [{ type: "text", text: content }];
|
|
5218
|
-
if (!Array.isArray(content)) {
|
|
5219
|
-
if (content && typeof content === "object" && typeof content.text === "string") {
|
|
5220
|
-
return [{ type: "text", text: String(content.text) }];
|
|
5221
|
-
}
|
|
5222
|
-
return [];
|
|
5223
|
-
}
|
|
5224
|
-
const parts = [];
|
|
5225
|
-
for (const raw of content) {
|
|
5226
|
-
if (typeof raw === "string") {
|
|
5227
|
-
parts.push({ type: "text", text: raw });
|
|
5228
|
-
continue;
|
|
5229
|
-
}
|
|
5230
|
-
if (!raw || typeof raw !== "object") continue;
|
|
5231
|
-
const part = normalizeMessagePartObject(raw);
|
|
5232
|
-
if (part) parts.push(part);
|
|
5233
|
-
}
|
|
5234
|
-
return parts;
|
|
5235
|
-
}
|
|
5236
|
-
function flattenMessageParts(parts) {
|
|
5237
|
-
return parts.map((part) => {
|
|
5238
|
-
if (part.type === "text") return part.text;
|
|
5239
|
-
if (part.type === "resource") return part.resource.text || "";
|
|
5240
|
-
return "";
|
|
5241
|
-
}).filter((value) => value.length > 0).join("\n");
|
|
5242
|
-
}
|
|
5243
|
-
function normalizeInputEnvelopePayload(input) {
|
|
5244
|
-
if (typeof input === "string") {
|
|
5245
|
-
return { parts: [{ type: "text", text: input }], textFallback: input };
|
|
5246
|
-
}
|
|
5247
|
-
if (!input || typeof input !== "object") {
|
|
5248
|
-
return { parts: [], textFallback: "" };
|
|
5249
|
-
}
|
|
5250
|
-
const record = input;
|
|
5251
|
-
const nestedInput = record.input;
|
|
5252
|
-
if (nestedInput && typeof nestedInput === "object") {
|
|
5253
|
-
const nested = nestedInput;
|
|
5254
|
-
return {
|
|
5255
|
-
parts: normalizeInputParts(nested.parts ?? nested.prompt),
|
|
5256
|
-
textFallback: typeof nested.textFallback === "string" ? nested.textFallback : void 0,
|
|
5257
|
-
metadata: normalizeInputMetadata(nested.metadata)
|
|
5258
|
-
};
|
|
5259
|
-
}
|
|
5260
|
-
const directText = typeof record.text === "string" ? record.text : typeof record.message === "string" ? record.message : void 0;
|
|
5261
|
-
if (directText !== void 0) {
|
|
5262
|
-
return { parts: [{ type: "text", text: directText }], textFallback: directText };
|
|
5263
|
-
}
|
|
5264
|
-
const directParts = normalizeInputParts(record.parts ?? record.prompt);
|
|
5265
|
-
return {
|
|
5266
|
-
parts: directParts,
|
|
5267
|
-
textFallback: typeof record.textFallback === "string" ? record.textFallback : void 0,
|
|
5268
|
-
metadata: normalizeInputMetadata(record.metadata)
|
|
5269
|
-
};
|
|
5270
|
-
}
|
|
5271
|
-
function normalizeInputMetadata(value) {
|
|
5272
|
-
if (!value || typeof value !== "object") return void 0;
|
|
5273
|
-
const record = value;
|
|
5274
|
-
const metadata = {};
|
|
5275
|
-
if (record.source === "dashboard" || record.source === "shortcut_api" || record.source === "provider_script" || record.source === "session_replay") {
|
|
5276
|
-
metadata.source = record.source;
|
|
5277
|
-
}
|
|
5278
|
-
if (typeof record.clientTimestamp === "number" && Number.isFinite(record.clientTimestamp)) {
|
|
5279
|
-
metadata.clientTimestamp = record.clientTimestamp;
|
|
5280
|
-
}
|
|
5281
|
-
return Object.keys(metadata).length > 0 ? metadata : void 0;
|
|
5282
|
-
}
|
|
5283
|
-
function normalizeInputParts(value) {
|
|
5284
|
-
if (!Array.isArray(value)) return [];
|
|
5285
|
-
const parts = [];
|
|
5286
|
-
for (const raw of value) {
|
|
5287
|
-
if (typeof raw === "string") {
|
|
5288
|
-
parts.push({ type: "text", text: raw });
|
|
5289
|
-
continue;
|
|
5290
|
-
}
|
|
5291
|
-
if (!raw || typeof raw !== "object") continue;
|
|
5292
|
-
const part = normalizeInputPartObject(raw);
|
|
5293
|
-
if (part) parts.push(part);
|
|
5294
|
-
}
|
|
5295
|
-
return parts;
|
|
5296
|
-
}
|
|
5297
|
-
function normalizeInputPartObject(raw) {
|
|
5298
|
-
const type = raw.type;
|
|
5299
|
-
if (type === "text" && typeof raw.text === "string") {
|
|
5300
|
-
return { type, text: raw.text };
|
|
5301
|
-
}
|
|
5302
|
-
if (type === "image" && typeof raw.mimeType === "string") {
|
|
5303
|
-
return {
|
|
5304
|
-
type,
|
|
5305
|
-
mimeType: raw.mimeType,
|
|
5306
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
5307
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
5308
|
-
...typeof raw.alt === "string" ? { alt: raw.alt } : {}
|
|
5309
|
-
};
|
|
5310
|
-
}
|
|
5311
|
-
if (type === "audio" && typeof raw.mimeType === "string") {
|
|
5312
|
-
return {
|
|
5313
|
-
type,
|
|
5314
|
-
mimeType: raw.mimeType,
|
|
5315
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
5316
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
5317
|
-
...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
|
|
5318
|
-
};
|
|
5319
|
-
}
|
|
5320
|
-
if (type === "video" && typeof raw.mimeType === "string") {
|
|
5321
|
-
return {
|
|
5322
|
-
type,
|
|
5323
|
-
mimeType: raw.mimeType,
|
|
5324
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
5325
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
5326
|
-
...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
|
|
5327
|
-
};
|
|
5328
|
-
}
|
|
5329
|
-
if (type === "resource" && typeof raw.uri === "string") {
|
|
5330
|
-
return {
|
|
5331
|
-
type,
|
|
5332
|
-
uri: raw.uri,
|
|
5333
|
-
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
5334
|
-
...typeof raw.name === "string" ? { name: raw.name } : {},
|
|
5335
|
-
...typeof raw.text === "string" ? { text: raw.text } : {},
|
|
5336
|
-
...typeof raw.data === "string" ? { data: raw.data } : {}
|
|
5337
|
-
};
|
|
5338
|
-
}
|
|
5339
|
-
if (type === "resource_link" && typeof raw.uri === "string") {
|
|
5340
|
-
return {
|
|
5341
|
-
type: "resource",
|
|
5342
|
-
uri: raw.uri,
|
|
5343
|
-
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
5344
|
-
...typeof raw.name === "string" ? { name: raw.name } : {}
|
|
5345
|
-
};
|
|
5346
|
-
}
|
|
5347
|
-
return null;
|
|
5348
|
-
}
|
|
5349
|
-
function normalizeMessagePartObject(raw) {
|
|
5350
|
-
const type = raw.type;
|
|
5351
|
-
if (type === "text" && typeof raw.text === "string") {
|
|
5352
|
-
return { type, text: raw.text };
|
|
5353
|
-
}
|
|
5354
|
-
if (type === "image" && typeof raw.mimeType === "string") {
|
|
5355
|
-
return {
|
|
5356
|
-
type,
|
|
5357
|
-
mimeType: raw.mimeType,
|
|
5358
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
5359
|
-
...typeof raw.data === "string" ? { data: raw.data } : {}
|
|
5360
|
-
};
|
|
5361
|
-
}
|
|
5362
|
-
if (type === "audio" && typeof raw.mimeType === "string") {
|
|
5363
|
-
return {
|
|
5364
|
-
type,
|
|
5365
|
-
mimeType: raw.mimeType,
|
|
5366
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
5367
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
5368
|
-
...typeof raw.transcript === "string" ? { transcript: raw.transcript } : {}
|
|
5369
|
-
};
|
|
5370
|
-
}
|
|
5371
|
-
if (type === "video" && typeof raw.mimeType === "string") {
|
|
5372
|
-
return {
|
|
5373
|
-
type,
|
|
5374
|
-
mimeType: raw.mimeType,
|
|
5375
|
-
...typeof raw.uri === "string" ? { uri: raw.uri } : {},
|
|
5376
|
-
...typeof raw.data === "string" ? { data: raw.data } : {},
|
|
5377
|
-
...typeof raw.posterUri === "string" ? { posterUri: raw.posterUri } : {}
|
|
5378
|
-
};
|
|
5379
|
-
}
|
|
5380
|
-
if (type === "resource_link" && typeof raw.uri === "string" && typeof raw.name === "string") {
|
|
5381
|
-
return {
|
|
5382
|
-
type,
|
|
5383
|
-
uri: raw.uri,
|
|
5384
|
-
name: raw.name,
|
|
5385
|
-
...typeof raw.mimeType === "string" ? { mimeType: raw.mimeType } : {},
|
|
5386
|
-
...typeof raw.size === "number" ? { size: raw.size } : {}
|
|
5387
|
-
};
|
|
5388
|
-
}
|
|
5389
|
-
if (type === "resource" && raw.resource && typeof raw.resource === "object") {
|
|
5390
|
-
const resource = raw.resource;
|
|
5391
|
-
if (typeof resource.uri !== "string") return null;
|
|
5392
|
-
return {
|
|
5393
|
-
type,
|
|
5394
|
-
resource: {
|
|
5395
|
-
uri: resource.uri,
|
|
5396
|
-
...typeof resource.mimeType === "string" || resource.mimeType === null ? { mimeType: resource.mimeType } : {},
|
|
5397
|
-
...typeof resource.text === "string" ? { text: resource.text } : {},
|
|
5398
|
-
...typeof resource.blob === "string" ? { blob: resource.blob } : {}
|
|
5424
|
+
*/
|
|
5425
|
+
async handleDomDebug(args) {
|
|
5426
|
+
if (!this.getCdp()?.isConnected) return { success: false, error: "CDP not connected" };
|
|
5427
|
+
const sessionId = args?.sessionId;
|
|
5428
|
+
const expression = `(() => {
|
|
5429
|
+
const result = {
|
|
5430
|
+
url: location.href,
|
|
5431
|
+
title: document.title,
|
|
5432
|
+
viewport: { w: window.innerWidth, h: window.innerHeight },
|
|
5433
|
+
|
|
5434
|
+
// Input field info
|
|
5435
|
+
inputs: [],
|
|
5436
|
+
// Textarea info
|
|
5437
|
+
textareas: [],
|
|
5438
|
+
// Contenteditable info
|
|
5439
|
+
editables: [],
|
|
5440
|
+
// Buttons (send, submit etc)
|
|
5441
|
+
buttons: [],
|
|
5442
|
+
// iframes (agent webviews)
|
|
5443
|
+
iframes: [],
|
|
5444
|
+
// role="textbox" info
|
|
5445
|
+
textboxes: [],
|
|
5446
|
+
};
|
|
5447
|
+
|
|
5448
|
+
// Input fields
|
|
5449
|
+
document.querySelectorAll('input[type="text"], input:not([type])').forEach((el, i) => {
|
|
5450
|
+
if (i >= 10) return;
|
|
5451
|
+
result.inputs.push({
|
|
5452
|
+
tag: 'input',
|
|
5453
|
+
id: el.id || null,
|
|
5454
|
+
class: (el.className || '').toString().slice(0, 150),
|
|
5455
|
+
placeholder: el.getAttribute('placeholder') || null,
|
|
5456
|
+
name: el.name || null,
|
|
5457
|
+
value: el.value?.slice(0, 100) || null,
|
|
5458
|
+
visible: el.offsetParent !== null,
|
|
5459
|
+
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; } })(),
|
|
5460
|
+
});
|
|
5461
|
+
});
|
|
5462
|
+
|
|
5463
|
+
// textarea
|
|
5464
|
+
document.querySelectorAll('textarea').forEach((el, i) => {
|
|
5465
|
+
if (i >= 10) return;
|
|
5466
|
+
result.textareas.push({
|
|
5467
|
+
id: el.id || null,
|
|
5468
|
+
class: (el.className || '').toString().slice(0, 150),
|
|
5469
|
+
placeholder: el.getAttribute('placeholder') || null,
|
|
5470
|
+
rows: el.rows,
|
|
5471
|
+
value: el.value?.slice(0, 100) || null,
|
|
5472
|
+
visible: el.offsetParent !== null,
|
|
5473
|
+
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; } })(),
|
|
5474
|
+
});
|
|
5475
|
+
});
|
|
5476
|
+
|
|
5477
|
+
// contenteditable
|
|
5478
|
+
document.querySelectorAll('[contenteditable="true"]').forEach((el, i) => {
|
|
5479
|
+
if (i >= 10) return;
|
|
5480
|
+
result.editables.push({
|
|
5481
|
+
tag: el.tagName?.toLowerCase(),
|
|
5482
|
+
id: el.id || null,
|
|
5483
|
+
class: (el.className || '').toString().slice(0, 150),
|
|
5484
|
+
role: el.getAttribute('role') || null,
|
|
5485
|
+
text: (el.textContent || '').trim().slice(0, 100),
|
|
5486
|
+
visible: el.offsetParent !== null,
|
|
5487
|
+
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; } })(),
|
|
5488
|
+
});
|
|
5489
|
+
});
|
|
5490
|
+
|
|
5491
|
+
// role="textbox"
|
|
5492
|
+
document.querySelectorAll('[role="textbox"]').forEach((el, i) => {
|
|
5493
|
+
if (i >= 10) return;
|
|
5494
|
+
result.textboxes.push({
|
|
5495
|
+
tag: el.tagName?.toLowerCase(),
|
|
5496
|
+
id: el.id || null,
|
|
5497
|
+
class: (el.className || '').toString().slice(0, 150),
|
|
5498
|
+
'aria-label': el.getAttribute('aria-label') || null,
|
|
5499
|
+
text: (el.textContent || '').trim().slice(0, 100),
|
|
5500
|
+
visible: el.offsetParent !== null,
|
|
5501
|
+
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; } })(),
|
|
5502
|
+
});
|
|
5503
|
+
});
|
|
5504
|
+
|
|
5505
|
+
// Buttons (send, submit, accept, reject, approve etc)
|
|
5506
|
+
const btnKeywords = /send|submit|accept|reject|approve|deny|cancel|confirm|run|execute|apply/i;
|
|
5507
|
+
document.querySelectorAll('button, [role="button"], input[type="submit"]').forEach((el, i) => {
|
|
5508
|
+
const text = (el.textContent || el.getAttribute('aria-label') || '').trim();
|
|
5509
|
+
if (i < 30 && (text.length < 30 || btnKeywords.test(text))) {
|
|
5510
|
+
result.buttons.push({
|
|
5511
|
+
tag: el.tagName?.toLowerCase(),
|
|
5512
|
+
id: el.id || null,
|
|
5513
|
+
class: (el.className || '').toString().slice(0, 150),
|
|
5514
|
+
text: text.slice(0, 80),
|
|
5515
|
+
'aria-label': el.getAttribute('aria-label') || null,
|
|
5516
|
+
disabled: el.disabled || el.getAttribute('disabled') !== null,
|
|
5517
|
+
visible: el.offsetParent !== null,
|
|
5518
|
+
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; } })(),
|
|
5519
|
+
});
|
|
5520
|
+
}
|
|
5521
|
+
});
|
|
5522
|
+
|
|
5523
|
+
// iframes
|
|
5524
|
+
document.querySelectorAll('iframe, webview').forEach((el, i) => {
|
|
5525
|
+
if (i >= 20) return;
|
|
5526
|
+
result.iframes.push({
|
|
5527
|
+
tag: el.tagName?.toLowerCase(),
|
|
5528
|
+
id: el.id || null,
|
|
5529
|
+
class: (el.className || '').toString().slice(0, 150),
|
|
5530
|
+
src: el.getAttribute('src')?.slice(0, 200) || null,
|
|
5531
|
+
title: el.getAttribute('title') || null,
|
|
5532
|
+
visible: el.offsetParent !== null,
|
|
5533
|
+
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; } })(),
|
|
5534
|
+
});
|
|
5535
|
+
});
|
|
5536
|
+
|
|
5537
|
+
return JSON.stringify(result);
|
|
5538
|
+
})()`;
|
|
5539
|
+
try {
|
|
5540
|
+
let raw;
|
|
5541
|
+
if (sessionId) {
|
|
5542
|
+
raw = await this.getCdp().evaluateInSessionFrame(sessionId, expression);
|
|
5543
|
+
} else {
|
|
5544
|
+
raw = await this.getCdp().evaluate(expression, 3e4);
|
|
5399
5545
|
}
|
|
5400
|
-
|
|
5546
|
+
const parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
5547
|
+
return { success: true, ...parsed };
|
|
5548
|
+
} catch (e) {
|
|
5549
|
+
return { success: false, error: e.message };
|
|
5550
|
+
}
|
|
5401
5551
|
}
|
|
5402
|
-
|
|
5403
|
-
}
|
|
5404
|
-
function flattenInputParts(parts) {
|
|
5405
|
-
return parts.map((part) => {
|
|
5406
|
-
if (part.type === "text") return part.text;
|
|
5407
|
-
if (part.type === "audio") return part.transcript || "";
|
|
5408
|
-
if (part.type === "resource") return part.text || "";
|
|
5409
|
-
return "";
|
|
5410
|
-
}).filter((value) => value.length > 0).join("\n");
|
|
5411
|
-
}
|
|
5552
|
+
};
|
|
5412
5553
|
|
|
5413
|
-
// src/providers/
|
|
5414
|
-
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5554
|
+
// src/providers/ide-provider-instance.ts
|
|
5555
|
+
init_contracts();
|
|
5556
|
+
import * as crypto2 from "crypto";
|
|
5557
|
+
|
|
5558
|
+
// src/providers/extension-provider-instance.ts
|
|
5559
|
+
init_contracts();
|
|
5418
5560
|
|
|
5419
5561
|
// src/providers/status-monitor.ts
|
|
5420
5562
|
var DEFAULT_MONITOR_CONFIG = {
|
|
@@ -5529,6 +5671,7 @@ var StatusMonitor = class {
|
|
|
5529
5671
|
};
|
|
5530
5672
|
|
|
5531
5673
|
// src/providers/control-effects.ts
|
|
5674
|
+
init_contracts();
|
|
5532
5675
|
init_chat_message_normalization();
|
|
5533
5676
|
function extractProviderControlValues(controls, data) {
|
|
5534
5677
|
if (!data || typeof data !== "object") return void 0;
|
|
@@ -5650,38 +5793,37 @@ function buildPersistedProviderEffectMessage(effect) {
|
|
|
5650
5793
|
return null;
|
|
5651
5794
|
}
|
|
5652
5795
|
function normalizeControlListResult(data) {
|
|
5653
|
-
if (data
|
|
5654
|
-
|
|
5655
|
-
options: normalizeControlOptions(data.options),
|
|
5656
|
-
...isScalarControlValue(data.currentValue) ? { currentValue: data.currentValue } : {},
|
|
5657
|
-
...typeof data.error === "string" ? { error: data.error } : {}
|
|
5658
|
-
};
|
|
5796
|
+
if (!data || typeof data !== "object" || !Array.isArray(data.options)) {
|
|
5797
|
+
throw new Error("Provider control list results must use the typed shape { options, currentValue?, error? }");
|
|
5659
5798
|
}
|
|
5660
|
-
const rawOptions = Array.isArray(data?.models) ? data.models : Array.isArray(data?.modes) ? data.modes : Array.isArray(data?.options) ? data.options : [];
|
|
5661
|
-
const options = normalizeControlOptions(rawOptions);
|
|
5662
5799
|
return {
|
|
5663
|
-
options,
|
|
5664
|
-
...isScalarControlValue(data
|
|
5665
|
-
...
|
|
5666
|
-
...typeof data?.error === "string" ? { error: data.error } : {}
|
|
5800
|
+
options: normalizeControlOptions(data.options),
|
|
5801
|
+
...isScalarControlValue(data.currentValue) ? { currentValue: data.currentValue } : {},
|
|
5802
|
+
...typeof data.error === "string" ? { error: data.error } : {}
|
|
5667
5803
|
};
|
|
5668
5804
|
}
|
|
5669
5805
|
function normalizeControlSetResult(data) {
|
|
5670
|
-
|
|
5806
|
+
if (!data || typeof data !== "object" || typeof data.ok !== "boolean") {
|
|
5807
|
+
throw new Error("Provider control set results must use the typed shape { ok, currentValue?, effects?, error? }");
|
|
5808
|
+
}
|
|
5809
|
+
const currentValue = isScalarControlValue(data.currentValue) ? data.currentValue : isScalarControlValue(data.value) ? data.value : void 0;
|
|
5671
5810
|
return {
|
|
5672
|
-
ok: data
|
|
5811
|
+
ok: data.ok,
|
|
5673
5812
|
...currentValue !== void 0 ? { currentValue } : {},
|
|
5674
|
-
...Array.isArray(data
|
|
5675
|
-
...typeof data
|
|
5813
|
+
...Array.isArray(data.effects) ? { effects: normalizeProviderEffects(data) } : {},
|
|
5814
|
+
...typeof data.error === "string" ? { error: data.error } : {}
|
|
5676
5815
|
};
|
|
5677
5816
|
}
|
|
5678
5817
|
function normalizeControlInvokeResult(data) {
|
|
5679
|
-
|
|
5818
|
+
if (!data || typeof data !== "object" || typeof data.ok !== "boolean") {
|
|
5819
|
+
throw new Error("Provider control invoke results must use the typed shape { ok, currentValue?, effects?, error? }");
|
|
5820
|
+
}
|
|
5821
|
+
const currentValue = isScalarControlValue(data.currentValue) ? data.currentValue : isScalarControlValue(data.value) ? data.value : void 0;
|
|
5680
5822
|
return {
|
|
5681
|
-
ok: data
|
|
5823
|
+
ok: data.ok,
|
|
5682
5824
|
...currentValue !== void 0 ? { currentValue } : {},
|
|
5683
|
-
...Array.isArray(data
|
|
5684
|
-
...typeof data
|
|
5825
|
+
...Array.isArray(data.effects) ? { effects: normalizeProviderEffects(data) } : {},
|
|
5826
|
+
...typeof data.error === "string" ? { error: data.error } : {}
|
|
5685
5827
|
};
|
|
5686
5828
|
}
|
|
5687
5829
|
function normalizeControlOptions(options) {
|
|
@@ -6572,19 +6714,37 @@ var ExtensionProviderInstance = class {
|
|
|
6572
6714
|
);
|
|
6573
6715
|
}
|
|
6574
6716
|
}
|
|
6717
|
+
buildSyntheticTurnKey(message, occurrence) {
|
|
6718
|
+
const role = typeof message?.role === "string" ? message.role : "";
|
|
6719
|
+
const kind = typeof message?.kind === "string" ? message.kind : "";
|
|
6720
|
+
const senderName = typeof message?.senderName === "string" ? message.senderName : "";
|
|
6721
|
+
const content = flattenContent(message?.content).replace(/\s+/g, " ").trim().slice(0, 500);
|
|
6722
|
+
return `${role}|${kind}|${senderName}|${content}|${occurrence}`;
|
|
6723
|
+
}
|
|
6575
6724
|
/**
|
|
6576
|
-
* Assign stable receivedAt to extension messages.
|
|
6577
|
-
* Same
|
|
6578
|
-
*
|
|
6725
|
+
* Assign stable receivedAt / synthetic _turnKey to extension messages.
|
|
6726
|
+
* Same transcript should keep the same identity across polling cycles and
|
|
6727
|
+
* stream resets, while repeated identical text later in the transcript still
|
|
6728
|
+
* produces a distinct completion marker via the occurrence suffix.
|
|
6579
6729
|
*/
|
|
6580
6730
|
assignReceivedAt(messages) {
|
|
6581
6731
|
const now = Date.now();
|
|
6582
6732
|
const nextHashes = /* @__PURE__ */ new Map();
|
|
6733
|
+
const occurrenceByBaseKey = /* @__PURE__ */ new Map();
|
|
6583
6734
|
for (const msg of messages) {
|
|
6584
|
-
const
|
|
6585
|
-
const
|
|
6735
|
+
const explicitTurnKey = typeof msg?._turnKey === "string" && msg._turnKey.trim() ? msg._turnKey.trim() : "";
|
|
6736
|
+
const explicitId = typeof msg?.id === "string" && msg.id.trim() ? `id:${msg.id.trim()}` : "";
|
|
6737
|
+
const explicitIndex = typeof msg?.index === "number" && Number.isFinite(msg.index) ? `idx:${msg.index}` : "";
|
|
6738
|
+
const baseKey = explicitTurnKey || explicitId || explicitIndex || `${msg?.role || ""}:${flattenContent(msg?.content || "").slice(0, 500)}`;
|
|
6739
|
+
const occurrence = (occurrenceByBaseKey.get(baseKey) || 0) + 1;
|
|
6740
|
+
occurrenceByBaseKey.set(baseKey, occurrence);
|
|
6741
|
+
const syntheticTurnKey = explicitTurnKey || explicitId || explicitIndex || this.buildSyntheticTurnKey(msg, occurrence);
|
|
6742
|
+
if (!explicitTurnKey && !explicitId && !explicitIndex) {
|
|
6743
|
+
msg._turnKey = syntheticTurnKey;
|
|
6744
|
+
}
|
|
6745
|
+
const prevTime = this.prevMessageHashes.get(syntheticTurnKey);
|
|
6586
6746
|
msg.receivedAt = prevTime || now;
|
|
6587
|
-
nextHashes.set(
|
|
6747
|
+
nextHashes.set(syntheticTurnKey, msg.receivedAt);
|
|
6588
6748
|
}
|
|
6589
6749
|
this.prevMessageHashes = nextHashes;
|
|
6590
6750
|
return normalizeChatMessages(messages);
|
|
@@ -6661,6 +6821,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
6661
6821
|
|
|
6662
6822
|
// src/providers/ide-provider-instance.ts
|
|
6663
6823
|
init_logger();
|
|
6824
|
+
init_read_chat_contract();
|
|
6664
6825
|
|
|
6665
6826
|
// src/providers/approval-utils.ts
|
|
6666
6827
|
var DEFAULT_APPROVAL_POSITIVE_HINTS = [
|
|
@@ -6942,7 +7103,7 @@ var IdeProviderInstance = class {
|
|
|
6942
7103
|
}
|
|
6943
7104
|
}
|
|
6944
7105
|
if (!raw || typeof raw !== "object") return;
|
|
6945
|
-
const chat = raw;
|
|
7106
|
+
const chat = validateReadChatResultPayload(raw, `${this.type} readChat`);
|
|
6946
7107
|
let { activeModal } = chat;
|
|
6947
7108
|
if (activeModal) {
|
|
6948
7109
|
const w = activeModal.width ?? Infinity;
|
|
@@ -8087,6 +8248,65 @@ function reconcileIdeRuntimeSessions(instanceManager, sessionRegistry) {
|
|
|
8087
8248
|
init_logger();
|
|
8088
8249
|
|
|
8089
8250
|
// src/commands/chat-commands.ts
|
|
8251
|
+
init_contracts();
|
|
8252
|
+
|
|
8253
|
+
// src/providers/provider-input-support.ts
|
|
8254
|
+
var VALID_INPUT_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
|
|
8255
|
+
function getProviderLabel(provider) {
|
|
8256
|
+
return provider?.name || provider?.type || "This provider";
|
|
8257
|
+
}
|
|
8258
|
+
function hasNonEmptyFallbackText(input) {
|
|
8259
|
+
return typeof input.textFallback === "string" && input.textFallback.trim().length > 0;
|
|
8260
|
+
}
|
|
8261
|
+
function getRequestedInputMediaTypes(input) {
|
|
8262
|
+
const types = /* @__PURE__ */ new Set();
|
|
8263
|
+
if (hasNonEmptyFallbackText(input) && !input.parts.some((part) => part.type === "text")) {
|
|
8264
|
+
types.add("text");
|
|
8265
|
+
}
|
|
8266
|
+
for (const part of input.parts) {
|
|
8267
|
+
if (VALID_INPUT_MEDIA_TYPES.has(part.type)) {
|
|
8268
|
+
types.add(part.type);
|
|
8269
|
+
}
|
|
8270
|
+
}
|
|
8271
|
+
return Array.from(types);
|
|
8272
|
+
}
|
|
8273
|
+
function getEffectiveSemanticPartCount(input) {
|
|
8274
|
+
let count = input.parts.length;
|
|
8275
|
+
if (hasNonEmptyFallbackText(input) && !input.parts.some((part) => part.type === "text")) {
|
|
8276
|
+
count += 1;
|
|
8277
|
+
}
|
|
8278
|
+
return count;
|
|
8279
|
+
}
|
|
8280
|
+
function assertTextOnlyInput(provider, input) {
|
|
8281
|
+
const unsupported = getRequestedInputMediaTypes(input).filter((type) => type !== "text");
|
|
8282
|
+
if (unsupported.length === 0) return;
|
|
8283
|
+
const label = getProviderLabel(provider);
|
|
8284
|
+
const suffix = unsupported.length === 1 ? "" : "s";
|
|
8285
|
+
throw new Error(`${label} only supports text input; unsupported input type${suffix}: ${unsupported.join(", ")}`);
|
|
8286
|
+
}
|
|
8287
|
+
function getDeclaredProviderInputSupport(provider) {
|
|
8288
|
+
const rawMediaTypes = Array.isArray(provider?.capabilities?.input?.mediaTypes) ? provider?.capabilities?.input?.mediaTypes.filter((type) => VALID_INPUT_MEDIA_TYPES.has(type)) : [];
|
|
8289
|
+
return {
|
|
8290
|
+
multipart: provider?.capabilities?.input?.multipart === true,
|
|
8291
|
+
mediaTypes: new Set(rawMediaTypes.length > 0 ? rawMediaTypes : ["text"])
|
|
8292
|
+
};
|
|
8293
|
+
}
|
|
8294
|
+
function assertProviderSupportsDeclaredInput(provider, input) {
|
|
8295
|
+
const label = getProviderLabel(provider);
|
|
8296
|
+
const support = getDeclaredProviderInputSupport(provider);
|
|
8297
|
+
const requestedTypes = getRequestedInputMediaTypes(input);
|
|
8298
|
+
const unsupported = requestedTypes.filter((type) => !support.mediaTypes.has(type));
|
|
8299
|
+
if (unsupported.length > 0) {
|
|
8300
|
+
const suffix = unsupported.length === 1 ? "" : "s";
|
|
8301
|
+
throw new Error(`${label} does not support input type${suffix}: ${unsupported.join(", ")}`);
|
|
8302
|
+
}
|
|
8303
|
+
if (getEffectiveSemanticPartCount(input) > 1 && !support.multipart) {
|
|
8304
|
+
throw new Error(`${label} does not support multipart input`);
|
|
8305
|
+
}
|
|
8306
|
+
}
|
|
8307
|
+
|
|
8308
|
+
// src/commands/chat-commands.ts
|
|
8309
|
+
init_read_chat_contract();
|
|
8090
8310
|
init_logger();
|
|
8091
8311
|
|
|
8092
8312
|
// src/logging/debug-config.ts
|
|
@@ -8268,10 +8488,15 @@ function isCliLikeTransport(transport) {
|
|
|
8268
8488
|
function isExtensionTransport(transport) {
|
|
8269
8489
|
return transport === "cdp-webview";
|
|
8270
8490
|
}
|
|
8271
|
-
function buildRecentSendKey(h, args, provider,
|
|
8491
|
+
function buildRecentSendKey(h, args, provider, signature) {
|
|
8272
8492
|
const transport = getTargetTransport(h, provider) || "unknown";
|
|
8273
8493
|
const target = args?.targetSessionId || args?.agentType || h.currentSession?.providerType || h.currentProviderType || h.currentManagerKey || "unknown";
|
|
8274
|
-
return `${transport}:${target}:${
|
|
8494
|
+
return `${transport}:${target}:${signature.trim()}`;
|
|
8495
|
+
}
|
|
8496
|
+
function buildSendInputSignature(input) {
|
|
8497
|
+
const text = typeof input.textFallback === "string" ? input.textFallback.trim() : "";
|
|
8498
|
+
if (text) return text;
|
|
8499
|
+
return JSON.stringify(input.parts || []);
|
|
8275
8500
|
}
|
|
8276
8501
|
function getSendChatInputEnvelope(args) {
|
|
8277
8502
|
return normalizeInputEnvelope(args?.input ? { input: args.input } : args);
|
|
@@ -8424,14 +8649,20 @@ function computeReadChatSync(messages, cursor) {
|
|
|
8424
8649
|
};
|
|
8425
8650
|
}
|
|
8426
8651
|
function buildReadChatCommandResult(payload, args) {
|
|
8427
|
-
|
|
8652
|
+
let validatedPayload;
|
|
8653
|
+
try {
|
|
8654
|
+
validatedPayload = validateReadChatResultPayload(payload, "read_chat command result");
|
|
8655
|
+
} catch (error) {
|
|
8656
|
+
return { success: false, error: error?.message || String(error) };
|
|
8657
|
+
}
|
|
8658
|
+
const messages = normalizeReadChatMessages(validatedPayload);
|
|
8428
8659
|
const cursor = normalizeReadChatCursor(args);
|
|
8429
8660
|
if (!cursor.knownMessageCount && !cursor.lastMessageSignature && cursor.tailLimit > 0 && messages.length > cursor.tailLimit) {
|
|
8430
8661
|
const tailMessages = messages.slice(-cursor.tailLimit);
|
|
8431
8662
|
const lastMessageSignature = getChatMessageSignature(tailMessages[tailMessages.length - 1]);
|
|
8432
8663
|
return {
|
|
8433
8664
|
success: true,
|
|
8434
|
-
...
|
|
8665
|
+
...validatedPayload,
|
|
8435
8666
|
messages: tailMessages,
|
|
8436
8667
|
syncMode: "full",
|
|
8437
8668
|
replaceFrom: 0,
|
|
@@ -8442,7 +8673,7 @@ function buildReadChatCommandResult(payload, args) {
|
|
|
8442
8673
|
const sync = computeReadChatSync(messages, cursor);
|
|
8443
8674
|
return {
|
|
8444
8675
|
success: true,
|
|
8445
|
-
...
|
|
8676
|
+
...validatedPayload,
|
|
8446
8677
|
messages: sync.messages,
|
|
8447
8678
|
syncMode: sync.syncMode,
|
|
8448
8679
|
replaceFrom: sync.replaceFrom,
|
|
@@ -8521,12 +8752,18 @@ async function handleReadChat(h, args) {
|
|
|
8521
8752
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
8522
8753
|
if (adapter) {
|
|
8523
8754
|
_log(`${transport} adapter: ${adapter.cliType}`);
|
|
8524
|
-
const
|
|
8755
|
+
const parsedStatus = typeof adapter.getScriptParsedStatus === "function" ? parseMaybeJson(adapter.getScriptParsedStatus()) : null;
|
|
8756
|
+
const parsedRecord = parsedStatus && typeof parsedStatus === "object" ? parsedStatus : null;
|
|
8757
|
+
const status = parsedRecord || adapter.getStatus();
|
|
8758
|
+
const title = typeof parsedRecord?.title === "string" ? parsedRecord.title : void 0;
|
|
8759
|
+
const providerSessionId = typeof parsedRecord?.providerSessionId === "string" ? parsedRecord.providerSessionId : void 0;
|
|
8525
8760
|
if (status) {
|
|
8526
8761
|
return buildReadChatCommandResult({
|
|
8527
8762
|
messages: status.messages || [],
|
|
8528
8763
|
status: status.status,
|
|
8529
|
-
activeModal: status.activeModal
|
|
8764
|
+
activeModal: status.activeModal,
|
|
8765
|
+
...title ? { title } : {},
|
|
8766
|
+
...providerSessionId ? { providerSessionId } : {}
|
|
8530
8767
|
}, args);
|
|
8531
8768
|
}
|
|
8532
8769
|
}
|
|
@@ -8544,25 +8781,26 @@ async function handleReadChat(h, args) {
|
|
|
8544
8781
|
}
|
|
8545
8782
|
}
|
|
8546
8783
|
if (parsed && typeof parsed === "object") {
|
|
8547
|
-
|
|
8784
|
+
const validated = validateReadChatResultPayload(parsed, "extension read_chat");
|
|
8785
|
+
_log(`Extension OK: ${validated.messages?.length || 0} msgs`);
|
|
8548
8786
|
traceProviderEvent(args, "provider", "extension.read_chat.success", {
|
|
8549
8787
|
h,
|
|
8550
8788
|
provider,
|
|
8551
8789
|
payload: {
|
|
8552
8790
|
method: "evaluateProviderScript",
|
|
8553
8791
|
result: evalResult.result,
|
|
8554
|
-
parsed,
|
|
8555
|
-
messageCount: Array.isArray(
|
|
8792
|
+
parsed: validated,
|
|
8793
|
+
messageCount: Array.isArray(validated.messages) ? validated.messages.length : 0
|
|
8556
8794
|
}
|
|
8557
8795
|
});
|
|
8558
8796
|
h.historyWriter.appendNewMessages(
|
|
8559
8797
|
provider?.type || "unknown_extension",
|
|
8560
|
-
toHistoryPersistedMessages(normalizeReadChatMessages(
|
|
8561
|
-
|
|
8798
|
+
toHistoryPersistedMessages(normalizeReadChatMessages(validated)),
|
|
8799
|
+
validated.title,
|
|
8562
8800
|
args?.targetSessionId,
|
|
8563
8801
|
historySessionId
|
|
8564
8802
|
);
|
|
8565
|
-
return buildReadChatCommandResult(
|
|
8803
|
+
return buildReadChatCommandResult(validated, args);
|
|
8566
8804
|
}
|
|
8567
8805
|
}
|
|
8568
8806
|
} catch (e) {
|
|
@@ -8617,15 +8855,16 @@ async function handleReadChat(h, args) {
|
|
|
8617
8855
|
}
|
|
8618
8856
|
}
|
|
8619
8857
|
if (parsed && typeof parsed === "object") {
|
|
8620
|
-
|
|
8858
|
+
const validated = validateReadChatResultPayload(parsed, "webview read_chat");
|
|
8859
|
+
_log(`Webview OK: ${validated.messages?.length || 0} msgs`);
|
|
8621
8860
|
h.historyWriter.appendNewMessages(
|
|
8622
8861
|
provider?.type || getCurrentProviderType(h, "unknown_webview"),
|
|
8623
|
-
toHistoryPersistedMessages(normalizeReadChatMessages(
|
|
8624
|
-
|
|
8862
|
+
toHistoryPersistedMessages(normalizeReadChatMessages(validated)),
|
|
8863
|
+
validated.title,
|
|
8625
8864
|
args?.targetSessionId,
|
|
8626
8865
|
historySessionId
|
|
8627
8866
|
);
|
|
8628
|
-
return buildReadChatCommandResult(
|
|
8867
|
+
return buildReadChatCommandResult(validated, args);
|
|
8629
8868
|
}
|
|
8630
8869
|
}
|
|
8631
8870
|
} catch (e) {
|
|
@@ -8646,25 +8885,26 @@ async function handleReadChat(h, args) {
|
|
|
8646
8885
|
}
|
|
8647
8886
|
}
|
|
8648
8887
|
if (parsed && typeof parsed === "object" && parsed.messages?.length > 0) {
|
|
8649
|
-
|
|
8888
|
+
const validated = validateReadChatResultPayload(parsed, "ide read_chat");
|
|
8889
|
+
_log(`OK: ${validated.messages?.length} msgs`);
|
|
8650
8890
|
traceProviderEvent(args, "provider", "ide.read_chat.success", {
|
|
8651
8891
|
h,
|
|
8652
8892
|
provider,
|
|
8653
8893
|
payload: {
|
|
8654
8894
|
method: "evaluate",
|
|
8655
8895
|
result: evalResult.result,
|
|
8656
|
-
parsed,
|
|
8657
|
-
messageCount: Array.isArray(
|
|
8896
|
+
parsed: validated,
|
|
8897
|
+
messageCount: Array.isArray(validated.messages) ? validated.messages.length : 0
|
|
8658
8898
|
}
|
|
8659
8899
|
});
|
|
8660
8900
|
h.historyWriter.appendNewMessages(
|
|
8661
8901
|
provider?.type || getCurrentProviderType(h, "unknown_ide"),
|
|
8662
|
-
toHistoryPersistedMessages(normalizeReadChatMessages(
|
|
8663
|
-
|
|
8902
|
+
toHistoryPersistedMessages(normalizeReadChatMessages(validated)),
|
|
8903
|
+
validated.title,
|
|
8664
8904
|
args?.targetSessionId,
|
|
8665
8905
|
historySessionId
|
|
8666
8906
|
);
|
|
8667
|
-
return buildReadChatCommandResult(
|
|
8907
|
+
return buildReadChatCommandResult(validated, args);
|
|
8668
8908
|
}
|
|
8669
8909
|
}
|
|
8670
8910
|
} catch (e) {
|
|
@@ -8682,11 +8922,12 @@ async function handleReadChat(h, args) {
|
|
|
8682
8922
|
async function handleSendChat(h, args) {
|
|
8683
8923
|
const input = getSendChatInputEnvelope(args);
|
|
8684
8924
|
const text = input.textFallback;
|
|
8685
|
-
|
|
8925
|
+
const hasInput = input.parts.length > 0 || typeof text === "string" && text.trim().length > 0;
|
|
8926
|
+
if (!hasInput) return { success: false, error: "input required" };
|
|
8686
8927
|
const _log = (msg) => LOG.debug("Command", `[send_chat] ${msg}`);
|
|
8687
8928
|
const provider = h.getProvider(args?.agentType);
|
|
8688
8929
|
const transport = getTargetTransport(h, provider);
|
|
8689
|
-
const dedupeKey = buildRecentSendKey(h, args, provider,
|
|
8930
|
+
const dedupeKey = buildRecentSendKey(h, args, provider, buildSendInputSignature(input));
|
|
8690
8931
|
const _logSendSuccess = (method, targetAgent) => {
|
|
8691
8932
|
return { success: true, sent: true, method, targetAgent };
|
|
8692
8933
|
};
|
|
@@ -8694,11 +8935,26 @@ async function handleSendChat(h, args) {
|
|
|
8694
8935
|
_log(`Suppressed duplicate send for ${dedupeKey}`);
|
|
8695
8936
|
return { success: true, sent: false, deduplicated: true };
|
|
8696
8937
|
}
|
|
8697
|
-
if (
|
|
8938
|
+
if (transport === "acp") {
|
|
8939
|
+
const target = getTargetInstance(h, args);
|
|
8940
|
+
if (!target || target.category !== "acp") {
|
|
8941
|
+
return { success: false, error: `ACP instance not found for ${provider?.type || args?.agentType || "unknown"}` };
|
|
8942
|
+
}
|
|
8943
|
+
try {
|
|
8944
|
+
assertProviderSupportsDeclaredInput(provider, input);
|
|
8945
|
+
target.onEvent("send_message", { input });
|
|
8946
|
+
return _logSendSuccess("acp-instance", target.type);
|
|
8947
|
+
} catch (e) {
|
|
8948
|
+
return { success: false, error: `acp send failed: ${e.message}` };
|
|
8949
|
+
}
|
|
8950
|
+
}
|
|
8951
|
+
if (transport === "pty") {
|
|
8698
8952
|
const adapter = getTargetedCliAdapter(h, args, provider?.type);
|
|
8699
8953
|
if (adapter) {
|
|
8700
8954
|
_log(`${transport} adapter: ${adapter.cliType}`);
|
|
8701
8955
|
try {
|
|
8956
|
+
assertTextOnlyInput(provider, input);
|
|
8957
|
+
if (!text) return { success: false, error: "text required for PTY send" };
|
|
8702
8958
|
await adapter.sendMessage(text);
|
|
8703
8959
|
return _logSendSuccess(`${transport}-adapter`, adapter.cliType);
|
|
8704
8960
|
} catch (e) {
|
|
@@ -8706,6 +8962,8 @@ async function handleSendChat(h, args) {
|
|
|
8706
8962
|
}
|
|
8707
8963
|
}
|
|
8708
8964
|
}
|
|
8965
|
+
assertTextOnlyInput(provider, input);
|
|
8966
|
+
if (!text) return { success: false, error: "text required" };
|
|
8709
8967
|
if (isExtensionTransport(transport)) {
|
|
8710
8968
|
_log(`Extension: ${provider?.type || "unknown_extension"}`);
|
|
8711
8969
|
try {
|
|
@@ -9870,14 +10128,14 @@ function normalizeProviderScriptArgs(args, scriptName) {
|
|
|
9870
10128
|
}
|
|
9871
10129
|
function buildControlScriptResult(scriptName, payload) {
|
|
9872
10130
|
if (!payload || typeof payload !== "object") return {};
|
|
9873
|
-
if (Array.isArray(payload.options)
|
|
10131
|
+
if (Array.isArray(payload.options)) {
|
|
9874
10132
|
return { controlResult: normalizeControlListResult(payload) };
|
|
9875
10133
|
}
|
|
9876
10134
|
const looksLikeValueMutation = /^set|^change/i.test(scriptName) || payload.currentValue !== void 0 || payload.value !== void 0;
|
|
9877
10135
|
if (looksLikeValueMutation) {
|
|
9878
10136
|
return { controlResult: normalizeControlSetResult(payload) };
|
|
9879
10137
|
}
|
|
9880
|
-
if (payload.ok !== void 0 ||
|
|
10138
|
+
if (payload.ok !== void 0 || Array.isArray(payload.effects) || typeof payload.error === "string") {
|
|
9881
10139
|
return { controlResult: normalizeControlInvokeResult(payload) };
|
|
9882
10140
|
}
|
|
9883
10141
|
return {};
|
|
@@ -10681,12 +10939,13 @@ var DaemonCommandHandler = class {
|
|
|
10681
10939
|
// src/commands/cli-manager.ts
|
|
10682
10940
|
init_provider_cli_adapter();
|
|
10683
10941
|
import * as os12 from "os";
|
|
10684
|
-
import * as
|
|
10942
|
+
import * as path12 from "path";
|
|
10685
10943
|
import * as crypto4 from "crypto";
|
|
10686
10944
|
import chalk from "chalk";
|
|
10687
10945
|
init_config();
|
|
10688
10946
|
|
|
10689
10947
|
// src/providers/cli-provider-instance.ts
|
|
10948
|
+
init_contracts();
|
|
10690
10949
|
import * as os11 from "os";
|
|
10691
10950
|
import * as path11 from "path";
|
|
10692
10951
|
import * as crypto3 from "crypto";
|
|
@@ -10990,6 +11249,7 @@ var CliProviderInstance = class {
|
|
|
10990
11249
|
onEvent(event, data) {
|
|
10991
11250
|
if (event === "send_message") {
|
|
10992
11251
|
const input = normalizeInputEnvelope(data);
|
|
11252
|
+
assertTextOnlyInput(this.provider, input);
|
|
10993
11253
|
if (input.textFallback) {
|
|
10994
11254
|
void this.adapter.sendMessage(input.textFallback).catch((e) => {
|
|
10995
11255
|
LOG.warn("CLI", `[${this.type}] send_message failed: ${e?.message || e}`);
|
|
@@ -11427,7 +11687,7 @@ ${effect.notification.body || ""}`.trim();
|
|
|
11427
11687
|
};
|
|
11428
11688
|
|
|
11429
11689
|
// src/providers/acp-provider-instance.ts
|
|
11430
|
-
|
|
11690
|
+
init_contracts();
|
|
11431
11691
|
import { Readable, Writable } from "stream";
|
|
11432
11692
|
import { spawn } from "child_process";
|
|
11433
11693
|
import {
|
|
@@ -11446,25 +11706,6 @@ function getPromptCapabilityFlags(agentCapabilities) {
|
|
|
11446
11706
|
embeddedContext: prompt.embeddedContext === true
|
|
11447
11707
|
};
|
|
11448
11708
|
}
|
|
11449
|
-
function getResourceNameFromUri(uri, fallback) {
|
|
11450
|
-
try {
|
|
11451
|
-
if (uri.startsWith("file://")) {
|
|
11452
|
-
return path12.basename(new URL(uri).pathname) || fallback;
|
|
11453
|
-
}
|
|
11454
|
-
return path12.basename(uri) || fallback;
|
|
11455
|
-
} catch {
|
|
11456
|
-
return fallback;
|
|
11457
|
-
}
|
|
11458
|
-
}
|
|
11459
|
-
function inputPartToResourceLink(part, fallbackName) {
|
|
11460
|
-
if (!part.uri) return null;
|
|
11461
|
-
return {
|
|
11462
|
-
type: "resource_link",
|
|
11463
|
-
uri: part.uri,
|
|
11464
|
-
name: getResourceNameFromUri(part.uri, fallbackName),
|
|
11465
|
-
...part.mimeType ? { mimeType: part.mimeType } : {}
|
|
11466
|
-
};
|
|
11467
|
-
}
|
|
11468
11709
|
function appendPromptText(promptParts, text) {
|
|
11469
11710
|
const normalized = typeof text === "string" ? text.trim() : "";
|
|
11470
11711
|
if (!normalized) return;
|
|
@@ -11481,55 +11722,60 @@ function buildAcpPromptParts(input, agentCapabilities) {
|
|
|
11481
11722
|
continue;
|
|
11482
11723
|
}
|
|
11483
11724
|
if (part.type === "image") {
|
|
11484
|
-
if (caps.image
|
|
11485
|
-
|
|
11486
|
-
|
|
11487
|
-
|
|
11488
|
-
|
|
11489
|
-
...part.uri ? { uri: part.uri } : {}
|
|
11490
|
-
});
|
|
11491
|
-
continue;
|
|
11725
|
+
if (!caps.image) {
|
|
11726
|
+
throw new Error("ACP agent does not support input type: image");
|
|
11727
|
+
}
|
|
11728
|
+
if (!part.data) {
|
|
11729
|
+
throw new Error("ACP image input requires inline image data");
|
|
11492
11730
|
}
|
|
11493
|
-
|
|
11494
|
-
|
|
11495
|
-
|
|
11731
|
+
promptParts.push({
|
|
11732
|
+
type: "image",
|
|
11733
|
+
data: part.data,
|
|
11734
|
+
mimeType: part.mimeType,
|
|
11735
|
+
...part.uri ? { uri: part.uri } : {}
|
|
11736
|
+
});
|
|
11496
11737
|
continue;
|
|
11497
11738
|
}
|
|
11498
11739
|
if (part.type === "audio") {
|
|
11499
|
-
if (caps.audio
|
|
11500
|
-
|
|
11501
|
-
|
|
11502
|
-
|
|
11503
|
-
|
|
11504
|
-
});
|
|
11505
|
-
continue;
|
|
11740
|
+
if (!caps.audio) {
|
|
11741
|
+
throw new Error("ACP agent does not support input type: audio");
|
|
11742
|
+
}
|
|
11743
|
+
if (!part.data) {
|
|
11744
|
+
throw new Error("ACP audio input requires inline audio data");
|
|
11506
11745
|
}
|
|
11507
|
-
|
|
11508
|
-
|
|
11509
|
-
|
|
11746
|
+
promptParts.push({
|
|
11747
|
+
type: "audio",
|
|
11748
|
+
data: part.data,
|
|
11749
|
+
mimeType: part.mimeType
|
|
11750
|
+
});
|
|
11510
11751
|
continue;
|
|
11511
11752
|
}
|
|
11512
11753
|
if (part.type === "resource") {
|
|
11513
|
-
if (caps.embeddedContext
|
|
11754
|
+
if (!caps.embeddedContext) {
|
|
11755
|
+
throw new Error("ACP agent does not support input type: resource");
|
|
11756
|
+
}
|
|
11757
|
+
if (part.text) {
|
|
11514
11758
|
promptParts.push({
|
|
11515
11759
|
type: "resource",
|
|
11516
|
-
resource:
|
|
11760
|
+
resource: { uri: part.uri, text: part.text, mimeType: part.mimeType ?? null }
|
|
11517
11761
|
});
|
|
11518
11762
|
continue;
|
|
11519
11763
|
}
|
|
11520
|
-
|
|
11521
|
-
|
|
11522
|
-
|
|
11523
|
-
|
|
11764
|
+
if (part.data) {
|
|
11765
|
+
promptParts.push({
|
|
11766
|
+
type: "resource",
|
|
11767
|
+
resource: { uri: part.uri, blob: part.data, mimeType: part.mimeType ?? null }
|
|
11768
|
+
});
|
|
11769
|
+
continue;
|
|
11770
|
+
}
|
|
11771
|
+
throw new Error("ACP resource input requires embedded text or binary data");
|
|
11524
11772
|
}
|
|
11525
11773
|
if (part.type === "video") {
|
|
11526
|
-
|
|
11527
|
-
if (fallback) promptParts.push(fallback);
|
|
11528
|
-
appendPromptText(promptParts, !part.uri ? `Attached video (${part.mimeType})` : void 0);
|
|
11774
|
+
throw new Error("ACP agent does not support input type: video");
|
|
11529
11775
|
}
|
|
11530
11776
|
}
|
|
11531
11777
|
if (!promptParts.some((part) => part.type === "text") && input.textFallback) {
|
|
11532
|
-
promptParts
|
|
11778
|
+
appendPromptText(promptParts, input.textFallback);
|
|
11533
11779
|
}
|
|
11534
11780
|
return promptParts;
|
|
11535
11781
|
}
|
|
@@ -11660,6 +11906,7 @@ var AcpProviderInstance = class {
|
|
|
11660
11906
|
onEvent(event, data) {
|
|
11661
11907
|
if (event === "send_message") {
|
|
11662
11908
|
const input = normalizeInputEnvelope(data);
|
|
11909
|
+
assertProviderSupportsDeclaredInput(this.provider, input);
|
|
11663
11910
|
const promptParts = buildAcpPromptParts(input, this.agentCapabilities);
|
|
11664
11911
|
this.sendPrompt(input.textFallback, promptParts.length > 0 ? promptParts : void 0).catch(
|
|
11665
11912
|
(e) => this.log.warn(`[${this.type}] sendPrompt error: ${e?.message}`)
|
|
@@ -12593,6 +12840,7 @@ ${rawInput}` : rawInput;
|
|
|
12593
12840
|
};
|
|
12594
12841
|
|
|
12595
12842
|
// src/commands/cli-manager.ts
|
|
12843
|
+
init_contracts();
|
|
12596
12844
|
init_logger();
|
|
12597
12845
|
|
|
12598
12846
|
// src/commands/hosted-runtime-restore.ts
|
|
@@ -12859,7 +13107,7 @@ var DaemonCliManager = class {
|
|
|
12859
13107
|
async startSession(cliType, workingDir, cliArgs, initialModel, options) {
|
|
12860
13108
|
const trimmed = (workingDir || "").trim();
|
|
12861
13109
|
if (!trimmed) throw new Error("working directory required");
|
|
12862
|
-
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os12.homedir()) :
|
|
13110
|
+
const resolvedDir = trimmed.startsWith("~") ? trimmed.replace(/^~/, os12.homedir()) : path12.resolve(trimmed);
|
|
12863
13111
|
const normalizedType = this.providerLoader.resolveAlias(cliType);
|
|
12864
13112
|
const provider = this.providerLoader.getByAlias(cliType);
|
|
12865
13113
|
const key = crypto4.randomUUID();
|
|
@@ -13318,6 +13566,12 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
13318
13566
|
const { adapter, key } = found;
|
|
13319
13567
|
if (action === "send_chat") {
|
|
13320
13568
|
const input = normalizeInputEnvelope(args?.input ? { input: args.input } : args);
|
|
13569
|
+
const provider = this.providerLoader.resolve(agentType) || this.providerLoader.getMeta(agentType);
|
|
13570
|
+
if (provider?.category === "acp") {
|
|
13571
|
+
assertProviderSupportsDeclaredInput(provider, input);
|
|
13572
|
+
} else {
|
|
13573
|
+
assertTextOnlyInput(provider, input);
|
|
13574
|
+
}
|
|
13321
13575
|
const message = input.textFallback;
|
|
13322
13576
|
if (!message) throw new Error("message required for send_chat");
|
|
13323
13577
|
await adapter.sendMessage(message);
|
|
@@ -13340,16 +13594,17 @@ Run 'adhdev doctor' for detailed diagnostics.`
|
|
|
13340
13594
|
import { execSync as execSync4, spawn as spawn2 } from "child_process";
|
|
13341
13595
|
import * as net from "net";
|
|
13342
13596
|
import * as os14 from "os";
|
|
13343
|
-
import * as
|
|
13597
|
+
import * as path14 from "path";
|
|
13344
13598
|
|
|
13345
13599
|
// src/providers/provider-loader.ts
|
|
13346
13600
|
import * as fs6 from "fs";
|
|
13347
|
-
import * as
|
|
13601
|
+
import * as path13 from "path";
|
|
13348
13602
|
import * as os13 from "os";
|
|
13349
13603
|
import * as chokidar from "chokidar";
|
|
13350
13604
|
init_logger();
|
|
13351
13605
|
|
|
13352
13606
|
// src/providers/provider-schema.ts
|
|
13607
|
+
var VALID_CAPABILITY_MEDIA_TYPES = /* @__PURE__ */ new Set(["text", "image", "audio", "video", "resource"]);
|
|
13353
13608
|
var KNOWN_PROVIDER_FIELDS = /* @__PURE__ */ new Set([
|
|
13354
13609
|
"type",
|
|
13355
13610
|
"name",
|
|
@@ -13400,6 +13655,7 @@ var KNOWN_PROVIDER_FIELDS = /* @__PURE__ */ new Set([
|
|
|
13400
13655
|
"sendDelayMs",
|
|
13401
13656
|
"sendKey",
|
|
13402
13657
|
"submitStrategy",
|
|
13658
|
+
"timeouts",
|
|
13403
13659
|
"disableUpstream"
|
|
13404
13660
|
]);
|
|
13405
13661
|
var VALUE_CONTROL_TYPES = /* @__PURE__ */ new Set(["select", "toggle", "cycle", "slider"]);
|
|
@@ -13426,6 +13682,7 @@ function validateProviderDefinition(raw) {
|
|
|
13426
13682
|
warnings.push("disableUpstream is deprecated in provider definitions; use machine-level provider source policy instead");
|
|
13427
13683
|
}
|
|
13428
13684
|
const category = provider.category;
|
|
13685
|
+
const controls = Array.isArray(provider.controls) ? provider.controls : [];
|
|
13429
13686
|
if (category === "cli" || category === "acp") {
|
|
13430
13687
|
const spawn4 = provider.spawn;
|
|
13431
13688
|
const command = spawn4 && typeof spawn4 === "object" ? spawn4.command : void 0;
|
|
@@ -13443,11 +13700,61 @@ function validateProviderDefinition(raw) {
|
|
|
13443
13700
|
if (category === "extension" && !provider.extensionId) {
|
|
13444
13701
|
warnings.push("Extension providers should have extensionId");
|
|
13445
13702
|
}
|
|
13446
|
-
|
|
13703
|
+
validateCapabilities(provider, controls, errors);
|
|
13704
|
+
for (const control of controls) {
|
|
13447
13705
|
validateControl(control, errors);
|
|
13448
13706
|
}
|
|
13449
13707
|
return { errors, warnings };
|
|
13450
13708
|
}
|
|
13709
|
+
function validateCapabilities(provider, controls, errors) {
|
|
13710
|
+
const capabilities = provider.capabilities;
|
|
13711
|
+
if (provider.contractVersion === 2) {
|
|
13712
|
+
if (!capabilities || typeof capabilities !== "object") {
|
|
13713
|
+
errors.push("contractVersion 2 providers must declare capabilities");
|
|
13714
|
+
return;
|
|
13715
|
+
}
|
|
13716
|
+
}
|
|
13717
|
+
if (!capabilities || typeof capabilities !== "object") {
|
|
13718
|
+
return;
|
|
13719
|
+
}
|
|
13720
|
+
const input = capabilities.input;
|
|
13721
|
+
if (!input || typeof input !== "object") {
|
|
13722
|
+
errors.push("capabilities.input is required");
|
|
13723
|
+
} else {
|
|
13724
|
+
if (typeof input.multipart !== "boolean") {
|
|
13725
|
+
errors.push("capabilities.input.multipart must be boolean");
|
|
13726
|
+
}
|
|
13727
|
+
if (!Array.isArray(input.mediaTypes) || input.mediaTypes.length === 0) {
|
|
13728
|
+
errors.push("capabilities.input.mediaTypes must be a non-empty array");
|
|
13729
|
+
} else if (input.mediaTypes.some((type) => typeof type !== "string" || !VALID_CAPABILITY_MEDIA_TYPES.has(type))) {
|
|
13730
|
+
errors.push(`capabilities.input.mediaTypes must only include: ${Array.from(VALID_CAPABILITY_MEDIA_TYPES).join(", ")}`);
|
|
13731
|
+
}
|
|
13732
|
+
}
|
|
13733
|
+
const output = capabilities.output;
|
|
13734
|
+
if (!output || typeof output !== "object") {
|
|
13735
|
+
errors.push("capabilities.output is required");
|
|
13736
|
+
} else {
|
|
13737
|
+
if (typeof output.richContent !== "boolean") {
|
|
13738
|
+
errors.push("capabilities.output.richContent must be boolean");
|
|
13739
|
+
}
|
|
13740
|
+
if (!Array.isArray(output.mediaTypes) || output.mediaTypes.length === 0) {
|
|
13741
|
+
errors.push("capabilities.output.mediaTypes must be a non-empty array");
|
|
13742
|
+
} else if (output.mediaTypes.some((type) => typeof type !== "string" || !VALID_CAPABILITY_MEDIA_TYPES.has(type))) {
|
|
13743
|
+
errors.push(`capabilities.output.mediaTypes must only include: ${Array.from(VALID_CAPABILITY_MEDIA_TYPES).join(", ")}`);
|
|
13744
|
+
}
|
|
13745
|
+
}
|
|
13746
|
+
const controlCapabilities = capabilities.controls;
|
|
13747
|
+
if (!controlCapabilities || typeof controlCapabilities !== "object") {
|
|
13748
|
+
errors.push("capabilities.controls is required");
|
|
13749
|
+
return;
|
|
13750
|
+
}
|
|
13751
|
+
if (typeof controlCapabilities.typedResults !== "boolean") {
|
|
13752
|
+
errors.push("capabilities.controls.typedResults must be boolean");
|
|
13753
|
+
}
|
|
13754
|
+
if (controls.length > 0 && controlCapabilities.typedResults !== true) {
|
|
13755
|
+
errors.push("providers declaring controls must set capabilities.controls.typedResults=true");
|
|
13756
|
+
}
|
|
13757
|
+
}
|
|
13451
13758
|
function validateControl(control, errors) {
|
|
13452
13759
|
if (!control || typeof control !== "object") {
|
|
13453
13760
|
errors.push("controls: each control must be an object");
|
|
@@ -13502,9 +13809,9 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13502
13809
|
static META_FILE = ".meta.json";
|
|
13503
13810
|
constructor(options) {
|
|
13504
13811
|
this.logFn = options?.logFn || LOG.forComponent("Provider").asLogFn();
|
|
13505
|
-
this.defaultProvidersDir =
|
|
13812
|
+
this.defaultProvidersDir = path13.join(os13.homedir(), ".adhdev", "providers");
|
|
13506
13813
|
this.userDir = this.defaultProvidersDir;
|
|
13507
|
-
this.upstreamDir =
|
|
13814
|
+
this.upstreamDir = path13.join(this.defaultProvidersDir, ".upstream");
|
|
13508
13815
|
this.disableUpstream = false;
|
|
13509
13816
|
this.applySourceConfig({
|
|
13510
13817
|
userDir: options?.userDir,
|
|
@@ -13552,7 +13859,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13552
13859
|
}
|
|
13553
13860
|
this.sourceMode = nextSourceMode;
|
|
13554
13861
|
this.userDir = this.explicitProviderDir || this.defaultProvidersDir;
|
|
13555
|
-
this.upstreamDir =
|
|
13862
|
+
this.upstreamDir = path13.join(this.defaultProvidersDir, ".upstream");
|
|
13556
13863
|
this.disableUpstream = this.sourceMode === "no-upstream";
|
|
13557
13864
|
if (this.explicitProviderDir) {
|
|
13558
13865
|
this.log(`Config 'providerDir' applied: ${this.userDir}`);
|
|
@@ -13566,7 +13873,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13566
13873
|
* Canonical provider directory shape for a given root.
|
|
13567
13874
|
*/
|
|
13568
13875
|
getProviderDir(root, category, type) {
|
|
13569
|
-
return
|
|
13876
|
+
return path13.join(root, category, type);
|
|
13570
13877
|
}
|
|
13571
13878
|
/**
|
|
13572
13879
|
* Canonical user override directory for a provider.
|
|
@@ -13593,7 +13900,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13593
13900
|
resolveProviderFile(type, ...segments) {
|
|
13594
13901
|
const dir = this.findProviderDirInternal(type);
|
|
13595
13902
|
if (!dir) return null;
|
|
13596
|
-
return
|
|
13903
|
+
return path13.join(dir, ...segments);
|
|
13597
13904
|
}
|
|
13598
13905
|
/**
|
|
13599
13906
|
* Load all providers (3-tier priority)
|
|
@@ -13632,7 +13939,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13632
13939
|
if (!fs6.existsSync(this.upstreamDir)) return false;
|
|
13633
13940
|
try {
|
|
13634
13941
|
return fs6.readdirSync(this.upstreamDir).some(
|
|
13635
|
-
(d) => fs6.statSync(
|
|
13942
|
+
(d) => fs6.statSync(path13.join(this.upstreamDir, d)).isDirectory()
|
|
13636
13943
|
);
|
|
13637
13944
|
} catch {
|
|
13638
13945
|
return false;
|
|
@@ -13947,8 +14254,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13947
14254
|
resolved._resolvedScriptDir = entry.scriptDir;
|
|
13948
14255
|
resolved._resolvedScriptsSource = `compatibility:${entry.ideVersion}`;
|
|
13949
14256
|
if (providerDir) {
|
|
13950
|
-
const fullDir =
|
|
13951
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
14257
|
+
const fullDir = path13.join(providerDir, entry.scriptDir);
|
|
14258
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
|
|
13952
14259
|
}
|
|
13953
14260
|
matched = true;
|
|
13954
14261
|
}
|
|
@@ -13963,8 +14270,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13963
14270
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
13964
14271
|
resolved._resolvedScriptsSource = "defaultScriptDir:version_miss";
|
|
13965
14272
|
if (providerDir) {
|
|
13966
|
-
const fullDir =
|
|
13967
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
14273
|
+
const fullDir = path13.join(providerDir, base.defaultScriptDir);
|
|
14274
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
|
|
13968
14275
|
}
|
|
13969
14276
|
}
|
|
13970
14277
|
resolved._versionWarning = `Version ${currentVersion} not in compatibility matrix. Using default scripts.`;
|
|
@@ -13981,8 +14288,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13981
14288
|
resolved._resolvedScriptDir = dirOverride;
|
|
13982
14289
|
resolved._resolvedScriptsSource = `versions:${range}`;
|
|
13983
14290
|
if (providerDir) {
|
|
13984
|
-
const fullDir =
|
|
13985
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
14291
|
+
const fullDir = path13.join(providerDir, dirOverride);
|
|
14292
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
|
|
13986
14293
|
}
|
|
13987
14294
|
}
|
|
13988
14295
|
} else if (override.scripts) {
|
|
@@ -13998,8 +14305,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
13998
14305
|
resolved._resolvedScriptDir = base.defaultScriptDir;
|
|
13999
14306
|
resolved._resolvedScriptsSource = "defaultScriptDir:no_version";
|
|
14000
14307
|
if (providerDir) {
|
|
14001
|
-
const fullDir =
|
|
14002
|
-
resolved._resolvedScriptsPath = fs6.existsSync(
|
|
14308
|
+
const fullDir = path13.join(providerDir, base.defaultScriptDir);
|
|
14309
|
+
resolved._resolvedScriptsPath = fs6.existsSync(path13.join(fullDir, "scripts.js")) ? path13.join(fullDir, "scripts.js") : fullDir;
|
|
14003
14310
|
}
|
|
14004
14311
|
}
|
|
14005
14312
|
}
|
|
@@ -14024,14 +14331,14 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14024
14331
|
this.log(` [loadScriptsFromDir] ${type}: providerDir not found`);
|
|
14025
14332
|
return null;
|
|
14026
14333
|
}
|
|
14027
|
-
const dir =
|
|
14334
|
+
const dir = path13.join(providerDir, scriptDir);
|
|
14028
14335
|
if (!fs6.existsSync(dir)) {
|
|
14029
14336
|
this.log(` [loadScriptsFromDir] ${type}: dir not found: ${dir}`);
|
|
14030
14337
|
return null;
|
|
14031
14338
|
}
|
|
14032
14339
|
const cached = this.scriptsCache.get(dir);
|
|
14033
14340
|
if (cached) return cached;
|
|
14034
|
-
const scriptsJs =
|
|
14341
|
+
const scriptsJs = path13.join(dir, "scripts.js");
|
|
14035
14342
|
if (fs6.existsSync(scriptsJs)) {
|
|
14036
14343
|
try {
|
|
14037
14344
|
delete __require.cache[__require.resolve(scriptsJs)];
|
|
@@ -14073,7 +14380,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14073
14380
|
return;
|
|
14074
14381
|
}
|
|
14075
14382
|
if (filePath.endsWith(".js") || filePath.endsWith(".json")) {
|
|
14076
|
-
this.log(`File changed: ${
|
|
14383
|
+
this.log(`File changed: ${path13.basename(filePath)}, reloading...`);
|
|
14077
14384
|
this.reload();
|
|
14078
14385
|
}
|
|
14079
14386
|
};
|
|
@@ -14128,7 +14435,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14128
14435
|
}
|
|
14129
14436
|
const https = __require("https");
|
|
14130
14437
|
const { execSync: execSync7 } = __require("child_process");
|
|
14131
|
-
const metaPath =
|
|
14438
|
+
const metaPath = path13.join(this.upstreamDir, _ProviderLoader.META_FILE);
|
|
14132
14439
|
let prevEtag = "";
|
|
14133
14440
|
let prevTimestamp = 0;
|
|
14134
14441
|
try {
|
|
@@ -14188,17 +14495,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14188
14495
|
return { updated: false };
|
|
14189
14496
|
}
|
|
14190
14497
|
this.log("Downloading latest providers from GitHub...");
|
|
14191
|
-
const tmpTar =
|
|
14192
|
-
const tmpExtract =
|
|
14498
|
+
const tmpTar = path13.join(os13.tmpdir(), `adhdev-providers-${Date.now()}.tar.gz`);
|
|
14499
|
+
const tmpExtract = path13.join(os13.tmpdir(), `adhdev-providers-extract-${Date.now()}`);
|
|
14193
14500
|
await this.downloadFile(_ProviderLoader.GITHUB_TARBALL_URL, tmpTar);
|
|
14194
14501
|
fs6.mkdirSync(tmpExtract, { recursive: true });
|
|
14195
14502
|
execSync7(`tar -xzf "${tmpTar}" -C "${tmpExtract}"`, { timeout: 3e4 });
|
|
14196
14503
|
const extracted = fs6.readdirSync(tmpExtract);
|
|
14197
14504
|
const rootDir = extracted.find(
|
|
14198
|
-
(d) => fs6.statSync(
|
|
14505
|
+
(d) => fs6.statSync(path13.join(tmpExtract, d)).isDirectory() && d.startsWith("adhdev-providers")
|
|
14199
14506
|
);
|
|
14200
14507
|
if (!rootDir) throw new Error("Unexpected tarball structure");
|
|
14201
|
-
const sourceDir =
|
|
14508
|
+
const sourceDir = path13.join(tmpExtract, rootDir);
|
|
14202
14509
|
const backupDir = this.upstreamDir + ".bak";
|
|
14203
14510
|
if (fs6.existsSync(this.upstreamDir)) {
|
|
14204
14511
|
if (fs6.existsSync(backupDir)) fs6.rmSync(backupDir, { recursive: true, force: true });
|
|
@@ -14273,8 +14580,8 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14273
14580
|
copyDirRecursive(src, dest) {
|
|
14274
14581
|
fs6.mkdirSync(dest, { recursive: true });
|
|
14275
14582
|
for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
|
|
14276
|
-
const srcPath =
|
|
14277
|
-
const destPath =
|
|
14583
|
+
const srcPath = path13.join(src, entry.name);
|
|
14584
|
+
const destPath = path13.join(dest, entry.name);
|
|
14278
14585
|
if (entry.isDirectory()) {
|
|
14279
14586
|
this.copyDirRecursive(srcPath, destPath);
|
|
14280
14587
|
} else {
|
|
@@ -14285,7 +14592,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14285
14592
|
/** .meta.json save */
|
|
14286
14593
|
writeMeta(metaPath, etag, timestamp) {
|
|
14287
14594
|
try {
|
|
14288
|
-
fs6.mkdirSync(
|
|
14595
|
+
fs6.mkdirSync(path13.dirname(metaPath), { recursive: true });
|
|
14289
14596
|
fs6.writeFileSync(metaPath, JSON.stringify({
|
|
14290
14597
|
etag,
|
|
14291
14598
|
timestamp,
|
|
@@ -14302,7 +14609,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14302
14609
|
const scan = (d) => {
|
|
14303
14610
|
try {
|
|
14304
14611
|
for (const entry of fs6.readdirSync(d, { withFileTypes: true })) {
|
|
14305
|
-
if (entry.isDirectory()) scan(
|
|
14612
|
+
if (entry.isDirectory()) scan(path13.join(d, entry.name));
|
|
14306
14613
|
else if (entry.name === "provider.json") count++;
|
|
14307
14614
|
}
|
|
14308
14615
|
} catch {
|
|
@@ -14487,17 +14794,17 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14487
14794
|
for (const root of searchRoots) {
|
|
14488
14795
|
if (!fs6.existsSync(root)) continue;
|
|
14489
14796
|
const candidate = this.getProviderDir(root, cat, type);
|
|
14490
|
-
if (fs6.existsSync(
|
|
14491
|
-
const catDir =
|
|
14797
|
+
if (fs6.existsSync(path13.join(candidate, "provider.json"))) return candidate;
|
|
14798
|
+
const catDir = path13.join(root, cat);
|
|
14492
14799
|
if (fs6.existsSync(catDir)) {
|
|
14493
14800
|
try {
|
|
14494
14801
|
for (const entry of fs6.readdirSync(catDir, { withFileTypes: true })) {
|
|
14495
14802
|
if (!entry.isDirectory()) continue;
|
|
14496
|
-
const jsonPath =
|
|
14803
|
+
const jsonPath = path13.join(catDir, entry.name, "provider.json");
|
|
14497
14804
|
if (fs6.existsSync(jsonPath)) {
|
|
14498
14805
|
try {
|
|
14499
14806
|
const data = JSON.parse(fs6.readFileSync(jsonPath, "utf-8"));
|
|
14500
|
-
if (data.type === type) return
|
|
14807
|
+
if (data.type === type) return path13.join(catDir, entry.name);
|
|
14501
14808
|
} catch {
|
|
14502
14809
|
}
|
|
14503
14810
|
}
|
|
@@ -14514,7 +14821,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14514
14821
|
* (template substitution is NOT applied here — scripts.js handles that)
|
|
14515
14822
|
*/
|
|
14516
14823
|
buildScriptWrappersFromDir(dir) {
|
|
14517
|
-
const scriptsJs =
|
|
14824
|
+
const scriptsJs = path13.join(dir, "scripts.js");
|
|
14518
14825
|
if (fs6.existsSync(scriptsJs)) {
|
|
14519
14826
|
try {
|
|
14520
14827
|
delete __require.cache[__require.resolve(scriptsJs)];
|
|
@@ -14528,7 +14835,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14528
14835
|
for (const file of fs6.readdirSync(dir)) {
|
|
14529
14836
|
if (!file.endsWith(".js")) continue;
|
|
14530
14837
|
const scriptName = toCamel(file.replace(".js", ""));
|
|
14531
|
-
const filePath =
|
|
14838
|
+
const filePath = path13.join(dir, file);
|
|
14532
14839
|
result[scriptName] = (...args) => {
|
|
14533
14840
|
try {
|
|
14534
14841
|
let content = fs6.readFileSync(filePath, "utf-8");
|
|
@@ -14588,7 +14895,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14588
14895
|
}
|
|
14589
14896
|
const hasJson = entries.some((e) => e.name === "provider.json");
|
|
14590
14897
|
if (hasJson) {
|
|
14591
|
-
const jsonPath =
|
|
14898
|
+
const jsonPath = path13.join(d, "provider.json");
|
|
14592
14899
|
try {
|
|
14593
14900
|
const raw = fs6.readFileSync(jsonPath, "utf-8");
|
|
14594
14901
|
const mod = JSON.parse(raw);
|
|
@@ -14609,7 +14916,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14609
14916
|
this.log(`\u26A0 Invalid provider at ${jsonPath}: ${validation.errors.join("; ")}`);
|
|
14610
14917
|
} else {
|
|
14611
14918
|
const hasCompatibility = Array.isArray(normalizedProvider.compatibility);
|
|
14612
|
-
const scriptsPath =
|
|
14919
|
+
const scriptsPath = path13.join(d, "scripts.js");
|
|
14613
14920
|
if (!hasCompatibility && fs6.existsSync(scriptsPath)) {
|
|
14614
14921
|
try {
|
|
14615
14922
|
delete __require.cache[__require.resolve(scriptsPath)];
|
|
@@ -14635,7 +14942,7 @@ var ProviderLoader = class _ProviderLoader {
|
|
|
14635
14942
|
if (!entry.isDirectory()) continue;
|
|
14636
14943
|
if (entry.name.startsWith("_") || entry.name.startsWith(".")) continue;
|
|
14637
14944
|
if (excludeDirs && d === dir && excludeDirs.includes(entry.name)) continue;
|
|
14638
|
-
scan(
|
|
14945
|
+
scan(path13.join(d, entry.name));
|
|
14639
14946
|
}
|
|
14640
14947
|
}
|
|
14641
14948
|
};
|
|
@@ -14893,8 +15200,8 @@ function detectCurrentWorkspace(ideId) {
|
|
|
14893
15200
|
const appNameMap = getMacAppIdentifiers();
|
|
14894
15201
|
const appName = appNameMap[ideId];
|
|
14895
15202
|
if (appName) {
|
|
14896
|
-
const storagePath =
|
|
14897
|
-
process.env.APPDATA ||
|
|
15203
|
+
const storagePath = path14.join(
|
|
15204
|
+
process.env.APPDATA || path14.join(os14.homedir(), "AppData", "Roaming"),
|
|
14898
15205
|
appName,
|
|
14899
15206
|
"storage.json"
|
|
14900
15207
|
);
|
|
@@ -15072,9 +15379,9 @@ init_logger();
|
|
|
15072
15379
|
|
|
15073
15380
|
// src/logging/command-log.ts
|
|
15074
15381
|
import * as fs7 from "fs";
|
|
15075
|
-
import * as
|
|
15382
|
+
import * as path15 from "path";
|
|
15076
15383
|
import * as os15 from "os";
|
|
15077
|
-
var LOG_DIR2 = process.platform === "win32" ?
|
|
15384
|
+
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");
|
|
15078
15385
|
var MAX_FILE_SIZE = 5 * 1024 * 1024;
|
|
15079
15386
|
var MAX_DAYS = 7;
|
|
15080
15387
|
try {
|
|
@@ -15112,13 +15419,13 @@ function getDateStr2() {
|
|
|
15112
15419
|
return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
15113
15420
|
}
|
|
15114
15421
|
var currentDate2 = getDateStr2();
|
|
15115
|
-
var currentFile =
|
|
15422
|
+
var currentFile = path15.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
15116
15423
|
var writeCount2 = 0;
|
|
15117
15424
|
function checkRotation() {
|
|
15118
15425
|
const today = getDateStr2();
|
|
15119
15426
|
if (today !== currentDate2) {
|
|
15120
15427
|
currentDate2 = today;
|
|
15121
|
-
currentFile =
|
|
15428
|
+
currentFile = path15.join(LOG_DIR2, `commands-${currentDate2}.jsonl`);
|
|
15122
15429
|
cleanOldFiles();
|
|
15123
15430
|
}
|
|
15124
15431
|
}
|
|
@@ -15132,7 +15439,7 @@ function cleanOldFiles() {
|
|
|
15132
15439
|
const dateMatch = file.match(/commands-(\d{4}-\d{2}-\d{2})/);
|
|
15133
15440
|
if (dateMatch && dateMatch[1] < cutoffStr) {
|
|
15134
15441
|
try {
|
|
15135
|
-
fs7.unlinkSync(
|
|
15442
|
+
fs7.unlinkSync(path15.join(LOG_DIR2, file));
|
|
15136
15443
|
} catch {
|
|
15137
15444
|
}
|
|
15138
15445
|
}
|
|
@@ -15545,13 +15852,13 @@ import { execFileSync } from "child_process";
|
|
|
15545
15852
|
import { spawn as spawn3 } from "child_process";
|
|
15546
15853
|
import * as fs8 from "fs";
|
|
15547
15854
|
import * as os17 from "os";
|
|
15548
|
-
import * as
|
|
15855
|
+
import * as path16 from "path";
|
|
15549
15856
|
var UPGRADE_HELPER_ENV = "ADHDEV_DAEMON_UPGRADE_HELPER";
|
|
15550
15857
|
function getUpgradeLogPath() {
|
|
15551
15858
|
const home = os17.homedir();
|
|
15552
|
-
const dir =
|
|
15859
|
+
const dir = path16.join(home, ".adhdev");
|
|
15553
15860
|
fs8.mkdirSync(dir, { recursive: true });
|
|
15554
|
-
return
|
|
15861
|
+
return path16.join(dir, "daemon-upgrade.log");
|
|
15555
15862
|
}
|
|
15556
15863
|
function appendUpgradeLog(message) {
|
|
15557
15864
|
const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] ${message}
|
|
@@ -15591,7 +15898,7 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
15591
15898
|
}
|
|
15592
15899
|
}
|
|
15593
15900
|
function stopSessionHostProcesses(appName) {
|
|
15594
|
-
const pidFile =
|
|
15901
|
+
const pidFile = path16.join(os17.homedir(), ".adhdev", `${appName}-session-host.pid`);
|
|
15595
15902
|
try {
|
|
15596
15903
|
if (fs8.existsSync(pidFile)) {
|
|
15597
15904
|
const pid = Number.parseInt(fs8.readFileSync(pidFile, "utf8").trim(), 10);
|
|
@@ -15620,7 +15927,7 @@ function stopSessionHostProcesses(appName) {
|
|
|
15620
15927
|
}
|
|
15621
15928
|
}
|
|
15622
15929
|
function removeDaemonPidFile() {
|
|
15623
|
-
const pidFile =
|
|
15930
|
+
const pidFile = path16.join(os17.homedir(), ".adhdev", "daemon.pid");
|
|
15624
15931
|
try {
|
|
15625
15932
|
fs8.unlinkSync(pidFile);
|
|
15626
15933
|
} catch {
|
|
@@ -15631,7 +15938,7 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
|
15631
15938
|
const npmRoot = execFileSync(getNpmExecutable(), ["root", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
15632
15939
|
if (!npmRoot) return;
|
|
15633
15940
|
const npmPrefix = execFileSync(getNpmExecutable(), ["prefix", "-g"], { encoding: "utf8", ...npmExecOpts }).trim();
|
|
15634
|
-
const binDir = process.platform === "win32" ? npmPrefix :
|
|
15941
|
+
const binDir = process.platform === "win32" ? npmPrefix : path16.join(npmPrefix, "bin");
|
|
15635
15942
|
const packageBaseName = pkgName.startsWith("@") ? pkgName.split("/")[1] : pkgName;
|
|
15636
15943
|
const binNames = /* @__PURE__ */ new Set([packageBaseName]);
|
|
15637
15944
|
if (pkgName === "@adhdev/daemon-standalone") {
|
|
@@ -15639,25 +15946,25 @@ function cleanupStaleGlobalInstallDirs(pkgName) {
|
|
|
15639
15946
|
}
|
|
15640
15947
|
if (pkgName.startsWith("@")) {
|
|
15641
15948
|
const [scope, name] = pkgName.split("/");
|
|
15642
|
-
const scopeDir =
|
|
15949
|
+
const scopeDir = path16.join(npmRoot, scope);
|
|
15643
15950
|
if (!fs8.existsSync(scopeDir)) return;
|
|
15644
15951
|
for (const entry of fs8.readdirSync(scopeDir)) {
|
|
15645
15952
|
if (!entry.startsWith(`.${name}-`)) continue;
|
|
15646
|
-
fs8.rmSync(
|
|
15647
|
-
appendUpgradeLog(`Removed stale scoped staging dir: ${
|
|
15953
|
+
fs8.rmSync(path16.join(scopeDir, entry), { recursive: true, force: true });
|
|
15954
|
+
appendUpgradeLog(`Removed stale scoped staging dir: ${path16.join(scopeDir, entry)}`);
|
|
15648
15955
|
}
|
|
15649
15956
|
} else {
|
|
15650
15957
|
for (const entry of fs8.readdirSync(npmRoot)) {
|
|
15651
15958
|
if (!entry.startsWith(`.${pkgName}-`)) continue;
|
|
15652
|
-
fs8.rmSync(
|
|
15653
|
-
appendUpgradeLog(`Removed stale staging dir: ${
|
|
15959
|
+
fs8.rmSync(path16.join(npmRoot, entry), { recursive: true, force: true });
|
|
15960
|
+
appendUpgradeLog(`Removed stale staging dir: ${path16.join(npmRoot, entry)}`);
|
|
15654
15961
|
}
|
|
15655
15962
|
}
|
|
15656
15963
|
if (fs8.existsSync(binDir)) {
|
|
15657
15964
|
for (const entry of fs8.readdirSync(binDir)) {
|
|
15658
15965
|
if (![...binNames].some((name) => entry.startsWith(`.${name}-`))) continue;
|
|
15659
|
-
fs8.rmSync(
|
|
15660
|
-
appendUpgradeLog(`Removed stale bin staging entry: ${
|
|
15966
|
+
fs8.rmSync(path16.join(binDir, entry), { recursive: true, force: true });
|
|
15967
|
+
appendUpgradeLog(`Removed stale bin staging entry: ${path16.join(binDir, entry)}`);
|
|
15661
15968
|
}
|
|
15662
15969
|
}
|
|
15663
15970
|
}
|
|
@@ -16687,6 +16994,7 @@ var DEFAULT_DAEMON_PORT = 19222;
|
|
|
16687
16994
|
var DAEMON_WS_PATH = "/ipc";
|
|
16688
16995
|
|
|
16689
16996
|
// src/agent-stream/provider-adapter.ts
|
|
16997
|
+
init_read_chat_contract();
|
|
16690
16998
|
init_chat_message_normalization();
|
|
16691
16999
|
var ProviderStreamAdapter = class {
|
|
16692
17000
|
agentType;
|
|
@@ -16792,26 +17100,29 @@ var ProviderStreamAdapter = class {
|
|
|
16792
17100
|
}
|
|
16793
17101
|
return state2;
|
|
16794
17102
|
}
|
|
17103
|
+
const validated = validateReadChatResultPayload(data, `${this.agentType} readChat`);
|
|
17104
|
+
const validatedStatus = validated.status;
|
|
17105
|
+
const streamStatus = validatedStatus === "generating" || validatedStatus === "long_generating" ? "streaming" : validatedStatus;
|
|
16795
17106
|
const state = {
|
|
16796
17107
|
agentType: this.agentType,
|
|
16797
17108
|
agentName: this.agentName,
|
|
16798
17109
|
extensionId: this.extensionId,
|
|
16799
|
-
status:
|
|
16800
|
-
messages: normalizeChatMessages(
|
|
16801
|
-
inputContent:
|
|
16802
|
-
activeModal:
|
|
17110
|
+
status: streamStatus,
|
|
17111
|
+
messages: normalizeChatMessages(validated.messages),
|
|
17112
|
+
inputContent: typeof validated.inputContent === "string" ? validated.inputContent : "",
|
|
17113
|
+
...validated.activeModal ? { activeModal: validated.activeModal } : {}
|
|
16803
17114
|
};
|
|
16804
|
-
if (typeof
|
|
16805
|
-
state.title =
|
|
17115
|
+
if (typeof validated.title === "string" && validated.title.trim()) {
|
|
17116
|
+
state.title = validated.title.trim();
|
|
16806
17117
|
}
|
|
16807
|
-
const controlValues = extractProviderControlValues(this.provider.controls,
|
|
17118
|
+
const controlValues = extractProviderControlValues(this.provider.controls, validated);
|
|
16808
17119
|
const surface = resolveProviderStateSurface({
|
|
16809
17120
|
controlValues,
|
|
16810
|
-
summaryMetadata:
|
|
17121
|
+
summaryMetadata: validated.summaryMetadata
|
|
16811
17122
|
});
|
|
16812
17123
|
if (surface.controlValues) state.controlValues = surface.controlValues;
|
|
16813
17124
|
if (surface.summaryMetadata) state.summaryMetadata = surface.summaryMetadata;
|
|
16814
|
-
const effects = normalizeProviderEffects(
|
|
17125
|
+
const effects = normalizeProviderEffects(validated);
|
|
16815
17126
|
if (effects.length > 0) state.effects = effects;
|
|
16816
17127
|
if (state.messages.length > 0) {
|
|
16817
17128
|
this.lastSuccessState = state;
|
|
@@ -17650,15 +17961,16 @@ var ProviderInstanceManager = class {
|
|
|
17650
17961
|
};
|
|
17651
17962
|
|
|
17652
17963
|
// src/index.ts
|
|
17964
|
+
init_io_contracts();
|
|
17653
17965
|
init_chat_message_normalization();
|
|
17654
17966
|
|
|
17655
17967
|
// src/providers/version-archive.ts
|
|
17656
17968
|
import * as fs10 from "fs";
|
|
17657
|
-
import * as
|
|
17969
|
+
import * as path17 from "path";
|
|
17658
17970
|
import * as os18 from "os";
|
|
17659
17971
|
import { execSync as execSync5 } from "child_process";
|
|
17660
17972
|
import { platform as platform8 } from "os";
|
|
17661
|
-
var ARCHIVE_PATH =
|
|
17973
|
+
var ARCHIVE_PATH = path17.join(os18.homedir(), ".adhdev", "version-history.json");
|
|
17662
17974
|
var MAX_ENTRIES_PER_PROVIDER = 20;
|
|
17663
17975
|
var VersionArchive = class {
|
|
17664
17976
|
history = {};
|
|
@@ -17705,7 +18017,7 @@ var VersionArchive = class {
|
|
|
17705
18017
|
}
|
|
17706
18018
|
save() {
|
|
17707
18019
|
try {
|
|
17708
|
-
fs10.mkdirSync(
|
|
18020
|
+
fs10.mkdirSync(path17.dirname(ARCHIVE_PATH), { recursive: true });
|
|
17709
18021
|
fs10.writeFileSync(ARCHIVE_PATH, JSON.stringify(this.history, null, 2));
|
|
17710
18022
|
} catch {
|
|
17711
18023
|
}
|
|
@@ -17762,7 +18074,7 @@ function checkPathExists2(paths) {
|
|
|
17762
18074
|
for (const p of paths) {
|
|
17763
18075
|
if (p.includes("*")) {
|
|
17764
18076
|
const home = os18.homedir();
|
|
17765
|
-
const resolved = p.replace(/\*/g, home.split(
|
|
18077
|
+
const resolved = p.replace(/\*/g, home.split(path17.sep).pop() || "");
|
|
17766
18078
|
if (fs10.existsSync(resolved)) return resolved;
|
|
17767
18079
|
} else {
|
|
17768
18080
|
if (fs10.existsSync(p)) return p;
|
|
@@ -17772,7 +18084,7 @@ function checkPathExists2(paths) {
|
|
|
17772
18084
|
}
|
|
17773
18085
|
function getMacAppVersion(appPath) {
|
|
17774
18086
|
if (platform8() !== "darwin" || !appPath.endsWith(".app")) return null;
|
|
17775
|
-
const plistPath =
|
|
18087
|
+
const plistPath = path17.join(appPath, "Contents", "Info.plist");
|
|
17776
18088
|
if (!fs10.existsSync(plistPath)) return null;
|
|
17777
18089
|
const raw = runCommand(`/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plistPath}"`);
|
|
17778
18090
|
return raw || null;
|
|
@@ -17798,7 +18110,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
17798
18110
|
const cliBin = provider.cli ? findBinary2(provider.cli) : null;
|
|
17799
18111
|
let resolvedBin = cliBin;
|
|
17800
18112
|
if (!resolvedBin && appPath && currentOs === "darwin") {
|
|
17801
|
-
const bundled =
|
|
18113
|
+
const bundled = path17.join(appPath, "Contents", "Resources", "app", "bin", provider.cli || "");
|
|
17802
18114
|
if (provider.cli && fs10.existsSync(bundled)) resolvedBin = bundled;
|
|
17803
18115
|
}
|
|
17804
18116
|
info.installed = !!(appPath || resolvedBin);
|
|
@@ -17839,7 +18151,7 @@ async function detectAllVersions(loader, archive) {
|
|
|
17839
18151
|
// src/daemon/dev-server.ts
|
|
17840
18152
|
import * as http2 from "http";
|
|
17841
18153
|
import * as fs14 from "fs";
|
|
17842
|
-
import * as
|
|
18154
|
+
import * as path21 from "path";
|
|
17843
18155
|
init_config();
|
|
17844
18156
|
|
|
17845
18157
|
// src/daemon/scaffold-template.ts
|
|
@@ -18184,7 +18496,7 @@ init_logger();
|
|
|
18184
18496
|
// src/daemon/dev-cdp-handlers.ts
|
|
18185
18497
|
init_logger();
|
|
18186
18498
|
import * as fs11 from "fs";
|
|
18187
|
-
import * as
|
|
18499
|
+
import * as path18 from "path";
|
|
18188
18500
|
async function handleCdpEvaluate(ctx, req, res) {
|
|
18189
18501
|
const body = await ctx.readBody(req);
|
|
18190
18502
|
const { expression, timeout, ideType } = body;
|
|
@@ -18362,17 +18674,17 @@ async function handleScriptHints(ctx, type, _req, res) {
|
|
|
18362
18674
|
return;
|
|
18363
18675
|
}
|
|
18364
18676
|
let scriptsPath = "";
|
|
18365
|
-
const directScripts =
|
|
18677
|
+
const directScripts = path18.join(dir, "scripts.js");
|
|
18366
18678
|
if (fs11.existsSync(directScripts)) {
|
|
18367
18679
|
scriptsPath = directScripts;
|
|
18368
18680
|
} else {
|
|
18369
|
-
const scriptsDir =
|
|
18681
|
+
const scriptsDir = path18.join(dir, "scripts");
|
|
18370
18682
|
if (fs11.existsSync(scriptsDir)) {
|
|
18371
18683
|
const versions = fs11.readdirSync(scriptsDir).filter((d) => {
|
|
18372
|
-
return fs11.statSync(
|
|
18684
|
+
return fs11.statSync(path18.join(scriptsDir, d)).isDirectory();
|
|
18373
18685
|
}).sort().reverse();
|
|
18374
18686
|
for (const ver of versions) {
|
|
18375
|
-
const p =
|
|
18687
|
+
const p = path18.join(scriptsDir, ver, "scripts.js");
|
|
18376
18688
|
if (fs11.existsSync(p)) {
|
|
18377
18689
|
scriptsPath = p;
|
|
18378
18690
|
break;
|
|
@@ -19201,7 +19513,7 @@ async function handleDomContext(ctx, type, req, res) {
|
|
|
19201
19513
|
|
|
19202
19514
|
// src/daemon/dev-cli-debug.ts
|
|
19203
19515
|
import * as fs12 from "fs";
|
|
19204
|
-
import * as
|
|
19516
|
+
import * as path19 from "path";
|
|
19205
19517
|
function slugifyFixtureName(value) {
|
|
19206
19518
|
const normalized = String(value || "").trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^-+|-+$/g, "");
|
|
19207
19519
|
return normalized || `fixture-${Date.now()}`;
|
|
@@ -19211,11 +19523,11 @@ function getCliFixtureDir(ctx, type) {
|
|
|
19211
19523
|
if (!providerDir) {
|
|
19212
19524
|
throw new Error(`Provider directory not found for '${type}'`);
|
|
19213
19525
|
}
|
|
19214
|
-
return
|
|
19526
|
+
return path19.join(providerDir, "fixtures");
|
|
19215
19527
|
}
|
|
19216
19528
|
function readCliFixture(ctx, type, name) {
|
|
19217
19529
|
const fixtureDir = getCliFixtureDir(ctx, type);
|
|
19218
|
-
const filePath =
|
|
19530
|
+
const filePath = path19.join(fixtureDir, `${name}.json`);
|
|
19219
19531
|
if (!fs12.existsSync(filePath)) {
|
|
19220
19532
|
throw new Error(`Fixture not found: ${filePath}`);
|
|
19221
19533
|
}
|
|
@@ -19982,7 +20294,7 @@ async function handleCliFixtureCapture(ctx, req, res) {
|
|
|
19982
20294
|
},
|
|
19983
20295
|
notes: typeof body?.notes === "string" ? body.notes : void 0
|
|
19984
20296
|
};
|
|
19985
|
-
const filePath =
|
|
20297
|
+
const filePath = path19.join(fixtureDir, `${name}.json`);
|
|
19986
20298
|
fs12.writeFileSync(filePath, JSON.stringify(fixture, null, 2));
|
|
19987
20299
|
ctx.json(res, 200, {
|
|
19988
20300
|
saved: true,
|
|
@@ -20006,7 +20318,7 @@ async function handleCliFixtureList(ctx, type, _req, res) {
|
|
|
20006
20318
|
return;
|
|
20007
20319
|
}
|
|
20008
20320
|
const fixtures = fs12.readdirSync(fixtureDir).filter((file) => file.endsWith(".json")).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" })).map((file) => {
|
|
20009
|
-
const fullPath =
|
|
20321
|
+
const fullPath = path19.join(fixtureDir, file);
|
|
20010
20322
|
try {
|
|
20011
20323
|
const raw = JSON.parse(fs12.readFileSync(fullPath, "utf-8"));
|
|
20012
20324
|
return {
|
|
@@ -20142,7 +20454,7 @@ async function handleCliRaw(ctx, req, res) {
|
|
|
20142
20454
|
|
|
20143
20455
|
// src/daemon/dev-auto-implement.ts
|
|
20144
20456
|
import * as fs13 from "fs";
|
|
20145
|
-
import * as
|
|
20457
|
+
import * as path20 from "path";
|
|
20146
20458
|
import * as os19 from "os";
|
|
20147
20459
|
function getAutoImplPid(ctx) {
|
|
20148
20460
|
const pid = ctx.autoImplProcess?.pid;
|
|
@@ -20199,22 +20511,22 @@ function getLatestScriptVersionDir(scriptsDir) {
|
|
|
20199
20511
|
if (!fs13.existsSync(scriptsDir)) return null;
|
|
20200
20512
|
const versions = fs13.readdirSync(scriptsDir).filter((d) => {
|
|
20201
20513
|
try {
|
|
20202
|
-
return fs13.statSync(
|
|
20514
|
+
return fs13.statSync(path20.join(scriptsDir, d)).isDirectory();
|
|
20203
20515
|
} catch {
|
|
20204
20516
|
return false;
|
|
20205
20517
|
}
|
|
20206
20518
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
20207
20519
|
if (versions.length === 0) return null;
|
|
20208
|
-
return
|
|
20520
|
+
return path20.join(scriptsDir, versions[0]);
|
|
20209
20521
|
}
|
|
20210
20522
|
function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
20211
|
-
const canonicalUserDir =
|
|
20212
|
-
const desiredDir = requestedDir ?
|
|
20213
|
-
const upstreamRoot =
|
|
20214
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
20523
|
+
const canonicalUserDir = path20.resolve(ctx.providerLoader.getUserProviderDir(category, type));
|
|
20524
|
+
const desiredDir = requestedDir ? path20.resolve(requestedDir) : canonicalUserDir;
|
|
20525
|
+
const upstreamRoot = path20.resolve(ctx.providerLoader.getUpstreamDir());
|
|
20526
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path20.sep}`)) {
|
|
20215
20527
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
20216
20528
|
}
|
|
20217
|
-
if (
|
|
20529
|
+
if (path20.basename(desiredDir) !== type) {
|
|
20218
20530
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
20219
20531
|
}
|
|
20220
20532
|
const sourceDir = ctx.findProviderDir(type);
|
|
@@ -20222,11 +20534,11 @@ function resolveAutoImplWritableProviderDir(ctx, category, type, requestedDir) {
|
|
|
20222
20534
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
20223
20535
|
}
|
|
20224
20536
|
if (!fs13.existsSync(desiredDir)) {
|
|
20225
|
-
fs13.mkdirSync(
|
|
20537
|
+
fs13.mkdirSync(path20.dirname(desiredDir), { recursive: true });
|
|
20226
20538
|
fs13.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
20227
20539
|
ctx.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
20228
20540
|
}
|
|
20229
|
-
const providerJson =
|
|
20541
|
+
const providerJson = path20.join(desiredDir, "provider.json");
|
|
20230
20542
|
if (!fs13.existsSync(providerJson)) {
|
|
20231
20543
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
20232
20544
|
}
|
|
@@ -20237,13 +20549,13 @@ function loadAutoImplReferenceScripts(ctx, referenceType) {
|
|
|
20237
20549
|
const refDir = ctx.findProviderDir(referenceType);
|
|
20238
20550
|
if (!refDir || !fs13.existsSync(refDir)) return {};
|
|
20239
20551
|
const referenceScripts = {};
|
|
20240
|
-
const scriptsDir =
|
|
20552
|
+
const scriptsDir = path20.join(refDir, "scripts");
|
|
20241
20553
|
const latestDir = getLatestScriptVersionDir(scriptsDir);
|
|
20242
20554
|
if (!latestDir) return referenceScripts;
|
|
20243
20555
|
for (const file of fs13.readdirSync(latestDir)) {
|
|
20244
20556
|
if (!file.endsWith(".js")) continue;
|
|
20245
20557
|
try {
|
|
20246
|
-
referenceScripts[file] = fs13.readFileSync(
|
|
20558
|
+
referenceScripts[file] = fs13.readFileSync(path20.join(latestDir, file), "utf-8");
|
|
20247
20559
|
} catch {
|
|
20248
20560
|
}
|
|
20249
20561
|
}
|
|
@@ -20351,9 +20663,9 @@ async function handleAutoImplement(ctx, type, req, res) {
|
|
|
20351
20663
|
});
|
|
20352
20664
|
const referenceScripts = loadAutoImplReferenceScripts(ctx, resolvedReference);
|
|
20353
20665
|
const prompt = buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domContext, referenceScripts, comment, resolvedReference, verification);
|
|
20354
|
-
const tmpDir =
|
|
20666
|
+
const tmpDir = path20.join(os19.tmpdir(), "adhdev-autoimpl");
|
|
20355
20667
|
if (!fs13.existsSync(tmpDir)) fs13.mkdirSync(tmpDir, { recursive: true });
|
|
20356
|
-
const promptFile =
|
|
20668
|
+
const promptFile = path20.join(tmpDir, `prompt-${type}-${Date.now()}.md`);
|
|
20357
20669
|
fs13.writeFileSync(promptFile, prompt, "utf-8");
|
|
20358
20670
|
ctx.log(`Auto-implement prompt written to ${promptFile} (${prompt.length} chars)`);
|
|
20359
20671
|
const agentProvider = ctx.providerLoader.resolve(agent) || ctx.providerLoader.getMeta(agent);
|
|
@@ -20790,7 +21102,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
20790
21102
|
setMode: "set_mode.js"
|
|
20791
21103
|
};
|
|
20792
21104
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
20793
|
-
const scriptsDir =
|
|
21105
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
20794
21106
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
20795
21107
|
if (latestScriptsDir) {
|
|
20796
21108
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -20801,7 +21113,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
20801
21113
|
for (const file of fs13.readdirSync(latestScriptsDir)) {
|
|
20802
21114
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
20803
21115
|
try {
|
|
20804
|
-
const content = fs13.readFileSync(
|
|
21116
|
+
const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
20805
21117
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
20806
21118
|
lines.push("```javascript");
|
|
20807
21119
|
lines.push(content);
|
|
@@ -20818,7 +21130,7 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
20818
21130
|
lines.push("");
|
|
20819
21131
|
for (const file of refFiles) {
|
|
20820
21132
|
try {
|
|
20821
|
-
const content = fs13.readFileSync(
|
|
21133
|
+
const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
20822
21134
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
20823
21135
|
lines.push("```javascript");
|
|
20824
21136
|
lines.push(content);
|
|
@@ -20859,10 +21171,10 @@ function buildAutoImplPrompt(ctx, type, provider, providerDir, functions, domCon
|
|
|
20859
21171
|
lines.push("");
|
|
20860
21172
|
}
|
|
20861
21173
|
}
|
|
20862
|
-
const docsDir =
|
|
21174
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
20863
21175
|
const loadGuide = (name) => {
|
|
20864
21176
|
try {
|
|
20865
|
-
const p =
|
|
21177
|
+
const p = path20.join(docsDir, name);
|
|
20866
21178
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
20867
21179
|
} catch {
|
|
20868
21180
|
}
|
|
@@ -21099,7 +21411,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
21099
21411
|
parseApproval: "parse_approval.js"
|
|
21100
21412
|
};
|
|
21101
21413
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
21102
|
-
const scriptsDir =
|
|
21414
|
+
const scriptsDir = path20.join(providerDir, "scripts");
|
|
21103
21415
|
const latestScriptsDir = getLatestScriptVersionDir(scriptsDir);
|
|
21104
21416
|
if (latestScriptsDir) {
|
|
21105
21417
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -21111,7 +21423,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
21111
21423
|
if (!file.endsWith(".js")) continue;
|
|
21112
21424
|
if (!targetFileNames.has(file)) continue;
|
|
21113
21425
|
try {
|
|
21114
|
-
const content = fs13.readFileSync(
|
|
21426
|
+
const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
21115
21427
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
21116
21428
|
lines.push("```javascript");
|
|
21117
21429
|
lines.push(content);
|
|
@@ -21127,7 +21439,7 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
21127
21439
|
lines.push("");
|
|
21128
21440
|
for (const file of refFiles) {
|
|
21129
21441
|
try {
|
|
21130
|
-
const content = fs13.readFileSync(
|
|
21442
|
+
const content = fs13.readFileSync(path20.join(latestScriptsDir, file), "utf-8");
|
|
21131
21443
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
21132
21444
|
lines.push("```javascript");
|
|
21133
21445
|
lines.push(content);
|
|
@@ -21160,10 +21472,10 @@ function buildCliAutoImplPrompt(ctx, type, provider, providerDir, functions, ref
|
|
|
21160
21472
|
lines.push("");
|
|
21161
21473
|
}
|
|
21162
21474
|
}
|
|
21163
|
-
const docsDir =
|
|
21475
|
+
const docsDir = path20.join(providerDir, "../../docs");
|
|
21164
21476
|
const loadGuide = (name) => {
|
|
21165
21477
|
try {
|
|
21166
|
-
const p =
|
|
21478
|
+
const p = path20.join(docsDir, name);
|
|
21167
21479
|
if (fs13.existsSync(p)) return fs13.readFileSync(p, "utf-8");
|
|
21168
21480
|
} catch {
|
|
21169
21481
|
}
|
|
@@ -21610,8 +21922,8 @@ var DevServer = class _DevServer {
|
|
|
21610
21922
|
}
|
|
21611
21923
|
getEndpointList() {
|
|
21612
21924
|
return this.routes.map((r) => {
|
|
21613
|
-
const
|
|
21614
|
-
return `${r.method.padEnd(5)} ${
|
|
21925
|
+
const path22 = typeof r.pattern === "string" ? r.pattern : r.pattern.source.replace(/\\\//g, "/").replace(/\(\[.*?\]\+\)/g, ":type").replace(/[\^$]/g, "");
|
|
21926
|
+
return `${r.method.padEnd(5)} ${path22}`;
|
|
21615
21927
|
});
|
|
21616
21928
|
}
|
|
21617
21929
|
async start(port = DEV_SERVER_PORT) {
|
|
@@ -21892,12 +22204,12 @@ var DevServer = class _DevServer {
|
|
|
21892
22204
|
// ─── DevConsole SPA ───
|
|
21893
22205
|
getConsoleDistDir() {
|
|
21894
22206
|
const candidates = [
|
|
21895
|
-
|
|
21896
|
-
|
|
21897
|
-
|
|
22207
|
+
path21.resolve(__dirname, "../../web-devconsole/dist"),
|
|
22208
|
+
path21.resolve(__dirname, "../../../web-devconsole/dist"),
|
|
22209
|
+
path21.join(process.cwd(), "packages/web-devconsole/dist")
|
|
21898
22210
|
];
|
|
21899
22211
|
for (const dir of candidates) {
|
|
21900
|
-
if (fs14.existsSync(
|
|
22212
|
+
if (fs14.existsSync(path21.join(dir, "index.html"))) return dir;
|
|
21901
22213
|
}
|
|
21902
22214
|
return null;
|
|
21903
22215
|
}
|
|
@@ -21907,7 +22219,7 @@ var DevServer = class _DevServer {
|
|
|
21907
22219
|
this.json(res, 500, { error: "DevConsole not found. Run: npm run build -w packages/web-devconsole" });
|
|
21908
22220
|
return;
|
|
21909
22221
|
}
|
|
21910
|
-
const htmlPath =
|
|
22222
|
+
const htmlPath = path21.join(distDir, "index.html");
|
|
21911
22223
|
try {
|
|
21912
22224
|
const html = fs14.readFileSync(htmlPath, "utf-8");
|
|
21913
22225
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
@@ -21932,15 +22244,15 @@ var DevServer = class _DevServer {
|
|
|
21932
22244
|
this.json(res, 404, { error: "Not found" });
|
|
21933
22245
|
return;
|
|
21934
22246
|
}
|
|
21935
|
-
const safePath =
|
|
21936
|
-
const filePath =
|
|
22247
|
+
const safePath = path21.normalize(pathname).replace(/^\.\.\//, "");
|
|
22248
|
+
const filePath = path21.join(distDir, safePath);
|
|
21937
22249
|
if (!filePath.startsWith(distDir)) {
|
|
21938
22250
|
this.json(res, 403, { error: "Forbidden" });
|
|
21939
22251
|
return;
|
|
21940
22252
|
}
|
|
21941
22253
|
try {
|
|
21942
22254
|
const content = fs14.readFileSync(filePath);
|
|
21943
|
-
const ext =
|
|
22255
|
+
const ext = path21.extname(filePath);
|
|
21944
22256
|
const contentType = _DevServer.MIME_MAP[ext] || "application/octet-stream";
|
|
21945
22257
|
res.writeHead(200, { "Content-Type": contentType, "Cache-Control": "public, max-age=31536000, immutable" });
|
|
21946
22258
|
res.end(content);
|
|
@@ -22053,9 +22365,9 @@ var DevServer = class _DevServer {
|
|
|
22053
22365
|
const rel = prefix ? `${prefix}/${entry.name}` : entry.name;
|
|
22054
22366
|
if (entry.isDirectory()) {
|
|
22055
22367
|
files.push({ path: rel, size: 0, type: "dir" });
|
|
22056
|
-
scan(
|
|
22368
|
+
scan(path21.join(d, entry.name), rel);
|
|
22057
22369
|
} else {
|
|
22058
|
-
const stat = fs14.statSync(
|
|
22370
|
+
const stat = fs14.statSync(path21.join(d, entry.name));
|
|
22059
22371
|
files.push({ path: rel, size: stat.size, type: "file" });
|
|
22060
22372
|
}
|
|
22061
22373
|
}
|
|
@@ -22078,7 +22390,7 @@ var DevServer = class _DevServer {
|
|
|
22078
22390
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
22079
22391
|
return;
|
|
22080
22392
|
}
|
|
22081
|
-
const fullPath =
|
|
22393
|
+
const fullPath = path21.resolve(dir, path21.normalize(filePath));
|
|
22082
22394
|
if (!fullPath.startsWith(dir)) {
|
|
22083
22395
|
this.json(res, 403, { error: "Forbidden" });
|
|
22084
22396
|
return;
|
|
@@ -22103,14 +22415,14 @@ var DevServer = class _DevServer {
|
|
|
22103
22415
|
this.json(res, 404, { error: `Provider directory not found: ${type}` });
|
|
22104
22416
|
return;
|
|
22105
22417
|
}
|
|
22106
|
-
const fullPath =
|
|
22418
|
+
const fullPath = path21.resolve(dir, path21.normalize(filePath));
|
|
22107
22419
|
if (!fullPath.startsWith(dir)) {
|
|
22108
22420
|
this.json(res, 403, { error: "Forbidden" });
|
|
22109
22421
|
return;
|
|
22110
22422
|
}
|
|
22111
22423
|
try {
|
|
22112
22424
|
if (fs14.existsSync(fullPath)) fs14.copyFileSync(fullPath, fullPath + ".bak");
|
|
22113
|
-
fs14.mkdirSync(
|
|
22425
|
+
fs14.mkdirSync(path21.dirname(fullPath), { recursive: true });
|
|
22114
22426
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
22115
22427
|
this.log(`File saved: ${fullPath} (${content.length} chars)`);
|
|
22116
22428
|
this.providerLoader.reload();
|
|
@@ -22127,7 +22439,7 @@ var DevServer = class _DevServer {
|
|
|
22127
22439
|
return;
|
|
22128
22440
|
}
|
|
22129
22441
|
for (const name of ["scripts.js", "provider.json"]) {
|
|
22130
|
-
const p =
|
|
22442
|
+
const p = path21.join(dir, name);
|
|
22131
22443
|
if (fs14.existsSync(p)) {
|
|
22132
22444
|
const source = fs14.readFileSync(p, "utf-8");
|
|
22133
22445
|
this.json(res, 200, { type, path: p, source, lines: source.split("\n").length });
|
|
@@ -22148,8 +22460,8 @@ var DevServer = class _DevServer {
|
|
|
22148
22460
|
this.json(res, 404, { error: `Provider not found: ${type}` });
|
|
22149
22461
|
return;
|
|
22150
22462
|
}
|
|
22151
|
-
const target = fs14.existsSync(
|
|
22152
|
-
const targetPath =
|
|
22463
|
+
const target = fs14.existsSync(path21.join(dir, "scripts.js")) ? "scripts.js" : "provider.json";
|
|
22464
|
+
const targetPath = path21.join(dir, target);
|
|
22153
22465
|
try {
|
|
22154
22466
|
if (fs14.existsSync(targetPath)) fs14.copyFileSync(targetPath, targetPath + ".bak");
|
|
22155
22467
|
fs14.writeFileSync(targetPath, source, "utf-8");
|
|
@@ -22296,7 +22608,7 @@ var DevServer = class _DevServer {
|
|
|
22296
22608
|
}
|
|
22297
22609
|
let targetDir;
|
|
22298
22610
|
targetDir = this.providerLoader.getUserProviderDir(category, type);
|
|
22299
|
-
const jsonPath =
|
|
22611
|
+
const jsonPath = path21.join(targetDir, "provider.json");
|
|
22300
22612
|
if (fs14.existsSync(jsonPath)) {
|
|
22301
22613
|
this.json(res, 409, { error: `Provider already exists at ${targetDir}`, path: targetDir });
|
|
22302
22614
|
return;
|
|
@@ -22308,8 +22620,8 @@ var DevServer = class _DevServer {
|
|
|
22308
22620
|
const createdFiles = ["provider.json"];
|
|
22309
22621
|
if (result.files) {
|
|
22310
22622
|
for (const [relPath, content] of Object.entries(result.files)) {
|
|
22311
|
-
const fullPath =
|
|
22312
|
-
fs14.mkdirSync(
|
|
22623
|
+
const fullPath = path21.join(targetDir, relPath);
|
|
22624
|
+
fs14.mkdirSync(path21.dirname(fullPath), { recursive: true });
|
|
22313
22625
|
fs14.writeFileSync(fullPath, content, "utf-8");
|
|
22314
22626
|
createdFiles.push(relPath);
|
|
22315
22627
|
}
|
|
@@ -22362,22 +22674,22 @@ var DevServer = class _DevServer {
|
|
|
22362
22674
|
if (!fs14.existsSync(scriptsDir)) return null;
|
|
22363
22675
|
const versions = fs14.readdirSync(scriptsDir).filter((d) => {
|
|
22364
22676
|
try {
|
|
22365
|
-
return fs14.statSync(
|
|
22677
|
+
return fs14.statSync(path21.join(scriptsDir, d)).isDirectory();
|
|
22366
22678
|
} catch {
|
|
22367
22679
|
return false;
|
|
22368
22680
|
}
|
|
22369
22681
|
}).sort((a, b) => b.localeCompare(a, void 0, { numeric: true, sensitivity: "base" }));
|
|
22370
22682
|
if (versions.length === 0) return null;
|
|
22371
|
-
return
|
|
22683
|
+
return path21.join(scriptsDir, versions[0]);
|
|
22372
22684
|
}
|
|
22373
22685
|
resolveAutoImplWritableProviderDir(category, type, requestedDir) {
|
|
22374
|
-
const canonicalUserDir =
|
|
22375
|
-
const desiredDir = requestedDir ?
|
|
22376
|
-
const upstreamRoot =
|
|
22377
|
-
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${
|
|
22686
|
+
const canonicalUserDir = path21.resolve(this.providerLoader.getUserProviderDir(category, type));
|
|
22687
|
+
const desiredDir = requestedDir ? path21.resolve(requestedDir) : canonicalUserDir;
|
|
22688
|
+
const upstreamRoot = path21.resolve(this.providerLoader.getUpstreamDir());
|
|
22689
|
+
if (desiredDir === upstreamRoot || desiredDir.startsWith(`${upstreamRoot}${path21.sep}`)) {
|
|
22378
22690
|
return { dir: null, reason: `Refusing to write into upstream provider directory: ${desiredDir}` };
|
|
22379
22691
|
}
|
|
22380
|
-
if (
|
|
22692
|
+
if (path21.basename(desiredDir) !== type) {
|
|
22381
22693
|
return { dir: null, reason: `Requested writable provider directory must end with '${type}': ${desiredDir}` };
|
|
22382
22694
|
}
|
|
22383
22695
|
const sourceDir = this.findProviderDir(type);
|
|
@@ -22385,11 +22697,11 @@ var DevServer = class _DevServer {
|
|
|
22385
22697
|
return { dir: null, reason: `Provider source directory not found for '${type}'` };
|
|
22386
22698
|
}
|
|
22387
22699
|
if (!fs14.existsSync(desiredDir)) {
|
|
22388
|
-
fs14.mkdirSync(
|
|
22700
|
+
fs14.mkdirSync(path21.dirname(desiredDir), { recursive: true });
|
|
22389
22701
|
fs14.cpSync(sourceDir, desiredDir, { recursive: true });
|
|
22390
22702
|
this.log(`Auto-implement writable copy created: ${desiredDir}`);
|
|
22391
22703
|
}
|
|
22392
|
-
const providerJson =
|
|
22704
|
+
const providerJson = path21.join(desiredDir, "provider.json");
|
|
22393
22705
|
if (!fs14.existsSync(providerJson)) {
|
|
22394
22706
|
return { dir: null, reason: `provider.json not found in writable provider directory: ${desiredDir}` };
|
|
22395
22707
|
}
|
|
@@ -22425,7 +22737,7 @@ var DevServer = class _DevServer {
|
|
|
22425
22737
|
setMode: "set_mode.js"
|
|
22426
22738
|
};
|
|
22427
22739
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
22428
|
-
const scriptsDir =
|
|
22740
|
+
const scriptsDir = path21.join(providerDir, "scripts");
|
|
22429
22741
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
22430
22742
|
if (latestScriptsDir) {
|
|
22431
22743
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -22436,7 +22748,7 @@ var DevServer = class _DevServer {
|
|
|
22436
22748
|
for (const file of fs14.readdirSync(latestScriptsDir)) {
|
|
22437
22749
|
if (file.endsWith(".js") && targetFileNames.has(file)) {
|
|
22438
22750
|
try {
|
|
22439
|
-
const content = fs14.readFileSync(
|
|
22751
|
+
const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
|
|
22440
22752
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
22441
22753
|
lines.push("```javascript");
|
|
22442
22754
|
lines.push(content);
|
|
@@ -22453,7 +22765,7 @@ var DevServer = class _DevServer {
|
|
|
22453
22765
|
lines.push("");
|
|
22454
22766
|
for (const file of refFiles) {
|
|
22455
22767
|
try {
|
|
22456
|
-
const content = fs14.readFileSync(
|
|
22768
|
+
const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
|
|
22457
22769
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
22458
22770
|
lines.push("```javascript");
|
|
22459
22771
|
lines.push(content);
|
|
@@ -22494,10 +22806,10 @@ var DevServer = class _DevServer {
|
|
|
22494
22806
|
lines.push("");
|
|
22495
22807
|
}
|
|
22496
22808
|
}
|
|
22497
|
-
const docsDir =
|
|
22809
|
+
const docsDir = path21.join(providerDir, "../../docs");
|
|
22498
22810
|
const loadGuide = (name) => {
|
|
22499
22811
|
try {
|
|
22500
|
-
const p =
|
|
22812
|
+
const p = path21.join(docsDir, name);
|
|
22501
22813
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
22502
22814
|
} catch {
|
|
22503
22815
|
}
|
|
@@ -22671,7 +22983,7 @@ var DevServer = class _DevServer {
|
|
|
22671
22983
|
parseApproval: "parse_approval.js"
|
|
22672
22984
|
};
|
|
22673
22985
|
const targetFileNames = new Set(functions.map((fn) => funcToFile[fn]).filter(Boolean));
|
|
22674
|
-
const scriptsDir =
|
|
22986
|
+
const scriptsDir = path21.join(providerDir, "scripts");
|
|
22675
22987
|
const latestScriptsDir = this.getLatestScriptVersionDir(scriptsDir);
|
|
22676
22988
|
if (latestScriptsDir) {
|
|
22677
22989
|
lines.push(`Scripts version directory: \`${latestScriptsDir}\``);
|
|
@@ -22683,7 +22995,7 @@ var DevServer = class _DevServer {
|
|
|
22683
22995
|
if (!file.endsWith(".js")) continue;
|
|
22684
22996
|
if (!targetFileNames.has(file)) continue;
|
|
22685
22997
|
try {
|
|
22686
|
-
const content = fs14.readFileSync(
|
|
22998
|
+
const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
|
|
22687
22999
|
lines.push(`### \`${file}\` \u270F\uFE0F EDIT`);
|
|
22688
23000
|
lines.push("```javascript");
|
|
22689
23001
|
lines.push(content);
|
|
@@ -22699,7 +23011,7 @@ var DevServer = class _DevServer {
|
|
|
22699
23011
|
lines.push("");
|
|
22700
23012
|
for (const file of refFiles) {
|
|
22701
23013
|
try {
|
|
22702
|
-
const content = fs14.readFileSync(
|
|
23014
|
+
const content = fs14.readFileSync(path21.join(latestScriptsDir, file), "utf-8");
|
|
22703
23015
|
lines.push(`### \`${file}\` \u{1F512}`);
|
|
22704
23016
|
lines.push("```javascript");
|
|
22705
23017
|
lines.push(content);
|
|
@@ -22732,10 +23044,10 @@ var DevServer = class _DevServer {
|
|
|
22732
23044
|
lines.push("");
|
|
22733
23045
|
}
|
|
22734
23046
|
}
|
|
22735
|
-
const docsDir =
|
|
23047
|
+
const docsDir = path21.join(providerDir, "../../docs");
|
|
22736
23048
|
const loadGuide = (name) => {
|
|
22737
23049
|
try {
|
|
22738
|
-
const p =
|
|
23050
|
+
const p = path21.join(docsDir, name);
|
|
22739
23051
|
if (fs14.existsSync(p)) return fs14.readFileSync(p, "utf-8");
|
|
22740
23052
|
} catch {
|
|
22741
23053
|
}
|