@eclipse-docks/extension-ai-system 0.8.0 → 0.8.1
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/README.md +2 -2
- package/dist/api.js +1 -1
- package/dist/{cognitive-extension-CG_d39K5.js → cognitive-extension-7_ZMUCGD.js} +358 -92
- package/dist/cognitive-extension-7_ZMUCGD.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/runtime/abort.d.ts +5 -0
- package/dist/runtime/abort.d.ts.map +1 -0
- package/dist/runtime/attachment-paths.d.ts +17 -0
- package/dist/runtime/attachment-paths.d.ts.map +1 -0
- package/dist/runtime/attachments.d.ts +5 -5
- package/dist/runtime/attachments.d.ts.map +1 -1
- package/dist/runtime/cognitive-runtime.d.ts +7 -3
- package/dist/runtime/cognitive-runtime.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +2 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/models/openai-compatible.d.ts.map +1 -1
- package/dist/runtime/session-workspace.d.ts +20 -0
- package/dist/runtime/session-workspace.d.ts.map +1 -0
- package/dist/runtime/specialists/index.d.ts.map +1 -1
- package/dist/runtime/specialists/loop.d.ts.map +1 -1
- package/dist/runtime/tools/command-adapter.d.ts.map +1 -1
- package/dist/runtime/tools/index.d.ts +0 -1
- package/dist/runtime/tools/index.d.ts.map +1 -1
- package/dist/runtime/tools/workspace-adapter.d.ts +1 -1
- package/dist/runtime/tools/workspace-adapter.d.ts.map +1 -1
- package/dist/runtime/tools/workspace-path-qualify.d.ts +22 -0
- package/dist/runtime/tools/workspace-path-qualify.d.ts.map +1 -0
- package/dist/runtime/tools/workspace-path.d.ts +17 -0
- package/dist/runtime/tools/workspace-path.d.ts.map +1 -0
- package/dist/{runtime-DfNGzEjU.js → runtime-By5PP2BC.js} +696 -384
- package/dist/runtime-By5PP2BC.js.map +1 -0
- package/dist/view/busy-status.d.ts +12 -0
- package/dist/view/busy-status.d.ts.map +1 -0
- package/dist/view/cognitive-settings-editor.d.ts +0 -1
- package/dist/view/cognitive-settings-editor.d.ts.map +1 -1
- package/dist/view/cognitive-view.d.ts +21 -0
- package/dist/view/cognitive-view.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/cognitive-extension-CG_d39K5.js.map +0 -1
- package/dist/runtime/tools/attachment-adapter.d.ts +0 -6
- package/dist/runtime/tools/attachment-adapter.d.ts.map +0 -1
- package/dist/runtime-DfNGzEjU.js.map +0 -1
|
@@ -1,20 +1,69 @@
|
|
|
1
|
-
import { _ as AI_SETTINGS_KEY, a as formatContextPercent, b as TOPIC, c as readPromptAttachmentFromFile, d as defaultProvidersSettings, g as AI_SETTINGS_EDITOR_ID, i as formatBucketDetail, m as detectEffortCapability, n as cognitiveRuntime, o as formatTokenCount, p as parseModelIds, r as estimateSessionContextUsage, s as ATTACHMENT_FILE_ACCEPT, u as fetchOpenAICompatibleModels, v as AI_VIEW_NAME, y as OPEN_AI_SETTINGS_COMMAND } from "./runtime-
|
|
1
|
+
import { _ as AI_SETTINGS_KEY, a as formatContextPercent, b as TOPIC, c as readPromptAttachmentFromFile, d as defaultProvidersSettings, g as AI_SETTINGS_EDITOR_ID, i as formatBucketDetail, m as detectEffortCapability, n as cognitiveRuntime, o as formatTokenCount, p as parseModelIds, r as estimateSessionContextUsage, s as ATTACHMENT_FILE_ACCEPT, u as fetchOpenAICompatibleModels, v as AI_VIEW_NAME, y as OPEN_AI_SETTINGS_COMMAND } from "./runtime-By5PP2BC.js";
|
|
2
2
|
import { DocksPart, SIDEBAR_AUXILIARY, confirmDialog, contributionRegistry, editorRegistry, registerAll, rootContext, toastError, toastInfo } from "@eclipse-docks/core";
|
|
3
3
|
import { css, customElement, html, nothing, property, query, state } from "@eclipse-docks/core/externals/lit";
|
|
4
4
|
import "@eclipse-docks/core/externals/webawesome";
|
|
5
5
|
import _decorate from "@oxc-project/runtime/helpers/decorate";
|
|
6
|
+
//#region src/view/busy-status.ts
|
|
7
|
+
/** Shown immediately when waiting on a model turn. */
|
|
8
|
+
var INITIAL_BUSY_STATUS = "Thinking…";
|
|
9
|
+
/**
|
|
10
|
+
* Rotating wait copy (Cursor / Copilot style). Picked at random after the initial message.
|
|
11
|
+
* Keep these light and short — they appear in the composer while busy.
|
|
12
|
+
*/
|
|
13
|
+
var BUSY_STATUS_MESSAGES = [
|
|
14
|
+
"Bribing the hamster…",
|
|
15
|
+
"Consulting the rubber duck…",
|
|
16
|
+
"Untangling the spaghetti…",
|
|
17
|
+
"Herding tokens…",
|
|
18
|
+
"Warming up the crystals…",
|
|
19
|
+
"Counting electric sheep…",
|
|
20
|
+
"Negotiating with the compiler…",
|
|
21
|
+
"Teaching frogs to code…",
|
|
22
|
+
"Aligning the bits…",
|
|
23
|
+
"Feeding the GPU snacks…",
|
|
24
|
+
"Looking under the couch…",
|
|
25
|
+
"Summoning a specialist…",
|
|
26
|
+
"Checking the manual twice…",
|
|
27
|
+
"Reticulating splines…",
|
|
28
|
+
"Sharpening pencils…",
|
|
29
|
+
"Pedaling harder…",
|
|
30
|
+
"Buffering brilliance…",
|
|
31
|
+
"Reversing the polarity…",
|
|
32
|
+
"Convincing the bits to cooperate…",
|
|
33
|
+
"Dusting off the playbook…",
|
|
34
|
+
"Whispering to the model…",
|
|
35
|
+
"Calibrating optimism…",
|
|
36
|
+
"Unfolding the roadmap…",
|
|
37
|
+
"Polishing ones and zeros…",
|
|
38
|
+
"Asking politely…"
|
|
39
|
+
];
|
|
40
|
+
var ROTATE_MS_MIN = 3e3;
|
|
41
|
+
/** Random delay until the next busy-status line (3–12s). */
|
|
42
|
+
function busyStatusRotateMs() {
|
|
43
|
+
return ROTATE_MS_MIN + Math.floor(Math.random() * 9001);
|
|
44
|
+
}
|
|
45
|
+
/** Next status, avoiding an immediate repeat of `current`. */
|
|
46
|
+
function nextBusyStatus(current) {
|
|
47
|
+
const pool = BUSY_STATUS_MESSAGES.filter((m) => m !== current);
|
|
48
|
+
if (!pool.length) return INITIAL_BUSY_STATUS;
|
|
49
|
+
return pool[Math.floor(Math.random() * pool.length)];
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
6
52
|
//#region src/view/cognitive-view.ts
|
|
7
53
|
var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
8
54
|
constructor(..._args) {
|
|
9
55
|
super(..._args);
|
|
10
56
|
this.scrollMode = "none";
|
|
57
|
+
this.composerPasteBound = false;
|
|
11
58
|
this.sessions = [];
|
|
12
59
|
this.focusedId = null;
|
|
13
60
|
this.draft = "";
|
|
14
61
|
this.pendingAttachmentIds = [];
|
|
15
62
|
this.dragOver = false;
|
|
16
63
|
this.previewAttachmentId = null;
|
|
64
|
+
this.toolDetail = null;
|
|
17
65
|
this.busy = false;
|
|
66
|
+
this.busyStatus = INITIAL_BUSY_STATUS;
|
|
18
67
|
this.pendingPermission = null;
|
|
19
68
|
this.policyMode = "auto";
|
|
20
69
|
this.optimizeFor = "balance";
|
|
@@ -26,6 +75,13 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
26
75
|
this.historyOpen = false;
|
|
27
76
|
this.historyQuery = "";
|
|
28
77
|
this.unsubs = [];
|
|
78
|
+
this.promptController = null;
|
|
79
|
+
this.nativePasteHandler = (e) => void this.onComposerPaste(e);
|
|
80
|
+
this.cancelKeyHandler = (e) => {
|
|
81
|
+
if (!this.busy || e.key !== "Escape") return;
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
this.cancelTurn();
|
|
84
|
+
};
|
|
29
85
|
}
|
|
30
86
|
static {
|
|
31
87
|
this.styles = css`
|
|
@@ -490,8 +546,44 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
490
546
|
color: var(--wa-color-text-quiet);
|
|
491
547
|
margin-bottom: var(--wa-space-2xs);
|
|
492
548
|
}
|
|
549
|
+
|
|
550
|
+
.tool-row {
|
|
551
|
+
display: flex;
|
|
552
|
+
align-items: center;
|
|
553
|
+
gap: var(--wa-space-2xs);
|
|
554
|
+
flex-wrap: wrap;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
.tool-row .tool-heading {
|
|
558
|
+
margin-bottom: 0;
|
|
559
|
+
flex: 1;
|
|
560
|
+
min-width: 0;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
.tool-detail-body {
|
|
564
|
+
max-height: min(70vh, 36rem);
|
|
565
|
+
overflow: auto;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
.tool-detail-body pre {
|
|
569
|
+
margin: 0;
|
|
570
|
+
font-family: var(--wa-font-family-code, var(--wa-font-mono));
|
|
571
|
+
font-size: var(--wa-font-size-xs);
|
|
572
|
+
white-space: pre-wrap;
|
|
573
|
+
word-break: break-word;
|
|
574
|
+
}
|
|
493
575
|
`;
|
|
494
576
|
}
|
|
577
|
+
updated() {
|
|
578
|
+
this.bindComposerPaste();
|
|
579
|
+
}
|
|
580
|
+
bindComposerPaste() {
|
|
581
|
+
if (this.composerPasteBound) return;
|
|
582
|
+
const native = this.textarea?.shadowRoot?.querySelector("textarea");
|
|
583
|
+
if (!native) return;
|
|
584
|
+
native.addEventListener("paste", this.nativePasteHandler);
|
|
585
|
+
this.composerPasteBound = true;
|
|
586
|
+
}
|
|
495
587
|
doBeforeUI() {
|
|
496
588
|
cognitiveRuntime.start();
|
|
497
589
|
this.syncSessions();
|
|
@@ -499,14 +591,13 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
499
591
|
this.approvalMode = cognitiveRuntime.getApprovalMode();
|
|
500
592
|
cognitiveRuntime.whenReady().then(() => {
|
|
501
593
|
this.syncSessions();
|
|
502
|
-
this.
|
|
503
|
-
this.approvalMode = cognitiveRuntime.getApprovalMode();
|
|
594
|
+
this.restoreRoutingFromRuntime();
|
|
504
595
|
this.scheduleScrollToBottom();
|
|
505
596
|
});
|
|
506
597
|
this.unsubs.push(cognitiveRuntime.events.subscribe(TOPIC.sessionChanged, () => {
|
|
507
598
|
this.syncSessions();
|
|
508
599
|
this.scheduleScrollToBottom();
|
|
509
|
-
}), cognitiveRuntime.events.subscribe(TOPIC.providersChanged, () => this.
|
|
600
|
+
}), cognitiveRuntime.events.subscribe(TOPIC.providersChanged, () => this.onProvidersChanged()), cognitiveRuntime.events.subscribe(TOPIC.approvalModeChanged, (mode) => {
|
|
510
601
|
this.approvalMode = mode;
|
|
511
602
|
}), cognitiveRuntime.events.subscribe(TOPIC.permissionAsked, (payload) => {
|
|
512
603
|
this.pendingPermission = payload;
|
|
@@ -525,9 +616,33 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
525
616
|
doClose() {
|
|
526
617
|
if (this.scrollDebounceTimer) clearTimeout(this.scrollDebounceTimer);
|
|
527
618
|
this.scrollDebounceTimer = void 0;
|
|
619
|
+
this.cancelTurn();
|
|
620
|
+
this.stopBusyStatus();
|
|
621
|
+
(this.textarea?.shadowRoot?.querySelector("textarea"))?.removeEventListener("paste", this.nativePasteHandler);
|
|
622
|
+
this.composerPasteBound = false;
|
|
528
623
|
for (const u of this.unsubs) u();
|
|
529
624
|
this.unsubs = [];
|
|
530
625
|
}
|
|
626
|
+
startBusyStatus() {
|
|
627
|
+
this.stopBusyStatus();
|
|
628
|
+
this.busyStatus = INITIAL_BUSY_STATUS;
|
|
629
|
+
this.setComposerText(this.busyStatus);
|
|
630
|
+
window.addEventListener("keydown", this.cancelKeyHandler);
|
|
631
|
+
const schedule = () => {
|
|
632
|
+
this.busyStatusTimer = setTimeout(() => {
|
|
633
|
+
this.busyStatus = nextBusyStatus(this.busyStatus);
|
|
634
|
+
this.setComposerText(this.busyStatus);
|
|
635
|
+
schedule();
|
|
636
|
+
}, busyStatusRotateMs());
|
|
637
|
+
};
|
|
638
|
+
schedule();
|
|
639
|
+
}
|
|
640
|
+
stopBusyStatus() {
|
|
641
|
+
if (this.busyStatusTimer) clearTimeout(this.busyStatusTimer);
|
|
642
|
+
this.busyStatusTimer = void 0;
|
|
643
|
+
this.busyStatus = INITIAL_BUSY_STATUS;
|
|
644
|
+
window.removeEventListener("keydown", this.cancelKeyHandler);
|
|
645
|
+
}
|
|
531
646
|
syncSessions() {
|
|
532
647
|
const byRecency = cognitiveRuntime.sessions.list();
|
|
533
648
|
this.sessions = [...byRecency].sort((a, b) => a.createdAt - b.createdAt);
|
|
@@ -558,11 +673,10 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
558
673
|
deleteSession(sessionId) {
|
|
559
674
|
if (this.sessions.length <= 1) {
|
|
560
675
|
cognitiveRuntime.sessions.createSession({ title: "Chat" });
|
|
561
|
-
cognitiveRuntime.
|
|
562
|
-
} else cognitiveRuntime.
|
|
676
|
+
cognitiveRuntime.removeSession(sessionId);
|
|
677
|
+
} else cognitiveRuntime.removeSession(sessionId);
|
|
563
678
|
this.streamingParts = [];
|
|
564
679
|
this.syncSessions();
|
|
565
|
-
cognitiveRuntime.commitSessions();
|
|
566
680
|
}
|
|
567
681
|
openSession(sessionId) {
|
|
568
682
|
if (!cognitiveRuntime.sessions.focus(sessionId)) return;
|
|
@@ -598,6 +712,31 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
598
712
|
this.modelIds = cognitiveRuntime.listConfiguredModels();
|
|
599
713
|
if (!this.manualModel || !this.modelIds.includes(this.manualModel)) this.manualModel = this.modelIds[0] ?? cognitiveRuntime.defaultModelId();
|
|
600
714
|
}
|
|
715
|
+
/** Mirror persisted runtime policy into the gear menu after hydrate. */
|
|
716
|
+
restoreRoutingFromRuntime() {
|
|
717
|
+
this.syncModels();
|
|
718
|
+
const policy = cognitiveRuntime.getModelPolicy();
|
|
719
|
+
if (policy.mode === "auto") {
|
|
720
|
+
this.policyMode = "auto";
|
|
721
|
+
this.optimizeFor = policy.optimizeFor;
|
|
722
|
+
} else {
|
|
723
|
+
this.policyMode = "manual";
|
|
724
|
+
this.manualModel = policy.model;
|
|
725
|
+
this.manualEffort = policy.effort ?? "auto";
|
|
726
|
+
if (!this.manualModel || !this.modelIds.includes(this.manualModel)) {
|
|
727
|
+
this.manualModel = this.modelIds[0] ?? cognitiveRuntime.defaultModelId();
|
|
728
|
+
this.applyPolicy();
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
this.approvalMode = cognitiveRuntime.getApprovalMode();
|
|
732
|
+
}
|
|
733
|
+
onProvidersChanged() {
|
|
734
|
+
this.syncModels();
|
|
735
|
+
if (this.policyMode !== "manual") return;
|
|
736
|
+
if (this.manualModel && this.modelIds.includes(this.manualModel)) return;
|
|
737
|
+
this.manualModel = this.modelIds[0] ?? cognitiveRuntime.defaultModelId();
|
|
738
|
+
this.applyPolicy();
|
|
739
|
+
}
|
|
601
740
|
effortChoices() {
|
|
602
741
|
const cap = detectEffortCapability(this.manualModel || cognitiveRuntime.defaultModelId());
|
|
603
742
|
if (!cap.supported) return ["auto", "none"];
|
|
@@ -631,6 +770,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
631
770
|
if (optimize === "cost" || optimize === "balance" || optimize === "intelligence") {
|
|
632
771
|
this.policyMode = "auto";
|
|
633
772
|
this.optimizeFor = optimize;
|
|
773
|
+
this.applyPolicy();
|
|
634
774
|
}
|
|
635
775
|
return;
|
|
636
776
|
}
|
|
@@ -639,6 +779,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
639
779
|
if (!model) return;
|
|
640
780
|
this.policyMode = "manual";
|
|
641
781
|
this.manualModel = model;
|
|
782
|
+
this.applyPolicy();
|
|
642
783
|
}
|
|
643
784
|
}
|
|
644
785
|
applyPolicy() {
|
|
@@ -652,12 +793,15 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
652
793
|
};
|
|
653
794
|
cognitiveRuntime.setModelPolicy(policy);
|
|
654
795
|
}
|
|
796
|
+
async setComposerText(value) {
|
|
797
|
+
this.draft = value;
|
|
798
|
+
await this.updateComplete;
|
|
799
|
+
if (this.textarea) this.textarea.value = value;
|
|
800
|
+
}
|
|
655
801
|
async clearComposer() {
|
|
656
|
-
this.draft = "";
|
|
657
802
|
this.pendingAttachmentIds = [];
|
|
658
|
-
await this.updateComplete;
|
|
659
|
-
if (this.textarea) this.textarea.value = "";
|
|
660
803
|
if (this.fileInput) this.fileInput.value = "";
|
|
804
|
+
await this.setComposerText("");
|
|
661
805
|
}
|
|
662
806
|
sessionAttachments() {
|
|
663
807
|
return this.focusedSession()?.attachments ?? [];
|
|
@@ -699,7 +843,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
699
843
|
}
|
|
700
844
|
accepted.push(result.attachment);
|
|
701
845
|
}
|
|
702
|
-
const stored = cognitiveRuntime.addAttachments(sessionId, accepted);
|
|
846
|
+
const stored = await cognitiveRuntime.addAttachments(sessionId, accepted);
|
|
703
847
|
if (stored.length) this.pendingAttachmentIds = [...this.pendingAttachmentIds, ...stored.map((a) => a.id).filter((id) => !this.pendingAttachmentIds.includes(id))];
|
|
704
848
|
this.syncSessions();
|
|
705
849
|
}
|
|
@@ -724,22 +868,47 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
724
868
|
this.dragOver = false;
|
|
725
869
|
if (e.dataTransfer?.files?.length) await this.addFiles(e.dataTransfer.files);
|
|
726
870
|
}
|
|
871
|
+
/** Attach clipboard files/images (e.g. Ctrl+V screenshot) when focused in the prompt. */
|
|
872
|
+
async onComposerPaste(e) {
|
|
873
|
+
if (this.busy) {
|
|
874
|
+
e.preventDefault();
|
|
875
|
+
return;
|
|
876
|
+
}
|
|
877
|
+
const files = filesFromClipboard(e.clipboardData);
|
|
878
|
+
if (!files.length) return;
|
|
879
|
+
e.preventDefault();
|
|
880
|
+
await this.addFiles(files);
|
|
881
|
+
}
|
|
882
|
+
cancelTurn() {
|
|
883
|
+
if (!this.busy && !this.promptController) return;
|
|
884
|
+
this.promptController?.abort();
|
|
885
|
+
if (this.pendingPermission) this.resolvePermission("deny");
|
|
886
|
+
}
|
|
727
887
|
async send() {
|
|
728
888
|
const text = this.draft.trim();
|
|
729
889
|
const attachmentIds = [...this.pendingAttachmentIds];
|
|
730
890
|
if (!text && !attachmentIds.length || this.busy) return;
|
|
731
891
|
this.applyPolicy();
|
|
732
|
-
|
|
892
|
+
this.pendingAttachmentIds = [];
|
|
893
|
+
if (this.fileInput) this.fileInput.value = "";
|
|
894
|
+
const controller = new AbortController();
|
|
895
|
+
this.promptController = controller;
|
|
733
896
|
this.busy = true;
|
|
734
897
|
this.streamingParts = [];
|
|
898
|
+
this.startBusyStatus();
|
|
735
899
|
try {
|
|
736
900
|
await cognitiveRuntime.prompt({
|
|
737
901
|
sessionId: this.focusedId ?? void 0,
|
|
738
902
|
text,
|
|
739
|
-
attachmentIds
|
|
903
|
+
attachmentIds,
|
|
904
|
+
signal: controller.signal
|
|
740
905
|
});
|
|
741
906
|
} finally {
|
|
907
|
+
if (this.promptController === controller) this.promptController = null;
|
|
908
|
+
this.stopBusyStatus();
|
|
742
909
|
this.busy = false;
|
|
910
|
+
this.streamingParts = [];
|
|
911
|
+
await this.clearComposer();
|
|
743
912
|
this.syncSessions();
|
|
744
913
|
this.scheduleScrollToBottom();
|
|
745
914
|
this.textarea?.focus();
|
|
@@ -839,6 +1008,38 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
839
1008
|
<wa-button variant="brand" @click=${() => this.closeAttachmentPreview()}>Close</wa-button>
|
|
840
1009
|
</div>
|
|
841
1010
|
</wa-dialog>
|
|
1011
|
+
`;
|
|
1012
|
+
}
|
|
1013
|
+
openToolDetail(part) {
|
|
1014
|
+
this.toolDetail = part;
|
|
1015
|
+
}
|
|
1016
|
+
closeToolDetail() {
|
|
1017
|
+
this.toolDetail = null;
|
|
1018
|
+
}
|
|
1019
|
+
renderToolDetailDialog() {
|
|
1020
|
+
const tool = this.toolDetail;
|
|
1021
|
+
if (!tool) return nothing;
|
|
1022
|
+
const label = `${tool.name} · ${tool.status}${tool.durationMs != null ? ` · ${tool.durationMs}ms` : ""}`;
|
|
1023
|
+
const body = JSON.stringify({
|
|
1024
|
+
args: tool.args ?? {},
|
|
1025
|
+
result: tool.result ?? null
|
|
1026
|
+
}, null, 2);
|
|
1027
|
+
return html`
|
|
1028
|
+
<wa-dialog
|
|
1029
|
+
label=${label}
|
|
1030
|
+
open
|
|
1031
|
+
light-dismiss
|
|
1032
|
+
with-footer
|
|
1033
|
+
style="--width: min(44rem, 96vw)"
|
|
1034
|
+
@wa-after-hide=${() => this.closeToolDetail()}
|
|
1035
|
+
>
|
|
1036
|
+
<div class="tool-detail-body">
|
|
1037
|
+
<pre>${body}</pre>
|
|
1038
|
+
</div>
|
|
1039
|
+
<div slot="footer">
|
|
1040
|
+
<wa-button variant="brand" @click=${() => this.closeToolDetail()}>Close</wa-button>
|
|
1041
|
+
</div>
|
|
1042
|
+
</wa-dialog>
|
|
842
1043
|
`;
|
|
843
1044
|
}
|
|
844
1045
|
resolvePermission(action) {
|
|
@@ -975,16 +1176,27 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
975
1176
|
<div class="composer">
|
|
976
1177
|
<div class="composer-row">
|
|
977
1178
|
<wa-textarea
|
|
978
|
-
placeholder
|
|
1179
|
+
placeholder=${this.busy ? this.busyStatus : "Enter your message here…"}
|
|
979
1180
|
size="s"
|
|
980
1181
|
resize="auto"
|
|
981
1182
|
rows="1"
|
|
982
|
-
.value=${this.draft}
|
|
1183
|
+
.value=${this.busy ? this.busyStatus : this.draft}
|
|
983
1184
|
?disabled=${this.busy}
|
|
1185
|
+
?readonly=${this.busy}
|
|
984
1186
|
@input=${(e) => {
|
|
1187
|
+
if (this.busy) return;
|
|
985
1188
|
this.draft = e.target.value;
|
|
986
1189
|
}}
|
|
987
1190
|
@keydown=${(e) => {
|
|
1191
|
+
if (this.busy) {
|
|
1192
|
+
if (e.key === "Escape") {
|
|
1193
|
+
e.preventDefault();
|
|
1194
|
+
this.cancelTurn();
|
|
1195
|
+
return;
|
|
1196
|
+
}
|
|
1197
|
+
e.preventDefault();
|
|
1198
|
+
return;
|
|
1199
|
+
}
|
|
988
1200
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
989
1201
|
e.preventDefault();
|
|
990
1202
|
this.send();
|
|
@@ -992,6 +1204,17 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
992
1204
|
}}
|
|
993
1205
|
></wa-textarea>
|
|
994
1206
|
<div class="composer-actions">
|
|
1207
|
+
${this.busy ? html`
|
|
1208
|
+
<wa-button
|
|
1209
|
+
size="s"
|
|
1210
|
+
appearance="plain"
|
|
1211
|
+
variant="danger"
|
|
1212
|
+
title="Stop (Esc)"
|
|
1213
|
+
@click=${() => this.cancelTurn()}
|
|
1214
|
+
>
|
|
1215
|
+
<wa-icon name="stop" label="Stop"></wa-icon>
|
|
1216
|
+
</wa-button>
|
|
1217
|
+
` : nothing}
|
|
995
1218
|
${this.renderAttachmentDropdown()}
|
|
996
1219
|
${this.renderContextDropdown()}
|
|
997
1220
|
</div>
|
|
@@ -999,6 +1222,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
999
1222
|
</div>
|
|
1000
1223
|
</div>
|
|
1001
1224
|
${this.renderAttachmentDialog()}
|
|
1225
|
+
${this.renderToolDetailDialog()}
|
|
1002
1226
|
</div>
|
|
1003
1227
|
`;
|
|
1004
1228
|
}
|
|
@@ -1130,6 +1354,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1130
1354
|
}
|
|
1131
1355
|
if (value.startsWith("effort:")) {
|
|
1132
1356
|
this.manualEffort = value.slice(7) || "auto";
|
|
1357
|
+
this.applyPolicy();
|
|
1133
1358
|
return;
|
|
1134
1359
|
}
|
|
1135
1360
|
this.onRouterSelect(value);
|
|
@@ -1177,7 +1402,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1177
1402
|
<wa-dropdown-item
|
|
1178
1403
|
value=${option.value}
|
|
1179
1404
|
type="checkbox"
|
|
1180
|
-
|
|
1405
|
+
.checked=${option.value === selected}
|
|
1181
1406
|
>
|
|
1182
1407
|
${option.label}
|
|
1183
1408
|
</wa-dropdown-item>
|
|
@@ -1189,7 +1414,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1189
1414
|
<wa-dropdown-item
|
|
1190
1415
|
value=${`model:${id}`}
|
|
1191
1416
|
type="checkbox"
|
|
1192
|
-
|
|
1417
|
+
.checked=${selected === `model:${id}`}
|
|
1193
1418
|
>
|
|
1194
1419
|
${id}
|
|
1195
1420
|
</wa-dropdown-item>
|
|
@@ -1202,7 +1427,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1202
1427
|
<wa-dropdown-item
|
|
1203
1428
|
value=${`effort:${level}`}
|
|
1204
1429
|
type="checkbox"
|
|
1205
|
-
|
|
1430
|
+
.checked=${this.manualEffort === level}
|
|
1206
1431
|
>
|
|
1207
1432
|
${level}
|
|
1208
1433
|
</wa-dropdown-item>
|
|
@@ -1215,7 +1440,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1215
1440
|
<wa-dropdown-item
|
|
1216
1441
|
value=${`approval:${option.value}`}
|
|
1217
1442
|
type="checkbox"
|
|
1218
|
-
|
|
1443
|
+
.checked=${this.approvalMode === option.value}
|
|
1219
1444
|
>
|
|
1220
1445
|
${option.label}
|
|
1221
1446
|
</wa-dropdown-item>
|
|
@@ -1268,18 +1493,18 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1268
1493
|
return this.renderAssistantMessage(message);
|
|
1269
1494
|
}
|
|
1270
1495
|
renderAssistantMessage(message, opts = {}) {
|
|
1271
|
-
const
|
|
1272
|
-
const techParts = message.parts.filter((p) => p.type !== "text");
|
|
1496
|
+
const { summaryText, techParts } = splitAssistantPresentation(message.parts);
|
|
1273
1497
|
const open = opts.streaming === true || techParts.some((p) => (p.type === "reasoning" || p.type === "tool") && p.status === "streaming");
|
|
1498
|
+
const summaryBubble = summaryText.length ? summaryText.map((p) => this.renderTextPart(p)) : html`<div class="bubble">${technicalSummary(techParts)}</div>`;
|
|
1274
1499
|
const summary = html`
|
|
1275
1500
|
<div slot="summary" class="msg-summary">
|
|
1276
1501
|
${opts.streaming ? html`
|
|
1277
1502
|
<div class="streaming-meta">
|
|
1278
1503
|
<wa-spinner style="font-size: 0.85rem"></wa-spinner>
|
|
1279
|
-
<span
|
|
1504
|
+
<span>${this.busy ? this.busyStatus : "streaming…"}</span>
|
|
1280
1505
|
</div>
|
|
1281
1506
|
` : nothing}
|
|
1282
|
-
${
|
|
1507
|
+
${summaryBubble}
|
|
1283
1508
|
</div>
|
|
1284
1509
|
`;
|
|
1285
1510
|
if (!techParts.length) return html`
|
|
@@ -1287,10 +1512,10 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1287
1512
|
${opts.streaming ? html`
|
|
1288
1513
|
<div class="streaming-meta">
|
|
1289
1514
|
<wa-spinner style="font-size: 0.85rem"></wa-spinner>
|
|
1290
|
-
<span
|
|
1515
|
+
<span>${this.busy ? this.busyStatus : "streaming…"}</span>
|
|
1291
1516
|
</div>
|
|
1292
1517
|
` : nothing}
|
|
1293
|
-
${
|
|
1518
|
+
${summaryBubble}
|
|
1294
1519
|
${message.id !== "streaming" ? this.renderMessageMeta(message) : nothing}
|
|
1295
1520
|
</div>
|
|
1296
1521
|
`;
|
|
@@ -1329,13 +1554,20 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1329
1554
|
`;
|
|
1330
1555
|
if (part.type === "tool") {
|
|
1331
1556
|
const heading = `${part.name} · ${part.status}${part.durationMs != null ? ` · ${part.durationMs}ms` : ""}`;
|
|
1557
|
+
const hasDetail = part.args != null || part.result != null || part.status === "error";
|
|
1332
1558
|
return html`
|
|
1333
|
-
<div>
|
|
1559
|
+
<div class="tool-row">
|
|
1334
1560
|
<div class="tool-heading">${heading}</div>
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1561
|
+
${hasDetail ? html`
|
|
1562
|
+
<wa-button
|
|
1563
|
+
size="s"
|
|
1564
|
+
appearance="plain"
|
|
1565
|
+
variant="neutral"
|
|
1566
|
+
@click=${() => this.openToolDetail(part)}
|
|
1567
|
+
>
|
|
1568
|
+
Details
|
|
1569
|
+
</wa-button>
|
|
1570
|
+
` : nothing}
|
|
1339
1571
|
</div>
|
|
1340
1572
|
`;
|
|
1341
1573
|
}
|
|
@@ -1351,7 +1583,9 @@ _decorate([state()], DocksCognitiveView.prototype, "draft", void 0);
|
|
|
1351
1583
|
_decorate([state()], DocksCognitiveView.prototype, "pendingAttachmentIds", void 0);
|
|
1352
1584
|
_decorate([state()], DocksCognitiveView.prototype, "dragOver", void 0);
|
|
1353
1585
|
_decorate([state()], DocksCognitiveView.prototype, "previewAttachmentId", void 0);
|
|
1586
|
+
_decorate([state()], DocksCognitiveView.prototype, "toolDetail", void 0);
|
|
1354
1587
|
_decorate([state()], DocksCognitiveView.prototype, "busy", void 0);
|
|
1588
|
+
_decorate([state()], DocksCognitiveView.prototype, "busyStatus", void 0);
|
|
1355
1589
|
_decorate([state()], DocksCognitiveView.prototype, "pendingPermission", void 0);
|
|
1356
1590
|
_decorate([state()], DocksCognitiveView.prototype, "policyMode", void 0);
|
|
1357
1591
|
_decorate([state()], DocksCognitiveView.prototype, "optimizeFor", void 0);
|
|
@@ -1364,14 +1598,14 @@ _decorate([state()], DocksCognitiveView.prototype, "historyOpen", void 0);
|
|
|
1364
1598
|
_decorate([state()], DocksCognitiveView.prototype, "historyQuery", void 0);
|
|
1365
1599
|
DocksCognitiveView = _decorate([customElement("docks-cognitive-view")], DocksCognitiveView);
|
|
1366
1600
|
var APPROVAL_OPTIONS$1 = [
|
|
1367
|
-
{
|
|
1368
|
-
value: "manual",
|
|
1369
|
-
label: "Manual"
|
|
1370
|
-
},
|
|
1371
1601
|
{
|
|
1372
1602
|
value: "auto_safe",
|
|
1373
1603
|
label: "Auto-approve non-critical"
|
|
1374
1604
|
},
|
|
1605
|
+
{
|
|
1606
|
+
value: "manual",
|
|
1607
|
+
label: "Manual"
|
|
1608
|
+
},
|
|
1375
1609
|
{
|
|
1376
1610
|
value: "auto_all",
|
|
1377
1611
|
label: "Approve all"
|
|
@@ -1380,15 +1614,40 @@ var APPROVAL_OPTIONS$1 = [
|
|
|
1380
1614
|
function capitalize(value) {
|
|
1381
1615
|
return value ? value[0].toUpperCase() + value.slice(1) : value;
|
|
1382
1616
|
}
|
|
1617
|
+
/**
|
|
1618
|
+
* Prefer text after the last tool/reasoning as the visible reply.
|
|
1619
|
+
* Interim narration stays out of the bubble — tool details cover the execution trail.
|
|
1620
|
+
*/
|
|
1621
|
+
function splitAssistantPresentation(parts) {
|
|
1622
|
+
const techParts = parts.filter((p) => p.type !== "text");
|
|
1623
|
+
let lastTechIndex = -1;
|
|
1624
|
+
for (let i = 0; i < parts.length; i++) if (parts[i].type !== "text") lastTechIndex = i;
|
|
1625
|
+
if (lastTechIndex < 0) return {
|
|
1626
|
+
summaryText: parts.filter((p) => p.type === "text"),
|
|
1627
|
+
techParts
|
|
1628
|
+
};
|
|
1629
|
+
const afterTools = parts.slice(lastTechIndex + 1).filter((p) => p.type === "text").filter((p) => p.text.trim());
|
|
1630
|
+
if (afterTools.length) return {
|
|
1631
|
+
summaryText: afterTools,
|
|
1632
|
+
techParts
|
|
1633
|
+
};
|
|
1634
|
+
return {
|
|
1635
|
+
summaryText: [],
|
|
1636
|
+
techParts
|
|
1637
|
+
};
|
|
1638
|
+
}
|
|
1383
1639
|
function technicalSummary(parts) {
|
|
1384
1640
|
const tools = parts.filter((p) => p.type === "tool");
|
|
1385
|
-
const
|
|
1386
|
-
const
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1641
|
+
const done = tools.filter((t) => t.status === "done").length;
|
|
1642
|
+
const errors = tools.filter((t) => t.status === "error").length;
|
|
1643
|
+
if (!tools.length) {
|
|
1644
|
+
if (parts.some((p) => p.type === "reasoning")) return "Thinking…";
|
|
1645
|
+
return "Details";
|
|
1646
|
+
}
|
|
1647
|
+
if (errors && done) return `Finished with ${errors} issue${errors === 1 ? "" : "s"} (${done} ok).`;
|
|
1648
|
+
if (errors) return `Couldn't complete ${errors} step${errors === 1 ? "" : "s"}.`;
|
|
1649
|
+
if (tools.some((t) => t.status === "running" || t.status === "preparing")) return "Working…";
|
|
1650
|
+
return done === 1 ? "Done." : `Done · ${done} steps.`;
|
|
1392
1651
|
}
|
|
1393
1652
|
function startOfDay(ts) {
|
|
1394
1653
|
const d = new Date(ts);
|
|
@@ -1463,6 +1722,29 @@ function shortModelLabel(modelRef) {
|
|
|
1463
1722
|
const slash = modelRef.indexOf("/");
|
|
1464
1723
|
return slash === -1 ? modelRef : modelRef.slice(slash + 1);
|
|
1465
1724
|
}
|
|
1725
|
+
function filesFromClipboard(data) {
|
|
1726
|
+
if (!data) return [];
|
|
1727
|
+
const fromFiles = [...data.files ?? []].filter((f) => f && f.size > 0);
|
|
1728
|
+
if (fromFiles.length) return fromFiles;
|
|
1729
|
+
const fromItems = [];
|
|
1730
|
+
for (const item of data.items ?? []) {
|
|
1731
|
+
if (item.kind !== "file") continue;
|
|
1732
|
+
const file = item.getAsFile();
|
|
1733
|
+
if (!file || file.size <= 0) continue;
|
|
1734
|
+
fromItems.push(nameClipboardFile(file, item.type));
|
|
1735
|
+
}
|
|
1736
|
+
return fromItems;
|
|
1737
|
+
}
|
|
1738
|
+
function nameClipboardFile(file, mimeHint) {
|
|
1739
|
+
const mime = (file.type || mimeHint || "application/octet-stream").toLowerCase();
|
|
1740
|
+
if (file.name && file.name !== "image.png" && file.name !== "blob") return file;
|
|
1741
|
+
const ext = mime === "image/jpeg" || mime === "image/jpg" ? "jpg" : mime === "image/png" ? "png" : mime === "image/gif" ? "gif" : mime === "image/webp" ? "webp" : mime === "image/svg+xml" ? "svg" : mime.startsWith("image/") ? "png" : "bin";
|
|
1742
|
+
const name = `clipboard-${Date.now()}.${ext}`;
|
|
1743
|
+
return new File([file], name, {
|
|
1744
|
+
type: mime || file.type,
|
|
1745
|
+
lastModified: file.lastModified
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1466
1748
|
function mergePart(parts, part) {
|
|
1467
1749
|
const next = [...parts];
|
|
1468
1750
|
const last = next[next.length - 1];
|
|
@@ -1491,16 +1773,16 @@ function mergePart(parts, part) {
|
|
|
1491
1773
|
//#endregion
|
|
1492
1774
|
//#region src/view/cognitive-settings-editor.ts
|
|
1493
1775
|
var APPROVAL_OPTIONS = [
|
|
1494
|
-
{
|
|
1495
|
-
value: "manual",
|
|
1496
|
-
label: "Manual",
|
|
1497
|
-
hint: "Confirm every tool before it runs"
|
|
1498
|
-
},
|
|
1499
1776
|
{
|
|
1500
1777
|
value: "auto_safe",
|
|
1501
1778
|
label: "Auto-approve non-critical",
|
|
1502
1779
|
hint: "The agent classifies each tool as safe or critical; only critical ones ask for approval"
|
|
1503
1780
|
},
|
|
1781
|
+
{
|
|
1782
|
+
value: "manual",
|
|
1783
|
+
label: "Manual",
|
|
1784
|
+
hint: "Confirm every tool before it runs"
|
|
1785
|
+
},
|
|
1504
1786
|
{
|
|
1505
1787
|
value: "auto_all",
|
|
1506
1788
|
label: "Approve all",
|
|
@@ -1711,59 +1993,15 @@ var DocksCognitiveSettingsEditor = class DocksCognitiveSettingsEditor extends Do
|
|
|
1711
1993
|
toastError(err instanceof Error ? err.message : String(err));
|
|
1712
1994
|
}
|
|
1713
1995
|
}
|
|
1714
|
-
renderToolbar() {
|
|
1715
|
-
return html`
|
|
1716
|
-
<wa-button size="s" appearance="plain" title="Add provider" @click=${() => this.addProvider()}>
|
|
1717
|
-
<wa-icon name="plus" label="Add provider"></wa-icon>
|
|
1718
|
-
</wa-button>
|
|
1719
|
-
<wa-button
|
|
1720
|
-
size="s"
|
|
1721
|
-
variant="brand"
|
|
1722
|
-
?disabled=${!this.isDirty()}
|
|
1723
|
-
@click=${() => void this.save()}
|
|
1724
|
-
>
|
|
1725
|
-
<wa-icon slot="start" name="floppy-disk"></wa-icon>
|
|
1726
|
-
Save
|
|
1727
|
-
</wa-button>
|
|
1728
|
-
`;
|
|
1729
|
-
}
|
|
1730
1996
|
renderContent() {
|
|
1731
1997
|
const rows = this.settings.providers;
|
|
1732
1998
|
return html`
|
|
1733
1999
|
<div class="editor">
|
|
1734
|
-
<section class="section">
|
|
1735
|
-
<header class="header">
|
|
1736
|
-
<div>
|
|
1737
|
-
<h2>Tool approvals</h2>
|
|
1738
|
-
<p class="hint">How the agent handles tool confirmation — same options as GitHub Copilot.</p>
|
|
1739
|
-
</div>
|
|
1740
|
-
</header>
|
|
1741
|
-
<wa-radio-group
|
|
1742
|
-
name="approval-mode"
|
|
1743
|
-
label="Approval mode"
|
|
1744
|
-
orientation="vertical"
|
|
1745
|
-
.value=${this.approvalMode}
|
|
1746
|
-
@change=${(e) => {
|
|
1747
|
-
const value = e.target.value;
|
|
1748
|
-
if (value === "manual" || value === "auto_safe" || value === "auto_all") this.setApprovalMode(value);
|
|
1749
|
-
}}
|
|
1750
|
-
>
|
|
1751
|
-
${APPROVAL_OPTIONS.map((option) => html`
|
|
1752
|
-
<wa-radio value=${option.value}>
|
|
1753
|
-
<span class="approval-option">
|
|
1754
|
-
<span class="approval-label">${option.label}</span>
|
|
1755
|
-
<span class="approval-hint">${option.hint}</span>
|
|
1756
|
-
</span>
|
|
1757
|
-
</wa-radio>
|
|
1758
|
-
`)}
|
|
1759
|
-
</wa-radio-group>
|
|
1760
|
-
</section>
|
|
1761
|
-
|
|
1762
2000
|
<section class="section">
|
|
1763
2001
|
<header class="header">
|
|
1764
2002
|
<div>
|
|
1765
2003
|
<h2>AI Providers</h2>
|
|
1766
|
-
<p class="hint">OpenAI-compatible endpoints. Edit cells in place, then
|
|
2004
|
+
<p class="hint">OpenAI-compatible endpoints. Edit cells in place, then save from the toolbar.</p>
|
|
1767
2005
|
</div>
|
|
1768
2006
|
<wa-button size="s" variant="brand" appearance="filled" @click=${() => this.addProvider()}>
|
|
1769
2007
|
<wa-icon slot="start" name="plus"></wa-icon>
|
|
@@ -1798,6 +2036,34 @@ var DocksCognitiveSettingsEditor = class DocksCognitiveSettingsEditor extends Do
|
|
|
1798
2036
|
<code>providerId/modelId</code> for Auto routing.
|
|
1799
2037
|
</wa-callout>
|
|
1800
2038
|
</section>
|
|
2039
|
+
|
|
2040
|
+
<section class="section">
|
|
2041
|
+
<header class="header">
|
|
2042
|
+
<div>
|
|
2043
|
+
<h2>Tool approvals</h2>
|
|
2044
|
+
<p class="hint">How the agent handles tool confirmation — same options as GitHub Copilot.</p>
|
|
2045
|
+
</div>
|
|
2046
|
+
</header>
|
|
2047
|
+
<wa-radio-group
|
|
2048
|
+
name="approval-mode"
|
|
2049
|
+
label="Approval mode"
|
|
2050
|
+
orientation="vertical"
|
|
2051
|
+
.value=${this.approvalMode}
|
|
2052
|
+
@change=${(e) => {
|
|
2053
|
+
const value = e.target.value;
|
|
2054
|
+
if (value === "manual" || value === "auto_safe" || value === "auto_all") this.setApprovalMode(value);
|
|
2055
|
+
}}
|
|
2056
|
+
>
|
|
2057
|
+
${APPROVAL_OPTIONS.map((option) => html`
|
|
2058
|
+
<wa-radio value=${option.value}>
|
|
2059
|
+
<span class="approval-option">
|
|
2060
|
+
<span class="approval-label">${option.label}</span>
|
|
2061
|
+
<span class="approval-hint">${option.hint}</span>
|
|
2062
|
+
</span>
|
|
2063
|
+
</wa-radio>
|
|
2064
|
+
`)}
|
|
2065
|
+
</wa-radio-group>
|
|
2066
|
+
</section>
|
|
1801
2067
|
</div>
|
|
1802
2068
|
`;
|
|
1803
2069
|
}
|
|
@@ -2126,4 +2392,4 @@ registerAll({
|
|
|
2126
2392
|
});
|
|
2127
2393
|
//#endregion
|
|
2128
2394
|
|
|
2129
|
-
//# sourceMappingURL=cognitive-extension-
|
|
2395
|
+
//# sourceMappingURL=cognitive-extension-7_ZMUCGD.js.map
|