create-walle 0.9.16 → 0.9.17
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/package.json +1 -1
- package/template/bin/github-polish.sh +10 -3
- package/template/claude-task-manager/lib/codex-terminal-final.js +77 -0
- package/template/claude-task-manager/lib/session-standup.js +138 -7
- package/template/claude-task-manager/public/css/prompts.css +28 -0
- package/template/claude-task-manager/public/css/walle-session.css +12 -1
- package/template/claude-task-manager/public/index.html +71 -13
- package/template/claude-task-manager/public/js/walle-session.js +98 -26
- package/template/claude-task-manager/server.js +86 -13
- package/template/docs/site/astro.config.mjs +0 -3
- package/template/docs/site/src/content/docs/index.mdx +2 -2
- package/template/package.json +1 -1
- package/template/wall-e/eval/benchmarks/chat-eval.json +1 -1
- package/template/wall-e/http/model-admin.js +19 -0
- package/template/wall-e/llm/anthropic.js +25 -10
- package/template/wall-e/llm/coding-availability.js +248 -0
- package/template/wall-e/llm/deepseek.js +5 -3
- package/template/wall-e/llm/google.js +6 -4
- package/template/wall-e/llm/openai.js +5 -3
- package/template/wall-e/skills/_bundled/gws-workspace/setup.js +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-walle",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.17",
|
|
4
4
|
"description": "CTM + Wall-E \u2014 AI coding dashboard and personal digital twin agent. Multi-agent terminal for Claude Code, Codex, Gemini, Aider, OpenCode, and more, plus prompt editor, task queue, and an agent that learns from Slack, email & calendar.",
|
|
5
5
|
"bin": {
|
|
6
6
|
"create-walle": "bin/create-walle.js"
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
# Run this after authenticating gh
|
|
2
|
+
# Run this after authenticating gh for the repository owner account:
|
|
3
3
|
# gh auth login
|
|
4
4
|
# Or manually set these in GitHub Settings > General
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
if [ -z "${WALLE_GITHUB_REPO:-}" ]; then
|
|
7
|
+
echo "Set WALLE_GITHUB_REPO=owner/repo before running this script."
|
|
8
|
+
exit 1
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
REPO="$WALLE_GITHUB_REPO"
|
|
12
|
+
|
|
13
|
+
gh repo edit "$REPO" \
|
|
7
14
|
--description "Wall-E — your personal digital twin. AI agent that learns from Slack, email & calendar. Includes CTM dashboard." \
|
|
8
15
|
--homepage "https://walle.sh" \
|
|
9
16
|
--add-topic "ai" \
|
|
@@ -15,4 +22,4 @@ gh repo edit ShanniLi/tools \
|
|
|
15
22
|
--add-topic "nodejs"
|
|
16
23
|
|
|
17
24
|
echo "Done. Set social preview image manually at:"
|
|
18
|
-
echo " https://github.com/
|
|
25
|
+
echo " https://github.com/${REPO}/settings"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const crypto = require('crypto');
|
|
4
|
+
const fs = require('fs');
|
|
4
5
|
|
|
5
6
|
function stripAnsi(text) {
|
|
6
7
|
return String(text || '')
|
|
@@ -45,8 +46,84 @@ function fingerprintFinalText(text) {
|
|
|
45
46
|
return crypto.createHash('sha1').update(String(text || '')).digest('hex').slice(0, 16);
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
function _codexAssistantOutputText(content) {
|
|
50
|
+
if (!Array.isArray(content)) return '';
|
|
51
|
+
return content
|
|
52
|
+
.filter((block) => block && block.type === 'output_text' && block.text)
|
|
53
|
+
.map((block) => block.text)
|
|
54
|
+
.join('\n')
|
|
55
|
+
.trim();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function codexFinalTextFromEntry(entry) {
|
|
59
|
+
if (!entry || typeof entry !== 'object') return null;
|
|
60
|
+
if (entry.type === 'event_msg' && entry.payload?.type === 'task_complete') {
|
|
61
|
+
const text = String(entry.payload.last_agent_message || '').trim();
|
|
62
|
+
if (text) {
|
|
63
|
+
return {
|
|
64
|
+
text,
|
|
65
|
+
timestamp: entry.timestamp || entry.payload.timestamp || '',
|
|
66
|
+
source: 'task_complete',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (entry.type === 'response_item' && entry.payload?.type === 'message' && entry.payload.role === 'assistant') {
|
|
71
|
+
const text = _codexAssistantOutputText(entry.payload.content);
|
|
72
|
+
if (text) {
|
|
73
|
+
return {
|
|
74
|
+
text,
|
|
75
|
+
timestamp: entry.timestamp || '',
|
|
76
|
+
source: 'assistant_message',
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function latestCodexFinalTextFromJsonlText(text) {
|
|
84
|
+
const lines = String(text || '').split(/\r?\n/);
|
|
85
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
86
|
+
const line = lines[i];
|
|
87
|
+
if (!line || !line.trim()) continue;
|
|
88
|
+
let entry;
|
|
89
|
+
try { entry = JSON.parse(line); } catch { continue; }
|
|
90
|
+
const final = codexFinalTextFromEntry(entry);
|
|
91
|
+
if (final) return final;
|
|
92
|
+
}
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function latestCodexFinalTextFromJsonlFile(filePath, options = {}) {
|
|
97
|
+
if (!filePath) return null;
|
|
98
|
+
const maxTailBytes = Math.max(1024, Number(options.maxTailBytes || 8 * 1024 * 1024));
|
|
99
|
+
let st;
|
|
100
|
+
try { st = fs.statSync(filePath); } catch { return null; }
|
|
101
|
+
if (!st || !st.isFile() || st.size <= 0) return null;
|
|
102
|
+
const readSize = Math.min(st.size, maxTailBytes);
|
|
103
|
+
const start = st.size - readSize;
|
|
104
|
+
let fd = null;
|
|
105
|
+
try {
|
|
106
|
+
fd = fs.openSync(filePath, 'r');
|
|
107
|
+
const buf = Buffer.alloc(readSize);
|
|
108
|
+
fs.readSync(fd, buf, 0, readSize, start);
|
|
109
|
+
let text = buf.toString('utf8');
|
|
110
|
+
if (start > 0) {
|
|
111
|
+
const firstNewline = text.indexOf('\n');
|
|
112
|
+
if (firstNewline >= 0) text = text.slice(firstNewline + 1);
|
|
113
|
+
}
|
|
114
|
+
return latestCodexFinalTextFromJsonlText(text);
|
|
115
|
+
} catch {
|
|
116
|
+
return null;
|
|
117
|
+
} finally {
|
|
118
|
+
try { if (fd != null) fs.closeSync(fd); } catch {}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
48
122
|
module.exports = {
|
|
123
|
+
codexFinalTextFromEntry,
|
|
49
124
|
fingerprintFinalText,
|
|
125
|
+
latestCodexFinalTextFromJsonlFile,
|
|
126
|
+
latestCodexFinalTextFromJsonlText,
|
|
50
127
|
markerForFinalText,
|
|
51
128
|
normalizeForTerminalSearch,
|
|
52
129
|
terminalContainsFinalText,
|
|
@@ -48,11 +48,127 @@ function progressText(progress) {
|
|
|
48
48
|
if (!progress) return '';
|
|
49
49
|
if (typeof progress === 'string') return progress;
|
|
50
50
|
if (typeof progress === 'object') {
|
|
51
|
-
|
|
51
|
+
if (progress.summary) return progress.summary;
|
|
52
|
+
if (Array.isArray(progress.bullets) && progress.bullets.length) {
|
|
53
|
+
return progress.bullets.filter(Boolean).slice(-1)[0] || '';
|
|
54
|
+
}
|
|
55
|
+
return progress.next || progress.phase || '';
|
|
52
56
|
}
|
|
53
57
|
return String(progress);
|
|
54
58
|
}
|
|
55
59
|
|
|
60
|
+
function sourceForValue(value, fallback = '') {
|
|
61
|
+
return value && typeof value === 'object' && value.source
|
|
62
|
+
? String(value.source)
|
|
63
|
+
: fallback;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function freshnessForValue(value, fallback = '') {
|
|
67
|
+
return value && typeof value === 'object' && value.freshness
|
|
68
|
+
? String(value.freshness)
|
|
69
|
+
: fallback;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function confidenceForValue(value, fallback = '') {
|
|
73
|
+
return value && typeof value === 'object' && value.confidence
|
|
74
|
+
? String(value.confidence)
|
|
75
|
+
: fallback;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function timestampForValue(value) {
|
|
79
|
+
if (!value || typeof value !== 'object') return 0;
|
|
80
|
+
return value.updatedAt || value.timestamp || value.promptTimestamp || value.aiUpdatedAt || 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function goalForSummary(session, summary = {}) {
|
|
84
|
+
const candidates = [
|
|
85
|
+
{
|
|
86
|
+
value: summary?.currentTask,
|
|
87
|
+
source: sourceForValue(summary?.currentTask, 'current-task'),
|
|
88
|
+
freshness: freshnessForValue(summary?.currentTask, ''),
|
|
89
|
+
confidence: confidenceForValue(summary?.currentTask, ''),
|
|
90
|
+
updatedAt: timestampForValue(summary?.currentTask),
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
value: summary?.intent,
|
|
94
|
+
source: sourceForValue(summary?.intent, 'intent'),
|
|
95
|
+
freshness: freshnessForValue(summary?.intent, ''),
|
|
96
|
+
confidence: confidenceForValue(summary?.intent, ''),
|
|
97
|
+
updatedAt: timestampForValue(summary?.intent),
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
value: summary?.summary,
|
|
101
|
+
source: summary?.aiSummary?.source || (summary?.summary ? 'ai-summary' : ''),
|
|
102
|
+
freshness: summary?.aiSummary?.status || '',
|
|
103
|
+
confidence: summary?.summary ? 'medium' : '',
|
|
104
|
+
updatedAt: summary?.aiSummary?.updatedAt || 0,
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
value: summary?.displayPrompt,
|
|
108
|
+
source: 'prompt-fallback',
|
|
109
|
+
freshness: 'fallback',
|
|
110
|
+
confidence: 'medium',
|
|
111
|
+
updatedAt: summary?.displayPrompt?.timestamp || summary?.displayPrompt?.updatedAt || 0,
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
value: summary?.lastPrompt,
|
|
115
|
+
source: 'prompt-fallback',
|
|
116
|
+
freshness: 'fallback',
|
|
117
|
+
confidence: 'medium',
|
|
118
|
+
updatedAt: summary?.lastPrompt?.timestamp || summary?.lastPrompt?.updatedAt || 0,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
value: session?.label,
|
|
122
|
+
source: 'title-fallback',
|
|
123
|
+
freshness: 'fallback',
|
|
124
|
+
confidence: 'low',
|
|
125
|
+
updatedAt: session?.lastActivity || session?.modifiedAt || session?.createdAt || 0,
|
|
126
|
+
},
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
for (const candidate of candidates) {
|
|
130
|
+
const text = truncateText(valueText(candidate.value), 170);
|
|
131
|
+
if (!text) continue;
|
|
132
|
+
return {
|
|
133
|
+
text,
|
|
134
|
+
source: candidate.source || 'unknown',
|
|
135
|
+
freshness: candidate.freshness || '',
|
|
136
|
+
confidence: candidate.confidence || '',
|
|
137
|
+
updatedAt: candidate.updatedAt || 0,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
text: '',
|
|
143
|
+
source: 'missing',
|
|
144
|
+
freshness: 'missing',
|
|
145
|
+
confidence: 'low',
|
|
146
|
+
updatedAt: 0,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function progressForSummary(summary = {}) {
|
|
151
|
+
const progress = summary?.progress || '';
|
|
152
|
+
const text = truncateText(progressText(progress), 190);
|
|
153
|
+
if (!progress || typeof progress !== 'object') {
|
|
154
|
+
return {
|
|
155
|
+
text,
|
|
156
|
+
source: progress ? 'text' : 'missing',
|
|
157
|
+
phase: '',
|
|
158
|
+
next: '',
|
|
159
|
+
updatedAt: 0,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
text,
|
|
165
|
+
source: progress.source || (Array.isArray(progress.bullets) && progress.bullets.length ? 'assistant-events' : 'progress'),
|
|
166
|
+
phase: progress.phase || '',
|
|
167
|
+
next: truncateText(progress.next || '', 160),
|
|
168
|
+
updatedAt: progress.updatedAt || 0,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
56
172
|
function toMs(value) {
|
|
57
173
|
if (!value) return 0;
|
|
58
174
|
if (typeof value === 'number' && Number.isFinite(value)) return value;
|
|
@@ -194,7 +310,7 @@ function prependEvidence(evidence, items) {
|
|
|
194
310
|
return out.slice(0, 5);
|
|
195
311
|
}
|
|
196
312
|
|
|
197
|
-
function baseEvidence({ session, status, summary, now, intentText, progress }) {
|
|
313
|
+
function baseEvidence({ session, status, summary, now, intentText, progress, goalSource }) {
|
|
198
314
|
const evidence = [];
|
|
199
315
|
if (status === 'waiting_input') evidence.push('waiting input');
|
|
200
316
|
else if (status === 'waiting') evidence.push('waiting');
|
|
@@ -205,7 +321,9 @@ function baseEvidence({ session, status, summary, now, intentText, progress }) {
|
|
|
205
321
|
if (wtEvidence) evidence.push(wtEvidence);
|
|
206
322
|
const age = ageLabel(now, latestActivity(session, summary));
|
|
207
323
|
if (age) evidence.push(`last activity ${age}`);
|
|
208
|
-
|
|
324
|
+
const promptBacked = [goalSource, summary?.currentTask?.source, summary?.intent?.source]
|
|
325
|
+
.some(source => ['latest-prompt', 'prompt-fallback'].includes(source));
|
|
326
|
+
if (intentText && promptBacked) {
|
|
209
327
|
evidence.push(`prompt: ${truncateText(intentText, 80)}`);
|
|
210
328
|
}
|
|
211
329
|
const progressPhase = progress && typeof progress === 'object' ? progress.phase : '';
|
|
@@ -219,7 +337,11 @@ function latestActivity(session, summary) {
|
|
|
219
337
|
const values = [
|
|
220
338
|
summary?.lastActivity,
|
|
221
339
|
summary?.progress?.updatedAt,
|
|
340
|
+
summary?.currentTask?.updatedAt,
|
|
341
|
+
summary?.currentTask?.timestamp,
|
|
342
|
+
summary?.currentTask?.promptTimestamp,
|
|
222
343
|
summary?.intent?.updatedAt,
|
|
344
|
+
summary?.aiSummary?.updatedAt,
|
|
223
345
|
session?.lastPtyActivity,
|
|
224
346
|
session?.lastActivity,
|
|
225
347
|
session?.modifiedAt,
|
|
@@ -238,10 +360,11 @@ function classifySessionStandup(session, signals = {}, now = Date.now()) {
|
|
|
238
360
|
const summary = signals.summary || {};
|
|
239
361
|
const streamStatus = signals.status || {};
|
|
240
362
|
const status = standupStatusForSession(session, streamStatus, summary);
|
|
241
|
-
const
|
|
242
|
-
const intentString =
|
|
363
|
+
const goal = goalForSummary(session, summary);
|
|
364
|
+
const intentString = goal.text;
|
|
243
365
|
const progress = summary.progress || '';
|
|
244
|
-
const
|
|
366
|
+
const progressInfo = progressForSummary(summary);
|
|
367
|
+
const progressString = progressInfo.text;
|
|
245
368
|
const summaryText = valueText(summary.summary) || intentString;
|
|
246
369
|
const lastActivityMs = latestActivity(session, summary);
|
|
247
370
|
const ageMs = lastActivityMs ? Math.max(0, now - lastActivityMs) : null;
|
|
@@ -304,7 +427,7 @@ function classifySessionStandup(session, signals = {}, now = Date.now()) {
|
|
|
304
427
|
confidence = 'medium';
|
|
305
428
|
}
|
|
306
429
|
|
|
307
|
-
let evidence = baseEvidence({ session, status, summary, now, intentText: intentString, progress });
|
|
430
|
+
let evidence = baseEvidence({ session, status, summary, now, intentText: intentString, progress, goalSource: goal.source });
|
|
308
431
|
if ((failed || warning) && attention?.evidence?.length) {
|
|
309
432
|
evidence = prependEvidence(evidence, attention.evidence);
|
|
310
433
|
}
|
|
@@ -338,7 +461,15 @@ function classifySessionStandup(session, signals = {}, now = Date.now()) {
|
|
|
338
461
|
confidence,
|
|
339
462
|
evidence,
|
|
340
463
|
attention: attention && attention.severity !== 'none' ? attention : null,
|
|
464
|
+
goal: goal.text,
|
|
465
|
+
goalSource: goal.source,
|
|
466
|
+
goalFreshness: goal.freshness,
|
|
467
|
+
goalConfidence: goal.confidence,
|
|
341
468
|
intent: intentString,
|
|
469
|
+
progressSummary: progressString,
|
|
470
|
+
progressSource: progressInfo.source,
|
|
471
|
+
progressPhase: progressInfo.phase,
|
|
472
|
+
progressNext: progressInfo.next,
|
|
342
473
|
progress: progressString,
|
|
343
474
|
lastActivity: toIso(lastActivityMs),
|
|
344
475
|
ageMs,
|
|
@@ -55,6 +55,34 @@
|
|
|
55
55
|
outline: none;
|
|
56
56
|
}
|
|
57
57
|
.sidebar-header input:focus { border-color: var(--accent); }
|
|
58
|
+
.prompt-filter-row {
|
|
59
|
+
display: grid;
|
|
60
|
+
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) 32px 32px 32px;
|
|
61
|
+
gap: 4px;
|
|
62
|
+
align-items: center;
|
|
63
|
+
min-width: 0;
|
|
64
|
+
}
|
|
65
|
+
.prompt-filter-row .prompt-filter-select {
|
|
66
|
+
min-width: 0;
|
|
67
|
+
width: 100%;
|
|
68
|
+
height: 28px;
|
|
69
|
+
}
|
|
70
|
+
.prompt-filter-row .prompt-filter-icon-btn {
|
|
71
|
+
width: 32px;
|
|
72
|
+
min-width: 32px;
|
|
73
|
+
height: 28px;
|
|
74
|
+
padding: 0;
|
|
75
|
+
display: inline-flex;
|
|
76
|
+
align-items: center;
|
|
77
|
+
justify-content: center;
|
|
78
|
+
overflow: hidden;
|
|
79
|
+
flex: 0 0 auto;
|
|
80
|
+
line-height: 1;
|
|
81
|
+
}
|
|
82
|
+
.prompt-filter-row .prompt-create-folder-btn {
|
|
83
|
+
font-size: 15px;
|
|
84
|
+
font-weight: 700;
|
|
85
|
+
}
|
|
58
86
|
.sidebar-header input.ai-active {
|
|
59
87
|
border-color: var(--purple, #bb9af7);
|
|
60
88
|
background: rgba(187, 154, 247, 0.08);
|
|
@@ -288,12 +288,23 @@
|
|
|
288
288
|
.walle-model-footer {
|
|
289
289
|
flex: 0 0 auto;
|
|
290
290
|
display: flex;
|
|
291
|
-
|
|
291
|
+
align-items: center;
|
|
292
|
+
justify-content: space-between;
|
|
293
|
+
gap: 10px;
|
|
292
294
|
padding: 8px 10px;
|
|
293
295
|
border-top: 1px solid #2f354f;
|
|
294
296
|
background: rgba(255,255,255,0.02);
|
|
295
297
|
}
|
|
298
|
+
.walle-model-source-note {
|
|
299
|
+
min-width: 0;
|
|
300
|
+
color: #8f98c7;
|
|
301
|
+
font-size: 11px;
|
|
302
|
+
overflow: hidden;
|
|
303
|
+
text-overflow: ellipsis;
|
|
304
|
+
white-space: nowrap;
|
|
305
|
+
}
|
|
296
306
|
.walle-model-legacy-toggle {
|
|
307
|
+
flex: 0 0 auto;
|
|
297
308
|
background: transparent;
|
|
298
309
|
color: #8f98c7;
|
|
299
310
|
border: 1px solid #3b4261;
|
|
@@ -2477,6 +2477,42 @@
|
|
|
2477
2477
|
color: var(--fg);
|
|
2478
2478
|
font-weight: 600;
|
|
2479
2479
|
}
|
|
2480
|
+
.standup-card-signals {
|
|
2481
|
+
display: flex;
|
|
2482
|
+
flex-direction: column;
|
|
2483
|
+
gap: 6px;
|
|
2484
|
+
min-width: 0;
|
|
2485
|
+
}
|
|
2486
|
+
.standup-card-line {
|
|
2487
|
+
display: grid;
|
|
2488
|
+
grid-template-columns: 58px minmax(0, 1fr);
|
|
2489
|
+
gap: 8px;
|
|
2490
|
+
align-items: start;
|
|
2491
|
+
min-width: 0;
|
|
2492
|
+
font-size: 12px;
|
|
2493
|
+
line-height: 1.35;
|
|
2494
|
+
}
|
|
2495
|
+
.standup-card-line-label {
|
|
2496
|
+
color: var(--fg-dim);
|
|
2497
|
+
font-size: 10px;
|
|
2498
|
+
font-weight: 700;
|
|
2499
|
+
text-transform: uppercase;
|
|
2500
|
+
letter-spacing: 0;
|
|
2501
|
+
padding-top: 1px;
|
|
2502
|
+
white-space: nowrap;
|
|
2503
|
+
}
|
|
2504
|
+
.standup-card-line-text {
|
|
2505
|
+
color: var(--fg);
|
|
2506
|
+
min-width: 0;
|
|
2507
|
+
overflow-wrap: anywhere;
|
|
2508
|
+
}
|
|
2509
|
+
.standup-card-line.is-muted .standup-card-line-text {
|
|
2510
|
+
color: var(--fg-dim);
|
|
2511
|
+
}
|
|
2512
|
+
.standup-card-recommendation {
|
|
2513
|
+
padding-top: 7px;
|
|
2514
|
+
border-top: 1px solid rgba(255,255,255,0.07);
|
|
2515
|
+
}
|
|
2480
2516
|
.standup-evidence {
|
|
2481
2517
|
display: flex;
|
|
2482
2518
|
flex-wrap: wrap;
|
|
@@ -4324,8 +4360,8 @@ url = "http://localhost:<span id="setup-mcp-port-display-toml">3457</span>/mcp"<
|
|
|
4324
4360
|
<div id="pe-ac-dropdown" style="display:none;position:absolute;top:100%;left:0;right:0;background:var(--bg-light, #24283b);border:1px solid var(--border);border-radius:6px;z-index:200;max-height:250px;overflow-y:auto;box-shadow:0 8px 24px rgba(0,0,0,0.5);"></div>
|
|
4325
4361
|
<button id="pe-ai-search-btn" class="ai-toggle" onclick="PE.toggleAiSearch()" title="AI-powered semantic search">AI</button>
|
|
4326
4362
|
</div>
|
|
4327
|
-
<div
|
|
4328
|
-
<select id="pe-context-filter" onchange="PE.filterPrompts()" style="flex:1;background:var(--bg);color:var(--fg);border:1px solid var(--border);padding:3px 6px;border-radius:4px;font-size:10px;">
|
|
4363
|
+
<div class="prompt-filter-row">
|
|
4364
|
+
<select id="pe-context-filter" class="prompt-filter-select" onchange="PE.filterPrompts()" style="flex:1;background:var(--bg);color:var(--fg);border:1px solid var(--border);padding:3px 6px;border-radius:4px;font-size:10px;">
|
|
4329
4365
|
<option value="">All Domains</option>
|
|
4330
4366
|
<option value="coding">Coding</option>
|
|
4331
4367
|
<option value="ops">Ops & Infra</option>
|
|
@@ -4335,7 +4371,7 @@ url = "http://localhost:<span id="setup-mcp-port-display-toml">3457</span>/mcp"<
|
|
|
4335
4371
|
<option value="meta">Meta / CTM</option>
|
|
4336
4372
|
<option value="general">General</option>
|
|
4337
4373
|
</select>
|
|
4338
|
-
<select id="pe-lifecycle-filter" onchange="PE.filterPrompts()" style="flex:1;background:var(--bg);color:var(--fg);border:1px solid var(--border);padding:3px 6px;border-radius:4px;font-size:10px;">
|
|
4374
|
+
<select id="pe-lifecycle-filter" class="prompt-filter-select" onchange="PE.filterPrompts()" style="flex:1;background:var(--bg);color:var(--fg);border:1px solid var(--border);padding:3px 6px;border-radius:4px;font-size:10px;">
|
|
4339
4375
|
<option value="">All Status</option>
|
|
4340
4376
|
<option value="draft">Draft</option>
|
|
4341
4377
|
<option value="used">Used</option>
|
|
@@ -4343,9 +4379,9 @@ url = "http://localhost:<span id="setup-mcp-port-display-toml">3457</span>/mcp"<
|
|
|
4343
4379
|
<option value="template">Template</option>
|
|
4344
4380
|
<option value="archived">Archived</option>
|
|
4345
4381
|
</select>
|
|
4346
|
-
<button class="btn small" id="pe-star-filter-btn" onclick="PE.filterPrompts('starred')" title="Starred only">★</button>
|
|
4347
|
-
<button class="btn small" id="pe-select-mode-btn" onclick="PE.toggleSelectMode()" title="Select multiple prompts">☐</button>
|
|
4348
|
-
<button class="btn small" onclick="PE.createNewFolder()" title="Create new folder"
|
|
4382
|
+
<button class="btn small prompt-filter-icon-btn" id="pe-star-filter-btn" onclick="PE.filterPrompts('starred')" title="Starred only">★</button>
|
|
4383
|
+
<button class="btn small prompt-filter-icon-btn" id="pe-select-mode-btn" onclick="PE.toggleSelectMode()" title="Select multiple prompts">☐</button>
|
|
4384
|
+
<button class="btn small prompt-filter-icon-btn prompt-create-folder-btn" onclick="PE.createNewFolder()" title="Create new folder" aria-label="Create new folder">+</button>
|
|
4349
4385
|
</div>
|
|
4350
4386
|
</div>
|
|
4351
4387
|
<div id="pe-bulk-bar" style="display:none;padding:6px 8px;background:var(--bg-lighter);border-bottom:1px solid var(--border);display:none;align-items:center;gap:6px;font-size:11px;">
|
|
@@ -4854,6 +4890,11 @@ url = "http://localhost:<span id="setup-mcp-port-display-toml">3457</span>/mcp"<
|
|
|
4854
4890
|
<input type="hidden" id="ns-agent" value="claude:" />
|
|
4855
4891
|
<label>Working Directory</label>
|
|
4856
4892
|
<input id="ns-cwd" type="text" placeholder="~/" onblur="_maybeRecommendWorktreeForNewSession(false)" />
|
|
4893
|
+
<label>Session Title (optional)</label>
|
|
4894
|
+
<input id="ns-label" type="text" placeholder="Auto-generated" />
|
|
4895
|
+
<div style="font-size:11px;color:var(--fg-dim,#565f89);margin:5px 0 10px;">
|
|
4896
|
+
Shown on the tab and sidebar. Rename later by double-clicking the session tab title.
|
|
4897
|
+
</div>
|
|
4857
4898
|
<div id="ns-worktree-row" style="margin-top:8px;display:flex;align-items:center;gap:8px;">
|
|
4858
4899
|
<label style="display:flex;align-items:center;gap:6px;margin:0;cursor:pointer;font-size:13px;color:var(--fg-dim,#a9b1d6);">
|
|
4859
4900
|
<input type="checkbox" id="ns-worktree" style="accent-color:var(--accent,#7aa2f7);width:15px;height:15px;" onchange="toggleWorktreeFields()" />
|
|
@@ -4863,7 +4904,10 @@ url = "http://localhost:<span id="setup-mcp-port-display-toml">3457</span>/mcp"<
|
|
|
4863
4904
|
</div>
|
|
4864
4905
|
<div id="ns-worktree-fields" style="display:none;margin-top:6px;">
|
|
4865
4906
|
<label style="font-size:12px;">Branch Name</label>
|
|
4866
|
-
<input id="ns-worktree-name" type="text" placeholder="Auto-generated from
|
|
4907
|
+
<input id="ns-worktree-name" type="text" placeholder="Auto-generated from session title" style="font-size:13px;" />
|
|
4908
|
+
<div style="font-size:11px;color:var(--fg-dim,#565f89);margin:5px 0 0;">
|
|
4909
|
+
Leave blank to generate a branch-safe name from the session title.
|
|
4910
|
+
</div>
|
|
4867
4911
|
</div>
|
|
4868
4912
|
<div id="ns-custom-fields" style="display:none">
|
|
4869
4913
|
<label>Command</label>
|
|
@@ -4871,8 +4915,6 @@ url = "http://localhost:<span id="setup-mcp-port-display-toml">3457</span>/mcp"<
|
|
|
4871
4915
|
<label>Arguments (comma-separated)</label>
|
|
4872
4916
|
<input id="ns-args" type="text" placeholder="" />
|
|
4873
4917
|
</div>
|
|
4874
|
-
<label>Label (optional)</label>
|
|
4875
|
-
<input id="ns-label" type="text" placeholder="Auto-generated" />
|
|
4876
4918
|
<div class="btn-row">
|
|
4877
4919
|
<button class="btn" onclick="closeModal('new-session-modal')">Cancel</button>
|
|
4878
4920
|
<button class="btn primary" onclick="createSession()">Create</button>
|
|
@@ -7810,11 +7852,27 @@ function renderStandupLane(lane) {
|
|
|
7810
7852
|
`;
|
|
7811
7853
|
}
|
|
7812
7854
|
|
|
7855
|
+
function renderStandupCardLine(label, text, opts) {
|
|
7856
|
+
opts = opts || {};
|
|
7857
|
+
const value = String(text || '').trim();
|
|
7858
|
+
if (!value) return '';
|
|
7859
|
+
const muted = opts.muted ? ' is-muted' : '';
|
|
7860
|
+
return `
|
|
7861
|
+
<div class="standup-card-line${muted}" data-standup-line="${standupEsc(label.toLowerCase())}">
|
|
7862
|
+
<div class="standup-card-line-label">${standupEsc(label)}</div>
|
|
7863
|
+
<div class="standup-card-line-text">${standupEsc(value)}</div>
|
|
7864
|
+
</div>
|
|
7865
|
+
`;
|
|
7866
|
+
}
|
|
7867
|
+
|
|
7813
7868
|
function renderStandupCard(card) {
|
|
7814
7869
|
const subtitle = [card.agent, card.model || card.provider, card.branch].filter(Boolean).join(' / ');
|
|
7815
|
-
const
|
|
7870
|
+
const goal = card.goal || card.intent || '';
|
|
7871
|
+
const progress = card.progressSummary || card.progress || '';
|
|
7816
7872
|
const canReview = card.capabilities && card.capabilities.review;
|
|
7817
7873
|
const chips = (card.evidence || []).map(item => `<span class="standup-chip" title="${standupEsc(item)}">${standupEsc(item)}</span>`).join('');
|
|
7874
|
+
const goalLine = renderStandupCardLine('Goal', goal);
|
|
7875
|
+
const progressLine = renderStandupCardLine('Progress', progress || 'No progress signal yet.', { muted: !progress });
|
|
7818
7876
|
return `
|
|
7819
7877
|
<article class="standup-card">
|
|
7820
7878
|
<div class="standup-card-top">
|
|
@@ -7824,8 +7882,8 @@ function renderStandupCard(card) {
|
|
|
7824
7882
|
</div>
|
|
7825
7883
|
<span class="standup-badge ${standupStatusClass(card.status)}">${standupEsc(card.status || 'unknown')}</span>
|
|
7826
7884
|
</div>
|
|
7827
|
-
|
|
7828
|
-
|
|
7885
|
+
${goalLine || progressLine ? `<div class="standup-card-signals">${goalLine}${progressLine}</div>` : ''}
|
|
7886
|
+
<div class="standup-card-text standup-card-recommendation"><strong>${standupEsc(card.actionLabel || 'Next')}</strong> ${standupEsc(card.recommendation || '')}</div>
|
|
7829
7887
|
${chips ? `<div class="standup-evidence">${chips}</div>` : ''}
|
|
7830
7888
|
<div class="standup-card-actions">
|
|
7831
7889
|
<button class="standup-action-btn primary" type="button" data-standup-action="open" data-session-id="${standupEsc(card.id)}">Open</button>
|
|
@@ -14211,7 +14269,7 @@ function createSession() {
|
|
|
14211
14269
|
if (useWorktree && cwd) {
|
|
14212
14270
|
var wtName = document.getElementById('ns-worktree-name').value.trim();
|
|
14213
14271
|
if (!wtName) {
|
|
14214
|
-
// Auto-generate from
|
|
14272
|
+
// Auto-generate from session title or timestamp
|
|
14215
14273
|
wtName = (label || '').trim().toLowerCase().replace(/[^a-z0-9_-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
|
|
14216
14274
|
if (!wtName) wtName = 'wt-' + Date.now().toString(36);
|
|
14217
14275
|
}
|