@goodandready/dsh-goal 0.2.9 → 0.2.10
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/lib/client.js +350 -13
- package/lib/engine-git-branch.js +105 -0
- package/lib/engine-intervention.js +150 -0
- package/lib/engine-issue-sync.js +66 -0
- package/lib/engine-milestones.js +42 -3
- package/lib/engine-prompt.js +28 -4
- package/lib/engine-retrospective.js +79 -0
- package/lib/engine-sessions.js +82 -0
- package/lib/engine-templates.js +167 -0
- package/lib/goal-engine-constants.js +30 -0
- package/lib/goal-engine.js +198 -233
- package/lib/index.js +36 -0
- package/lib/routes.js +52 -0
- package/lib/tools.js +11 -1
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -22,6 +22,15 @@ export const Config = z.object({
|
|
|
22
22
|
maxTokenBudget: z.number().default(0).description('Maximum token budget per goal session (0 to disable)'),
|
|
23
23
|
budgetWarningThreshold: z.number().default(80).description('Percentage of token budget consumed before model warning injection (e.g. 80)'),
|
|
24
24
|
autoCheckpointOnMilestone: z.boolean().default(false).description('Automatically create git commit checkpoint upon milestone completion'),
|
|
25
|
+
enableLiveActivityFeed: z.boolean().default(true).description('Display compact recent tool and control activity feed in details modal'),
|
|
26
|
+
enablePreplanning: z.boolean().default(true).description('Generate initial draft plan for approval before launching autonomous turns'),
|
|
27
|
+
autoBranchOnGoalStart: z.boolean().default(true).description('Automatically create dedicated isolated git branch for goal execution'),
|
|
28
|
+
enablePostGoalRetrospective: z.boolean().default(true).description('Generate structured retrospective and analytics card upon goal completion'),
|
|
29
|
+
autoScaleBudgetNearCompletion: z.boolean().default(false).description('Automatically grant token buffer extension if budget reaches 100% near completion'),
|
|
30
|
+
enableTemplatesDrawer: z.boolean().default(true).description('Provide pre-configured engineering goal templates in UI drawer'),
|
|
31
|
+
enableMilestoneDependencies: z.boolean().default(true).description('Enforce milestone dependency ordering and block premature execution'),
|
|
32
|
+
soundScheme: z.string().default('default').description('Audio theme for status and milestone notifications'),
|
|
33
|
+
enableVoiceAnnouncements: z.boolean().default(false).description('Use Web Speech API for voice announcements on milestone events'),
|
|
25
34
|
storagePath: z.string().default('').description('Custom filesystem path for persistent state storage'),
|
|
26
35
|
});
|
|
27
36
|
|
|
@@ -43,6 +52,15 @@ export function apply(ctx, config = {}) {
|
|
|
43
52
|
maxTokenBudget: config?.maxTokenBudget ?? 0,
|
|
44
53
|
budgetWarningThreshold: config?.budgetWarningThreshold ?? 80,
|
|
45
54
|
autoCheckpointOnMilestone: config?.autoCheckpointOnMilestone ?? false,
|
|
55
|
+
enableLiveActivityFeed: config?.enableLiveActivityFeed ?? true,
|
|
56
|
+
enablePreplanning: config?.enablePreplanning ?? true,
|
|
57
|
+
autoBranchOnGoalStart: config?.autoBranchOnGoalStart ?? true,
|
|
58
|
+
enablePostGoalRetrospective: config?.enablePostGoalRetrospective ?? true,
|
|
59
|
+
autoScaleBudgetNearCompletion: config?.autoScaleBudgetNearCompletion ?? false,
|
|
60
|
+
enableTemplatesDrawer: config?.enableTemplatesDrawer ?? true,
|
|
61
|
+
enableMilestoneDependencies: config?.enableMilestoneDependencies ?? true,
|
|
62
|
+
soundScheme: config?.soundScheme ?? 'default',
|
|
63
|
+
enableVoiceAnnouncements: config?.enableVoiceAnnouncements ?? false,
|
|
46
64
|
storagePath: config?.storagePath,
|
|
47
65
|
};
|
|
48
66
|
|
|
@@ -60,6 +78,15 @@ export function apply(ctx, config = {}) {
|
|
|
60
78
|
maxTokenBudget: currentSettings.maxTokenBudget,
|
|
61
79
|
budgetWarningThreshold: currentSettings.budgetWarningThreshold,
|
|
62
80
|
autoCheckpointOnMilestone: currentSettings.autoCheckpointOnMilestone,
|
|
81
|
+
enableLiveActivityFeed: currentSettings.enableLiveActivityFeed,
|
|
82
|
+
enablePreplanning: currentSettings.enablePreplanning,
|
|
83
|
+
autoBranchOnGoalStart: currentSettings.autoBranchOnGoalStart,
|
|
84
|
+
enablePostGoalRetrospective: currentSettings.enablePostGoalRetrospective,
|
|
85
|
+
autoScaleBudgetNearCompletion: currentSettings.autoScaleBudgetNearCompletion,
|
|
86
|
+
enableTemplatesDrawer: currentSettings.enableTemplatesDrawer,
|
|
87
|
+
enableMilestoneDependencies: currentSettings.enableMilestoneDependencies,
|
|
88
|
+
soundScheme: currentSettings.soundScheme,
|
|
89
|
+
enableVoiceAnnouncements: currentSettings.enableVoiceAnnouncements,
|
|
63
90
|
storagePath,
|
|
64
91
|
});
|
|
65
92
|
|
|
@@ -220,6 +247,15 @@ export function apply(ctx, config = {}) {
|
|
|
220
247
|
maxTokenBudget: live.maxTokenBudget,
|
|
221
248
|
budgetWarningThreshold: live.budgetWarningThreshold,
|
|
222
249
|
autoCheckpointOnMilestone: live.autoCheckpointOnMilestone,
|
|
250
|
+
enableLiveActivityFeed: live.enableLiveActivityFeed,
|
|
251
|
+
enablePreplanning: live.enablePreplanning,
|
|
252
|
+
autoBranchOnGoalStart: live.autoBranchOnGoalStart,
|
|
253
|
+
enablePostGoalRetrospective: live.enablePostGoalRetrospective,
|
|
254
|
+
autoScaleBudgetNearCompletion: live.autoScaleBudgetNearCompletion,
|
|
255
|
+
enableTemplatesDrawer: live.enableTemplatesDrawer,
|
|
256
|
+
enableMilestoneDependencies: live.enableMilestoneDependencies,
|
|
257
|
+
soundScheme: live.soundScheme,
|
|
258
|
+
enableVoiceAnnouncements: live.enableVoiceAnnouncements,
|
|
223
259
|
});
|
|
224
260
|
};
|
|
225
261
|
|
package/lib/routes.js
CHANGED
|
@@ -2,6 +2,7 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { MilestoneStatus, detectLanguage, sessionIdOf } from './goal-engine-constants.js';
|
|
4
4
|
import { saveGoalArtifact, rollbackToCheckpoint } from './engine-reports.js';
|
|
5
|
+
import { getTemplatesCatalogue } from './engine-templates.js';
|
|
5
6
|
|
|
6
7
|
export function isLoopback(value) {
|
|
7
8
|
if (!value) return false;
|
|
@@ -194,6 +195,12 @@ export function registerRoutes(ctx, {
|
|
|
194
195
|
|
|
195
196
|
res.setHeader('Content-Type', 'application/json; charset=utf-8');
|
|
196
197
|
|
|
198
|
+
// GET /dsh-goal/templates
|
|
199
|
+
if (req.method === 'GET' && (pathname === '/dsh-goal/templates' || pathname === '/dsh-goal/templates/')) {
|
|
200
|
+
res.statusCode = 200;
|
|
201
|
+
return res.end(JSON.stringify({ ok: true, templates: getTemplatesCatalogue() }));
|
|
202
|
+
}
|
|
203
|
+
|
|
197
204
|
// GET /dsh-goal/state
|
|
198
205
|
if (req.method === 'GET' && (pathname === '/dsh-goal/state' || pathname === '/dsh-goal/state/')) {
|
|
199
206
|
const sid = sessionIdOf(req, 'default');
|
|
@@ -421,6 +428,51 @@ export function registerRoutes(ctx, {
|
|
|
421
428
|
return res.end(JSON.stringify({ ok: true, artifact, state: snap }));
|
|
422
429
|
}
|
|
423
430
|
|
|
431
|
+
case 'intervene': {
|
|
432
|
+
result = engine.intervene(data, sid);
|
|
433
|
+
if (data.resume) {
|
|
434
|
+
engine.resume(sid);
|
|
435
|
+
const prompt = engine.getStatePromptInjection(sid);
|
|
436
|
+
if (typeof resumeActiveAgent === 'function') {
|
|
437
|
+
resumeActiveAgent(prompt, sid);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
break;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
case 'preplan_approve': {
|
|
444
|
+
result = engine.approvePreplan(sid);
|
|
445
|
+
const prompt = engine.getStatePromptInjection(sid);
|
|
446
|
+
if (typeof resumeActiveAgent === 'function') {
|
|
447
|
+
resumeActiveAgent(prompt, sid);
|
|
448
|
+
}
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
case 'branch_action': {
|
|
453
|
+
const op = String(data.operation || data.branchOperation || 'merge').toLowerCase();
|
|
454
|
+
const targetBranch = String(data.targetBranch || 'main');
|
|
455
|
+
if (op === 'merge') {
|
|
456
|
+
const ok = engine.mergeGoalBranch(targetBranch, sid);
|
|
457
|
+
if (!ok) {
|
|
458
|
+
res.statusCode = 500;
|
|
459
|
+
return res.end(JSON.stringify({ error: `Failed to merge goal branch into ${targetBranch}` }));
|
|
460
|
+
}
|
|
461
|
+
} else if (op === 'discard') {
|
|
462
|
+
const ok = engine.discardGoalBranch(targetBranch, sid);
|
|
463
|
+
if (!ok) {
|
|
464
|
+
res.statusCode = 500;
|
|
465
|
+
return res.end(JSON.stringify({ error: 'Failed to discard goal branch' }));
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
result = engine.getSnapshot(sid);
|
|
469
|
+
break;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
case 'templates':
|
|
473
|
+
res.statusCode = 200;
|
|
474
|
+
return res.end(JSON.stringify({ ok: true, templates: getTemplatesCatalogue() }));
|
|
475
|
+
|
|
424
476
|
default:
|
|
425
477
|
res.statusCode = 400;
|
|
426
478
|
return res.end(JSON.stringify({ error: `Unknown action: ${action}` }));
|
package/lib/tools.js
CHANGED
|
@@ -195,6 +195,9 @@ export function registerTools(ctx, { engine, resumeActiveAgent }) {
|
|
|
195
195
|
const handleSetMilestones = async ({ milestones }, toolCtx) => {
|
|
196
196
|
const sid = sessionIdOf(toolCtx, 'default');
|
|
197
197
|
const snap = engine.setMilestones(milestones, sid);
|
|
198
|
+
if (typeof engine.recordToolActivity === 'function') {
|
|
199
|
+
engine.recordToolActivity('goal_set_milestones', 'success', 'Defined milestones', sid);
|
|
200
|
+
}
|
|
198
201
|
return {
|
|
199
202
|
success: true,
|
|
200
203
|
count: snap.milestones?.length || 0,
|
|
@@ -215,6 +218,7 @@ export function registerTools(ctx, { engine, resumeActiveAgent }) {
|
|
|
215
218
|
properties: {
|
|
216
219
|
id: { type: 'string', description: 'Short identifier, e.g. M1, step-1' },
|
|
217
220
|
title: { type: 'string', description: 'Concise actionable title' },
|
|
221
|
+
dependsOn: { type: 'array', items: { type: 'string' }, description: 'Prerequisite milestone IDs' },
|
|
218
222
|
},
|
|
219
223
|
required: ['id', 'title'],
|
|
220
224
|
},
|
|
@@ -231,7 +235,10 @@ export function registerTools(ctx, { engine, resumeActiveAgent }) {
|
|
|
231
235
|
// Tool 5: goal_update_progress
|
|
232
236
|
const handleUpdateProgress = async ({ milestone_id, status, notes, checklist }, toolCtx) => {
|
|
233
237
|
const sid = sessionIdOf(toolCtx, 'default');
|
|
234
|
-
engine.updateMilestone(milestone_id, status, notes, sid, checklist);
|
|
238
|
+
const ok = engine.updateMilestone(milestone_id, status, notes, sid, checklist);
|
|
239
|
+
if (typeof engine.recordToolActivity === 'function') {
|
|
240
|
+
engine.recordToolActivity('goal_update_progress', ok ? 'success' : 'error', String(milestone_id) + ' -> ' + String(status), sid);
|
|
241
|
+
}
|
|
235
242
|
const snap = engine.getSnapshot(sid);
|
|
236
243
|
const targetMilestone = snap.milestones?.find((m) => m.id === String(milestone_id) || m.id.toLowerCase().replace(/[^a-z0-9]/g, '') === String(milestone_id).toLowerCase().replace(/[^a-z0-9]/g, '') || m.id.toLowerCase().replace(/[^0-9]/g, '') === String(milestone_id).toLowerCase().replace(/[^0-9]/g, ''));
|
|
237
244
|
return {
|
|
@@ -282,6 +289,9 @@ export function registerTools(ctx, { engine, resumeActiveAgent }) {
|
|
|
282
289
|
const handleGoalFinish = async ({ summary }, toolCtx) => {
|
|
283
290
|
const sid = sessionIdOf(toolCtx, 'default');
|
|
284
291
|
const snap = engine.completeGoal(summary, sid);
|
|
292
|
+
if (typeof engine.recordToolActivity === 'function') {
|
|
293
|
+
engine.recordToolActivity('goal_finish', 'success', summary ? summary.slice(0, 80) : 'Goal finished', sid);
|
|
294
|
+
}
|
|
285
295
|
return {
|
|
286
296
|
success: true,
|
|
287
297
|
completed: true,
|
package/package.json
CHANGED