@goodandready/dsh-goal 0.2.5 → 0.2.7
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 +13 -0
- package/README.ru.md +7 -0
- package/README.zh.md +7 -0
- package/lib/client.js +539 -135
- package/lib/engine-milestones.js +106 -0
- package/lib/engine-prompt.js +29 -8
- package/lib/engine-reports.js +108 -2
- package/lib/goal-engine-constants.js +116 -0
- package/lib/goal-engine.js +120 -112
- package/lib/index.js +15 -0
- package/lib/routes.js +88 -1
- package/lib/tools.js +19 -3
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -282,6 +282,46 @@ window.__ModuleLoader__.load({
|
|
|
282
282
|
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
function IconMinimize({ size = 14, className = '' }) {
|
|
286
|
+
|
|
287
|
+
return React.createElement(
|
|
288
|
+
|
|
289
|
+
'svg',
|
|
290
|
+
|
|
291
|
+
{
|
|
292
|
+
|
|
293
|
+
width: size,
|
|
294
|
+
|
|
295
|
+
height: size,
|
|
296
|
+
|
|
297
|
+
viewBox: '0 0 24 24',
|
|
298
|
+
|
|
299
|
+
fill: 'none',
|
|
300
|
+
|
|
301
|
+
stroke: 'currentColor',
|
|
302
|
+
|
|
303
|
+
strokeWidth: 1.8,
|
|
304
|
+
|
|
305
|
+
strokeLinecap: 'round',
|
|
306
|
+
|
|
307
|
+
strokeLinejoin: 'round',
|
|
308
|
+
|
|
309
|
+
className,
|
|
310
|
+
|
|
311
|
+
},
|
|
312
|
+
|
|
313
|
+
React.createElement('polyline', { points: '4 14 10 14 10 20' }),
|
|
314
|
+
|
|
315
|
+
React.createElement('polyline', { points: '20 10 14 10 14 4' }),
|
|
316
|
+
|
|
317
|
+
React.createElement('line', { x1: 14, y1: 10, x2: 21, y2: 3 }),
|
|
318
|
+
|
|
319
|
+
React.createElement('line', { x1: 3, y1: 21, x2: 10, y2: 14 }),
|
|
320
|
+
|
|
321
|
+
);
|
|
322
|
+
|
|
323
|
+
}
|
|
324
|
+
|
|
285
325
|
function IconRotateCcw({ size = 13, className = '' }) {
|
|
286
326
|
|
|
287
327
|
return React.createElement(
|
|
@@ -372,6 +412,54 @@ window.__ModuleLoader__.load({
|
|
|
372
412
|
|
|
373
413
|
}
|
|
374
414
|
|
|
415
|
+
.dsh-goal-dock-pill {
|
|
416
|
+
display: inline-flex;
|
|
417
|
+
align-items: center;
|
|
418
|
+
gap: 8px;
|
|
419
|
+
background: var(--dsw-alias-surface-raised);
|
|
420
|
+
border: 1px solid var(--dsw-alias-border-subtle);
|
|
421
|
+
border-radius: 9999px;
|
|
422
|
+
padding: 4px 12px;
|
|
423
|
+
box-shadow: var(--dsw-alias-shadow-md);
|
|
424
|
+
backdrop-filter: blur(8px);
|
|
425
|
+
font-size: 13px;
|
|
426
|
+
max-width: 100%;
|
|
427
|
+
box-sizing: border-box;
|
|
428
|
+
}
|
|
429
|
+
.dsh-goal-dock-pill .dsh-goal-title {
|
|
430
|
+
max-width: 260px;
|
|
431
|
+
white-space: nowrap;
|
|
432
|
+
overflow: hidden;
|
|
433
|
+
text-overflow: ellipsis;
|
|
434
|
+
font-weight: 500;
|
|
435
|
+
}
|
|
436
|
+
.dsh-goal-checklist {
|
|
437
|
+
margin-top: 6px;
|
|
438
|
+
display: flex;
|
|
439
|
+
flex-direction: column;
|
|
440
|
+
gap: 4px;
|
|
441
|
+
}
|
|
442
|
+
.dsh-goal-checklist-item {
|
|
443
|
+
display: flex;
|
|
444
|
+
align-items: center;
|
|
445
|
+
gap: 6px;
|
|
446
|
+
font-size: 12px;
|
|
447
|
+
color: var(--dsw-alias-label-secondary);
|
|
448
|
+
cursor: pointer;
|
|
449
|
+
user-select: none;
|
|
450
|
+
}
|
|
451
|
+
.dsh-goal-checklist-item input[type="checkbox"] {
|
|
452
|
+
cursor: pointer;
|
|
453
|
+
margin: 0;
|
|
454
|
+
}
|
|
455
|
+
.dsh-goal-budget-warn {
|
|
456
|
+
color: var(--dsw-alias-status-warning);
|
|
457
|
+
font-weight: 600;
|
|
458
|
+
display: inline-flex;
|
|
459
|
+
align-items: center;
|
|
460
|
+
gap: 4px;
|
|
461
|
+
font-size: 12px;
|
|
462
|
+
}
|
|
375
463
|
.dsh-goal-dock.dsh-goal-dock-quick {
|
|
376
464
|
|
|
377
465
|
justify-content: flex-start;
|
|
@@ -1646,6 +1734,10 @@ window.__ModuleLoader__.load({
|
|
|
1646
1734
|
|
|
1647
1735
|
const [gitCopied, setGitCopied] = useState(false);
|
|
1648
1736
|
|
|
1737
|
+
const [artifactSaved, setArtifactSaved] = useState(false);
|
|
1738
|
+
|
|
1739
|
+
const [savingArtifact, setSavingArtifact] = useState(false);
|
|
1740
|
+
|
|
1649
1741
|
const [nudgeText, setNudgeText] = useState('');
|
|
1650
1742
|
|
|
1651
1743
|
const [nudgeSent, setNudgeSent] = useState(false);
|
|
@@ -2010,6 +2102,51 @@ window.__ModuleLoader__.load({
|
|
|
2010
2102
|
|
|
2011
2103
|
m.notes ? React.createElement('div', { style: { fontSize: 12, color: 'var(--dsw-alias-label-tertiary)', marginTop: 2 } }, m.notes) : null,
|
|
2012
2104
|
|
|
2105
|
+
Array.isArray(m.checklist) && m.checklist.length > 0
|
|
2106
|
+
? React.createElement(
|
|
2107
|
+
'div',
|
|
2108
|
+
{ className: 'dsh-goal-checklist' },
|
|
2109
|
+
m.checklist.map((item, itemIdx) =>
|
|
2110
|
+
React.createElement(
|
|
2111
|
+
'label',
|
|
2112
|
+
{ key: itemIdx, className: 'dsh-goal-checklist-item' },
|
|
2113
|
+
React.createElement('input', {
|
|
2114
|
+
type: 'checkbox',
|
|
2115
|
+
checked: Boolean(item.done),
|
|
2116
|
+
onChange: () => onAction?.('toggle_checklist_item', { milestoneId: m.id, itemIndex: itemIdx, done: !item.done }),
|
|
2117
|
+
}),
|
|
2118
|
+
React.createElement(
|
|
2119
|
+
'span',
|
|
2120
|
+
{ style: { textDecoration: item.done ? 'line-through' : 'none', color: item.done ? 'var(--dsw-alias-label-tertiary)' : 'inherit' } },
|
|
2121
|
+
item.text
|
|
2122
|
+
)
|
|
2123
|
+
)
|
|
2124
|
+
)
|
|
2125
|
+
)
|
|
2126
|
+
: null,
|
|
2127
|
+
|
|
2128
|
+
m.checkpointCommit
|
|
2129
|
+
? React.createElement(
|
|
2130
|
+
'div',
|
|
2131
|
+
{ style: { marginTop: 4 } },
|
|
2132
|
+
React.createElement(
|
|
2133
|
+
'button',
|
|
2134
|
+
{
|
|
2135
|
+
type: 'button',
|
|
2136
|
+
className: 'dsh-goal-btn-inline-reset',
|
|
2137
|
+
style: { fontSize: 11, padding: '1px 6px' },
|
|
2138
|
+
title: t('rollbackBtn') || 'Rollback to Checkpoint',
|
|
2139
|
+
onClick: () => {
|
|
2140
|
+
if (confirm(t('rollbackConfirm') || `Rollback working tree to checkpoint ${m.checkpointCommit}?`)) {
|
|
2141
|
+
onAction?.('rollback_milestone', { commit: m.checkpointCommit });
|
|
2142
|
+
}
|
|
2143
|
+
},
|
|
2144
|
+
},
|
|
2145
|
+
`↩ ${m.checkpointCommit}`
|
|
2146
|
+
)
|
|
2147
|
+
)
|
|
2148
|
+
: null,
|
|
2149
|
+
|
|
2013
2150
|
),
|
|
2014
2151
|
|
|
2015
2152
|
),
|
|
@@ -2086,6 +2223,28 @@ window.__ModuleLoader__.load({
|
|
|
2086
2223
|
|
|
2087
2224
|
),
|
|
2088
2225
|
|
|
2226
|
+
React.createElement(
|
|
2227
|
+
'button',
|
|
2228
|
+
{
|
|
2229
|
+
className: `dsh-goal-btn dsh-goal-btn-copy${artifactSaved ? ' copied' : ''}`,
|
|
2230
|
+
disabled: savingArtifact,
|
|
2231
|
+
onClick: async () => {
|
|
2232
|
+
setSavingArtifact(true);
|
|
2233
|
+
try {
|
|
2234
|
+
await onAction?.('save_artifact');
|
|
2235
|
+
setArtifactSaved(true);
|
|
2236
|
+
setTimeout(() => setArtifactSaved(false), 3000);
|
|
2237
|
+
} catch (err) {
|
|
2238
|
+
console.warn('[dsh-goal] Save artifact error:', err);
|
|
2239
|
+
} finally {
|
|
2240
|
+
setSavingArtifact(false);
|
|
2241
|
+
}
|
|
2242
|
+
},
|
|
2243
|
+
title: t('saveArtifact') || 'Save Run Artifact to .dsh/goals/',
|
|
2244
|
+
},
|
|
2245
|
+
artifactSaved ? (t('artifactSaved') || '✅ Saved to .dsh/goals/') : (t('saveArtifact') || '💾 Save Run Artifact')
|
|
2246
|
+
),
|
|
2247
|
+
|
|
2089
2248
|
)
|
|
2090
2249
|
|
|
2091
2250
|
: null,
|
|
@@ -2408,6 +2567,26 @@ window.__ModuleLoader__.load({
|
|
|
2408
2567
|
|
|
2409
2568
|
const [isQuickLaunchOpen, setIsQuickLaunchOpen] = useState(false);
|
|
2410
2569
|
|
|
2570
|
+
const [isDockCollapsed, setIsDockCollapsed] = useState(() => {
|
|
2571
|
+
try {
|
|
2572
|
+
return localStorage.getItem('dsh_goal_dock_collapsed') === 'true';
|
|
2573
|
+
} catch (e) {
|
|
2574
|
+
return false;
|
|
2575
|
+
}
|
|
2576
|
+
});
|
|
2577
|
+
|
|
2578
|
+
const toggleDockCollapse = () => {
|
|
2579
|
+
setIsDockCollapsed((prev) => {
|
|
2580
|
+
const next = !prev;
|
|
2581
|
+
try {
|
|
2582
|
+
localStorage.setItem('dsh_goal_dock_collapsed', String(next));
|
|
2583
|
+
} catch (e) {
|
|
2584
|
+
// Handled defensively: localStorage might be unavailable or quota exceeded
|
|
2585
|
+
}
|
|
2586
|
+
return next;
|
|
2587
|
+
});
|
|
2588
|
+
};
|
|
2589
|
+
|
|
2411
2590
|
const [now, setNow] = useState(() => Date.now());
|
|
2412
2591
|
|
|
2413
2592
|
const stateRef = useRef(null);
|
|
@@ -2460,7 +2639,7 @@ window.__ModuleLoader__.load({
|
|
|
2460
2639
|
|
|
2461
2640
|
const active = resolveLocale();
|
|
2462
2641
|
|
|
2463
|
-
return LOCALES[active]?.[key] || LOCALES.en?.[key] ||
|
|
2642
|
+
return LOCALES[active]?.[key] || LOCALES.en?.[key] || key;
|
|
2464
2643
|
|
|
2465
2644
|
};
|
|
2466
2645
|
|
|
@@ -2926,6 +3105,8 @@ window.__ModuleLoader__.load({
|
|
|
2926
3105
|
|
|
2927
3106
|
const etaStr = state?.formattedETA ? ` (ETA ${state.formattedETA})` : '';
|
|
2928
3107
|
|
|
3108
|
+
const isBudgetExceeded = state?.state === 'PAUSED' && state?.logs?.some((l) => l.message?.includes('Token budget reached'));
|
|
3109
|
+
|
|
2929
3110
|
return React.createElement(
|
|
2930
3111
|
|
|
2931
3112
|
React.Fragment,
|
|
@@ -2938,7 +3119,54 @@ window.__ModuleLoader__.load({
|
|
|
2938
3119
|
|
|
2939
3120
|
{ className: 'dsh-goal-dock', 'data-goal-dock': 'true' },
|
|
2940
3121
|
|
|
2941
|
-
|
|
3122
|
+
isDockCollapsed
|
|
3123
|
+
? React.createElement(
|
|
3124
|
+
'div',
|
|
3125
|
+
{ className: 'dsh-goal-dock-pill' },
|
|
3126
|
+
React.createElement(
|
|
3127
|
+
'span',
|
|
3128
|
+
{ className: 'dsh-goal-icon' },
|
|
3129
|
+
isCompleted ? React.createElement(IconCheck, { size: 14 }) : React.createElement(IconTarget, { size: 13 })
|
|
3130
|
+
),
|
|
3131
|
+
React.createElement(
|
|
3132
|
+
'span',
|
|
3133
|
+
{ className: `dsh-goal-badge ${isCompleted ? 'dsh-goal-badge-ok' : isPaused ? 'dsh-goal-badge-warn' : ''}` },
|
|
3134
|
+
isCompleted ? (t('goalCompleted') || 'Done') : isPaused ? (t('paused') || 'Paused') : (t('goalLabel') || 'Goal')
|
|
3135
|
+
),
|
|
3136
|
+
React.createElement('span', { className: 'dsh-goal-title', title: state.title }, state.title),
|
|
3137
|
+
React.createElement('span', { className: 'dsh-goal-time' }, `⏱ ${liveElapsedStr}`),
|
|
3138
|
+
!isCompleted ? React.createElement(
|
|
3139
|
+
'button',
|
|
3140
|
+
{
|
|
3141
|
+
className: 'dsh-goal-btn icon-only',
|
|
3142
|
+
style: { padding: '2px 4px', height: 22 },
|
|
3143
|
+
title: isPaused ? (t('resume') || 'Resume') : (t('pause') || 'Pause'),
|
|
3144
|
+
onClick: () => handleAction(isPaused ? 'resume' : 'pause'),
|
|
3145
|
+
},
|
|
3146
|
+
isPaused ? React.createElement(IconPlay, { size: 12 }) : React.createElement(IconPause, { size: 12 })
|
|
3147
|
+
) : null,
|
|
3148
|
+
React.createElement(
|
|
3149
|
+
'button',
|
|
3150
|
+
{
|
|
3151
|
+
className: 'dsh-goal-btn icon-only',
|
|
3152
|
+
style: { padding: '2px 4px', height: 22 },
|
|
3153
|
+
title: t('details') || 'Expand goal details',
|
|
3154
|
+
onClick: () => setIsModalOpen(true),
|
|
3155
|
+
},
|
|
3156
|
+
React.createElement(IconExpand, { size: 12 })
|
|
3157
|
+
),
|
|
3158
|
+
React.createElement(
|
|
3159
|
+
'button',
|
|
3160
|
+
{
|
|
3161
|
+
className: 'dsh-goal-btn icon-only',
|
|
3162
|
+
style: { padding: '2px 4px', height: 22 },
|
|
3163
|
+
title: t('expandDock') || 'Expand goal banner',
|
|
3164
|
+
onClick: toggleDockCollapse,
|
|
3165
|
+
},
|
|
3166
|
+
'⤢'
|
|
3167
|
+
)
|
|
3168
|
+
)
|
|
3169
|
+
: React.createElement(
|
|
2942
3170
|
|
|
2943
3171
|
'div',
|
|
2944
3172
|
|
|
@@ -3016,6 +3244,37 @@ window.__ModuleLoader__.load({
|
|
|
3016
3244
|
|
|
3017
3245
|
: null,
|
|
3018
3246
|
|
|
3247
|
+
isBudgetExceeded
|
|
3248
|
+
? React.createElement(
|
|
3249
|
+
'button',
|
|
3250
|
+
{
|
|
3251
|
+
className: 'dsh-goal-btn',
|
|
3252
|
+
style: { background: 'var(--dsw-alias-status-warning)', color: 'var(--dsw-alias-surface-raised)', fontWeight: 600, fontSize: 12, padding: '2px 8px' },
|
|
3253
|
+
title: t('extendBudgetBtn') || '+50k Tokens & Resume',
|
|
3254
|
+
onClick: () => handleAction('extend_budget', { addTokens: 50000 }),
|
|
3255
|
+
},
|
|
3256
|
+
t('extendBudgetBtn') || '+50k & Resume'
|
|
3257
|
+
)
|
|
3258
|
+
: null,
|
|
3259
|
+
|
|
3260
|
+
React.createElement(
|
|
3261
|
+
|
|
3262
|
+
'button',
|
|
3263
|
+
|
|
3264
|
+
{
|
|
3265
|
+
|
|
3266
|
+
className: 'dsh-goal-btn icon-only',
|
|
3267
|
+
|
|
3268
|
+
title: t('compactDock') || 'Collapse to compact pill',
|
|
3269
|
+
|
|
3270
|
+
onClick: toggleDockCollapse,
|
|
3271
|
+
|
|
3272
|
+
},
|
|
3273
|
+
|
|
3274
|
+
React.createElement(IconMinimize, { size: 14 }),
|
|
3275
|
+
|
|
3276
|
+
),
|
|
3277
|
+
|
|
3019
3278
|
React.createElement(
|
|
3020
3279
|
|
|
3021
3280
|
'button',
|
|
@@ -3386,9 +3645,15 @@ window.__ModuleLoader__.load({
|
|
|
3386
3645
|
|
|
3387
3646
|
const notifStatus = getFieldStatus('enableBrowserNotifications', draft?.enableBrowserNotifications, snap);
|
|
3388
3647
|
|
|
3389
|
-
const
|
|
3648
|
+
const budgetStatus = getFieldStatus('maxTokenBudget', draft?.maxTokenBudget, snap);
|
|
3649
|
+
|
|
3650
|
+
const budgetWarnStatus = getFieldStatus('budgetWarningThreshold', draft?.budgetWarningThreshold, snap);
|
|
3651
|
+
|
|
3652
|
+
const autoCheckpointStatus = getFieldStatus('autoCheckpointOnMilestone', draft?.autoCheckpointOnMilestone, snap);
|
|
3390
3653
|
|
|
3391
|
-
const
|
|
3654
|
+
const dirty = maxIterStatus.isDirty || autoDriveStatus.isDirty || enableSoundStatus.isDirty || quickLaunchStatus.isDirty || toolFailStatus.isDirty || notifStatus.isDirty || budgetStatus.isDirty || budgetWarnStatus.isDirty || autoCheckpointStatus.isDirty;
|
|
3655
|
+
|
|
3656
|
+
const invalid = maxIterStatus.invalid || toolFailStatus.invalid || budgetStatus.invalid || budgetWarnStatus.invalid;
|
|
3392
3657
|
|
|
3393
3658
|
const disabled = !scope || saving || snap?.writable === false;
|
|
3394
3659
|
|
|
@@ -3410,6 +3675,12 @@ window.__ModuleLoader__.load({
|
|
|
3410
3675
|
|
|
3411
3676
|
enableBrowserNotifications: prev?.enableBrowserNotifications !== undefined ? prev.enableBrowserNotifications : notifStatus.value,
|
|
3412
3677
|
|
|
3678
|
+
maxTokenBudget: prev?.maxTokenBudget !== undefined ? prev.maxTokenBudget : budgetStatus.value,
|
|
3679
|
+
|
|
3680
|
+
budgetWarningThreshold: prev?.budgetWarningThreshold !== undefined ? prev.budgetWarningThreshold : budgetWarnStatus.value,
|
|
3681
|
+
|
|
3682
|
+
autoCheckpointOnMilestone: prev?.autoCheckpointOnMilestone !== undefined ? prev.autoCheckpointOnMilestone : autoCheckpointStatus.value,
|
|
3683
|
+
|
|
3413
3684
|
[field]: val,
|
|
3414
3685
|
|
|
3415
3686
|
}));
|
|
@@ -3939,6 +4210,101 @@ window.__ModuleLoader__.load({
|
|
|
3939
4210
|
|
|
3940
4211
|
),
|
|
3941
4212
|
|
|
4213
|
+
React.createElement(
|
|
4214
|
+
'div',
|
|
4215
|
+
{ className: 'dsh-goal-card-field' },
|
|
4216
|
+
React.createElement(
|
|
4217
|
+
'div',
|
|
4218
|
+
{ className: 'dsh-goal-field-label-row' },
|
|
4219
|
+
React.createElement('label', { htmlFor: 'dsh-goal-token-budget' }, t('budgetLabel') || 'Token Budget (0 for unlimited):'),
|
|
4220
|
+
React.createElement(
|
|
4221
|
+
'div',
|
|
4222
|
+
{ className: 'dsh-goal-field-meta' },
|
|
4223
|
+
budgetStatus.isOverridden
|
|
4224
|
+
? React.createElement('span', { className: 'dsh-goal-override-tag' }, t('overridden') || 'overridden')
|
|
4225
|
+
: null,
|
|
4226
|
+
budgetStatus.isOverridden
|
|
4227
|
+
? React.createElement(
|
|
4228
|
+
'button',
|
|
4229
|
+
{
|
|
4230
|
+
type: 'button',
|
|
4231
|
+
className: 'dsh-goal-btn-inline-reset',
|
|
4232
|
+
title: t('resetField') || 'Reset to default',
|
|
4233
|
+
onClick: () => edit('maxTokenBudget', snap?.base?.maxTokenBudget ?? DEFAULT_SETTINGS.maxTokenBudget),
|
|
4234
|
+
},
|
|
4235
|
+
React.createElement(IconRotateCcw, { size: 12 }),
|
|
4236
|
+
t('resetField') || 'Default'
|
|
4237
|
+
)
|
|
4238
|
+
: null
|
|
4239
|
+
)
|
|
4240
|
+
),
|
|
4241
|
+
React.createElement('input', {
|
|
4242
|
+
id: 'dsh-goal-token-budget',
|
|
4243
|
+
type: 'number',
|
|
4244
|
+
min: 0,
|
|
4245
|
+
step: 10000,
|
|
4246
|
+
placeholder: String(budgetStatus.baseValue),
|
|
4247
|
+
value: budgetStatus.value !== undefined ? String(budgetStatus.value) : '',
|
|
4248
|
+
disabled,
|
|
4249
|
+
className: 'dsh-goal-card-input',
|
|
4250
|
+
onChange: (e) => edit('maxTokenBudget', parseNumberField(e.target.value)),
|
|
4251
|
+
})
|
|
4252
|
+
),
|
|
4253
|
+
|
|
4254
|
+
React.createElement(
|
|
4255
|
+
'div',
|
|
4256
|
+
{ className: 'dsh-goal-card-field' },
|
|
4257
|
+
React.createElement(
|
|
4258
|
+
'div',
|
|
4259
|
+
{ className: 'dsh-goal-field-label-row' },
|
|
4260
|
+
React.createElement('label', { htmlFor: 'dsh-goal-warn-thresh' }, t('budgetWarnLabel') || 'Budget Warning Threshold (%):'),
|
|
4261
|
+
React.createElement(
|
|
4262
|
+
'div',
|
|
4263
|
+
{ className: 'dsh-goal-field-meta' },
|
|
4264
|
+
budgetWarnStatus.isOverridden
|
|
4265
|
+
? React.createElement('span', { className: 'dsh-goal-override-tag' }, t('overridden') || 'overridden')
|
|
4266
|
+
: null,
|
|
4267
|
+
budgetWarnStatus.isOverridden
|
|
4268
|
+
? React.createElement(
|
|
4269
|
+
'button',
|
|
4270
|
+
{
|
|
4271
|
+
type: 'button',
|
|
4272
|
+
className: 'dsh-goal-btn-inline-reset',
|
|
4273
|
+
title: t('resetField') || 'Reset to default',
|
|
4274
|
+
onClick: () => edit('budgetWarningThreshold', snap?.base?.budgetWarningThreshold ?? DEFAULT_SETTINGS.budgetWarningThreshold),
|
|
4275
|
+
},
|
|
4276
|
+
React.createElement(IconRotateCcw, { size: 12 }),
|
|
4277
|
+
t('resetField') || 'Default'
|
|
4278
|
+
)
|
|
4279
|
+
: null
|
|
4280
|
+
)
|
|
4281
|
+
),
|
|
4282
|
+
React.createElement('input', {
|
|
4283
|
+
id: 'dsh-goal-warn-thresh',
|
|
4284
|
+
type: 'number',
|
|
4285
|
+
min: 10,
|
|
4286
|
+
max: 100,
|
|
4287
|
+
placeholder: String(budgetWarnStatus.baseValue),
|
|
4288
|
+
value: budgetWarnStatus.value !== undefined ? String(budgetWarnStatus.value) : '',
|
|
4289
|
+
disabled,
|
|
4290
|
+
className: 'dsh-goal-card-input',
|
|
4291
|
+
onChange: (e) => edit('budgetWarningThreshold', parseNumberField(e.target.value)),
|
|
4292
|
+
})
|
|
4293
|
+
),
|
|
4294
|
+
|
|
4295
|
+
React.createElement(
|
|
4296
|
+
'div',
|
|
4297
|
+
{ className: 'dsh-goal-check-row' },
|
|
4298
|
+
React.createElement('input', {
|
|
4299
|
+
id: 'dsh-goal-auto-checkpoint',
|
|
4300
|
+
type: 'checkbox',
|
|
4301
|
+
checked: Boolean(autoCheckpointStatus.value),
|
|
4302
|
+
disabled,
|
|
4303
|
+
onChange: (e) => edit('autoCheckpointOnMilestone', e.target.checked),
|
|
4304
|
+
}),
|
|
4305
|
+
React.createElement('label', { htmlFor: 'dsh-goal-auto-checkpoint' }, t('autoCheckpointLabel') || 'Auto-create Git checkpoint on milestone completed')
|
|
4306
|
+
),
|
|
4307
|
+
|
|
3942
4308
|
React.createElement(
|
|
3943
4309
|
|
|
3944
4310
|
'div',
|
|
@@ -4077,6 +4443,19 @@ window.__ModuleLoader__.load({
|
|
|
4077
4443
|
checking: 'Checking…',
|
|
4078
4444
|
updateDone: 'Updated successfully. Please restart DSH to apply.',
|
|
4079
4445
|
updateFailed: 'Update failed: ',
|
|
4446
|
+
compactDock: 'Collapse to compact pill',
|
|
4447
|
+
expandDock: 'Expand goal banner',
|
|
4448
|
+
saveArtifact: 'Save Run Artifact',
|
|
4449
|
+
artifactSaved: '✅ Artifact Saved (.dsh/goals/)',
|
|
4450
|
+
saveArtifactFailed: 'Artifact save failed',
|
|
4451
|
+
extendBudgetBtn: '+50k Tokens & Resume',
|
|
4452
|
+
budgetExceededBadge: 'Budget Limit Reached',
|
|
4453
|
+
budgetLabel: 'Token Budget (0 for unlimited):',
|
|
4454
|
+
budgetWarnLabel: 'Budget Warning Threshold (%):',
|
|
4455
|
+
autoCheckpointLabel: 'Auto-create Git checkpoint on milestone completed',
|
|
4456
|
+
rollbackBtn: 'Rollback to Checkpoint',
|
|
4457
|
+
rollbackConfirm: 'Rollback working tree to this checkpoint?',
|
|
4458
|
+
rollbackSuccess: 'Rolled back to checkpoint',
|
|
4080
4459
|
|
|
4081
4460
|
goalCompleted: 'Goal completed',
|
|
4082
4461
|
|
|
@@ -4190,6 +4569,19 @@ window.__ModuleLoader__.load({
|
|
|
4190
4569
|
checking: '正在检查…',
|
|
4191
4570
|
updateDone: '更新成功。请重启 DSH 以生效。',
|
|
4192
4571
|
updateFailed: '更新失败:',
|
|
4572
|
+
compactDock: '收起为迷你胶囊',
|
|
4573
|
+
expandDock: '展开目标横幅',
|
|
4574
|
+
saveArtifact: '导出运行报告工件',
|
|
4575
|
+
artifactSaved: '✅ 工件已保存 (.dsh/goals/)',
|
|
4576
|
+
saveArtifactFailed: '工件保存失败',
|
|
4577
|
+
extendBudgetBtn: '追加 50k Tokens 并恢复',
|
|
4578
|
+
budgetExceededBadge: '已达 Token 预算上限',
|
|
4579
|
+
budgetLabel: 'Token 预算上限 (0 为不限制):',
|
|
4580
|
+
budgetWarnLabel: '预算预警阈值 (%):',
|
|
4581
|
+
autoCheckpointLabel: '里程碑完成时自动创建 Git 检查点',
|
|
4582
|
+
rollbackBtn: '回滚到该检查点',
|
|
4583
|
+
rollbackConfirm: '确定将工作区代码回滚至该里程碑检查点吗?',
|
|
4584
|
+
rollbackSuccess: '已成功回滚到检查点',
|
|
4193
4585
|
|
|
4194
4586
|
goalCompleted: '目标已完成',
|
|
4195
4587
|
|
|
@@ -4296,146 +4688,158 @@ window.__ModuleLoader__.load({
|
|
|
4296
4688
|
module.exports.inject = ['slots', 'locale', 'settingsScope'];
|
|
4297
4689
|
|
|
4298
4690
|
module.exports.apply = function apply(ctx) {
|
|
4691
|
+
if (typeof ctx.effect === 'function') {
|
|
4692
|
+
ctx.effect(() => {
|
|
4693
|
+
try {
|
|
4694
|
+
ctx.locale?.register?.(NS, LOCALES);
|
|
4695
|
+
} catch (err) { /* handled defensively */ }
|
|
4696
|
+
|
|
4697
|
+
const settingsScope =
|
|
4698
|
+
ctx.settingsScope && typeof ctx.settingsScope.bind === 'function'
|
|
4699
|
+
? ctx.settingsScope.bind({ namespace: NS })
|
|
4700
|
+
: null;
|
|
4701
|
+
|
|
4702
|
+
const disposers = [];
|
|
4703
|
+
const registerSlotSafe = (name, entry, comp) => {
|
|
4704
|
+
try {
|
|
4705
|
+
if (typeof ctx.slots?.inject === 'function') {
|
|
4706
|
+
const unreg = ctx.slots.inject(name, () => {
|
|
4707
|
+
try {
|
|
4708
|
+
return ctx.slots.register(entry, comp);
|
|
4709
|
+
} catch (err) { /* handled defensively */ }
|
|
4710
|
+
});
|
|
4711
|
+
if (typeof unreg === 'function') disposers.push(unreg);
|
|
4712
|
+
} else if (typeof ctx.slots?.register === 'function') {
|
|
4713
|
+
const unreg = ctx.slots.register(entry, comp);
|
|
4714
|
+
if (typeof unreg === 'function') disposers.push(unreg);
|
|
4715
|
+
}
|
|
4716
|
+
} catch (err) { /* handled defensively */ }
|
|
4717
|
+
};
|
|
4718
|
+
|
|
4719
|
+
registerSlotSafe(
|
|
4720
|
+
'conversation.input.dock',
|
|
4721
|
+
{
|
|
4722
|
+
name: 'conversation.input.dock',
|
|
4723
|
+
id: '@goodandready/dsh-goal',
|
|
4724
|
+
order: 10,
|
|
4725
|
+
locale: NS,
|
|
4726
|
+
inject: (slotProps) => ({ ctx, ...slotProps }),
|
|
4727
|
+
},
|
|
4728
|
+
GoalTopBanner,
|
|
4729
|
+
);
|
|
4730
|
+
|
|
4731
|
+
registerSlotSafe(
|
|
4732
|
+
'plugins.item',
|
|
4733
|
+
{
|
|
4734
|
+
name: 'plugins.item',
|
|
4735
|
+
id: ROW_ID,
|
|
4736
|
+
order: 60,
|
|
4737
|
+
label: () => 'Goal',
|
|
4738
|
+
locale: NS,
|
|
4739
|
+
inject: () => ({ ctx, scope: settingsScope }),
|
|
4740
|
+
},
|
|
4741
|
+
GoalSettingsCard,
|
|
4742
|
+
);
|
|
4743
|
+
|
|
4744
|
+
registerSlotSafe(
|
|
4745
|
+
'plugins.row.config',
|
|
4746
|
+
{
|
|
4747
|
+
name: 'plugins.row.config',
|
|
4748
|
+
key: ROW_CONFIG_KEY,
|
|
4749
|
+
locale: NS,
|
|
4750
|
+
inject: () => ({ ctx, scope: settingsScope }),
|
|
4751
|
+
},
|
|
4752
|
+
GoalSettingsCard,
|
|
4753
|
+
);
|
|
4754
|
+
|
|
4755
|
+
registerSlotSafe(
|
|
4756
|
+
'settings.plugin.item',
|
|
4757
|
+
{
|
|
4758
|
+
name: 'settings.plugin.item',
|
|
4759
|
+
key: NS,
|
|
4760
|
+
locale: NS,
|
|
4761
|
+
inject: () => ({ ctx, scope: settingsScope }),
|
|
4762
|
+
},
|
|
4763
|
+
GoalSettingsCard,
|
|
4764
|
+
);
|
|
4299
4765
|
|
|
4300
|
-
|
|
4301
|
-
|
|
4302
|
-
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
}
|
|
4307
|
-
|
|
4308
|
-
// Plugin settings scope
|
|
4309
|
-
|
|
4310
|
-
const settingsScope =
|
|
4311
|
-
|
|
4312
|
-
ctx.settingsScope && typeof ctx.settingsScope.bind === 'function'
|
|
4313
|
-
|
|
4314
|
-
? ctx.settingsScope.bind({ namespace: NS })
|
|
4315
|
-
|
|
4316
|
-
: null;
|
|
4317
|
-
|
|
4318
|
-
const registerSlotSafe = (name, entry, comp) => {
|
|
4319
|
-
|
|
4766
|
+
return () => {
|
|
4767
|
+
for (const dispose of disposers) {
|
|
4768
|
+
try { dispose(); } catch (e) { /* handled defensively */ }
|
|
4769
|
+
}
|
|
4770
|
+
};
|
|
4771
|
+
}, 'dsh-goal: client slots & locale');
|
|
4772
|
+
} else {
|
|
4320
4773
|
try {
|
|
4321
|
-
|
|
4322
|
-
if (typeof ctx.slots?.inject === 'function') {
|
|
4323
|
-
|
|
4324
|
-
ctx.slots.inject(name, () => {
|
|
4325
|
-
|
|
4326
|
-
try {
|
|
4327
|
-
|
|
4328
|
-
return ctx.slots.register(entry, comp);
|
|
4329
|
-
|
|
4330
|
-
} catch (err) { /* handled defensively */ }
|
|
4331
|
-
|
|
4332
|
-
});
|
|
4333
|
-
|
|
4334
|
-
} else if (typeof ctx.slots?.register === 'function') {
|
|
4335
|
-
|
|
4336
|
-
ctx.slots.register(entry, comp);
|
|
4337
|
-
|
|
4338
|
-
}
|
|
4339
|
-
|
|
4774
|
+
ctx.locale?.register?.(NS, LOCALES);
|
|
4340
4775
|
} catch (err) { /* handled defensively */ }
|
|
4341
4776
|
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
registerSlotSafe(
|
|
4347
|
-
|
|
4348
|
-
'conversation.input.dock',
|
|
4349
|
-
|
|
4350
|
-
{
|
|
4351
|
-
|
|
4352
|
-
name: 'conversation.input.dock',
|
|
4353
|
-
|
|
4354
|
-
id: '@goodandready/dsh-goal',
|
|
4355
|
-
|
|
4356
|
-
order: 10,
|
|
4357
|
-
|
|
4358
|
-
locale: NS,
|
|
4359
|
-
|
|
4360
|
-
inject: (slotProps) => ({ ctx, ...slotProps }),
|
|
4361
|
-
|
|
4362
|
-
},
|
|
4363
|
-
|
|
4364
|
-
GoalTopBanner,
|
|
4365
|
-
|
|
4366
|
-
);
|
|
4777
|
+
const settingsScope =
|
|
4778
|
+
ctx.settingsScope && typeof ctx.settingsScope.bind === 'function'
|
|
4779
|
+
? ctx.settingsScope.bind({ namespace: NS })
|
|
4780
|
+
: null;
|
|
4367
4781
|
|
|
4368
|
-
|
|
4369
|
-
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
|
|
4379
|
-
|
|
4380
|
-
|
|
4381
|
-
id: ROW_ID,
|
|
4382
|
-
|
|
4383
|
-
order: 60,
|
|
4384
|
-
|
|
4385
|
-
label: () => 'Goal',
|
|
4386
|
-
|
|
4387
|
-
locale: NS,
|
|
4388
|
-
|
|
4389
|
-
inject: () => ({ ctx, scope: settingsScope }),
|
|
4390
|
-
|
|
4391
|
-
},
|
|
4392
|
-
|
|
4393
|
-
GoalSettingsCard,
|
|
4394
|
-
|
|
4395
|
-
);
|
|
4396
|
-
|
|
4397
|
-
// Row seat and the legacy seat kept as fallbacks.
|
|
4398
|
-
|
|
4399
|
-
registerSlotSafe(
|
|
4400
|
-
|
|
4401
|
-
'plugins.row.config',
|
|
4402
|
-
|
|
4403
|
-
{
|
|
4404
|
-
|
|
4405
|
-
name: 'plugins.row.config',
|
|
4406
|
-
|
|
4407
|
-
key: ROW_CONFIG_KEY,
|
|
4408
|
-
|
|
4409
|
-
locale: NS,
|
|
4410
|
-
|
|
4411
|
-
inject: () => ({ ctx, scope: settingsScope }),
|
|
4412
|
-
|
|
4413
|
-
},
|
|
4414
|
-
|
|
4415
|
-
GoalSettingsCard,
|
|
4416
|
-
|
|
4417
|
-
);
|
|
4418
|
-
|
|
4419
|
-
registerSlotSafe(
|
|
4420
|
-
|
|
4421
|
-
'settings.plugin.item',
|
|
4422
|
-
|
|
4423
|
-
{
|
|
4424
|
-
|
|
4425
|
-
name: 'settings.plugin.item',
|
|
4426
|
-
|
|
4427
|
-
key: NS,
|
|
4428
|
-
|
|
4429
|
-
locale: NS,
|
|
4430
|
-
|
|
4431
|
-
inject: () => ({ ctx, scope: settingsScope }),
|
|
4782
|
+
const registerSlotSafe = (name, entry, comp) => {
|
|
4783
|
+
try {
|
|
4784
|
+
if (typeof ctx.slots?.inject === 'function') {
|
|
4785
|
+
ctx.slots.inject(name, () => {
|
|
4786
|
+
try {
|
|
4787
|
+
return ctx.slots.register(entry, comp);
|
|
4788
|
+
} catch (err) { /* handled defensively */ }
|
|
4789
|
+
});
|
|
4790
|
+
} else if (typeof ctx.slots?.register === 'function') {
|
|
4791
|
+
ctx.slots.register(entry, comp);
|
|
4792
|
+
}
|
|
4793
|
+
} catch (err) { /* handled defensively */ }
|
|
4794
|
+
};
|
|
4432
4795
|
|
|
4433
|
-
|
|
4796
|
+
registerSlotSafe(
|
|
4797
|
+
'conversation.input.dock',
|
|
4798
|
+
{
|
|
4799
|
+
name: 'conversation.input.dock',
|
|
4800
|
+
id: '@goodandready/dsh-goal',
|
|
4801
|
+
order: 10,
|
|
4802
|
+
locale: NS,
|
|
4803
|
+
inject: (slotProps) => ({ ctx, ...slotProps }),
|
|
4804
|
+
},
|
|
4805
|
+
GoalTopBanner,
|
|
4806
|
+
);
|
|
4434
4807
|
|
|
4435
|
-
|
|
4808
|
+
registerSlotSafe(
|
|
4809
|
+
'plugins.item',
|
|
4810
|
+
{
|
|
4811
|
+
name: 'plugins.item',
|
|
4812
|
+
id: ROW_ID,
|
|
4813
|
+
order: 60,
|
|
4814
|
+
label: () => 'Goal',
|
|
4815
|
+
locale: NS,
|
|
4816
|
+
inject: () => ({ ctx, scope: settingsScope }),
|
|
4817
|
+
},
|
|
4818
|
+
GoalSettingsCard,
|
|
4819
|
+
);
|
|
4436
4820
|
|
|
4437
|
-
|
|
4821
|
+
registerSlotSafe(
|
|
4822
|
+
'plugins.row.config',
|
|
4823
|
+
{
|
|
4824
|
+
name: 'plugins.row.config',
|
|
4825
|
+
key: ROW_CONFIG_KEY,
|
|
4826
|
+
locale: NS,
|
|
4827
|
+
inject: () => ({ ctx, scope: settingsScope }),
|
|
4828
|
+
},
|
|
4829
|
+
GoalSettingsCard,
|
|
4830
|
+
);
|
|
4438
4831
|
|
|
4832
|
+
registerSlotSafe(
|
|
4833
|
+
'settings.plugin.item',
|
|
4834
|
+
{
|
|
4835
|
+
name: 'settings.plugin.item',
|
|
4836
|
+
key: NS,
|
|
4837
|
+
locale: NS,
|
|
4838
|
+
inject: () => ({ ctx, scope: settingsScope }),
|
|
4839
|
+
},
|
|
4840
|
+
GoalSettingsCard,
|
|
4841
|
+
);
|
|
4842
|
+
}
|
|
4439
4843
|
};
|
|
4440
4844
|
|
|
4441
4845
|
return module.exports;
|