@eclipse-docks/extension-ai-system 0.8.0 → 0.8.2
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.d.ts +1 -1
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +87 -2
- package/dist/api.js.map +1 -0
- package/dist/{cognitive-extension-CG_d39K5.js → cognitive-extension-BKGxwLYj.js} +524 -102
- package/dist/cognitive-extension-BKGxwLYj.js.map +1 -0
- package/dist/cognitive-extension.d.ts.map +1 -1
- 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 +12 -3
- package/dist/runtime/cognitive-runtime.d.ts.map +1 -1
- package/dist/runtime/context/usage.d.ts +3 -0
- package/dist/runtime/context/usage.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +4 -0
- package/dist/runtime/index.d.ts.map +1 -1
- package/dist/runtime/models/openai-compatible.d.ts.map +1 -1
- package/dist/runtime/models/types.d.ts +6 -1
- package/dist/runtime/models/types.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/skills-commands.d.ts +3 -0
- package/dist/runtime/skills-commands.d.ts.map +1 -0
- package/dist/runtime/skills-parse.d.ts +14 -0
- package/dist/runtime/skills-parse.d.ts.map +1 -0
- package/dist/runtime/skills-resolve.d.ts +9 -0
- package/dist/runtime/skills-resolve.d.ts.map +1 -0
- package/dist/runtime/skills-select.d.ts +9 -0
- package/dist/runtime/skills-select.d.ts.map +1 -0
- package/dist/runtime/skills-types.d.ts +47 -0
- package/dist/runtime/skills-types.d.ts.map +1 -0
- package/dist/runtime/skills.d.ts +13 -0
- package/dist/runtime/skills.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/fetch-adapter.d.ts +4 -0
- package/dist/runtime/tools/fetch-adapter.d.ts.map +1 -0
- package/dist/runtime/tools/index.d.ts +1 -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/types.d.ts +7 -0
- package/dist/runtime/types.d.ts.map +1 -1
- package/dist/{runtime-DfNGzEjU.js → runtime-B0IHjzQO.js} +1042 -401
- package/dist/runtime-B0IHjzQO.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 +22 -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 {
|
|
2
|
-
import { DocksPart, SIDEBAR_AUXILIARY, confirmDialog, contributionRegistry, editorRegistry, registerAll, rootContext, toastError, toastInfo } from "@eclipse-docks/core";
|
|
3
|
-
import { css, customElement, html, nothing, property, query, state } from "@eclipse-docks/core/externals/lit";
|
|
1
|
+
import { C as detectEffortCapability, D as AI_VIEW_NAME, E as AI_SETTINGS_KEY, O as OPEN_AI_SETTINGS_COMMAND, S as parseModelIds, T as AI_SETTINGS_EDITOR_ID, _ as readPromptAttachmentFromFile, b as defaultProvidersSettings, f as estimateSessionContextUsage, g as ATTACHMENT_FILE_ACCEPT, h as formatTokenCount, k as TOPIC, m as formatContextPercent, p as formatBucketDetail, r as cognitiveRuntime, t as registerSkillCommands, y as fetchOpenAICompatibleModels } from "./runtime-B0IHjzQO.js";
|
|
2
|
+
import { DocksPart, File as File$1, FileContentType, SIDEBAR_AUXILIARY, confirmDialog, contributionRegistry, editorRegistry, filebrowserDialog, parseMarkdownHtml, registerAll, rootContext, toastError, toastInfo, workspaceService } from "@eclipse-docks/core";
|
|
3
|
+
import { css, customElement, html, nothing, property, query, state, unsafeHTML } 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`
|
|
@@ -124,11 +180,21 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
124
180
|
display: flex;
|
|
125
181
|
flex-direction: column;
|
|
126
182
|
gap: var(--wa-space-2xs);
|
|
127
|
-
|
|
183
|
+
width: 90%;
|
|
184
|
+
min-width: 90%;
|
|
185
|
+
max-width: 90%;
|
|
186
|
+
align-self: flex-start;
|
|
187
|
+
align-items: stretch;
|
|
128
188
|
}
|
|
129
189
|
|
|
130
190
|
.msg.user {
|
|
131
|
-
align-
|
|
191
|
+
align-self: flex-end;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.msg .bubble,
|
|
195
|
+
.msg wa-details.msg-details {
|
|
196
|
+
width: 100%;
|
|
197
|
+
box-sizing: border-box;
|
|
132
198
|
}
|
|
133
199
|
|
|
134
200
|
.msg-meta {
|
|
@@ -166,6 +232,39 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
166
232
|
white-space: pre-wrap;
|
|
167
233
|
line-height: var(--wa-line-height-normal);
|
|
168
234
|
max-width: 100%;
|
|
235
|
+
overflow-wrap: anywhere;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
.bubble.markdown {
|
|
239
|
+
white-space: normal;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.bubble.markdown > :first-child {
|
|
243
|
+
margin-block-start: 0;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.bubble.markdown > :last-child {
|
|
247
|
+
margin-block-end: 0;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.bubble.markdown pre {
|
|
251
|
+
overflow-x: auto;
|
|
252
|
+
padding: var(--wa-space-s);
|
|
253
|
+
border-radius: var(--wa-border-radius-m);
|
|
254
|
+
background: color-mix(in srgb, var(--wa-color-neutral-fill-quiet) 55%, transparent);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
.bubble.markdown code {
|
|
258
|
+
font-family: var(--wa-font-family-code, ui-monospace, monospace);
|
|
259
|
+
font-size: 0.92em;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.bubble.markdown pre code {
|
|
263
|
+
font-size: inherit;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.bubble.markdown a {
|
|
267
|
+
color: var(--wa-color-brand-on-normal);
|
|
169
268
|
}
|
|
170
269
|
|
|
171
270
|
.msg.user .bubble {
|
|
@@ -262,6 +361,34 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
262
361
|
background: var(--bucket-color, var(--wa-color-brand-fill-normal));
|
|
263
362
|
}
|
|
264
363
|
|
|
364
|
+
.context-io {
|
|
365
|
+
display: grid;
|
|
366
|
+
grid-template-columns: 1fr 1fr;
|
|
367
|
+
gap: var(--wa-space-2xs);
|
|
368
|
+
padding-top: var(--wa-space-s);
|
|
369
|
+
border-top: var(--wa-border-width-s) solid var(--wa-color-border-normal);
|
|
370
|
+
font-size: var(--wa-font-size-xs);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.context-io-heading {
|
|
374
|
+
grid-column: 1 / -1;
|
|
375
|
+
font-weight: var(--wa-font-weight-semibold, 600);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
.context-io-item {
|
|
379
|
+
display: flex;
|
|
380
|
+
flex-direction: column;
|
|
381
|
+
gap: 0.1rem;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
.context-io-item span {
|
|
385
|
+
color: var(--wa-color-text-quiet);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.context-io-item strong {
|
|
389
|
+
font-variant-numeric: tabular-nums;
|
|
390
|
+
}
|
|
391
|
+
|
|
265
392
|
.context-footer {
|
|
266
393
|
display: flex;
|
|
267
394
|
flex-direction: column;
|
|
@@ -490,8 +617,44 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
490
617
|
color: var(--wa-color-text-quiet);
|
|
491
618
|
margin-bottom: var(--wa-space-2xs);
|
|
492
619
|
}
|
|
620
|
+
|
|
621
|
+
.tool-row {
|
|
622
|
+
display: flex;
|
|
623
|
+
align-items: center;
|
|
624
|
+
gap: var(--wa-space-2xs);
|
|
625
|
+
flex-wrap: wrap;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
.tool-row .tool-heading {
|
|
629
|
+
margin-bottom: 0;
|
|
630
|
+
flex: 1;
|
|
631
|
+
min-width: 0;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
.tool-detail-body {
|
|
635
|
+
max-height: min(70vh, 36rem);
|
|
636
|
+
overflow: auto;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
.tool-detail-body pre {
|
|
640
|
+
margin: 0;
|
|
641
|
+
font-family: var(--wa-font-family-code, var(--wa-font-mono));
|
|
642
|
+
font-size: var(--wa-font-size-xs);
|
|
643
|
+
white-space: pre-wrap;
|
|
644
|
+
word-break: break-word;
|
|
645
|
+
}
|
|
493
646
|
`;
|
|
494
647
|
}
|
|
648
|
+
updated() {
|
|
649
|
+
this.bindComposerPaste();
|
|
650
|
+
}
|
|
651
|
+
bindComposerPaste() {
|
|
652
|
+
if (this.composerPasteBound) return;
|
|
653
|
+
const native = this.textarea?.shadowRoot?.querySelector("textarea");
|
|
654
|
+
if (!native) return;
|
|
655
|
+
native.addEventListener("paste", this.nativePasteHandler);
|
|
656
|
+
this.composerPasteBound = true;
|
|
657
|
+
}
|
|
495
658
|
doBeforeUI() {
|
|
496
659
|
cognitiveRuntime.start();
|
|
497
660
|
this.syncSessions();
|
|
@@ -499,14 +662,13 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
499
662
|
this.approvalMode = cognitiveRuntime.getApprovalMode();
|
|
500
663
|
cognitiveRuntime.whenReady().then(() => {
|
|
501
664
|
this.syncSessions();
|
|
502
|
-
this.
|
|
503
|
-
this.approvalMode = cognitiveRuntime.getApprovalMode();
|
|
665
|
+
this.restoreRoutingFromRuntime();
|
|
504
666
|
this.scheduleScrollToBottom();
|
|
505
667
|
});
|
|
506
668
|
this.unsubs.push(cognitiveRuntime.events.subscribe(TOPIC.sessionChanged, () => {
|
|
507
669
|
this.syncSessions();
|
|
508
670
|
this.scheduleScrollToBottom();
|
|
509
|
-
}), cognitiveRuntime.events.subscribe(TOPIC.providersChanged, () => this.
|
|
671
|
+
}), cognitiveRuntime.events.subscribe(TOPIC.providersChanged, () => this.onProvidersChanged()), cognitiveRuntime.events.subscribe(TOPIC.approvalModeChanged, (mode) => {
|
|
510
672
|
this.approvalMode = mode;
|
|
511
673
|
}), cognitiveRuntime.events.subscribe(TOPIC.permissionAsked, (payload) => {
|
|
512
674
|
this.pendingPermission = payload;
|
|
@@ -525,9 +687,33 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
525
687
|
doClose() {
|
|
526
688
|
if (this.scrollDebounceTimer) clearTimeout(this.scrollDebounceTimer);
|
|
527
689
|
this.scrollDebounceTimer = void 0;
|
|
690
|
+
this.cancelTurn();
|
|
691
|
+
this.stopBusyStatus();
|
|
692
|
+
(this.textarea?.shadowRoot?.querySelector("textarea"))?.removeEventListener("paste", this.nativePasteHandler);
|
|
693
|
+
this.composerPasteBound = false;
|
|
528
694
|
for (const u of this.unsubs) u();
|
|
529
695
|
this.unsubs = [];
|
|
530
696
|
}
|
|
697
|
+
startBusyStatus() {
|
|
698
|
+
this.stopBusyStatus();
|
|
699
|
+
this.busyStatus = INITIAL_BUSY_STATUS;
|
|
700
|
+
this.setComposerText(this.busyStatus);
|
|
701
|
+
window.addEventListener("keydown", this.cancelKeyHandler);
|
|
702
|
+
const schedule = () => {
|
|
703
|
+
this.busyStatusTimer = setTimeout(() => {
|
|
704
|
+
this.busyStatus = nextBusyStatus(this.busyStatus);
|
|
705
|
+
this.setComposerText(this.busyStatus);
|
|
706
|
+
schedule();
|
|
707
|
+
}, busyStatusRotateMs());
|
|
708
|
+
};
|
|
709
|
+
schedule();
|
|
710
|
+
}
|
|
711
|
+
stopBusyStatus() {
|
|
712
|
+
if (this.busyStatusTimer) clearTimeout(this.busyStatusTimer);
|
|
713
|
+
this.busyStatusTimer = void 0;
|
|
714
|
+
this.busyStatus = INITIAL_BUSY_STATUS;
|
|
715
|
+
window.removeEventListener("keydown", this.cancelKeyHandler);
|
|
716
|
+
}
|
|
531
717
|
syncSessions() {
|
|
532
718
|
const byRecency = cognitiveRuntime.sessions.list();
|
|
533
719
|
this.sessions = [...byRecency].sort((a, b) => a.createdAt - b.createdAt);
|
|
@@ -558,11 +744,10 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
558
744
|
deleteSession(sessionId) {
|
|
559
745
|
if (this.sessions.length <= 1) {
|
|
560
746
|
cognitiveRuntime.sessions.createSession({ title: "Chat" });
|
|
561
|
-
cognitiveRuntime.
|
|
562
|
-
} else cognitiveRuntime.
|
|
747
|
+
cognitiveRuntime.removeSession(sessionId);
|
|
748
|
+
} else cognitiveRuntime.removeSession(sessionId);
|
|
563
749
|
this.streamingParts = [];
|
|
564
750
|
this.syncSessions();
|
|
565
|
-
cognitiveRuntime.commitSessions();
|
|
566
751
|
}
|
|
567
752
|
openSession(sessionId) {
|
|
568
753
|
if (!cognitiveRuntime.sessions.focus(sessionId)) return;
|
|
@@ -598,6 +783,31 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
598
783
|
this.modelIds = cognitiveRuntime.listConfiguredModels();
|
|
599
784
|
if (!this.manualModel || !this.modelIds.includes(this.manualModel)) this.manualModel = this.modelIds[0] ?? cognitiveRuntime.defaultModelId();
|
|
600
785
|
}
|
|
786
|
+
/** Mirror persisted runtime policy into the gear menu after hydrate. */
|
|
787
|
+
restoreRoutingFromRuntime() {
|
|
788
|
+
this.syncModels();
|
|
789
|
+
const policy = cognitiveRuntime.getModelPolicy();
|
|
790
|
+
if (policy.mode === "auto") {
|
|
791
|
+
this.policyMode = "auto";
|
|
792
|
+
this.optimizeFor = policy.optimizeFor;
|
|
793
|
+
} else {
|
|
794
|
+
this.policyMode = "manual";
|
|
795
|
+
this.manualModel = policy.model;
|
|
796
|
+
this.manualEffort = policy.effort ?? "auto";
|
|
797
|
+
if (!this.manualModel || !this.modelIds.includes(this.manualModel)) {
|
|
798
|
+
this.manualModel = this.modelIds[0] ?? cognitiveRuntime.defaultModelId();
|
|
799
|
+
this.applyPolicy();
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
this.approvalMode = cognitiveRuntime.getApprovalMode();
|
|
803
|
+
}
|
|
804
|
+
onProvidersChanged() {
|
|
805
|
+
this.syncModels();
|
|
806
|
+
if (this.policyMode !== "manual") return;
|
|
807
|
+
if (this.manualModel && this.modelIds.includes(this.manualModel)) return;
|
|
808
|
+
this.manualModel = this.modelIds[0] ?? cognitiveRuntime.defaultModelId();
|
|
809
|
+
this.applyPolicy();
|
|
810
|
+
}
|
|
601
811
|
effortChoices() {
|
|
602
812
|
const cap = detectEffortCapability(this.manualModel || cognitiveRuntime.defaultModelId());
|
|
603
813
|
if (!cap.supported) return ["auto", "none"];
|
|
@@ -631,6 +841,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
631
841
|
if (optimize === "cost" || optimize === "balance" || optimize === "intelligence") {
|
|
632
842
|
this.policyMode = "auto";
|
|
633
843
|
this.optimizeFor = optimize;
|
|
844
|
+
this.applyPolicy();
|
|
634
845
|
}
|
|
635
846
|
return;
|
|
636
847
|
}
|
|
@@ -639,6 +850,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
639
850
|
if (!model) return;
|
|
640
851
|
this.policyMode = "manual";
|
|
641
852
|
this.manualModel = model;
|
|
853
|
+
this.applyPolicy();
|
|
642
854
|
}
|
|
643
855
|
}
|
|
644
856
|
applyPolicy() {
|
|
@@ -652,12 +864,15 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
652
864
|
};
|
|
653
865
|
cognitiveRuntime.setModelPolicy(policy);
|
|
654
866
|
}
|
|
867
|
+
async setComposerText(value) {
|
|
868
|
+
this.draft = value;
|
|
869
|
+
await this.updateComplete;
|
|
870
|
+
if (this.textarea) this.textarea.value = value;
|
|
871
|
+
}
|
|
655
872
|
async clearComposer() {
|
|
656
|
-
this.draft = "";
|
|
657
873
|
this.pendingAttachmentIds = [];
|
|
658
|
-
await this.updateComplete;
|
|
659
|
-
if (this.textarea) this.textarea.value = "";
|
|
660
874
|
if (this.fileInput) this.fileInput.value = "";
|
|
875
|
+
await this.setComposerText("");
|
|
661
876
|
}
|
|
662
877
|
sessionAttachments() {
|
|
663
878
|
return this.focusedSession()?.attachments ?? [];
|
|
@@ -679,6 +894,40 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
679
894
|
if (this.previewAttachmentId === attachmentId) this.previewAttachmentId = null;
|
|
680
895
|
this.syncSessions();
|
|
681
896
|
}
|
|
897
|
+
async saveAttachmentToWorkspace(attachmentId) {
|
|
898
|
+
const attachment = this.sessionAttachments().find((a) => a.id === attachmentId);
|
|
899
|
+
if (!attachment) return;
|
|
900
|
+
const preferredName = attachmentSaveFileName(attachment);
|
|
901
|
+
const parent = await filebrowserDialog("directory");
|
|
902
|
+
if (!parent) return;
|
|
903
|
+
try {
|
|
904
|
+
const workspace = await workspaceService.getWorkspace();
|
|
905
|
+
if (!workspace) {
|
|
906
|
+
toastError("No workspace connected");
|
|
907
|
+
return;
|
|
908
|
+
}
|
|
909
|
+
const parentPath = parent.replace(/\/$/, "");
|
|
910
|
+
const fileName = await uniqueWorkspaceFileName(workspace, parentPath, preferredName);
|
|
911
|
+
const path = `${parentPath}/${fileName}`;
|
|
912
|
+
const resource = await workspace.getResource(path, { create: true });
|
|
913
|
+
if (!(resource instanceof File$1)) {
|
|
914
|
+
toastError("Could not create file in the selected folder");
|
|
915
|
+
return;
|
|
916
|
+
}
|
|
917
|
+
if (attachment.dataUrl) {
|
|
918
|
+
const blob = await (await fetch(attachment.dataUrl)).blob();
|
|
919
|
+
const named = new globalThis.File([blob], fileName, { type: blob.type || attachment.mime || "" });
|
|
920
|
+
await resource.saveContents(named, { contentType: FileContentType.BINARY });
|
|
921
|
+
} else if (attachment.text != null) await resource.saveContents(attachment.text);
|
|
922
|
+
else {
|
|
923
|
+
toastError("Attachment has no payload to save");
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
toastInfo(`Saved ${fileName}`);
|
|
927
|
+
} catch (err) {
|
|
928
|
+
toastError(err instanceof Error ? err.message : String(err));
|
|
929
|
+
}
|
|
930
|
+
}
|
|
682
931
|
async addFiles(fileList) {
|
|
683
932
|
const files = [...fileList];
|
|
684
933
|
if (!files.length) return;
|
|
@@ -699,7 +948,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
699
948
|
}
|
|
700
949
|
accepted.push(result.attachment);
|
|
701
950
|
}
|
|
702
|
-
const stored = cognitiveRuntime.addAttachments(sessionId, accepted);
|
|
951
|
+
const stored = await cognitiveRuntime.addAttachments(sessionId, accepted);
|
|
703
952
|
if (stored.length) this.pendingAttachmentIds = [...this.pendingAttachmentIds, ...stored.map((a) => a.id).filter((id) => !this.pendingAttachmentIds.includes(id))];
|
|
704
953
|
this.syncSessions();
|
|
705
954
|
}
|
|
@@ -724,22 +973,47 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
724
973
|
this.dragOver = false;
|
|
725
974
|
if (e.dataTransfer?.files?.length) await this.addFiles(e.dataTransfer.files);
|
|
726
975
|
}
|
|
976
|
+
/** Attach clipboard files/images (e.g. Ctrl+V screenshot) when focused in the prompt. */
|
|
977
|
+
async onComposerPaste(e) {
|
|
978
|
+
if (this.busy) {
|
|
979
|
+
e.preventDefault();
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
const files = filesFromClipboard(e.clipboardData);
|
|
983
|
+
if (!files.length) return;
|
|
984
|
+
e.preventDefault();
|
|
985
|
+
await this.addFiles(files);
|
|
986
|
+
}
|
|
987
|
+
cancelTurn() {
|
|
988
|
+
if (!this.busy && !this.promptController) return;
|
|
989
|
+
this.promptController?.abort();
|
|
990
|
+
if (this.pendingPermission) this.resolvePermission("deny");
|
|
991
|
+
}
|
|
727
992
|
async send() {
|
|
728
993
|
const text = this.draft.trim();
|
|
729
994
|
const attachmentIds = [...this.pendingAttachmentIds];
|
|
730
995
|
if (!text && !attachmentIds.length || this.busy) return;
|
|
731
996
|
this.applyPolicy();
|
|
732
|
-
|
|
997
|
+
this.pendingAttachmentIds = [];
|
|
998
|
+
if (this.fileInput) this.fileInput.value = "";
|
|
999
|
+
const controller = new AbortController();
|
|
1000
|
+
this.promptController = controller;
|
|
733
1001
|
this.busy = true;
|
|
734
1002
|
this.streamingParts = [];
|
|
1003
|
+
this.startBusyStatus();
|
|
735
1004
|
try {
|
|
736
1005
|
await cognitiveRuntime.prompt({
|
|
737
1006
|
sessionId: this.focusedId ?? void 0,
|
|
738
1007
|
text,
|
|
739
|
-
attachmentIds
|
|
1008
|
+
attachmentIds,
|
|
1009
|
+
signal: controller.signal
|
|
740
1010
|
});
|
|
741
1011
|
} finally {
|
|
1012
|
+
if (this.promptController === controller) this.promptController = null;
|
|
1013
|
+
this.stopBusyStatus();
|
|
742
1014
|
this.busy = false;
|
|
1015
|
+
this.streamingParts = [];
|
|
1016
|
+
await this.clearComposer();
|
|
743
1017
|
this.syncSessions();
|
|
744
1018
|
this.scheduleScrollToBottom();
|
|
745
1019
|
this.textarea?.focus();
|
|
@@ -786,6 +1060,15 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
786
1060
|
`}
|
|
787
1061
|
<span class="attach-name">${file.name}</span>
|
|
788
1062
|
</button>
|
|
1063
|
+
<wa-button
|
|
1064
|
+
size="s"
|
|
1065
|
+
appearance="plain"
|
|
1066
|
+
title=${`Save ${file.name} to workspace folder`}
|
|
1067
|
+
?disabled=${this.busy}
|
|
1068
|
+
@click=${() => void this.saveAttachmentToWorkspace(file.id)}
|
|
1069
|
+
>
|
|
1070
|
+
<wa-icon name="floppy-disk" label=${`Save ${file.name}`}></wa-icon>
|
|
1071
|
+
</wa-button>
|
|
789
1072
|
<wa-button
|
|
790
1073
|
size="s"
|
|
791
1074
|
appearance="plain"
|
|
@@ -839,6 +1122,38 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
839
1122
|
<wa-button variant="brand" @click=${() => this.closeAttachmentPreview()}>Close</wa-button>
|
|
840
1123
|
</div>
|
|
841
1124
|
</wa-dialog>
|
|
1125
|
+
`;
|
|
1126
|
+
}
|
|
1127
|
+
openToolDetail(part) {
|
|
1128
|
+
this.toolDetail = part;
|
|
1129
|
+
}
|
|
1130
|
+
closeToolDetail() {
|
|
1131
|
+
this.toolDetail = null;
|
|
1132
|
+
}
|
|
1133
|
+
renderToolDetailDialog() {
|
|
1134
|
+
const tool = this.toolDetail;
|
|
1135
|
+
if (!tool) return nothing;
|
|
1136
|
+
const label = `${tool.name} · ${tool.status}${tool.durationMs != null ? ` · ${tool.durationMs}ms` : ""}`;
|
|
1137
|
+
const body = JSON.stringify({
|
|
1138
|
+
args: tool.args ?? {},
|
|
1139
|
+
result: tool.result ?? null
|
|
1140
|
+
}, null, 2);
|
|
1141
|
+
return html`
|
|
1142
|
+
<wa-dialog
|
|
1143
|
+
label=${label}
|
|
1144
|
+
open
|
|
1145
|
+
light-dismiss
|
|
1146
|
+
with-footer
|
|
1147
|
+
style="--width: min(44rem, 96vw)"
|
|
1148
|
+
@wa-after-hide=${() => this.closeToolDetail()}
|
|
1149
|
+
>
|
|
1150
|
+
<div class="tool-detail-body">
|
|
1151
|
+
<pre>${body}</pre>
|
|
1152
|
+
</div>
|
|
1153
|
+
<div slot="footer">
|
|
1154
|
+
<wa-button variant="brand" @click=${() => this.closeToolDetail()}>Close</wa-button>
|
|
1155
|
+
</div>
|
|
1156
|
+
</wa-dialog>
|
|
842
1157
|
`;
|
|
843
1158
|
}
|
|
844
1159
|
resolvePermission(action) {
|
|
@@ -878,7 +1193,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
878
1193
|
const usage = this.contextUsage();
|
|
879
1194
|
const canCompact = (this.focusedSession()?.history.length ?? 0) > 12;
|
|
880
1195
|
const percentLabel = formatContextPercent(usage.percent);
|
|
881
|
-
const title = `Context ${percentLabel} ·
|
|
1196
|
+
const title = `Context window ${percentLabel} · ~${formatTokenCount(usage.used)} / ${formatTokenCount(usage.limit)}`;
|
|
882
1197
|
const ringValue = Math.min(100, Math.max(usage.percent, usage.used > 0 ? 1 : 0));
|
|
883
1198
|
return html`
|
|
884
1199
|
<wa-dropdown
|
|
@@ -907,7 +1222,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
907
1222
|
@keydown=${(e) => e.stopPropagation()}
|
|
908
1223
|
>
|
|
909
1224
|
<div class="context-header">
|
|
910
|
-
<strong>Context
|
|
1225
|
+
<strong>Context window</strong>
|
|
911
1226
|
<span>${percentLabel}</span>
|
|
912
1227
|
</div>
|
|
913
1228
|
<div class="context-bars">
|
|
@@ -928,10 +1243,26 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
928
1243
|
</div>
|
|
929
1244
|
<div class="context-footer">
|
|
930
1245
|
<span class="context-remaining">
|
|
931
|
-
~${formatTokenCount(usage.used)}
|
|
1246
|
+
~${formatTokenCount(usage.used)} in window · ${formatTokenCount(usage.remaining)} free of
|
|
932
1247
|
${formatTokenCount(usage.limit)}
|
|
933
1248
|
· ${shortModelLabel(usage.modelRef)}
|
|
934
1249
|
</span>
|
|
1250
|
+
</div>
|
|
1251
|
+
<div
|
|
1252
|
+
class="context-io"
|
|
1253
|
+
title="Sum of provider-reported tokens across every model request in this chat. Each tool-loop call re-sends the prompt, so API input grows much faster than the context window fill."
|
|
1254
|
+
>
|
|
1255
|
+
<div class="context-io-heading">API usage (this chat)</div>
|
|
1256
|
+
<div class="context-io-item">
|
|
1257
|
+
<span>Input</span>
|
|
1258
|
+
<strong>${usage.inputTokens ? formatTokenCount(usage.inputTokens) : "—"}</strong>
|
|
1259
|
+
</div>
|
|
1260
|
+
<div class="context-io-item">
|
|
1261
|
+
<span>Output</span>
|
|
1262
|
+
<strong>${usage.outputTokens ? formatTokenCount(usage.outputTokens) : "—"}</strong>
|
|
1263
|
+
</div>
|
|
1264
|
+
</div>
|
|
1265
|
+
<div class="context-footer">
|
|
935
1266
|
<wa-button
|
|
936
1267
|
size="s"
|
|
937
1268
|
variant=${usage.level === "critical" ? "danger" : "neutral"}
|
|
@@ -975,16 +1306,27 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
975
1306
|
<div class="composer">
|
|
976
1307
|
<div class="composer-row">
|
|
977
1308
|
<wa-textarea
|
|
978
|
-
placeholder
|
|
1309
|
+
placeholder=${this.busy ? this.busyStatus : "Enter your message here…"}
|
|
979
1310
|
size="s"
|
|
980
1311
|
resize="auto"
|
|
981
1312
|
rows="1"
|
|
982
|
-
.value=${this.draft}
|
|
1313
|
+
.value=${this.busy ? this.busyStatus : this.draft}
|
|
983
1314
|
?disabled=${this.busy}
|
|
1315
|
+
?readonly=${this.busy}
|
|
984
1316
|
@input=${(e) => {
|
|
1317
|
+
if (this.busy) return;
|
|
985
1318
|
this.draft = e.target.value;
|
|
986
1319
|
}}
|
|
987
1320
|
@keydown=${(e) => {
|
|
1321
|
+
if (this.busy) {
|
|
1322
|
+
if (e.key === "Escape") {
|
|
1323
|
+
e.preventDefault();
|
|
1324
|
+
this.cancelTurn();
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
e.preventDefault();
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
988
1330
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
989
1331
|
e.preventDefault();
|
|
990
1332
|
this.send();
|
|
@@ -992,6 +1334,17 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
992
1334
|
}}
|
|
993
1335
|
></wa-textarea>
|
|
994
1336
|
<div class="composer-actions">
|
|
1337
|
+
${this.busy ? html`
|
|
1338
|
+
<wa-button
|
|
1339
|
+
size="s"
|
|
1340
|
+
appearance="plain"
|
|
1341
|
+
variant="danger"
|
|
1342
|
+
title="Stop (Esc)"
|
|
1343
|
+
@click=${() => this.cancelTurn()}
|
|
1344
|
+
>
|
|
1345
|
+
<wa-icon name="stop" label="Stop"></wa-icon>
|
|
1346
|
+
</wa-button>
|
|
1347
|
+
` : nothing}
|
|
995
1348
|
${this.renderAttachmentDropdown()}
|
|
996
1349
|
${this.renderContextDropdown()}
|
|
997
1350
|
</div>
|
|
@@ -999,6 +1352,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
999
1352
|
</div>
|
|
1000
1353
|
</div>
|
|
1001
1354
|
${this.renderAttachmentDialog()}
|
|
1355
|
+
${this.renderToolDetailDialog()}
|
|
1002
1356
|
</div>
|
|
1003
1357
|
`;
|
|
1004
1358
|
}
|
|
@@ -1130,6 +1484,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1130
1484
|
}
|
|
1131
1485
|
if (value.startsWith("effort:")) {
|
|
1132
1486
|
this.manualEffort = value.slice(7) || "auto";
|
|
1487
|
+
this.applyPolicy();
|
|
1133
1488
|
return;
|
|
1134
1489
|
}
|
|
1135
1490
|
this.onRouterSelect(value);
|
|
@@ -1177,7 +1532,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1177
1532
|
<wa-dropdown-item
|
|
1178
1533
|
value=${option.value}
|
|
1179
1534
|
type="checkbox"
|
|
1180
|
-
|
|
1535
|
+
.checked=${option.value === selected}
|
|
1181
1536
|
>
|
|
1182
1537
|
${option.label}
|
|
1183
1538
|
</wa-dropdown-item>
|
|
@@ -1189,7 +1544,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1189
1544
|
<wa-dropdown-item
|
|
1190
1545
|
value=${`model:${id}`}
|
|
1191
1546
|
type="checkbox"
|
|
1192
|
-
|
|
1547
|
+
.checked=${selected === `model:${id}`}
|
|
1193
1548
|
>
|
|
1194
1549
|
${id}
|
|
1195
1550
|
</wa-dropdown-item>
|
|
@@ -1202,7 +1557,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1202
1557
|
<wa-dropdown-item
|
|
1203
1558
|
value=${`effort:${level}`}
|
|
1204
1559
|
type="checkbox"
|
|
1205
|
-
|
|
1560
|
+
.checked=${this.manualEffort === level}
|
|
1206
1561
|
>
|
|
1207
1562
|
${level}
|
|
1208
1563
|
</wa-dropdown-item>
|
|
@@ -1215,7 +1570,7 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1215
1570
|
<wa-dropdown-item
|
|
1216
1571
|
value=${`approval:${option.value}`}
|
|
1217
1572
|
type="checkbox"
|
|
1218
|
-
|
|
1573
|
+
.checked=${this.approvalMode === option.value}
|
|
1219
1574
|
>
|
|
1220
1575
|
${option.label}
|
|
1221
1576
|
</wa-dropdown-item>
|
|
@@ -1268,18 +1623,18 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1268
1623
|
return this.renderAssistantMessage(message);
|
|
1269
1624
|
}
|
|
1270
1625
|
renderAssistantMessage(message, opts = {}) {
|
|
1271
|
-
const
|
|
1272
|
-
const techParts = message.parts.filter((p) => p.type !== "text");
|
|
1626
|
+
const { summaryText, techParts } = splitAssistantPresentation(message.parts);
|
|
1273
1627
|
const open = opts.streaming === true || techParts.some((p) => (p.type === "reasoning" || p.type === "tool") && p.status === "streaming");
|
|
1628
|
+
const summaryBubble = summaryText.length ? summaryText.map((p) => this.renderTextPart(p, { markdown: true })) : opts.streaming ? nothing : html`<div class="bubble">${technicalSummary(techParts)}</div>`;
|
|
1274
1629
|
const summary = html`
|
|
1275
1630
|
<div slot="summary" class="msg-summary">
|
|
1276
1631
|
${opts.streaming ? html`
|
|
1277
1632
|
<div class="streaming-meta">
|
|
1278
1633
|
<wa-spinner style="font-size: 0.85rem"></wa-spinner>
|
|
1279
|
-
<span
|
|
1634
|
+
<span>${this.busy ? this.busyStatus : "streaming…"}</span>
|
|
1280
1635
|
</div>
|
|
1281
1636
|
` : nothing}
|
|
1282
|
-
${
|
|
1637
|
+
${summaryBubble}
|
|
1283
1638
|
</div>
|
|
1284
1639
|
`;
|
|
1285
1640
|
if (!techParts.length) return html`
|
|
@@ -1287,10 +1642,10 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1287
1642
|
${opts.streaming ? html`
|
|
1288
1643
|
<div class="streaming-meta">
|
|
1289
1644
|
<wa-spinner style="font-size: 0.85rem"></wa-spinner>
|
|
1290
|
-
<span
|
|
1645
|
+
<span>${this.busy ? this.busyStatus : "streaming…"}</span>
|
|
1291
1646
|
</div>
|
|
1292
1647
|
` : nothing}
|
|
1293
|
-
${
|
|
1648
|
+
${summaryBubble}
|
|
1294
1649
|
${message.id !== "streaming" ? this.renderMessageMeta(message) : nothing}
|
|
1295
1650
|
</div>
|
|
1296
1651
|
`;
|
|
@@ -1316,9 +1671,10 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1316
1671
|
</div>
|
|
1317
1672
|
`;
|
|
1318
1673
|
}
|
|
1319
|
-
renderTextPart(part) {
|
|
1320
|
-
if (part.type
|
|
1321
|
-
return
|
|
1674
|
+
renderTextPart(part, opts = {}) {
|
|
1675
|
+
if (part.type !== "text") return nothing;
|
|
1676
|
+
if (opts.markdown) return html`<div class="bubble markdown">${unsafeHTML(parseMarkdownHtml(part.text))}</div>`;
|
|
1677
|
+
return html`<div class="bubble">${part.text}</div>`;
|
|
1322
1678
|
}
|
|
1323
1679
|
renderTechnicalPart(part) {
|
|
1324
1680
|
if (part.type === "reasoning") return html`
|
|
@@ -1329,13 +1685,20 @@ var DocksCognitiveView = class DocksCognitiveView extends DocksPart {
|
|
|
1329
1685
|
`;
|
|
1330
1686
|
if (part.type === "tool") {
|
|
1331
1687
|
const heading = `${part.name} · ${part.status}${part.durationMs != null ? ` · ${part.durationMs}ms` : ""}`;
|
|
1688
|
+
const hasDetail = part.args != null || part.result != null || part.status === "error";
|
|
1332
1689
|
return html`
|
|
1333
|
-
<div>
|
|
1690
|
+
<div class="tool-row">
|
|
1334
1691
|
<div class="tool-heading">${heading}</div>
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1692
|
+
${hasDetail ? html`
|
|
1693
|
+
<wa-button
|
|
1694
|
+
size="s"
|
|
1695
|
+
appearance="plain"
|
|
1696
|
+
variant="neutral"
|
|
1697
|
+
@click=${() => this.openToolDetail(part)}
|
|
1698
|
+
>
|
|
1699
|
+
Details
|
|
1700
|
+
</wa-button>
|
|
1701
|
+
` : nothing}
|
|
1339
1702
|
</div>
|
|
1340
1703
|
`;
|
|
1341
1704
|
}
|
|
@@ -1351,7 +1714,9 @@ _decorate([state()], DocksCognitiveView.prototype, "draft", void 0);
|
|
|
1351
1714
|
_decorate([state()], DocksCognitiveView.prototype, "pendingAttachmentIds", void 0);
|
|
1352
1715
|
_decorate([state()], DocksCognitiveView.prototype, "dragOver", void 0);
|
|
1353
1716
|
_decorate([state()], DocksCognitiveView.prototype, "previewAttachmentId", void 0);
|
|
1717
|
+
_decorate([state()], DocksCognitiveView.prototype, "toolDetail", void 0);
|
|
1354
1718
|
_decorate([state()], DocksCognitiveView.prototype, "busy", void 0);
|
|
1719
|
+
_decorate([state()], DocksCognitiveView.prototype, "busyStatus", void 0);
|
|
1355
1720
|
_decorate([state()], DocksCognitiveView.prototype, "pendingPermission", void 0);
|
|
1356
1721
|
_decorate([state()], DocksCognitiveView.prototype, "policyMode", void 0);
|
|
1357
1722
|
_decorate([state()], DocksCognitiveView.prototype, "optimizeFor", void 0);
|
|
@@ -1364,14 +1729,14 @@ _decorate([state()], DocksCognitiveView.prototype, "historyOpen", void 0);
|
|
|
1364
1729
|
_decorate([state()], DocksCognitiveView.prototype, "historyQuery", void 0);
|
|
1365
1730
|
DocksCognitiveView = _decorate([customElement("docks-cognitive-view")], DocksCognitiveView);
|
|
1366
1731
|
var APPROVAL_OPTIONS$1 = [
|
|
1367
|
-
{
|
|
1368
|
-
value: "manual",
|
|
1369
|
-
label: "Manual"
|
|
1370
|
-
},
|
|
1371
1732
|
{
|
|
1372
1733
|
value: "auto_safe",
|
|
1373
1734
|
label: "Auto-approve non-critical"
|
|
1374
1735
|
},
|
|
1736
|
+
{
|
|
1737
|
+
value: "manual",
|
|
1738
|
+
label: "Manual"
|
|
1739
|
+
},
|
|
1375
1740
|
{
|
|
1376
1741
|
value: "auto_all",
|
|
1377
1742
|
label: "Approve all"
|
|
@@ -1380,15 +1745,64 @@ var APPROVAL_OPTIONS$1 = [
|
|
|
1380
1745
|
function capitalize(value) {
|
|
1381
1746
|
return value ? value[0].toUpperCase() + value.slice(1) : value;
|
|
1382
1747
|
}
|
|
1748
|
+
/** Basename used when saving an attachment into a workspace folder. */
|
|
1749
|
+
function attachmentSaveFileName(attachment) {
|
|
1750
|
+
const fromName = attachment.name.trim().split(/[/\\]/).pop()?.trim();
|
|
1751
|
+
if (fromName) return fromName;
|
|
1752
|
+
const fromPath = attachment.path?.split(/[/\\]/).pop()?.trim();
|
|
1753
|
+
if (fromPath) return fromPath;
|
|
1754
|
+
if (attachment.kind === "image") return attachment.mime === "image/jpeg" ? "attachment.jpg" : "attachment.png";
|
|
1755
|
+
return "attachment.txt";
|
|
1756
|
+
}
|
|
1757
|
+
/** `photo.png` → `photo (1).png`, `photo (2).png`, … when the path is taken. */
|
|
1758
|
+
function withNumericSuffix(fileName, n) {
|
|
1759
|
+
const dot = fileName.lastIndexOf(".");
|
|
1760
|
+
if (dot > 0) return `${fileName.slice(0, dot)} (${n})${fileName.slice(dot)}`;
|
|
1761
|
+
return `${fileName} (${n})`;
|
|
1762
|
+
}
|
|
1763
|
+
async function uniqueWorkspaceFileName(workspace, parentPath, fileName) {
|
|
1764
|
+
const candidatePath = (name) => `${parentPath}/${name}`;
|
|
1765
|
+
if (!await workspace.getResource(candidatePath(fileName))) return fileName;
|
|
1766
|
+
for (let n = 1; n < 1e4; n++) {
|
|
1767
|
+
const next = withNumericSuffix(fileName, n);
|
|
1768
|
+
if (!await workspace.getResource(candidatePath(next))) return next;
|
|
1769
|
+
}
|
|
1770
|
+
return withNumericSuffix(fileName, Date.now());
|
|
1771
|
+
}
|
|
1772
|
+
/**
|
|
1773
|
+
* Prefer text after the last tool/reasoning as the visible reply.
|
|
1774
|
+
* Interim narration stays out of the bubble — tool details cover the execution trail.
|
|
1775
|
+
*/
|
|
1776
|
+
function splitAssistantPresentation(parts) {
|
|
1777
|
+
const techParts = parts.filter((p) => p.type !== "text");
|
|
1778
|
+
let lastTechIndex = -1;
|
|
1779
|
+
for (let i = 0; i < parts.length; i++) if (parts[i].type !== "text") lastTechIndex = i;
|
|
1780
|
+
if (lastTechIndex < 0) return {
|
|
1781
|
+
summaryText: parts.filter((p) => p.type === "text"),
|
|
1782
|
+
techParts
|
|
1783
|
+
};
|
|
1784
|
+
const afterTools = parts.slice(lastTechIndex + 1).filter((p) => p.type === "text").filter((p) => p.text.trim());
|
|
1785
|
+
if (afterTools.length) return {
|
|
1786
|
+
summaryText: afterTools,
|
|
1787
|
+
techParts
|
|
1788
|
+
};
|
|
1789
|
+
return {
|
|
1790
|
+
summaryText: [],
|
|
1791
|
+
techParts
|
|
1792
|
+
};
|
|
1793
|
+
}
|
|
1383
1794
|
function technicalSummary(parts) {
|
|
1384
1795
|
const tools = parts.filter((p) => p.type === "tool");
|
|
1385
|
-
const
|
|
1386
|
-
const
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1796
|
+
const done = tools.filter((t) => t.status === "done").length;
|
|
1797
|
+
const errors = tools.filter((t) => t.status === "error").length;
|
|
1798
|
+
if (!tools.length) {
|
|
1799
|
+
if (parts.some((p) => p.type === "reasoning")) return "Thinking…";
|
|
1800
|
+
return "Details";
|
|
1801
|
+
}
|
|
1802
|
+
if (errors && done) return `Finished with ${errors} issue${errors === 1 ? "" : "s"} (${done} ok).`;
|
|
1803
|
+
if (errors) return `Couldn't complete ${errors} step${errors === 1 ? "" : "s"}.`;
|
|
1804
|
+
if (tools.some((t) => t.status === "running" || t.status === "preparing")) return "Working…";
|
|
1805
|
+
return done === 1 ? "Done." : `Done · ${done} steps.`;
|
|
1392
1806
|
}
|
|
1393
1807
|
function startOfDay(ts) {
|
|
1394
1808
|
const d = new Date(ts);
|
|
@@ -1463,6 +1877,29 @@ function shortModelLabel(modelRef) {
|
|
|
1463
1877
|
const slash = modelRef.indexOf("/");
|
|
1464
1878
|
return slash === -1 ? modelRef : modelRef.slice(slash + 1);
|
|
1465
1879
|
}
|
|
1880
|
+
function filesFromClipboard(data) {
|
|
1881
|
+
if (!data) return [];
|
|
1882
|
+
const fromFiles = [...data.files ?? []].filter((f) => f && f.size > 0);
|
|
1883
|
+
if (fromFiles.length) return fromFiles;
|
|
1884
|
+
const fromItems = [];
|
|
1885
|
+
for (const item of data.items ?? []) {
|
|
1886
|
+
if (item.kind !== "file") continue;
|
|
1887
|
+
const file = item.getAsFile();
|
|
1888
|
+
if (!file || file.size <= 0) continue;
|
|
1889
|
+
fromItems.push(nameClipboardFile(file, item.type));
|
|
1890
|
+
}
|
|
1891
|
+
return fromItems;
|
|
1892
|
+
}
|
|
1893
|
+
function nameClipboardFile(file, mimeHint) {
|
|
1894
|
+
const mime = (file.type || mimeHint || "application/octet-stream").toLowerCase();
|
|
1895
|
+
if (file.name && file.name !== "image.png" && file.name !== "blob") return file;
|
|
1896
|
+
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";
|
|
1897
|
+
const name = `clipboard-${Date.now()}.${ext}`;
|
|
1898
|
+
return new File([file], name, {
|
|
1899
|
+
type: mime || file.type,
|
|
1900
|
+
lastModified: file.lastModified
|
|
1901
|
+
});
|
|
1902
|
+
}
|
|
1466
1903
|
function mergePart(parts, part) {
|
|
1467
1904
|
const next = [...parts];
|
|
1468
1905
|
const last = next[next.length - 1];
|
|
@@ -1491,16 +1928,16 @@ function mergePart(parts, part) {
|
|
|
1491
1928
|
//#endregion
|
|
1492
1929
|
//#region src/view/cognitive-settings-editor.ts
|
|
1493
1930
|
var APPROVAL_OPTIONS = [
|
|
1494
|
-
{
|
|
1495
|
-
value: "manual",
|
|
1496
|
-
label: "Manual",
|
|
1497
|
-
hint: "Confirm every tool before it runs"
|
|
1498
|
-
},
|
|
1499
1931
|
{
|
|
1500
1932
|
value: "auto_safe",
|
|
1501
1933
|
label: "Auto-approve non-critical",
|
|
1502
1934
|
hint: "The agent classifies each tool as safe or critical; only critical ones ask for approval"
|
|
1503
1935
|
},
|
|
1936
|
+
{
|
|
1937
|
+
value: "manual",
|
|
1938
|
+
label: "Manual",
|
|
1939
|
+
hint: "Confirm every tool before it runs"
|
|
1940
|
+
},
|
|
1504
1941
|
{
|
|
1505
1942
|
value: "auto_all",
|
|
1506
1943
|
label: "Approve all",
|
|
@@ -1711,59 +2148,15 @@ var DocksCognitiveSettingsEditor = class DocksCognitiveSettingsEditor extends Do
|
|
|
1711
2148
|
toastError(err instanceof Error ? err.message : String(err));
|
|
1712
2149
|
}
|
|
1713
2150
|
}
|
|
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
2151
|
renderContent() {
|
|
1731
2152
|
const rows = this.settings.providers;
|
|
1732
2153
|
return html`
|
|
1733
2154
|
<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
2155
|
<section class="section">
|
|
1763
2156
|
<header class="header">
|
|
1764
2157
|
<div>
|
|
1765
2158
|
<h2>AI Providers</h2>
|
|
1766
|
-
<p class="hint">OpenAI-compatible endpoints. Edit cells in place, then
|
|
2159
|
+
<p class="hint">OpenAI-compatible endpoints. Edit cells in place, then save from the toolbar.</p>
|
|
1767
2160
|
</div>
|
|
1768
2161
|
<wa-button size="s" variant="brand" appearance="filled" @click=${() => this.addProvider()}>
|
|
1769
2162
|
<wa-icon slot="start" name="plus"></wa-icon>
|
|
@@ -1798,6 +2191,34 @@ var DocksCognitiveSettingsEditor = class DocksCognitiveSettingsEditor extends Do
|
|
|
1798
2191
|
<code>providerId/modelId</code> for Auto routing.
|
|
1799
2192
|
</wa-callout>
|
|
1800
2193
|
</section>
|
|
2194
|
+
|
|
2195
|
+
<section class="section">
|
|
2196
|
+
<header class="header">
|
|
2197
|
+
<div>
|
|
2198
|
+
<h2>Tool approvals</h2>
|
|
2199
|
+
<p class="hint">How the agent handles tool confirmation — same options as GitHub Copilot.</p>
|
|
2200
|
+
</div>
|
|
2201
|
+
</header>
|
|
2202
|
+
<wa-radio-group
|
|
2203
|
+
name="approval-mode"
|
|
2204
|
+
label="Approval mode"
|
|
2205
|
+
orientation="vertical"
|
|
2206
|
+
.value=${this.approvalMode}
|
|
2207
|
+
@change=${(e) => {
|
|
2208
|
+
const value = e.target.value;
|
|
2209
|
+
if (value === "manual" || value === "auto_safe" || value === "auto_all") this.setApprovalMode(value);
|
|
2210
|
+
}}
|
|
2211
|
+
>
|
|
2212
|
+
${APPROVAL_OPTIONS.map((option) => html`
|
|
2213
|
+
<wa-radio value=${option.value}>
|
|
2214
|
+
<span class="approval-option">
|
|
2215
|
+
<span class="approval-label">${option.label}</span>
|
|
2216
|
+
<span class="approval-hint">${option.hint}</span>
|
|
2217
|
+
</span>
|
|
2218
|
+
</wa-radio>
|
|
2219
|
+
`)}
|
|
2220
|
+
</wa-radio-group>
|
|
2221
|
+
</section>
|
|
1801
2222
|
</div>
|
|
1802
2223
|
`;
|
|
1803
2224
|
}
|
|
@@ -2088,6 +2509,7 @@ function uniqueProviderId(existing) {
|
|
|
2088
2509
|
//#endregion
|
|
2089
2510
|
//#region src/cognitive-extension.ts
|
|
2090
2511
|
cognitiveRuntime.start();
|
|
2512
|
+
registerSkillCommands();
|
|
2091
2513
|
rootContext.put("cognitiveRuntime", cognitiveRuntime);
|
|
2092
2514
|
contributionRegistry.registerContribution(SIDEBAR_AUXILIARY, {
|
|
2093
2515
|
name: AI_VIEW_NAME,
|
|
@@ -2126,4 +2548,4 @@ registerAll({
|
|
|
2126
2548
|
});
|
|
2127
2549
|
//#endregion
|
|
2128
2550
|
|
|
2129
|
-
//# sourceMappingURL=cognitive-extension-
|
|
2551
|
+
//# sourceMappingURL=cognitive-extension-BKGxwLYj.js.map
|