@pellux/goodvibes-agent 0.1.113 → 0.1.114
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/CHANGELOG.md +6 -0
- package/dist/package/main.js +736 -50
- package/package.json +1 -1
- package/src/agent/persona-discovery.ts +117 -0
- package/src/agent/routine-discovery.ts +115 -0
- package/src/cli/help.ts +9 -1
- package/src/cli/local-library-command.ts +81 -1
- package/src/cli/routines-command.ts +156 -1
- package/src/input/agent-workspace-basic-command-editors.ts +90 -0
- package/src/input/agent-workspace-categories.ts +4 -0
- package/src/input/agent-workspace-command-editor.ts +2 -0
- package/src/input/agent-workspace-types.ts +2 -0
- package/src/input/commands/personas-runtime.ts +87 -2
- package/src/input/commands/routines-runtime.ts +87 -2
- package/src/version.ts +1 -1
package/dist/package/main.js
CHANGED
|
@@ -816523,7 +816523,7 @@ var createStyledCell = (char, overrides = {}) => ({
|
|
|
816523
816523
|
// src/version.ts
|
|
816524
816524
|
import { readFileSync } from "fs";
|
|
816525
816525
|
import { join } from "path";
|
|
816526
|
-
var _version = "0.1.
|
|
816526
|
+
var _version = "0.1.114";
|
|
816527
816527
|
var _sdkVersion = "0.33.35";
|
|
816528
816528
|
try {
|
|
816529
816529
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, "..", "package.json"), "utf-8"));
|
|
@@ -841974,7 +841974,7 @@ async function initializeBootstrapCore(stdout, options, getControlPlaneRecentEve
|
|
|
841974
841974
|
}
|
|
841975
841975
|
|
|
841976
841976
|
// src/runtime/bootstrap-shell.ts
|
|
841977
|
-
import { join as
|
|
841977
|
+
import { join as join91 } from "path";
|
|
841978
841978
|
|
|
841979
841979
|
// src/input/command-registry.ts
|
|
841980
841980
|
class CommandRegistry {
|
|
@@ -852664,6 +852664,100 @@ function registerDelegationRuntimeCommands(registry5) {
|
|
|
852664
852664
|
});
|
|
852665
852665
|
}
|
|
852666
852666
|
|
|
852667
|
+
// src/agent/persona-discovery.ts
|
|
852668
|
+
import { promises as fsPromises5 } from "fs";
|
|
852669
|
+
import { join as join87 } from "path";
|
|
852670
|
+
var DIRECTORY_MARKERS = ["PERSONA.md", "persona.md", "AGENT.md", "agent.md"];
|
|
852671
|
+
function parseFrontmatter2(content) {
|
|
852672
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
852673
|
+
if (!match)
|
|
852674
|
+
return {};
|
|
852675
|
+
const result2 = {};
|
|
852676
|
+
for (const line of match[1].split(`
|
|
852677
|
+
`)) {
|
|
852678
|
+
const [key, ...rest] = line.split(":");
|
|
852679
|
+
if (key && rest.length > 0) {
|
|
852680
|
+
result2[key.trim()] = rest.join(":").trim();
|
|
852681
|
+
}
|
|
852682
|
+
}
|
|
852683
|
+
return result2;
|
|
852684
|
+
}
|
|
852685
|
+
function getPersonaDirectories(cwd, homeDir) {
|
|
852686
|
+
return [
|
|
852687
|
+
{ root: join87(cwd, ".goodvibes", "personas"), origin: "project-local" },
|
|
852688
|
+
{ root: join87(cwd, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "personas"), origin: "project-local" },
|
|
852689
|
+
{ root: join87(cwd, ".goodvibes", "agents"), origin: "project-local" },
|
|
852690
|
+
{ root: join87(homeDir, ".goodvibes", "personas"), origin: "global" },
|
|
852691
|
+
{ root: join87(homeDir, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "personas"), origin: "global" },
|
|
852692
|
+
{ root: join87(homeDir, ".goodvibes", "agents"), origin: "global" }
|
|
852693
|
+
];
|
|
852694
|
+
}
|
|
852695
|
+
async function readPersonaFile(path7, origin) {
|
|
852696
|
+
let content = "";
|
|
852697
|
+
try {
|
|
852698
|
+
content = await fsPromises5.readFile(path7, "utf-8");
|
|
852699
|
+
} catch {
|
|
852700
|
+
return null;
|
|
852701
|
+
}
|
|
852702
|
+
const frontmatter = parseFrontmatter2(content);
|
|
852703
|
+
const markdownBody = content.replace(/^---\n[\s\S]*?\n---\n?/, "").trim();
|
|
852704
|
+
const body2 = (frontmatter.system_prompt ?? markdownBody).trim();
|
|
852705
|
+
if (!body2)
|
|
852706
|
+
return null;
|
|
852707
|
+
const name51 = frontmatter.name ?? path7.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "persona";
|
|
852708
|
+
const description = frontmatter.description ?? frontmatter.summary ?? frontmatter.title ?? "";
|
|
852709
|
+
return {
|
|
852710
|
+
name: name51,
|
|
852711
|
+
description,
|
|
852712
|
+
path: path7,
|
|
852713
|
+
origin,
|
|
852714
|
+
body: body2,
|
|
852715
|
+
frontmatter
|
|
852716
|
+
};
|
|
852717
|
+
}
|
|
852718
|
+
async function scanPersonaDirectory(root, origin) {
|
|
852719
|
+
let entries = [];
|
|
852720
|
+
try {
|
|
852721
|
+
entries = await fsPromises5.readdir(root);
|
|
852722
|
+
} catch {
|
|
852723
|
+
return [];
|
|
852724
|
+
}
|
|
852725
|
+
const records = [];
|
|
852726
|
+
for (const entry of entries.sort((a4, b3) => a4.localeCompare(b3))) {
|
|
852727
|
+
if (entry.endsWith(".md")) {
|
|
852728
|
+
const record2 = await readPersonaFile(join87(root, entry), origin);
|
|
852729
|
+
if (record2)
|
|
852730
|
+
records.push(record2);
|
|
852731
|
+
continue;
|
|
852732
|
+
}
|
|
852733
|
+
for (const marker of DIRECTORY_MARKERS) {
|
|
852734
|
+
const record2 = await readPersonaFile(join87(root, entry, marker), origin);
|
|
852735
|
+
if (record2) {
|
|
852736
|
+
records.push(record2);
|
|
852737
|
+
break;
|
|
852738
|
+
}
|
|
852739
|
+
}
|
|
852740
|
+
}
|
|
852741
|
+
return records;
|
|
852742
|
+
}
|
|
852743
|
+
async function discoverPersonas(shellPaths) {
|
|
852744
|
+
const seen = new Set;
|
|
852745
|
+
const records = [];
|
|
852746
|
+
for (const { root, origin } of getPersonaDirectories(shellPaths.workingDirectory, shellPaths.homeDirectory)) {
|
|
852747
|
+
for (const record2 of await scanPersonaDirectory(root, origin)) {
|
|
852748
|
+
const key = record2.name.toLowerCase();
|
|
852749
|
+
if (seen.has(key))
|
|
852750
|
+
continue;
|
|
852751
|
+
seen.add(key);
|
|
852752
|
+
records.push(record2);
|
|
852753
|
+
}
|
|
852754
|
+
}
|
|
852755
|
+
return records.sort((a4, b3) => {
|
|
852756
|
+
const originRank = a4.origin === b3.origin ? 0 : a4.origin === "project-local" ? -1 : 1;
|
|
852757
|
+
return originRank || a4.name.localeCompare(b3.name);
|
|
852758
|
+
});
|
|
852759
|
+
}
|
|
852760
|
+
|
|
852667
852761
|
// src/input/commands/personas-runtime.ts
|
|
852668
852762
|
function parsePersonaArgs(args2) {
|
|
852669
852763
|
const flags2 = new Map;
|
|
@@ -852737,6 +852831,84 @@ function renderPersona(persona, activePersonaId) {
|
|
|
852737
852831
|
].filter(Boolean).join(`
|
|
852738
852832
|
`);
|
|
852739
852833
|
}
|
|
852834
|
+
function summarizeDiscoveredPersona(persona) {
|
|
852835
|
+
const description = persona.description ? ` - ${persona.description}` : "";
|
|
852836
|
+
return ` ${persona.name} ${persona.origin}${description}
|
|
852837
|
+
path: ${persona.path}`;
|
|
852838
|
+
}
|
|
852839
|
+
function renderDiscoveredPersonas(personas) {
|
|
852840
|
+
if (personas.length === 0) {
|
|
852841
|
+
return [
|
|
852842
|
+
"Discovered Agent persona files",
|
|
852843
|
+
" No persona markdown files found in project/global Agent persona folders.",
|
|
852844
|
+
" Search roots: .goodvibes/personas, .goodvibes/agent/personas, .goodvibes/agents, ~/.goodvibes/personas, ~/.goodvibes/agent/personas, ~/.goodvibes/agents"
|
|
852845
|
+
].join(`
|
|
852846
|
+
`);
|
|
852847
|
+
}
|
|
852848
|
+
return [
|
|
852849
|
+
`Discovered Agent persona files (${personas.length})`,
|
|
852850
|
+
...personas.map(summarizeDiscoveredPersona),
|
|
852851
|
+
"",
|
|
852852
|
+
"Import one with: /personas import-discovered <name> --yes"
|
|
852853
|
+
].join(`
|
|
852854
|
+
`);
|
|
852855
|
+
}
|
|
852856
|
+
function discoveredPersonaLookupValues(persona) {
|
|
852857
|
+
const slug = persona.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
852858
|
+
const basename5 = persona.path.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
|
|
852859
|
+
return [persona.name, slug, persona.path, basename5].map((value) => value.trim().toLowerCase()).filter(Boolean);
|
|
852860
|
+
}
|
|
852861
|
+
function findDiscoveredPersona(personas, idOrName) {
|
|
852862
|
+
const lookup = idOrName.trim().toLowerCase();
|
|
852863
|
+
if (!lookup)
|
|
852864
|
+
return null;
|
|
852865
|
+
return personas.find((persona) => discoveredPersonaLookupValues(persona).includes(lookup)) ?? null;
|
|
852866
|
+
}
|
|
852867
|
+
function frontmatterList(persona, key) {
|
|
852868
|
+
const value = persona.frontmatter[key];
|
|
852869
|
+
if (!value)
|
|
852870
|
+
return [];
|
|
852871
|
+
return splitList(value);
|
|
852872
|
+
}
|
|
852873
|
+
async function importDiscoveredPersona(args2, ctx, personaRegistry) {
|
|
852874
|
+
const parsed = parsePersonaArgs(args2);
|
|
852875
|
+
const name51 = parsed.rest.join(" ").trim();
|
|
852876
|
+
if (!name51) {
|
|
852877
|
+
ctx.print("Usage: /personas import-discovered <name> [--use] --yes");
|
|
852878
|
+
return;
|
|
852879
|
+
}
|
|
852880
|
+
const discovered = findDiscoveredPersona(await discoverPersonas(requireShellPaths(ctx)), name51);
|
|
852881
|
+
if (!discovered) {
|
|
852882
|
+
ctx.print(`Unknown discovered Agent persona: ${name51}
|
|
852883
|
+
Run /personas discover to inspect available persona files.`);
|
|
852884
|
+
return;
|
|
852885
|
+
}
|
|
852886
|
+
if (!parsed.yes) {
|
|
852887
|
+
ctx.print([
|
|
852888
|
+
"Agent persona import preview",
|
|
852889
|
+
` name: ${discovered.name}`,
|
|
852890
|
+
` origin: ${discovered.origin}`,
|
|
852891
|
+
` path: ${discovered.path}`,
|
|
852892
|
+
` description: ${discovered.description || "(none)"}`,
|
|
852893
|
+
` body characters: ${discovered.body.length}`,
|
|
852894
|
+
" next: rerun with --yes to import into the Agent-local persona registry"
|
|
852895
|
+
].join(`
|
|
852896
|
+
`));
|
|
852897
|
+
return;
|
|
852898
|
+
}
|
|
852899
|
+
const persona = personaRegistry.create({
|
|
852900
|
+
name: discovered.name,
|
|
852901
|
+
description: discovered.description || `Imported persona from ${discovered.origin} markdown file.`,
|
|
852902
|
+
body: discovered.body,
|
|
852903
|
+
tags: frontmatterList(discovered, "tags"),
|
|
852904
|
+
triggers: frontmatterList(discovered, "triggers"),
|
|
852905
|
+
source: "imported",
|
|
852906
|
+
provenance: `discovered:${discovered.origin}:${discovered.path}`
|
|
852907
|
+
});
|
|
852908
|
+
if (parsed.flags.get("use") === "true")
|
|
852909
|
+
personaRegistry.setActive(persona.id);
|
|
852910
|
+
ctx.print(`Imported Agent persona ${persona.id}: ${persona.name}${parsed.flags.get("use") === "true" ? " (active)" : ""}`);
|
|
852911
|
+
}
|
|
852740
852912
|
function requiredFlag(flags2, key) {
|
|
852741
852913
|
const value = flags2.get(key)?.trim();
|
|
852742
852914
|
if (!value)
|
|
@@ -852751,7 +852923,7 @@ function registerPersonasRuntimeCommands(registry5) {
|
|
|
852751
852923
|
name: "personas",
|
|
852752
852924
|
aliases: ["persona"],
|
|
852753
852925
|
description: "Manage local GoodVibes Agent personas",
|
|
852754
|
-
usage: "[list|search <query>|show <id>|create --name <name> --description <summary> --body <instructions>|update <id> [--name ...] [--description ...] [--body ...]|use <id>|active|clear|review <id>|stale <id> <reason...>|delete <id> --yes]",
|
|
852926
|
+
usage: "[list|discover|import-discovered <name> --yes|search <query>|show <id>|create --name <name> --description <summary> --body <instructions>|update <id> [--name ...] [--description ...] [--body ...]|use <id>|active|clear|review <id>|stale <id> <reason...>|delete <id> --yes]",
|
|
852755
852927
|
async handler(args2, ctx) {
|
|
852756
852928
|
const sub = (args2[0] ?? "list").toLowerCase();
|
|
852757
852929
|
const registryStore = registryFromContext(ctx);
|
|
@@ -852760,6 +852932,14 @@ function registerPersonasRuntimeCommands(registry5) {
|
|
|
852760
852932
|
ctx.print(renderList("Agent Personas", registryStore, registryStore.list()));
|
|
852761
852933
|
return;
|
|
852762
852934
|
}
|
|
852935
|
+
if (sub === "discover" || sub === "discovered") {
|
|
852936
|
+
ctx.print(renderDiscoveredPersonas(await discoverPersonas(requireShellPaths(ctx))));
|
|
852937
|
+
return;
|
|
852938
|
+
}
|
|
852939
|
+
if (sub === "import-discovered" || sub === "import-persona") {
|
|
852940
|
+
await importDiscoveredPersona(args2.slice(1), ctx, registryStore);
|
|
852941
|
+
return;
|
|
852942
|
+
}
|
|
852763
852943
|
if (sub === "search") {
|
|
852764
852944
|
const query2 = args2.slice(1).join(" ").trim();
|
|
852765
852945
|
ctx.print(renderList(query2 ? `Agent Personas matching "${query2}"` : "Agent Personas", registryStore, registryStore.search(query2)));
|
|
@@ -852864,7 +853044,7 @@ function registerPersonasRuntimeCommands(registry5) {
|
|
|
852864
853044
|
ctx.print(`Deleted Agent persona ${removed.id}: ${removed.name}`);
|
|
852865
853045
|
return;
|
|
852866
853046
|
}
|
|
852867
|
-
ctx.print("Usage: /personas [list|search <query>|show <id>|create|update|use|active|clear|review|stale|delete]");
|
|
853047
|
+
ctx.print("Usage: /personas [list|discover|import-discovered|search <query>|show <id>|create|update|use|active|clear|review|stale|delete]");
|
|
852868
853048
|
} catch (error51) {
|
|
852869
853049
|
printError2(ctx, error51);
|
|
852870
853050
|
}
|
|
@@ -852975,7 +853155,7 @@ function findDiscoveredSkill(skills, idOrName) {
|
|
|
852975
853155
|
return null;
|
|
852976
853156
|
return skills.find((skill) => discoveredSkillLookupValues(skill).includes(lookup)) ?? null;
|
|
852977
853157
|
}
|
|
852978
|
-
function
|
|
853158
|
+
function frontmatterList2(skill, key) {
|
|
852979
853159
|
const value = skill.frontmatter[key];
|
|
852980
853160
|
if (!value)
|
|
852981
853161
|
return [];
|
|
@@ -853011,8 +853191,8 @@ Run /agent-skills discover to inspect available skill files.`);
|
|
|
853011
853191
|
name: discovered.name,
|
|
853012
853192
|
description: discovered.description || `Imported skill from ${discovered.origin} skill file.`,
|
|
853013
853193
|
procedure: discovered.body,
|
|
853014
|
-
triggers:
|
|
853015
|
-
tags:
|
|
853194
|
+
triggers: frontmatterList2(discovered, "triggers"),
|
|
853195
|
+
tags: frontmatterList2(discovered, "tags"),
|
|
853016
853196
|
enabled: parsed.flags.get("enabled") === "true",
|
|
853017
853197
|
source: "imported",
|
|
853018
853198
|
provenance: `discovered:${discovered.origin}:${discovered.path}`
|
|
@@ -853317,6 +853497,98 @@ function registerAgentSkillsRuntimeCommands(registry5) {
|
|
|
853317
853497
|
});
|
|
853318
853498
|
}
|
|
853319
853499
|
|
|
853500
|
+
// src/agent/routine-discovery.ts
|
|
853501
|
+
import { promises as fsPromises6 } from "fs";
|
|
853502
|
+
import { join as join88 } from "path";
|
|
853503
|
+
var DIRECTORY_MARKERS2 = ["ROUTINE.md", "routine.md"];
|
|
853504
|
+
function parseFrontmatter3(content) {
|
|
853505
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
853506
|
+
if (!match)
|
|
853507
|
+
return {};
|
|
853508
|
+
const result2 = {};
|
|
853509
|
+
for (const line of match[1].split(`
|
|
853510
|
+
`)) {
|
|
853511
|
+
const [key, ...rest] = line.split(":");
|
|
853512
|
+
if (key && rest.length > 0) {
|
|
853513
|
+
result2[key.trim()] = rest.join(":").trim();
|
|
853514
|
+
}
|
|
853515
|
+
}
|
|
853516
|
+
return result2;
|
|
853517
|
+
}
|
|
853518
|
+
function getRoutineDirectories(cwd, homeDir) {
|
|
853519
|
+
return [
|
|
853520
|
+
{ root: join88(cwd, ".goodvibes", "routines"), origin: "project-local" },
|
|
853521
|
+
{ root: join88(cwd, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "routines"), origin: "project-local" },
|
|
853522
|
+
{ root: join88(homeDir, ".goodvibes", "routines"), origin: "global" },
|
|
853523
|
+
{ root: join88(homeDir, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "routines"), origin: "global" }
|
|
853524
|
+
];
|
|
853525
|
+
}
|
|
853526
|
+
async function readRoutineFile(path7, origin) {
|
|
853527
|
+
let content = "";
|
|
853528
|
+
try {
|
|
853529
|
+
content = await fsPromises6.readFile(path7, "utf-8");
|
|
853530
|
+
} catch {
|
|
853531
|
+
return null;
|
|
853532
|
+
}
|
|
853533
|
+
const frontmatter = parseFrontmatter3(content);
|
|
853534
|
+
const markdownBody = content.replace(/^---\n[\s\S]*?\n---\n?/, "").trim();
|
|
853535
|
+
const steps = (frontmatter.steps ?? markdownBody).trim();
|
|
853536
|
+
if (!steps)
|
|
853537
|
+
return null;
|
|
853538
|
+
const name51 = frontmatter.name ?? path7.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "routine";
|
|
853539
|
+
const description = frontmatter.description ?? frontmatter.summary ?? frontmatter.title ?? "";
|
|
853540
|
+
return {
|
|
853541
|
+
name: name51,
|
|
853542
|
+
description,
|
|
853543
|
+
path: path7,
|
|
853544
|
+
origin,
|
|
853545
|
+
steps,
|
|
853546
|
+
frontmatter
|
|
853547
|
+
};
|
|
853548
|
+
}
|
|
853549
|
+
async function scanRoutineDirectory(root, origin) {
|
|
853550
|
+
let entries = [];
|
|
853551
|
+
try {
|
|
853552
|
+
entries = await fsPromises6.readdir(root);
|
|
853553
|
+
} catch {
|
|
853554
|
+
return [];
|
|
853555
|
+
}
|
|
853556
|
+
const records = [];
|
|
853557
|
+
for (const entry of entries.sort((a4, b3) => a4.localeCompare(b3))) {
|
|
853558
|
+
if (entry.endsWith(".md")) {
|
|
853559
|
+
const record2 = await readRoutineFile(join88(root, entry), origin);
|
|
853560
|
+
if (record2)
|
|
853561
|
+
records.push(record2);
|
|
853562
|
+
continue;
|
|
853563
|
+
}
|
|
853564
|
+
for (const marker of DIRECTORY_MARKERS2) {
|
|
853565
|
+
const record2 = await readRoutineFile(join88(root, entry, marker), origin);
|
|
853566
|
+
if (record2) {
|
|
853567
|
+
records.push(record2);
|
|
853568
|
+
break;
|
|
853569
|
+
}
|
|
853570
|
+
}
|
|
853571
|
+
}
|
|
853572
|
+
return records;
|
|
853573
|
+
}
|
|
853574
|
+
async function discoverRoutines(shellPaths) {
|
|
853575
|
+
const seen = new Set;
|
|
853576
|
+
const records = [];
|
|
853577
|
+
for (const { root, origin } of getRoutineDirectories(shellPaths.workingDirectory, shellPaths.homeDirectory)) {
|
|
853578
|
+
for (const record2 of await scanRoutineDirectory(root, origin)) {
|
|
853579
|
+
const key = record2.name.toLowerCase();
|
|
853580
|
+
if (seen.has(key))
|
|
853581
|
+
continue;
|
|
853582
|
+
seen.add(key);
|
|
853583
|
+
records.push(record2);
|
|
853584
|
+
}
|
|
853585
|
+
}
|
|
853586
|
+
return records.sort((a4, b3) => {
|
|
853587
|
+
const originRank = a4.origin === b3.origin ? 0 : a4.origin === "project-local" ? -1 : 1;
|
|
853588
|
+
return originRank || a4.name.localeCompare(b3.name);
|
|
853589
|
+
});
|
|
853590
|
+
}
|
|
853591
|
+
|
|
853320
853592
|
// src/input/commands/routines-runtime.ts
|
|
853321
853593
|
function parseRoutineArgs(args2) {
|
|
853322
853594
|
const flags2 = new Map;
|
|
@@ -853400,9 +853672,86 @@ function renderRoutine(routine) {
|
|
|
853400
853672
|
].filter(Boolean).join(`
|
|
853401
853673
|
`);
|
|
853402
853674
|
}
|
|
853675
|
+
function summarizeDiscoveredRoutine(routine) {
|
|
853676
|
+
const description = routine.description ? ` - ${routine.description}` : "";
|
|
853677
|
+
return ` ${routine.name} ${routine.origin}${description}
|
|
853678
|
+
path: ${routine.path}`;
|
|
853679
|
+
}
|
|
853680
|
+
function renderDiscoveredRoutines(routines) {
|
|
853681
|
+
if (routines.length === 0) {
|
|
853682
|
+
return [
|
|
853683
|
+
"Discovered Agent routine files",
|
|
853684
|
+
" No routine markdown files found in project/global Agent routine folders.",
|
|
853685
|
+
" Search roots: .goodvibes/routines, .goodvibes/agent/routines, ~/.goodvibes/routines, ~/.goodvibes/agent/routines"
|
|
853686
|
+
].join(`
|
|
853687
|
+
`);
|
|
853688
|
+
}
|
|
853689
|
+
return [
|
|
853690
|
+
`Discovered Agent routine files (${routines.length})`,
|
|
853691
|
+
...routines.map(summarizeDiscoveredRoutine),
|
|
853692
|
+
"",
|
|
853693
|
+
"Import one with: /routines import-discovered <name> --yes"
|
|
853694
|
+
].join(`
|
|
853695
|
+
`);
|
|
853696
|
+
}
|
|
853697
|
+
function discoveredRoutineLookupValues(routine) {
|
|
853698
|
+
const slug = routine.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
853699
|
+
const basename5 = routine.path.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
|
|
853700
|
+
return [routine.name, slug, routine.path, basename5].map((value) => value.trim().toLowerCase()).filter(Boolean);
|
|
853701
|
+
}
|
|
853702
|
+
function findDiscoveredRoutine(routines, idOrName) {
|
|
853703
|
+
const lookup = idOrName.trim().toLowerCase();
|
|
853704
|
+
if (!lookup)
|
|
853705
|
+
return null;
|
|
853706
|
+
return routines.find((routine) => discoveredRoutineLookupValues(routine).includes(lookup)) ?? null;
|
|
853707
|
+
}
|
|
853708
|
+
function frontmatterList3(routine, key) {
|
|
853709
|
+
const value = routine.frontmatter[key];
|
|
853710
|
+
if (!value)
|
|
853711
|
+
return [];
|
|
853712
|
+
return splitList3(value);
|
|
853713
|
+
}
|
|
853403
853714
|
function printError4(ctx, error51) {
|
|
853404
853715
|
ctx.print(`Error: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
853405
853716
|
}
|
|
853717
|
+
async function importDiscoveredRoutine(args2, ctx, routineRegistry) {
|
|
853718
|
+
const parsed = parseRoutineArgs(args2);
|
|
853719
|
+
const name51 = parsed.rest.join(" ").trim();
|
|
853720
|
+
if (!name51) {
|
|
853721
|
+
ctx.print("Usage: /routines import-discovered <name> [--enabled] --yes");
|
|
853722
|
+
return;
|
|
853723
|
+
}
|
|
853724
|
+
const discovered = findDiscoveredRoutine(await discoverRoutines(requireShellPaths(ctx)), name51);
|
|
853725
|
+
if (!discovered) {
|
|
853726
|
+
ctx.print(`Unknown discovered Agent routine: ${name51}
|
|
853727
|
+
Run /routines discover to inspect available routine files.`);
|
|
853728
|
+
return;
|
|
853729
|
+
}
|
|
853730
|
+
if (!parsed.yes) {
|
|
853731
|
+
ctx.print([
|
|
853732
|
+
"Agent routine import preview",
|
|
853733
|
+
` name: ${discovered.name}`,
|
|
853734
|
+
` origin: ${discovered.origin}`,
|
|
853735
|
+
` path: ${discovered.path}`,
|
|
853736
|
+
` description: ${discovered.description || "(none)"}`,
|
|
853737
|
+
` steps characters: ${discovered.steps.length}`,
|
|
853738
|
+
" next: rerun with --yes to import into the Agent-local routine registry"
|
|
853739
|
+
].join(`
|
|
853740
|
+
`));
|
|
853741
|
+
return;
|
|
853742
|
+
}
|
|
853743
|
+
const routine = routineRegistry.create({
|
|
853744
|
+
name: discovered.name,
|
|
853745
|
+
description: discovered.description || `Imported routine from ${discovered.origin} markdown file.`,
|
|
853746
|
+
steps: discovered.steps,
|
|
853747
|
+
tags: frontmatterList3(discovered, "tags"),
|
|
853748
|
+
triggers: frontmatterList3(discovered, "triggers"),
|
|
853749
|
+
enabled: parsed.flags.get("enabled") === "true",
|
|
853750
|
+
source: "imported",
|
|
853751
|
+
provenance: `discovered:${discovered.origin}:${discovered.path}`
|
|
853752
|
+
});
|
|
853753
|
+
ctx.print(`Imported Agent routine ${routine.id}: ${routine.name}${routine.enabled ? " (enabled)" : ""}`);
|
|
853754
|
+
}
|
|
853406
853755
|
async function promoteRoutine(args2, routineRegistry, ctx) {
|
|
853407
853756
|
const parsed = parseRoutineSchedulePromotionArgs(args2);
|
|
853408
853757
|
if (parsed.errors.length > 0) {
|
|
@@ -853444,6 +853793,14 @@ async function runRoutinesRuntimeCommand(args2, ctx) {
|
|
|
853444
853793
|
ctx.print(renderList3("Enabled Agent Routines", routineRegistry, snapshot.enabledRoutines));
|
|
853445
853794
|
return;
|
|
853446
853795
|
}
|
|
853796
|
+
if (sub === "discover" || sub === "discovered") {
|
|
853797
|
+
ctx.print(renderDiscoveredRoutines(await discoverRoutines(requireShellPaths(ctx))));
|
|
853798
|
+
return;
|
|
853799
|
+
}
|
|
853800
|
+
if (sub === "import-discovered" || sub === "import-routine") {
|
|
853801
|
+
await importDiscoveredRoutine(args2.slice(1), ctx, routineRegistry);
|
|
853802
|
+
return;
|
|
853803
|
+
}
|
|
853447
853804
|
if (sub === "search") {
|
|
853448
853805
|
const query2 = args2.slice(1).join(" ").trim();
|
|
853449
853806
|
ctx.print(renderList3(query2 ? `Agent Routines matching "${query2}"` : "Agent Routines", routineRegistry, routineRegistry.search(query2)));
|
|
@@ -853579,7 +853936,7 @@ async function runRoutinesRuntimeCommand(args2, ctx) {
|
|
|
853579
853936
|
ctx.print(`Deleted Agent routine ${removed.id}: ${removed.name}`);
|
|
853580
853937
|
return;
|
|
853581
853938
|
}
|
|
853582
|
-
ctx.print("Usage: /routines [list|enabled|search|show|receipts|reconcile|receipt|create|update|enable|disable|start|review|stale|promote|delete]");
|
|
853939
|
+
ctx.print("Usage: /routines [list|enabled|discover|import-discovered|search|show|receipts|reconcile|receipt|create|update|enable|disable|start|review|stale|promote|delete]");
|
|
853583
853940
|
} catch (error51) {
|
|
853584
853941
|
printError4(ctx, error51);
|
|
853585
853942
|
}
|
|
@@ -853589,14 +853946,14 @@ function registerRoutinesRuntimeCommands(registry5) {
|
|
|
853589
853946
|
name: "routines",
|
|
853590
853947
|
aliases: ["routine"],
|
|
853591
853948
|
description: "Manage local GoodVibes Agent routines",
|
|
853592
|
-
usage: "[list|enabled|search <query>|show <id>|receipts|reconcile|receipt <id>|create --name <name> --description <summary> --steps <steps>|update <id> [--name ...] [--description ...] [--steps ...]|enable <id>|disable <id>|start <id>|review <id>|stale <id> <reason...>|promote <id> --cron <expr> [--delivery-channel slack] --yes|delete <id> --yes]",
|
|
853949
|
+
usage: "[list|enabled|discover|import-discovered <name> --yes|search <query>|show <id>|receipts|reconcile|receipt <id>|create --name <name> --description <summary> --steps <steps>|update <id> [--name ...] [--description ...] [--steps ...]|enable <id>|disable <id>|start <id>|review <id>|stale <id> <reason...>|promote <id> --cron <expr> [--delivery-channel slack] --yes|delete <id> --yes]",
|
|
853593
853950
|
handler: runRoutinesRuntimeCommand
|
|
853594
853951
|
});
|
|
853595
853952
|
}
|
|
853596
853953
|
|
|
853597
853954
|
// src/input/commands/channels-runtime.ts
|
|
853598
853955
|
import { existsSync as existsSync72, readFileSync as readFileSync79 } from "fs";
|
|
853599
|
-
import { join as
|
|
853956
|
+
import { join as join89 } from "path";
|
|
853600
853957
|
|
|
853601
853958
|
// src/input/agent-workspace-channels.ts
|
|
853602
853959
|
var AGENT_WORKSPACE_CHANNEL_SPECS = [
|
|
@@ -853807,7 +854164,7 @@ function resolveChannelDaemonConnection(context) {
|
|
|
853807
854164
|
const host = typeof hostValue === "string" && hostValue.trim().length > 0 ? hostValue.trim() : "127.0.0.1";
|
|
853808
854165
|
const port = typeof portValue === "number" && Number.isFinite(portValue) ? portValue : 3421;
|
|
853809
854166
|
const homeDirectory = context.workspace?.shellPaths?.homeDirectory ?? process.env.HOME ?? "";
|
|
853810
|
-
const tokenPath =
|
|
854167
|
+
const tokenPath = join89(homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
|
|
853811
854168
|
if (!existsSync72(tokenPath))
|
|
853812
854169
|
return { baseUrl: `http://${host}:${port}`, token: null, tokenPath };
|
|
853813
854170
|
try {
|
|
@@ -854903,7 +855260,7 @@ function registerBuiltinCommands(registry5) {
|
|
|
854903
855260
|
|
|
854904
855261
|
// src/input/input-history.ts
|
|
854905
855262
|
import { existsSync as existsSync73, mkdirSync as mkdirSync61, readFileSync as readFileSync80, writeFileSync as writeFileSync52 } from "fs";
|
|
854906
|
-
import { dirname as dirname59, join as
|
|
855263
|
+
import { dirname as dirname59, join as join90 } from "path";
|
|
854907
855264
|
class HistorySearch {
|
|
854908
855265
|
getEntries;
|
|
854909
855266
|
active = false;
|
|
@@ -854982,7 +855339,7 @@ function resolveHistoryPath2(options) {
|
|
|
854982
855339
|
if (!userRoot) {
|
|
854983
855340
|
throw new Error("InputHistory requires historyPath or an explicit userRoot/homeDirectory.");
|
|
854984
855341
|
}
|
|
854985
|
-
return
|
|
855342
|
+
return join90(userRoot, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "input-history.json");
|
|
854986
855343
|
}
|
|
854987
855344
|
|
|
854988
855345
|
class InputHistory {
|
|
@@ -863784,7 +864141,7 @@ function createBootstrapShell(options) {
|
|
|
863784
864141
|
hookActivityTracker: services.hookActivityTracker,
|
|
863785
864142
|
hookWorkbench: services.hookWorkbench,
|
|
863786
864143
|
mcpRegistry: services.mcpRegistry,
|
|
863787
|
-
daemonHomeDir:
|
|
864144
|
+
daemonHomeDir: join91(services.homeDirectory, ".goodvibes", "daemon")
|
|
863788
864145
|
});
|
|
863789
864146
|
services.panelManager.prewarmRegistered();
|
|
863790
864147
|
const systemMessageRouter = createSystemMessageRouter(conversation, systemMessagesPanel, (kind2) => {
|
|
@@ -866199,7 +866556,7 @@ import { dirname as dirname61 } from "path";
|
|
|
866199
866556
|
// src/runtime/onboarding/verify.ts
|
|
866200
866557
|
init_config8();
|
|
866201
866558
|
import { existsSync as existsSync75 } from "fs";
|
|
866202
|
-
import { join as
|
|
866559
|
+
import { join as join92 } from "path";
|
|
866203
866560
|
function getNow(deps) {
|
|
866204
866561
|
return deps.clock?.() ?? Date.now();
|
|
866205
866562
|
}
|
|
@@ -866280,7 +866637,7 @@ function verifyAuthOperation(_deps, operation) {
|
|
|
866280
866637
|
}
|
|
866281
866638
|
function verifyCreateAgentProfileOperation(deps, operation) {
|
|
866282
866639
|
const resolution2 = resolveAgentRuntimeProfileHome(deps.shellPaths.homeDirectory, operation.name);
|
|
866283
|
-
const ok3 = existsSync75(
|
|
866640
|
+
const ok3 = existsSync75(join92(resolution2.homeDirectory, "profile.json"));
|
|
866284
866641
|
return {
|
|
866285
866642
|
id: `agent-profile:${resolution2.id}`,
|
|
866286
866643
|
status: ok3 ? "pass" : "fail",
|
|
@@ -868337,7 +868694,7 @@ class AutocompleteEngine {
|
|
|
868337
868694
|
|
|
868338
868695
|
// src/input/file-picker.ts
|
|
868339
868696
|
import { readdir as readdir6 } from "fs/promises";
|
|
868340
|
-
import { join as
|
|
868697
|
+
import { join as join93, relative as relative15 } from "path";
|
|
868341
868698
|
|
|
868342
868699
|
class FilePickerModal {
|
|
868343
868700
|
shellPaths;
|
|
@@ -868470,7 +868827,7 @@ class FilePickerModal {
|
|
|
868470
868827
|
continue;
|
|
868471
868828
|
if (entry.name === "node_modules" || entry.name === "dist")
|
|
868472
868829
|
continue;
|
|
868473
|
-
const fullPath =
|
|
868830
|
+
const fullPath = join93(dir, entry.name);
|
|
868474
868831
|
const relPath = relative15(this.shellPaths.workingDirectory, fullPath);
|
|
868475
868832
|
if (entry.isDirectory()) {
|
|
868476
868833
|
files.push(relPath + "/");
|
|
@@ -871900,7 +872257,7 @@ function splitCommaList(value) {
|
|
|
871900
872257
|
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
871901
872258
|
}
|
|
871902
872259
|
function isAgentWorkspaceBasicCommandEditorKind(kind2) {
|
|
871903
|
-
return kind2 === "knowledge-bookmarks" || kind2 === "knowledge-file" || kind2 === "knowledge-browser-history" || kind2 === "knowledge-connector-ingest" || kind2 === "tts-prompt" || kind2 === "image-input" || kind2 === "skill-bundle" || kind2 === "skill-discovery-import" || kind2 === "profile-template-export" || kind2 === "profile-template-import" || kind2 === "mcp-server" || kind2 === "notify-webhook" || kind2 === "notify-webhook-remove" || kind2 === "notify-webhook-test";
|
|
872260
|
+
return kind2 === "knowledge-bookmarks" || kind2 === "knowledge-file" || kind2 === "knowledge-browser-history" || kind2 === "knowledge-connector-ingest" || kind2 === "tts-prompt" || kind2 === "image-input" || kind2 === "skill-bundle" || kind2 === "persona-discovery-import" || kind2 === "routine-discovery-import" || kind2 === "skill-discovery-import" || kind2 === "profile-template-export" || kind2 === "profile-template-import" || kind2 === "mcp-server" || kind2 === "notify-webhook" || kind2 === "notify-webhook-remove" || kind2 === "notify-webhook-test";
|
|
871904
872261
|
}
|
|
871905
872262
|
function createAgentWorkspaceBasicCommandEditor(kind2) {
|
|
871906
872263
|
if (kind2 === "knowledge-bookmarks") {
|
|
@@ -872090,6 +872447,34 @@ function createAgentWorkspaceBasicCommandEditor(kind2) {
|
|
|
872090
872447
|
]
|
|
872091
872448
|
};
|
|
872092
872449
|
}
|
|
872450
|
+
if (kind2 === "persona-discovery-import") {
|
|
872451
|
+
return {
|
|
872452
|
+
kind: kind2,
|
|
872453
|
+
mode: "create",
|
|
872454
|
+
title: "Import Discovered Persona",
|
|
872455
|
+
selectedFieldIndex: 0,
|
|
872456
|
+
message: "Import one discovered persona markdown file into the Agent-local persona registry. Type yes on the final field to confirm.",
|
|
872457
|
+
fields: [
|
|
872458
|
+
{ id: "name", label: "Discovered persona", value: "", required: true, multiline: false, hint: "Name shown by /personas discover." },
|
|
872459
|
+
{ id: "use", label: "Use now", value: "yes", required: false, multiline: false, hint: "yes/no." },
|
|
872460
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /personas import-discovered with --yes." }
|
|
872461
|
+
]
|
|
872462
|
+
};
|
|
872463
|
+
}
|
|
872464
|
+
if (kind2 === "routine-discovery-import") {
|
|
872465
|
+
return {
|
|
872466
|
+
kind: kind2,
|
|
872467
|
+
mode: "create",
|
|
872468
|
+
title: "Import Discovered Routine",
|
|
872469
|
+
selectedFieldIndex: 0,
|
|
872470
|
+
message: "Import one discovered routine markdown file into the Agent-local routine registry. Type yes on the final field to confirm.",
|
|
872471
|
+
fields: [
|
|
872472
|
+
{ id: "name", label: "Discovered routine", value: "", required: true, multiline: false, hint: "Name shown by /routines discover." },
|
|
872473
|
+
{ id: "enabled", label: "Enable now", value: "yes", required: false, multiline: false, hint: "yes/no." },
|
|
872474
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /routines import-discovered with --yes." }
|
|
872475
|
+
]
|
|
872476
|
+
};
|
|
872477
|
+
}
|
|
872093
872478
|
return {
|
|
872094
872479
|
kind: kind2,
|
|
872095
872480
|
mode: "create",
|
|
@@ -872460,6 +872845,66 @@ function buildAgentWorkspaceBasicCommandEditorSubmission(editor, readField, comm
|
|
|
872460
872845
|
}
|
|
872461
872846
|
};
|
|
872462
872847
|
}
|
|
872848
|
+
if (editor.kind === "persona-discovery-import") {
|
|
872849
|
+
if (!isAffirmative2(readField("confirm"))) {
|
|
872850
|
+
return {
|
|
872851
|
+
kind: "editor",
|
|
872852
|
+
editor: { ...editor, message: "Discovered persona import not confirmed. Type yes, then press Enter." },
|
|
872853
|
+
status: "Agent persona import not confirmed."
|
|
872854
|
+
};
|
|
872855
|
+
}
|
|
872856
|
+
const parts2 = [
|
|
872857
|
+
"/personas",
|
|
872858
|
+
"import-discovered",
|
|
872859
|
+
quoteSlashCommandArg(readField("name"))
|
|
872860
|
+
];
|
|
872861
|
+
if (isAffirmative2(readField("use")))
|
|
872862
|
+
parts2.push("--use");
|
|
872863
|
+
parts2.push("--yes");
|
|
872864
|
+
const command9 = parts2.join(" ");
|
|
872865
|
+
return {
|
|
872866
|
+
kind: "dispatch",
|
|
872867
|
+
command: command9,
|
|
872868
|
+
status: "Opening discovered persona import.",
|
|
872869
|
+
actionResult: {
|
|
872870
|
+
kind: "dispatched",
|
|
872871
|
+
title: "Opening discovered persona import",
|
|
872872
|
+
detail: "The workspace handed a confirmed local persona import command to the shell-owned command router.",
|
|
872873
|
+
command: command9,
|
|
872874
|
+
safety: "safe"
|
|
872875
|
+
}
|
|
872876
|
+
};
|
|
872877
|
+
}
|
|
872878
|
+
if (editor.kind === "routine-discovery-import") {
|
|
872879
|
+
if (!isAffirmative2(readField("confirm"))) {
|
|
872880
|
+
return {
|
|
872881
|
+
kind: "editor",
|
|
872882
|
+
editor: { ...editor, message: "Discovered routine import not confirmed. Type yes, then press Enter." },
|
|
872883
|
+
status: "Agent routine import not confirmed."
|
|
872884
|
+
};
|
|
872885
|
+
}
|
|
872886
|
+
const parts2 = [
|
|
872887
|
+
"/routines",
|
|
872888
|
+
"import-discovered",
|
|
872889
|
+
quoteSlashCommandArg(readField("name"))
|
|
872890
|
+
];
|
|
872891
|
+
if (isAffirmative2(readField("enabled")))
|
|
872892
|
+
parts2.push("--enabled");
|
|
872893
|
+
parts2.push("--yes");
|
|
872894
|
+
const command9 = parts2.join(" ");
|
|
872895
|
+
return {
|
|
872896
|
+
kind: "dispatch",
|
|
872897
|
+
command: command9,
|
|
872898
|
+
status: "Opening discovered routine import.",
|
|
872899
|
+
actionResult: {
|
|
872900
|
+
kind: "dispatched",
|
|
872901
|
+
title: "Opening discovered routine import",
|
|
872902
|
+
detail: "The workspace handed a confirmed local routine import command to the shell-owned command router.",
|
|
872903
|
+
command: command9,
|
|
872904
|
+
safety: "safe"
|
|
872905
|
+
}
|
|
872906
|
+
};
|
|
872907
|
+
}
|
|
872463
872908
|
const commandParts = [
|
|
872464
872909
|
"/agent-skills bundle create",
|
|
872465
872910
|
"--name",
|
|
@@ -873034,6 +873479,8 @@ var AGENT_WORKSPACE_CATEGORIES = [
|
|
|
873034
873479
|
actions: [
|
|
873035
873480
|
{ id: "personas-list", label: "List personas", detail: "Print the full local persona library.", command: "/personas list", kind: "command", safety: "read-only" },
|
|
873036
873481
|
{ id: "personas-active", label: "Show active persona", detail: "Inspect the active local persona applied to new turns.", command: "/personas active", kind: "command", safety: "read-only" },
|
|
873482
|
+
{ id: "personas-discover", label: "Discover persona files", detail: "Scan project and global Agent persona folders for persona markdown without importing it.", command: "/personas discover", kind: "command", safety: "read-only" },
|
|
873483
|
+
{ id: "personas-import-discovered", label: "Import discovered persona", detail: "Open an in-workspace form that imports one reviewed persona markdown file into the Agent-local persona registry after typed confirmation.", editorKind: "persona-discovery-import", kind: "editor", safety: "safe" },
|
|
873037
873484
|
{ id: "personas-prev", label: "Previous persona", detail: "Move the local persona selection up without changing active state.", localKind: "persona", selectionDelta: -1, kind: "local-selection", safety: "safe" },
|
|
873038
873485
|
{ id: "personas-next", label: "Next persona", detail: "Move the local persona selection down without changing active state.", localKind: "persona", selectionDelta: 1, kind: "local-selection", safety: "safe" },
|
|
873039
873486
|
{ id: "personas-create", label: "Create persona", detail: "Open an in-workspace form for a local persona that writes Agent-local state only.", editorKind: "persona", kind: "editor", safety: "safe" },
|
|
@@ -873076,6 +873523,8 @@ var AGENT_WORKSPACE_CATEGORIES = [
|
|
|
873076
873523
|
actions: [
|
|
873077
873524
|
{ id: "routines-list", label: "List routines", detail: "Print the full local Agent routine library.", command: "/routines list", kind: "command", safety: "read-only" },
|
|
873078
873525
|
{ id: "routines-enabled", label: "Enabled routines", detail: "Show routines available for direct use.", command: "/routines enabled", kind: "command", safety: "read-only" },
|
|
873526
|
+
{ id: "routines-discover", label: "Discover routine files", detail: "Scan project and global Agent routine folders for routine markdown without importing it.", command: "/routines discover", kind: "command", safety: "read-only" },
|
|
873527
|
+
{ id: "routines-import-discovered", label: "Import discovered routine", detail: "Open an in-workspace form that imports one reviewed routine markdown file into the Agent-local routine registry after typed confirmation.", editorKind: "routine-discovery-import", kind: "editor", safety: "safe" },
|
|
873079
873528
|
{ id: "routines-prev", label: "Previous routine", detail: "Move the local routine selection up without changing enabled state.", localKind: "routine", selectionDelta: -1, kind: "local-selection", safety: "safe" },
|
|
873080
873529
|
{ id: "routines-next", label: "Next routine", detail: "Move the local routine selection down without changing enabled state.", localKind: "routine", selectionDelta: 1, kind: "local-selection", safety: "safe" },
|
|
873081
873530
|
{ id: "routines-create", label: "Create routine", detail: "Open an in-workspace form for a repeatable local workflow that writes Agent-local state only.", editorKind: "routine", kind: "editor", safety: "safe" },
|
|
@@ -883063,7 +883512,7 @@ function wireShellUiOpeners(options) {
|
|
|
883063
883512
|
|
|
883064
883513
|
// src/cli/entrypoint.ts
|
|
883065
883514
|
import { existsSync as existsSync85 } from "fs";
|
|
883066
|
-
import { join as
|
|
883515
|
+
import { join as join101 } from "path";
|
|
883067
883516
|
// src/cli/parser.ts
|
|
883068
883517
|
var COMMAND_ALIASES = {
|
|
883069
883518
|
run: "run",
|
|
@@ -883428,7 +883877,7 @@ function parseGoodVibesCli(argv, binary2 = "goodvibes-agent") {
|
|
|
883428
883877
|
}
|
|
883429
883878
|
// src/cli/help.ts
|
|
883430
883879
|
import { existsSync as existsSync79, readFileSync as readFileSync87 } from "fs";
|
|
883431
|
-
import { dirname as dirname63, join as
|
|
883880
|
+
import { dirname as dirname63, join as join94 } from "path";
|
|
883432
883881
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
883433
883882
|
function readJsonVersion(path7) {
|
|
883434
883883
|
try {
|
|
@@ -883442,7 +883891,7 @@ function readJsonVersion(path7) {
|
|
|
883442
883891
|
}
|
|
883443
883892
|
function getPackageVersion() {
|
|
883444
883893
|
const here = dirname63(fileURLToPath4(import.meta.url));
|
|
883445
|
-
return readJsonVersion(
|
|
883894
|
+
return readJsonVersion(join94(here, "..", "..", "package.json")) ?? VERSION;
|
|
883446
883895
|
}
|
|
883447
883896
|
function renderGoodVibesVersion(binary2 = "goodvibes-agent") {
|
|
883448
883897
|
return `${binary2} ${getPackageVersion()}`;
|
|
@@ -883582,6 +884031,8 @@ var COMMAND_HELP = {
|
|
|
883582
884031
|
usage: [
|
|
883583
884032
|
"personas list",
|
|
883584
884033
|
"personas active",
|
|
884034
|
+
"personas discover",
|
|
884035
|
+
"personas import-discovered <name> [--use] --yes",
|
|
883585
884036
|
"personas search <query>",
|
|
883586
884037
|
"personas show <id>",
|
|
883587
884038
|
"personas create --name <name> --description <summary> --body <instructions> [--tags a,b] [--triggers a,b] [--use]",
|
|
@@ -883595,6 +884046,8 @@ var COMMAND_HELP = {
|
|
|
883595
884046
|
summary: "Manage Agent-local personas for the serial main conversation. Personas do not spawn worker agents.",
|
|
883596
884047
|
examples: [
|
|
883597
884048
|
"personas list",
|
|
884049
|
+
"personas discover",
|
|
884050
|
+
'personas import-discovered "Travel Planner" --use --yes',
|
|
883598
884051
|
'personas create --name "Travel Planner" --description "Plan trips" --body "Compare options before booking" --use',
|
|
883599
884052
|
"personas review travel-planner",
|
|
883600
884053
|
"personas delete travel-planner --yes"
|
|
@@ -883660,15 +884113,19 @@ var COMMAND_HELP = {
|
|
|
883660
884113
|
usage: [
|
|
883661
884114
|
"routines list",
|
|
883662
884115
|
"routines enabled",
|
|
884116
|
+
"routines discover",
|
|
884117
|
+
"routines import-discovered <name> [--enabled] --yes",
|
|
883663
884118
|
"routines show <id>",
|
|
883664
884119
|
"routines receipts",
|
|
883665
884120
|
"routines reconcile",
|
|
883666
884121
|
"routines receipt <receipt-id>",
|
|
883667
884122
|
"routines promote <id> (--cron <expr>|--every <interval>|--at <iso-time>) [--timezone <tz>] [--name <schedule-name>] [--provider <id>] [--model <model>] [--delivery-channel <channel[:route[:label]]>|--delivery-route <route[:label]>|--delivery-webhook <url>|--delivery-link <url>] [--disabled] --yes"
|
|
883668
884123
|
],
|
|
883669
|
-
summary: "Inspect Agent-local routines, review local promotion receipts, reconcile receipts against live connected schedules, and explicitly promote a reviewed routine into a GoodVibes schedule. Without --yes, promote only prints the schedules.create preview.",
|
|
884124
|
+
summary: "Inspect and import Agent-local routines, review local promotion receipts, reconcile receipts against live connected schedules, and explicitly promote a reviewed routine into a GoodVibes schedule. Without --yes, promote only prints the schedules.create preview.",
|
|
883670
884125
|
examples: [
|
|
883671
884126
|
"routines list",
|
|
884127
|
+
"routines discover",
|
|
884128
|
+
'routines import-discovered "Daily Brief" --enabled --yes',
|
|
883672
884129
|
"routines show daily-operations-sweep",
|
|
883673
884130
|
"routines receipts",
|
|
883674
884131
|
"routines reconcile",
|
|
@@ -884175,7 +884632,7 @@ function renderOnboardingCliStatus(options) {
|
|
|
884175
884632
|
}
|
|
884176
884633
|
// src/cli/external-runtime.ts
|
|
884177
884634
|
import { existsSync as existsSync80, readFileSync as readFileSync88 } from "fs";
|
|
884178
|
-
import { join as
|
|
884635
|
+
import { join as join95 } from "path";
|
|
884179
884636
|
function isRecord29(value) {
|
|
884180
884637
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
884181
884638
|
}
|
|
@@ -884189,7 +884646,7 @@ function resolveBaseUrl2(configManager) {
|
|
|
884189
884646
|
return `http://${host}:${Number.isFinite(port) ? port : 3421}`;
|
|
884190
884647
|
}
|
|
884191
884648
|
function readOperatorToken(homeDirectory) {
|
|
884192
|
-
const path7 =
|
|
884649
|
+
const path7 = join95(homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
|
|
884193
884650
|
if (!existsSync80(path7))
|
|
884194
884651
|
return { token: null, path: path7 };
|
|
884195
884652
|
try {
|
|
@@ -884567,7 +885024,7 @@ function applyRuntimeCommandEndpointFlagOverrides(configManager, command8, flags
|
|
|
884567
885024
|
}
|
|
884568
885025
|
// src/cli/bundle-command.ts
|
|
884569
885026
|
import { existsSync as existsSync82, mkdirSync as mkdirSync65, readFileSync as readFileSync89, writeFileSync as writeFileSync56 } from "fs";
|
|
884570
|
-
import { dirname as dirname64, join as
|
|
885027
|
+
import { dirname as dirname64, join as join97 } from "path";
|
|
884571
885028
|
|
|
884572
885029
|
// src/cli/provider-classification.ts
|
|
884573
885030
|
var SUBSCRIPTION_PROVIDERS = new Set([
|
|
@@ -884658,7 +885115,7 @@ function classifyProviderSetup(input) {
|
|
|
884658
885115
|
// src/cli/service-posture.ts
|
|
884659
885116
|
import { closeSync as closeSync4, existsSync as existsSync81, openSync as openSync4, readSync as readSync2, statSync as statSync21 } from "fs";
|
|
884660
885117
|
import net3 from "net";
|
|
884661
|
-
import { isAbsolute as isAbsolute13, join as
|
|
885118
|
+
import { isAbsolute as isAbsolute13, join as join96 } from "path";
|
|
884662
885119
|
|
|
884663
885120
|
// src/cli/redaction.ts
|
|
884664
885121
|
var REDACTED_VALUE = "<redacted>";
|
|
@@ -884828,7 +885285,7 @@ function resolveConfiguredLogPath(runtime3) {
|
|
|
884828
885285
|
const trimmed2 = value.trim();
|
|
884829
885286
|
if (!trimmed2)
|
|
884830
885287
|
return;
|
|
884831
|
-
return isAbsolute13(trimmed2) ? trimmed2 :
|
|
885288
|
+
return isAbsolute13(trimmed2) ? trimmed2 : join96(runtime3.homeDirectory, trimmed2);
|
|
884832
885289
|
}
|
|
884833
885290
|
function createExternalDaemonLifecycle(logPath) {
|
|
884834
885291
|
return {
|
|
@@ -884937,7 +885394,7 @@ function readAuthPosture(runtime3) {
|
|
|
884937
885394
|
});
|
|
884938
885395
|
const userStorePath = shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-users.json");
|
|
884939
885396
|
const bootstrapCredentialPath = shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-bootstrap.txt");
|
|
884940
|
-
const operatorTokenPath =
|
|
885397
|
+
const operatorTokenPath = join97(runtime3.homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
|
|
884941
885398
|
return {
|
|
884942
885399
|
userStorePath,
|
|
884943
885400
|
userStorePresent: existsSync82(userStorePath),
|
|
@@ -885097,7 +885554,7 @@ async function handleBundleCommand(runtime3) {
|
|
|
885097
885554
|
}
|
|
885098
885555
|
// src/cli/management.ts
|
|
885099
885556
|
import { existsSync as existsSync84 } from "fs";
|
|
885100
|
-
import { join as
|
|
885557
|
+
import { join as join100 } from "path";
|
|
885101
885558
|
import { spawn as spawn5 } from "child_process";
|
|
885102
885559
|
import { networkInterfaces as networkInterfaces4 } from "os";
|
|
885103
885560
|
|
|
@@ -885124,7 +885581,7 @@ function formatProviderAuthRoute(route) {
|
|
|
885124
885581
|
|
|
885125
885582
|
// src/cli/management-commands.ts
|
|
885126
885583
|
import { mkdirSync as mkdirSync66, writeFileSync as writeFileSync57 } from "fs";
|
|
885127
|
-
import { dirname as dirname65, join as
|
|
885584
|
+
import { dirname as dirname65, join as join98 } from "path";
|
|
885128
885585
|
init_config8();
|
|
885129
885586
|
init_config8();
|
|
885130
885587
|
init_config8();
|
|
@@ -885441,7 +885898,7 @@ async function handleTasks(runtime3) {
|
|
|
885441
885898
|
});
|
|
885442
885899
|
}
|
|
885443
885900
|
async function renderPairing(runtime3) {
|
|
885444
|
-
const daemonHomeDir =
|
|
885901
|
+
const daemonHomeDir = join98(runtime3.homeDirectory, ".goodvibes", "daemon");
|
|
885445
885902
|
const tokenRecord = getOrCreateCompanionToken(GOODVIBES_AGENT_PAIRING_SURFACE, { daemonHomeDir });
|
|
885446
885903
|
const binding = resolveRuntimeEndpointBinding(runtime3.configManager, "controlPlane");
|
|
885447
885904
|
const daemonUrl = `http://${urlHostForBindHost2(binding.host)}:${binding.port}`;
|
|
@@ -885980,7 +886437,7 @@ var DELEGATION_METHOD = {
|
|
|
885980
886437
|
|
|
885981
886438
|
// src/cli/agent-knowledge-runtime.ts
|
|
885982
886439
|
import { existsSync as existsSync83, readFileSync as readFileSync90 } from "fs";
|
|
885983
|
-
import { join as
|
|
886440
|
+
import { join as join99 } from "path";
|
|
885984
886441
|
|
|
885985
886442
|
// node_modules/@pellux/goodvibes-sdk/dist/browser-scoped.js
|
|
885986
886443
|
init_dist();
|
|
@@ -886346,7 +886803,7 @@ function resolveDaemonConnection(runtime3) {
|
|
|
886346
886803
|
const host = String(runtime3.configManager.get("controlPlane.host") ?? "127.0.0.1");
|
|
886347
886804
|
const port = Number(runtime3.configManager.get("controlPlane.port") ?? 3421);
|
|
886348
886805
|
const baseUrl = `http://${host}:${Number.isFinite(port) ? port : 3421}`;
|
|
886349
|
-
const tokenPath =
|
|
886806
|
+
const tokenPath = join99(runtime3.homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
|
|
886350
886807
|
if (!existsSync83(tokenPath))
|
|
886351
886808
|
return { baseUrl, token: null, tokenPath };
|
|
886352
886809
|
try {
|
|
@@ -887132,6 +887589,48 @@ function renderPersona2(persona, activePersonaId) {
|
|
|
887132
887589
|
].filter((line2) => Boolean(line2)).join(`
|
|
887133
887590
|
`);
|
|
887134
887591
|
}
|
|
887592
|
+
function summarizeDiscoveredPersona2(persona) {
|
|
887593
|
+
const description = persona.description ? ` - ${persona.description}` : "";
|
|
887594
|
+
return [
|
|
887595
|
+
` ${persona.name} ${persona.origin}${description}`,
|
|
887596
|
+
` path: ${persona.path}`
|
|
887597
|
+
].join(`
|
|
887598
|
+
`);
|
|
887599
|
+
}
|
|
887600
|
+
function renderDiscoveredPersonaList(personas) {
|
|
887601
|
+
if (personas.length === 0) {
|
|
887602
|
+
return [
|
|
887603
|
+
"Discovered Agent persona files",
|
|
887604
|
+
" No persona markdown files found in Agent persona folders.",
|
|
887605
|
+
" Search roots: .goodvibes/personas, .goodvibes/agent/personas, .goodvibes/agents, ~/.goodvibes/personas, ~/.goodvibes/agent/personas, ~/.goodvibes/agents"
|
|
887606
|
+
].join(`
|
|
887607
|
+
`);
|
|
887608
|
+
}
|
|
887609
|
+
return [
|
|
887610
|
+
`Discovered Agent persona files (${personas.length})`,
|
|
887611
|
+
...personas.map(summarizeDiscoveredPersona2),
|
|
887612
|
+
"",
|
|
887613
|
+
"Import one with: goodvibes-agent personas import-discovered <name> --yes"
|
|
887614
|
+
].join(`
|
|
887615
|
+
`);
|
|
887616
|
+
}
|
|
887617
|
+
function discoveredPersonaLookupValues2(persona) {
|
|
887618
|
+
const slug = persona.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
887619
|
+
const basename6 = persona.path.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
|
|
887620
|
+
return [persona.name, slug, persona.path, basename6].map((value) => value.trim().toLowerCase()).filter(Boolean);
|
|
887621
|
+
}
|
|
887622
|
+
function findDiscoveredPersona2(personas, idOrName) {
|
|
887623
|
+
const lookup = idOrName.trim().toLowerCase();
|
|
887624
|
+
if (!lookup)
|
|
887625
|
+
return null;
|
|
887626
|
+
return personas.find((persona) => discoveredPersonaLookupValues2(persona).includes(lookup)) ?? null;
|
|
887627
|
+
}
|
|
887628
|
+
function discoveredPersonaFrontmatterList(persona, key) {
|
|
887629
|
+
const value = persona.frontmatter[key];
|
|
887630
|
+
if (!value)
|
|
887631
|
+
return [];
|
|
887632
|
+
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
887633
|
+
}
|
|
887135
887634
|
function summarizeSkill2(skill) {
|
|
887136
887635
|
const enabled = skill.enabled ? "enabled" : "disabled";
|
|
887137
887636
|
const tags = skill.tags.length > 0 ? ` tags=${skill.tags.join(",")}` : "";
|
|
@@ -887255,7 +887754,7 @@ function renderBundle2(bundle) {
|
|
|
887255
887754
|
`);
|
|
887256
887755
|
}
|
|
887257
887756
|
function usagePersonas() {
|
|
887258
|
-
return "Usage: goodvibes-agent personas [list|active|search <query>|show <id>|create|update <id>|use <id>|clear|review <id>|stale <id> <reason>|delete <id> --yes]";
|
|
887757
|
+
return "Usage: goodvibes-agent personas [list|active|discover|import-discovered <name> --yes|search <query>|show <id>|create|update <id>|use <id>|clear|review <id>|stale <id> <reason>|delete <id> --yes]";
|
|
887259
887758
|
}
|
|
887260
887759
|
function usageSkills() {
|
|
887261
887760
|
return "Usage: goodvibes-agent skills [list|enabled|active|discover|import-discovered <name> --yes|search <query>|show <id>|create|update <id>|enable <id>|disable <id>|review <id>|stale <id> <reason>|delete <id> --yes|bundle ...]";
|
|
@@ -887284,6 +887783,45 @@ async function handlePersonasCommand(runtime3) {
|
|
|
887284
887783
|
return failure(runtime3, "agent.personas.active_missing", "No active Agent persona.", 1);
|
|
887285
887784
|
return success3(runtime3, "agent.personas.active", active, renderPersona2(active, active.id));
|
|
887286
887785
|
}
|
|
887786
|
+
if (normalized === "discover") {
|
|
887787
|
+
const discovered = await discoverPersonas(shellPaths(runtime3));
|
|
887788
|
+
return success3(runtime3, "agent.personas.discover", { personas: discovered }, renderDiscoveredPersonaList(discovered));
|
|
887789
|
+
}
|
|
887790
|
+
if (normalized === "import-discovered" || normalized === "import-persona") {
|
|
887791
|
+
const options = parseOptions(rest);
|
|
887792
|
+
const name51 = options.positionals.join(" ").trim();
|
|
887793
|
+
if (!name51)
|
|
887794
|
+
return failure(runtime3, "invalid_persona_command", "Usage: goodvibes-agent personas import-discovered <name> [--use] --yes", 2);
|
|
887795
|
+
const discovered = findDiscoveredPersona2(await discoverPersonas(shellPaths(runtime3)), name51);
|
|
887796
|
+
if (!discovered) {
|
|
887797
|
+
return failure(runtime3, "persona_discovery_not_found", `Unknown discovered Agent persona: ${name51}
|
|
887798
|
+
Run goodvibes-agent personas discover to inspect available persona files.`, 1);
|
|
887799
|
+
}
|
|
887800
|
+
if (!hasFlag3(options, "yes")) {
|
|
887801
|
+
return success3(runtime3, "agent.personas.import_discovered.preview", { persona: discovered }, [
|
|
887802
|
+
"Agent persona import preview",
|
|
887803
|
+
` name: ${discovered.name}`,
|
|
887804
|
+
` origin: ${discovered.origin}`,
|
|
887805
|
+
` path: ${discovered.path}`,
|
|
887806
|
+
` description: ${discovered.description || "(none)"}`,
|
|
887807
|
+
` body characters: ${discovered.body.length}`,
|
|
887808
|
+
" next: rerun with --yes to import into the Agent-local persona registry"
|
|
887809
|
+
].join(`
|
|
887810
|
+
`));
|
|
887811
|
+
}
|
|
887812
|
+
const persona = registry5.create({
|
|
887813
|
+
name: discovered.name,
|
|
887814
|
+
description: discovered.description || `Imported persona from ${discovered.origin} markdown file.`,
|
|
887815
|
+
body: discovered.body,
|
|
887816
|
+
tags: discoveredPersonaFrontmatterList(discovered, "tags"),
|
|
887817
|
+
triggers: discoveredPersonaFrontmatterList(discovered, "triggers"),
|
|
887818
|
+
source: "imported",
|
|
887819
|
+
provenance: `discovered:${discovered.origin}:${discovered.path}`
|
|
887820
|
+
});
|
|
887821
|
+
if (hasFlag3(options, "use"))
|
|
887822
|
+
registry5.setActive(persona.id);
|
|
887823
|
+
return success3(runtime3, "agent.personas.import_discovered", persona, `Imported Agent persona ${persona.id}: ${persona.name}${hasFlag3(options, "use") ? " (active)" : ""}`);
|
|
887824
|
+
}
|
|
887287
887825
|
if (normalized === "search" || normalized === "find") {
|
|
887288
887826
|
const query2 = rest.join(" ").trim();
|
|
887289
887827
|
const results = registry5.search(query2);
|
|
@@ -888511,17 +889049,87 @@ function routineRegistry(runtime3) {
|
|
|
888511
889049
|
homeDirectory: runtime3.homeDirectory
|
|
888512
889050
|
}));
|
|
888513
889051
|
}
|
|
889052
|
+
function shellPaths2(runtime3) {
|
|
889053
|
+
return createShellPathService2({
|
|
889054
|
+
workingDirectory: runtime3.workingDirectory,
|
|
889055
|
+
homeDirectory: runtime3.homeDirectory
|
|
889056
|
+
});
|
|
889057
|
+
}
|
|
888514
889058
|
function routineReceiptStore(runtime3) {
|
|
888515
889059
|
return RoutineScheduleReceiptStore.fromShellPaths(createShellPathService2({
|
|
888516
889060
|
workingDirectory: runtime3.workingDirectory,
|
|
888517
889061
|
homeDirectory: runtime3.homeDirectory
|
|
888518
889062
|
}));
|
|
888519
889063
|
}
|
|
889064
|
+
function splitList6(value) {
|
|
889065
|
+
if (!value)
|
|
889066
|
+
return [];
|
|
889067
|
+
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
889068
|
+
}
|
|
889069
|
+
function parseImportFlags(args2) {
|
|
889070
|
+
const positionals = [];
|
|
889071
|
+
let enabled = false;
|
|
889072
|
+
let yes = false;
|
|
889073
|
+
for (const arg of args2) {
|
|
889074
|
+
if (arg === "--enabled") {
|
|
889075
|
+
enabled = true;
|
|
889076
|
+
continue;
|
|
889077
|
+
}
|
|
889078
|
+
if (arg === "--yes") {
|
|
889079
|
+
yes = true;
|
|
889080
|
+
continue;
|
|
889081
|
+
}
|
|
889082
|
+
positionals.push(arg);
|
|
889083
|
+
}
|
|
889084
|
+
return { name: positionals.join(" ").trim(), enabled, yes };
|
|
889085
|
+
}
|
|
888520
889086
|
function summarizeRoutine2(routine) {
|
|
888521
889087
|
const enabled = routine.enabled ? "enabled" : "disabled";
|
|
888522
889088
|
const tags = routine.tags.length > 0 ? ` tags=${routine.tags.join(",")}` : "";
|
|
888523
889089
|
return ` ${routine.id} ${enabled} ${routine.reviewState} starts=${routine.startCount} ${routine.name} - ${routine.description}${tags}`;
|
|
888524
889090
|
}
|
|
889091
|
+
function summarizeDiscoveredRoutine2(routine) {
|
|
889092
|
+
const description = routine.description ? ` - ${routine.description}` : "";
|
|
889093
|
+
return [
|
|
889094
|
+
` ${routine.name} ${routine.origin}${description}`,
|
|
889095
|
+
` path: ${routine.path}`
|
|
889096
|
+
].join(`
|
|
889097
|
+
`);
|
|
889098
|
+
}
|
|
889099
|
+
function renderDiscoveredRoutineList(routines) {
|
|
889100
|
+
if (routines.length === 0) {
|
|
889101
|
+
return [
|
|
889102
|
+
"Discovered Agent routine files",
|
|
889103
|
+
" No routine markdown files found in Agent routine folders.",
|
|
889104
|
+
" Search roots: .goodvibes/routines, .goodvibes/agent/routines, ~/.goodvibes/routines, ~/.goodvibes/agent/routines"
|
|
889105
|
+
].join(`
|
|
889106
|
+
`);
|
|
889107
|
+
}
|
|
889108
|
+
return [
|
|
889109
|
+
`Discovered Agent routine files (${routines.length})`,
|
|
889110
|
+
...routines.map(summarizeDiscoveredRoutine2),
|
|
889111
|
+
"",
|
|
889112
|
+
"Import one with: goodvibes-agent routines import-discovered <name> --yes"
|
|
889113
|
+
].join(`
|
|
889114
|
+
`);
|
|
889115
|
+
}
|
|
889116
|
+
function discoveredRoutineLookupValues2(routine) {
|
|
889117
|
+
const slug = routine.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
889118
|
+
const basename6 = routine.path.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
|
|
889119
|
+
return [routine.name, slug, routine.path, basename6].map((value) => value.trim().toLowerCase()).filter(Boolean);
|
|
889120
|
+
}
|
|
889121
|
+
function findDiscoveredRoutine2(routines, idOrName) {
|
|
889122
|
+
const lookup = idOrName.trim().toLowerCase();
|
|
889123
|
+
if (!lookup)
|
|
889124
|
+
return null;
|
|
889125
|
+
return routines.find((routine) => discoveredRoutineLookupValues2(routine).includes(lookup)) ?? null;
|
|
889126
|
+
}
|
|
889127
|
+
function discoveredRoutineFrontmatterList(routine, key) {
|
|
889128
|
+
const value = routine.frontmatter[key];
|
|
889129
|
+
if (!value)
|
|
889130
|
+
return [];
|
|
889131
|
+
return splitList6(value);
|
|
889132
|
+
}
|
|
888525
889133
|
function renderRoutineList(title, path7, routines) {
|
|
888526
889134
|
if (routines.length === 0) {
|
|
888527
889135
|
return [
|
|
@@ -888640,6 +889248,84 @@ async function handleRoutinesCommand(runtime3) {
|
|
|
888640
889248
|
exitCode: 0
|
|
888641
889249
|
};
|
|
888642
889250
|
}
|
|
889251
|
+
if (normalized === "discover") {
|
|
889252
|
+
const discovered = await discoverRoutines(shellPaths2(runtime3));
|
|
889253
|
+
const value = {
|
|
889254
|
+
ok: true,
|
|
889255
|
+
kind: "agent.routines.discover",
|
|
889256
|
+
data: { routines: discovered }
|
|
889257
|
+
};
|
|
889258
|
+
return {
|
|
889259
|
+
output: jsonOrText3(runtime3, value, renderDiscoveredRoutineList(discovered)),
|
|
889260
|
+
exitCode: 0
|
|
889261
|
+
};
|
|
889262
|
+
}
|
|
889263
|
+
if (normalized === "import-discovered" || normalized === "import-routine") {
|
|
889264
|
+
const parsed = parseImportFlags(rest);
|
|
889265
|
+
if (!parsed.name) {
|
|
889266
|
+
const failure3 = {
|
|
889267
|
+
ok: false,
|
|
889268
|
+
kind: "invalid_routine_command",
|
|
889269
|
+
error: "Usage: goodvibes-agent routines import-discovered <name> [--enabled] --yes"
|
|
889270
|
+
};
|
|
889271
|
+
return {
|
|
889272
|
+
output: runtime3.cli.flags.outputFormat === "json" ? JSON.stringify(failure3, null, 2) : failure3.error,
|
|
889273
|
+
exitCode: 2
|
|
889274
|
+
};
|
|
889275
|
+
}
|
|
889276
|
+
const discovered = findDiscoveredRoutine2(await discoverRoutines(shellPaths2(runtime3)), parsed.name);
|
|
889277
|
+
if (!discovered) {
|
|
889278
|
+
const failure3 = {
|
|
889279
|
+
ok: false,
|
|
889280
|
+
kind: "routine_discovery_not_found",
|
|
889281
|
+
error: `Unknown discovered Agent routine: ${parsed.name}
|
|
889282
|
+
Run goodvibes-agent routines discover to inspect available routine files.`
|
|
889283
|
+
};
|
|
889284
|
+
return {
|
|
889285
|
+
output: runtime3.cli.flags.outputFormat === "json" ? JSON.stringify(failure3, null, 2) : failure3.error,
|
|
889286
|
+
exitCode: 1
|
|
889287
|
+
};
|
|
889288
|
+
}
|
|
889289
|
+
if (!parsed.yes) {
|
|
889290
|
+
const value2 = {
|
|
889291
|
+
ok: true,
|
|
889292
|
+
kind: "agent.routines.import_discovered.preview",
|
|
889293
|
+
data: { routine: discovered }
|
|
889294
|
+
};
|
|
889295
|
+
return {
|
|
889296
|
+
output: jsonOrText3(runtime3, value2, [
|
|
889297
|
+
"Agent routine import preview",
|
|
889298
|
+
` name: ${discovered.name}`,
|
|
889299
|
+
` origin: ${discovered.origin}`,
|
|
889300
|
+
` path: ${discovered.path}`,
|
|
889301
|
+
` description: ${discovered.description || "(none)"}`,
|
|
889302
|
+
` steps characters: ${discovered.steps.length}`,
|
|
889303
|
+
" next: rerun with --yes to import into the Agent-local routine registry"
|
|
889304
|
+
].join(`
|
|
889305
|
+
`)),
|
|
889306
|
+
exitCode: 0
|
|
889307
|
+
};
|
|
889308
|
+
}
|
|
889309
|
+
const routine = registry5.create({
|
|
889310
|
+
name: discovered.name,
|
|
889311
|
+
description: discovered.description || `Imported routine from ${discovered.origin} markdown file.`,
|
|
889312
|
+
steps: discovered.steps,
|
|
889313
|
+
tags: discoveredRoutineFrontmatterList(discovered, "tags"),
|
|
889314
|
+
triggers: discoveredRoutineFrontmatterList(discovered, "triggers"),
|
|
889315
|
+
enabled: parsed.enabled,
|
|
889316
|
+
source: "imported",
|
|
889317
|
+
provenance: `discovered:${discovered.origin}:${discovered.path}`
|
|
889318
|
+
});
|
|
889319
|
+
const value = {
|
|
889320
|
+
ok: true,
|
|
889321
|
+
kind: "agent.routines.import_discovered",
|
|
889322
|
+
data: routine
|
|
889323
|
+
};
|
|
889324
|
+
return {
|
|
889325
|
+
output: jsonOrText3(runtime3, value, `Imported Agent routine ${routine.id}: ${routine.name}${routine.enabled ? " (enabled)" : ""}`),
|
|
889326
|
+
exitCode: 0
|
|
889327
|
+
};
|
|
889328
|
+
}
|
|
888643
889329
|
if (normalized === "show") {
|
|
888644
889330
|
const id = rest[0];
|
|
888645
889331
|
if (!id)
|
|
@@ -888704,7 +889390,7 @@ async function handleRoutinesCommand(runtime3) {
|
|
|
888704
889390
|
return handleRoutinePromotion(runtime3, rest);
|
|
888705
889391
|
}
|
|
888706
889392
|
return {
|
|
888707
|
-
output: "Usage: goodvibes-agent routines [list|enabled|show <id>|receipts|reconcile|receipt <id>|promote <id> (--cron <expr>|--every <interval>|--at <iso-time>) [--delivery-channel <channel>|--delivery-route <route>|--delivery-webhook <url>] --yes]",
|
|
889393
|
+
output: "Usage: goodvibes-agent routines [list|enabled|discover|import-discovered <name> --yes|show <id>|receipts|reconcile|receipt <id>|promote <id> (--cron <expr>|--every <interval>|--at <iso-time>) [--delivery-channel <channel>|--delivery-route <route>|--delivery-webhook <url>] --yes]",
|
|
888708
889394
|
exitCode: 2
|
|
888709
889395
|
};
|
|
888710
889396
|
}
|
|
@@ -888806,13 +889492,13 @@ async function withRuntimeServices(runtime3, fn) {
|
|
|
888806
889492
|
}
|
|
888807
889493
|
}
|
|
888808
889494
|
function readAuthPaths(runtime3) {
|
|
888809
|
-
const
|
|
889495
|
+
const shellPaths3 = createShellPathService2({
|
|
888810
889496
|
workingDirectory: runtime3.workingDirectory,
|
|
888811
889497
|
homeDirectory: runtime3.homeDirectory
|
|
888812
889498
|
});
|
|
888813
|
-
const userStorePath =
|
|
888814
|
-
const bootstrapCredentialPath =
|
|
888815
|
-
const operatorTokenPath =
|
|
889499
|
+
const userStorePath = shellPaths3.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-users.json");
|
|
889500
|
+
const bootstrapCredentialPath = shellPaths3.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-bootstrap.txt");
|
|
889501
|
+
const operatorTokenPath = join100(runtime3.homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
|
|
888816
889502
|
return {
|
|
888817
889503
|
userStorePath,
|
|
888818
889504
|
userStorePresent: existsSync84(userStorePath),
|
|
@@ -889327,7 +890013,7 @@ async function prepareShellCliRuntime(argv, roots, binary2 = "goodvibes-agent")
|
|
|
889327
890013
|
workingDirectory: bootstrapWorkingDir,
|
|
889328
890014
|
homeDirectory: bootstrapHomeDirectory
|
|
889329
890015
|
} = ownership;
|
|
889330
|
-
configureActivityLogger(
|
|
890016
|
+
configureActivityLogger(join101(bootstrapWorkingDir, ".goodvibes", "logs"));
|
|
889331
890017
|
const configManager = new ConfigManager({
|
|
889332
890018
|
workingDir: bootstrapWorkingDir,
|
|
889333
890019
|
homeDir: bootstrapHomeDirectory,
|
|
@@ -889372,14 +890058,14 @@ async function prepareShellCliRuntime(argv, roots, binary2 = "goodvibes-agent")
|
|
|
889372
890058
|
process.exit(2);
|
|
889373
890059
|
}
|
|
889374
890060
|
if (cli.command === "status" || cli.command === "doctor" || cli.command === "onboarding" && cli.commandArgs[0] === "status") {
|
|
889375
|
-
const
|
|
890061
|
+
const shellPaths3 = createShellPathService2({
|
|
889376
890062
|
workingDirectory: bootstrapWorkingDir,
|
|
889377
890063
|
homeDirectory: bootstrapHomeDirectory
|
|
889378
890064
|
});
|
|
889379
|
-
const userStorePath =
|
|
889380
|
-
const bootstrapCredentialPath =
|
|
889381
|
-
const operatorTokenPath =
|
|
889382
|
-
const onboardingMarkers = readOnboardingCheckMarkers(
|
|
890065
|
+
const userStorePath = shellPaths3.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-users.json");
|
|
890066
|
+
const bootstrapCredentialPath = shellPaths3.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-bootstrap.txt");
|
|
890067
|
+
const operatorTokenPath = join101(bootstrapHomeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
|
|
890068
|
+
const onboardingMarkers = readOnboardingCheckMarkers(shellPaths3);
|
|
889383
890069
|
const service = await buildCliServicePosture({
|
|
889384
890070
|
configManager,
|
|
889385
890071
|
workingDirectory: bootstrapWorkingDir,
|
|
@@ -889493,8 +890179,8 @@ function getInteractiveTerminalLaunchError(input) {
|
|
|
889493
890179
|
`);
|
|
889494
890180
|
}
|
|
889495
890181
|
function applyInitialTuiCliState(options) {
|
|
889496
|
-
const { cli, input, commandRegistry, commandContext, shellPaths:
|
|
889497
|
-
const globalOnboardingMarker = readOnboardingCheckMarker(
|
|
890182
|
+
const { cli, input, commandRegistry, commandContext, shellPaths: shellPaths3, render } = options;
|
|
890183
|
+
const globalOnboardingMarker = readOnboardingCheckMarker(shellPaths3, "user");
|
|
889498
890184
|
const seededPrompt = cli.flags.prompt ?? (cli.rawCommand === undefined && cli.positionals.length > 0 ? cli.positionals.join(" ") : undefined);
|
|
889499
890185
|
if (cli.command === "onboarding") {
|
|
889500
890186
|
input.openOnboardingWizard({ mode: "edit", reset: true });
|
|
@@ -889516,7 +890202,7 @@ function applyInitialTuiCliState(options) {
|
|
|
889516
890202
|
|
|
889517
890203
|
// src/audio/player.ts
|
|
889518
890204
|
import { accessSync, constants as constants4 } from "fs";
|
|
889519
|
-
import { delimiter, join as
|
|
890205
|
+
import { delimiter, join as join102 } from "path";
|
|
889520
890206
|
import { spawn as spawn6 } from "child_process";
|
|
889521
890207
|
|
|
889522
890208
|
class LocalStreamingAudioPlayer {
|
|
@@ -889613,7 +890299,7 @@ function findExecutable(name51, env2) {
|
|
|
889613
890299
|
if (!dir)
|
|
889614
890300
|
continue;
|
|
889615
890301
|
for (const ext of extensions14) {
|
|
889616
|
-
const candidate =
|
|
890302
|
+
const candidate = join102(dir, `${name51}${ext}`);
|
|
889617
890303
|
try {
|
|
889618
890304
|
accessSync(candidate, constants4.X_OK);
|
|
889619
890305
|
return candidate;
|