zelari-code 1.41.0 → 1.43.0

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.
Files changed (33) hide show
  1. package/dist/cli/budget/llmCompact.js +97 -83
  2. package/dist/cli/budget/llmCompact.js.map +1 -1
  3. package/dist/cli/budget/requestMeter.js +138 -0
  4. package/dist/cli/budget/requestMeter.js.map +1 -0
  5. package/dist/cli/budget/requestSnapshotStore.js +55 -0
  6. package/dist/cli/budget/requestSnapshotStore.js.map +1 -0
  7. package/dist/cli/budget/tokenBudget.js +147 -15
  8. package/dist/cli/budget/tokenBudget.js.map +1 -1
  9. package/dist/cli/hooks/conversationContext.js +4 -0
  10. package/dist/cli/hooks/conversationContext.js.map +1 -1
  11. package/dist/cli/hooks/historyCompaction.js +76 -21
  12. package/dist/cli/hooks/historyCompaction.js.map +1 -1
  13. package/dist/cli/hooks/useChatTurn.js +90 -23
  14. package/dist/cli/hooks/useChatTurn.js.map +1 -1
  15. package/dist/cli/main.bundled.js +1555 -890
  16. package/dist/cli/main.bundled.js.map +4 -4
  17. package/dist/cli/provider/openai-compatible.js +11 -1
  18. package/dist/cli/provider/openai-compatible.js.map +1 -1
  19. package/dist/cli/runHeadless.js +15 -0
  20. package/dist/cli/runHeadless.js.map +1 -1
  21. package/dist/cli/toolRegistry.js +16 -0
  22. package/dist/cli/toolRegistry.js.map +1 -1
  23. package/dist/cli/tools/planTaskTools.js +236 -0
  24. package/dist/cli/tools/planTaskTools.js.map +1 -0
  25. package/dist/cli/workspace/planStore.js +213 -0
  26. package/dist/cli/workspace/planStore.js.map +1 -0
  27. package/dist/cli/workspace/planStore.test.js +295 -0
  28. package/dist/cli/workspace/planStore.test.js.map +1 -0
  29. package/dist/cli/workspace/stubs.js +14 -4
  30. package/dist/cli/workspace/stubs.js.map +1 -1
  31. package/dist/cli/workspace/workspaceSummary.js +7 -1
  32. package/dist/cli/workspace/workspaceSummary.js.map +1 -1
  33. package/package.json +2 -2
@@ -0,0 +1,236 @@
1
+ /**
2
+ * tools/planTaskTools.ts — Durable workspace plan-task tools (ADR-0018, 3a).
3
+ *
4
+ * `task_create` / `task_update` / `task_list` operate on the canonical
5
+ * `.zelari/plan.json` store (src/cli/workspace/planStore.ts) shared with the
6
+ * council stubs. Distinct from `todo_write`/`todo_read` (session-scoped,
7
+ * volatile): these tasks are multi-session durable and visible to the
8
+ * Desktop Live Tasks panel (M3).
9
+ *
10
+ * @since v1.43.0
11
+ */
12
+ import { z } from 'zod';
13
+ import { typedOk, typedErr, } from '@zelari/core/harness/tools/toolTypes';
14
+ import { withPlanStore, nextPlanTaskId, writePlanTaskArtifact, PlanStoreError, PLAN_MAX_TASKS, PLAN_NOTES_MAX, PLAN_TITLE_MAX, } from '../workspace/planStore.js';
15
+ const StatusSchema = z
16
+ .enum(['pending', 'in_progress', 'completed', 'cancelled', 'blocked'])
17
+ .describe('blocked exists only here (session todos have no blocked); no rigid FSM — corrections like completed → in_progress are allowed');
18
+ const PrioritySchema = z.enum(['low', 'medium', 'high', 'critical']);
19
+ const CreateSchema = z.object({
20
+ title: z
21
+ .string()
22
+ .min(1)
23
+ .max(PLAN_TITLE_MAX)
24
+ .describe('Short task description'),
25
+ priority: PrioritySchema.optional().describe('Default medium'),
26
+ phaseId: z
27
+ .string()
28
+ .min(1)
29
+ .max(64)
30
+ .optional()
31
+ .describe('Existing plan phase id (see .zelari/plan.json phases)'),
32
+ notes: z
33
+ .string()
34
+ .max(PLAN_NOTES_MAX)
35
+ .optional()
36
+ .describe('Optional context/acceptance notes'),
37
+ });
38
+ const UpdateSchema = z
39
+ .object({
40
+ id: z.string().min(1).max(64).describe('Task id from task_create/task_list'),
41
+ status: StatusSchema.optional(),
42
+ title: z.string().min(1).max(PLAN_TITLE_MAX).optional(),
43
+ priority: PrioritySchema.optional(),
44
+ phaseId: z.string().min(1).max(64).optional(),
45
+ notes: z.string().max(PLAN_NOTES_MAX).optional(),
46
+ appendNote: z
47
+ .string()
48
+ .max(PLAN_NOTES_MAX)
49
+ .optional()
50
+ .describe('Append to existing notes (kept within the size cap)'),
51
+ })
52
+ .describe('At least one field besides id must be present');
53
+ const ListSchema = z.object({
54
+ status: StatusSchema.optional().describe('Filter by status'),
55
+ phaseId: z.string().min(1).max(64).optional().describe('Filter by phase'),
56
+ });
57
+ function taskSummaryLine(t) {
58
+ return `- ${t.id}: ${t.title} (${t.status}${t.priority ? `, ${t.priority}` : ''})`;
59
+ }
60
+ function toTaskPayload(t) {
61
+ return {
62
+ id: t.id,
63
+ title: t.title,
64
+ status: t.status,
65
+ phaseId: t.phaseId,
66
+ priority: t.priority,
67
+ };
68
+ }
69
+ function safeEmit(sink, event) {
70
+ if (!sink)
71
+ return;
72
+ try {
73
+ sink(event);
74
+ }
75
+ catch {
76
+ // A failing sink must never break the tool result.
77
+ }
78
+ }
79
+ /** Build the three plan-task tools bound to a project root. */
80
+ // Widened to a homogeneous array so callers can map/wrap without fighting
81
+ // the input/output unions of the individual tool definitions.
82
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
83
+ export function createPlanTaskTools(opts) {
84
+ const projectRoot = opts.projectRoot;
85
+ const onTaskEvent = opts.onTaskEvent;
86
+ const taskCreate = {
87
+ name: 'task_create',
88
+ description: 'Create a durable workspace task in .zelari/plan.json (multi-session, shared ' +
89
+ 'with the Desktop Live Tasks panel). Use for project work that must survive ' +
90
+ 'this session. For volatile per-session tracking use todo_write instead. ' +
91
+ 'Returns the assigned id (t<N>).',
92
+ permissions: ['write'],
93
+ timeoutMs: 5_000,
94
+ inputSchema: CreateSchema,
95
+ execute: async (input) => {
96
+ try {
97
+ const res = await withPlanStore(projectRoot, (store) => {
98
+ if (store.tasks.length >= PLAN_MAX_TASKS) {
99
+ return typedErr(`PLAN_TOO_MANY_TASKS: plan.json already holds ${store.tasks.length} tasks (max ${PLAN_MAX_TASKS}).`);
100
+ }
101
+ const now = new Date().toISOString();
102
+ const id = nextPlanTaskId(store);
103
+ const task = {
104
+ id,
105
+ title: input.title.trim().slice(0, PLAN_TITLE_MAX),
106
+ // council readers (buildPlanSummary) render `name` — keep the
107
+ // alias in sync from creation, not just on reload.
108
+ name: input.title.trim().slice(0, PLAN_TITLE_MAX),
109
+ status: 'pending',
110
+ priority: input.priority,
111
+ phaseId: input.phaseId?.trim().slice(0, 64),
112
+ notes: input.notes?.trim().slice(0, PLAN_NOTES_MAX),
113
+ createdAt: now,
114
+ updatedAt: now,
115
+ };
116
+ store.tasks.push(task);
117
+ writePlanTaskArtifact(store.rootDir, task);
118
+ return typedOk({ id, task });
119
+ });
120
+ if (res.ok) {
121
+ safeEmit(onTaskEvent, {
122
+ type: 'task_update',
123
+ source: 'workspace_plan',
124
+ task: toTaskPayload(res.value.task),
125
+ });
126
+ }
127
+ return res;
128
+ }
129
+ catch (err) {
130
+ return typedErr(planStoreErrorMessage(err, 'task_create'));
131
+ }
132
+ },
133
+ };
134
+ const taskUpdate = {
135
+ name: 'task_update',
136
+ description: 'Update a durable workspace task in .zelari/plan.json (status, title, ' +
137
+ 'priority, phaseId, notes, or appendNote). Accepts council-created ids ' +
138
+ 'too (task_list shows them). Errors with PLAN_TASK_NOT_FOUND on unknown ids.',
139
+ permissions: ['write'],
140
+ timeoutMs: 5_000,
141
+ inputSchema: UpdateSchema,
142
+ execute: async (input) => {
143
+ try {
144
+ const res = await withPlanStore(projectRoot, (store) => {
145
+ const task = store.tasks.find((t) => t.id === input.id);
146
+ if (!task) {
147
+ return typedErr(`PLAN_TASK_NOT_FOUND: no task with id "${input.id}" in .zelari/plan.json ` +
148
+ `(call task_list for current ids).`);
149
+ }
150
+ if (input.title !== undefined) {
151
+ task.title = input.title.trim().slice(0, PLAN_TITLE_MAX);
152
+ // keep the council `name` alias in sync
153
+ task.name = task.title;
154
+ }
155
+ if (input.status !== undefined)
156
+ task.status = input.status;
157
+ if (input.priority !== undefined)
158
+ task.priority = input.priority;
159
+ if (input.phaseId !== undefined)
160
+ task.phaseId = input.phaseId.slice(0, 64);
161
+ if (input.notes !== undefined) {
162
+ task.notes = input.notes.slice(0, PLAN_NOTES_MAX);
163
+ }
164
+ if (input.appendNote !== undefined) {
165
+ const prev = typeof task.notes === 'string' ? task.notes : '';
166
+ const merged = prev ? `${prev}\n${input.appendNote}` : input.appendNote;
167
+ task.notes = merged.slice(-PLAN_NOTES_MAX);
168
+ }
169
+ task.updatedAt = new Date().toISOString();
170
+ writePlanTaskArtifact(store.rootDir, task);
171
+ return typedOk({ task });
172
+ });
173
+ if (res.ok) {
174
+ safeEmit(onTaskEvent, {
175
+ type: 'task_update',
176
+ source: 'workspace_plan',
177
+ task: toTaskPayload(res.value.task),
178
+ });
179
+ }
180
+ return res;
181
+ }
182
+ catch (err) {
183
+ return typedErr(planStoreErrorMessage(err, 'task_update'));
184
+ }
185
+ },
186
+ };
187
+ const taskList = {
188
+ name: 'task_list',
189
+ description: 'List durable workspace tasks from .zelari/plan.json (both t<N> agent ' +
190
+ 'tasks and council-created plan tasks). Optional status/phaseId filters. ' +
191
+ 'Use before task_update to discover ids.',
192
+ permissions: ['read'],
193
+ timeoutMs: 5_000,
194
+ inputSchema: ListSchema,
195
+ execute: async (input) => {
196
+ try {
197
+ // Snapshot events carry the FULL task list (not the filtered view the
198
+ // agent asked for), so consumers can use them as a complete refresh.
199
+ let allPayloads = [];
200
+ const res = await withPlanStore(projectRoot, (store) => {
201
+ allPayloads = store.tasks.map(toTaskPayload);
202
+ const filtered = store.tasks.filter((t) => (input.status === undefined || t.status === input.status) &&
203
+ (input.phaseId === undefined || t.phaseId === input.phaseId));
204
+ const done = store.tasks.filter((t) => t.status === 'completed' || t.status === 'cancelled').length;
205
+ const formatted = filtered.length === 0
206
+ ? '(no matching workspace tasks)'
207
+ : filtered.map(taskSummaryLine).join('\n');
208
+ return typedOk({
209
+ tasks: filtered,
210
+ total: store.tasks.length,
211
+ done,
212
+ formatted: `${formatted}\n(done/total: ${done}/${store.tasks.length})`,
213
+ });
214
+ });
215
+ if (res.ok) {
216
+ safeEmit(onTaskEvent, {
217
+ type: 'task_snapshot',
218
+ source: 'workspace_plan',
219
+ tasks: allPayloads,
220
+ });
221
+ }
222
+ return res;
223
+ }
224
+ catch (err) {
225
+ return typedErr(planStoreErrorMessage(err, 'task_list'));
226
+ }
227
+ },
228
+ };
229
+ return [taskCreate, taskUpdate, taskList];
230
+ }
231
+ function planStoreErrorMessage(err, tool) {
232
+ if (err instanceof PlanStoreError)
233
+ return err.message;
234
+ return `[${tool}] ${err instanceof Error ? err.message : String(err)}`;
235
+ }
236
+ //# sourceMappingURL=planTaskTools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planTaskTools.js","sourceRoot":"","sources":["../../../src/cli/tools/planTaskTools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,213 @@
1
+ /**
2
+ * workspace/planStore.ts — Durable workspace task store (ADR-0018, slice 3a).
3
+ *
4
+ * Canonical, versioned view of `.zelari/plan.json`, shared by the agent-loop
5
+ * `task_*` tools (src/cli/tools/planTaskTools.ts) and the council stubs
6
+ * (createPlan/createTask/updateTask — src/cli/workspace/stubs.ts).
7
+ *
8
+ * Contract (docs/decisions/0018-workspace-task-store-plan-json.md):
9
+ * - Envelope v1: root carries `schemaVersion`, `counter`, `tasks`; every
10
+ * other root field (`phases`, `milestones`, council metadata, …) is
11
+ * preserved verbatim in pass-through. Unknown fields on a task are kept
12
+ * unless explicitly overwritten.
13
+ * - Status: `pending | in_progress | completed | cancelled | blocked`.
14
+ * Legacy council `done` is normalized to `completed` on read; `task_*`
15
+ * writes use the v1 vocabulary. Council readers were patched to accept
16
+ * both (workspaceSummary.ts).
17
+ * - Ids: `t<N>` sequential via the persisted `counter` — never collides
18
+ * with council ids (`<phaseId>-<slug>-<N>`).
19
+ * - Concurrency: same in-process keyed mutex as the council stubs
20
+ * (`workspaceMutex`, key `<root>:plan`) + atomic tmp+rename write, with a
21
+ * `plan.json.bak` backup before rewriting an existing file. Cross-process
22
+ * races (two CLIs on the same cwd) remain best-effort until a lock file
23
+ * lands (ADR-0018 hardening, out of scope for 3a).
24
+ *
25
+ * @since v1.43.0
26
+ */
27
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync, } from 'node:fs';
28
+ import { dirname, join } from 'node:path';
29
+ import { resolveWorkspaceRoot } from './paths.js';
30
+ import { Storage, workspaceMutex } from './storage.js';
31
+ export const PLAN_SCHEMA_VERSION = 1;
32
+ export const PLAN_MAX_TASKS = 100;
33
+ export const PLAN_TITLE_MAX = 200;
34
+ export const PLAN_NOTES_MAX = 2000;
35
+ export const PLAN_TAG_MAX = 64;
36
+ export const PLAN_TASK_STATUSES = [
37
+ 'pending',
38
+ 'in_progress',
39
+ 'completed',
40
+ 'cancelled',
41
+ 'blocked',
42
+ ];
43
+ /** Typed store error — corrupt file never gets overwritten silently. */
44
+ export class PlanStoreError extends Error {
45
+ code;
46
+ constructor(message, code) {
47
+ super(message);
48
+ this.code = code;
49
+ this.name = 'PlanStoreError';
50
+ }
51
+ }
52
+ /** Resolved plan.json path for a project root (creates nothing). */
53
+ export function planJsonPathFor(projectRoot = process.cwd()) {
54
+ return join(resolveWorkspaceRoot(projectRoot), 'plan.json');
55
+ }
56
+ /**
57
+ * Read-modify-write the plan store under the shared workspace mutex.
58
+ * Corrupt JSON → PlanStoreError('PLAN_CORRUPT') and the file is left intact.
59
+ */
60
+ export async function withPlanStore(projectRoot, fn) {
61
+ const rootDir = resolveWorkspaceRoot(projectRoot);
62
+ return workspaceMutex.run(`${rootDir}:plan`, () => {
63
+ const handle = loadHandle(rootDir);
64
+ const out = fn(handle);
65
+ saveHandle(rootDir, handle);
66
+ return out;
67
+ });
68
+ }
69
+ /** Allocate the next `t<N>` id (increments the persisted counter). */
70
+ export function nextPlanTaskId(store) {
71
+ const maxExisting = store.tasks.reduce((max, t) => {
72
+ const m = /^t(\d+)$/.exec(t.id);
73
+ return m ? Math.max(max, parseInt(m[1], 10)) : max;
74
+ }, 0);
75
+ store.counter = Math.max(store.counter, maxExisting) + 1;
76
+ return `t${store.counter}`;
77
+ }
78
+ /** Write/refresh the per-task artifact the workspace summary links to. */
79
+ export function writePlanTaskArtifact(rootDir, task) {
80
+ const path = join(rootDir, 'plan-tasks', `${task.id}.md`);
81
+ mkdirSync(dirname(path), { recursive: true });
82
+ const meta = {
83
+ kind: 'task',
84
+ id: task.id,
85
+ name: task.title,
86
+ phaseId: task.phaseId,
87
+ status: task.status,
88
+ priority: task.priority ?? 'medium',
89
+ updatedAt: task.updatedAt,
90
+ };
91
+ const body = [
92
+ `# Task ${task.id}: ${task.title}`,
93
+ '',
94
+ `- Status: **${task.status}**`,
95
+ `- Priority: ${task.priority ?? 'medium'}`,
96
+ task.phaseId ? `- Phase: ${task.phaseId}` : null,
97
+ task.agent ? `- Agent: ${task.agent}` : null,
98
+ '',
99
+ task.notes?.trim() ? task.notes.trim() : '_(no notes)_',
100
+ '',
101
+ ]
102
+ .filter((l) => l !== null)
103
+ .join('\n');
104
+ new Storage().write(path, meta, body);
105
+ }
106
+ // ── internals ─────────────────────────────────────────────────────────
107
+ function loadHandle(rootDir) {
108
+ const jsonPath = join(rootDir, 'plan.json');
109
+ if (!existsSync(jsonPath)) {
110
+ return { rootDir, tasks: [], counter: 0, rootFields: {} };
111
+ }
112
+ let parsed;
113
+ try {
114
+ const raw = JSON.parse(readFileSync(jsonPath, 'utf8'));
115
+ if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
116
+ throw new Error('root is not a JSON object');
117
+ }
118
+ parsed = raw;
119
+ }
120
+ catch {
121
+ throw new PlanStoreError(`PLAN_CORRUPT: ${jsonPath} is not valid JSON — refusing to overwrite a ` +
122
+ `possibly hand-edited or crashed write. Fix or remove the file (a ` +
123
+ `.bak may exist), then retry.`, 'PLAN_CORRUPT');
124
+ }
125
+ const { tasks: rawTasks, counter, schemaVersion: _schemaVersion, ...rootFields } = parsed;
126
+ const tasks = (Array.isArray(rawTasks) ? rawTasks : [])
127
+ .map(normalizeTask)
128
+ .filter((t) => typeof t.id === 'string' && t.id.length > 0);
129
+ const numericCounter = typeof counter === 'number' && Number.isFinite(counter) && counter >= 0
130
+ ? Math.floor(counter)
131
+ : 0;
132
+ return { rootDir, tasks, counter: numericCounter, rootFields };
133
+ }
134
+ function saveHandle(rootDir, handle) {
135
+ if (handle.tasks.length > PLAN_MAX_TASKS) {
136
+ throw new PlanStoreError(`PLAN_TOO_MANY_TASKS: plan.json would exceed ${PLAN_MAX_TASKS} tasks ` +
137
+ `(${handle.tasks.length}) — cancel or complete tasks first.`, 'PLAN_TOO_MANY_TASKS');
138
+ }
139
+ const jsonPath = join(rootDir, 'plan.json');
140
+ mkdirSync(rootDir, { recursive: true });
141
+ if (existsSync(jsonPath)) {
142
+ copyFileSync(jsonPath, `${jsonPath}.bak`);
143
+ }
144
+ const file = {
145
+ ...handle.rootFields,
146
+ schemaVersion: PLAN_SCHEMA_VERSION,
147
+ counter: handle.counter,
148
+ tasks: handle.tasks,
149
+ };
150
+ const tmp = `${jsonPath}.tmp-${process.pid}`;
151
+ writeFileSync(tmp, JSON.stringify(file, null, 2) + '\n', 'utf8');
152
+ renameSync(tmp, jsonPath);
153
+ }
154
+ /** Normalize a raw task record (council or v1) into the contract shape. */
155
+ function normalizeTask(raw) {
156
+ const t = (raw !== null && typeof raw === 'object'
157
+ ? { ...raw }
158
+ : {});
159
+ if (typeof t.id === 'string') {
160
+ t.id = t.id.trim().slice(0, 64);
161
+ }
162
+ const titleSource = firstString(t.title) ??
163
+ firstString(t.name) ??
164
+ firstString(t.description) ??
165
+ '';
166
+ t.title = titleSource.slice(0, PLAN_TITLE_MAX);
167
+ // Council readers (buildPlanSummary) render `name` — keep the alias in
168
+ // sync so t<N> tasks display correctly there too.
169
+ if (t.title && !firstString(t.name)) {
170
+ t.name = t.title;
171
+ }
172
+ t.status = normalizeStatus(t.status);
173
+ if (typeof t.notes === 'string') {
174
+ t.notes = t.notes.slice(0, PLAN_NOTES_MAX);
175
+ }
176
+ if (typeof t.phaseId === 'string') {
177
+ t.phaseId = t.phaseId.slice(0, PLAN_TAG_MAX);
178
+ }
179
+ if (typeof t.agent === 'string') {
180
+ t.agent = t.agent.slice(0, PLAN_TAG_MAX);
181
+ }
182
+ return t;
183
+ }
184
+ function normalizeStatus(raw) {
185
+ const s = typeof raw === 'string' ? raw.trim().toLowerCase() : '';
186
+ switch (s) {
187
+ case 'in_progress':
188
+ case 'in-progress':
189
+ case 'doing':
190
+ case 'started':
191
+ case 'active':
192
+ return 'in_progress';
193
+ case 'completed':
194
+ case 'complete':
195
+ case 'done':
196
+ case 'finished':
197
+ return 'completed';
198
+ case 'cancelled':
199
+ case 'canceled':
200
+ case 'closed':
201
+ return 'cancelled';
202
+ case 'blocked':
203
+ case 'on-hold':
204
+ case 'on hold':
205
+ return 'blocked';
206
+ default:
207
+ return 'pending';
208
+ }
209
+ }
210
+ function firstString(v) {
211
+ return typeof v === 'string' && v.trim().length > 0 ? v : null;
212
+ }
213
+ //# sourceMappingURL=planStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"planStore.js","sourceRoot":"","sources":["../../../src/cli/workspace/planStore.ts"],"names":[],"mappings":"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"}