create-walle 0.9.13 → 0.9.15
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 +8 -3
- package/bin/create-walle.js +232 -32
- package/bin/mcp-inject.js +18 -53
- package/package.json +3 -1
- package/template/claude-task-manager/api-prompts.js +11 -2
- package/template/claude-task-manager/approval-agent.js +7 -0
- package/template/claude-task-manager/db.js +94 -75
- package/template/claude-task-manager/docs/session-standup-command-center-design.md +242 -0
- package/template/claude-task-manager/docs/session-tooltip-freshness-design.md +224 -0
- package/template/claude-task-manager/docs/session-ux-issue-review-2026-05-01.md +369 -0
- package/template/claude-task-manager/fuzzy-utils.js +10 -2
- package/template/claude-task-manager/git-utils.js +140 -10
- package/template/claude-task-manager/lib/agent-capabilities.js +1 -1
- package/template/claude-task-manager/lib/agent-presets.js +38 -5
- package/template/claude-task-manager/lib/codex-terminal-final.js +53 -0
- package/template/claude-task-manager/lib/ctm-session-context-api.js +222 -0
- package/template/claude-task-manager/lib/session-diagnostics.js +56 -0
- package/template/claude-task-manager/lib/session-history.js +309 -16
- package/template/claude-task-manager/lib/session-standup.js +409 -0
- package/template/claude-task-manager/lib/session-stream.js +253 -20
- package/template/claude-task-manager/lib/standup-attention.js +200 -0
- package/template/claude-task-manager/lib/status-hooks.js +8 -2
- package/template/claude-task-manager/lib/update-telemetry.js +114 -0
- package/template/claude-task-manager/lib/walle-ctm-history.js +49 -6
- package/template/claude-task-manager/lib/walle-default-model.js +55 -0
- package/template/claude-task-manager/lib/walle-mcp-auto-config.js +66 -0
- package/template/claude-task-manager/lib/walle-supervisor.js +86 -19
- package/template/claude-task-manager/lib/walle-transcript.js +1 -3
- package/template/claude-task-manager/lib/worktree-cwd.js +82 -0
- package/template/claude-task-manager/package.json +1 -0
- package/template/claude-task-manager/providers/codex-mcp.js +104 -0
- package/template/claude-task-manager/providers/index.js +2 -0
- package/template/claude-task-manager/public/css/setup.css +2 -1
- package/template/claude-task-manager/public/css/walle.css +71 -0
- package/template/claude-task-manager/public/index.html +2388 -429
- package/template/claude-task-manager/public/js/message-renderer.js +314 -35
- package/template/claude-task-manager/public/js/session-search-utils.js +185 -3
- package/template/claude-task-manager/public/js/session-status-precedence.js +125 -0
- package/template/claude-task-manager/public/js/setup.js +62 -19
- package/template/claude-task-manager/public/js/stream-view.js +396 -55
- package/template/claude-task-manager/public/js/terminal-restore-state.js +57 -0
- package/template/claude-task-manager/public/js/walle-session.js +234 -26
- package/template/claude-task-manager/public/js/walle.js +143 -2
- package/template/claude-task-manager/server.js +1402 -433
- package/template/claude-task-manager/session-integrity.js +77 -28
- package/template/claude-task-manager/workers/approval-widget-validator.js +15 -5
- package/template/claude-task-manager/workers/scrollback-worker.js +5 -6
- package/template/claude-task-manager/workers/state-detectors/codex.js +6 -0
- package/template/package.json +1 -1
- package/template/wall-e/agent-runners/claude-code.js +2 -0
- package/template/wall-e/agent.js +63 -8
- package/template/wall-e/api-walle.js +330 -52
- package/template/wall-e/brain.js +291 -42
- package/template/wall-e/chat.js +172 -15
- package/template/wall-e/coding/compaction-service.js +19 -5
- package/template/wall-e/coding/stream-processor.js +22 -2
- package/template/wall-e/coding/workspace-replay.js +1 -4
- package/template/wall-e/coding-orchestrator.js +250 -80
- package/template/wall-e/compat.js +0 -28
- package/template/wall-e/context/context-builder.js +3 -1
- package/template/wall-e/embeddings.js +2 -7
- package/template/wall-e/eval/agent-runner.js +30 -9
- package/template/wall-e/eval/benchmark-generator.js +21 -1
- package/template/wall-e/eval/benchmarks/chat-eval.json +66 -6
- package/template/wall-e/eval/benchmarks/coding-agent.json +0 -596
- package/template/wall-e/eval/cc-replay.js +1 -0
- package/template/wall-e/eval/codex-cli-baseline.js +633 -0
- package/template/wall-e/eval/debug-agent003.js +1 -0
- package/template/wall-e/eval/eval-orchestrator.js +3 -3
- package/template/wall-e/eval/run-agent-benchmarks.js +11 -3
- package/template/wall-e/eval/run-codex-cli-baseline.js +177 -0
- package/template/wall-e/eval/run-model-comparison.js +1 -0
- package/template/wall-e/eval/swebench-adapter.js +1 -0
- package/template/wall-e/evaluation/quorum-evaluator.js +0 -1
- package/template/wall-e/extraction/knowledge-extractor.js +1 -2
- package/template/wall-e/lib/mcp-integration.js +336 -0
- package/template/wall-e/llm/ollama.js +47 -8
- package/template/wall-e/llm/ollama.plugin.json +1 -1
- package/template/wall-e/llm/tool-adapter.js +1 -0
- package/template/wall-e/loops/ingest.js +42 -8
- package/template/wall-e/loops/initiative.js +87 -2
- package/template/wall-e/mcp-server.js +872 -19
- package/template/wall-e/memory/ctm-context-client.js +230 -0
- package/template/wall-e/memory/ctm-session-context.js +1376 -0
- package/template/wall-e/prompts/coding/memory-protocol.md +6 -0
- package/template/wall-e/server.js +30 -1
- package/template/wall-e/skills/_bundled/memory-search/SKILL.md +8 -0
- package/template/wall-e/skills/_bundled/scan-ctm-sessions/SKILL.md +20 -0
- package/template/wall-e/skills/_bundled/scan-ctm-sessions/run.js +43 -0
- package/template/wall-e/skills/_bundled/slack-mentions/run.js +471 -188
- package/template/wall-e/skills/skill-planner.js +86 -4
- package/template/wall-e/slack/socket-mode-listener.js +276 -0
- package/template/wall-e/telemetry.js +70 -2
- package/template/wall-e/tools/builtin-middleware.js +55 -2
- package/template/wall-e/tools/shell-policy.js +1 -1
- package/template/wall-e/tools/slack-owner.js +104 -0
- package/template/website/index.html +4 -4
- package/template/builder-journal.md +0 -17
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
(function initTerminalRestoreState(root, factory) {
|
|
4
|
+
if (typeof module === 'object' && module.exports) {
|
|
5
|
+
module.exports = factory();
|
|
6
|
+
} else {
|
|
7
|
+
root.TerminalRestoreState = factory();
|
|
8
|
+
}
|
|
9
|
+
})(typeof globalThis !== 'undefined' ? globalThis : this, function buildTerminalRestoreState() {
|
|
10
|
+
const STATES = Object.freeze({
|
|
11
|
+
INACTIVE: 'inactive',
|
|
12
|
+
ACTIVATING: 'activating',
|
|
13
|
+
RESTORE_SAVED: 'restore_saved',
|
|
14
|
+
RESTORE_SNAPSHOT: 'restore_snapshot',
|
|
15
|
+
WAIT_FRESH_SNAPSHOT: 'wait_fresh_snapshot',
|
|
16
|
+
ATTACHING: 'attaching',
|
|
17
|
+
SNAPSHOT_REQUESTED: 'snapshot_requested',
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
function shouldShowInitialOverlay({ hasTerminal, canRestoreExitedText, hasCachedSnapshot, shouldRestoreSavedText }) {
|
|
21
|
+
return Boolean(hasTerminal && !canRestoreExitedText && !hasCachedSnapshot && !shouldRestoreSavedText);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function activationRestoreDecision({
|
|
25
|
+
canRestoreExitedText,
|
|
26
|
+
shouldRestoreSavedText,
|
|
27
|
+
hasCachedSnapshot,
|
|
28
|
+
cachedSnapshotDimsMatch,
|
|
29
|
+
} = {}) {
|
|
30
|
+
if (canRestoreExitedText) {
|
|
31
|
+
return { state: STATES.RESTORE_SAVED, action: 'restore-saved-scrollback', reason: 'exited-saved-scrollback' };
|
|
32
|
+
}
|
|
33
|
+
if (shouldRestoreSavedText) {
|
|
34
|
+
return { state: STATES.RESTORE_SAVED, action: 'restore-saved-scrollback', reason: 'snapshot-shorter-than-saved' };
|
|
35
|
+
}
|
|
36
|
+
if (hasCachedSnapshot && cachedSnapshotDimsMatch) {
|
|
37
|
+
return { state: STATES.RESTORE_SNAPSHOT, action: 'restore-cached-snapshot', reason: 'cached-dims-match' };
|
|
38
|
+
}
|
|
39
|
+
if (hasCachedSnapshot && !cachedSnapshotDimsMatch) {
|
|
40
|
+
return { state: STATES.WAIT_FRESH_SNAPSHOT, action: 'show-loading-overlay', reason: 'cached-dims-mismatch' };
|
|
41
|
+
}
|
|
42
|
+
return { state: STATES.WAIT_FRESH_SNAPSHOT, action: 'wait-fresh-snapshot', reason: 'no-local-restore' };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function activationRequestDecision({ needsAttach } = {}) {
|
|
46
|
+
return needsAttach
|
|
47
|
+
? { state: STATES.ATTACHING, messageType: 'attach', clearStaleQueue: true, reason: 'needs-attach' }
|
|
48
|
+
: { state: STATES.SNAPSHOT_REQUESTED, messageType: 'snapshot', clearStaleQueue: true, reason: 'refresh-snapshot' };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
STATES,
|
|
53
|
+
shouldShowInitialOverlay,
|
|
54
|
+
activationRestoreDecision,
|
|
55
|
+
activationRequestDecision,
|
|
56
|
+
};
|
|
57
|
+
});
|
|
@@ -7,9 +7,18 @@ window.WalleSession = (function() {
|
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
9
|
// ---------- state helper ----------
|
|
10
|
+
function initialModelFromSession(s) {
|
|
11
|
+
var meta = (s && s.meta) || {};
|
|
12
|
+
return {
|
|
13
|
+
model: meta.model_registry_id || meta.modelRegistryId || meta.model_id || '',
|
|
14
|
+
provider: meta.model_provider ? providerLabel(meta.model_provider) : '',
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
|
|
10
18
|
function getState(id) {
|
|
11
19
|
var s = state.sessions.get(id);
|
|
12
20
|
if (!s) return null;
|
|
21
|
+
var initialModel = initialModelFromSession(s);
|
|
13
22
|
if (!s.walleState) {
|
|
14
23
|
s.walleState = {
|
|
15
24
|
messages: [],
|
|
@@ -17,16 +26,28 @@ window.WalleSession = (function() {
|
|
|
17
26
|
totalCost: 0,
|
|
18
27
|
totalTokens: 0,
|
|
19
28
|
messageCount: 0,
|
|
20
|
-
selectedModel:
|
|
29
|
+
selectedModel: initialModel.model,
|
|
21
30
|
selectedModelLabel: '',
|
|
22
|
-
selectedModelProvider:
|
|
23
|
-
_currentAssistant: null
|
|
31
|
+
selectedModelProvider: initialModel.provider,
|
|
32
|
+
_currentAssistant: null,
|
|
33
|
+
_modelHydrated: true,
|
|
34
|
+
_modelManual: false,
|
|
35
|
+
promptNavIdx: -1
|
|
24
36
|
};
|
|
37
|
+
} else if (!s.walleState._modelHydrated) {
|
|
38
|
+
s.walleState.selectedModel = s.walleState.selectedModel || initialModel.model;
|
|
39
|
+
s.walleState.selectedModelProvider = s.walleState.selectedModelProvider || initialModel.provider;
|
|
40
|
+
s.walleState._modelHydrated = true;
|
|
41
|
+
} else if (initialModel.model && !s.walleState.selectedModel && !s.walleState._modelManual) {
|
|
42
|
+
s.walleState.selectedModel = initialModel.model;
|
|
43
|
+
s.walleState.selectedModelProvider = s.walleState.selectedModelProvider || initialModel.provider;
|
|
25
44
|
}
|
|
45
|
+
if (typeof s.walleState.promptNavIdx !== 'number') s.walleState.promptNavIdx = -1;
|
|
26
46
|
return s.walleState;
|
|
27
47
|
}
|
|
28
48
|
|
|
29
49
|
var _walleModelRegistryCache = null;
|
|
50
|
+
var _walleModelRegistryLoaded = false;
|
|
30
51
|
var _walleModelRegistryPromise = null;
|
|
31
52
|
var _walleModelPicker = null;
|
|
32
53
|
|
|
@@ -163,17 +184,31 @@ window.WalleSession = (function() {
|
|
|
163
184
|
var toolbarModelBtn = createModelPickerButton(id, 'toolbar');
|
|
164
185
|
toolbar.appendChild(toolbarModelBtn);
|
|
165
186
|
|
|
166
|
-
//
|
|
187
|
+
// Prompt navigation for user messages (shares terminal prompt-nav styling)
|
|
167
188
|
var msgNav = document.createElement('div');
|
|
168
|
-
msgNav.className = 'prompt-nav';
|
|
189
|
+
msgNav.className = 'prompt-nav walle-prompt-nav';
|
|
190
|
+
msgNav.id = 'walle-prompt-nav-' + id;
|
|
169
191
|
msgNav.style.position = 'relative';
|
|
192
|
+
var prevBtn = document.createElement('button');
|
|
193
|
+
prevBtn.className = 'prompt-nav-btn';
|
|
194
|
+
prevBtn.dataset.dir = 'prev';
|
|
195
|
+
prevBtn.title = 'Previous prompt (Alt+\u2191)';
|
|
196
|
+
prevBtn.innerHTML = '▲';
|
|
197
|
+
prevBtn.onclick = function() { promptNavGo(id, -1); };
|
|
198
|
+
msgNav.appendChild(prevBtn);
|
|
170
199
|
var msgBadge = document.createElement('span');
|
|
171
200
|
msgBadge.className = 'prompt-nav-badge';
|
|
172
201
|
msgBadge.id = 'walle-msg-badge-' + id;
|
|
173
|
-
msgBadge.title = '
|
|
174
|
-
|
|
175
|
-
msgBadge.textContent = '\u26A0 ' + (ws0 ? ws0.messageCount : 0) + ' messages';
|
|
202
|
+
msgBadge.title = 'Click to see all prompts';
|
|
203
|
+
msgBadge.onclick = function() { promptNavToggleList(id); };
|
|
176
204
|
msgNav.appendChild(msgBadge);
|
|
205
|
+
var nextBtn = document.createElement('button');
|
|
206
|
+
nextBtn.className = 'prompt-nav-btn';
|
|
207
|
+
nextBtn.dataset.dir = 'next';
|
|
208
|
+
nextBtn.title = 'Next prompt (Alt+\u2193)';
|
|
209
|
+
nextBtn.innerHTML = '▼';
|
|
210
|
+
nextBtn.onclick = function() { promptNavGo(id, 1); };
|
|
211
|
+
msgNav.appendChild(nextBtn);
|
|
177
212
|
toolbar.appendChild(msgNav);
|
|
178
213
|
|
|
179
214
|
// Review action button (rightmost)
|
|
@@ -260,6 +295,8 @@ window.WalleSession = (function() {
|
|
|
260
295
|
for (var i = 0; i < ws.messages.length; i++) {
|
|
261
296
|
renderMessage(messagesArea, ws.messages[i]);
|
|
262
297
|
}
|
|
298
|
+
syncPromptMessageDomIndices(id);
|
|
299
|
+
updatePromptNav(id);
|
|
263
300
|
scrollToBottom(messagesArea);
|
|
264
301
|
|
|
265
302
|
loadWalleModels().then(function() { syncWalleModelButtons(id); }).catch(function() {});
|
|
@@ -269,6 +306,7 @@ window.WalleSession = (function() {
|
|
|
269
306
|
function renderMessage(container, msg) {
|
|
270
307
|
var el = document.createElement('div');
|
|
271
308
|
el.className = 'walle-msg';
|
|
309
|
+
el.dataset.walleRole = msg.role || '';
|
|
272
310
|
|
|
273
311
|
var avatar = document.createElement('div');
|
|
274
312
|
avatar.className = 'walle-msg-avatar ' + (msg.role === 'user' ? 'user' : 'assistant');
|
|
@@ -464,6 +502,7 @@ window.WalleSession = (function() {
|
|
|
464
502
|
|
|
465
503
|
var ws = getState(id);
|
|
466
504
|
if (!ws) return;
|
|
505
|
+
if (ws.isGenerating) return;
|
|
467
506
|
|
|
468
507
|
var msg = { role: 'user', content: text, timestamp: Date.now() };
|
|
469
508
|
ws.messages.push(msg);
|
|
@@ -472,12 +511,18 @@ window.WalleSession = (function() {
|
|
|
472
511
|
var messagesArea = document.getElementById('walle-messages-' + id);
|
|
473
512
|
if (messagesArea) {
|
|
474
513
|
renderMessage(messagesArea, msg);
|
|
514
|
+
syncPromptMessageDomIndices(id);
|
|
515
|
+
updatePromptNav(id);
|
|
475
516
|
scrollToBottom(messagesArea);
|
|
476
517
|
}
|
|
477
518
|
|
|
478
|
-
// Send via WebSocket (include model
|
|
519
|
+
// Send via WebSocket (include model/provider when the session is pinned)
|
|
479
520
|
var model = ws.selectedModel || '';
|
|
480
|
-
|
|
521
|
+
var modelItem = findModelItem(model);
|
|
522
|
+
var session = state.sessions.get(id);
|
|
523
|
+
var meta = (session && session.meta) || {};
|
|
524
|
+
var provider = modelItem ? modelItem.provider : (model && model === meta.model_id ? (meta.model_provider || '') : '');
|
|
525
|
+
send({ type: 'walle-message', id: id, text: text, model: model, provider: provider, contextSessionId: resolveContextSessionId(id) });
|
|
481
526
|
|
|
482
527
|
// Clear input
|
|
483
528
|
textarea.value = '';
|
|
@@ -600,6 +645,8 @@ window.WalleSession = (function() {
|
|
|
600
645
|
ws.isGenerating = false;
|
|
601
646
|
|
|
602
647
|
renderMessage(messagesArea, assistantMsg);
|
|
648
|
+
syncPromptMessageDomIndices(id);
|
|
649
|
+
updatePromptNav(id);
|
|
603
650
|
scrollToBottom(messagesArea);
|
|
604
651
|
updateSendButton(id, false);
|
|
605
652
|
updateHeaderStats(id);
|
|
@@ -611,6 +658,12 @@ window.WalleSession = (function() {
|
|
|
611
658
|
var ws = getState(id);
|
|
612
659
|
if (!ws) return;
|
|
613
660
|
|
|
661
|
+
var session = state.sessions.get(id);
|
|
662
|
+
if (session) {
|
|
663
|
+
session.needsAttach = false;
|
|
664
|
+
session._walleHistoryRequested = true;
|
|
665
|
+
}
|
|
666
|
+
|
|
614
667
|
ws.messages = [];
|
|
615
668
|
ws.messageCount = 0;
|
|
616
669
|
ws.totalCost = 0;
|
|
@@ -635,6 +688,7 @@ window.WalleSession = (function() {
|
|
|
635
688
|
if (document.getElementById('walle-session-' + id)) {
|
|
636
689
|
renderSession(id);
|
|
637
690
|
}
|
|
691
|
+
updatePromptNav(id);
|
|
638
692
|
}
|
|
639
693
|
|
|
640
694
|
// ---------- handleError ----------
|
|
@@ -736,18 +790,31 @@ window.WalleSession = (function() {
|
|
|
736
790
|
}
|
|
737
791
|
|
|
738
792
|
// ---------- model picker ----------
|
|
793
|
+
function invalidateWalleModelCache() {
|
|
794
|
+
_walleModelRegistryCache = null;
|
|
795
|
+
_walleModelRegistryLoaded = false;
|
|
796
|
+
}
|
|
797
|
+
|
|
739
798
|
function loadWalleModels() {
|
|
740
|
-
if (
|
|
799
|
+
if (_walleModelRegistryLoaded && Array.isArray(_walleModelRegistryCache)) {
|
|
800
|
+
return Promise.resolve(_walleModelRegistryCache);
|
|
801
|
+
}
|
|
741
802
|
if (_walleModelRegistryPromise) return _walleModelRegistryPromise;
|
|
742
|
-
_walleModelRegistryPromise = fetch('/api/models/registry')
|
|
743
|
-
.then(function(r) {
|
|
803
|
+
_walleModelRegistryPromise = fetch('/api/models/registry', { cache: 'no-store' })
|
|
804
|
+
.then(function(r) {
|
|
805
|
+
if (!r.ok) throw new Error('HTTP ' + r.status);
|
|
806
|
+
return r.json();
|
|
807
|
+
})
|
|
744
808
|
.then(function(data) {
|
|
745
|
-
|
|
809
|
+
if (data && data.error) throw new Error(data.error);
|
|
810
|
+
var rows = Array.isArray(data) ? data : (Array.isArray(data?.models) ? data.models : []);
|
|
811
|
+
_walleModelRegistryCache = normalizeWalleModels(rows);
|
|
812
|
+
_walleModelRegistryLoaded = true;
|
|
746
813
|
return _walleModelRegistryCache;
|
|
747
814
|
})
|
|
748
815
|
.catch(function() {
|
|
749
|
-
|
|
750
|
-
return
|
|
816
|
+
invalidateWalleModelCache();
|
|
817
|
+
return [];
|
|
751
818
|
})
|
|
752
819
|
.finally(function() {
|
|
753
820
|
_walleModelRegistryPromise = null;
|
|
@@ -898,8 +965,10 @@ window.WalleSession = (function() {
|
|
|
898
965
|
|
|
899
966
|
function findModelItem(modelId) {
|
|
900
967
|
if (!_walleModelRegistryCache || !modelId) return null;
|
|
968
|
+
var id = String(modelId);
|
|
901
969
|
for (var i = 0; i < _walleModelRegistryCache.length; i++) {
|
|
902
|
-
|
|
970
|
+
var item = _walleModelRegistryCache[i];
|
|
971
|
+
if (item.id === id || item.modelId === id) return item;
|
|
903
972
|
}
|
|
904
973
|
return null;
|
|
905
974
|
}
|
|
@@ -910,6 +979,7 @@ window.WalleSession = (function() {
|
|
|
910
979
|
ws.selectedModel = item ? item.id : '';
|
|
911
980
|
ws.selectedModelLabel = item ? item.baseLabel : '';
|
|
912
981
|
ws.selectedModelProvider = item ? item.providerLabel : '';
|
|
982
|
+
ws._modelManual = true;
|
|
913
983
|
syncWalleModelButtons(id);
|
|
914
984
|
closeModelPicker();
|
|
915
985
|
}
|
|
@@ -962,7 +1032,7 @@ window.WalleSession = (function() {
|
|
|
962
1032
|
popover.appendChild(footer);
|
|
963
1033
|
|
|
964
1034
|
var showLegacy = false;
|
|
965
|
-
var models = _walleModelRegistryCache || [];
|
|
1035
|
+
var models = _walleModelRegistryLoaded ? (_walleModelRegistryCache || []) : [];
|
|
966
1036
|
|
|
967
1037
|
function makeSection(titleText) {
|
|
968
1038
|
var title = document.createElement('div');
|
|
@@ -1026,7 +1096,7 @@ window.WalleSession = (function() {
|
|
|
1026
1096
|
|
|
1027
1097
|
function renderList() {
|
|
1028
1098
|
while (body.firstChild) body.removeChild(body.firstChild);
|
|
1029
|
-
if (!models.length && !
|
|
1099
|
+
if (!models.length && !_walleModelRegistryLoaded) {
|
|
1030
1100
|
renderLoading();
|
|
1031
1101
|
return;
|
|
1032
1102
|
}
|
|
@@ -1090,7 +1160,7 @@ window.WalleSession = (function() {
|
|
|
1090
1160
|
}
|
|
1091
1161
|
});
|
|
1092
1162
|
|
|
1093
|
-
if (
|
|
1163
|
+
if (_walleModelRegistryLoaded) {
|
|
1094
1164
|
renderList();
|
|
1095
1165
|
} else {
|
|
1096
1166
|
renderLoading();
|
|
@@ -1143,6 +1213,128 @@ window.WalleSession = (function() {
|
|
|
1143
1213
|
});
|
|
1144
1214
|
}
|
|
1145
1215
|
|
|
1216
|
+
// ---------- prompt navigation ----------
|
|
1217
|
+
function getPromptEntries(ws) {
|
|
1218
|
+
var prompts = [];
|
|
1219
|
+
var messages = (ws && ws.messages) || [];
|
|
1220
|
+
for (var i = 0; i < messages.length; i++) {
|
|
1221
|
+
var m = messages[i];
|
|
1222
|
+
if (!m || m.role !== 'user') continue;
|
|
1223
|
+
prompts.push({ messageIndex: i, content: m.content || '', timestamp: m.timestamp || 0 });
|
|
1224
|
+
}
|
|
1225
|
+
return prompts;
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
function promptPreview(text) {
|
|
1229
|
+
if (typeof _extractPromptPreview === 'function') {
|
|
1230
|
+
var extracted = _extractPromptPreview(text);
|
|
1231
|
+
if (extracted) return extracted;
|
|
1232
|
+
}
|
|
1233
|
+
var line = String(text || '').split('\n').map(function(s) { return s.trim(); }).filter(Boolean)[0] || '';
|
|
1234
|
+
return line || '(empty prompt)';
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
function syncPromptMessageDomIndices(id) {
|
|
1238
|
+
var area = document.getElementById('walle-messages-' + id);
|
|
1239
|
+
if (!area) return;
|
|
1240
|
+
var nodes = area.querySelectorAll('.walle-msg[data-walle-role="user"]');
|
|
1241
|
+
for (var i = 0; i < nodes.length; i++) {
|
|
1242
|
+
nodes[i].dataset.wallePromptIdx = String(i);
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
function updatePromptNav(id) {
|
|
1247
|
+
var ws = getState(id);
|
|
1248
|
+
if (!ws) return;
|
|
1249
|
+
var nav = document.getElementById('walle-prompt-nav-' + id);
|
|
1250
|
+
if (!nav) return;
|
|
1251
|
+
var prompts = getPromptEntries(ws);
|
|
1252
|
+
var total = prompts.length;
|
|
1253
|
+
if (ws.promptNavIdx >= total) ws.promptNavIdx = -1;
|
|
1254
|
+
var badge = nav.querySelector('.prompt-nav-badge');
|
|
1255
|
+
var prevBtn = nav.querySelector('[data-dir="prev"]');
|
|
1256
|
+
var nextBtn = nav.querySelector('[data-dir="next"]');
|
|
1257
|
+
if (badge) {
|
|
1258
|
+
badge.textContent = total === 0
|
|
1259
|
+
? '0 prompts'
|
|
1260
|
+
: (ws.promptNavIdx >= 0 ? (ws.promptNavIdx + 1) + '/' + total : total + (total === 1 ? ' prompt' : ' prompts'));
|
|
1261
|
+
}
|
|
1262
|
+
if (prevBtn) prevBtn.disabled = total === 0;
|
|
1263
|
+
if (nextBtn) nextBtn.disabled = total === 0;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
function jumpToPrompt(id, idx) {
|
|
1267
|
+
var ws = getState(id);
|
|
1268
|
+
if (!ws) return false;
|
|
1269
|
+
var prompts = getPromptEntries(ws);
|
|
1270
|
+
if (idx < 0 || idx >= prompts.length) return false;
|
|
1271
|
+
syncPromptMessageDomIndices(id);
|
|
1272
|
+
var area = document.getElementById('walle-messages-' + id);
|
|
1273
|
+
if (!area) return false;
|
|
1274
|
+
var target = area.querySelector('.walle-msg[data-walle-prompt-idx="' + idx + '"]');
|
|
1275
|
+
if (!target) return false;
|
|
1276
|
+
ws.promptNavIdx = idx;
|
|
1277
|
+
var top = Math.max(0, target.offsetTop - area.offsetTop - 8);
|
|
1278
|
+
area.scrollTop = top;
|
|
1279
|
+
updatePromptNav(id);
|
|
1280
|
+
return true;
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
function promptNavGo(id, dir) {
|
|
1284
|
+
var ws = getState(id);
|
|
1285
|
+
if (!ws) return;
|
|
1286
|
+
var total = getPromptEntries(ws).length;
|
|
1287
|
+
if (total === 0) return;
|
|
1288
|
+
var idx = ws.promptNavIdx;
|
|
1289
|
+
var next = idx < 0 ? (dir < 0 ? total - 1 : 0) : idx + dir;
|
|
1290
|
+
if (next < 0 || next >= total) return;
|
|
1291
|
+
jumpToPrompt(id, next);
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1294
|
+
function promptNavToggleList(id) {
|
|
1295
|
+
var ws = getState(id);
|
|
1296
|
+
if (!ws) return;
|
|
1297
|
+
var nav = document.getElementById('walle-prompt-nav-' + id);
|
|
1298
|
+
if (!nav) return;
|
|
1299
|
+
var existing = nav.querySelector('.prompt-nav-list');
|
|
1300
|
+
if (existing) { existing.remove(); return; }
|
|
1301
|
+
var prompts = getPromptEntries(ws);
|
|
1302
|
+
if (prompts.length === 0) return;
|
|
1303
|
+
|
|
1304
|
+
var list = document.createElement('div');
|
|
1305
|
+
list.className = 'prompt-nav-list';
|
|
1306
|
+
list.addEventListener('wheel', function(e) { e.stopPropagation(); }, { passive: false });
|
|
1307
|
+
var seen = {};
|
|
1308
|
+
for (var i = prompts.length - 1; i >= 0; i--) {
|
|
1309
|
+
var text = promptPreview(prompts[i].content);
|
|
1310
|
+
var fullText = text;
|
|
1311
|
+
if (text.length > 80) text = text.slice(0, 80) + '\u2026';
|
|
1312
|
+
if (seen[text]) continue;
|
|
1313
|
+
seen[text] = true;
|
|
1314
|
+
var item = document.createElement('div');
|
|
1315
|
+
item.className = 'prompt-nav-list-item' + (i === ws.promptNavIdx ? ' current' : '');
|
|
1316
|
+
item.textContent = text;
|
|
1317
|
+
item.title = fullText;
|
|
1318
|
+
item.onclick = (function(idx) { return function() {
|
|
1319
|
+
if (jumpToPrompt(id, idx)) list.remove();
|
|
1320
|
+
}; })(i);
|
|
1321
|
+
list.appendChild(item);
|
|
1322
|
+
}
|
|
1323
|
+
nav.appendChild(list);
|
|
1324
|
+
|
|
1325
|
+
setTimeout(function() {
|
|
1326
|
+
function close(e) {
|
|
1327
|
+
if (!list.contains(e.target)) {
|
|
1328
|
+
list.remove();
|
|
1329
|
+
document.removeEventListener('click', close);
|
|
1330
|
+
document.removeEventListener('mousedown', close);
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
document.addEventListener('click', close);
|
|
1334
|
+
document.addEventListener('mousedown', close);
|
|
1335
|
+
}, 0);
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1146
1338
|
// ---------- helpers ----------
|
|
1147
1339
|
function scrollToBottom(el) {
|
|
1148
1340
|
if (el) {
|
|
@@ -1232,11 +1424,22 @@ window.WalleSession = (function() {
|
|
|
1232
1424
|
costEl.textContent = '$' + ws.totalCost.toFixed(2);
|
|
1233
1425
|
}
|
|
1234
1426
|
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1427
|
+
updatePromptNav(id);
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
function handleModel(msg) {
|
|
1431
|
+
var id = msg.id;
|
|
1432
|
+
var s = state.sessions.get(id);
|
|
1433
|
+
if (!s) return;
|
|
1434
|
+
s.meta = s.meta || {};
|
|
1435
|
+
if (msg.model_id) s.meta.model_id = msg.model_id;
|
|
1436
|
+
if (msg.model_provider) s.meta.model_provider = msg.model_provider;
|
|
1437
|
+
var ws = getState(id);
|
|
1438
|
+
if (!ws || ws._modelManual || !msg.model_id) return;
|
|
1439
|
+
ws.selectedModel = msg.model_id;
|
|
1440
|
+
ws.selectedModelLabel = '';
|
|
1441
|
+
ws.selectedModelProvider = msg.model_provider ? providerLabel(msg.model_provider) : ws.selectedModelProvider;
|
|
1442
|
+
syncWalleModelButtons(id);
|
|
1240
1443
|
}
|
|
1241
1444
|
|
|
1242
1445
|
// ---------- public API ----------
|
|
@@ -1248,6 +1451,11 @@ window.WalleSession = (function() {
|
|
|
1248
1451
|
handleResponse: handleResponse,
|
|
1249
1452
|
handleHistory: handleHistory,
|
|
1250
1453
|
handleError: handleError,
|
|
1251
|
-
|
|
1454
|
+
handleModel: handleModel,
|
|
1455
|
+
promptNavGo: promptNavGo,
|
|
1456
|
+
promptNavToggleList: promptNavToggleList,
|
|
1457
|
+
updatePromptNav: updatePromptNav,
|
|
1458
|
+
populateWalleModelSelector: populateWalleModelSelector,
|
|
1459
|
+
invalidateModelCache: invalidateWalleModelCache
|
|
1252
1460
|
};
|
|
1253
1461
|
})();
|
|
@@ -2045,6 +2045,7 @@ function renderChatUI() {
|
|
|
2045
2045
|
html += '</div>'; // container
|
|
2046
2046
|
|
|
2047
2047
|
safeSetHtml(body, html);
|
|
2048
|
+
renderServiceAlerts(_serviceAlerts);
|
|
2048
2049
|
|
|
2049
2050
|
// Update elapsed timer if processing
|
|
2050
2051
|
if (chatThinkingState.isProcessing && chatThinkingState.startTime) {
|
|
@@ -6095,10 +6096,13 @@ checkProviderStatus();
|
|
|
6095
6096
|
// ---------------------------------------------------------------------------
|
|
6096
6097
|
|
|
6097
6098
|
var _alertsPollTimer = null;
|
|
6099
|
+
var _serviceAlerts = [];
|
|
6100
|
+
var _updatePromptShownVersions = {};
|
|
6098
6101
|
|
|
6099
6102
|
function checkServiceAlerts() {
|
|
6100
6103
|
api('/alerts').then(function(d) {
|
|
6101
6104
|
var alerts = d.alerts || [];
|
|
6105
|
+
_serviceAlerts = alerts;
|
|
6102
6106
|
var providerIssue = null;
|
|
6103
6107
|
for (var i = 0; i < alerts.length; i++) {
|
|
6104
6108
|
var issue = _normalizeProviderIssue(alerts[i]);
|
|
@@ -6109,6 +6113,7 @@ function checkServiceAlerts() {
|
|
|
6109
6113
|
if (currentView === 'chat') renderChatUI();
|
|
6110
6114
|
}
|
|
6111
6115
|
renderServiceAlerts(alerts);
|
|
6116
|
+
maybeShowUpdateWizard(alerts);
|
|
6112
6117
|
clearTimeout(_alertsPollTimer);
|
|
6113
6118
|
_alertsPollTimer = setTimeout(checkServiceAlerts, 60000);
|
|
6114
6119
|
}).catch(function() {
|
|
@@ -6130,8 +6135,14 @@ function renderServiceAlerts(alerts) {
|
|
|
6130
6135
|
var safeId = esc(a.id).replace(/'/g, ''');
|
|
6131
6136
|
var dismissBtn = '<button class="we-service-alert-dismiss" onclick="WE._dismissAlert(\'' + safeId + '\')" title="Dismiss">×</button>';
|
|
6132
6137
|
var actionBtn = '';
|
|
6133
|
-
|
|
6134
|
-
|
|
6138
|
+
var actionLabel = esc(a.action_label || 'Fix');
|
|
6139
|
+
if (a.action === 'repair_slack_owner') {
|
|
6140
|
+
var actionName = esc(a.action || 'custom').replace(/'/g, ''');
|
|
6141
|
+
actionBtn = ' <button class="we-service-alert-action" onclick="WE._runAlertAction(\'' + safeId + '\', \'' + actionName + '\')">' + actionLabel + '</button>';
|
|
6142
|
+
} else if (a.action === 'show_update_wizard') {
|
|
6143
|
+
actionBtn = ' <button class="we-service-alert-action" onclick="WE._showUpdateWizardFromAlert(\'' + safeId + '\')">' + actionLabel + '</button>';
|
|
6144
|
+
} else if (a.action_url && /^(\/|https?:\/\/)/.test(a.action_url)) {
|
|
6145
|
+
actionBtn = ' <a href="' + esc(a.action_url) + '" class="we-service-alert-action">' + actionLabel + '</a>';
|
|
6135
6146
|
}
|
|
6136
6147
|
return '<div class="we-service-alert-item ' + kind + '">'
|
|
6137
6148
|
+ '<span class="we-service-alert-icon">' + icon + '</span>'
|
|
@@ -6150,6 +6161,136 @@ function renderServiceAlerts(alerts) {
|
|
|
6150
6161
|
}
|
|
6151
6162
|
}
|
|
6152
6163
|
|
|
6164
|
+
function _findUpdateAlert(alerts) {
|
|
6165
|
+
alerts = alerts || _serviceAlerts || [];
|
|
6166
|
+
for (var i = 0; i < alerts.length; i++) {
|
|
6167
|
+
if (alerts[i] && alerts[i].type === 'update_available') return alerts[i];
|
|
6168
|
+
}
|
|
6169
|
+
return null;
|
|
6170
|
+
}
|
|
6171
|
+
|
|
6172
|
+
function maybeShowUpdateWizard(alerts) {
|
|
6173
|
+
var alert = _findUpdateAlert(alerts);
|
|
6174
|
+
if (!alert) return;
|
|
6175
|
+
var version = alert.latest || 'unknown';
|
|
6176
|
+
if (_updatePromptShownVersions[version]) return;
|
|
6177
|
+
var key = 'walle:updatePrompt:' + version;
|
|
6178
|
+
try {
|
|
6179
|
+
if (window.localStorage && localStorage.getItem(key)) return;
|
|
6180
|
+
if (window.localStorage) localStorage.setItem(key, 'shown');
|
|
6181
|
+
} catch {}
|
|
6182
|
+
_updatePromptShownVersions[version] = true;
|
|
6183
|
+
showUpdateWizard(alert, { automatic: true });
|
|
6184
|
+
WE._trackUpgradePrompt('shown');
|
|
6185
|
+
}
|
|
6186
|
+
|
|
6187
|
+
function copyTextToClipboard(text) {
|
|
6188
|
+
if (navigator.clipboard && navigator.clipboard.writeText) {
|
|
6189
|
+
return navigator.clipboard.writeText(text);
|
|
6190
|
+
}
|
|
6191
|
+
var ta = document.createElement('textarea');
|
|
6192
|
+
ta.value = text;
|
|
6193
|
+
ta.style.position = 'fixed';
|
|
6194
|
+
ta.style.left = '-9999px';
|
|
6195
|
+
document.body.appendChild(ta);
|
|
6196
|
+
ta.select();
|
|
6197
|
+
try { document.execCommand('copy'); } finally { ta.remove(); }
|
|
6198
|
+
return Promise.resolve();
|
|
6199
|
+
}
|
|
6200
|
+
|
|
6201
|
+
function showUpdateWizard(alert, opts) {
|
|
6202
|
+
opts = opts || {};
|
|
6203
|
+
var existing = document.getElementById('we-update-wizard');
|
|
6204
|
+
if (existing) existing.remove();
|
|
6205
|
+
var command = 'npx create-walle@latest update';
|
|
6206
|
+
var overlay = document.createElement('div');
|
|
6207
|
+
overlay.id = 'we-update-wizard';
|
|
6208
|
+
overlay.className = 'we-update-wizard-overlay';
|
|
6209
|
+
overlay.innerHTML = ''
|
|
6210
|
+
+ '<div class="we-update-wizard" role="dialog" aria-modal="true" aria-labelledby="we-update-title">'
|
|
6211
|
+
+ '<button class="we-update-wizard-close" type="button" aria-label="Close">×</button>'
|
|
6212
|
+
+ '<div class="we-update-wizard-kicker">Update available</div>'
|
|
6213
|
+
+ '<h3 id="we-update-title">Update CTM / Wall-E</h3>'
|
|
6214
|
+
+ '<p>Version <strong>' + esc(alert.latest || 'latest') + '</strong> is available. You are running <strong>' + esc(alert.current || 'unknown') + '</strong>.</p>'
|
|
6215
|
+
+ '<div class="we-update-command">' + esc(command) + '</div>'
|
|
6216
|
+
+ '<div class="we-update-wizard-actions">'
|
|
6217
|
+
+ '<button class="btn primary we-update-copy" type="button">Copy Command</button>'
|
|
6218
|
+
+ '<button class="btn we-update-later" type="button">Later</button>'
|
|
6219
|
+
+ '<button class="btn danger we-update-dismiss" type="button">Dismiss</button>'
|
|
6220
|
+
+ '</div>'
|
|
6221
|
+
+ '</div>';
|
|
6222
|
+
document.body.appendChild(overlay);
|
|
6223
|
+
|
|
6224
|
+
var close = function(action) {
|
|
6225
|
+
overlay.remove();
|
|
6226
|
+
if (action) WE._trackUpgradePrompt(action);
|
|
6227
|
+
};
|
|
6228
|
+
overlay.addEventListener('click', function(e) {
|
|
6229
|
+
if (e.target === overlay) close('later');
|
|
6230
|
+
});
|
|
6231
|
+
overlay.querySelector('.we-update-wizard-close').addEventListener('click', function() { close('later'); });
|
|
6232
|
+
overlay.querySelector('.we-update-later').addEventListener('click', function() { close('later'); });
|
|
6233
|
+
overlay.querySelector('.we-update-dismiss').addEventListener('click', function() {
|
|
6234
|
+
WE._dismissAlert(alert.id || 'version_update');
|
|
6235
|
+
close();
|
|
6236
|
+
});
|
|
6237
|
+
overlay.querySelector('.we-update-copy').addEventListener('click', function(e) {
|
|
6238
|
+
var btn = e.currentTarget;
|
|
6239
|
+
copyTextToClipboard(command).then(function() {
|
|
6240
|
+
btn.textContent = 'Copied';
|
|
6241
|
+
WE._trackUpgradePrompt('copy_command');
|
|
6242
|
+
if (typeof showToast === 'function') showToast('Update command copied', 'var(--green, #9ece6a)', 1800);
|
|
6243
|
+
}).catch(function() {
|
|
6244
|
+
btn.textContent = command;
|
|
6245
|
+
});
|
|
6246
|
+
});
|
|
6247
|
+
}
|
|
6248
|
+
|
|
6249
|
+
WE._showUpdateWizardFromAlert = function(alertId) {
|
|
6250
|
+
var alert = null;
|
|
6251
|
+
for (var i = 0; i < _serviceAlerts.length; i++) {
|
|
6252
|
+
if (String(_serviceAlerts[i].id) === String(alertId)) alert = _serviceAlerts[i];
|
|
6253
|
+
}
|
|
6254
|
+
showUpdateWizard(alert || _findUpdateAlert(_serviceAlerts) || { id: 'version_update' }, { automatic: false });
|
|
6255
|
+
WE._trackUpgradePrompt('shown');
|
|
6256
|
+
};
|
|
6257
|
+
|
|
6258
|
+
WE._trackUpgradePrompt = function(action) {
|
|
6259
|
+
resolveWalleBase().then(function() {
|
|
6260
|
+
var token = window._ctmState?.token || '';
|
|
6261
|
+
fetch(WALLE_BASE + '/api/wall-e/update/prompt-event?token=' + encodeURIComponent(token), {
|
|
6262
|
+
method: 'POST',
|
|
6263
|
+
headers: { 'Content-Type': 'application/json' },
|
|
6264
|
+
body: JSON.stringify({ action: action })
|
|
6265
|
+
}).catch(function() {});
|
|
6266
|
+
}).catch(function() {});
|
|
6267
|
+
};
|
|
6268
|
+
|
|
6269
|
+
WE._runAlertAction = function(alertId, actionName) {
|
|
6270
|
+
if (actionName !== 'repair_slack_owner') return;
|
|
6271
|
+
resolveWalleBase().then(function() {
|
|
6272
|
+
var token = window._ctmState?.token || '';
|
|
6273
|
+
fetch(WALLE_BASE + '/api/wall-e/slack/repair-owner?token=' + encodeURIComponent(token), { method: 'POST' })
|
|
6274
|
+
.then(function(r) { return r.json().then(function(d) { return { ok: r.ok, data: d }; }); })
|
|
6275
|
+
.then(function(result) {
|
|
6276
|
+
if (result.ok && result.data && result.data.ok) {
|
|
6277
|
+
if (typeof showToast === 'function') showToast('Slack sync fixed automatically', 'var(--green, #9ece6a)', 2500);
|
|
6278
|
+
checkServiceAlerts();
|
|
6279
|
+
return;
|
|
6280
|
+
}
|
|
6281
|
+
var msg = (result.data && result.data.error) || 'Could not fix Slack sync automatically';
|
|
6282
|
+
if (result.data && result.data.needsSlackAuth) {
|
|
6283
|
+
if (typeof navTo === 'function') navTo('setup');
|
|
6284
|
+
msg = 'Connect Slack first, then Wall-E can finish setup automatically.';
|
|
6285
|
+
}
|
|
6286
|
+
if (typeof showToast === 'function') showToast(msg, 'var(--red, #f7768e)', 3500);
|
|
6287
|
+
})
|
|
6288
|
+
.catch(function(e) {
|
|
6289
|
+
if (typeof showToast === 'function') showToast(e.message, 'var(--red, #f7768e)', 3500);
|
|
6290
|
+
});
|
|
6291
|
+
});
|
|
6292
|
+
};
|
|
6293
|
+
|
|
6153
6294
|
WE._dismissAlert = function(alertId) {
|
|
6154
6295
|
resolveWalleBase().then(function() {
|
|
6155
6296
|
var token = window._ctmState?.token || '';
|