@pellux/goodvibes-agent 0.1.113 → 0.1.116
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 +19 -0
- package/README.md +4 -0
- package/dist/package/main.js +1659 -324
- package/docs/getting-started.md +4 -0
- package/package.json +1 -1
- package/src/agent/behavior-discovery-summary.ts +167 -0
- package/src/agent/persona-discovery.ts +117 -0
- package/src/agent/routine-discovery.ts +115 -0
- package/src/agent/runtime-profile-starters.ts +331 -0
- package/src/agent/runtime-profile.ts +150 -330
- package/src/cli/help.ts +11 -3
- package/src/cli/local-library-command.ts +81 -1
- package/src/cli/profiles-command.ts +128 -0
- package/src/cli/routines-command.ts +156 -1
- package/src/input/agent-workspace-basic-command-editor-submission.ts +534 -0
- package/src/input/agent-workspace-basic-command-editors.ts +77 -395
- package/src/input/agent-workspace-categories.ts +7 -0
- package/src/input/agent-workspace-command-editor.ts +4 -0
- package/src/input/agent-workspace-setup.ts +33 -13
- package/src/input/agent-workspace-snapshot.ts +6 -0
- package/src/input/agent-workspace-types.ts +6 -0
- package/src/input/commands/agent-runtime-profile-runtime.ts +73 -4
- package/src/input/commands/personas-runtime.ts +87 -2
- package/src/input/commands/routines-runtime.ts +87 -2
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +46 -9
- package/src/input/onboarding/onboarding-wizard-steps.ts +1 -1
- package/src/renderer/agent-workspace.ts +26 -0
- package/src/runtime/onboarding/derivation.ts +20 -1
- package/src/runtime/onboarding/snapshot.ts +2 -0
- package/src/runtime/onboarding/types.ts +2 -0
- 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.116";
|
|
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 join92 } from "path";
|
|
841978
841978
|
|
|
841979
841979
|
// src/input/command-registry.ts
|
|
841980
841980
|
class CommandRegistry {
|
|
@@ -851684,9 +851684,195 @@ import { dirname as dirname58 } from "path";
|
|
|
851684
851684
|
|
|
851685
851685
|
// src/agent/runtime-profile.ts
|
|
851686
851686
|
import { existsSync as existsSync71, mkdirSync as mkdirSync59, readFileSync as readFileSync78, readdirSync as readdirSync20, rmSync as rmSync9, statSync as statSync19, writeFileSync as writeFileSync51 } from "fs";
|
|
851687
|
-
import { dirname as dirname57, join as
|
|
851688
|
-
|
|
851689
|
-
|
|
851687
|
+
import { dirname as dirname57, join as join88 } from "path";
|
|
851688
|
+
|
|
851689
|
+
// src/agent/persona-discovery.ts
|
|
851690
|
+
import { promises as fsPromises5 } from "fs";
|
|
851691
|
+
import { join as join86 } from "path";
|
|
851692
|
+
var DIRECTORY_MARKERS = ["PERSONA.md", "persona.md", "AGENT.md", "agent.md"];
|
|
851693
|
+
function parseFrontmatter2(content) {
|
|
851694
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
851695
|
+
if (!match)
|
|
851696
|
+
return {};
|
|
851697
|
+
const result2 = {};
|
|
851698
|
+
for (const line of match[1].split(`
|
|
851699
|
+
`)) {
|
|
851700
|
+
const [key, ...rest] = line.split(":");
|
|
851701
|
+
if (key && rest.length > 0) {
|
|
851702
|
+
result2[key.trim()] = rest.join(":").trim();
|
|
851703
|
+
}
|
|
851704
|
+
}
|
|
851705
|
+
return result2;
|
|
851706
|
+
}
|
|
851707
|
+
function getPersonaDirectories(cwd, homeDir) {
|
|
851708
|
+
return [
|
|
851709
|
+
{ root: join86(cwd, ".goodvibes", "personas"), origin: "project-local" },
|
|
851710
|
+
{ root: join86(cwd, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "personas"), origin: "project-local" },
|
|
851711
|
+
{ root: join86(cwd, ".goodvibes", "agents"), origin: "project-local" },
|
|
851712
|
+
{ root: join86(homeDir, ".goodvibes", "personas"), origin: "global" },
|
|
851713
|
+
{ root: join86(homeDir, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "personas"), origin: "global" },
|
|
851714
|
+
{ root: join86(homeDir, ".goodvibes", "agents"), origin: "global" }
|
|
851715
|
+
];
|
|
851716
|
+
}
|
|
851717
|
+
async function readPersonaFile(path7, origin) {
|
|
851718
|
+
let content = "";
|
|
851719
|
+
try {
|
|
851720
|
+
content = await fsPromises5.readFile(path7, "utf-8");
|
|
851721
|
+
} catch {
|
|
851722
|
+
return null;
|
|
851723
|
+
}
|
|
851724
|
+
const frontmatter = parseFrontmatter2(content);
|
|
851725
|
+
const markdownBody = content.replace(/^---\n[\s\S]*?\n---\n?/, "").trim();
|
|
851726
|
+
const body2 = (frontmatter.system_prompt ?? markdownBody).trim();
|
|
851727
|
+
if (!body2)
|
|
851728
|
+
return null;
|
|
851729
|
+
const name51 = frontmatter.name ?? path7.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "persona";
|
|
851730
|
+
const description = frontmatter.description ?? frontmatter.summary ?? frontmatter.title ?? "";
|
|
851731
|
+
return {
|
|
851732
|
+
name: name51,
|
|
851733
|
+
description,
|
|
851734
|
+
path: path7,
|
|
851735
|
+
origin,
|
|
851736
|
+
body: body2,
|
|
851737
|
+
frontmatter
|
|
851738
|
+
};
|
|
851739
|
+
}
|
|
851740
|
+
async function scanPersonaDirectory(root, origin) {
|
|
851741
|
+
let entries = [];
|
|
851742
|
+
try {
|
|
851743
|
+
entries = await fsPromises5.readdir(root);
|
|
851744
|
+
} catch {
|
|
851745
|
+
return [];
|
|
851746
|
+
}
|
|
851747
|
+
const records = [];
|
|
851748
|
+
for (const entry of entries.sort((a4, b3) => a4.localeCompare(b3))) {
|
|
851749
|
+
if (entry.endsWith(".md")) {
|
|
851750
|
+
const record2 = await readPersonaFile(join86(root, entry), origin);
|
|
851751
|
+
if (record2)
|
|
851752
|
+
records.push(record2);
|
|
851753
|
+
continue;
|
|
851754
|
+
}
|
|
851755
|
+
for (const marker of DIRECTORY_MARKERS) {
|
|
851756
|
+
const record2 = await readPersonaFile(join86(root, entry, marker), origin);
|
|
851757
|
+
if (record2) {
|
|
851758
|
+
records.push(record2);
|
|
851759
|
+
break;
|
|
851760
|
+
}
|
|
851761
|
+
}
|
|
851762
|
+
}
|
|
851763
|
+
return records;
|
|
851764
|
+
}
|
|
851765
|
+
async function discoverPersonas(shellPaths) {
|
|
851766
|
+
const seen = new Set;
|
|
851767
|
+
const records = [];
|
|
851768
|
+
for (const { root, origin } of getPersonaDirectories(shellPaths.workingDirectory, shellPaths.homeDirectory)) {
|
|
851769
|
+
for (const record2 of await scanPersonaDirectory(root, origin)) {
|
|
851770
|
+
const key = record2.name.toLowerCase();
|
|
851771
|
+
if (seen.has(key))
|
|
851772
|
+
continue;
|
|
851773
|
+
seen.add(key);
|
|
851774
|
+
records.push(record2);
|
|
851775
|
+
}
|
|
851776
|
+
}
|
|
851777
|
+
return records.sort((a4, b3) => {
|
|
851778
|
+
const originRank = a4.origin === b3.origin ? 0 : a4.origin === "project-local" ? -1 : 1;
|
|
851779
|
+
return originRank || a4.name.localeCompare(b3.name);
|
|
851780
|
+
});
|
|
851781
|
+
}
|
|
851782
|
+
|
|
851783
|
+
// src/agent/routine-discovery.ts
|
|
851784
|
+
import { promises as fsPromises6 } from "fs";
|
|
851785
|
+
import { join as join87 } from "path";
|
|
851786
|
+
var DIRECTORY_MARKERS2 = ["ROUTINE.md", "routine.md"];
|
|
851787
|
+
function parseFrontmatter3(content) {
|
|
851788
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
851789
|
+
if (!match)
|
|
851790
|
+
return {};
|
|
851791
|
+
const result2 = {};
|
|
851792
|
+
for (const line of match[1].split(`
|
|
851793
|
+
`)) {
|
|
851794
|
+
const [key, ...rest] = line.split(":");
|
|
851795
|
+
if (key && rest.length > 0) {
|
|
851796
|
+
result2[key.trim()] = rest.join(":").trim();
|
|
851797
|
+
}
|
|
851798
|
+
}
|
|
851799
|
+
return result2;
|
|
851800
|
+
}
|
|
851801
|
+
function getRoutineDirectories(cwd, homeDir) {
|
|
851802
|
+
return [
|
|
851803
|
+
{ root: join87(cwd, ".goodvibes", "routines"), origin: "project-local" },
|
|
851804
|
+
{ root: join87(cwd, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "routines"), origin: "project-local" },
|
|
851805
|
+
{ root: join87(homeDir, ".goodvibes", "routines"), origin: "global" },
|
|
851806
|
+
{ root: join87(homeDir, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "routines"), origin: "global" }
|
|
851807
|
+
];
|
|
851808
|
+
}
|
|
851809
|
+
async function readRoutineFile(path7, origin) {
|
|
851810
|
+
let content = "";
|
|
851811
|
+
try {
|
|
851812
|
+
content = await fsPromises6.readFile(path7, "utf-8");
|
|
851813
|
+
} catch {
|
|
851814
|
+
return null;
|
|
851815
|
+
}
|
|
851816
|
+
const frontmatter = parseFrontmatter3(content);
|
|
851817
|
+
const markdownBody = content.replace(/^---\n[\s\S]*?\n---\n?/, "").trim();
|
|
851818
|
+
const steps = (frontmatter.steps ?? markdownBody).trim();
|
|
851819
|
+
if (!steps)
|
|
851820
|
+
return null;
|
|
851821
|
+
const name51 = frontmatter.name ?? path7.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "routine";
|
|
851822
|
+
const description = frontmatter.description ?? frontmatter.summary ?? frontmatter.title ?? "";
|
|
851823
|
+
return {
|
|
851824
|
+
name: name51,
|
|
851825
|
+
description,
|
|
851826
|
+
path: path7,
|
|
851827
|
+
origin,
|
|
851828
|
+
steps,
|
|
851829
|
+
frontmatter
|
|
851830
|
+
};
|
|
851831
|
+
}
|
|
851832
|
+
async function scanRoutineDirectory(root, origin) {
|
|
851833
|
+
let entries = [];
|
|
851834
|
+
try {
|
|
851835
|
+
entries = await fsPromises6.readdir(root);
|
|
851836
|
+
} catch {
|
|
851837
|
+
return [];
|
|
851838
|
+
}
|
|
851839
|
+
const records = [];
|
|
851840
|
+
for (const entry of entries.sort((a4, b3) => a4.localeCompare(b3))) {
|
|
851841
|
+
if (entry.endsWith(".md")) {
|
|
851842
|
+
const record2 = await readRoutineFile(join87(root, entry), origin);
|
|
851843
|
+
if (record2)
|
|
851844
|
+
records.push(record2);
|
|
851845
|
+
continue;
|
|
851846
|
+
}
|
|
851847
|
+
for (const marker of DIRECTORY_MARKERS2) {
|
|
851848
|
+
const record2 = await readRoutineFile(join87(root, entry, marker), origin);
|
|
851849
|
+
if (record2) {
|
|
851850
|
+
records.push(record2);
|
|
851851
|
+
break;
|
|
851852
|
+
}
|
|
851853
|
+
}
|
|
851854
|
+
}
|
|
851855
|
+
return records;
|
|
851856
|
+
}
|
|
851857
|
+
async function discoverRoutines(shellPaths) {
|
|
851858
|
+
const seen = new Set;
|
|
851859
|
+
const records = [];
|
|
851860
|
+
for (const { root, origin } of getRoutineDirectories(shellPaths.workingDirectory, shellPaths.homeDirectory)) {
|
|
851861
|
+
for (const record2 of await scanRoutineDirectory(root, origin)) {
|
|
851862
|
+
const key = record2.name.toLowerCase();
|
|
851863
|
+
if (seen.has(key))
|
|
851864
|
+
continue;
|
|
851865
|
+
seen.add(key);
|
|
851866
|
+
records.push(record2);
|
|
851867
|
+
}
|
|
851868
|
+
}
|
|
851869
|
+
return records.sort((a4, b3) => {
|
|
851870
|
+
const originRank = a4.origin === b3.origin ? 0 : a4.origin === "project-local" ? -1 : 1;
|
|
851871
|
+
return originRank || a4.name.localeCompare(b3.name);
|
|
851872
|
+
});
|
|
851873
|
+
}
|
|
851874
|
+
|
|
851875
|
+
// src/agent/runtime-profile-starters.ts
|
|
851690
851876
|
var STARTER_TEMPLATES = [
|
|
851691
851877
|
{
|
|
851692
851878
|
id: "household",
|
|
@@ -852007,6 +852193,10 @@ var STARTER_TEMPLATES = [
|
|
|
852007
852193
|
]
|
|
852008
852194
|
}
|
|
852009
852195
|
];
|
|
852196
|
+
|
|
852197
|
+
// src/agent/runtime-profile.ts
|
|
852198
|
+
var PROFILE_CREATED_FILE = "profile.json";
|
|
852199
|
+
var PROFILE_ID_PATTERN = /^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/;
|
|
852010
852200
|
function normalizeAgentRuntimeProfileId(value) {
|
|
852011
852201
|
return value.trim().toLowerCase().replace(/[^a-z0-9._-]+/g, "-").replace(/^[._-]+|[._-]+$/g, "").replace(/[-_]{2,}/g, "-");
|
|
852012
852202
|
}
|
|
@@ -852022,20 +852212,20 @@ function assertValidAgentRuntimeProfileId(value) {
|
|
|
852022
852212
|
return normalized;
|
|
852023
852213
|
}
|
|
852024
852214
|
function getAgentRuntimeProfilesRoot(baseHomeDirectory) {
|
|
852025
|
-
return
|
|
852215
|
+
return join88(baseHomeDirectory, ".goodvibes", "agent", "profile-homes");
|
|
852026
852216
|
}
|
|
852027
852217
|
function getAgentRuntimeProfileTemplatesRoot(baseHomeDirectory) {
|
|
852028
|
-
return
|
|
852218
|
+
return join88(baseHomeDirectory, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "profile-starters");
|
|
852029
852219
|
}
|
|
852030
852220
|
function resolveAgentRuntimeProfileHome(baseHomeDirectory, profileName) {
|
|
852031
852221
|
const id = assertValidAgentRuntimeProfileId(profileName);
|
|
852032
852222
|
return {
|
|
852033
852223
|
id,
|
|
852034
|
-
homeDirectory:
|
|
852224
|
+
homeDirectory: join88(getAgentRuntimeProfilesRoot(baseHomeDirectory), id)
|
|
852035
852225
|
};
|
|
852036
852226
|
}
|
|
852037
852227
|
function readProfileCreatedAt(homeDirectory) {
|
|
852038
|
-
const path7 =
|
|
852228
|
+
const path7 = join88(homeDirectory, PROFILE_CREATED_FILE);
|
|
852039
852229
|
if (!existsSync71(path7))
|
|
852040
852230
|
return null;
|
|
852041
852231
|
try {
|
|
@@ -852048,7 +852238,7 @@ function readProfileCreatedAt(homeDirectory) {
|
|
|
852048
852238
|
return null;
|
|
852049
852239
|
}
|
|
852050
852240
|
function readProfileStarterTemplate(homeDirectory) {
|
|
852051
|
-
const path7 =
|
|
852241
|
+
const path7 = join88(homeDirectory, PROFILE_CREATED_FILE);
|
|
852052
852242
|
if (!existsSync71(path7))
|
|
852053
852243
|
return {};
|
|
852054
852244
|
try {
|
|
@@ -852082,7 +852272,7 @@ function buildProfileInfo(baseHomeDirectory, id) {
|
|
|
852082
852272
|
};
|
|
852083
852273
|
}
|
|
852084
852274
|
function profileStorePath(homeDirectory, folder, file2) {
|
|
852085
|
-
return
|
|
852275
|
+
return join88(homeDirectory, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, folder, file2);
|
|
852086
852276
|
}
|
|
852087
852277
|
function isAgentRuntimeProfileTemplateId(value) {
|
|
852088
852278
|
if (typeof value !== "string")
|
|
@@ -852111,6 +852301,65 @@ function parseStringArray(value) {
|
|
|
852111
852301
|
return [];
|
|
852112
852302
|
return value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter(Boolean);
|
|
852113
852303
|
}
|
|
852304
|
+
function splitFrontmatterList(value) {
|
|
852305
|
+
if (!value)
|
|
852306
|
+
return [];
|
|
852307
|
+
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
852308
|
+
}
|
|
852309
|
+
function normalizedLookupValues(value, path7) {
|
|
852310
|
+
const slug = value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
852311
|
+
const basename5 = path7?.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
|
|
852312
|
+
return [value, slug, path7 ?? "", basename5].map((entry) => entry.trim().toLowerCase()).filter(Boolean);
|
|
852313
|
+
}
|
|
852314
|
+
function selectDiscoveredRecord(records, selector2, label) {
|
|
852315
|
+
if (records.length === 0)
|
|
852316
|
+
throw new Error(`No discovered Agent ${label} files found.`);
|
|
852317
|
+
if (!selector2?.trim())
|
|
852318
|
+
return records[0];
|
|
852319
|
+
const lookup = selector2.trim().toLowerCase();
|
|
852320
|
+
const match = records.find((record2) => normalizedLookupValues(record2.name, record2.path).includes(lookup));
|
|
852321
|
+
if (!match)
|
|
852322
|
+
throw new Error(`Unknown discovered Agent ${label}: ${selector2}.`);
|
|
852323
|
+
return match;
|
|
852324
|
+
}
|
|
852325
|
+
function selectDiscoveredRecords(records, selectors4, label) {
|
|
852326
|
+
if (records.length === 0)
|
|
852327
|
+
throw new Error(`No discovered Agent ${label} files found.`);
|
|
852328
|
+
if (!selectors4 || selectors4.length === 0 || selectors4.includes("all"))
|
|
852329
|
+
return records;
|
|
852330
|
+
return selectors4.map((selector2) => selectDiscoveredRecord(records, selector2, label));
|
|
852331
|
+
}
|
|
852332
|
+
function discoveredSkillToTemplate(skill) {
|
|
852333
|
+
if (!skill.body.trim())
|
|
852334
|
+
throw new Error(`Discovered Agent skill ${skill.name} has no procedure body.`);
|
|
852335
|
+
return {
|
|
852336
|
+
name: skill.name,
|
|
852337
|
+
description: skill.description || `Imported skill from ${skill.origin} skill file.`,
|
|
852338
|
+
procedure: skill.body,
|
|
852339
|
+
triggers: splitFrontmatterList(skill.frontmatter.triggers),
|
|
852340
|
+
tags: splitFrontmatterList(skill.frontmatter.tags)
|
|
852341
|
+
};
|
|
852342
|
+
}
|
|
852343
|
+
function discoveredRoutineToTemplate(routine) {
|
|
852344
|
+
if (!routine.steps.trim())
|
|
852345
|
+
throw new Error(`Discovered Agent routine ${routine.name} has no steps.`);
|
|
852346
|
+
return {
|
|
852347
|
+
name: routine.name,
|
|
852348
|
+
description: routine.description || `Imported routine from ${routine.origin} markdown file.`,
|
|
852349
|
+
steps: routine.steps,
|
|
852350
|
+
triggers: splitFrontmatterList(routine.frontmatter.triggers),
|
|
852351
|
+
tags: splitFrontmatterList(routine.frontmatter.tags)
|
|
852352
|
+
};
|
|
852353
|
+
}
|
|
852354
|
+
function discoveredPersonaToTemplate(persona) {
|
|
852355
|
+
return {
|
|
852356
|
+
name: persona.name,
|
|
852357
|
+
description: persona.description || `Imported persona from ${persona.origin} markdown file.`,
|
|
852358
|
+
body: persona.body,
|
|
852359
|
+
tags: splitFrontmatterList(persona.frontmatter.tags),
|
|
852360
|
+
triggers: splitFrontmatterList(persona.frontmatter.triggers)
|
|
852361
|
+
};
|
|
852362
|
+
}
|
|
852114
852363
|
function readTemplateTextBlock(value, field) {
|
|
852115
852364
|
if (typeof value !== "string" || !value.trim())
|
|
852116
852365
|
throw new Error(`Starter template ${field} is required.`);
|
|
@@ -852184,7 +852433,7 @@ function listLocalTemplates(baseHomeDirectory) {
|
|
|
852184
852433
|
const root = getAgentRuntimeProfileTemplatesRoot(baseHomeDirectory);
|
|
852185
852434
|
if (!existsSync71(root))
|
|
852186
852435
|
return [];
|
|
852187
|
-
return readdirSync20(root).filter((entry) => entry.endsWith(".json")).map((entry) => readLocalTemplate(
|
|
852436
|
+
return readdirSync20(root).filter((entry) => entry.endsWith(".json")).map((entry) => readLocalTemplate(join88(root, entry))).filter((entry) => entry !== null).sort((left, right) => left.id.localeCompare(right.id));
|
|
852188
852437
|
}
|
|
852189
852438
|
function resolveAgentRuntimeProfileTemplate(templateId, baseHomeDirectory) {
|
|
852190
852439
|
const id = assertValidAgentRuntimeProfileId(templateId);
|
|
@@ -852235,11 +852484,63 @@ function importAgentRuntimeProfileTemplate(baseHomeDirectory, sourcePath) {
|
|
|
852235
852484
|
const parsed = parseStarterTemplate(JSON.parse(readFileSync78(source, "utf-8")), "local");
|
|
852236
852485
|
const root = getAgentRuntimeProfileTemplatesRoot(baseHomeDirectory);
|
|
852237
852486
|
mkdirSync59(root, { recursive: true });
|
|
852238
|
-
const target =
|
|
852487
|
+
const target = join88(root, `${parsed.id}.json`);
|
|
852239
852488
|
writeFileSync51(target, `${JSON.stringify(templateFilePayload({ ...parsed, source: "local", path: target }), null, 2)}
|
|
852240
852489
|
`, "utf-8");
|
|
852241
852490
|
return summarizeTemplate({ ...parsed, source: "local", path: target });
|
|
852242
852491
|
}
|
|
852492
|
+
async function createAgentRuntimeProfileTemplateFromDiscovered(shellPaths, options) {
|
|
852493
|
+
const id = assertValidAgentRuntimeProfileId(options.id);
|
|
852494
|
+
const [personas, skills, routines] = await Promise.all([
|
|
852495
|
+
discoverPersonas(shellPaths),
|
|
852496
|
+
discoverSkills(shellPaths),
|
|
852497
|
+
discoverRoutines(shellPaths)
|
|
852498
|
+
]);
|
|
852499
|
+
const selectedPersona = selectDiscoveredRecord(personas, options.persona, "persona");
|
|
852500
|
+
const selectedSkills = selectDiscoveredRecords(skills, options.skills, "skill");
|
|
852501
|
+
const selectedRoutines = selectDiscoveredRecords(routines, options.routines, "routine");
|
|
852502
|
+
const target = join88(getAgentRuntimeProfileTemplatesRoot(shellPaths.homeDirectory), `${id}.json`);
|
|
852503
|
+
if (existsSync71(target) && options.replace !== true) {
|
|
852504
|
+
throw new Error(`Agent starter template already exists: ${id}. Rerun with --replace to overwrite it.`);
|
|
852505
|
+
}
|
|
852506
|
+
const persona = discoveredPersonaToTemplate(selectedPersona);
|
|
852507
|
+
const template = {
|
|
852508
|
+
id,
|
|
852509
|
+
source: "local",
|
|
852510
|
+
path: target,
|
|
852511
|
+
name: options.name?.trim() || `${persona.name} Starter`,
|
|
852512
|
+
description: options.description?.trim() || "Agent starter template assembled from discovered local persona, skill, and routine files.",
|
|
852513
|
+
personaName: persona.name,
|
|
852514
|
+
skillNames: selectedSkills.map((skill) => skill.name),
|
|
852515
|
+
routineNames: selectedRoutines.map((routine) => routine.name),
|
|
852516
|
+
persona,
|
|
852517
|
+
skills: selectedSkills.map(discoveredSkillToTemplate),
|
|
852518
|
+
routines: selectedRoutines.map(discoveredRoutineToTemplate)
|
|
852519
|
+
};
|
|
852520
|
+
mkdirSync59(dirname57(target), { recursive: true });
|
|
852521
|
+
writeFileSync51(target, `${JSON.stringify(templateFilePayload(template), null, 2)}
|
|
852522
|
+
`, "utf-8");
|
|
852523
|
+
return summarizeTemplate(template);
|
|
852524
|
+
}
|
|
852525
|
+
async function createAgentRuntimeProfileFromDiscovered(shellPaths, options) {
|
|
852526
|
+
const profileId = assertValidAgentRuntimeProfileId(options.profileName);
|
|
852527
|
+
const resolution2 = resolveAgentRuntimeProfileHome(shellPaths.homeDirectory, profileId);
|
|
852528
|
+
if (existsSync71(resolution2.homeDirectory)) {
|
|
852529
|
+
throw new Error(`Agent profile already exists: ${resolution2.id}`);
|
|
852530
|
+
}
|
|
852531
|
+
const templateId = assertValidAgentRuntimeProfileId(options.templateId ?? profileId);
|
|
852532
|
+
const template = await createAgentRuntimeProfileTemplateFromDiscovered(shellPaths, {
|
|
852533
|
+
id: templateId,
|
|
852534
|
+
name: options.name,
|
|
852535
|
+
description: options.description,
|
|
852536
|
+
persona: options.persona,
|
|
852537
|
+
skills: options.skills,
|
|
852538
|
+
routines: options.routines,
|
|
852539
|
+
replace: options.replace
|
|
852540
|
+
});
|
|
852541
|
+
const profile5 = createAgentRuntimeProfile(shellPaths.homeDirectory, profileId, { templateId: template.id });
|
|
852542
|
+
return { profile: profile5, template };
|
|
852543
|
+
}
|
|
852243
852544
|
function createMissingSkill(registry5, template) {
|
|
852244
852545
|
const existing = registry5.get(template.name);
|
|
852245
852546
|
if (existing)
|
|
@@ -852304,7 +852605,7 @@ function listAgentRuntimeProfiles(baseHomeDirectory) {
|
|
|
852304
852605
|
return [];
|
|
852305
852606
|
return readdirSync20(root).filter((entry) => PROFILE_ID_PATTERN.test(entry) && !entry.includes("..")).filter((entry) => {
|
|
852306
852607
|
try {
|
|
852307
|
-
return statSync19(
|
|
852608
|
+
return statSync19(join88(root, entry)).isDirectory();
|
|
852308
852609
|
} catch {
|
|
852309
852610
|
return false;
|
|
852310
852611
|
}
|
|
@@ -852318,7 +852619,7 @@ function createAgentRuntimeProfile(baseHomeDirectory, profileName, options = {})
|
|
|
852318
852619
|
mkdirSync59(resolution2.homeDirectory, { recursive: true });
|
|
852319
852620
|
const createdAt = new Date().toISOString();
|
|
852320
852621
|
const appliedTemplate = options.templateId ? applyAgentRuntimeProfileTemplate(resolution2.homeDirectory, options.templateId, baseHomeDirectory) : undefined;
|
|
852321
|
-
writeFileSync51(
|
|
852622
|
+
writeFileSync51(join88(resolution2.homeDirectory, PROFILE_CREATED_FILE), `${JSON.stringify({
|
|
852322
852623
|
id: resolution2.id,
|
|
852323
852624
|
createdAt,
|
|
852324
852625
|
starterTemplate: appliedTemplate
|
|
@@ -852348,6 +852649,12 @@ function parseFlag(args2, name51) {
|
|
|
852348
852649
|
const value = args2[index + 1];
|
|
852349
852650
|
return value && !value.startsWith("--") ? value : undefined;
|
|
852350
852651
|
}
|
|
852652
|
+
function parseCsvFlag(args2, name51) {
|
|
852653
|
+
const raw = parseFlag(args2, name51);
|
|
852654
|
+
if (!raw)
|
|
852655
|
+
return;
|
|
852656
|
+
return raw.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
852657
|
+
}
|
|
852351
852658
|
function profileLine(profile5) {
|
|
852352
852659
|
const created = profile5.createdAt ? ` created=${profile5.createdAt}` : "";
|
|
852353
852660
|
const starter = profile5.starterTemplateId ? ` starter=${profile5.starterTemplateId}` : "";
|
|
@@ -852387,7 +852694,8 @@ function renderTemplates(homeDirectory) {
|
|
|
852387
852694
|
" /agent-profile template export research ./agent-starter.json --yes",
|
|
852388
852695
|
" edit the JSON file",
|
|
852389
852696
|
" /agent-profile template import ./agent-starter.json --yes",
|
|
852390
|
-
" /agent-profile create <name> --template <imported-id> --yes"
|
|
852697
|
+
" /agent-profile create <name> --template <imported-id> --yes",
|
|
852698
|
+
" /agent-profile create-from-discovered <name> --yes"
|
|
852391
852699
|
].join(`
|
|
852392
852700
|
`);
|
|
852393
852701
|
}
|
|
@@ -852434,8 +852742,8 @@ function registerAgentRuntimeProfileRuntimeCommands(registry5) {
|
|
|
852434
852742
|
name: "agent-profile",
|
|
852435
852743
|
aliases: ["runtime-profile", "agent-profiles"],
|
|
852436
852744
|
description: "Manage isolated Agent profiles and starter templates",
|
|
852437
|
-
usage: "[list|templates|guide|template show|template export|template import|create|delete]",
|
|
852438
|
-
handler(args2, ctx) {
|
|
852745
|
+
usage: "[list|templates|guide|template show|template export|template import|template from-discovered|create|create-from-discovered|delete]",
|
|
852746
|
+
async handler(args2, ctx) {
|
|
852439
852747
|
const shellPaths = requireShellPaths(ctx);
|
|
852440
852748
|
const homeDirectory = shellPaths.homeDirectory;
|
|
852441
852749
|
const parsed = stripYesFlag(args2);
|
|
@@ -852501,7 +852809,36 @@ function registerAgentRuntimeProfileRuntimeCommands(registry5) {
|
|
|
852501
852809
|
use: /agent-profile create <name> --template ${template.id} --yes`);
|
|
852502
852810
|
return;
|
|
852503
852811
|
}
|
|
852504
|
-
|
|
852812
|
+
if (mode === "from-discovered" || mode === "import-discovered") {
|
|
852813
|
+
const templateId = commandArgs[2];
|
|
852814
|
+
if (!templateId) {
|
|
852815
|
+
ctx.print("Usage: /agent-profile template from-discovered <id> [--name <name>] [--description <summary>] [--persona <name>] [--skills all|name,name] [--routines all|name,name] [--replace] --yes");
|
|
852816
|
+
return;
|
|
852817
|
+
}
|
|
852818
|
+
if (!parsed.yes) {
|
|
852819
|
+
requireYesFlag(ctx, `create Agent starter template ${templateId} from discovered behavior`, "/agent-profile template from-discovered <id> --yes");
|
|
852820
|
+
return;
|
|
852821
|
+
}
|
|
852822
|
+
const template = await createAgentRuntimeProfileTemplateFromDiscovered(shellPaths, {
|
|
852823
|
+
id: templateId,
|
|
852824
|
+
name: parseFlag(commandArgs, "--name"),
|
|
852825
|
+
description: parseFlag(commandArgs, "--description"),
|
|
852826
|
+
persona: parseFlag(commandArgs, "--persona"),
|
|
852827
|
+
skills: parseCsvFlag(commandArgs, "--skills"),
|
|
852828
|
+
routines: parseCsvFlag(commandArgs, "--routines"),
|
|
852829
|
+
replace: commandArgs.includes("--replace")
|
|
852830
|
+
});
|
|
852831
|
+
ctx.print([
|
|
852832
|
+
`Agent starter template created from discovered behavior: ${template.id}`,
|
|
852833
|
+
` persona: ${template.personaName}`,
|
|
852834
|
+
` skills: ${template.skillNames.join(", ")}`,
|
|
852835
|
+
` routines: ${template.routineNames.join(", ")}`,
|
|
852836
|
+
` use: /agent-profile create <name> --template ${template.id} --yes`
|
|
852837
|
+
].join(`
|
|
852838
|
+
`));
|
|
852839
|
+
return;
|
|
852840
|
+
}
|
|
852841
|
+
ctx.print("Usage: /agent-profile template [show <id>|export <id> <path> --yes|import <path> --yes|from-discovered <id> --yes]");
|
|
852505
852842
|
return;
|
|
852506
852843
|
}
|
|
852507
852844
|
if (sub === "create") {
|
|
@@ -852522,6 +852859,38 @@ function registerAgentRuntimeProfileRuntimeCommands(registry5) {
|
|
|
852522
852859
|
profile5.starterTemplateId ? ` starter: ${profile5.starterTemplateId}` : "",
|
|
852523
852860
|
` launch: goodvibes-agent --agent-profile ${profile5.id}`
|
|
852524
852861
|
].filter(Boolean).join(`
|
|
852862
|
+
`));
|
|
852863
|
+
return;
|
|
852864
|
+
}
|
|
852865
|
+
if (sub === "create-from-discovered" || sub === "create-discovered") {
|
|
852866
|
+
const profileName = commandArgs[1];
|
|
852867
|
+
if (!profileName) {
|
|
852868
|
+
ctx.print("Usage: /agent-profile create-from-discovered <name> [--template-id <id>] [--profile-name <display>] [--description <summary>] [--persona <name>] [--skills all|name,name] [--routines all|name,name] [--replace] --yes");
|
|
852869
|
+
return;
|
|
852870
|
+
}
|
|
852871
|
+
if (!parsed.yes) {
|
|
852872
|
+
requireYesFlag(ctx, `create Agent profile ${profileName} from discovered behavior`, "/agent-profile create-from-discovered <name> --yes");
|
|
852873
|
+
return;
|
|
852874
|
+
}
|
|
852875
|
+
const created = await createAgentRuntimeProfileFromDiscovered(shellPaths, {
|
|
852876
|
+
profileName,
|
|
852877
|
+
templateId: parseFlag(commandArgs, "--template-id") ?? parseFlag(commandArgs, "--starter-id"),
|
|
852878
|
+
name: parseFlag(commandArgs, "--profile-name") ?? parseFlag(commandArgs, "--name"),
|
|
852879
|
+
description: parseFlag(commandArgs, "--description"),
|
|
852880
|
+
persona: parseFlag(commandArgs, "--persona"),
|
|
852881
|
+
skills: parseCsvFlag(commandArgs, "--skills"),
|
|
852882
|
+
routines: parseCsvFlag(commandArgs, "--routines"),
|
|
852883
|
+
replace: commandArgs.includes("--replace")
|
|
852884
|
+
});
|
|
852885
|
+
ctx.print([
|
|
852886
|
+
`Agent profile created from discovered behavior: ${created.profile.id}`,
|
|
852887
|
+
` home: ${created.profile.homeDirectory}`,
|
|
852888
|
+
` starter: ${created.template.id}`,
|
|
852889
|
+
` persona: ${created.template.personaName}`,
|
|
852890
|
+
` skills: ${created.template.skillNames.join(", ")}`,
|
|
852891
|
+
` routines: ${created.template.routineNames.join(", ")}`,
|
|
852892
|
+
` launch: goodvibes-agent --agent-profile ${created.profile.id}`
|
|
852893
|
+
].join(`
|
|
852525
852894
|
`));
|
|
852526
852895
|
return;
|
|
852527
852896
|
}
|
|
@@ -852538,7 +852907,7 @@ function registerAgentRuntimeProfileRuntimeCommands(registry5) {
|
|
|
852538
852907
|
ctx.print(deleteAgentRuntimeProfile(homeDirectory, name51) ? `Agent profile deleted: ${name51}` : `Agent profile not found: ${name51}`);
|
|
852539
852908
|
return;
|
|
852540
852909
|
}
|
|
852541
|
-
ctx.print("Usage: /agent-profile [list|templates|guide|template show <id>|template export <id> <path> --yes|template import <path> --yes|create <name> [--template <id>] --yes|delete <name> --yes]");
|
|
852910
|
+
ctx.print("Usage: /agent-profile [list|templates|guide|template show <id>|template export <id> <path> --yes|template import <path> --yes|create <name> [--template <id>] --yes|create-from-discovered <name> --yes|delete <name> --yes]");
|
|
852542
852911
|
} catch (error51) {
|
|
852543
852912
|
ctx.print(`Error: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
852544
852913
|
}
|
|
@@ -852737,6 +853106,84 @@ function renderPersona(persona, activePersonaId) {
|
|
|
852737
853106
|
].filter(Boolean).join(`
|
|
852738
853107
|
`);
|
|
852739
853108
|
}
|
|
853109
|
+
function summarizeDiscoveredPersona(persona) {
|
|
853110
|
+
const description = persona.description ? ` - ${persona.description}` : "";
|
|
853111
|
+
return ` ${persona.name} ${persona.origin}${description}
|
|
853112
|
+
path: ${persona.path}`;
|
|
853113
|
+
}
|
|
853114
|
+
function renderDiscoveredPersonas(personas) {
|
|
853115
|
+
if (personas.length === 0) {
|
|
853116
|
+
return [
|
|
853117
|
+
"Discovered Agent persona files",
|
|
853118
|
+
" No persona markdown files found in project/global Agent persona folders.",
|
|
853119
|
+
" Search roots: .goodvibes/personas, .goodvibes/agent/personas, .goodvibes/agents, ~/.goodvibes/personas, ~/.goodvibes/agent/personas, ~/.goodvibes/agents"
|
|
853120
|
+
].join(`
|
|
853121
|
+
`);
|
|
853122
|
+
}
|
|
853123
|
+
return [
|
|
853124
|
+
`Discovered Agent persona files (${personas.length})`,
|
|
853125
|
+
...personas.map(summarizeDiscoveredPersona),
|
|
853126
|
+
"",
|
|
853127
|
+
"Import one with: /personas import-discovered <name> --yes"
|
|
853128
|
+
].join(`
|
|
853129
|
+
`);
|
|
853130
|
+
}
|
|
853131
|
+
function discoveredPersonaLookupValues(persona) {
|
|
853132
|
+
const slug = persona.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
853133
|
+
const basename5 = persona.path.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
|
|
853134
|
+
return [persona.name, slug, persona.path, basename5].map((value) => value.trim().toLowerCase()).filter(Boolean);
|
|
853135
|
+
}
|
|
853136
|
+
function findDiscoveredPersona(personas, idOrName) {
|
|
853137
|
+
const lookup = idOrName.trim().toLowerCase();
|
|
853138
|
+
if (!lookup)
|
|
853139
|
+
return null;
|
|
853140
|
+
return personas.find((persona) => discoveredPersonaLookupValues(persona).includes(lookup)) ?? null;
|
|
853141
|
+
}
|
|
853142
|
+
function frontmatterList(persona, key) {
|
|
853143
|
+
const value = persona.frontmatter[key];
|
|
853144
|
+
if (!value)
|
|
853145
|
+
return [];
|
|
853146
|
+
return splitList(value);
|
|
853147
|
+
}
|
|
853148
|
+
async function importDiscoveredPersona(args2, ctx, personaRegistry) {
|
|
853149
|
+
const parsed = parsePersonaArgs(args2);
|
|
853150
|
+
const name51 = parsed.rest.join(" ").trim();
|
|
853151
|
+
if (!name51) {
|
|
853152
|
+
ctx.print("Usage: /personas import-discovered <name> [--use] --yes");
|
|
853153
|
+
return;
|
|
853154
|
+
}
|
|
853155
|
+
const discovered = findDiscoveredPersona(await discoverPersonas(requireShellPaths(ctx)), name51);
|
|
853156
|
+
if (!discovered) {
|
|
853157
|
+
ctx.print(`Unknown discovered Agent persona: ${name51}
|
|
853158
|
+
Run /personas discover to inspect available persona files.`);
|
|
853159
|
+
return;
|
|
853160
|
+
}
|
|
853161
|
+
if (!parsed.yes) {
|
|
853162
|
+
ctx.print([
|
|
853163
|
+
"Agent persona import preview",
|
|
853164
|
+
` name: ${discovered.name}`,
|
|
853165
|
+
` origin: ${discovered.origin}`,
|
|
853166
|
+
` path: ${discovered.path}`,
|
|
853167
|
+
` description: ${discovered.description || "(none)"}`,
|
|
853168
|
+
` body characters: ${discovered.body.length}`,
|
|
853169
|
+
" next: rerun with --yes to import into the Agent-local persona registry"
|
|
853170
|
+
].join(`
|
|
853171
|
+
`));
|
|
853172
|
+
return;
|
|
853173
|
+
}
|
|
853174
|
+
const persona = personaRegistry.create({
|
|
853175
|
+
name: discovered.name,
|
|
853176
|
+
description: discovered.description || `Imported persona from ${discovered.origin} markdown file.`,
|
|
853177
|
+
body: discovered.body,
|
|
853178
|
+
tags: frontmatterList(discovered, "tags"),
|
|
853179
|
+
triggers: frontmatterList(discovered, "triggers"),
|
|
853180
|
+
source: "imported",
|
|
853181
|
+
provenance: `discovered:${discovered.origin}:${discovered.path}`
|
|
853182
|
+
});
|
|
853183
|
+
if (parsed.flags.get("use") === "true")
|
|
853184
|
+
personaRegistry.setActive(persona.id);
|
|
853185
|
+
ctx.print(`Imported Agent persona ${persona.id}: ${persona.name}${parsed.flags.get("use") === "true" ? " (active)" : ""}`);
|
|
853186
|
+
}
|
|
852740
853187
|
function requiredFlag(flags2, key) {
|
|
852741
853188
|
const value = flags2.get(key)?.trim();
|
|
852742
853189
|
if (!value)
|
|
@@ -852751,7 +853198,7 @@ function registerPersonasRuntimeCommands(registry5) {
|
|
|
852751
853198
|
name: "personas",
|
|
852752
853199
|
aliases: ["persona"],
|
|
852753
853200
|
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]",
|
|
853201
|
+
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
853202
|
async handler(args2, ctx) {
|
|
852756
853203
|
const sub = (args2[0] ?? "list").toLowerCase();
|
|
852757
853204
|
const registryStore = registryFromContext(ctx);
|
|
@@ -852760,6 +853207,14 @@ function registerPersonasRuntimeCommands(registry5) {
|
|
|
852760
853207
|
ctx.print(renderList("Agent Personas", registryStore, registryStore.list()));
|
|
852761
853208
|
return;
|
|
852762
853209
|
}
|
|
853210
|
+
if (sub === "discover" || sub === "discovered") {
|
|
853211
|
+
ctx.print(renderDiscoveredPersonas(await discoverPersonas(requireShellPaths(ctx))));
|
|
853212
|
+
return;
|
|
853213
|
+
}
|
|
853214
|
+
if (sub === "import-discovered" || sub === "import-persona") {
|
|
853215
|
+
await importDiscoveredPersona(args2.slice(1), ctx, registryStore);
|
|
853216
|
+
return;
|
|
853217
|
+
}
|
|
852763
853218
|
if (sub === "search") {
|
|
852764
853219
|
const query2 = args2.slice(1).join(" ").trim();
|
|
852765
853220
|
ctx.print(renderList(query2 ? `Agent Personas matching "${query2}"` : "Agent Personas", registryStore, registryStore.search(query2)));
|
|
@@ -852864,7 +853319,7 @@ function registerPersonasRuntimeCommands(registry5) {
|
|
|
852864
853319
|
ctx.print(`Deleted Agent persona ${removed.id}: ${removed.name}`);
|
|
852865
853320
|
return;
|
|
852866
853321
|
}
|
|
852867
|
-
ctx.print("Usage: /personas [list|search <query>|show <id>|create|update|use|active|clear|review|stale|delete]");
|
|
853322
|
+
ctx.print("Usage: /personas [list|discover|import-discovered|search <query>|show <id>|create|update|use|active|clear|review|stale|delete]");
|
|
852868
853323
|
} catch (error51) {
|
|
852869
853324
|
printError2(ctx, error51);
|
|
852870
853325
|
}
|
|
@@ -852975,7 +853430,7 @@ function findDiscoveredSkill(skills, idOrName) {
|
|
|
852975
853430
|
return null;
|
|
852976
853431
|
return skills.find((skill) => discoveredSkillLookupValues(skill).includes(lookup)) ?? null;
|
|
852977
853432
|
}
|
|
852978
|
-
function
|
|
853433
|
+
function frontmatterList2(skill, key) {
|
|
852979
853434
|
const value = skill.frontmatter[key];
|
|
852980
853435
|
if (!value)
|
|
852981
853436
|
return [];
|
|
@@ -853011,8 +853466,8 @@ Run /agent-skills discover to inspect available skill files.`);
|
|
|
853011
853466
|
name: discovered.name,
|
|
853012
853467
|
description: discovered.description || `Imported skill from ${discovered.origin} skill file.`,
|
|
853013
853468
|
procedure: discovered.body,
|
|
853014
|
-
triggers:
|
|
853015
|
-
tags:
|
|
853469
|
+
triggers: frontmatterList2(discovered, "triggers"),
|
|
853470
|
+
tags: frontmatterList2(discovered, "tags"),
|
|
853016
853471
|
enabled: parsed.flags.get("enabled") === "true",
|
|
853017
853472
|
source: "imported",
|
|
853018
853473
|
provenance: `discovered:${discovered.origin}:${discovered.path}`
|
|
@@ -853400,9 +853855,86 @@ function renderRoutine(routine) {
|
|
|
853400
853855
|
].filter(Boolean).join(`
|
|
853401
853856
|
`);
|
|
853402
853857
|
}
|
|
853858
|
+
function summarizeDiscoveredRoutine(routine) {
|
|
853859
|
+
const description = routine.description ? ` - ${routine.description}` : "";
|
|
853860
|
+
return ` ${routine.name} ${routine.origin}${description}
|
|
853861
|
+
path: ${routine.path}`;
|
|
853862
|
+
}
|
|
853863
|
+
function renderDiscoveredRoutines(routines) {
|
|
853864
|
+
if (routines.length === 0) {
|
|
853865
|
+
return [
|
|
853866
|
+
"Discovered Agent routine files",
|
|
853867
|
+
" No routine markdown files found in project/global Agent routine folders.",
|
|
853868
|
+
" Search roots: .goodvibes/routines, .goodvibes/agent/routines, ~/.goodvibes/routines, ~/.goodvibes/agent/routines"
|
|
853869
|
+
].join(`
|
|
853870
|
+
`);
|
|
853871
|
+
}
|
|
853872
|
+
return [
|
|
853873
|
+
`Discovered Agent routine files (${routines.length})`,
|
|
853874
|
+
...routines.map(summarizeDiscoveredRoutine),
|
|
853875
|
+
"",
|
|
853876
|
+
"Import one with: /routines import-discovered <name> --yes"
|
|
853877
|
+
].join(`
|
|
853878
|
+
`);
|
|
853879
|
+
}
|
|
853880
|
+
function discoveredRoutineLookupValues(routine) {
|
|
853881
|
+
const slug = routine.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
853882
|
+
const basename5 = routine.path.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
|
|
853883
|
+
return [routine.name, slug, routine.path, basename5].map((value) => value.trim().toLowerCase()).filter(Boolean);
|
|
853884
|
+
}
|
|
853885
|
+
function findDiscoveredRoutine(routines, idOrName) {
|
|
853886
|
+
const lookup = idOrName.trim().toLowerCase();
|
|
853887
|
+
if (!lookup)
|
|
853888
|
+
return null;
|
|
853889
|
+
return routines.find((routine) => discoveredRoutineLookupValues(routine).includes(lookup)) ?? null;
|
|
853890
|
+
}
|
|
853891
|
+
function frontmatterList3(routine, key) {
|
|
853892
|
+
const value = routine.frontmatter[key];
|
|
853893
|
+
if (!value)
|
|
853894
|
+
return [];
|
|
853895
|
+
return splitList3(value);
|
|
853896
|
+
}
|
|
853403
853897
|
function printError4(ctx, error51) {
|
|
853404
853898
|
ctx.print(`Error: ${error51 instanceof Error ? error51.message : String(error51)}`);
|
|
853405
853899
|
}
|
|
853900
|
+
async function importDiscoveredRoutine(args2, ctx, routineRegistry) {
|
|
853901
|
+
const parsed = parseRoutineArgs(args2);
|
|
853902
|
+
const name51 = parsed.rest.join(" ").trim();
|
|
853903
|
+
if (!name51) {
|
|
853904
|
+
ctx.print("Usage: /routines import-discovered <name> [--enabled] --yes");
|
|
853905
|
+
return;
|
|
853906
|
+
}
|
|
853907
|
+
const discovered = findDiscoveredRoutine(await discoverRoutines(requireShellPaths(ctx)), name51);
|
|
853908
|
+
if (!discovered) {
|
|
853909
|
+
ctx.print(`Unknown discovered Agent routine: ${name51}
|
|
853910
|
+
Run /routines discover to inspect available routine files.`);
|
|
853911
|
+
return;
|
|
853912
|
+
}
|
|
853913
|
+
if (!parsed.yes) {
|
|
853914
|
+
ctx.print([
|
|
853915
|
+
"Agent routine import preview",
|
|
853916
|
+
` name: ${discovered.name}`,
|
|
853917
|
+
` origin: ${discovered.origin}`,
|
|
853918
|
+
` path: ${discovered.path}`,
|
|
853919
|
+
` description: ${discovered.description || "(none)"}`,
|
|
853920
|
+
` steps characters: ${discovered.steps.length}`,
|
|
853921
|
+
" next: rerun with --yes to import into the Agent-local routine registry"
|
|
853922
|
+
].join(`
|
|
853923
|
+
`));
|
|
853924
|
+
return;
|
|
853925
|
+
}
|
|
853926
|
+
const routine = routineRegistry.create({
|
|
853927
|
+
name: discovered.name,
|
|
853928
|
+
description: discovered.description || `Imported routine from ${discovered.origin} markdown file.`,
|
|
853929
|
+
steps: discovered.steps,
|
|
853930
|
+
tags: frontmatterList3(discovered, "tags"),
|
|
853931
|
+
triggers: frontmatterList3(discovered, "triggers"),
|
|
853932
|
+
enabled: parsed.flags.get("enabled") === "true",
|
|
853933
|
+
source: "imported",
|
|
853934
|
+
provenance: `discovered:${discovered.origin}:${discovered.path}`
|
|
853935
|
+
});
|
|
853936
|
+
ctx.print(`Imported Agent routine ${routine.id}: ${routine.name}${routine.enabled ? " (enabled)" : ""}`);
|
|
853937
|
+
}
|
|
853406
853938
|
async function promoteRoutine(args2, routineRegistry, ctx) {
|
|
853407
853939
|
const parsed = parseRoutineSchedulePromotionArgs(args2);
|
|
853408
853940
|
if (parsed.errors.length > 0) {
|
|
@@ -853444,6 +853976,14 @@ async function runRoutinesRuntimeCommand(args2, ctx) {
|
|
|
853444
853976
|
ctx.print(renderList3("Enabled Agent Routines", routineRegistry, snapshot.enabledRoutines));
|
|
853445
853977
|
return;
|
|
853446
853978
|
}
|
|
853979
|
+
if (sub === "discover" || sub === "discovered") {
|
|
853980
|
+
ctx.print(renderDiscoveredRoutines(await discoverRoutines(requireShellPaths(ctx))));
|
|
853981
|
+
return;
|
|
853982
|
+
}
|
|
853983
|
+
if (sub === "import-discovered" || sub === "import-routine") {
|
|
853984
|
+
await importDiscoveredRoutine(args2.slice(1), ctx, routineRegistry);
|
|
853985
|
+
return;
|
|
853986
|
+
}
|
|
853447
853987
|
if (sub === "search") {
|
|
853448
853988
|
const query2 = args2.slice(1).join(" ").trim();
|
|
853449
853989
|
ctx.print(renderList3(query2 ? `Agent Routines matching "${query2}"` : "Agent Routines", routineRegistry, routineRegistry.search(query2)));
|
|
@@ -853579,7 +854119,7 @@ async function runRoutinesRuntimeCommand(args2, ctx) {
|
|
|
853579
854119
|
ctx.print(`Deleted Agent routine ${removed.id}: ${removed.name}`);
|
|
853580
854120
|
return;
|
|
853581
854121
|
}
|
|
853582
|
-
ctx.print("Usage: /routines [list|enabled|search|show|receipts|reconcile|receipt|create|update|enable|disable|start|review|stale|promote|delete]");
|
|
854122
|
+
ctx.print("Usage: /routines [list|enabled|discover|import-discovered|search|show|receipts|reconcile|receipt|create|update|enable|disable|start|review|stale|promote|delete]");
|
|
853583
854123
|
} catch (error51) {
|
|
853584
854124
|
printError4(ctx, error51);
|
|
853585
854125
|
}
|
|
@@ -853589,14 +854129,14 @@ function registerRoutinesRuntimeCommands(registry5) {
|
|
|
853589
854129
|
name: "routines",
|
|
853590
854130
|
aliases: ["routine"],
|
|
853591
854131
|
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]",
|
|
854132
|
+
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
854133
|
handler: runRoutinesRuntimeCommand
|
|
853594
854134
|
});
|
|
853595
854135
|
}
|
|
853596
854136
|
|
|
853597
854137
|
// src/input/commands/channels-runtime.ts
|
|
853598
854138
|
import { existsSync as existsSync72, readFileSync as readFileSync79 } from "fs";
|
|
853599
|
-
import { join as
|
|
854139
|
+
import { join as join89 } from "path";
|
|
853600
854140
|
|
|
853601
854141
|
// src/input/agent-workspace-channels.ts
|
|
853602
854142
|
var AGENT_WORKSPACE_CHANNEL_SPECS = [
|
|
@@ -853807,7 +854347,7 @@ function resolveChannelDaemonConnection(context) {
|
|
|
853807
854347
|
const host = typeof hostValue === "string" && hostValue.trim().length > 0 ? hostValue.trim() : "127.0.0.1";
|
|
853808
854348
|
const port = typeof portValue === "number" && Number.isFinite(portValue) ? portValue : 3421;
|
|
853809
854349
|
const homeDirectory = context.workspace?.shellPaths?.homeDirectory ?? process.env.HOME ?? "";
|
|
853810
|
-
const tokenPath =
|
|
854350
|
+
const tokenPath = join89(homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
|
|
853811
854351
|
if (!existsSync72(tokenPath))
|
|
853812
854352
|
return { baseUrl: `http://${host}:${port}`, token: null, tokenPath };
|
|
853813
854353
|
try {
|
|
@@ -854132,6 +854672,143 @@ Use /channels list to see available channel ids.`);
|
|
|
854132
854672
|
// src/input/agent-workspace-snapshot.ts
|
|
854133
854673
|
import { basename as basename5, sep as sep3 } from "path";
|
|
854134
854674
|
|
|
854675
|
+
// src/agent/behavior-discovery-summary.ts
|
|
854676
|
+
import { readdirSync as readdirSync21, readFileSync as readFileSync80 } from "fs";
|
|
854677
|
+
import { join as join90 } from "path";
|
|
854678
|
+
var EMPTY_SUMMARY = {
|
|
854679
|
+
count: 0,
|
|
854680
|
+
projectLocalCount: 0,
|
|
854681
|
+
globalCount: 0,
|
|
854682
|
+
names: []
|
|
854683
|
+
};
|
|
854684
|
+
var EMPTY_AGENT_BEHAVIOR_DISCOVERY_SNAPSHOT = {
|
|
854685
|
+
personas: EMPTY_SUMMARY,
|
|
854686
|
+
skills: EMPTY_SUMMARY,
|
|
854687
|
+
routines: EMPTY_SUMMARY
|
|
854688
|
+
};
|
|
854689
|
+
function parseFrontmatter4(content) {
|
|
854690
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
854691
|
+
if (!match)
|
|
854692
|
+
return {};
|
|
854693
|
+
const result2 = {};
|
|
854694
|
+
for (const line of match[1].split(`
|
|
854695
|
+
`)) {
|
|
854696
|
+
const [key, ...rest] = line.split(":");
|
|
854697
|
+
if (key && rest.length > 0) {
|
|
854698
|
+
result2[key.trim()] = rest.join(":").trim();
|
|
854699
|
+
}
|
|
854700
|
+
}
|
|
854701
|
+
return result2;
|
|
854702
|
+
}
|
|
854703
|
+
function markdownBody(content) {
|
|
854704
|
+
return content.replace(/^---\n[\s\S]*?\n---\n?/, "").trim();
|
|
854705
|
+
}
|
|
854706
|
+
function readDiscoveryCandidate(path7, origin, definition) {
|
|
854707
|
+
let content = "";
|
|
854708
|
+
try {
|
|
854709
|
+
content = readFileSync80(path7, "utf-8");
|
|
854710
|
+
} catch {
|
|
854711
|
+
return null;
|
|
854712
|
+
}
|
|
854713
|
+
const frontmatter = parseFrontmatter4(content);
|
|
854714
|
+
const body2 = definition.frontmatterBodyKey ? (frontmatter[definition.frontmatterBodyKey] ?? markdownBody(content)).trim() : markdownBody(content);
|
|
854715
|
+
if (body2.length === 0)
|
|
854716
|
+
return null;
|
|
854717
|
+
const name51 = frontmatter.name ?? path7.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
|
|
854718
|
+
const normalized = name51.trim();
|
|
854719
|
+
return normalized ? { name: normalized, origin } : null;
|
|
854720
|
+
}
|
|
854721
|
+
function candidatePaths(root, entry, markers) {
|
|
854722
|
+
if (entry.endsWith(".md"))
|
|
854723
|
+
return [join90(root, entry)];
|
|
854724
|
+
return markers.map((marker) => join90(root, entry, marker));
|
|
854725
|
+
}
|
|
854726
|
+
function summarizeDefinition(definition, limit3) {
|
|
854727
|
+
const seen = new Set;
|
|
854728
|
+
const names2 = [];
|
|
854729
|
+
let projectLocalCount = 0;
|
|
854730
|
+
let globalCount = 0;
|
|
854731
|
+
for (const { root, origin } of definition.roots) {
|
|
854732
|
+
let entries = [];
|
|
854733
|
+
try {
|
|
854734
|
+
entries = readdirSync21(root);
|
|
854735
|
+
} catch {
|
|
854736
|
+
continue;
|
|
854737
|
+
}
|
|
854738
|
+
for (const entry of entries.sort((left, right) => left.localeCompare(right))) {
|
|
854739
|
+
for (const path7 of candidatePaths(root, entry, definition.markers)) {
|
|
854740
|
+
const candidate = readDiscoveryCandidate(path7, origin, definition);
|
|
854741
|
+
if (!candidate)
|
|
854742
|
+
continue;
|
|
854743
|
+
const key = candidate.name.toLowerCase();
|
|
854744
|
+
if (seen.has(key))
|
|
854745
|
+
break;
|
|
854746
|
+
seen.add(key);
|
|
854747
|
+
if (candidate.origin === "project-local")
|
|
854748
|
+
projectLocalCount += 1;
|
|
854749
|
+
else
|
|
854750
|
+
globalCount += 1;
|
|
854751
|
+
if (names2.length < limit3)
|
|
854752
|
+
names2.push(candidate.name);
|
|
854753
|
+
break;
|
|
854754
|
+
}
|
|
854755
|
+
}
|
|
854756
|
+
}
|
|
854757
|
+
if (seen.size === 0)
|
|
854758
|
+
return EMPTY_SUMMARY;
|
|
854759
|
+
return {
|
|
854760
|
+
count: seen.size,
|
|
854761
|
+
projectLocalCount,
|
|
854762
|
+
globalCount,
|
|
854763
|
+
names: names2
|
|
854764
|
+
};
|
|
854765
|
+
}
|
|
854766
|
+
function definitions(shellPaths) {
|
|
854767
|
+
const cwd = shellPaths.workingDirectory;
|
|
854768
|
+
const homeDir = shellPaths.homeDirectory;
|
|
854769
|
+
const personas = {
|
|
854770
|
+
roots: [
|
|
854771
|
+
{ root: join90(cwd, ".goodvibes", "personas"), origin: "project-local" },
|
|
854772
|
+
{ root: join90(cwd, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "personas"), origin: "project-local" },
|
|
854773
|
+
{ root: join90(cwd, ".goodvibes", "agents"), origin: "project-local" },
|
|
854774
|
+
{ root: join90(homeDir, ".goodvibes", "personas"), origin: "global" },
|
|
854775
|
+
{ root: join90(homeDir, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "personas"), origin: "global" },
|
|
854776
|
+
{ root: join90(homeDir, ".goodvibes", "agents"), origin: "global" }
|
|
854777
|
+
],
|
|
854778
|
+
markers: ["PERSONA.md", "persona.md", "AGENT.md", "agent.md"],
|
|
854779
|
+
frontmatterBodyKey: "system_prompt"
|
|
854780
|
+
};
|
|
854781
|
+
const skills = {
|
|
854782
|
+
roots: [
|
|
854783
|
+
{ root: join90(cwd, ".goodvibes", "skills"), origin: "project-local" },
|
|
854784
|
+
{ root: join90(cwd, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "skills"), origin: "project-local" },
|
|
854785
|
+
{ root: join90(homeDir, ".goodvibes", "skills"), origin: "global" },
|
|
854786
|
+
{ root: join90(homeDir, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "skills"), origin: "global" }
|
|
854787
|
+
],
|
|
854788
|
+
markers: ["SKILL.md"]
|
|
854789
|
+
};
|
|
854790
|
+
const routines = {
|
|
854791
|
+
roots: [
|
|
854792
|
+
{ root: join90(cwd, ".goodvibes", "routines"), origin: "project-local" },
|
|
854793
|
+
{ root: join90(cwd, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "routines"), origin: "project-local" },
|
|
854794
|
+
{ root: join90(homeDir, ".goodvibes", "routines"), origin: "global" },
|
|
854795
|
+
{ root: join90(homeDir, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "routines"), origin: "global" }
|
|
854796
|
+
],
|
|
854797
|
+
markers: ["ROUTINE.md", "routine.md"],
|
|
854798
|
+
frontmatterBodyKey: "steps"
|
|
854799
|
+
};
|
|
854800
|
+
return {
|
|
854801
|
+
personas: summarizeDefinition(personas, 4),
|
|
854802
|
+
skills: summarizeDefinition(skills, 4),
|
|
854803
|
+
routines: summarizeDefinition(routines, 4)
|
|
854804
|
+
};
|
|
854805
|
+
}
|
|
854806
|
+
function summarizeAgentBehaviorDiscovery(shellPaths) {
|
|
854807
|
+
if (!shellPaths)
|
|
854808
|
+
return EMPTY_AGENT_BEHAVIOR_DISCOVERY_SNAPSHOT;
|
|
854809
|
+
return definitions(shellPaths);
|
|
854810
|
+
}
|
|
854811
|
+
|
|
854135
854812
|
// src/agent/memory-prompt.ts
|
|
854136
854813
|
var DEFAULT_LIMIT = 10;
|
|
854137
854814
|
var MIN_PROMPT_MEMORY_CONFIDENCE = 50;
|
|
@@ -854164,9 +854841,16 @@ function buildReviewedMemoryPrompt(memoryRegistry, limit3 = DEFAULT_LIMIT) {
|
|
|
854164
854841
|
function setupStatusForCount(count, ready, empty) {
|
|
854165
854842
|
return count > 0 ? ready : empty;
|
|
854166
854843
|
}
|
|
854844
|
+
function sampleNames(summary) {
|
|
854845
|
+
if (summary.names.length === 0)
|
|
854846
|
+
return "";
|
|
854847
|
+
const suffix = summary.count > summary.names.length ? `, +${summary.count - summary.names.length} more` : "";
|
|
854848
|
+
return ` Found: ${summary.names.join(", ")}${suffix}.`;
|
|
854849
|
+
}
|
|
854167
854850
|
function buildAgentWorkspaceSetupChecklist(input) {
|
|
854168
854851
|
const providerReady = input.provider !== "unknown" && input.model !== "unknown";
|
|
854169
854852
|
const hasActivePersona = input.activePersonaName !== "(none)" && input.activePersonaName !== "(unavailable)";
|
|
854853
|
+
const discoveredBehaviorCount = input.discoveredPersonas.count + input.discoveredSkills.count + input.discoveredRoutines.count;
|
|
854170
854854
|
return [
|
|
854171
854855
|
{
|
|
854172
854856
|
id: "runtime",
|
|
@@ -854192,30 +854876,30 @@ function buildAgentWorkspaceSetupChecklist(input) {
|
|
|
854192
854876
|
{
|
|
854193
854877
|
id: "profile",
|
|
854194
854878
|
label: "Agent profile",
|
|
854195
|
-
status:
|
|
854196
|
-
detail: input.runtimeProfileCount > 0 ? `${input.runtimeProfileCount} isolated Agent profile(s) are available.` : `${input.runtimeStarterTemplateCount} starter template(s) are available if this machine needs separate operator identities.`,
|
|
854197
|
-
command: "/agent-profile templates"
|
|
854879
|
+
status: input.runtimeProfileCount > 0 ? "ready" : discoveredBehaviorCount > 0 ? "recommended" : "optional",
|
|
854880
|
+
detail: input.runtimeProfileCount > 0 ? `${input.runtimeProfileCount} isolated Agent profile(s) are available.` : discoveredBehaviorCount > 0 ? `${discoveredBehaviorCount} discovered behavior file(s) can seed an isolated Agent profile from the Profiles workspace.` : `${input.runtimeStarterTemplateCount} starter template(s) are available if this machine needs separate operator identities.`,
|
|
854881
|
+
command: discoveredBehaviorCount > 0 && input.runtimeProfileCount === 0 ? "/agent-profile guide" : "/agent-profile templates"
|
|
854198
854882
|
},
|
|
854199
854883
|
{
|
|
854200
854884
|
id: "persona",
|
|
854201
854885
|
label: "Persona",
|
|
854202
854886
|
status: hasActivePersona ? "ready" : "recommended",
|
|
854203
|
-
detail: hasActivePersona ? `Active persona: ${input.activePersonaName}.` : "Create or choose a persona to make the assistant voice and policy explicit.",
|
|
854204
|
-
command: "/personas"
|
|
854887
|
+
detail: hasActivePersona ? `Active persona: ${input.activePersonaName}.${input.discoveredPersonas.count > 0 ? ` ${input.discoveredPersonas.count} discovered persona file(s) are still available to import.` : ""}` : input.discoveredPersonas.count > 0 ? `${input.discoveredPersonas.count} discovered persona file(s) can be imported into the Agent-local registry.${sampleNames(input.discoveredPersonas)}` : "Create or choose a persona to make the assistant voice and policy explicit.",
|
|
854888
|
+
command: input.discoveredPersonas.count > 0 ? "/personas discover" : "/personas"
|
|
854205
854889
|
},
|
|
854206
854890
|
{
|
|
854207
854891
|
id: "skills",
|
|
854208
854892
|
label: "Skills",
|
|
854209
|
-
status: input.enabledSkillCount > 0 || input.enabledSkillBundleCount > 0 ? "ready" : input.skillCount > 0 || input.skillBundleCount > 0 ? "recommended" : "optional",
|
|
854210
|
-
detail: input.skillCount > 0 || input.skillBundleCount > 0 ? `${input.enabledSkillCount}/${input.skillCount} local skill(s) enabled; ${input.enabledSkillBundleCount}/${input.skillBundleCount} bundle(s) enabled.` : "Create reusable local skills and bundles for repeated workflows.",
|
|
854211
|
-
command: "/agent-skills"
|
|
854893
|
+
status: input.enabledSkillCount > 0 || input.enabledSkillBundleCount > 0 ? "ready" : input.skillCount > 0 || input.skillBundleCount > 0 || input.discoveredSkills.count > 0 ? "recommended" : "optional",
|
|
854894
|
+
detail: input.skillCount > 0 || input.skillBundleCount > 0 ? `${input.enabledSkillCount}/${input.skillCount} local skill(s) enabled; ${input.enabledSkillBundleCount}/${input.skillBundleCount} bundle(s) enabled.${input.discoveredSkills.count > 0 ? ` ${input.discoveredSkills.count} discovered skill file(s) are still available to import.` : ""}` : input.discoveredSkills.count > 0 ? `${input.discoveredSkills.count} discovered skill file(s) can be imported as local reusable procedures.${sampleNames(input.discoveredSkills)}` : "Create reusable local skills and bundles for repeated workflows.",
|
|
854895
|
+
command: input.discoveredSkills.count > 0 ? "/agent-skills discover" : "/agent-skills"
|
|
854212
854896
|
},
|
|
854213
854897
|
{
|
|
854214
854898
|
id: "routines",
|
|
854215
854899
|
label: "Routines",
|
|
854216
|
-
status: setupStatusForCount(input.enabledRoutineCount, "ready", input.routineCount > 0 ? "recommended" : "optional"),
|
|
854217
|
-
detail: input.routineCount > 0 ? `${input.enabledRoutineCount}/${input.routineCount} local routine(s) enabled.` : "Create local routines first; promote schedules only with explicit confirmation.",
|
|
854218
|
-
command: "/routines"
|
|
854900
|
+
status: setupStatusForCount(input.enabledRoutineCount, "ready", input.routineCount > 0 || input.discoveredRoutines.count > 0 ? "recommended" : "optional"),
|
|
854901
|
+
detail: input.routineCount > 0 ? `${input.enabledRoutineCount}/${input.routineCount} local routine(s) enabled.${input.discoveredRoutines.count > 0 ? ` ${input.discoveredRoutines.count} discovered routine file(s) are still available to import.` : ""}` : input.discoveredRoutines.count > 0 ? `${input.discoveredRoutines.count} discovered routine file(s) can be imported as main-conversation workflows.${sampleNames(input.discoveredRoutines)}` : "Create local routines first; promote schedules only with explicit confirmation.",
|
|
854902
|
+
command: input.discoveredRoutines.count > 0 ? "/routines discover" : "/routines"
|
|
854219
854903
|
},
|
|
854220
854904
|
{
|
|
854221
854905
|
id: "memory",
|
|
@@ -854592,6 +855276,7 @@ function buildAgentWorkspaceRuntimeSnapshot(context) {
|
|
|
854592
855276
|
return { count: 0, enabled: 0, items: [] };
|
|
854593
855277
|
}
|
|
854594
855278
|
})();
|
|
855279
|
+
const discoveredBehavior = summarizeAgentBehaviorDiscovery(context.workspace?.shellPaths);
|
|
854595
855280
|
const runtimeProfiles = (() => {
|
|
854596
855281
|
try {
|
|
854597
855282
|
return listAgentRuntimeProfiles(context.workspace?.shellPaths?.homeDirectory ?? "");
|
|
@@ -854678,6 +855363,9 @@ function buildAgentWorkspaceRuntimeSnapshot(context) {
|
|
|
854678
855363
|
skillBundleCount: skillSnapshot.bundleCount,
|
|
854679
855364
|
enabledSkillBundleCount: skillSnapshot.enabledBundleCount,
|
|
854680
855365
|
activePersonaName: personaSnapshot.activeName,
|
|
855366
|
+
discoveredPersonas: discoveredBehavior.personas,
|
|
855367
|
+
discoveredSkills: discoveredBehavior.skills,
|
|
855368
|
+
discoveredRoutines: discoveredBehavior.routines,
|
|
854681
855369
|
readyChannelCount: channels.filter((channel) => channel.ready).length,
|
|
854682
855370
|
voiceProviderCount: voiceProviders.length,
|
|
854683
855371
|
mediaProviderCount: mediaProviders.length,
|
|
@@ -854711,6 +855399,7 @@ function buildAgentWorkspaceRuntimeSnapshot(context) {
|
|
|
854711
855399
|
localPersonaCount: personaSnapshot.count,
|
|
854712
855400
|
activePersonaName: personaSnapshot.activeName,
|
|
854713
855401
|
localPersonas: personaSnapshot.items,
|
|
855402
|
+
discoveredBehavior,
|
|
854714
855403
|
knowledgeRoute: "/api/goodvibes-agent/knowledge",
|
|
854715
855404
|
knowledgeIsolation: "agent-only",
|
|
854716
855405
|
executionPolicy: "serial-proactive",
|
|
@@ -854902,8 +855591,8 @@ function registerBuiltinCommands(registry5) {
|
|
|
854902
855591
|
}
|
|
854903
855592
|
|
|
854904
855593
|
// src/input/input-history.ts
|
|
854905
|
-
import { existsSync as existsSync73, mkdirSync as mkdirSync61, readFileSync as
|
|
854906
|
-
import { dirname as dirname59, join as
|
|
855594
|
+
import { existsSync as existsSync73, mkdirSync as mkdirSync61, readFileSync as readFileSync81, writeFileSync as writeFileSync52 } from "fs";
|
|
855595
|
+
import { dirname as dirname59, join as join91 } from "path";
|
|
854907
855596
|
class HistorySearch {
|
|
854908
855597
|
getEntries;
|
|
854909
855598
|
active = false;
|
|
@@ -854982,7 +855671,7 @@ function resolveHistoryPath2(options) {
|
|
|
854982
855671
|
if (!userRoot) {
|
|
854983
855672
|
throw new Error("InputHistory requires historyPath or an explicit userRoot/homeDirectory.");
|
|
854984
855673
|
}
|
|
854985
|
-
return
|
|
855674
|
+
return join91(userRoot, ".goodvibes", GOODVIBES_AGENT_SURFACE_ROOT, "input-history.json");
|
|
854986
855675
|
}
|
|
854987
855676
|
|
|
854988
855677
|
class InputHistory {
|
|
@@ -855063,7 +855752,7 @@ class InputHistory {
|
|
|
855063
855752
|
load() {
|
|
855064
855753
|
try {
|
|
855065
855754
|
if (existsSync73(this.historyPath)) {
|
|
855066
|
-
const raw =
|
|
855755
|
+
const raw = readFileSync81(this.historyPath, "utf-8");
|
|
855067
855756
|
const parsed = JSON.parse(raw);
|
|
855068
855757
|
if (Array.isArray(parsed)) {
|
|
855069
855758
|
this.entries = parsed.map((entry) => this.normalizeStoredEntry(entry)).filter((entry) => entry !== null).slice(0, this.maxEntries);
|
|
@@ -860836,7 +861525,7 @@ function registerAgentPanels(manager5, deps) {
|
|
|
860836
861525
|
|
|
860837
861526
|
// src/panels/builtin/session.ts
|
|
860838
861527
|
import { networkInterfaces as networkInterfaces3 } from "os";
|
|
860839
|
-
import { readFileSync as
|
|
861528
|
+
import { readFileSync as readFileSync82 } from "fs";
|
|
860840
861529
|
|
|
860841
861530
|
// src/panels/confirm-state.ts
|
|
860842
861531
|
function handleConfirmInput(confirm, key) {
|
|
@@ -862412,7 +863101,7 @@ function getLocalNetworkIp2() {
|
|
|
862412
863101
|
}
|
|
862413
863102
|
function readBootstrapPassword(credentialPath) {
|
|
862414
863103
|
try {
|
|
862415
|
-
const content =
|
|
863104
|
+
const content = readFileSync82(credentialPath, "utf-8");
|
|
862416
863105
|
for (const line2 of content.split(`
|
|
862417
863106
|
`)) {
|
|
862418
863107
|
if (line2.startsWith("password=")) {
|
|
@@ -863784,7 +864473,7 @@ function createBootstrapShell(options) {
|
|
|
863784
864473
|
hookActivityTracker: services.hookActivityTracker,
|
|
863785
864474
|
hookWorkbench: services.hookWorkbench,
|
|
863786
864475
|
mcpRegistry: services.mcpRegistry,
|
|
863787
|
-
daemonHomeDir:
|
|
864476
|
+
daemonHomeDir: join92(services.homeDirectory, ".goodvibes", "daemon")
|
|
863788
864477
|
});
|
|
863789
864478
|
services.panelManager.prewarmRegistered();
|
|
863790
864479
|
const systemMessageRouter = createSystemMessageRouter(conversation, systemMessagesPanel, (kind2) => {
|
|
@@ -865730,7 +866419,7 @@ var verifyBundle2 = exports_security2.verifyBundle;
|
|
|
865730
866419
|
var MAX_INPUT_LENGTH2 = exports_security2.MAX_INPUT_LENGTH;
|
|
865731
866420
|
var MAX_TOKEN_COUNT2 = exports_security2.MAX_TOKEN_COUNT;
|
|
865732
866421
|
// src/runtime/onboarding/state.ts
|
|
865733
|
-
import { existsSync as existsSync74, mkdirSync as mkdirSync62, readFileSync as
|
|
866422
|
+
import { existsSync as existsSync74, mkdirSync as mkdirSync62, readFileSync as readFileSync83, writeFileSync as writeFileSync53 } from "fs";
|
|
865734
866423
|
import { dirname as dirname60 } from "path";
|
|
865735
866424
|
var ONBOARDING_RUNTIME_STATE_FILE = "onboarding-state.json";
|
|
865736
866425
|
function resolveStatePath(shellPaths, scope) {
|
|
@@ -865776,7 +866465,7 @@ function readOnboardingRuntimeState(shellPaths, scope = "project") {
|
|
|
865776
866465
|
};
|
|
865777
866466
|
}
|
|
865778
866467
|
try {
|
|
865779
|
-
const parsed = JSON.parse(
|
|
866468
|
+
const parsed = JSON.parse(readFileSync83(path7, "utf-8"));
|
|
865780
866469
|
if (!isRuntimeStatePayload(parsed)) {
|
|
865781
866470
|
return {
|
|
865782
866471
|
scope,
|
|
@@ -866136,6 +866825,7 @@ async function collectOnboardingSnapshot(deps) {
|
|
|
866136
866825
|
records: sortSurfaceRecords(surfaceResult.value)
|
|
866137
866826
|
},
|
|
866138
866827
|
providerAccounts: providerAccountsResult.value,
|
|
866828
|
+
localBehaviorDiscovery: summarizeAgentBehaviorDiscovery(deps.shellPaths),
|
|
866139
866829
|
collectionIssues
|
|
866140
866830
|
};
|
|
866141
866831
|
}
|
|
@@ -866193,13 +866883,13 @@ var INBOUND_EVENT_SURFACE_KINDS = new Set([
|
|
|
866193
866883
|
]);
|
|
866194
866884
|
// src/runtime/onboarding/apply.ts
|
|
866195
866885
|
init_config8();
|
|
866196
|
-
import { existsSync as existsSync76, mkdirSync as mkdirSync63, readFileSync as
|
|
866886
|
+
import { existsSync as existsSync76, mkdirSync as mkdirSync63, readFileSync as readFileSync84, rmSync as rmSync10, unlinkSync as unlinkSync12, writeFileSync as writeFileSync54 } from "fs";
|
|
866197
866887
|
import { dirname as dirname61 } from "path";
|
|
866198
866888
|
|
|
866199
866889
|
// src/runtime/onboarding/verify.ts
|
|
866200
866890
|
init_config8();
|
|
866201
866891
|
import { existsSync as existsSync75 } from "fs";
|
|
866202
|
-
import { join as
|
|
866892
|
+
import { join as join93 } from "path";
|
|
866203
866893
|
function getNow(deps) {
|
|
866204
866894
|
return deps.clock?.() ?? Date.now();
|
|
866205
866895
|
}
|
|
@@ -866280,7 +866970,7 @@ function verifyAuthOperation(_deps, operation) {
|
|
|
866280
866970
|
}
|
|
866281
866971
|
function verifyCreateAgentProfileOperation(deps, operation) {
|
|
866282
866972
|
const resolution2 = resolveAgentRuntimeProfileHome(deps.shellPaths.homeDirectory, operation.name);
|
|
866283
|
-
const ok3 = existsSync75(
|
|
866973
|
+
const ok3 = existsSync75(join93(resolution2.homeDirectory, "profile.json"));
|
|
866284
866974
|
return {
|
|
866285
866975
|
id: `agent-profile:${resolution2.id}`,
|
|
866286
866976
|
status: ok3 ? "pass" : "fail",
|
|
@@ -866318,7 +867008,7 @@ function isPlainObject3(value) {
|
|
|
866318
867008
|
function readJsonObject(path7) {
|
|
866319
867009
|
if (!existsSync76(path7))
|
|
866320
867010
|
return {};
|
|
866321
|
-
const parsed = JSON.parse(
|
|
867011
|
+
const parsed = JSON.parse(readFileSync84(path7, "utf-8"));
|
|
866322
867012
|
if (!isPlainObject3(parsed))
|
|
866323
867013
|
throw new Error(`Expected an object JSON payload at ${path7}.`);
|
|
866324
867014
|
return parsed;
|
|
@@ -866353,7 +867043,7 @@ function restoreFile(path7, previous, reload) {
|
|
|
866353
867043
|
reload?.();
|
|
866354
867044
|
}
|
|
866355
867045
|
function snapshotFileRollback(path7, reload) {
|
|
866356
|
-
const previous = existsSync76(path7) ?
|
|
867046
|
+
const previous = existsSync76(path7) ? readFileSync84(path7, "utf-8") : null;
|
|
866357
867047
|
return () => restoreFile(path7, previous, reload);
|
|
866358
867048
|
}
|
|
866359
867049
|
async function runRollbacks(rollbacks) {
|
|
@@ -866516,7 +867206,7 @@ async function buildSecretRollbackAction(deps, operation) {
|
|
|
866516
867206
|
throw new Error(`Secret storage locations for ${scope} scope are unavailable.`);
|
|
866517
867207
|
const snapshots = locations.map((location) => ({
|
|
866518
867208
|
path: location.path,
|
|
866519
|
-
previous: existsSync76(location.path) ?
|
|
867209
|
+
previous: existsSync76(location.path) ? readFileSync84(location.path, "utf-8") : null
|
|
866520
867210
|
}));
|
|
866521
867211
|
return () => {
|
|
866522
867212
|
for (const snapshot of snapshots)
|
|
@@ -866736,7 +867426,7 @@ async function applyOnboardingRequest(deps, request2) {
|
|
|
866736
867426
|
};
|
|
866737
867427
|
}
|
|
866738
867428
|
// src/runtime/onboarding/markers.ts
|
|
866739
|
-
import { existsSync as existsSync77, mkdirSync as mkdirSync64, readFileSync as
|
|
867429
|
+
import { existsSync as existsSync77, mkdirSync as mkdirSync64, readFileSync as readFileSync85, writeFileSync as writeFileSync55 } from "fs";
|
|
866740
867430
|
import { dirname as dirname62 } from "path";
|
|
866741
867431
|
var ONBOARDING_CHECK_MARKER_FILE = "onboarding-checked.json";
|
|
866742
867432
|
function resolveMarkerPath(shellPaths, scope) {
|
|
@@ -866783,7 +867473,7 @@ function readOnboardingCheckMarker(shellPaths, scope = "user") {
|
|
|
866783
867473
|
if (!existsSync77(path7))
|
|
866784
867474
|
return buildMissingMarkerState(scope, path7);
|
|
866785
867475
|
try {
|
|
866786
|
-
const parsed = JSON.parse(
|
|
867476
|
+
const parsed = JSON.parse(readFileSync85(path7, "utf-8"));
|
|
866787
867477
|
if (!isCheckMarkerPayload(parsed)) {
|
|
866788
867478
|
return buildParseErrorState(scope, path7, "Invalid onboarding check marker payload.");
|
|
866789
867479
|
}
|
|
@@ -866825,7 +867515,7 @@ function writeOnboardingCheckMarker(shellPaths, options = {}) {
|
|
|
866825
867515
|
return readOnboardingCheckMarker(shellPaths, scope);
|
|
866826
867516
|
}
|
|
866827
867517
|
// src/input/handler-content-actions.ts
|
|
866828
|
-
import { readFileSync as
|
|
867518
|
+
import { readFileSync as readFileSync86, existsSync as existsSync78 } from "fs";
|
|
866829
867519
|
var MARKER_REGEX = /\[(TEXT|IMAGE): [^\]]+\]/g;
|
|
866830
867520
|
var IMAGE_PREFIXES = [
|
|
866831
867521
|
{ prefix: "iVBORw0KGgo", mediaType: "image/png" },
|
|
@@ -866887,7 +867577,7 @@ function registerPaste(state4, content, projectRoot) {
|
|
|
866887
867577
|
try {
|
|
866888
867578
|
const resolvedPath3 = resolveAndValidatePath(trimmed2, projectRoot);
|
|
866889
867579
|
if (existsSync78(resolvedPath3)) {
|
|
866890
|
-
const data =
|
|
867580
|
+
const data = readFileSync86(resolvedPath3);
|
|
866891
867581
|
const base644 = data.toString("base64");
|
|
866892
867582
|
const ext = trimmed2.slice(trimmed2.lastIndexOf("."));
|
|
866893
867583
|
const mediaType = mediaTypeFromExt(ext);
|
|
@@ -866937,7 +867627,7 @@ function expandPrompt(pasteRegistry, imageRegistry, text, projectRoot) {
|
|
|
866937
867627
|
const filePath = injectMatch[1];
|
|
866938
867628
|
try {
|
|
866939
867629
|
const resolvedPath3 = resolveAndValidatePath(filePath, projectRoot);
|
|
866940
|
-
const content =
|
|
867630
|
+
const content = readFileSync86(resolvedPath3, "utf-8");
|
|
866941
867631
|
expanded = expanded.slice(0, injectMatch.index) + content + expanded.slice(injectMatch.index + injectMatch[0].length);
|
|
866942
867632
|
injectRegex.lastIndex = injectMatch.index + content.length;
|
|
866943
867633
|
} catch (err2) {
|
|
@@ -868337,7 +869027,7 @@ class AutocompleteEngine {
|
|
|
868337
869027
|
|
|
868338
869028
|
// src/input/file-picker.ts
|
|
868339
869029
|
import { readdir as readdir6 } from "fs/promises";
|
|
868340
|
-
import { join as
|
|
869030
|
+
import { join as join94, relative as relative15 } from "path";
|
|
868341
869031
|
|
|
868342
869032
|
class FilePickerModal {
|
|
868343
869033
|
shellPaths;
|
|
@@ -868470,7 +869160,7 @@ class FilePickerModal {
|
|
|
868470
869160
|
continue;
|
|
868471
869161
|
if (entry.name === "node_modules" || entry.name === "dist")
|
|
868472
869162
|
continue;
|
|
868473
|
-
const fullPath =
|
|
869163
|
+
const fullPath = join94(dir, entry.name);
|
|
868474
869164
|
const relPath = relative15(this.shellPaths.workingDirectory, fullPath);
|
|
868475
869165
|
if (entry.isDirectory()) {
|
|
868476
869166
|
files.push(relPath + "/");
|
|
@@ -871892,218 +872582,13 @@ function quoteSlashCommandArg(value) {
|
|
|
871892
872582
|
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
|
|
871893
872583
|
}
|
|
871894
872584
|
|
|
871895
|
-
// src/input/agent-workspace-basic-command-
|
|
872585
|
+
// src/input/agent-workspace-basic-command-editor-submission.ts
|
|
871896
872586
|
function isAffirmative2(value) {
|
|
871897
872587
|
return /^(y|yes|true)$/i.test(value.trim());
|
|
871898
872588
|
}
|
|
871899
872589
|
function splitCommaList(value) {
|
|
871900
872590
|
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
871901
872591
|
}
|
|
871902
|
-
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";
|
|
871904
|
-
}
|
|
871905
|
-
function createAgentWorkspaceBasicCommandEditor(kind2) {
|
|
871906
|
-
if (kind2 === "knowledge-bookmarks") {
|
|
871907
|
-
return {
|
|
871908
|
-
kind: kind2,
|
|
871909
|
-
mode: "create",
|
|
871910
|
-
title: "Import Bookmarks into Agent Knowledge",
|
|
871911
|
-
selectedFieldIndex: 0,
|
|
871912
|
-
message: "Import a browser bookmark export into the isolated Agent Knowledge segment. Type yes on the final field to confirm.",
|
|
871913
|
-
fields: [
|
|
871914
|
-
{ id: "path", label: "Bookmark export path", value: "", required: true, multiline: false, hint: "Path to an HTML or JSON browser bookmark export." },
|
|
871915
|
-
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /knowledge import-bookmarks with --yes." }
|
|
871916
|
-
]
|
|
871917
|
-
};
|
|
871918
|
-
}
|
|
871919
|
-
if (kind2 === "knowledge-file") {
|
|
871920
|
-
return {
|
|
871921
|
-
kind: kind2,
|
|
871922
|
-
mode: "create",
|
|
871923
|
-
title: "Ingest File into Agent Knowledge",
|
|
871924
|
-
selectedFieldIndex: 0,
|
|
871925
|
-
message: "Import a local source-backed file into the isolated Agent Knowledge segment. Type yes on the final field to confirm.",
|
|
871926
|
-
fields: [
|
|
871927
|
-
{ id: "path", label: "File path", value: "", required: true, multiline: false, hint: "Path to a local document or text file to ingest." },
|
|
871928
|
-
{ id: "title", label: "Title", value: "", required: false, multiline: false, hint: "Optional source title." },
|
|
871929
|
-
{ id: "tags", label: "Tags", value: "", required: false, multiline: false, hint: "Comma-separated optional tags." },
|
|
871930
|
-
{ id: "folder", label: "Folder", value: "", required: false, multiline: false, hint: "Optional Agent Knowledge folder path." },
|
|
871931
|
-
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /knowledge ingest-file with --yes." }
|
|
871932
|
-
]
|
|
871933
|
-
};
|
|
871934
|
-
}
|
|
871935
|
-
if (kind2 === "knowledge-browser-history") {
|
|
871936
|
-
return {
|
|
871937
|
-
kind: kind2,
|
|
871938
|
-
mode: "create",
|
|
871939
|
-
title: "Import Browser History into Agent Knowledge",
|
|
871940
|
-
selectedFieldIndex: 0,
|
|
871941
|
-
message: "Import local browser history/bookmarks into the isolated Agent Knowledge segment. Type yes on the final field to confirm.",
|
|
871942
|
-
fields: [
|
|
871943
|
-
{ id: "browsers", label: "Browsers", value: "", required: false, multiline: false, hint: "Optional comma list: chrome, brave, edge, firefox, safari, etc." },
|
|
871944
|
-
{ id: "sources", label: "Sources", value: "history,bookmark", required: false, multiline: false, hint: "history, bookmark, or both." },
|
|
871945
|
-
{ id: "limit", label: "Limit", value: "250", required: false, multiline: false, hint: "Maximum browser entries to import." },
|
|
871946
|
-
{ id: "sinceDays", label: "Since days", value: "", required: false, multiline: false, hint: "Optional age window, such as 30." },
|
|
871947
|
-
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /knowledge import-browser-history with --yes." }
|
|
871948
|
-
]
|
|
871949
|
-
};
|
|
871950
|
-
}
|
|
871951
|
-
if (kind2 === "knowledge-connector-ingest") {
|
|
871952
|
-
return {
|
|
871953
|
-
kind: kind2,
|
|
871954
|
-
mode: "create",
|
|
871955
|
-
title: "Ingest Connector Input",
|
|
871956
|
-
selectedFieldIndex: 0,
|
|
871957
|
-
message: "Send explicit connector input into the isolated Agent Knowledge segment. Type yes on the final field to confirm.",
|
|
871958
|
-
fields: [
|
|
871959
|
-
{ id: "connectorId", label: "Connector id", value: "", required: true, multiline: false, hint: "Connector id from /knowledge connectors." },
|
|
871960
|
-
{ id: "input", label: "Input", value: "", required: false, multiline: true, hint: "Optional JSON or text input. Ctrl-J inserts a new line." },
|
|
871961
|
-
{ id: "path", label: "Path", value: "", required: false, multiline: false, hint: "Optional local path for connectors that read files." },
|
|
871962
|
-
{ id: "content", label: "Content", value: "", required: false, multiline: true, hint: "Optional raw content for connectors that accept text." },
|
|
871963
|
-
{ id: "allowPrivateHosts", label: "Allow private hosts", value: "no", required: false, multiline: false, hint: "yes/no. Defaults to no." },
|
|
871964
|
-
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /knowledge ingest-connector with --yes." }
|
|
871965
|
-
]
|
|
871966
|
-
};
|
|
871967
|
-
}
|
|
871968
|
-
if (kind2 === "mcp-server") {
|
|
871969
|
-
return {
|
|
871970
|
-
kind: kind2,
|
|
871971
|
-
mode: "create",
|
|
871972
|
-
title: "Add MCP Server",
|
|
871973
|
-
selectedFieldIndex: 0,
|
|
871974
|
-
message: "Add or update one MCP server from the Agent workspace. Type yes on the final field to confirm.",
|
|
871975
|
-
fields: [
|
|
871976
|
-
{ id: "name", label: "Server name", value: "", required: true, multiline: false, hint: "Letters, numbers, dot, underscore, and dash only." },
|
|
871977
|
-
{ id: "command", label: "Command", value: "", required: true, multiline: false, hint: "Executable command, such as bunx, npx, uvx, or a full local binary path." },
|
|
871978
|
-
{ id: "args", label: "Arguments", value: "", required: false, multiline: false, hint: "Optional command arguments. Quotes are supported." },
|
|
871979
|
-
{ id: "scope", label: "Scope", value: "", required: false, multiline: false, hint: "Optional. Defaults to project. Use project or global." },
|
|
871980
|
-
{ id: "role", label: "Role", value: "", required: false, multiline: false, hint: "Optional. general, docs, filesystem, git, database, browser, automation, ops, or remote." },
|
|
871981
|
-
{ id: "trust", label: "Trust mode", value: "", required: false, multiline: false, hint: "Optional. Defaults to constrained. Use constrained, ask-on-risk, or blocked. Use settings for allow-all." },
|
|
871982
|
-
{ id: "env", label: "Env refs", value: "", required: false, multiline: false, hint: "Comma-separated KEY=VALUE entries. Prefer secret refs, not raw secrets." },
|
|
871983
|
-
{ id: "paths", label: "Allowed paths", value: "", required: false, multiline: false, hint: "Comma-separated path allowlist entries." },
|
|
871984
|
-
{ id: "hosts", label: "Allowed hosts", value: "", required: false, multiline: false, hint: "Comma-separated host allowlist entries." },
|
|
871985
|
-
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /mcp add with --yes." }
|
|
871986
|
-
]
|
|
871987
|
-
};
|
|
871988
|
-
}
|
|
871989
|
-
if (kind2 === "notify-webhook") {
|
|
871990
|
-
return {
|
|
871991
|
-
kind: kind2,
|
|
871992
|
-
mode: "create",
|
|
871993
|
-
title: "Add Notification Webhook",
|
|
871994
|
-
selectedFieldIndex: 0,
|
|
871995
|
-
message: "Add one webhook notification target for explicit reminder/routine delivery. Type yes on the final field to confirm.",
|
|
871996
|
-
fields: [
|
|
871997
|
-
{ id: "url", label: "Webhook URL", value: "", required: true, multiline: false, hint: "HTTP(S) target, for example https://ntfy.sh/my-topic." },
|
|
871998
|
-
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /notify add with --yes." }
|
|
871999
|
-
]
|
|
872000
|
-
};
|
|
872001
|
-
}
|
|
872002
|
-
if (kind2 === "notify-webhook-remove") {
|
|
872003
|
-
return {
|
|
872004
|
-
kind: kind2,
|
|
872005
|
-
mode: "delete",
|
|
872006
|
-
title: "Remove Notification Webhook",
|
|
872007
|
-
selectedFieldIndex: 0,
|
|
872008
|
-
message: "Remove one configured webhook notification target. Type yes on the final field to confirm.",
|
|
872009
|
-
fields: [
|
|
872010
|
-
{ id: "url", label: "Webhook URL", value: "", required: true, multiline: false, hint: "Exact HTTP(S) webhook URL to remove from configured notification targets." },
|
|
872011
|
-
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /notify remove with --yes." }
|
|
872012
|
-
]
|
|
872013
|
-
};
|
|
872014
|
-
}
|
|
872015
|
-
if (kind2 === "notify-webhook-test") {
|
|
872016
|
-
return {
|
|
872017
|
-
kind: kind2,
|
|
872018
|
-
mode: "create",
|
|
872019
|
-
title: "Test Notification Webhooks",
|
|
872020
|
-
selectedFieldIndex: 0,
|
|
872021
|
-
message: "Send one test notification to configured webhook targets. Type yes on the final field to confirm.",
|
|
872022
|
-
fields: [
|
|
872023
|
-
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /notify test with --yes." }
|
|
872024
|
-
]
|
|
872025
|
-
};
|
|
872026
|
-
}
|
|
872027
|
-
if (kind2 === "tts-prompt") {
|
|
872028
|
-
return {
|
|
872029
|
-
kind: kind2,
|
|
872030
|
-
mode: "create",
|
|
872031
|
-
title: "Speak Assistant Reply",
|
|
872032
|
-
selectedFieldIndex: 0,
|
|
872033
|
-
message: "Submit a normal assistant prompt and play the reply through configured live TTS.",
|
|
872034
|
-
fields: [
|
|
872035
|
-
{ id: "prompt", label: "Prompt", value: "", required: true, multiline: true, hint: "Assistant prompt to speak. Ctrl-J inserts a new line." }
|
|
872036
|
-
]
|
|
872037
|
-
};
|
|
872038
|
-
}
|
|
872039
|
-
if (kind2 === "image-input") {
|
|
872040
|
-
return {
|
|
872041
|
-
kind: kind2,
|
|
872042
|
-
mode: "create",
|
|
872043
|
-
title: "Attach Image Input",
|
|
872044
|
-
selectedFieldIndex: 0,
|
|
872045
|
-
message: "Attach an image to the next assistant turn. The existing image command validates file type and model support.",
|
|
872046
|
-
fields: [
|
|
872047
|
-
{ id: "path", label: "Image path", value: "", required: true, multiline: false, hint: "PNG, JPEG, WebP, or GIF path under the current workspace." },
|
|
872048
|
-
{ id: "prompt", label: "Prompt", value: "", required: false, multiline: true, hint: "Optional prompt. Ctrl-J inserts a new line." }
|
|
872049
|
-
]
|
|
872050
|
-
};
|
|
872051
|
-
}
|
|
872052
|
-
if (kind2 === "profile-template-export") {
|
|
872053
|
-
return {
|
|
872054
|
-
kind: kind2,
|
|
872055
|
-
mode: "create",
|
|
872056
|
-
title: "Export Agent Starter Template",
|
|
872057
|
-
selectedFieldIndex: 0,
|
|
872058
|
-
message: "Export a starter template JSON file for review and customization. Type yes on the final field to confirm.",
|
|
872059
|
-
fields: [
|
|
872060
|
-
{ id: "templateId", label: "Starter id", value: "", required: true, multiline: false, hint: "Existing starter id from /agent-profile templates." },
|
|
872061
|
-
{ id: "path", label: "Output path", value: "", required: true, multiline: false, hint: "Workspace-relative JSON path to write." },
|
|
872062
|
-
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /agent-profile template export with --yes." }
|
|
872063
|
-
]
|
|
872064
|
-
};
|
|
872065
|
-
}
|
|
872066
|
-
if (kind2 === "profile-template-import") {
|
|
872067
|
-
return {
|
|
872068
|
-
kind: kind2,
|
|
872069
|
-
mode: "create",
|
|
872070
|
-
title: "Import Agent Starter Template",
|
|
872071
|
-
selectedFieldIndex: 0,
|
|
872072
|
-
message: "Import a reviewed starter template JSON file into this Agent home. Type yes on the final field to confirm.",
|
|
872073
|
-
fields: [
|
|
872074
|
-
{ id: "path", label: "Template path", value: "", required: true, multiline: false, hint: "Workspace-relative JSON path to import." },
|
|
872075
|
-
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /agent-profile template import with --yes." }
|
|
872076
|
-
]
|
|
872077
|
-
};
|
|
872078
|
-
}
|
|
872079
|
-
if (kind2 === "skill-discovery-import") {
|
|
872080
|
-
return {
|
|
872081
|
-
kind: kind2,
|
|
872082
|
-
mode: "create",
|
|
872083
|
-
title: "Import Discovered Skill",
|
|
872084
|
-
selectedFieldIndex: 0,
|
|
872085
|
-
message: "Import one discovered SKILL.md or .md skill file into the Agent-local skill registry. Type yes on the final field to confirm.",
|
|
872086
|
-
fields: [
|
|
872087
|
-
{ id: "name", label: "Discovered skill", value: "", required: true, multiline: false, hint: "Name shown by /agent-skills discover." },
|
|
872088
|
-
{ id: "enabled", label: "Enable now", value: "yes", required: false, multiline: false, hint: "yes/no." },
|
|
872089
|
-
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /agent-skills import-discovered with --yes." }
|
|
872090
|
-
]
|
|
872091
|
-
};
|
|
872092
|
-
}
|
|
872093
|
-
return {
|
|
872094
|
-
kind: kind2,
|
|
872095
|
-
mode: "create",
|
|
872096
|
-
title: "Create Skill Bundle",
|
|
872097
|
-
selectedFieldIndex: 0,
|
|
872098
|
-
message: "Group existing local skills into a reviewable bundle that can be enabled together.",
|
|
872099
|
-
fields: [
|
|
872100
|
-
{ id: "name", label: "Bundle name", value: "", required: true, multiline: false, hint: "Short bundle name." },
|
|
872101
|
-
{ id: "description", label: "Description", value: "", required: true, multiline: false, hint: "One-line bundle summary." },
|
|
872102
|
-
{ id: "skills", label: "Skill ids", value: "", required: true, multiline: false, hint: "Comma-separated existing local skill ids." },
|
|
872103
|
-
{ id: "enabled", label: "Enable now", value: "yes", required: false, multiline: false, hint: "yes/no." }
|
|
872104
|
-
]
|
|
872105
|
-
};
|
|
872106
|
-
}
|
|
872107
872592
|
function buildAgentWorkspaceBasicCommandEditorSubmission(editor, readField, commandDispatchAvailable) {
|
|
872108
872593
|
if (!commandDispatchAvailable) {
|
|
872109
872594
|
return {
|
|
@@ -872430,6 +872915,100 @@ function buildAgentWorkspaceBasicCommandEditorSubmission(editor, readField, comm
|
|
|
872430
872915
|
}
|
|
872431
872916
|
};
|
|
872432
872917
|
}
|
|
872918
|
+
if (editor.kind === "profile-template-from-discovered") {
|
|
872919
|
+
if (!isAffirmative2(readField("confirm"))) {
|
|
872920
|
+
return {
|
|
872921
|
+
kind: "editor",
|
|
872922
|
+
editor: { ...editor, message: "Starter-from-discovered creation not confirmed. Type yes, then press Enter." },
|
|
872923
|
+
status: "Agent starter-from-discovered creation not confirmed."
|
|
872924
|
+
};
|
|
872925
|
+
}
|
|
872926
|
+
const parts2 = [
|
|
872927
|
+
"/agent-profile",
|
|
872928
|
+
"template",
|
|
872929
|
+
"from-discovered",
|
|
872930
|
+
quoteSlashCommandArg(readField("id"))
|
|
872931
|
+
];
|
|
872932
|
+
const name51 = readField("name");
|
|
872933
|
+
const description = readField("description");
|
|
872934
|
+
const persona = readField("persona");
|
|
872935
|
+
const skills = readField("skills");
|
|
872936
|
+
const routines = readField("routines");
|
|
872937
|
+
if (name51.length > 0)
|
|
872938
|
+
parts2.push("--name", quoteSlashCommandArg(name51));
|
|
872939
|
+
if (description.length > 0)
|
|
872940
|
+
parts2.push("--description", quoteSlashCommandArg(description));
|
|
872941
|
+
if (persona.length > 0)
|
|
872942
|
+
parts2.push("--persona", quoteSlashCommandArg(persona));
|
|
872943
|
+
if (skills.length > 0)
|
|
872944
|
+
parts2.push("--skills", quoteSlashCommandArg(skills));
|
|
872945
|
+
if (routines.length > 0)
|
|
872946
|
+
parts2.push("--routines", quoteSlashCommandArg(routines));
|
|
872947
|
+
if (isAffirmative2(readField("replace")))
|
|
872948
|
+
parts2.push("--replace");
|
|
872949
|
+
parts2.push("--yes");
|
|
872950
|
+
const command9 = parts2.join(" ");
|
|
872951
|
+
return {
|
|
872952
|
+
kind: "dispatch",
|
|
872953
|
+
command: command9,
|
|
872954
|
+
status: "Opening Agent starter-from-discovered creation.",
|
|
872955
|
+
actionResult: {
|
|
872956
|
+
kind: "dispatched",
|
|
872957
|
+
title: "Opening Agent starter-from-discovered creation",
|
|
872958
|
+
detail: "The workspace handed a confirmed starter creation command to the shell-owned command router.",
|
|
872959
|
+
command: command9,
|
|
872960
|
+
safety: "safe"
|
|
872961
|
+
}
|
|
872962
|
+
};
|
|
872963
|
+
}
|
|
872964
|
+
if (editor.kind === "profile-from-discovered") {
|
|
872965
|
+
if (!isAffirmative2(readField("confirm"))) {
|
|
872966
|
+
return {
|
|
872967
|
+
kind: "editor",
|
|
872968
|
+
editor: { ...editor, message: "Profile-from-discovered creation not confirmed. Type yes, then press Enter." },
|
|
872969
|
+
status: "Agent profile-from-discovered creation not confirmed."
|
|
872970
|
+
};
|
|
872971
|
+
}
|
|
872972
|
+
const parts2 = [
|
|
872973
|
+
"/agent-profile",
|
|
872974
|
+
"create-from-discovered",
|
|
872975
|
+
quoteSlashCommandArg(readField("profile"))
|
|
872976
|
+
];
|
|
872977
|
+
const templateId = readField("templateId");
|
|
872978
|
+
const name51 = readField("name");
|
|
872979
|
+
const description = readField("description");
|
|
872980
|
+
const persona = readField("persona");
|
|
872981
|
+
const skills = readField("skills");
|
|
872982
|
+
const routines = readField("routines");
|
|
872983
|
+
if (templateId.length > 0)
|
|
872984
|
+
parts2.push("--template-id", quoteSlashCommandArg(templateId));
|
|
872985
|
+
if (name51.length > 0)
|
|
872986
|
+
parts2.push("--name", quoteSlashCommandArg(name51));
|
|
872987
|
+
if (description.length > 0)
|
|
872988
|
+
parts2.push("--description", quoteSlashCommandArg(description));
|
|
872989
|
+
if (persona.length > 0)
|
|
872990
|
+
parts2.push("--persona", quoteSlashCommandArg(persona));
|
|
872991
|
+
if (skills.length > 0)
|
|
872992
|
+
parts2.push("--skills", quoteSlashCommandArg(skills));
|
|
872993
|
+
if (routines.length > 0)
|
|
872994
|
+
parts2.push("--routines", quoteSlashCommandArg(routines));
|
|
872995
|
+
if (isAffirmative2(readField("replace")))
|
|
872996
|
+
parts2.push("--replace");
|
|
872997
|
+
parts2.push("--yes");
|
|
872998
|
+
const command9 = parts2.join(" ");
|
|
872999
|
+
return {
|
|
873000
|
+
kind: "dispatch",
|
|
873001
|
+
command: command9,
|
|
873002
|
+
status: "Opening Agent profile-from-discovered creation.",
|
|
873003
|
+
actionResult: {
|
|
873004
|
+
kind: "dispatched",
|
|
873005
|
+
title: "Opening Agent profile-from-discovered creation",
|
|
873006
|
+
detail: "The workspace handed a confirmed discovered-behavior profile creation command to the shell-owned command router.",
|
|
873007
|
+
command: command9,
|
|
873008
|
+
safety: "safe"
|
|
873009
|
+
}
|
|
873010
|
+
};
|
|
873011
|
+
}
|
|
872433
873012
|
if (editor.kind === "skill-discovery-import") {
|
|
872434
873013
|
if (!isAffirmative2(readField("confirm"))) {
|
|
872435
873014
|
return {
|
|
@@ -872460,6 +873039,66 @@ function buildAgentWorkspaceBasicCommandEditorSubmission(editor, readField, comm
|
|
|
872460
873039
|
}
|
|
872461
873040
|
};
|
|
872462
873041
|
}
|
|
873042
|
+
if (editor.kind === "persona-discovery-import") {
|
|
873043
|
+
if (!isAffirmative2(readField("confirm"))) {
|
|
873044
|
+
return {
|
|
873045
|
+
kind: "editor",
|
|
873046
|
+
editor: { ...editor, message: "Discovered persona import not confirmed. Type yes, then press Enter." },
|
|
873047
|
+
status: "Agent persona import not confirmed."
|
|
873048
|
+
};
|
|
873049
|
+
}
|
|
873050
|
+
const parts2 = [
|
|
873051
|
+
"/personas",
|
|
873052
|
+
"import-discovered",
|
|
873053
|
+
quoteSlashCommandArg(readField("name"))
|
|
873054
|
+
];
|
|
873055
|
+
if (isAffirmative2(readField("use")))
|
|
873056
|
+
parts2.push("--use");
|
|
873057
|
+
parts2.push("--yes");
|
|
873058
|
+
const command9 = parts2.join(" ");
|
|
873059
|
+
return {
|
|
873060
|
+
kind: "dispatch",
|
|
873061
|
+
command: command9,
|
|
873062
|
+
status: "Opening discovered persona import.",
|
|
873063
|
+
actionResult: {
|
|
873064
|
+
kind: "dispatched",
|
|
873065
|
+
title: "Opening discovered persona import",
|
|
873066
|
+
detail: "The workspace handed a confirmed local persona import command to the shell-owned command router.",
|
|
873067
|
+
command: command9,
|
|
873068
|
+
safety: "safe"
|
|
873069
|
+
}
|
|
873070
|
+
};
|
|
873071
|
+
}
|
|
873072
|
+
if (editor.kind === "routine-discovery-import") {
|
|
873073
|
+
if (!isAffirmative2(readField("confirm"))) {
|
|
873074
|
+
return {
|
|
873075
|
+
kind: "editor",
|
|
873076
|
+
editor: { ...editor, message: "Discovered routine import not confirmed. Type yes, then press Enter." },
|
|
873077
|
+
status: "Agent routine import not confirmed."
|
|
873078
|
+
};
|
|
873079
|
+
}
|
|
873080
|
+
const parts2 = [
|
|
873081
|
+
"/routines",
|
|
873082
|
+
"import-discovered",
|
|
873083
|
+
quoteSlashCommandArg(readField("name"))
|
|
873084
|
+
];
|
|
873085
|
+
if (isAffirmative2(readField("enabled")))
|
|
873086
|
+
parts2.push("--enabled");
|
|
873087
|
+
parts2.push("--yes");
|
|
873088
|
+
const command9 = parts2.join(" ");
|
|
873089
|
+
return {
|
|
873090
|
+
kind: "dispatch",
|
|
873091
|
+
command: command9,
|
|
873092
|
+
status: "Opening discovered routine import.",
|
|
873093
|
+
actionResult: {
|
|
873094
|
+
kind: "dispatched",
|
|
873095
|
+
title: "Opening discovered routine import",
|
|
873096
|
+
detail: "The workspace handed a confirmed local routine import command to the shell-owned command router.",
|
|
873097
|
+
command: command9,
|
|
873098
|
+
safety: "safe"
|
|
873099
|
+
}
|
|
873100
|
+
};
|
|
873101
|
+
}
|
|
872463
873102
|
const commandParts = [
|
|
872464
873103
|
"/agent-skills bundle create",
|
|
872465
873104
|
"--name",
|
|
@@ -872486,6 +873125,280 @@ function buildAgentWorkspaceBasicCommandEditorSubmission(editor, readField, comm
|
|
|
872486
873125
|
};
|
|
872487
873126
|
}
|
|
872488
873127
|
|
|
873128
|
+
// src/input/agent-workspace-basic-command-editors.ts
|
|
873129
|
+
function isAgentWorkspaceBasicCommandEditorKind(kind2) {
|
|
873130
|
+
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 === "profile-template-from-discovered" || kind2 === "profile-from-discovered" || kind2 === "mcp-server" || kind2 === "notify-webhook" || kind2 === "notify-webhook-remove" || kind2 === "notify-webhook-test";
|
|
873131
|
+
}
|
|
873132
|
+
function createAgentWorkspaceBasicCommandEditor(kind2) {
|
|
873133
|
+
if (kind2 === "knowledge-bookmarks") {
|
|
873134
|
+
return {
|
|
873135
|
+
kind: kind2,
|
|
873136
|
+
mode: "create",
|
|
873137
|
+
title: "Import Bookmarks into Agent Knowledge",
|
|
873138
|
+
selectedFieldIndex: 0,
|
|
873139
|
+
message: "Import a browser bookmark export into the isolated Agent Knowledge segment. Type yes on the final field to confirm.",
|
|
873140
|
+
fields: [
|
|
873141
|
+
{ id: "path", label: "Bookmark export path", value: "", required: true, multiline: false, hint: "Path to an HTML or JSON browser bookmark export." },
|
|
873142
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /knowledge import-bookmarks with --yes." }
|
|
873143
|
+
]
|
|
873144
|
+
};
|
|
873145
|
+
}
|
|
873146
|
+
if (kind2 === "knowledge-file") {
|
|
873147
|
+
return {
|
|
873148
|
+
kind: kind2,
|
|
873149
|
+
mode: "create",
|
|
873150
|
+
title: "Ingest File into Agent Knowledge",
|
|
873151
|
+
selectedFieldIndex: 0,
|
|
873152
|
+
message: "Import a local source-backed file into the isolated Agent Knowledge segment. Type yes on the final field to confirm.",
|
|
873153
|
+
fields: [
|
|
873154
|
+
{ id: "path", label: "File path", value: "", required: true, multiline: false, hint: "Path to a local document or text file to ingest." },
|
|
873155
|
+
{ id: "title", label: "Title", value: "", required: false, multiline: false, hint: "Optional source title." },
|
|
873156
|
+
{ id: "tags", label: "Tags", value: "", required: false, multiline: false, hint: "Comma-separated optional tags." },
|
|
873157
|
+
{ id: "folder", label: "Folder", value: "", required: false, multiline: false, hint: "Optional Agent Knowledge folder path." },
|
|
873158
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /knowledge ingest-file with --yes." }
|
|
873159
|
+
]
|
|
873160
|
+
};
|
|
873161
|
+
}
|
|
873162
|
+
if (kind2 === "knowledge-browser-history") {
|
|
873163
|
+
return {
|
|
873164
|
+
kind: kind2,
|
|
873165
|
+
mode: "create",
|
|
873166
|
+
title: "Import Browser History into Agent Knowledge",
|
|
873167
|
+
selectedFieldIndex: 0,
|
|
873168
|
+
message: "Import local browser history/bookmarks into the isolated Agent Knowledge segment. Type yes on the final field to confirm.",
|
|
873169
|
+
fields: [
|
|
873170
|
+
{ id: "browsers", label: "Browsers", value: "", required: false, multiline: false, hint: "Optional comma list: chrome, brave, edge, firefox, safari, etc." },
|
|
873171
|
+
{ id: "sources", label: "Sources", value: "history,bookmark", required: false, multiline: false, hint: "history, bookmark, or both." },
|
|
873172
|
+
{ id: "limit", label: "Limit", value: "250", required: false, multiline: false, hint: "Maximum browser entries to import." },
|
|
873173
|
+
{ id: "sinceDays", label: "Since days", value: "", required: false, multiline: false, hint: "Optional age window, such as 30." },
|
|
873174
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /knowledge import-browser-history with --yes." }
|
|
873175
|
+
]
|
|
873176
|
+
};
|
|
873177
|
+
}
|
|
873178
|
+
if (kind2 === "knowledge-connector-ingest") {
|
|
873179
|
+
return {
|
|
873180
|
+
kind: kind2,
|
|
873181
|
+
mode: "create",
|
|
873182
|
+
title: "Ingest Connector Input",
|
|
873183
|
+
selectedFieldIndex: 0,
|
|
873184
|
+
message: "Send explicit connector input into the isolated Agent Knowledge segment. Type yes on the final field to confirm.",
|
|
873185
|
+
fields: [
|
|
873186
|
+
{ id: "connectorId", label: "Connector id", value: "", required: true, multiline: false, hint: "Connector id from /knowledge connectors." },
|
|
873187
|
+
{ id: "input", label: "Input", value: "", required: false, multiline: true, hint: "Optional JSON or text input. Ctrl-J inserts a new line." },
|
|
873188
|
+
{ id: "path", label: "Path", value: "", required: false, multiline: false, hint: "Optional local path for connectors that read files." },
|
|
873189
|
+
{ id: "content", label: "Content", value: "", required: false, multiline: true, hint: "Optional raw content for connectors that accept text." },
|
|
873190
|
+
{ id: "allowPrivateHosts", label: "Allow private hosts", value: "no", required: false, multiline: false, hint: "yes/no. Defaults to no." },
|
|
873191
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /knowledge ingest-connector with --yes." }
|
|
873192
|
+
]
|
|
873193
|
+
};
|
|
873194
|
+
}
|
|
873195
|
+
if (kind2 === "mcp-server") {
|
|
873196
|
+
return {
|
|
873197
|
+
kind: kind2,
|
|
873198
|
+
mode: "create",
|
|
873199
|
+
title: "Add MCP Server",
|
|
873200
|
+
selectedFieldIndex: 0,
|
|
873201
|
+
message: "Add or update one MCP server from the Agent workspace. Type yes on the final field to confirm.",
|
|
873202
|
+
fields: [
|
|
873203
|
+
{ id: "name", label: "Server name", value: "", required: true, multiline: false, hint: "Letters, numbers, dot, underscore, and dash only." },
|
|
873204
|
+
{ id: "command", label: "Command", value: "", required: true, multiline: false, hint: "Executable command, such as bunx, npx, uvx, or a full local binary path." },
|
|
873205
|
+
{ id: "args", label: "Arguments", value: "", required: false, multiline: false, hint: "Optional command arguments. Quotes are supported." },
|
|
873206
|
+
{ id: "scope", label: "Scope", value: "", required: false, multiline: false, hint: "Optional. Defaults to project. Use project or global." },
|
|
873207
|
+
{ id: "role", label: "Role", value: "", required: false, multiline: false, hint: "Optional. general, docs, filesystem, git, database, browser, automation, ops, or remote." },
|
|
873208
|
+
{ id: "trust", label: "Trust mode", value: "", required: false, multiline: false, hint: "Optional. Defaults to constrained. Use constrained, ask-on-risk, or blocked. Use settings for allow-all." },
|
|
873209
|
+
{ id: "env", label: "Env refs", value: "", required: false, multiline: false, hint: "Comma-separated KEY=VALUE entries. Prefer secret refs, not raw secrets." },
|
|
873210
|
+
{ id: "paths", label: "Allowed paths", value: "", required: false, multiline: false, hint: "Comma-separated path allowlist entries." },
|
|
873211
|
+
{ id: "hosts", label: "Allowed hosts", value: "", required: false, multiline: false, hint: "Comma-separated host allowlist entries." },
|
|
873212
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /mcp add with --yes." }
|
|
873213
|
+
]
|
|
873214
|
+
};
|
|
873215
|
+
}
|
|
873216
|
+
if (kind2 === "notify-webhook") {
|
|
873217
|
+
return {
|
|
873218
|
+
kind: kind2,
|
|
873219
|
+
mode: "create",
|
|
873220
|
+
title: "Add Notification Webhook",
|
|
873221
|
+
selectedFieldIndex: 0,
|
|
873222
|
+
message: "Add one webhook notification target for explicit reminder/routine delivery. Type yes on the final field to confirm.",
|
|
873223
|
+
fields: [
|
|
873224
|
+
{ id: "url", label: "Webhook URL", value: "", required: true, multiline: false, hint: "HTTP(S) target, for example https://ntfy.sh/my-topic." },
|
|
873225
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /notify add with --yes." }
|
|
873226
|
+
]
|
|
873227
|
+
};
|
|
873228
|
+
}
|
|
873229
|
+
if (kind2 === "notify-webhook-remove") {
|
|
873230
|
+
return {
|
|
873231
|
+
kind: kind2,
|
|
873232
|
+
mode: "delete",
|
|
873233
|
+
title: "Remove Notification Webhook",
|
|
873234
|
+
selectedFieldIndex: 0,
|
|
873235
|
+
message: "Remove one configured webhook notification target. Type yes on the final field to confirm.",
|
|
873236
|
+
fields: [
|
|
873237
|
+
{ id: "url", label: "Webhook URL", value: "", required: true, multiline: false, hint: "Exact HTTP(S) webhook URL to remove from configured notification targets." },
|
|
873238
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /notify remove with --yes." }
|
|
873239
|
+
]
|
|
873240
|
+
};
|
|
873241
|
+
}
|
|
873242
|
+
if (kind2 === "notify-webhook-test") {
|
|
873243
|
+
return {
|
|
873244
|
+
kind: kind2,
|
|
873245
|
+
mode: "create",
|
|
873246
|
+
title: "Test Notification Webhooks",
|
|
873247
|
+
selectedFieldIndex: 0,
|
|
873248
|
+
message: "Send one test notification to configured webhook targets. Type yes on the final field to confirm.",
|
|
873249
|
+
fields: [
|
|
873250
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /notify test with --yes." }
|
|
873251
|
+
]
|
|
873252
|
+
};
|
|
873253
|
+
}
|
|
873254
|
+
if (kind2 === "tts-prompt") {
|
|
873255
|
+
return {
|
|
873256
|
+
kind: kind2,
|
|
873257
|
+
mode: "create",
|
|
873258
|
+
title: "Speak Assistant Reply",
|
|
873259
|
+
selectedFieldIndex: 0,
|
|
873260
|
+
message: "Submit a normal assistant prompt and play the reply through configured live TTS.",
|
|
873261
|
+
fields: [
|
|
873262
|
+
{ id: "prompt", label: "Prompt", value: "", required: true, multiline: true, hint: "Assistant prompt to speak. Ctrl-J inserts a new line." }
|
|
873263
|
+
]
|
|
873264
|
+
};
|
|
873265
|
+
}
|
|
873266
|
+
if (kind2 === "image-input") {
|
|
873267
|
+
return {
|
|
873268
|
+
kind: kind2,
|
|
873269
|
+
mode: "create",
|
|
873270
|
+
title: "Attach Image Input",
|
|
873271
|
+
selectedFieldIndex: 0,
|
|
873272
|
+
message: "Attach an image to the next assistant turn. The existing image command validates file type and model support.",
|
|
873273
|
+
fields: [
|
|
873274
|
+
{ id: "path", label: "Image path", value: "", required: true, multiline: false, hint: "PNG, JPEG, WebP, or GIF path under the current workspace." },
|
|
873275
|
+
{ id: "prompt", label: "Prompt", value: "", required: false, multiline: true, hint: "Optional prompt. Ctrl-J inserts a new line." }
|
|
873276
|
+
]
|
|
873277
|
+
};
|
|
873278
|
+
}
|
|
873279
|
+
if (kind2 === "profile-template-export") {
|
|
873280
|
+
return {
|
|
873281
|
+
kind: kind2,
|
|
873282
|
+
mode: "create",
|
|
873283
|
+
title: "Export Agent Starter Template",
|
|
873284
|
+
selectedFieldIndex: 0,
|
|
873285
|
+
message: "Export a starter template JSON file for review and customization. Type yes on the final field to confirm.",
|
|
873286
|
+
fields: [
|
|
873287
|
+
{ id: "templateId", label: "Starter id", value: "", required: true, multiline: false, hint: "Existing starter id from /agent-profile templates." },
|
|
873288
|
+
{ id: "path", label: "Output path", value: "", required: true, multiline: false, hint: "Workspace-relative JSON path to write." },
|
|
873289
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /agent-profile template export with --yes." }
|
|
873290
|
+
]
|
|
873291
|
+
};
|
|
873292
|
+
}
|
|
873293
|
+
if (kind2 === "profile-template-import") {
|
|
873294
|
+
return {
|
|
873295
|
+
kind: kind2,
|
|
873296
|
+
mode: "create",
|
|
873297
|
+
title: "Import Agent Starter Template",
|
|
873298
|
+
selectedFieldIndex: 0,
|
|
873299
|
+
message: "Import a reviewed starter template JSON file into this Agent home. Type yes on the final field to confirm.",
|
|
873300
|
+
fields: [
|
|
873301
|
+
{ id: "path", label: "Template path", value: "", required: true, multiline: false, hint: "Workspace-relative JSON path to import." },
|
|
873302
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /agent-profile template import with --yes." }
|
|
873303
|
+
]
|
|
873304
|
+
};
|
|
873305
|
+
}
|
|
873306
|
+
if (kind2 === "profile-template-from-discovered") {
|
|
873307
|
+
return {
|
|
873308
|
+
kind: kind2,
|
|
873309
|
+
mode: "create",
|
|
873310
|
+
title: "Create Starter from Discovered Behavior",
|
|
873311
|
+
selectedFieldIndex: 0,
|
|
873312
|
+
message: "Create an Agent-local starter template from reviewed discovered persona, skill, and routine markdown. Type yes on the final field to confirm.",
|
|
873313
|
+
fields: [
|
|
873314
|
+
{ id: "id", label: "Starter id", value: "", required: true, multiline: false, hint: "New local starter id, for example research-desk." },
|
|
873315
|
+
{ id: "name", label: "Starter name", value: "", required: false, multiline: false, hint: "Optional display name. Defaults to the selected persona name." },
|
|
873316
|
+
{ id: "description", label: "Description", value: "", required: false, multiline: false, hint: "Optional one-line summary." },
|
|
873317
|
+
{ id: "persona", label: "Persona", value: "", required: false, multiline: false, hint: "Optional discovered persona name/path. Blank uses the first discovered persona." },
|
|
873318
|
+
{ id: "skills", label: "Skills", value: "", required: false, multiline: false, hint: "all or comma-separated discovered skill names. Blank includes all." },
|
|
873319
|
+
{ id: "routines", label: "Routines", value: "", required: false, multiline: false, hint: "all or comma-separated discovered routine names. Blank includes all." },
|
|
873320
|
+
{ id: "replace", label: "Replace existing", value: "no", required: false, multiline: false, hint: "yes/no. Existing starter ids are protected unless this is yes." },
|
|
873321
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /agent-profile template from-discovered with --yes." }
|
|
873322
|
+
]
|
|
873323
|
+
};
|
|
873324
|
+
}
|
|
873325
|
+
if (kind2 === "profile-from-discovered") {
|
|
873326
|
+
return {
|
|
873327
|
+
kind: kind2,
|
|
873328
|
+
mode: "create",
|
|
873329
|
+
title: "Create Profile from Discovered Behavior",
|
|
873330
|
+
selectedFieldIndex: 0,
|
|
873331
|
+
message: "Create a local starter template and isolated Agent profile from reviewed discovered behavior markdown. Type yes on the final field to confirm.",
|
|
873332
|
+
fields: [
|
|
873333
|
+
{ id: "profile", label: "Profile name", value: "", required: true, multiline: false, hint: "New isolated Agent profile name, for example research-desk." },
|
|
873334
|
+
{ id: "templateId", label: "Starter id", value: "", required: false, multiline: false, hint: "Optional local starter id. Blank uses the profile name." },
|
|
873335
|
+
{ id: "name", label: "Starter name", value: "", required: false, multiline: false, hint: "Optional display name for the generated starter." },
|
|
873336
|
+
{ id: "description", label: "Description", value: "", required: false, multiline: false, hint: "Optional one-line summary." },
|
|
873337
|
+
{ id: "persona", label: "Persona", value: "", required: false, multiline: false, hint: "Optional discovered persona name/path. Blank uses the first discovered persona." },
|
|
873338
|
+
{ id: "skills", label: "Skills", value: "", required: false, multiline: false, hint: "all or comma-separated discovered skill names. Blank includes all." },
|
|
873339
|
+
{ id: "routines", label: "Routines", value: "", required: false, multiline: false, hint: "all or comma-separated discovered routine names. Blank includes all." },
|
|
873340
|
+
{ id: "replace", label: "Replace starter", value: "no", required: false, multiline: false, hint: "yes/no. Existing starter ids are protected unless this is yes." },
|
|
873341
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /agent-profile create-from-discovered with --yes." }
|
|
873342
|
+
]
|
|
873343
|
+
};
|
|
873344
|
+
}
|
|
873345
|
+
if (kind2 === "skill-discovery-import") {
|
|
873346
|
+
return {
|
|
873347
|
+
kind: kind2,
|
|
873348
|
+
mode: "create",
|
|
873349
|
+
title: "Import Discovered Skill",
|
|
873350
|
+
selectedFieldIndex: 0,
|
|
873351
|
+
message: "Import one discovered SKILL.md or .md skill file into the Agent-local skill registry. Type yes on the final field to confirm.",
|
|
873352
|
+
fields: [
|
|
873353
|
+
{ id: "name", label: "Discovered skill", value: "", required: true, multiline: false, hint: "Name shown by /agent-skills discover." },
|
|
873354
|
+
{ id: "enabled", label: "Enable now", value: "yes", required: false, multiline: false, hint: "yes/no." },
|
|
873355
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /agent-skills import-discovered with --yes." }
|
|
873356
|
+
]
|
|
873357
|
+
};
|
|
873358
|
+
}
|
|
873359
|
+
if (kind2 === "persona-discovery-import") {
|
|
873360
|
+
return {
|
|
873361
|
+
kind: kind2,
|
|
873362
|
+
mode: "create",
|
|
873363
|
+
title: "Import Discovered Persona",
|
|
873364
|
+
selectedFieldIndex: 0,
|
|
873365
|
+
message: "Import one discovered persona markdown file into the Agent-local persona registry. Type yes on the final field to confirm.",
|
|
873366
|
+
fields: [
|
|
873367
|
+
{ id: "name", label: "Discovered persona", value: "", required: true, multiline: false, hint: "Name shown by /personas discover." },
|
|
873368
|
+
{ id: "use", label: "Use now", value: "yes", required: false, multiline: false, hint: "yes/no." },
|
|
873369
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /personas import-discovered with --yes." }
|
|
873370
|
+
]
|
|
873371
|
+
};
|
|
873372
|
+
}
|
|
873373
|
+
if (kind2 === "routine-discovery-import") {
|
|
873374
|
+
return {
|
|
873375
|
+
kind: kind2,
|
|
873376
|
+
mode: "create",
|
|
873377
|
+
title: "Import Discovered Routine",
|
|
873378
|
+
selectedFieldIndex: 0,
|
|
873379
|
+
message: "Import one discovered routine markdown file into the Agent-local routine registry. Type yes on the final field to confirm.",
|
|
873380
|
+
fields: [
|
|
873381
|
+
{ id: "name", label: "Discovered routine", value: "", required: true, multiline: false, hint: "Name shown by /routines discover." },
|
|
873382
|
+
{ id: "enabled", label: "Enable now", value: "yes", required: false, multiline: false, hint: "yes/no." },
|
|
873383
|
+
{ id: "confirm", label: "Confirm", value: "", required: true, multiline: false, hint: "Type yes to run /routines import-discovered with --yes." }
|
|
873384
|
+
]
|
|
873385
|
+
};
|
|
873386
|
+
}
|
|
873387
|
+
return {
|
|
873388
|
+
kind: kind2,
|
|
873389
|
+
mode: "create",
|
|
873390
|
+
title: "Create Skill Bundle",
|
|
873391
|
+
selectedFieldIndex: 0,
|
|
873392
|
+
message: "Group existing local skills into a reviewable bundle that can be enabled together.",
|
|
873393
|
+
fields: [
|
|
873394
|
+
{ id: "name", label: "Bundle name", value: "", required: true, multiline: false, hint: "Short bundle name." },
|
|
873395
|
+
{ id: "description", label: "Description", value: "", required: true, multiline: false, hint: "One-line bundle summary." },
|
|
873396
|
+
{ id: "skills", label: "Skill ids", value: "", required: true, multiline: false, hint: "Comma-separated existing local skill ids." },
|
|
873397
|
+
{ id: "enabled", label: "Enable now", value: "yes", required: false, multiline: false, hint: "yes/no." }
|
|
873398
|
+
]
|
|
873399
|
+
};
|
|
873400
|
+
}
|
|
873401
|
+
|
|
872489
873402
|
// src/input/agent-workspace-knowledge-query-editor.ts
|
|
872490
873403
|
function createAgentKnowledgeQueryEditor(mode) {
|
|
872491
873404
|
return {
|
|
@@ -872909,6 +873822,7 @@ var AGENT_WORKSPACE_CATEGORIES = [
|
|
|
872909
873822
|
{ id: "setup-provider-model", label: "Provider and model", detail: "Choose the provider/model route for normal assistant chat.", command: "/model", kind: "command", safety: "safe" },
|
|
872910
873823
|
{ id: "setup-agent-knowledge", label: "Agent Knowledge", detail: "Inspect the isolated Agent Knowledge store before ingesting source-backed material.", command: "/knowledge status", kind: "command", safety: "read-only" },
|
|
872911
873824
|
{ id: "setup-runtime-profiles", label: "Agent profiles", detail: "Browse starter templates for isolated Agent homes and operator identities.", command: "/agent-profile templates", kind: "command", safety: "read-only" },
|
|
873825
|
+
{ id: "setup-profile-from-discovered", label: "Profile from discovered behavior", detail: "Create an isolated Agent profile directly from reviewed local persona, skill, and routine files.", editorKind: "profile-from-discovered", kind: "editor", safety: "safe" },
|
|
872912
873826
|
{ id: "setup-personas", label: "Personas", detail: "Create or select the active local Agent persona.", targetCategoryId: "personas", kind: "workspace", safety: "safe" },
|
|
872913
873827
|
{ id: "setup-skills", label: "Skills", detail: "Create, review, and enable reusable local Agent skills.", targetCategoryId: "skills", kind: "workspace", safety: "safe" },
|
|
872914
873828
|
{ id: "setup-routines", label: "Routines", detail: "Create, review, and enable local Agent routines before any explicit schedule promotion.", targetCategoryId: "routines", kind: "workspace", safety: "safe" },
|
|
@@ -873000,6 +873914,8 @@ var AGENT_WORKSPACE_CATEGORIES = [
|
|
|
873000
873914
|
{ id: "runtime-profile-list", label: "List Agent profiles", detail: "List isolated Agent profile homes under this Agent home.", command: "/agent-profile list", kind: "command", safety: "read-only" },
|
|
873001
873915
|
{ id: "runtime-profile-template-export", label: "Export starter template", detail: "Open an in-workspace form that exports a starter template JSON file for review and customization.", editorKind: "profile-template-export", kind: "editor", safety: "safe" },
|
|
873002
873916
|
{ id: "runtime-profile-template-import", label: "Import starter template", detail: "Open an in-workspace form that imports a reviewed starter template JSON file into this Agent home.", editorKind: "profile-template-import", kind: "editor", safety: "safe" },
|
|
873917
|
+
{ id: "runtime-profile-template-from-discovered", label: "Starter from discovered behavior", detail: "Open an in-workspace form that creates one local starter template from reviewed discovered persona, skill, and routine files.", editorKind: "profile-template-from-discovered", kind: "editor", safety: "safe" },
|
|
873918
|
+
{ id: "runtime-profile-from-discovered", label: "Profile from discovered behavior", detail: "Open an in-workspace form that creates a local starter and isolated Agent profile from reviewed discovered behavior files.", editorKind: "profile-from-discovered", kind: "editor", safety: "safe" },
|
|
873003
873919
|
{ id: "runtime-profile-create", label: "Create Agent profile", detail: "Open an in-workspace form that creates an isolated Agent home from a built-in or local starter.", editorKind: "profile", kind: "editor", safety: "safe" },
|
|
873004
873920
|
{ id: "runtime-profile-template-edit", label: "Customize starter", detail: "Open the starter export form, edit the JSON file, then import it as a local starter.", editorKind: "profile-template-export", kind: "editor", safety: "safe" },
|
|
873005
873921
|
{ id: "runtime-profile-switch", label: "Switch Agent profile", detail: "Launch goodvibes-agent --agent-profile NAME to use that isolated Agent home. This workspace cannot switch the current process home after startup.", kind: "guidance", safety: "safe" }
|
|
@@ -873034,6 +873950,8 @@ var AGENT_WORKSPACE_CATEGORIES = [
|
|
|
873034
873950
|
actions: [
|
|
873035
873951
|
{ id: "personas-list", label: "List personas", detail: "Print the full local persona library.", command: "/personas list", kind: "command", safety: "read-only" },
|
|
873036
873952
|
{ 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" },
|
|
873953
|
+
{ 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" },
|
|
873954
|
+
{ 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
873955
|
{ 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
873956
|
{ 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
873957
|
{ 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 +873994,8 @@ var AGENT_WORKSPACE_CATEGORIES = [
|
|
|
873076
873994
|
actions: [
|
|
873077
873995
|
{ id: "routines-list", label: "List routines", detail: "Print the full local Agent routine library.", command: "/routines list", kind: "command", safety: "read-only" },
|
|
873078
873996
|
{ id: "routines-enabled", label: "Enabled routines", detail: "Show routines available for direct use.", command: "/routines enabled", kind: "command", safety: "read-only" },
|
|
873997
|
+
{ 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" },
|
|
873998
|
+
{ 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
873999
|
{ 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
874000
|
{ 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
874001
|
{ 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" },
|
|
@@ -874503,6 +875423,33 @@ function getOnboardingWizardVisibleFieldCount(viewportHeight) {
|
|
|
874503
875423
|
}
|
|
874504
875424
|
|
|
874505
875425
|
// src/input/onboarding/onboarding-wizard-operator-steps.ts
|
|
875426
|
+
function discoveryCount(discovery) {
|
|
875427
|
+
if (!discovery)
|
|
875428
|
+
return 0;
|
|
875429
|
+
return discovery.personas.count + discovery.skills.count + discovery.routines.count;
|
|
875430
|
+
}
|
|
875431
|
+
function discoverySummary(discovery) {
|
|
875432
|
+
if (!discovery || discoveryCount(discovery) === 0)
|
|
875433
|
+
return "No importable local behavior files found yet";
|
|
875434
|
+
return [
|
|
875435
|
+
`${discovery.personas.count} persona file(s)`,
|
|
875436
|
+
`${discovery.skills.count} skill file(s)`,
|
|
875437
|
+
`${discovery.routines.count} routine file(s)`
|
|
875438
|
+
].join("; ");
|
|
875439
|
+
}
|
|
875440
|
+
function discoverySample(discovery) {
|
|
875441
|
+
if (!discovery)
|
|
875442
|
+
return "";
|
|
875443
|
+
const names2 = [
|
|
875444
|
+
...discovery.personas.names,
|
|
875445
|
+
...discovery.skills.names,
|
|
875446
|
+
...discovery.routines.names
|
|
875447
|
+
].slice(0, 4);
|
|
875448
|
+
if (names2.length === 0)
|
|
875449
|
+
return "Use /personas discover, /agent-skills discover, and /routines discover after setup to rescan.";
|
|
875450
|
+
const remaining = discoveryCount(discovery) > names2.length ? `, +${discoveryCount(discovery) - names2.length} more` : "";
|
|
875451
|
+
return `Import candidates: ${names2.join(", ")}${remaining}.`;
|
|
875452
|
+
}
|
|
874506
875453
|
function buildCommunicationStep() {
|
|
874507
875454
|
return {
|
|
874508
875455
|
id: "agent-communication",
|
|
@@ -874628,15 +875575,17 @@ function buildAgentKnowledgeStep() {
|
|
|
874628
875575
|
]
|
|
874629
875576
|
};
|
|
874630
875577
|
}
|
|
874631
|
-
function buildLocalStateStep() {
|
|
875578
|
+
function buildLocalStateStep(discovery) {
|
|
875579
|
+
const discoveredCount = discoveryCount(discovery);
|
|
874632
875580
|
return {
|
|
874633
875581
|
id: "agent-local-state",
|
|
874634
875582
|
title: "Local memory and behavior",
|
|
874635
|
-
shortLabel: "
|
|
874636
|
-
description: "Review the Agent-local behavior model. Memory, personas, skills, routines, and Agent profiles stay local until a stable shared registry exists.",
|
|
875583
|
+
shortLabel: "Behavior",
|
|
875584
|
+
description: discoveredCount > 0 ? "Review importable Agent-local behavior files, then create an isolated profile from them or import individual records." : "Review the Agent-local behavior model. Memory, personas, skills, routines, and Agent profiles stay local until a stable shared registry exists.",
|
|
874637
875585
|
summaryTitle: "Local Agent state",
|
|
874638
875586
|
summaryLines: [
|
|
874639
875587
|
"Memory/personas/skills/routines: local Agent registries",
|
|
875588
|
+
`Discovered behavior files: ${discoverySummary(discovery)}`,
|
|
874640
875589
|
"Secrets: rejected or stored by secret reference",
|
|
874641
875590
|
"Profiles: isolated Agent homes"
|
|
874642
875591
|
],
|
|
@@ -874652,22 +875601,22 @@ function buildLocalStateStep() {
|
|
|
874652
875601
|
kind: "status",
|
|
874653
875602
|
id: "agent-local-state.personas",
|
|
874654
875603
|
label: "Personas",
|
|
874655
|
-
hint: "Use /personas to create and activate serial operating modes for the main conversation.",
|
|
874656
|
-
defaultValue: "Local registry"
|
|
875604
|
+
hint: discovery?.personas.count && discovery.personas.count > 0 ? `${discovery.personas.count} persona file(s) are available. Use the Profiles workspace to create a profile from discovered behavior, or preview individual files with /personas discover.` : "Use /personas to create and activate serial operating modes for the main conversation.",
|
|
875605
|
+
defaultValue: discovery?.personas.count && discovery.personas.count > 0 ? `${discovery.personas.count} discovered` : "Local registry"
|
|
874657
875606
|
},
|
|
874658
875607
|
{
|
|
874659
875608
|
kind: "status",
|
|
874660
875609
|
id: "agent-local-state.skills",
|
|
874661
875610
|
label: "Skills",
|
|
874662
|
-
hint: "Use /agent-skills and /skills local to manage reusable Agent procedures.",
|
|
874663
|
-
defaultValue: "Local registry"
|
|
875611
|
+
hint: discovery?.skills.count && discovery.skills.count > 0 ? `${discovery.skills.count} skill file(s) are available. Use the Profiles workspace to create a profile from discovered behavior, or preview individual files with /agent-skills discover.` : "Use /agent-skills and /skills local to manage reusable Agent procedures.",
|
|
875612
|
+
defaultValue: discovery?.skills.count && discovery.skills.count > 0 ? `${discovery.skills.count} discovered` : "Local registry"
|
|
874664
875613
|
},
|
|
874665
875614
|
{
|
|
874666
875615
|
kind: "status",
|
|
874667
875616
|
id: "agent-local-state.routines",
|
|
874668
875617
|
label: "Routines",
|
|
874669
|
-
hint: "Use /routines for reusable local procedures. Starting a routine prints steps in the main conversation and does not spawn hidden work.",
|
|
874670
|
-
defaultValue: "Local registry"
|
|
875618
|
+
hint: discovery?.routines.count && discovery.routines.count > 0 ? `${discovery.routines.count} routine file(s) are available. Use the Profiles workspace to create a profile from discovered behavior, or preview individual files with /routines discover. ${discoverySample(discovery)}` : "Use /routines for reusable local procedures. Starting a routine prints steps in the main conversation and does not spawn hidden work.",
|
|
875619
|
+
defaultValue: discovery?.routines.count && discovery.routines.count > 0 ? `${discovery.routines.count} discovered` : "Local registry"
|
|
874671
875620
|
}
|
|
874672
875621
|
]
|
|
874673
875622
|
};
|
|
@@ -874816,7 +875765,7 @@ function buildOnboardingWizardSteps(controller) {
|
|
|
874816
875765
|
buildCommunicationStep(),
|
|
874817
875766
|
buildToolsStep(),
|
|
874818
875767
|
buildAgentKnowledgeStep(),
|
|
874819
|
-
buildLocalStateStep(),
|
|
875768
|
+
buildLocalStateStep(controller.runtimeSnapshot?.localBehaviorDiscovery),
|
|
874820
875769
|
buildAutomationStep(),
|
|
874821
875770
|
buildVoiceMediaStep(),
|
|
874822
875771
|
buildDelegationPolicyStep(),
|
|
@@ -877329,7 +878278,7 @@ function handleProfilePickerToken(state4, token) {
|
|
|
877329
878278
|
}
|
|
877330
878279
|
|
|
877331
878280
|
// src/input/handler-picker-routes.ts
|
|
877332
|
-
import { readFileSync as
|
|
878281
|
+
import { readFileSync as readFileSync87 } from "fs";
|
|
877333
878282
|
|
|
877334
878283
|
// src/renderer/model-picker-overlay.ts
|
|
877335
878284
|
var MODEL_PICKER_CHROME_LINES = 7;
|
|
@@ -877621,7 +878570,7 @@ function handleFilePickerToken(state4, token) {
|
|
|
877621
878570
|
throw new Error("working directory is unavailable");
|
|
877622
878571
|
}
|
|
877623
878572
|
const resolvedPath3 = resolveAndValidatePath(selected, projectRoot);
|
|
877624
|
-
const data =
|
|
878573
|
+
const data = readFileSync87(resolvedPath3);
|
|
877625
878574
|
const base644 = data.toString("base64");
|
|
877626
878575
|
const mediaType = state4.mediaTypeFromExt(ext);
|
|
877627
878576
|
const filename = selected.split("/").pop() ?? selected;
|
|
@@ -881121,6 +882070,29 @@ function setupChecklistLines(snapshot2) {
|
|
|
881121
882070
|
}
|
|
881122
882071
|
return lines;
|
|
881123
882072
|
}
|
|
882073
|
+
function discoverySummaryLine(label, summary, command8) {
|
|
882074
|
+
if (summary.count === 0)
|
|
882075
|
+
return [];
|
|
882076
|
+
const names2 = summary.names.length > 0 ? ` ${summary.names.join(", ")}${summary.count > summary.names.length ? `, +${summary.count - summary.names.length} more` : ""}.` : "";
|
|
882077
|
+
return [
|
|
882078
|
+
{ text: `${label}: ${summary.count} discovered; project ${summary.projectLocalCount}; global ${summary.globalCount}.`, fg: FULLSCREEN_PALETTE.info, bold: true },
|
|
882079
|
+
{ text: ` ${command8} to preview, then use the import form after review.${names2}`, fg: FULLSCREEN_PALETTE.muted }
|
|
882080
|
+
];
|
|
882081
|
+
}
|
|
882082
|
+
function behaviorDiscoveryLines(snapshot2) {
|
|
882083
|
+
const lines = [
|
|
882084
|
+
...discoverySummaryLine("Discovered personas", snapshot2.discoveredBehavior.personas, "/personas discover"),
|
|
882085
|
+
...discoverySummaryLine("Discovered skills", snapshot2.discoveredBehavior.skills, "/agent-skills discover"),
|
|
882086
|
+
...discoverySummaryLine("Discovered routines", snapshot2.discoveredBehavior.routines, "/routines discover")
|
|
882087
|
+
];
|
|
882088
|
+
if (lines.length === 0)
|
|
882089
|
+
return [];
|
|
882090
|
+
return [
|
|
882091
|
+
{ text: "" },
|
|
882092
|
+
{ text: "Discovered Behavior Files", fg: FULLSCREEN_PALETTE.title, bold: true },
|
|
882093
|
+
...lines
|
|
882094
|
+
];
|
|
882095
|
+
}
|
|
881124
882096
|
function localLibraryLines(title, items, emptyText, selectedId) {
|
|
881125
882097
|
const lines = [
|
|
881126
882098
|
{ text: title, fg: FULLSCREEN_PALETTE.title, bold: true }
|
|
@@ -881201,7 +882173,7 @@ function snapshotLines(workspace, category, snapshot2) {
|
|
|
881201
882173
|
if (category.id === "home") {
|
|
881202
882174
|
base2.push({ text: `Chat route: ${snapshot2.provider} / ${snapshot2.modelDisplayName}`, fg: FULLSCREEN_PALETTE.info }, { text: `Session: ${snapshot2.sessionId}`, fg: FULLSCREEN_PALETTE.muted }, { text: `Policy: ${snapshot2.executionPolicy}; WRFC ${snapshot2.wrfcPolicy}`, fg: FULLSCREEN_PALETTE.good });
|
|
881203
882175
|
} else if (category.id === "setup") {
|
|
881204
|
-
base2.push({ text: `Connection: ${snapshot2.runtimeBaseUrl}`, fg: FULLSCREEN_PALETTE.info }, { text: "Agent role: interactive operator TUI; setup changes here are Agent-local.", fg: FULLSCREEN_PALETTE.good }, ...setupChecklistLines(snapshot2), { text: "" }, { text: `Workspace: ${snapshot2.workingDirectory}`, fg: FULLSCREEN_PALETTE.muted }, { text: `Home: ${snapshot2.homeDirectory}`, fg: FULLSCREEN_PALETTE.muted });
|
|
882176
|
+
base2.push({ text: `Connection: ${snapshot2.runtimeBaseUrl}`, fg: FULLSCREEN_PALETTE.info }, { text: "Agent role: interactive operator TUI; setup changes here are Agent-local.", fg: FULLSCREEN_PALETTE.good }, ...setupChecklistLines(snapshot2), ...behaviorDiscoveryLines(snapshot2), { text: "" }, { text: `Workspace: ${snapshot2.workingDirectory}`, fg: FULLSCREEN_PALETTE.muted }, { text: `Home: ${snapshot2.homeDirectory}`, fg: FULLSCREEN_PALETTE.muted });
|
|
881205
882177
|
} else if (category.id === "channels") {
|
|
881206
882178
|
const enabledCount = snapshot2.channels.filter((channel) => channel.enabled).length;
|
|
881207
882179
|
const readyCount = snapshot2.channels.filter((channel) => channel.ready).length;
|
|
@@ -883063,7 +884035,7 @@ function wireShellUiOpeners(options) {
|
|
|
883063
884035
|
|
|
883064
884036
|
// src/cli/entrypoint.ts
|
|
883065
884037
|
import { existsSync as existsSync85 } from "fs";
|
|
883066
|
-
import { join as
|
|
884038
|
+
import { join as join102 } from "path";
|
|
883067
884039
|
// src/cli/parser.ts
|
|
883068
884040
|
var COMMAND_ALIASES = {
|
|
883069
884041
|
run: "run",
|
|
@@ -883427,14 +884399,14 @@ function parseGoodVibesCli(argv, binary2 = "goodvibes-agent") {
|
|
|
883427
884399
|
};
|
|
883428
884400
|
}
|
|
883429
884401
|
// src/cli/help.ts
|
|
883430
|
-
import { existsSync as existsSync79, readFileSync as
|
|
883431
|
-
import { dirname as dirname63, join as
|
|
884402
|
+
import { existsSync as existsSync79, readFileSync as readFileSync88 } from "fs";
|
|
884403
|
+
import { dirname as dirname63, join as join95 } from "path";
|
|
883432
884404
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
883433
884405
|
function readJsonVersion(path7) {
|
|
883434
884406
|
try {
|
|
883435
884407
|
if (!existsSync79(path7))
|
|
883436
884408
|
return null;
|
|
883437
|
-
const parsed = JSON.parse(
|
|
884409
|
+
const parsed = JSON.parse(readFileSync88(path7, "utf-8"));
|
|
883438
884410
|
return typeof parsed.version === "string" ? parsed.version : null;
|
|
883439
884411
|
} catch {
|
|
883440
884412
|
return null;
|
|
@@ -883442,7 +884414,7 @@ function readJsonVersion(path7) {
|
|
|
883442
884414
|
}
|
|
883443
884415
|
function getPackageVersion() {
|
|
883444
884416
|
const here = dirname63(fileURLToPath4(import.meta.url));
|
|
883445
|
-
return readJsonVersion(
|
|
884417
|
+
return readJsonVersion(join95(here, "..", "..", "package.json")) ?? VERSION;
|
|
883446
884418
|
}
|
|
883447
884419
|
function renderGoodVibesVersion(binary2 = "goodvibes-agent") {
|
|
883448
884420
|
return `${binary2} ${getPackageVersion()}`;
|
|
@@ -883574,14 +884546,16 @@ var COMMAND_HELP = {
|
|
|
883574
884546
|
examples: ["providers", "providers inspect openai-subscriber", "providers use openai openai:gpt-5.4"]
|
|
883575
884547
|
},
|
|
883576
884548
|
profiles: {
|
|
883577
|
-
usage: ["profiles list", "profiles templates", "profiles templates export <id> <path> --yes", "profiles templates import <path> --yes", "profiles show <name>", "profiles create <name> [--template <id>] --yes", "profiles delete <name> --yes", "--agent-profile <name>"],
|
|
884549
|
+
usage: ["profiles list", "profiles templates", "profiles templates from-discovered <id> --yes", "profiles create-from-discovered <name> --yes", "profiles templates export <id> <path> --yes", "profiles templates import <path> --yes", "profiles show <name>", "profiles create <name> [--template <id>] --yes", "profiles delete <name> --yes", "--agent-profile <name>"],
|
|
883578
884550
|
summary: "Create and inspect isolated Agent profile homes, with starter templates for household, research, travel, operations, personal productivity, and local imported starters. A profile changes Agent-local config, sessions, memory, personas, skills, routines, and setup paths without changing connected GoodVibes services.",
|
|
883579
|
-
examples: ["profiles templates", "profiles templates export research ./research-starter.json --yes", "profiles templates import ./research-starter.json --yes", "profiles create household --template household --yes", "--agent-profile household status"]
|
|
884551
|
+
examples: ["profiles templates", "profiles create-from-discovered research-desk --yes", "profiles templates from-discovered research-desk --yes", "profiles templates export research ./research-starter.json --yes", "profiles templates import ./research-starter.json --yes", "profiles create household --template household --yes", "--agent-profile household status"]
|
|
883580
884552
|
},
|
|
883581
884553
|
personas: {
|
|
883582
884554
|
usage: [
|
|
883583
884555
|
"personas list",
|
|
883584
884556
|
"personas active",
|
|
884557
|
+
"personas discover",
|
|
884558
|
+
"personas import-discovered <name> [--use] --yes",
|
|
883585
884559
|
"personas search <query>",
|
|
883586
884560
|
"personas show <id>",
|
|
883587
884561
|
"personas create --name <name> --description <summary> --body <instructions> [--tags a,b] [--triggers a,b] [--use]",
|
|
@@ -883595,6 +884569,8 @@ var COMMAND_HELP = {
|
|
|
883595
884569
|
summary: "Manage Agent-local personas for the serial main conversation. Personas do not spawn worker agents.",
|
|
883596
884570
|
examples: [
|
|
883597
884571
|
"personas list",
|
|
884572
|
+
"personas discover",
|
|
884573
|
+
'personas import-discovered "Travel Planner" --use --yes',
|
|
883598
884574
|
'personas create --name "Travel Planner" --description "Plan trips" --body "Compare options before booking" --use',
|
|
883599
884575
|
"personas review travel-planner",
|
|
883600
884576
|
"personas delete travel-planner --yes"
|
|
@@ -883660,15 +884636,19 @@ var COMMAND_HELP = {
|
|
|
883660
884636
|
usage: [
|
|
883661
884637
|
"routines list",
|
|
883662
884638
|
"routines enabled",
|
|
884639
|
+
"routines discover",
|
|
884640
|
+
"routines import-discovered <name> [--enabled] --yes",
|
|
883663
884641
|
"routines show <id>",
|
|
883664
884642
|
"routines receipts",
|
|
883665
884643
|
"routines reconcile",
|
|
883666
884644
|
"routines receipt <receipt-id>",
|
|
883667
884645
|
"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
884646
|
],
|
|
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.",
|
|
884647
|
+
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
884648
|
examples: [
|
|
883671
884649
|
"routines list",
|
|
884650
|
+
"routines discover",
|
|
884651
|
+
'routines import-discovered "Daily Brief" --enabled --yes',
|
|
883672
884652
|
"routines show daily-operations-sweep",
|
|
883673
884653
|
"routines receipts",
|
|
883674
884654
|
"routines reconcile",
|
|
@@ -884174,8 +885154,8 @@ function renderOnboardingCliStatus(options) {
|
|
|
884174
885154
|
`);
|
|
884175
885155
|
}
|
|
884176
885156
|
// src/cli/external-runtime.ts
|
|
884177
|
-
import { existsSync as existsSync80, readFileSync as
|
|
884178
|
-
import { join as
|
|
885157
|
+
import { existsSync as existsSync80, readFileSync as readFileSync89 } from "fs";
|
|
885158
|
+
import { join as join96 } from "path";
|
|
884179
885159
|
function isRecord29(value) {
|
|
884180
885160
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
884181
885161
|
}
|
|
@@ -884189,11 +885169,11 @@ function resolveBaseUrl2(configManager) {
|
|
|
884189
885169
|
return `http://${host}:${Number.isFinite(port) ? port : 3421}`;
|
|
884190
885170
|
}
|
|
884191
885171
|
function readOperatorToken(homeDirectory) {
|
|
884192
|
-
const path7 =
|
|
885172
|
+
const path7 = join96(homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
|
|
884193
885173
|
if (!existsSync80(path7))
|
|
884194
885174
|
return { token: null, path: path7 };
|
|
884195
885175
|
try {
|
|
884196
|
-
const parsed = JSON.parse(
|
|
885176
|
+
const parsed = JSON.parse(readFileSync89(path7, "utf-8"));
|
|
884197
885177
|
const token = isRecord29(parsed) && typeof parsed.token === "string" ? parsed.token : null;
|
|
884198
885178
|
return { token, path: path7 };
|
|
884199
885179
|
} catch {
|
|
@@ -884566,8 +885546,8 @@ function applyRuntimeCommandEndpointFlagOverrides(configManager, command8, flags
|
|
|
884566
885546
|
return [];
|
|
884567
885547
|
}
|
|
884568
885548
|
// src/cli/bundle-command.ts
|
|
884569
|
-
import { existsSync as existsSync82, mkdirSync as mkdirSync65, readFileSync as
|
|
884570
|
-
import { dirname as dirname64, join as
|
|
885549
|
+
import { existsSync as existsSync82, mkdirSync as mkdirSync65, readFileSync as readFileSync90, writeFileSync as writeFileSync56 } from "fs";
|
|
885550
|
+
import { dirname as dirname64, join as join98 } from "path";
|
|
884571
885551
|
|
|
884572
885552
|
// src/cli/provider-classification.ts
|
|
884573
885553
|
var SUBSCRIPTION_PROVIDERS = new Set([
|
|
@@ -884658,7 +885638,7 @@ function classifyProviderSetup(input) {
|
|
|
884658
885638
|
// src/cli/service-posture.ts
|
|
884659
885639
|
import { closeSync as closeSync4, existsSync as existsSync81, openSync as openSync4, readSync as readSync2, statSync as statSync21 } from "fs";
|
|
884660
885640
|
import net3 from "net";
|
|
884661
|
-
import { isAbsolute as isAbsolute13, join as
|
|
885641
|
+
import { isAbsolute as isAbsolute13, join as join97 } from "path";
|
|
884662
885642
|
|
|
884663
885643
|
// src/cli/redaction.ts
|
|
884664
885644
|
var REDACTED_VALUE = "<redacted>";
|
|
@@ -884828,7 +885808,7 @@ function resolveConfiguredLogPath(runtime3) {
|
|
|
884828
885808
|
const trimmed2 = value.trim();
|
|
884829
885809
|
if (!trimmed2)
|
|
884830
885810
|
return;
|
|
884831
|
-
return isAbsolute13(trimmed2) ? trimmed2 :
|
|
885811
|
+
return isAbsolute13(trimmed2) ? trimmed2 : join97(runtime3.homeDirectory, trimmed2);
|
|
884832
885812
|
}
|
|
884833
885813
|
function createExternalDaemonLifecycle(logPath) {
|
|
884834
885814
|
return {
|
|
@@ -884914,7 +885894,7 @@ function getNestedValue(source, key) {
|
|
|
884914
885894
|
}
|
|
884915
885895
|
function readJsonFile2(path7) {
|
|
884916
885896
|
try {
|
|
884917
|
-
return { ok: true, value: JSON.parse(
|
|
885897
|
+
return { ok: true, value: JSON.parse(readFileSync90(path7, "utf-8")) };
|
|
884918
885898
|
} catch (error51) {
|
|
884919
885899
|
return { ok: false, error: error51 instanceof Error ? error51.message : String(error51) };
|
|
884920
885900
|
}
|
|
@@ -884937,7 +885917,7 @@ function readAuthPosture(runtime3) {
|
|
|
884937
885917
|
});
|
|
884938
885918
|
const userStorePath = shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-users.json");
|
|
884939
885919
|
const bootstrapCredentialPath = shellPaths.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-bootstrap.txt");
|
|
884940
|
-
const operatorTokenPath =
|
|
885920
|
+
const operatorTokenPath = join98(runtime3.homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
|
|
884941
885921
|
return {
|
|
884942
885922
|
userStorePath,
|
|
884943
885923
|
userStorePresent: existsSync82(userStorePath),
|
|
@@ -885097,7 +886077,7 @@ async function handleBundleCommand(runtime3) {
|
|
|
885097
886077
|
}
|
|
885098
886078
|
// src/cli/management.ts
|
|
885099
886079
|
import { existsSync as existsSync84 } from "fs";
|
|
885100
|
-
import { join as
|
|
886080
|
+
import { join as join101 } from "path";
|
|
885101
886081
|
import { spawn as spawn5 } from "child_process";
|
|
885102
886082
|
import { networkInterfaces as networkInterfaces4 } from "os";
|
|
885103
886083
|
|
|
@@ -885124,7 +886104,7 @@ function formatProviderAuthRoute(route) {
|
|
|
885124
886104
|
|
|
885125
886105
|
// src/cli/management-commands.ts
|
|
885126
886106
|
import { mkdirSync as mkdirSync66, writeFileSync as writeFileSync57 } from "fs";
|
|
885127
|
-
import { dirname as dirname65, join as
|
|
886107
|
+
import { dirname as dirname65, join as join99 } from "path";
|
|
885128
886108
|
init_config8();
|
|
885129
886109
|
init_config8();
|
|
885130
886110
|
init_config8();
|
|
@@ -885441,7 +886421,7 @@ async function handleTasks(runtime3) {
|
|
|
885441
886421
|
});
|
|
885442
886422
|
}
|
|
885443
886423
|
async function renderPairing(runtime3) {
|
|
885444
|
-
const daemonHomeDir =
|
|
886424
|
+
const daemonHomeDir = join99(runtime3.homeDirectory, ".goodvibes", "daemon");
|
|
885445
886425
|
const tokenRecord = getOrCreateCompanionToken(GOODVIBES_AGENT_PAIRING_SURFACE, { daemonHomeDir });
|
|
885446
886426
|
const binding = resolveRuntimeEndpointBinding(runtime3.configManager, "controlPlane");
|
|
885447
886427
|
const daemonUrl = `http://${urlHostForBindHost2(binding.host)}:${binding.port}`;
|
|
@@ -885979,8 +886959,8 @@ var DELEGATION_METHOD = {
|
|
|
885979
886959
|
};
|
|
885980
886960
|
|
|
885981
886961
|
// src/cli/agent-knowledge-runtime.ts
|
|
885982
|
-
import { existsSync as existsSync83, readFileSync as
|
|
885983
|
-
import { join as
|
|
886962
|
+
import { existsSync as existsSync83, readFileSync as readFileSync91 } from "fs";
|
|
886963
|
+
import { join as join100 } from "path";
|
|
885984
886964
|
|
|
885985
886965
|
// node_modules/@pellux/goodvibes-sdk/dist/browser-scoped.js
|
|
885986
886966
|
init_dist();
|
|
@@ -886346,11 +887326,11 @@ function resolveDaemonConnection(runtime3) {
|
|
|
886346
887326
|
const host = String(runtime3.configManager.get("controlPlane.host") ?? "127.0.0.1");
|
|
886347
887327
|
const port = Number(runtime3.configManager.get("controlPlane.port") ?? 3421);
|
|
886348
887328
|
const baseUrl = `http://${host}:${Number.isFinite(port) ? port : 3421}`;
|
|
886349
|
-
const tokenPath =
|
|
887329
|
+
const tokenPath = join100(runtime3.homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
|
|
886350
887330
|
if (!existsSync83(tokenPath))
|
|
886351
887331
|
return { baseUrl, token: null, tokenPath };
|
|
886352
887332
|
try {
|
|
886353
|
-
const parsed = JSON.parse(
|
|
887333
|
+
const parsed = JSON.parse(readFileSync91(tokenPath, "utf-8"));
|
|
886354
887334
|
const token = isRecord31(parsed) && typeof parsed.token === "string" ? parsed.token : null;
|
|
886355
887335
|
return { baseUrl, token, tokenPath };
|
|
886356
887336
|
} catch {
|
|
@@ -887132,6 +888112,48 @@ function renderPersona2(persona, activePersonaId) {
|
|
|
887132
888112
|
].filter((line2) => Boolean(line2)).join(`
|
|
887133
888113
|
`);
|
|
887134
888114
|
}
|
|
888115
|
+
function summarizeDiscoveredPersona2(persona) {
|
|
888116
|
+
const description = persona.description ? ` - ${persona.description}` : "";
|
|
888117
|
+
return [
|
|
888118
|
+
` ${persona.name} ${persona.origin}${description}`,
|
|
888119
|
+
` path: ${persona.path}`
|
|
888120
|
+
].join(`
|
|
888121
|
+
`);
|
|
888122
|
+
}
|
|
888123
|
+
function renderDiscoveredPersonaList(personas) {
|
|
888124
|
+
if (personas.length === 0) {
|
|
888125
|
+
return [
|
|
888126
|
+
"Discovered Agent persona files",
|
|
888127
|
+
" No persona markdown files found in Agent persona folders.",
|
|
888128
|
+
" Search roots: .goodvibes/personas, .goodvibes/agent/personas, .goodvibes/agents, ~/.goodvibes/personas, ~/.goodvibes/agent/personas, ~/.goodvibes/agents"
|
|
888129
|
+
].join(`
|
|
888130
|
+
`);
|
|
888131
|
+
}
|
|
888132
|
+
return [
|
|
888133
|
+
`Discovered Agent persona files (${personas.length})`,
|
|
888134
|
+
...personas.map(summarizeDiscoveredPersona2),
|
|
888135
|
+
"",
|
|
888136
|
+
"Import one with: goodvibes-agent personas import-discovered <name> --yes"
|
|
888137
|
+
].join(`
|
|
888138
|
+
`);
|
|
888139
|
+
}
|
|
888140
|
+
function discoveredPersonaLookupValues2(persona) {
|
|
888141
|
+
const slug = persona.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
888142
|
+
const basename6 = persona.path.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
|
|
888143
|
+
return [persona.name, slug, persona.path, basename6].map((value) => value.trim().toLowerCase()).filter(Boolean);
|
|
888144
|
+
}
|
|
888145
|
+
function findDiscoveredPersona2(personas, idOrName) {
|
|
888146
|
+
const lookup = idOrName.trim().toLowerCase();
|
|
888147
|
+
if (!lookup)
|
|
888148
|
+
return null;
|
|
888149
|
+
return personas.find((persona) => discoveredPersonaLookupValues2(persona).includes(lookup)) ?? null;
|
|
888150
|
+
}
|
|
888151
|
+
function discoveredPersonaFrontmatterList(persona, key) {
|
|
888152
|
+
const value = persona.frontmatter[key];
|
|
888153
|
+
if (!value)
|
|
888154
|
+
return [];
|
|
888155
|
+
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
888156
|
+
}
|
|
887135
888157
|
function summarizeSkill2(skill) {
|
|
887136
888158
|
const enabled = skill.enabled ? "enabled" : "disabled";
|
|
887137
888159
|
const tags = skill.tags.length > 0 ? ` tags=${skill.tags.join(",")}` : "";
|
|
@@ -887255,7 +888277,7 @@ function renderBundle2(bundle) {
|
|
|
887255
888277
|
`);
|
|
887256
888278
|
}
|
|
887257
888279
|
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]";
|
|
888280
|
+
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
888281
|
}
|
|
887260
888282
|
function usageSkills() {
|
|
887261
888283
|
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 +888306,45 @@ async function handlePersonasCommand(runtime3) {
|
|
|
887284
888306
|
return failure(runtime3, "agent.personas.active_missing", "No active Agent persona.", 1);
|
|
887285
888307
|
return success3(runtime3, "agent.personas.active", active, renderPersona2(active, active.id));
|
|
887286
888308
|
}
|
|
888309
|
+
if (normalized === "discover") {
|
|
888310
|
+
const discovered = await discoverPersonas(shellPaths(runtime3));
|
|
888311
|
+
return success3(runtime3, "agent.personas.discover", { personas: discovered }, renderDiscoveredPersonaList(discovered));
|
|
888312
|
+
}
|
|
888313
|
+
if (normalized === "import-discovered" || normalized === "import-persona") {
|
|
888314
|
+
const options = parseOptions(rest);
|
|
888315
|
+
const name51 = options.positionals.join(" ").trim();
|
|
888316
|
+
if (!name51)
|
|
888317
|
+
return failure(runtime3, "invalid_persona_command", "Usage: goodvibes-agent personas import-discovered <name> [--use] --yes", 2);
|
|
888318
|
+
const discovered = findDiscoveredPersona2(await discoverPersonas(shellPaths(runtime3)), name51);
|
|
888319
|
+
if (!discovered) {
|
|
888320
|
+
return failure(runtime3, "persona_discovery_not_found", `Unknown discovered Agent persona: ${name51}
|
|
888321
|
+
Run goodvibes-agent personas discover to inspect available persona files.`, 1);
|
|
888322
|
+
}
|
|
888323
|
+
if (!hasFlag3(options, "yes")) {
|
|
888324
|
+
return success3(runtime3, "agent.personas.import_discovered.preview", { persona: discovered }, [
|
|
888325
|
+
"Agent persona import preview",
|
|
888326
|
+
` name: ${discovered.name}`,
|
|
888327
|
+
` origin: ${discovered.origin}`,
|
|
888328
|
+
` path: ${discovered.path}`,
|
|
888329
|
+
` description: ${discovered.description || "(none)"}`,
|
|
888330
|
+
` body characters: ${discovered.body.length}`,
|
|
888331
|
+
" next: rerun with --yes to import into the Agent-local persona registry"
|
|
888332
|
+
].join(`
|
|
888333
|
+
`));
|
|
888334
|
+
}
|
|
888335
|
+
const persona = registry5.create({
|
|
888336
|
+
name: discovered.name,
|
|
888337
|
+
description: discovered.description || `Imported persona from ${discovered.origin} markdown file.`,
|
|
888338
|
+
body: discovered.body,
|
|
888339
|
+
tags: discoveredPersonaFrontmatterList(discovered, "tags"),
|
|
888340
|
+
triggers: discoveredPersonaFrontmatterList(discovered, "triggers"),
|
|
888341
|
+
source: "imported",
|
|
888342
|
+
provenance: `discovered:${discovered.origin}:${discovered.path}`
|
|
888343
|
+
});
|
|
888344
|
+
if (hasFlag3(options, "use"))
|
|
888345
|
+
registry5.setActive(persona.id);
|
|
888346
|
+
return success3(runtime3, "agent.personas.import_discovered", persona, `Imported Agent persona ${persona.id}: ${persona.name}${hasFlag3(options, "use") ? " (active)" : ""}`);
|
|
888347
|
+
}
|
|
887287
888348
|
if (normalized === "search" || normalized === "find") {
|
|
887288
888349
|
const query2 = rest.join(" ").trim();
|
|
887289
888350
|
const results = registry5.search(query2);
|
|
@@ -887597,7 +888658,7 @@ Run goodvibes-agent skills discover to inspect available skill files.`, 1);
|
|
|
887597
888658
|
}
|
|
887598
888659
|
|
|
887599
888660
|
// src/cli/memory-command.ts
|
|
887600
|
-
import { mkdirSync as mkdirSync67, readFileSync as
|
|
888661
|
+
import { mkdirSync as mkdirSync67, readFileSync as readFileSync92, writeFileSync as writeFileSync58 } from "fs";
|
|
887601
888662
|
import { dirname as dirname66, resolve as resolve40 } from "path";
|
|
887602
888663
|
init_state3();
|
|
887603
888664
|
var VALID_CLASSES2 = ["decision", "constraint", "incident", "pattern", "fact", "risk", "runbook", "architecture", "ownership"];
|
|
@@ -887877,7 +888938,7 @@ function isMemoryBundle(value) {
|
|
|
887877
888938
|
return value.schemaVersion === "v1" && typeof value.exportedAt === "number" && (value.scope === "all" || typeof value.scope === "string" && isMemoryScope2(value.scope)) && typeof value.recordCount === "number" && typeof value.linkCount === "number" && Array.isArray(value.records) && value.records.every(isMemoryRecord) && Array.isArray(value.links) && value.links.every(isMemoryLink);
|
|
887878
888939
|
}
|
|
887879
888940
|
function readBundle(path7) {
|
|
887880
|
-
const parsed = JSON.parse(
|
|
888941
|
+
const parsed = JSON.parse(readFileSync92(path7, "utf-8"));
|
|
887881
888942
|
if (!isMemoryBundle(parsed))
|
|
887882
888943
|
throw new Error("Invalid Agent memory bundle.");
|
|
887883
888944
|
for (const record2 of parsed.records) {
|
|
@@ -888200,6 +889261,12 @@ function parseTemplate(args2) {
|
|
|
888200
889261
|
return normalized;
|
|
888201
889262
|
throw new Error(`Unknown Agent starter profile template: ${raw}. Use profiles templates to list starters.`);
|
|
888202
889263
|
}
|
|
889264
|
+
function parseCsvFlag2(args2, names2) {
|
|
889265
|
+
const raw = flagValue2(args2, names2);
|
|
889266
|
+
if (!raw)
|
|
889267
|
+
return;
|
|
889268
|
+
return raw.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
889269
|
+
}
|
|
888203
889270
|
function profileLine2(profile5) {
|
|
888204
889271
|
const created = profile5.createdAt ? ` created=${profile5.createdAt}` : "";
|
|
888205
889272
|
const starter = profile5.starterTemplateId ? ` starter=${profile5.starterTemplateId}` : "";
|
|
@@ -888250,6 +889317,29 @@ function renderProfilesResult(result2) {
|
|
|
888250
889317
|
` source: ${result2.data.template.source}`,
|
|
888251
889318
|
` use: goodvibes-agent profiles create <name> --template ${result2.data.template.id} --yes`
|
|
888252
889319
|
].join(`
|
|
889320
|
+
`);
|
|
889321
|
+
}
|
|
889322
|
+
if (result2.kind === "agent.profiles.template.from_discovered" && result2.data?.template) {
|
|
889323
|
+
return [
|
|
889324
|
+
`Agent starter template created from discovered behavior: ${result2.data.template.id}`,
|
|
889325
|
+
` name: ${result2.data.template.name}`,
|
|
889326
|
+
` persona: ${result2.data.template.personaName}`,
|
|
889327
|
+
` skills: ${result2.data.template.skillNames.join(", ")}`,
|
|
889328
|
+
` routines: ${result2.data.template.routineNames.join(", ")}`,
|
|
889329
|
+
` use: goodvibes-agent profiles create <name> --template ${result2.data.template.id} --yes`
|
|
889330
|
+
].join(`
|
|
889331
|
+
`);
|
|
889332
|
+
}
|
|
889333
|
+
if (result2.kind === "agent.profiles.create_from_discovered" && result2.data?.profile && result2.data.template) {
|
|
889334
|
+
return [
|
|
889335
|
+
`Agent profile created from discovered behavior: ${result2.data.profile.id}`,
|
|
889336
|
+
` home: ${result2.data.profile.homeDirectory}`,
|
|
889337
|
+
` starter: ${result2.data.template.id}`,
|
|
889338
|
+
` persona: ${result2.data.template.personaName}`,
|
|
889339
|
+
` skills: ${result2.data.template.skillNames.join(", ")}`,
|
|
889340
|
+
` routines: ${result2.data.template.routineNames.join(", ")}`,
|
|
889341
|
+
` launch: ${result2.data.nextCommand ?? `goodvibes-agent --agent-profile ${result2.data.profile.id}`}`
|
|
889342
|
+
].join(`
|
|
888253
889343
|
`);
|
|
888254
889344
|
}
|
|
888255
889345
|
const profile5 = result2.data?.profile;
|
|
@@ -888293,6 +889383,51 @@ async function handleProfilesCommand(runtime3) {
|
|
|
888293
889383
|
}
|
|
888294
889384
|
if (sub === "templates" || sub === "starters") {
|
|
888295
889385
|
const [templateAction, templateId, templatePath] = values2;
|
|
889386
|
+
if (templateAction === "from-discovered" || templateAction === "import-discovered") {
|
|
889387
|
+
if (!templateId) {
|
|
889388
|
+
const result5 = {
|
|
889389
|
+
ok: false,
|
|
889390
|
+
kind: "agent.profiles.error",
|
|
889391
|
+
error: "Usage: goodvibes-agent profiles templates from-discovered <id> [--name <name>] [--description <summary>] [--persona <name>] [--skills all|name,name] [--routines all|name,name] [--replace] --yes"
|
|
889392
|
+
};
|
|
889393
|
+
return {
|
|
889394
|
+
output: renderProfilesOutput(result5, runtime3.cli.flags.outputFormat),
|
|
889395
|
+
exitCode: 2
|
|
889396
|
+
};
|
|
889397
|
+
}
|
|
889398
|
+
if (!hasYes(rawRest)) {
|
|
889399
|
+
const result5 = {
|
|
889400
|
+
ok: false,
|
|
889401
|
+
kind: "agent.profiles.error",
|
|
889402
|
+
error: `Refusing to create Agent starter template ${templateId} from discovered behavior without --yes.`
|
|
889403
|
+
};
|
|
889404
|
+
return {
|
|
889405
|
+
output: renderProfilesOutput(result5, runtime3.cli.flags.outputFormat),
|
|
889406
|
+
exitCode: 2
|
|
889407
|
+
};
|
|
889408
|
+
}
|
|
889409
|
+
const template = await createAgentRuntimeProfileTemplateFromDiscovered({
|
|
889410
|
+
homeDirectory: runtime3.homeDirectory,
|
|
889411
|
+
workingDirectory: runtime3.workingDirectory
|
|
889412
|
+
}, {
|
|
889413
|
+
id: templateId,
|
|
889414
|
+
name: flagValue2(rawRest, ["--name"]) ?? undefined,
|
|
889415
|
+
description: flagValue2(rawRest, ["--description"]) ?? undefined,
|
|
889416
|
+
persona: flagValue2(rawRest, ["--persona"]) ?? undefined,
|
|
889417
|
+
skills: parseCsvFlag2(rawRest, ["--skills"]),
|
|
889418
|
+
routines: parseCsvFlag2(rawRest, ["--routines"]),
|
|
889419
|
+
replace: hasYes(rawRest) && rawRest.includes("--replace")
|
|
889420
|
+
});
|
|
889421
|
+
const result4 = {
|
|
889422
|
+
ok: true,
|
|
889423
|
+
kind: "agent.profiles.template.from_discovered",
|
|
889424
|
+
data: { template }
|
|
889425
|
+
};
|
|
889426
|
+
return {
|
|
889427
|
+
output: renderProfilesOutput(result4, runtime3.cli.flags.outputFormat),
|
|
889428
|
+
exitCode: 0
|
|
889429
|
+
};
|
|
889430
|
+
}
|
|
888296
889431
|
if (templateAction === "export") {
|
|
888297
889432
|
if (!templateId || !templatePath) {
|
|
888298
889433
|
const result5 = {
|
|
@@ -888439,6 +889574,58 @@ async function handleProfilesCommand(runtime3) {
|
|
|
888439
889574
|
exitCode: 0
|
|
888440
889575
|
};
|
|
888441
889576
|
}
|
|
889577
|
+
if (sub === "create-from-discovered" || sub === "create-discovered") {
|
|
889578
|
+
const name51 = values2[0];
|
|
889579
|
+
if (!name51) {
|
|
889580
|
+
const result4 = {
|
|
889581
|
+
ok: false,
|
|
889582
|
+
kind: "agent.profiles.error",
|
|
889583
|
+
error: "Usage: goodvibes-agent profiles create-from-discovered <name> [--template-id <id>] [--profile-name <display>] [--description <summary>] [--persona <name>] [--skills all|name,name] [--routines all|name,name] [--replace] --yes"
|
|
889584
|
+
};
|
|
889585
|
+
return {
|
|
889586
|
+
output: renderProfilesOutput(result4, runtime3.cli.flags.outputFormat),
|
|
889587
|
+
exitCode: 2
|
|
889588
|
+
};
|
|
889589
|
+
}
|
|
889590
|
+
if (!hasYes(rawRest)) {
|
|
889591
|
+
const result4 = {
|
|
889592
|
+
ok: false,
|
|
889593
|
+
kind: "agent.profiles.error",
|
|
889594
|
+
error: `Refusing to create Agent profile ${name51} from discovered behavior without --yes.`
|
|
889595
|
+
};
|
|
889596
|
+
return {
|
|
889597
|
+
output: renderProfilesOutput(result4, runtime3.cli.flags.outputFormat),
|
|
889598
|
+
exitCode: 2
|
|
889599
|
+
};
|
|
889600
|
+
}
|
|
889601
|
+
const created = await createAgentRuntimeProfileFromDiscovered({
|
|
889602
|
+
homeDirectory: runtime3.homeDirectory,
|
|
889603
|
+
workingDirectory: runtime3.workingDirectory
|
|
889604
|
+
}, {
|
|
889605
|
+
profileName: name51,
|
|
889606
|
+
templateId: flagValue2(rawRest, ["--template-id", "--starter-id"]) ?? undefined,
|
|
889607
|
+
name: flagValue2(rawRest, ["--profile-name", "--name"]) ?? undefined,
|
|
889608
|
+
description: flagValue2(rawRest, ["--description"]) ?? undefined,
|
|
889609
|
+
persona: flagValue2(rawRest, ["--persona"]) ?? undefined,
|
|
889610
|
+
skills: parseCsvFlag2(rawRest, ["--skills"]),
|
|
889611
|
+
routines: parseCsvFlag2(rawRest, ["--routines"]),
|
|
889612
|
+
replace: rawRest.includes("--replace")
|
|
889613
|
+
});
|
|
889614
|
+
const result3 = {
|
|
889615
|
+
ok: true,
|
|
889616
|
+
kind: "agent.profiles.create_from_discovered",
|
|
889617
|
+
data: {
|
|
889618
|
+
profile: created.profile,
|
|
889619
|
+
appliedTemplate: created.profile.starterTemplateApplication,
|
|
889620
|
+
template: created.template,
|
|
889621
|
+
nextCommand: `goodvibes-agent --agent-profile ${created.profile.id}`
|
|
889622
|
+
}
|
|
889623
|
+
};
|
|
889624
|
+
return {
|
|
889625
|
+
output: renderProfilesOutput(result3, runtime3.cli.flags.outputFormat),
|
|
889626
|
+
exitCode: 0
|
|
889627
|
+
};
|
|
889628
|
+
}
|
|
888442
889629
|
if (sub === "delete" || sub === "remove") {
|
|
888443
889630
|
const name51 = values2[0];
|
|
888444
889631
|
if (!name51) {
|
|
@@ -888511,17 +889698,87 @@ function routineRegistry(runtime3) {
|
|
|
888511
889698
|
homeDirectory: runtime3.homeDirectory
|
|
888512
889699
|
}));
|
|
888513
889700
|
}
|
|
889701
|
+
function shellPaths2(runtime3) {
|
|
889702
|
+
return createShellPathService2({
|
|
889703
|
+
workingDirectory: runtime3.workingDirectory,
|
|
889704
|
+
homeDirectory: runtime3.homeDirectory
|
|
889705
|
+
});
|
|
889706
|
+
}
|
|
888514
889707
|
function routineReceiptStore(runtime3) {
|
|
888515
889708
|
return RoutineScheduleReceiptStore.fromShellPaths(createShellPathService2({
|
|
888516
889709
|
workingDirectory: runtime3.workingDirectory,
|
|
888517
889710
|
homeDirectory: runtime3.homeDirectory
|
|
888518
889711
|
}));
|
|
888519
889712
|
}
|
|
889713
|
+
function splitList6(value) {
|
|
889714
|
+
if (!value)
|
|
889715
|
+
return [];
|
|
889716
|
+
return value.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
889717
|
+
}
|
|
889718
|
+
function parseImportFlags(args2) {
|
|
889719
|
+
const positionals = [];
|
|
889720
|
+
let enabled = false;
|
|
889721
|
+
let yes = false;
|
|
889722
|
+
for (const arg of args2) {
|
|
889723
|
+
if (arg === "--enabled") {
|
|
889724
|
+
enabled = true;
|
|
889725
|
+
continue;
|
|
889726
|
+
}
|
|
889727
|
+
if (arg === "--yes") {
|
|
889728
|
+
yes = true;
|
|
889729
|
+
continue;
|
|
889730
|
+
}
|
|
889731
|
+
positionals.push(arg);
|
|
889732
|
+
}
|
|
889733
|
+
return { name: positionals.join(" ").trim(), enabled, yes };
|
|
889734
|
+
}
|
|
888520
889735
|
function summarizeRoutine2(routine) {
|
|
888521
889736
|
const enabled = routine.enabled ? "enabled" : "disabled";
|
|
888522
889737
|
const tags = routine.tags.length > 0 ? ` tags=${routine.tags.join(",")}` : "";
|
|
888523
889738
|
return ` ${routine.id} ${enabled} ${routine.reviewState} starts=${routine.startCount} ${routine.name} - ${routine.description}${tags}`;
|
|
888524
889739
|
}
|
|
889740
|
+
function summarizeDiscoveredRoutine2(routine) {
|
|
889741
|
+
const description = routine.description ? ` - ${routine.description}` : "";
|
|
889742
|
+
return [
|
|
889743
|
+
` ${routine.name} ${routine.origin}${description}`,
|
|
889744
|
+
` path: ${routine.path}`
|
|
889745
|
+
].join(`
|
|
889746
|
+
`);
|
|
889747
|
+
}
|
|
889748
|
+
function renderDiscoveredRoutineList(routines) {
|
|
889749
|
+
if (routines.length === 0) {
|
|
889750
|
+
return [
|
|
889751
|
+
"Discovered Agent routine files",
|
|
889752
|
+
" No routine markdown files found in Agent routine folders.",
|
|
889753
|
+
" Search roots: .goodvibes/routines, .goodvibes/agent/routines, ~/.goodvibes/routines, ~/.goodvibes/agent/routines"
|
|
889754
|
+
].join(`
|
|
889755
|
+
`);
|
|
889756
|
+
}
|
|
889757
|
+
return [
|
|
889758
|
+
`Discovered Agent routine files (${routines.length})`,
|
|
889759
|
+
...routines.map(summarizeDiscoveredRoutine2),
|
|
889760
|
+
"",
|
|
889761
|
+
"Import one with: goodvibes-agent routines import-discovered <name> --yes"
|
|
889762
|
+
].join(`
|
|
889763
|
+
`);
|
|
889764
|
+
}
|
|
889765
|
+
function discoveredRoutineLookupValues2(routine) {
|
|
889766
|
+
const slug = routine.name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
889767
|
+
const basename6 = routine.path.split(/[\\/]/).pop()?.replace(/\.md$/i, "") ?? "";
|
|
889768
|
+
return [routine.name, slug, routine.path, basename6].map((value) => value.trim().toLowerCase()).filter(Boolean);
|
|
889769
|
+
}
|
|
889770
|
+
function findDiscoveredRoutine2(routines, idOrName) {
|
|
889771
|
+
const lookup = idOrName.trim().toLowerCase();
|
|
889772
|
+
if (!lookup)
|
|
889773
|
+
return null;
|
|
889774
|
+
return routines.find((routine) => discoveredRoutineLookupValues2(routine).includes(lookup)) ?? null;
|
|
889775
|
+
}
|
|
889776
|
+
function discoveredRoutineFrontmatterList(routine, key) {
|
|
889777
|
+
const value = routine.frontmatter[key];
|
|
889778
|
+
if (!value)
|
|
889779
|
+
return [];
|
|
889780
|
+
return splitList6(value);
|
|
889781
|
+
}
|
|
888525
889782
|
function renderRoutineList(title, path7, routines) {
|
|
888526
889783
|
if (routines.length === 0) {
|
|
888527
889784
|
return [
|
|
@@ -888640,6 +889897,84 @@ async function handleRoutinesCommand(runtime3) {
|
|
|
888640
889897
|
exitCode: 0
|
|
888641
889898
|
};
|
|
888642
889899
|
}
|
|
889900
|
+
if (normalized === "discover") {
|
|
889901
|
+
const discovered = await discoverRoutines(shellPaths2(runtime3));
|
|
889902
|
+
const value = {
|
|
889903
|
+
ok: true,
|
|
889904
|
+
kind: "agent.routines.discover",
|
|
889905
|
+
data: { routines: discovered }
|
|
889906
|
+
};
|
|
889907
|
+
return {
|
|
889908
|
+
output: jsonOrText3(runtime3, value, renderDiscoveredRoutineList(discovered)),
|
|
889909
|
+
exitCode: 0
|
|
889910
|
+
};
|
|
889911
|
+
}
|
|
889912
|
+
if (normalized === "import-discovered" || normalized === "import-routine") {
|
|
889913
|
+
const parsed = parseImportFlags(rest);
|
|
889914
|
+
if (!parsed.name) {
|
|
889915
|
+
const failure3 = {
|
|
889916
|
+
ok: false,
|
|
889917
|
+
kind: "invalid_routine_command",
|
|
889918
|
+
error: "Usage: goodvibes-agent routines import-discovered <name> [--enabled] --yes"
|
|
889919
|
+
};
|
|
889920
|
+
return {
|
|
889921
|
+
output: runtime3.cli.flags.outputFormat === "json" ? JSON.stringify(failure3, null, 2) : failure3.error,
|
|
889922
|
+
exitCode: 2
|
|
889923
|
+
};
|
|
889924
|
+
}
|
|
889925
|
+
const discovered = findDiscoveredRoutine2(await discoverRoutines(shellPaths2(runtime3)), parsed.name);
|
|
889926
|
+
if (!discovered) {
|
|
889927
|
+
const failure3 = {
|
|
889928
|
+
ok: false,
|
|
889929
|
+
kind: "routine_discovery_not_found",
|
|
889930
|
+
error: `Unknown discovered Agent routine: ${parsed.name}
|
|
889931
|
+
Run goodvibes-agent routines discover to inspect available routine files.`
|
|
889932
|
+
};
|
|
889933
|
+
return {
|
|
889934
|
+
output: runtime3.cli.flags.outputFormat === "json" ? JSON.stringify(failure3, null, 2) : failure3.error,
|
|
889935
|
+
exitCode: 1
|
|
889936
|
+
};
|
|
889937
|
+
}
|
|
889938
|
+
if (!parsed.yes) {
|
|
889939
|
+
const value2 = {
|
|
889940
|
+
ok: true,
|
|
889941
|
+
kind: "agent.routines.import_discovered.preview",
|
|
889942
|
+
data: { routine: discovered }
|
|
889943
|
+
};
|
|
889944
|
+
return {
|
|
889945
|
+
output: jsonOrText3(runtime3, value2, [
|
|
889946
|
+
"Agent routine import preview",
|
|
889947
|
+
` name: ${discovered.name}`,
|
|
889948
|
+
` origin: ${discovered.origin}`,
|
|
889949
|
+
` path: ${discovered.path}`,
|
|
889950
|
+
` description: ${discovered.description || "(none)"}`,
|
|
889951
|
+
` steps characters: ${discovered.steps.length}`,
|
|
889952
|
+
" next: rerun with --yes to import into the Agent-local routine registry"
|
|
889953
|
+
].join(`
|
|
889954
|
+
`)),
|
|
889955
|
+
exitCode: 0
|
|
889956
|
+
};
|
|
889957
|
+
}
|
|
889958
|
+
const routine = registry5.create({
|
|
889959
|
+
name: discovered.name,
|
|
889960
|
+
description: discovered.description || `Imported routine from ${discovered.origin} markdown file.`,
|
|
889961
|
+
steps: discovered.steps,
|
|
889962
|
+
tags: discoveredRoutineFrontmatterList(discovered, "tags"),
|
|
889963
|
+
triggers: discoveredRoutineFrontmatterList(discovered, "triggers"),
|
|
889964
|
+
enabled: parsed.enabled,
|
|
889965
|
+
source: "imported",
|
|
889966
|
+
provenance: `discovered:${discovered.origin}:${discovered.path}`
|
|
889967
|
+
});
|
|
889968
|
+
const value = {
|
|
889969
|
+
ok: true,
|
|
889970
|
+
kind: "agent.routines.import_discovered",
|
|
889971
|
+
data: routine
|
|
889972
|
+
};
|
|
889973
|
+
return {
|
|
889974
|
+
output: jsonOrText3(runtime3, value, `Imported Agent routine ${routine.id}: ${routine.name}${routine.enabled ? " (enabled)" : ""}`),
|
|
889975
|
+
exitCode: 0
|
|
889976
|
+
};
|
|
889977
|
+
}
|
|
888643
889978
|
if (normalized === "show") {
|
|
888644
889979
|
const id = rest[0];
|
|
888645
889980
|
if (!id)
|
|
@@ -888704,7 +890039,7 @@ async function handleRoutinesCommand(runtime3) {
|
|
|
888704
890039
|
return handleRoutinePromotion(runtime3, rest);
|
|
888705
890040
|
}
|
|
888706
890041
|
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]",
|
|
890042
|
+
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
890043
|
exitCode: 2
|
|
888709
890044
|
};
|
|
888710
890045
|
}
|
|
@@ -888806,13 +890141,13 @@ async function withRuntimeServices(runtime3, fn) {
|
|
|
888806
890141
|
}
|
|
888807
890142
|
}
|
|
888808
890143
|
function readAuthPaths(runtime3) {
|
|
888809
|
-
const
|
|
890144
|
+
const shellPaths3 = createShellPathService2({
|
|
888810
890145
|
workingDirectory: runtime3.workingDirectory,
|
|
888811
890146
|
homeDirectory: runtime3.homeDirectory
|
|
888812
890147
|
});
|
|
888813
|
-
const userStorePath =
|
|
888814
|
-
const bootstrapCredentialPath =
|
|
888815
|
-
const operatorTokenPath =
|
|
890148
|
+
const userStorePath = shellPaths3.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-users.json");
|
|
890149
|
+
const bootstrapCredentialPath = shellPaths3.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-bootstrap.txt");
|
|
890150
|
+
const operatorTokenPath = join101(runtime3.homeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
|
|
888816
890151
|
return {
|
|
888817
890152
|
userStorePath,
|
|
888818
890153
|
userStorePresent: existsSync84(userStorePath),
|
|
@@ -889327,7 +890662,7 @@ async function prepareShellCliRuntime(argv, roots, binary2 = "goodvibes-agent")
|
|
|
889327
890662
|
workingDirectory: bootstrapWorkingDir,
|
|
889328
890663
|
homeDirectory: bootstrapHomeDirectory
|
|
889329
890664
|
} = ownership;
|
|
889330
|
-
configureActivityLogger(
|
|
890665
|
+
configureActivityLogger(join102(bootstrapWorkingDir, ".goodvibes", "logs"));
|
|
889331
890666
|
const configManager = new ConfigManager({
|
|
889332
890667
|
workingDir: bootstrapWorkingDir,
|
|
889333
890668
|
homeDir: bootstrapHomeDirectory,
|
|
@@ -889372,14 +890707,14 @@ async function prepareShellCliRuntime(argv, roots, binary2 = "goodvibes-agent")
|
|
|
889372
890707
|
process.exit(2);
|
|
889373
890708
|
}
|
|
889374
890709
|
if (cli.command === "status" || cli.command === "doctor" || cli.command === "onboarding" && cli.commandArgs[0] === "status") {
|
|
889375
|
-
const
|
|
890710
|
+
const shellPaths3 = createShellPathService2({
|
|
889376
890711
|
workingDirectory: bootstrapWorkingDir,
|
|
889377
890712
|
homeDirectory: bootstrapHomeDirectory
|
|
889378
890713
|
});
|
|
889379
|
-
const userStorePath =
|
|
889380
|
-
const bootstrapCredentialPath =
|
|
889381
|
-
const operatorTokenPath =
|
|
889382
|
-
const onboardingMarkers = readOnboardingCheckMarkers(
|
|
890714
|
+
const userStorePath = shellPaths3.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-users.json");
|
|
890715
|
+
const bootstrapCredentialPath = shellPaths3.resolveUserPath(GOODVIBES_AGENT_SURFACE_ROOT, "auth-bootstrap.txt");
|
|
890716
|
+
const operatorTokenPath = join102(bootstrapHomeDirectory, ".goodvibes", "daemon", "operator-tokens.json");
|
|
890717
|
+
const onboardingMarkers = readOnboardingCheckMarkers(shellPaths3);
|
|
889383
890718
|
const service = await buildCliServicePosture({
|
|
889384
890719
|
configManager,
|
|
889385
890720
|
workingDirectory: bootstrapWorkingDir,
|
|
@@ -889493,8 +890828,8 @@ function getInteractiveTerminalLaunchError(input) {
|
|
|
889493
890828
|
`);
|
|
889494
890829
|
}
|
|
889495
890830
|
function applyInitialTuiCliState(options) {
|
|
889496
|
-
const { cli, input, commandRegistry, commandContext, shellPaths:
|
|
889497
|
-
const globalOnboardingMarker = readOnboardingCheckMarker(
|
|
890831
|
+
const { cli, input, commandRegistry, commandContext, shellPaths: shellPaths3, render } = options;
|
|
890832
|
+
const globalOnboardingMarker = readOnboardingCheckMarker(shellPaths3, "user");
|
|
889498
890833
|
const seededPrompt = cli.flags.prompt ?? (cli.rawCommand === undefined && cli.positionals.length > 0 ? cli.positionals.join(" ") : undefined);
|
|
889499
890834
|
if (cli.command === "onboarding") {
|
|
889500
890835
|
input.openOnboardingWizard({ mode: "edit", reset: true });
|
|
@@ -889516,7 +890851,7 @@ function applyInitialTuiCliState(options) {
|
|
|
889516
890851
|
|
|
889517
890852
|
// src/audio/player.ts
|
|
889518
890853
|
import { accessSync, constants as constants4 } from "fs";
|
|
889519
|
-
import { delimiter, join as
|
|
890854
|
+
import { delimiter, join as join103 } from "path";
|
|
889520
890855
|
import { spawn as spawn6 } from "child_process";
|
|
889521
890856
|
|
|
889522
890857
|
class LocalStreamingAudioPlayer {
|
|
@@ -889613,7 +890948,7 @@ function findExecutable(name51, env2) {
|
|
|
889613
890948
|
if (!dir)
|
|
889614
890949
|
continue;
|
|
889615
890950
|
for (const ext of extensions14) {
|
|
889616
|
-
const candidate =
|
|
890951
|
+
const candidate = join103(dir, `${name51}${ext}`);
|
|
889617
890952
|
try {
|
|
889618
890953
|
accessSync(candidate, constants4.X_OK);
|
|
889619
890954
|
return candidate;
|