@vigent/cli 0.2.3 → 0.3.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/README.md +48 -48
- package/dist/agents.js +29 -0
- package/dist/app.js +521 -20
- package/dist/attach.js +102 -0
- package/dist/choices.js +4 -1
- package/dist/cli-engines.js +15 -5
- package/dist/cli.js +25 -15
- package/dist/config.js +26 -2
- package/dist/diffview.js +1 -1
- package/dist/engines.js +18 -11
- package/dist/float.js +1 -1
- package/dist/hunk-review.js +218 -0
- package/dist/hunks.js +60 -0
- package/dist/icons.js +1 -0
- package/dist/keys.js +3 -1
- package/dist/main.js +16 -0
- package/dist/markdown.js +1 -1
- package/dist/notify.js +33 -0
- package/dist/pi-sdk.js +45 -0
- package/dist/pi-ui.js +78 -0
- package/dist/picker.js +21 -11
- package/dist/serve-page.js +247 -0
- package/dist/serve.js +267 -0
- package/dist/session.js +122 -11
- package/dist/settings.js +1 -1
- package/dist/templates.js +125 -0
- package/dist/theme.js +2 -0
- package/dist/tui.js +13 -0
- package/package.json +5 -5
package/dist/session.js
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session layer: one Session per agent.
|
|
3
|
+
*
|
|
4
|
+
* - PiSession runs a real pi coding agent in-process, with its read / write /
|
|
5
|
+
* edit / bash tools rooted in the agent's own git worktree.
|
|
6
|
+
* - DemoSession replays a scripted transcript so the UI can be explored
|
|
7
|
+
* without API keys.
|
|
8
|
+
*/
|
|
9
|
+
import { expandPrompt } from "./attach.js";
|
|
10
|
+
import { loadPiAi, loadPiSdk } from "./pi-sdk.js";
|
|
11
|
+
import { extensionUi, piResources } from "./pi-ui.js";
|
|
1
12
|
import { flattenTree } from "./tree.js";
|
|
2
13
|
import { diffStat } from "./worktree.js";
|
|
3
14
|
export const STATE_GLYPH = {
|
|
@@ -20,6 +31,8 @@ export class Session {
|
|
|
20
31
|
state = "idle";
|
|
21
32
|
items = [];
|
|
22
33
|
tokens = 0;
|
|
34
|
+
/** money spent, in US dollars, as the engine reports it; undefined = the engine doesn't say (Codex) */
|
|
35
|
+
cost;
|
|
23
36
|
version = 0; // bumped on every change, used for render caching
|
|
24
37
|
listeners = new Set();
|
|
25
38
|
statTimer;
|
|
@@ -244,7 +257,7 @@ export class PiSession extends Session {
|
|
|
244
257
|
this.ready = this.init();
|
|
245
258
|
}
|
|
246
259
|
async init() {
|
|
247
|
-
const sdk = await
|
|
260
|
+
const sdk = await loadPiSdk();
|
|
248
261
|
const sessionManager = this.opts.sessionDir
|
|
249
262
|
? sdk.SessionManager.continueRecent(this.cwd, this.opts.sessionDir)
|
|
250
263
|
: sdk.SessionManager.inMemory();
|
|
@@ -263,10 +276,13 @@ export class PiSession extends Session {
|
|
|
263
276
|
...(this.opts.agentDir ? { agentDir: this.opts.agentDir } : {}),
|
|
264
277
|
});
|
|
265
278
|
this.session = session;
|
|
279
|
+
await this.bindExtensions(sdk, session);
|
|
266
280
|
if (resuming) {
|
|
267
281
|
const restored = itemsFromMessages(session.messages ?? []);
|
|
268
282
|
this.items.push(...restored.items);
|
|
269
283
|
this.tokens += restored.tokens;
|
|
284
|
+
if (restored.cost !== undefined)
|
|
285
|
+
this.cost = (this.cost ?? 0) + restored.cost;
|
|
270
286
|
this.pushInfo(`resumed: ${restored.items.filter((i) => i.kind === "user").length} earlier prompts`);
|
|
271
287
|
this.refreshStat(0);
|
|
272
288
|
}
|
|
@@ -306,8 +322,11 @@ export class PiSession extends Session {
|
|
|
306
322
|
last.text = extractText(event.message.content);
|
|
307
323
|
last.streaming = false;
|
|
308
324
|
const usage = event.message?.usage;
|
|
309
|
-
if (usage)
|
|
310
|
-
this.tokens += (usage
|
|
325
|
+
if (usage) {
|
|
326
|
+
this.tokens += usageTokens(usage);
|
|
327
|
+
if (typeof usage.cost?.total === "number")
|
|
328
|
+
this.cost = (this.cost ?? 0) + usage.cost.total;
|
|
329
|
+
}
|
|
311
330
|
if (!last.text)
|
|
312
331
|
this.items.pop(); // a turn that only called tools
|
|
313
332
|
this.emit();
|
|
@@ -377,15 +396,93 @@ export class PiSession extends Session {
|
|
|
377
396
|
this.emit();
|
|
378
397
|
return { editorText: r.editorText };
|
|
379
398
|
}
|
|
399
|
+
/** where this agent's extensions show dialogs and messages (set by the app) */
|
|
400
|
+
uiHost;
|
|
401
|
+
/** statuses extensions keep up to date (ctx.ui.setStatus), shown in the winbar */
|
|
402
|
+
extensionStatus = new Map();
|
|
403
|
+
/**
|
|
404
|
+
* Hand pi's extensions their UI and start them (session_start), as pi's
|
|
405
|
+
* own modes do. Without this, an extension's confirm() always answers no
|
|
406
|
+
* and its notify() goes nowhere.
|
|
407
|
+
*/
|
|
408
|
+
async bindExtensions(sdk, session) {
|
|
409
|
+
const THEME = Symbol.for("@mariozechner/pi-coding-agent:theme");
|
|
410
|
+
try {
|
|
411
|
+
if (!globalThis[THEME])
|
|
412
|
+
sdk.initTheme?.(undefined, false);
|
|
413
|
+
}
|
|
414
|
+
catch {
|
|
415
|
+
// extensions that style text get plain text
|
|
416
|
+
}
|
|
417
|
+
const ui = extensionUi(() => this.uiHost ?? this.fallbackUi, () => globalThis[THEME]);
|
|
418
|
+
try {
|
|
419
|
+
await session.bindExtensions({
|
|
420
|
+
uiContext: ui,
|
|
421
|
+
commandContextActions: {
|
|
422
|
+
waitForIdle: () => session.agent.waitForIdle(),
|
|
423
|
+
// one conversation per agent in vigent: :new starts another agent
|
|
424
|
+
newSession: async () => ({ cancelled: true }),
|
|
425
|
+
fork: async () => ({ cancelled: true }),
|
|
426
|
+
switchSession: async () => ({ cancelled: true }),
|
|
427
|
+
navigateTree: async (targetId) => {
|
|
428
|
+
const r = await session.navigateTree(targetId, {});
|
|
429
|
+
return { cancelled: r.cancelled };
|
|
430
|
+
},
|
|
431
|
+
reload: async () => {
|
|
432
|
+
await session.reload();
|
|
433
|
+
},
|
|
434
|
+
},
|
|
435
|
+
onError: (err) => this.pushInfo(`extension error (${shortExtPath(err?.extensionPath)}${err?.event ? `, ${err.event}` : ""}): ${err?.error ?? err}`),
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
catch (err) {
|
|
439
|
+
this.pushInfo(`pi extensions didn't start: ${String(err?.message ?? err)}`);
|
|
440
|
+
}
|
|
441
|
+
const failed = piResources(session).extensions.filter((e) => e.error);
|
|
442
|
+
for (const e of failed)
|
|
443
|
+
this.pushInfo(`extension ${shortExtPath(e.path)} didn't load: ${e.error}`);
|
|
444
|
+
}
|
|
445
|
+
/** with no screen to ask on: messages still reach the transcript, dialogs answer no */
|
|
446
|
+
fallbackUi = {
|
|
447
|
+
select: async () => undefined,
|
|
448
|
+
confirm: async () => false,
|
|
449
|
+
input: async () => undefined,
|
|
450
|
+
notify: (message) => this.pushInfo(message),
|
|
451
|
+
setStatus: (key, text) => this.setExtensionStatus(key, text),
|
|
452
|
+
};
|
|
453
|
+
setExtensionStatus(key, text) {
|
|
454
|
+
if (text)
|
|
455
|
+
this.extensionStatus.set(key, text);
|
|
456
|
+
else
|
|
457
|
+
this.extensionStatus.delete(key);
|
|
458
|
+
this.emit();
|
|
459
|
+
}
|
|
460
|
+
/** What pi loaded for this agent: extensions, their commands, skills, prompt templates, AGENTS.md files. */
|
|
461
|
+
resources() {
|
|
462
|
+
return this.session ? piResources(this.session) : undefined;
|
|
463
|
+
}
|
|
380
464
|
send(text) {
|
|
381
465
|
this.pushUser(text);
|
|
382
466
|
this.setState("running");
|
|
467
|
+
const attached = expandPrompt(text, "pi", this.cwd);
|
|
468
|
+
if (attached.skipped.length)
|
|
469
|
+
this.pushInfo(`not attached: ${attached.skipped.join(", ")}`);
|
|
383
470
|
this.ready
|
|
384
471
|
// pi reports agent_end a moment before it accepts the next prompt (queued prompts hit this)
|
|
385
472
|
.then(() => this.session.agent?.waitForIdle?.())
|
|
386
|
-
.then(() => this.session.prompt(
|
|
473
|
+
.then(() => this.session.prompt(attached.prompt))
|
|
474
|
+
// an extension command (/name) or a handled input runs no turn: nothing else will end it
|
|
475
|
+
.then(() => {
|
|
476
|
+
if (this.state === "running")
|
|
477
|
+
this.setState("idle");
|
|
478
|
+
})
|
|
387
479
|
.catch((err) => {
|
|
388
|
-
|
|
480
|
+
const text = String(err?.message ?? err);
|
|
481
|
+
// pi's own advice (/login, its docs paths) is for pi's TUI, not vigent: keep its first line
|
|
482
|
+
const key = /api key|login|auth/i.test(text);
|
|
483
|
+
this.pushInfo(`error: ${key ? text.split("\n")[0] : text}`);
|
|
484
|
+
if (key)
|
|
485
|
+
this.pushInfo(PI_KEY_HINT);
|
|
389
486
|
this.setState("error");
|
|
390
487
|
});
|
|
391
488
|
}
|
|
@@ -403,6 +500,7 @@ export function itemsFromMessages(messages) {
|
|
|
403
500
|
const items = [];
|
|
404
501
|
const byCallId = new Map();
|
|
405
502
|
let tokens = 0;
|
|
503
|
+
let cost;
|
|
406
504
|
for (const m of messages) {
|
|
407
505
|
if (m?.role === "user") {
|
|
408
506
|
const text = extractText(m.content);
|
|
@@ -426,8 +524,11 @@ export function itemsFromMessages(messages) {
|
|
|
426
524
|
if (b.id)
|
|
427
525
|
byCallId.set(b.id, item);
|
|
428
526
|
}
|
|
429
|
-
if (m.usage)
|
|
430
|
-
tokens += (m.usage
|
|
527
|
+
if (m.usage) {
|
|
528
|
+
tokens += usageTokens(m.usage);
|
|
529
|
+
if (typeof m.usage.cost?.total === "number")
|
|
530
|
+
cost = (cost ?? 0) + m.usage.cost.total;
|
|
531
|
+
}
|
|
431
532
|
const err = piError(m);
|
|
432
533
|
if (err)
|
|
433
534
|
items.push({ kind: "info", text: err });
|
|
@@ -438,8 +539,14 @@ export function itemsFromMessages(messages) {
|
|
|
438
539
|
item.tool.output = extractText(m.content);
|
|
439
540
|
}
|
|
440
541
|
}
|
|
441
|
-
return { items, tokens };
|
|
542
|
+
return { items, tokens, cost };
|
|
442
543
|
}
|
|
544
|
+
/** pi's usage: every token the request read or wrote, cached ones included (like Claude Code's count) */
|
|
545
|
+
function usageTokens(u) {
|
|
546
|
+
return u.totalTokens ?? (u.input ?? 0) + (u.output ?? 0) + (u.cacheRead ?? 0) + (u.cacheWrite ?? 0);
|
|
547
|
+
}
|
|
548
|
+
/** What to do when pi can't get through: this agent stays on pi, so start one elsewhere. */
|
|
549
|
+
export const PI_KEY_HINT = "this agent runs on pi, and pi has no working API key. Agents keep the engine they started on: :new <task> starts one on the default engine (:engine picks it, e.g. Claude Code or Codex with your existing login), and :kill removes this one.";
|
|
443
550
|
/**
|
|
444
551
|
* The error of a reply whose request failed (pi ends it with stopReason
|
|
445
552
|
* "error" and an errorMessage), with a hint when the key or login was refused.
|
|
@@ -449,8 +556,7 @@ export function piError(message) {
|
|
|
449
556
|
return undefined;
|
|
450
557
|
const text = String(message.errorMessage ?? "").trim() || "the request failed";
|
|
451
558
|
const auth = /\b(401|403)\b|auth|api[ _-]?key|unauthori[sz]ed|forbidden|credential|expired|login/i.test(text);
|
|
452
|
-
|
|
453
|
-
return `error: ${text}${hint}`;
|
|
559
|
+
return auth ? `error: ${text}\n${PI_KEY_HINT}` : `error: ${text}`;
|
|
454
560
|
}
|
|
455
561
|
function extractText(content) {
|
|
456
562
|
if (typeof content === "string")
|
|
@@ -472,7 +578,7 @@ function summarizeArgs(args) {
|
|
|
472
578
|
}
|
|
473
579
|
/** A pi-ai model from "provider/model", or a bare id (Anthropic's). Undefined when pi doesn't know it. */
|
|
474
580
|
export async function piModel(id) {
|
|
475
|
-
const ai = await
|
|
581
|
+
const ai = await loadPiAi();
|
|
476
582
|
const slash = id.indexOf("/");
|
|
477
583
|
const [provider, modelId] = slash > 0 ? [id.slice(0, slash), id.slice(slash + 1)] : ["anthropic", id];
|
|
478
584
|
try {
|
|
@@ -482,3 +588,8 @@ export async function piModel(id) {
|
|
|
482
588
|
return undefined;
|
|
483
589
|
}
|
|
484
590
|
}
|
|
591
|
+
/** ~/.pi/agent/extensions/guard.ts → extensions/guard.ts */
|
|
592
|
+
function shortExtPath(p) {
|
|
593
|
+
const parts = String(p ?? "extension").split(/[\\/]/);
|
|
594
|
+
return parts.slice(-2).join("/");
|
|
595
|
+
}
|
package/dist/settings.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Changes apply at once. A key row waits for the new keys: type them, then
|
|
8
8
|
* Enter (Esc cancels).
|
|
9
9
|
*/
|
|
10
|
-
import { truncateToWidth, visibleWidth } from "
|
|
10
|
+
import { truncateToWidth, visibleWidth } from "./tui.js";
|
|
11
11
|
import { keyFromInput } from "./keys.js";
|
|
12
12
|
import { RESET } from "./theme.js";
|
|
13
13
|
export class SettingsFloat {
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session templates: a prompt you start agents with often, with the engine,
|
|
3
|
+
* model and effort it should run on.
|
|
4
|
+
*
|
|
5
|
+
* [templates.fix]
|
|
6
|
+
* prompt = "Find and fix this bug: {task}. Reproduce it with a failing test first."
|
|
7
|
+
* engine = "claude"
|
|
8
|
+
* effort = "high"
|
|
9
|
+
*
|
|
10
|
+
* `:new -t fix the cart total is off` starts an agent and sends the prompt,
|
|
11
|
+
* with `{task}` replaced by what you typed. A few are built in; a template
|
|
12
|
+
* in config.toml with the same name replaces the built-in one.
|
|
13
|
+
*/
|
|
14
|
+
import { EFFORTS } from "./choices.js";
|
|
15
|
+
import { isEngineId } from "./engines.js";
|
|
16
|
+
export const BUILTIN_TEMPLATES = [
|
|
17
|
+
{
|
|
18
|
+
name: "fix",
|
|
19
|
+
description: "reproduce a bug with a failing test, then fix it",
|
|
20
|
+
prompt: "Find and fix this bug: {task}\n\nFirst reproduce it with a failing test. Then make the smallest change that makes the test pass, and run the whole test suite before you finish.",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: "test",
|
|
24
|
+
description: "write tests in the project's own style",
|
|
25
|
+
prompt: "Write tests for {task}. Cover the usual cases and the edge cases, follow the style of the tests already in the project, and run them. Don't change the code under test; if a test finds a bug, say so.",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: "review",
|
|
29
|
+
description: "review this branch's work; changes nothing",
|
|
30
|
+
prompt: "Review the work on this branch: compare it with the branch it started from using git. Look for bugs, missing tests and code that's hard to follow.{task}\n\nList what you find by file and line, most serious first. Don't change any files.",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: "explain",
|
|
34
|
+
description: "how something works and where it lives; changes nothing",
|
|
35
|
+
prompt: "Explain {task}: how it works, where it lives in the code, and what would break if it changed. Don't change any files.",
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
/** Whether the prompt has a place for the task. */
|
|
39
|
+
export function needsTask(t) {
|
|
40
|
+
return t.prompt.includes("{task}");
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The prompt for a task. `{task}` takes the task; a template without one gets
|
|
44
|
+
* the task added after it. The review template's `{task}` is optional focus.
|
|
45
|
+
*/
|
|
46
|
+
export function fillTemplate(t, task) {
|
|
47
|
+
const text = task.trim();
|
|
48
|
+
if (!needsTask(t))
|
|
49
|
+
return text ? `${t.prompt}\n\n${text}` : t.prompt;
|
|
50
|
+
if (t.name === "review" && t.builtin)
|
|
51
|
+
return t.prompt.replace("{task}", text ? ` Focus on: ${text}.` : "");
|
|
52
|
+
return t.prompt.split("{task}").join(text);
|
|
53
|
+
}
|
|
54
|
+
/** Built-ins first, then yours (yours replace a built-in of the same name), in config order. */
|
|
55
|
+
export function allTemplates(user) {
|
|
56
|
+
const out = BUILTIN_TEMPLATES.map((t) => user[t.name] ?? { ...t, builtin: true });
|
|
57
|
+
for (const t of Object.values(user))
|
|
58
|
+
if (!BUILTIN_TEMPLATES.some((b) => b.name === t.name))
|
|
59
|
+
out.push(t);
|
|
60
|
+
return out;
|
|
61
|
+
}
|
|
62
|
+
/** `[templates]` from config.toml; problems become warnings, never errors. */
|
|
63
|
+
export function parseTemplates(value, warnings) {
|
|
64
|
+
const out = {};
|
|
65
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
66
|
+
warnings.push("config: [templates] should be a table");
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
for (const [name, raw] of Object.entries(value)) {
|
|
70
|
+
const where = `config [templates.${name}]`;
|
|
71
|
+
if (!/^[\w-]+$/.test(name)) {
|
|
72
|
+
warnings.push(`${where}: a template name is letters, digits, - and _`);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
76
|
+
warnings.push(`${where} should be a table`);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const r = raw;
|
|
80
|
+
if (typeof r.prompt !== "string" || !r.prompt.trim()) {
|
|
81
|
+
warnings.push(`${where}: 'prompt' is required`);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const t = { name, prompt: r.prompt.trim() };
|
|
85
|
+
for (const [k, v] of Object.entries(r)) {
|
|
86
|
+
switch (k) {
|
|
87
|
+
case "prompt":
|
|
88
|
+
break;
|
|
89
|
+
case "description":
|
|
90
|
+
case "model":
|
|
91
|
+
if (typeof v === "string")
|
|
92
|
+
t[k] = v;
|
|
93
|
+
else
|
|
94
|
+
warnings.push(`${where}: '${k}' should be a string`);
|
|
95
|
+
break;
|
|
96
|
+
case "engine":
|
|
97
|
+
if (typeof v === "string" && isEngineId(v))
|
|
98
|
+
t.engine = v;
|
|
99
|
+
else
|
|
100
|
+
warnings.push(`${where}: 'engine' should be "pi", "claude", "codex" or "opencode"`);
|
|
101
|
+
break;
|
|
102
|
+
case "worktree":
|
|
103
|
+
if (typeof v === "boolean")
|
|
104
|
+
t.worktree = v;
|
|
105
|
+
else
|
|
106
|
+
warnings.push(`${where}: 'worktree' should be true or false`);
|
|
107
|
+
break;
|
|
108
|
+
case "effort":
|
|
109
|
+
if (typeof v === "string")
|
|
110
|
+
t.effort = v;
|
|
111
|
+
else
|
|
112
|
+
warnings.push(`${where}: 'effort' should be a string`);
|
|
113
|
+
break;
|
|
114
|
+
default:
|
|
115
|
+
warnings.push(`${where}: unknown option '${k}'`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (t.effort && t.engine && !EFFORTS[t.engine].includes(t.effort)) {
|
|
119
|
+
warnings.push(`${where}: 'effort' should be one of ${EFFORTS[t.engine].join(", ")}`);
|
|
120
|
+
delete t.effort;
|
|
121
|
+
}
|
|
122
|
+
out[name] = t;
|
|
123
|
+
}
|
|
124
|
+
return out;
|
|
125
|
+
}
|
package/dist/theme.js
CHANGED
|
@@ -105,6 +105,8 @@ const LINKS = {
|
|
|
105
105
|
VigentSidebar: "NeoTreeNormal",
|
|
106
106
|
VigentIndent: "NeoTreeIndentMarker",
|
|
107
107
|
VigentUser: "Title",
|
|
108
|
+
/** `@path` in a prompt */
|
|
109
|
+
VigentMention: "Directory",
|
|
108
110
|
VigentTool: "Function",
|
|
109
111
|
VigentToolOutput: "Comment",
|
|
110
112
|
VigentSpinner: "WarningMsg",
|
package/dist/tui.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The parts of pi-tui vigent uses, imported from their own modules.
|
|
3
|
+
*
|
|
4
|
+
* pi-tui's index also loads its editor, markdown (marked), image and
|
|
5
|
+
* autocomplete components, none of which vigent draws; skipping them makes
|
|
6
|
+
* every start faster. Everything from pi-tui goes through this file, so a
|
|
7
|
+
* change in its layout is fixed here once.
|
|
8
|
+
*/
|
|
9
|
+
export { fuzzyFilter } from "@mariozechner/pi-tui/dist/fuzzy.js";
|
|
10
|
+
export { parseKey } from "@mariozechner/pi-tui/dist/keys.js";
|
|
11
|
+
export { ProcessTerminal } from "@mariozechner/pi-tui/dist/terminal.js";
|
|
12
|
+
export { TUI } from "@mariozechner/pi-tui/dist/tui.js";
|
|
13
|
+
export { truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@mariozechner/pi-tui/dist/utils.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vigent/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "A vim-style terminal app for running coding agents side by side, each in its own git worktree. Built on pi.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vim",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"llm",
|
|
16
16
|
"cli"
|
|
17
17
|
],
|
|
18
|
-
"homepage": "https://
|
|
18
|
+
"homepage": "https://vigent.farming-labs.dev",
|
|
19
19
|
"bugs": {
|
|
20
20
|
"url": "https://github.com/farming-labs/vigent/issues"
|
|
21
21
|
},
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"author": "KinfeMichael Tariku",
|
|
28
28
|
"type": "module",
|
|
29
29
|
"bin": {
|
|
30
|
-
"vigent": "./dist/
|
|
30
|
+
"vigent": "./dist/main.js"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"dist",
|
|
@@ -48,8 +48,6 @@
|
|
|
48
48
|
"node": ">=20"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@mariozechner/pi-ai": "^0.73.1",
|
|
52
|
-
"@mariozechner/pi-coding-agent": "^0.73.1",
|
|
53
51
|
"@mariozechner/pi-tui": "^0.73.1",
|
|
54
52
|
"smol-toml": "^1.9.1"
|
|
55
53
|
},
|
|
@@ -58,6 +56,8 @@
|
|
|
58
56
|
"typescript": "^7.0.2"
|
|
59
57
|
},
|
|
60
58
|
"optionalDependencies": {
|
|
59
|
+
"@mariozechner/pi-ai": "^0.73.1",
|
|
60
|
+
"@mariozechner/pi-coding-agent": "^0.73.1",
|
|
61
61
|
"riftri": "^0.6.7"
|
|
62
62
|
},
|
|
63
63
|
"publishConfig": {
|