pi-anchor 0.1.0 → 0.1.1
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/dist/{chunk-NNYUD5O7.js → chunk-QKBUATPO.js} +25 -15
- package/dist/extension.cjs +61 -15
- package/dist/extension.js +37 -1
- package/dist/index.cjs +25 -15
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/extension.ts +38 -0
- package/src/pi-types.d.ts +2 -0
- package/src/tui.ts +31 -18
|
@@ -1191,22 +1191,32 @@ function updateStartupBanner(ctx, store) {
|
|
|
1191
1191
|
}
|
|
1192
1192
|
const groups = groupAnchorsByQuadrant(active);
|
|
1193
1193
|
const sorted = [...groups.today, ...groups.upcoming, ...groups.habits, ...groups.backlog];
|
|
1194
|
-
const lines = [
|
|
1195
|
-
`\u2316 Anchor \xB7 ${active.length} active commitments:`
|
|
1196
|
-
];
|
|
1197
1194
|
const topItems = sorted.slice(0, 3);
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1195
|
+
const factory = (_tui, theme) => ({
|
|
1196
|
+
render: (width) => {
|
|
1197
|
+
const maxTitleWidth = Math.max(16, width - 36);
|
|
1198
|
+
const fg = theme?.fg ? theme.fg.bind(theme) : (_c, text) => text;
|
|
1199
|
+
const lines = [
|
|
1200
|
+
fg("accent", `\u2316 Anchor \xB7 ${active.length} active commitments:`)
|
|
1201
|
+
];
|
|
1202
|
+
for (let i = 0; i < topItems.length; i++) {
|
|
1203
|
+
const a = topItems[i];
|
|
1204
|
+
const num = (i + 1).toString().padStart(2, "0");
|
|
1205
|
+
const q = classifyAnchor(a);
|
|
1206
|
+
const tgt = formatTargetDate(a);
|
|
1207
|
+
const titlePadded = truncateToWidth(a.title, maxTitleWidth);
|
|
1208
|
+
lines.push(` \u2022 ${fg("muted", `[${q}]`)} ${fg("dim", num)} ${titlePadded} ${fg("dim", `(${tgt})`)}`);
|
|
1209
|
+
}
|
|
1210
|
+
if (sorted.length > 3) {
|
|
1211
|
+
lines.push(fg("dim", ` (+${sorted.length - 3} more \xB7 run /anchor to inspect)`));
|
|
1212
|
+
}
|
|
1213
|
+
return lines;
|
|
1214
|
+
},
|
|
1215
|
+
invalidate: () => {
|
|
1216
|
+
}
|
|
1217
|
+
});
|
|
1218
|
+
const content = ctx.ui?.theme ? factory : factory().render(80);
|
|
1219
|
+
ctx.ui.setWidget("anchor-startup", content, { placement: "aboveEditor" });
|
|
1210
1220
|
}
|
|
1211
1221
|
async function openAnchorDashboard(ctx, store) {
|
|
1212
1222
|
if (!ctx.hasUI || !ctx.ui) return;
|
package/dist/extension.cjs
CHANGED
|
@@ -1205,22 +1205,32 @@ function updateStartupBanner(ctx, store) {
|
|
|
1205
1205
|
}
|
|
1206
1206
|
const groups = groupAnchorsByQuadrant(active);
|
|
1207
1207
|
const sorted = [...groups.today, ...groups.upcoming, ...groups.habits, ...groups.backlog];
|
|
1208
|
-
const lines = [
|
|
1209
|
-
`\u2316 Anchor \xB7 ${active.length} active commitments:`
|
|
1210
|
-
];
|
|
1211
1208
|
const topItems = sorted.slice(0, 3);
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1209
|
+
const factory = (_tui, theme) => ({
|
|
1210
|
+
render: (width) => {
|
|
1211
|
+
const maxTitleWidth = Math.max(16, width - 36);
|
|
1212
|
+
const fg = theme?.fg ? theme.fg.bind(theme) : (_c, text) => text;
|
|
1213
|
+
const lines = [
|
|
1214
|
+
fg("accent", `\u2316 Anchor \xB7 ${active.length} active commitments:`)
|
|
1215
|
+
];
|
|
1216
|
+
for (let i = 0; i < topItems.length; i++) {
|
|
1217
|
+
const a = topItems[i];
|
|
1218
|
+
const num = (i + 1).toString().padStart(2, "0");
|
|
1219
|
+
const q = classifyAnchor(a);
|
|
1220
|
+
const tgt = formatTargetDate(a);
|
|
1221
|
+
const titlePadded = truncateToWidth(a.title, maxTitleWidth);
|
|
1222
|
+
lines.push(` \u2022 ${fg("muted", `[${q}]`)} ${fg("dim", num)} ${titlePadded} ${fg("dim", `(${tgt})`)}`);
|
|
1223
|
+
}
|
|
1224
|
+
if (sorted.length > 3) {
|
|
1225
|
+
lines.push(fg("dim", ` (+${sorted.length - 3} more \xB7 run /anchor to inspect)`));
|
|
1226
|
+
}
|
|
1227
|
+
return lines;
|
|
1228
|
+
},
|
|
1229
|
+
invalidate: () => {
|
|
1230
|
+
}
|
|
1231
|
+
});
|
|
1232
|
+
const content = ctx.ui?.theme ? factory : factory().render(80);
|
|
1233
|
+
ctx.ui.setWidget("anchor-startup", content, { placement: "aboveEditor" });
|
|
1224
1234
|
}
|
|
1225
1235
|
async function openAnchorDashboard(ctx, store) {
|
|
1226
1236
|
if (!ctx.hasUI || !ctx.ui) return;
|
|
@@ -1426,6 +1436,42 @@ Mark as completed and archive?`
|
|
|
1426
1436
|
verifyCommand: import_typebox.Type.Optional(import_typebox.Type.String({ description: "Optional shell command for automated physical verification" })),
|
|
1427
1437
|
id: import_typebox.Type.Optional(import_typebox.Type.String({ description: "Anchor ID, e.g. anc-1 (for settle or touch)" }))
|
|
1428
1438
|
}),
|
|
1439
|
+
renderCall(args, theme) {
|
|
1440
|
+
const action = args.action || "list";
|
|
1441
|
+
let title = theme.fg("toolTitle", theme.bold("\u2316 anchor ")) + theme.fg("accent", action);
|
|
1442
|
+
if (action === "pin" && args.title) {
|
|
1443
|
+
const due = args.targetDate ? ` ${theme.fg("dim", `[${args.targetDate}]`)}` : "";
|
|
1444
|
+
const files = args.files && args.files.length > 0 ? ` ${theme.fg("muted", `(${args.files.slice(0, 2).join(", ")})`)}` : "";
|
|
1445
|
+
title += ` "${args.title}"${due}${files}`;
|
|
1446
|
+
} else if (action === "settle" && args.id) {
|
|
1447
|
+
title += ` ${theme.fg("dim", `#${args.id}`)}`;
|
|
1448
|
+
} else if (action === "touch" && args.id) {
|
|
1449
|
+
title += ` ${theme.fg("dim", `#${args.id}`)}`;
|
|
1450
|
+
} else if (action === "list") {
|
|
1451
|
+
if (args.priority) title += ` ${theme.fg("muted", `[${args.priority}]`)}`;
|
|
1452
|
+
}
|
|
1453
|
+
return {
|
|
1454
|
+
render: () => [title],
|
|
1455
|
+
invalidate: () => {
|
|
1456
|
+
}
|
|
1457
|
+
};
|
|
1458
|
+
},
|
|
1459
|
+
renderResult(result, _options, theme) {
|
|
1460
|
+
if (result.isError) {
|
|
1461
|
+
const errText = result.content?.[0]?.text || "Execution failed";
|
|
1462
|
+
return {
|
|
1463
|
+
render: () => [theme.fg("error", `\u2717 ${errText}`)],
|
|
1464
|
+
invalidate: () => {
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1467
|
+
}
|
|
1468
|
+
const text = result.content?.[0]?.text || "OK";
|
|
1469
|
+
return {
|
|
1470
|
+
render: () => [theme.fg("success", `\u2714 ${text}`)],
|
|
1471
|
+
invalidate: () => {
|
|
1472
|
+
}
|
|
1473
|
+
};
|
|
1474
|
+
},
|
|
1429
1475
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
1430
1476
|
if (!ctx) return { content: [{ type: "text", text: "Error: context required" }], isError: true };
|
|
1431
1477
|
if (params.action === "pin") {
|
package/dist/extension.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
sweepStore,
|
|
12
12
|
updateAnchorStatusBar,
|
|
13
13
|
updateStartupBanner
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-QKBUATPO.js";
|
|
15
15
|
|
|
16
16
|
// src/extension.ts
|
|
17
17
|
import { Type } from "@sinclair/typebox";
|
|
@@ -175,6 +175,42 @@ Mark as completed and archive?`
|
|
|
175
175
|
verifyCommand: Type.Optional(Type.String({ description: "Optional shell command for automated physical verification" })),
|
|
176
176
|
id: Type.Optional(Type.String({ description: "Anchor ID, e.g. anc-1 (for settle or touch)" }))
|
|
177
177
|
}),
|
|
178
|
+
renderCall(args, theme) {
|
|
179
|
+
const action = args.action || "list";
|
|
180
|
+
let title = theme.fg("toolTitle", theme.bold("\u2316 anchor ")) + theme.fg("accent", action);
|
|
181
|
+
if (action === "pin" && args.title) {
|
|
182
|
+
const due = args.targetDate ? ` ${theme.fg("dim", `[${args.targetDate}]`)}` : "";
|
|
183
|
+
const files = args.files && args.files.length > 0 ? ` ${theme.fg("muted", `(${args.files.slice(0, 2).join(", ")})`)}` : "";
|
|
184
|
+
title += ` "${args.title}"${due}${files}`;
|
|
185
|
+
} else if (action === "settle" && args.id) {
|
|
186
|
+
title += ` ${theme.fg("dim", `#${args.id}`)}`;
|
|
187
|
+
} else if (action === "touch" && args.id) {
|
|
188
|
+
title += ` ${theme.fg("dim", `#${args.id}`)}`;
|
|
189
|
+
} else if (action === "list") {
|
|
190
|
+
if (args.priority) title += ` ${theme.fg("muted", `[${args.priority}]`)}`;
|
|
191
|
+
}
|
|
192
|
+
return {
|
|
193
|
+
render: () => [title],
|
|
194
|
+
invalidate: () => {
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
},
|
|
198
|
+
renderResult(result, _options, theme) {
|
|
199
|
+
if (result.isError) {
|
|
200
|
+
const errText = result.content?.[0]?.text || "Execution failed";
|
|
201
|
+
return {
|
|
202
|
+
render: () => [theme.fg("error", `\u2717 ${errText}`)],
|
|
203
|
+
invalidate: () => {
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
const text = result.content?.[0]?.text || "OK";
|
|
208
|
+
return {
|
|
209
|
+
render: () => [theme.fg("success", `\u2714 ${text}`)],
|
|
210
|
+
invalidate: () => {
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
},
|
|
178
214
|
async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
|
|
179
215
|
if (!ctx) return { content: [{ type: "text", text: "Error: context required" }], isError: true };
|
|
180
216
|
if (params.action === "pin") {
|
package/dist/index.cjs
CHANGED
|
@@ -1038,22 +1038,32 @@ function updateStartupBanner(ctx, store) {
|
|
|
1038
1038
|
}
|
|
1039
1039
|
const groups = groupAnchorsByQuadrant(active);
|
|
1040
1040
|
const sorted = [...groups.today, ...groups.upcoming, ...groups.habits, ...groups.backlog];
|
|
1041
|
-
const lines = [
|
|
1042
|
-
`\u2316 Anchor \xB7 ${active.length} active commitments:`
|
|
1043
|
-
];
|
|
1044
1041
|
const topItems = sorted.slice(0, 3);
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1042
|
+
const factory = (_tui, theme) => ({
|
|
1043
|
+
render: (width) => {
|
|
1044
|
+
const maxTitleWidth = Math.max(16, width - 36);
|
|
1045
|
+
const fg = theme?.fg ? theme.fg.bind(theme) : (_c, text) => text;
|
|
1046
|
+
const lines = [
|
|
1047
|
+
fg("accent", `\u2316 Anchor \xB7 ${active.length} active commitments:`)
|
|
1048
|
+
];
|
|
1049
|
+
for (let i = 0; i < topItems.length; i++) {
|
|
1050
|
+
const a = topItems[i];
|
|
1051
|
+
const num = (i + 1).toString().padStart(2, "0");
|
|
1052
|
+
const q = classifyAnchor(a);
|
|
1053
|
+
const tgt = formatTargetDate(a);
|
|
1054
|
+
const titlePadded = truncateToWidth(a.title, maxTitleWidth);
|
|
1055
|
+
lines.push(` \u2022 ${fg("muted", `[${q}]`)} ${fg("dim", num)} ${titlePadded} ${fg("dim", `(${tgt})`)}`);
|
|
1056
|
+
}
|
|
1057
|
+
if (sorted.length > 3) {
|
|
1058
|
+
lines.push(fg("dim", ` (+${sorted.length - 3} more \xB7 run /anchor to inspect)`));
|
|
1059
|
+
}
|
|
1060
|
+
return lines;
|
|
1061
|
+
},
|
|
1062
|
+
invalidate: () => {
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
const content = ctx.ui?.theme ? factory : factory().render(80);
|
|
1066
|
+
ctx.ui.setWidget("anchor-startup", content, { placement: "aboveEditor" });
|
|
1057
1067
|
}
|
|
1058
1068
|
async function openAnchorDashboard(ctx, store) {
|
|
1059
1069
|
if (!ctx.hasUI || !ctx.ui) return;
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
package/src/extension.ts
CHANGED
|
@@ -212,6 +212,44 @@ export default function (pi: ExtensionAPI) {
|
|
|
212
212
|
verifyCommand: Type.Optional(Type.String({ description: 'Optional shell command for automated physical verification' })),
|
|
213
213
|
id: Type.Optional(Type.String({ description: 'Anchor ID, e.g. anc-1 (for settle or touch)' }))
|
|
214
214
|
}),
|
|
215
|
+
renderCall(args: any, theme: any) {
|
|
216
|
+
const action = args.action || 'list';
|
|
217
|
+
let title = theme.fg('toolTitle', theme.bold('⌖ anchor ')) + theme.fg('accent', action);
|
|
218
|
+
|
|
219
|
+
if (action === 'pin' && args.title) {
|
|
220
|
+
const due = args.targetDate ? ` ${theme.fg('dim', `[${args.targetDate}]`)}` : '';
|
|
221
|
+
const files = (args.files && args.files.length > 0)
|
|
222
|
+
? ` ${theme.fg('muted', `(${args.files.slice(0, 2).join(', ')})`)}`
|
|
223
|
+
: '';
|
|
224
|
+
title += ` "${args.title}"${due}${files}`;
|
|
225
|
+
} else if (action === 'settle' && args.id) {
|
|
226
|
+
title += ` ${theme.fg('dim', `#${args.id}`)}`;
|
|
227
|
+
} else if (action === 'touch' && args.id) {
|
|
228
|
+
title += ` ${theme.fg('dim', `#${args.id}`)}`;
|
|
229
|
+
} else if (action === 'list') {
|
|
230
|
+
if (args.priority) title += ` ${theme.fg('muted', `[${args.priority}]`)}`;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return {
|
|
234
|
+
render: () => [title],
|
|
235
|
+
invalidate: () => {}
|
|
236
|
+
};
|
|
237
|
+
},
|
|
238
|
+
renderResult(result: any, _options: any, theme: any) {
|
|
239
|
+
if (result.isError) {
|
|
240
|
+
const errText = result.content?.[0]?.text || 'Execution failed';
|
|
241
|
+
return {
|
|
242
|
+
render: () => [theme.fg('error', `✗ ${errText}`)],
|
|
243
|
+
invalidate: () => {}
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const text = result.content?.[0]?.text || 'OK';
|
|
248
|
+
return {
|
|
249
|
+
render: () => [theme.fg('success', `✔ ${text}`)],
|
|
250
|
+
invalidate: () => {}
|
|
251
|
+
};
|
|
252
|
+
},
|
|
215
253
|
async execute(_toolCallId: string, params: any, _signal?: AbortSignal, _onUpdate?: (partial: any) => void, ctx?: ExtensionContext) {
|
|
216
254
|
if (!ctx) return { content: [{ type: 'text', text: 'Error: context required' }], isError: true };
|
|
217
255
|
if (params.action === 'pin') {
|
package/src/pi-types.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ declare module '@earendil-works/pi-coding-agent' {
|
|
|
18
18
|
promptSnippet?: string;
|
|
19
19
|
promptGuidelines?: string[];
|
|
20
20
|
parameters: unknown;
|
|
21
|
+
renderCall?: (args: any, theme: any, context?: any) => any;
|
|
22
|
+
renderResult?: (result: any, options: any, theme: any, context?: any) => any;
|
|
21
23
|
execute: (
|
|
22
24
|
toolCallId: string,
|
|
23
25
|
params: any,
|
package/src/tui.ts
CHANGED
|
@@ -298,26 +298,39 @@ export function updateStartupBanner(ctx: ExtensionContext, store: AnchorStore):
|
|
|
298
298
|
|
|
299
299
|
const groups = groupAnchorsByQuadrant(active);
|
|
300
300
|
const sorted = [...groups.today, ...groups.upcoming, ...groups.habits, ...groups.backlog];
|
|
301
|
-
|
|
302
|
-
const lines: string[] = [
|
|
303
|
-
`⌖ Anchor · ${active.length} active commitments:`
|
|
304
|
-
];
|
|
305
|
-
|
|
306
301
|
const topItems = sorted.slice(0, 3);
|
|
307
|
-
for (let i = 0; i < topItems.length; i++) {
|
|
308
|
-
const a = topItems[i];
|
|
309
|
-
const num = (i + 1).toString().padStart(2, '0');
|
|
310
|
-
const q = classifyAnchor(a);
|
|
311
|
-
const tgt = formatTargetDate(a);
|
|
312
|
-
const titlePadded = a.title.length > 34 ? a.title.slice(0, 32) + '..' : a.title;
|
|
313
|
-
lines.push(` • [${q}] ${num} ${titlePadded} (${tgt})`);
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
if (sorted.length > 3) {
|
|
317
|
-
lines.push(` (+${sorted.length - 3} more · run /anchor to inspect)`);
|
|
318
|
-
}
|
|
319
302
|
|
|
320
|
-
|
|
303
|
+
const factory = (_tui?: any, theme?: any) => ({
|
|
304
|
+
render: (width: number) => {
|
|
305
|
+
const maxTitleWidth = Math.max(16, width - 36);
|
|
306
|
+
const fg = theme?.fg ? theme.fg.bind(theme) : (_c: string, text: string) => text;
|
|
307
|
+
|
|
308
|
+
const lines: string[] = [
|
|
309
|
+
fg('accent', `⌖ Anchor · ${active.length} active commitments:`)
|
|
310
|
+
];
|
|
311
|
+
|
|
312
|
+
for (let i = 0; i < topItems.length; i++) {
|
|
313
|
+
const a = topItems[i];
|
|
314
|
+
const num = (i + 1).toString().padStart(2, '0');
|
|
315
|
+
const q = classifyAnchor(a);
|
|
316
|
+
const tgt = formatTargetDate(a);
|
|
317
|
+
const titlePadded = truncateToWidth(a.title, maxTitleWidth);
|
|
318
|
+
lines.push(` • ${fg('muted', `[${q}]`)} ${fg('dim', num)} ${titlePadded} ${fg('dim', `(${tgt})`)}`);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (sorted.length > 3) {
|
|
322
|
+
lines.push(fg('dim', ` (+${sorted.length - 3} more · run /anchor to inspect)`));
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return lines;
|
|
326
|
+
},
|
|
327
|
+
invalidate: () => {}
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
// Reactive component factory in real TUI mode, static string[] in mock tests
|
|
331
|
+
const content = (ctx as any).ui?.theme ? factory : factory().render(80);
|
|
332
|
+
|
|
333
|
+
ctx.ui.setWidget('anchor-startup', content as any, { placement: 'aboveEditor' });
|
|
321
334
|
}
|
|
322
335
|
|
|
323
336
|
/**
|