@agentforge-ai/cli 0.4.3 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/default/convex/agents.ts +204 -0
- package/dist/default/convex/apiKeys.ts +133 -0
- package/dist/default/convex/cronJobs.ts +224 -0
- package/dist/default/convex/files.ts +103 -0
- package/dist/default/convex/folders.ts +110 -0
- package/dist/default/convex/heartbeat.ts +371 -0
- package/dist/default/convex/logs.ts +66 -0
- package/dist/default/convex/mastraIntegration.ts +185 -0
- package/dist/default/convex/mcpConnections.ts +127 -0
- package/dist/default/convex/messages.ts +90 -0
- package/dist/default/convex/projects.ts +114 -0
- package/dist/default/convex/schema.ts +150 -83
- package/dist/default/convex/sessions.ts +174 -0
- package/dist/default/convex/settings.ts +79 -0
- package/dist/default/convex/skills.ts +178 -0
- package/dist/default/convex/threads.ts +100 -0
- package/dist/default/convex/usage.ts +195 -0
- package/dist/default/convex/vault.ts +397 -0
- package/dist/default/dashboard/app/main.tsx +7 -3
- package/dist/default/dashboard/app/routes/agents.tsx +103 -161
- package/dist/default/dashboard/app/routes/chat.tsx +163 -317
- package/dist/default/dashboard/app/routes/connections.tsx +247 -386
- package/dist/default/dashboard/app/routes/cron.tsx +127 -286
- package/dist/default/dashboard/app/routes/files.tsx +184 -167
- package/dist/default/dashboard/app/routes/index.tsx +63 -96
- package/dist/default/dashboard/app/routes/projects.tsx +106 -225
- package/dist/default/dashboard/app/routes/sessions.tsx +87 -253
- package/dist/default/dashboard/app/routes/settings.tsx +316 -532
- package/dist/default/dashboard/app/routes/skills.tsx +329 -216
- package/dist/default/dashboard/app/routes/usage.tsx +107 -150
- package/dist/default/dashboard/tsconfig.json +3 -2
- package/dist/default/dashboard/vite.config.ts +6 -0
- package/dist/index.js +256 -49
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/default/convex/agents.ts +204 -0
- package/templates/default/convex/apiKeys.ts +133 -0
- package/templates/default/convex/cronJobs.ts +224 -0
- package/templates/default/convex/files.ts +103 -0
- package/templates/default/convex/folders.ts +110 -0
- package/templates/default/convex/heartbeat.ts +371 -0
- package/templates/default/convex/logs.ts +66 -0
- package/templates/default/convex/mastraIntegration.ts +185 -0
- package/templates/default/convex/mcpConnections.ts +127 -0
- package/templates/default/convex/messages.ts +90 -0
- package/templates/default/convex/projects.ts +114 -0
- package/templates/default/convex/schema.ts +150 -83
- package/templates/default/convex/sessions.ts +174 -0
- package/templates/default/convex/settings.ts +79 -0
- package/templates/default/convex/skills.ts +178 -0
- package/templates/default/convex/threads.ts +100 -0
- package/templates/default/convex/usage.ts +195 -0
- package/templates/default/convex/vault.ts +397 -0
- package/templates/default/dashboard/app/main.tsx +7 -3
- package/templates/default/dashboard/app/routes/agents.tsx +103 -161
- package/templates/default/dashboard/app/routes/chat.tsx +163 -317
- package/templates/default/dashboard/app/routes/connections.tsx +247 -386
- package/templates/default/dashboard/app/routes/cron.tsx +127 -286
- package/templates/default/dashboard/app/routes/files.tsx +184 -167
- package/templates/default/dashboard/app/routes/index.tsx +63 -96
- package/templates/default/dashboard/app/routes/projects.tsx +106 -225
- package/templates/default/dashboard/app/routes/sessions.tsx +87 -253
- package/templates/default/dashboard/app/routes/settings.tsx +316 -532
- package/templates/default/dashboard/app/routes/skills.tsx +329 -216
- package/templates/default/dashboard/app/routes/usage.tsx +107 -150
- package/templates/default/dashboard/tsconfig.json +3 -2
- package/templates/default/dashboard/vite.config.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -340,8 +340,8 @@ function getConvexUrl() {
|
|
|
340
340
|
"CONVEX_URL not found. Run `npx convex dev` first, or set CONVEX_URL in your .env file."
|
|
341
341
|
);
|
|
342
342
|
}
|
|
343
|
-
function createClient() {
|
|
344
|
-
const { ConvexHttpClient } =
|
|
343
|
+
async function createClient() {
|
|
344
|
+
const { ConvexHttpClient } = await import("convex/browser");
|
|
345
345
|
const url = getConvexUrl();
|
|
346
346
|
return new ConvexHttpClient(url);
|
|
347
347
|
}
|
|
@@ -446,7 +446,7 @@ function prompt(question) {
|
|
|
446
446
|
function registerAgentsCommand(program2) {
|
|
447
447
|
const agents = program2.command("agents").description("Manage agents");
|
|
448
448
|
agents.command("list").description("List all agents").option("--active", "Show only active agents").option("--json", "Output as JSON").action(async (opts) => {
|
|
449
|
-
const client = createClient();
|
|
449
|
+
const client = await createClient();
|
|
450
450
|
const result = await safeCall(
|
|
451
451
|
() => client.query("agents:list", {}),
|
|
452
452
|
"Failed to list agents"
|
|
@@ -482,7 +482,7 @@ function registerAgentsCommand(program2) {
|
|
|
482
482
|
}
|
|
483
483
|
const provider = model.includes(":") ? model.split(":")[0] : "openai";
|
|
484
484
|
const agentId = name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
485
|
-
const client = createClient();
|
|
485
|
+
const client = await createClient();
|
|
486
486
|
await safeCall(
|
|
487
487
|
() => client.mutation("agents:create", {
|
|
488
488
|
id: agentId,
|
|
@@ -497,7 +497,7 @@ function registerAgentsCommand(program2) {
|
|
|
497
497
|
success(`Agent "${name}" created with ID: ${agentId}`);
|
|
498
498
|
});
|
|
499
499
|
agents.command("inspect").argument("<id>", "Agent ID").description("Show detailed agent information").action(async (id) => {
|
|
500
|
-
const client = createClient();
|
|
500
|
+
const client = await createClient();
|
|
501
501
|
const agent = await safeCall(
|
|
502
502
|
() => client.query("agents:getByAgentId", { id }),
|
|
503
503
|
"Failed to fetch agent"
|
|
@@ -525,7 +525,7 @@ function registerAgentsCommand(program2) {
|
|
|
525
525
|
`);
|
|
526
526
|
});
|
|
527
527
|
agents.command("edit").argument("<id>", "Agent ID").option("--name <name>", "New name").option("--model <model>", "New model").option("--instructions <text>", "New instructions").description("Edit an agent").action(async (id, opts) => {
|
|
528
|
-
const client = createClient();
|
|
528
|
+
const client = await createClient();
|
|
529
529
|
const agent = await safeCall(
|
|
530
530
|
() => client.query("agents:getByAgentId", { id }),
|
|
531
531
|
"Failed to fetch agent"
|
|
@@ -571,7 +571,7 @@ function registerAgentsCommand(program2) {
|
|
|
571
571
|
return;
|
|
572
572
|
}
|
|
573
573
|
}
|
|
574
|
-
const client = createClient();
|
|
574
|
+
const client = await createClient();
|
|
575
575
|
const agent = await safeCall(
|
|
576
576
|
() => client.query("agents:getByAgentId", { id }),
|
|
577
577
|
"Failed to fetch agent"
|
|
@@ -587,7 +587,7 @@ function registerAgentsCommand(program2) {
|
|
|
587
587
|
success(`Agent "${id}" deleted.`);
|
|
588
588
|
});
|
|
589
589
|
agents.command("enable").argument("<id>", "Agent ID").description("Enable an agent").action(async (id) => {
|
|
590
|
-
const client = createClient();
|
|
590
|
+
const client = await createClient();
|
|
591
591
|
const agent = await safeCall(() => client.query("agents:getByAgentId", { id }), "Failed to fetch agent");
|
|
592
592
|
if (!agent) {
|
|
593
593
|
error(`Agent "${id}" not found.`);
|
|
@@ -597,7 +597,7 @@ function registerAgentsCommand(program2) {
|
|
|
597
597
|
success(`Agent "${id}" enabled.`);
|
|
598
598
|
});
|
|
599
599
|
agents.command("disable").argument("<id>", "Agent ID").description("Disable an agent").action(async (id) => {
|
|
600
|
-
const client = createClient();
|
|
600
|
+
const client = await createClient();
|
|
601
601
|
const agent = await safeCall(() => client.query("agents:getByAgentId", { id }), "Failed to fetch agent");
|
|
602
602
|
if (!agent) {
|
|
603
603
|
error(`Agent "${id}" not found.`);
|
|
@@ -612,7 +612,7 @@ function registerAgentsCommand(program2) {
|
|
|
612
612
|
import readline2 from "readline";
|
|
613
613
|
function registerChatCommand(program2) {
|
|
614
614
|
program2.command("chat").argument("[agent-id]", "Agent ID to chat with").option("-s, --session <id>", "Resume an existing session").description("Start an interactive chat session with an agent").action(async (agentId, opts) => {
|
|
615
|
-
const client = createClient();
|
|
615
|
+
const client = await createClient();
|
|
616
616
|
if (!agentId && !opts.session) {
|
|
617
617
|
const agents = await safeCall(() => client.query("agents:list", {}), "Failed to list agents");
|
|
618
618
|
if (!agents || agents.length === 0) {
|
|
@@ -705,7 +705,7 @@ function registerChatCommand(program2) {
|
|
|
705
705
|
function registerSessionsCommand(program2) {
|
|
706
706
|
const sessions = program2.command("sessions").description("Manage sessions");
|
|
707
707
|
sessions.command("list").option("--status <status>", "Filter by status (active, ended)").option("--json", "Output as JSON").description("List all sessions").action(async (opts) => {
|
|
708
|
-
const client = createClient();
|
|
708
|
+
const client = await createClient();
|
|
709
709
|
const result = await safeCall(() => client.query("sessions:list", {}), "Failed to list sessions");
|
|
710
710
|
if (opts.json) {
|
|
711
711
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -728,7 +728,7 @@ function registerSessionsCommand(program2) {
|
|
|
728
728
|
})));
|
|
729
729
|
});
|
|
730
730
|
sessions.command("inspect").argument("<id>", "Session ID").description("Show session details").action(async (id) => {
|
|
731
|
-
const client = createClient();
|
|
731
|
+
const client = await createClient();
|
|
732
732
|
const session = await safeCall(() => client.query("sessions:getById", { id }), "Failed to fetch session");
|
|
733
733
|
if (!session) {
|
|
734
734
|
error(`Session "${id}" not found.`);
|
|
@@ -739,7 +739,7 @@ function registerSessionsCommand(program2) {
|
|
|
739
739
|
details({ ID: s._id, Name: s.name, Agent: s.agentId, Status: s.status, Started: formatDate(s.startedAt), "Last Activity": formatDate(s.lastActivityAt) });
|
|
740
740
|
});
|
|
741
741
|
sessions.command("end").argument("<id>", "Session ID").description("End an active session").action(async (id) => {
|
|
742
|
-
const client = createClient();
|
|
742
|
+
const client = await createClient();
|
|
743
743
|
await safeCall(() => client.mutation("sessions:update", { _id: id, status: "ended" }), "Failed to end session");
|
|
744
744
|
success(`Session "${id}" ended.`);
|
|
745
745
|
});
|
|
@@ -747,7 +747,7 @@ function registerSessionsCommand(program2) {
|
|
|
747
747
|
function registerThreadsCommand(program2) {
|
|
748
748
|
const threads = program2.command("threads").description("Manage conversation threads");
|
|
749
749
|
threads.command("list").option("--agent <id>", "Filter by agent ID").option("--json", "Output as JSON").description("List all threads").action(async (opts) => {
|
|
750
|
-
const client = createClient();
|
|
750
|
+
const client = await createClient();
|
|
751
751
|
const args = opts.agent ? { agentId: opts.agent } : {};
|
|
752
752
|
const result = await safeCall(() => client.query("threads:list", args), "Failed to list threads");
|
|
753
753
|
if (opts.json) {
|
|
@@ -769,7 +769,7 @@ function registerThreadsCommand(program2) {
|
|
|
769
769
|
})));
|
|
770
770
|
});
|
|
771
771
|
threads.command("inspect").argument("<id>", "Thread ID").description("Show thread messages").action(async (id) => {
|
|
772
|
-
const client = createClient();
|
|
772
|
+
const client = await createClient();
|
|
773
773
|
const messages = await safeCall(() => client.query("messages:listByThread", { threadId: id }), "Failed to fetch messages");
|
|
774
774
|
header(`Thread: ${id}`);
|
|
775
775
|
const items = messages || [];
|
|
@@ -784,7 +784,7 @@ function registerThreadsCommand(program2) {
|
|
|
784
784
|
console.log();
|
|
785
785
|
});
|
|
786
786
|
threads.command("delete").argument("<id>", "Thread ID").description("Delete a thread and its messages").action(async (id) => {
|
|
787
|
-
const client = createClient();
|
|
787
|
+
const client = await createClient();
|
|
788
788
|
await safeCall(() => client.mutation("threads:remove", { _id: id }), "Failed to delete thread");
|
|
789
789
|
success(`Thread "${id}" deleted.`);
|
|
790
790
|
});
|
|
@@ -804,7 +804,7 @@ function prompt2(q) {
|
|
|
804
804
|
function registerSkillsCommand(program2) {
|
|
805
805
|
const skills = program2.command("skills").description("Manage agent skills");
|
|
806
806
|
skills.command("list").option("--installed", "Show only installed skills").option("--json", "Output as JSON").description("List all skills").action(async (opts) => {
|
|
807
|
-
const client = createClient();
|
|
807
|
+
const client = await createClient();
|
|
808
808
|
const result = await safeCall(() => client.query("skills:list", {}), "Failed to list skills");
|
|
809
809
|
if (opts.json) {
|
|
810
810
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -916,7 +916,7 @@ Edit \`skills/${name}/config.json\` to customize.
|
|
|
916
916
|
info(`Edit skills/${name}/index.ts to implement your tool logic.`);
|
|
917
917
|
});
|
|
918
918
|
skills.command("install").argument("<name>", "Skill name to install").description("Install a skill").action(async (name) => {
|
|
919
|
-
const client = createClient();
|
|
919
|
+
const client = await createClient();
|
|
920
920
|
await safeCall(
|
|
921
921
|
() => client.mutation("skills:create", {
|
|
922
922
|
name,
|
|
@@ -937,7 +937,7 @@ Edit \`skills/${name}/config.json\` to customize.
|
|
|
937
937
|
success(`Skill "${name}" removed from disk.`);
|
|
938
938
|
}
|
|
939
939
|
}
|
|
940
|
-
const client = createClient();
|
|
940
|
+
const client = await createClient();
|
|
941
941
|
try {
|
|
942
942
|
const skills2 = await client.query("skills:list", {});
|
|
943
943
|
const skill = skills2.find((s) => s.name === name);
|
|
@@ -983,7 +983,7 @@ function prompt3(q) {
|
|
|
983
983
|
function registerCronCommand(program2) {
|
|
984
984
|
const cron = program2.command("cron").description("Manage cron jobs");
|
|
985
985
|
cron.command("list").option("--json", "Output as JSON").description("List all cron jobs").action(async (opts) => {
|
|
986
|
-
const client = createClient();
|
|
986
|
+
const client = await createClient();
|
|
987
987
|
const result = await safeCall(() => client.query("cronJobs:list", {}), "Failed to list cron jobs");
|
|
988
988
|
if (opts.json) {
|
|
989
989
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -1014,7 +1014,7 @@ function registerCronCommand(program2) {
|
|
|
1014
1014
|
error("All fields are required.");
|
|
1015
1015
|
process.exit(1);
|
|
1016
1016
|
}
|
|
1017
|
-
const client = createClient();
|
|
1017
|
+
const client = await createClient();
|
|
1018
1018
|
await safeCall(
|
|
1019
1019
|
() => client.mutation("cronJobs:create", { name, schedule, agentId, action, isEnabled: true }),
|
|
1020
1020
|
"Failed to create cron job"
|
|
@@ -1022,17 +1022,17 @@ function registerCronCommand(program2) {
|
|
|
1022
1022
|
success(`Cron job "${name}" created.`);
|
|
1023
1023
|
});
|
|
1024
1024
|
cron.command("delete").argument("<id>", "Cron job ID").description("Delete a cron job").action(async (id) => {
|
|
1025
|
-
const client = createClient();
|
|
1025
|
+
const client = await createClient();
|
|
1026
1026
|
await safeCall(() => client.mutation("cronJobs:remove", { _id: id }), "Failed to delete");
|
|
1027
1027
|
success(`Cron job "${id}" deleted.`);
|
|
1028
1028
|
});
|
|
1029
1029
|
cron.command("enable").argument("<id>", "Cron job ID").description("Enable a cron job").action(async (id) => {
|
|
1030
|
-
const client = createClient();
|
|
1030
|
+
const client = await createClient();
|
|
1031
1031
|
await safeCall(() => client.mutation("cronJobs:update", { _id: id, isEnabled: true }), "Failed");
|
|
1032
1032
|
success(`Cron job "${id}" enabled.`);
|
|
1033
1033
|
});
|
|
1034
1034
|
cron.command("disable").argument("<id>", "Cron job ID").description("Disable a cron job").action(async (id) => {
|
|
1035
|
-
const client = createClient();
|
|
1035
|
+
const client = await createClient();
|
|
1036
1036
|
await safeCall(() => client.mutation("cronJobs:update", { _id: id, isEnabled: false }), "Failed");
|
|
1037
1037
|
success(`Cron job "${id}" disabled.`);
|
|
1038
1038
|
});
|
|
@@ -1050,7 +1050,7 @@ function prompt4(q) {
|
|
|
1050
1050
|
function registerMcpCommand(program2) {
|
|
1051
1051
|
const mcp = program2.command("mcp").description("Manage MCP connections");
|
|
1052
1052
|
mcp.command("list").option("--json", "Output as JSON").description("List all MCP connections").action(async (opts) => {
|
|
1053
|
-
const client = createClient();
|
|
1053
|
+
const client = await createClient();
|
|
1054
1054
|
const result = await safeCall(() => client.query("mcpConnections:list", {}), "Failed to list connections");
|
|
1055
1055
|
if (opts.json) {
|
|
1056
1056
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -1079,7 +1079,7 @@ function registerMcpCommand(program2) {
|
|
|
1079
1079
|
error("All fields required.");
|
|
1080
1080
|
process.exit(1);
|
|
1081
1081
|
}
|
|
1082
|
-
const client = createClient();
|
|
1082
|
+
const client = await createClient();
|
|
1083
1083
|
await safeCall(
|
|
1084
1084
|
() => client.mutation("mcpConnections:create", {
|
|
1085
1085
|
name,
|
|
@@ -1093,13 +1093,13 @@ function registerMcpCommand(program2) {
|
|
|
1093
1093
|
success(`MCP connection "${name}" added.`);
|
|
1094
1094
|
});
|
|
1095
1095
|
mcp.command("remove").argument("<id>", "Connection ID").description("Remove an MCP connection").action(async (id) => {
|
|
1096
|
-
const client = createClient();
|
|
1096
|
+
const client = await createClient();
|
|
1097
1097
|
await safeCall(() => client.mutation("mcpConnections:remove", { _id: id }), "Failed");
|
|
1098
1098
|
success(`Connection "${id}" removed.`);
|
|
1099
1099
|
});
|
|
1100
1100
|
mcp.command("test").argument("<id>", "Connection ID").description("Test an MCP connection").action(async (id) => {
|
|
1101
1101
|
info(`Testing connection "${id}"...`);
|
|
1102
|
-
const client = createClient();
|
|
1102
|
+
const client = await createClient();
|
|
1103
1103
|
const conns = await safeCall(() => client.query("mcpConnections:list", {}), "Failed");
|
|
1104
1104
|
const conn = conns.find((c) => c._id === id || c._id?.endsWith(id));
|
|
1105
1105
|
if (!conn) {
|
|
@@ -1124,12 +1124,12 @@ function registerMcpCommand(program2) {
|
|
|
1124
1124
|
}
|
|
1125
1125
|
});
|
|
1126
1126
|
mcp.command("enable").argument("<id>", "Connection ID").description("Enable a connection").action(async (id) => {
|
|
1127
|
-
const client = createClient();
|
|
1127
|
+
const client = await createClient();
|
|
1128
1128
|
await safeCall(() => client.mutation("mcpConnections:update", { _id: id, isEnabled: true }), "Failed");
|
|
1129
1129
|
success(`Connection "${id}" enabled.`);
|
|
1130
1130
|
});
|
|
1131
1131
|
mcp.command("disable").argument("<id>", "Connection ID").description("Disable a connection").action(async (id) => {
|
|
1132
|
-
const client = createClient();
|
|
1132
|
+
const client = await createClient();
|
|
1133
1133
|
await safeCall(() => client.mutation("mcpConnections:update", { _id: id, isEnabled: false }), "Failed");
|
|
1134
1134
|
success(`Connection "${id}" disabled.`);
|
|
1135
1135
|
});
|
|
@@ -1141,7 +1141,7 @@ import path6 from "path";
|
|
|
1141
1141
|
function registerFilesCommand(program2) {
|
|
1142
1142
|
const files = program2.command("files").description("Manage files");
|
|
1143
1143
|
files.command("list").argument("[folder]", "Folder ID to list files from").option("--json", "Output as JSON").description("List files").action(async (folder, opts) => {
|
|
1144
|
-
const client = createClient();
|
|
1144
|
+
const client = await createClient();
|
|
1145
1145
|
const args = folder ? { folderId: folder } : {};
|
|
1146
1146
|
const result = await safeCall(() => client.query("files:list", args), "Failed to list files");
|
|
1147
1147
|
if (opts.json) {
|
|
@@ -1187,7 +1187,7 @@ function registerFilesCommand(program2) {
|
|
|
1187
1187
|
".xml": "text/xml"
|
|
1188
1188
|
};
|
|
1189
1189
|
const mimeType = mimeTypes[ext] || "application/octet-stream";
|
|
1190
|
-
const client = createClient();
|
|
1190
|
+
const client = await createClient();
|
|
1191
1191
|
await safeCall(
|
|
1192
1192
|
() => client.mutation("files:create", {
|
|
1193
1193
|
name,
|
|
@@ -1202,13 +1202,13 @@ function registerFilesCommand(program2) {
|
|
|
1202
1202
|
info("Note: File content storage requires Convex file storage or R2 integration.");
|
|
1203
1203
|
});
|
|
1204
1204
|
files.command("delete").argument("<id>", "File ID").description("Delete a file").action(async (id) => {
|
|
1205
|
-
const client = createClient();
|
|
1205
|
+
const client = await createClient();
|
|
1206
1206
|
await safeCall(() => client.mutation("files:remove", { _id: id }), "Failed to delete file");
|
|
1207
1207
|
success(`File "${id}" deleted.`);
|
|
1208
1208
|
});
|
|
1209
1209
|
const folders = program2.command("folders").description("Manage folders");
|
|
1210
1210
|
folders.command("list").option("--json", "Output as JSON").description("List all folders").action(async (opts) => {
|
|
1211
|
-
const client = createClient();
|
|
1211
|
+
const client = await createClient();
|
|
1212
1212
|
const result = await safeCall(() => client.query("folders:list", {}), "Failed to list folders");
|
|
1213
1213
|
if (opts.json) {
|
|
1214
1214
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -1228,7 +1228,7 @@ function registerFilesCommand(program2) {
|
|
|
1228
1228
|
})));
|
|
1229
1229
|
});
|
|
1230
1230
|
folders.command("create").argument("<name>", "Folder name").option("--parent <id>", "Parent folder ID").description("Create a folder").action(async (name, opts) => {
|
|
1231
|
-
const client = createClient();
|
|
1231
|
+
const client = await createClient();
|
|
1232
1232
|
await safeCall(
|
|
1233
1233
|
() => client.mutation("folders:create", { name, parentId: opts.parent }),
|
|
1234
1234
|
"Failed to create folder"
|
|
@@ -1236,7 +1236,7 @@ function registerFilesCommand(program2) {
|
|
|
1236
1236
|
success(`Folder "${name}" created.`);
|
|
1237
1237
|
});
|
|
1238
1238
|
folders.command("delete").argument("<id>", "Folder ID").description("Delete a folder").action(async (id) => {
|
|
1239
|
-
const client = createClient();
|
|
1239
|
+
const client = await createClient();
|
|
1240
1240
|
await safeCall(() => client.mutation("folders:remove", { _id: id }), "Failed to delete folder");
|
|
1241
1241
|
success(`Folder "${id}" deleted.`);
|
|
1242
1242
|
});
|
|
@@ -1259,7 +1259,7 @@ function prompt5(q) {
|
|
|
1259
1259
|
function registerProjectsCommand(program2) {
|
|
1260
1260
|
const projects = program2.command("projects").description("Manage projects and workspaces");
|
|
1261
1261
|
projects.command("list").option("--json", "Output as JSON").description("List all projects").action(async (opts) => {
|
|
1262
|
-
const client = createClient();
|
|
1262
|
+
const client = await createClient();
|
|
1263
1263
|
const result = await safeCall(() => client.query("projects:list", {}), "Failed to list projects");
|
|
1264
1264
|
if (opts.json) {
|
|
1265
1265
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -1281,7 +1281,7 @@ function registerProjectsCommand(program2) {
|
|
|
1281
1281
|
});
|
|
1282
1282
|
projects.command("create").argument("<name>", "Project name").option("-d, --description <desc>", "Project description").description("Create a new project").action(async (name, opts) => {
|
|
1283
1283
|
const description = opts.description || await prompt5("Description (optional): ");
|
|
1284
|
-
const client = createClient();
|
|
1284
|
+
const client = await createClient();
|
|
1285
1285
|
await safeCall(
|
|
1286
1286
|
() => client.mutation("projects:create", { name, description, status: "active" }),
|
|
1287
1287
|
"Failed to create project"
|
|
@@ -1289,7 +1289,7 @@ function registerProjectsCommand(program2) {
|
|
|
1289
1289
|
success(`Project "${name}" created.`);
|
|
1290
1290
|
});
|
|
1291
1291
|
projects.command("inspect").argument("<id>", "Project ID").description("Show project details").action(async (id) => {
|
|
1292
|
-
const client = createClient();
|
|
1292
|
+
const client = await createClient();
|
|
1293
1293
|
const projects2 = await safeCall(() => client.query("projects:list", {}), "Failed");
|
|
1294
1294
|
const project = projects2.find((p) => p._id === id || p._id?.endsWith(id));
|
|
1295
1295
|
if (!project) {
|
|
@@ -1314,12 +1314,12 @@ function registerProjectsCommand(program2) {
|
|
|
1314
1314
|
return;
|
|
1315
1315
|
}
|
|
1316
1316
|
}
|
|
1317
|
-
const client = createClient();
|
|
1317
|
+
const client = await createClient();
|
|
1318
1318
|
await safeCall(() => client.mutation("projects:remove", { _id: id }), "Failed");
|
|
1319
1319
|
success(`Project "${id}" deleted.`);
|
|
1320
1320
|
});
|
|
1321
1321
|
projects.command("switch").argument("<id>", "Project ID to switch to").description("Set the active project").action(async (id) => {
|
|
1322
|
-
const client = createClient();
|
|
1322
|
+
const client = await createClient();
|
|
1323
1323
|
const projects2 = await safeCall(() => client.query("projects:list", {}), "Failed");
|
|
1324
1324
|
const project = projects2.find((p) => p._id === id || p._id?.endsWith(id));
|
|
1325
1325
|
if (!project) {
|
|
@@ -1516,7 +1516,7 @@ function promptSecret(q) {
|
|
|
1516
1516
|
function registerVaultCommand(program2) {
|
|
1517
1517
|
const vault = program2.command("vault").description("Manage secrets securely");
|
|
1518
1518
|
vault.command("list").option("--json", "Output as JSON").description("List all stored secrets (values hidden)").action(async (opts) => {
|
|
1519
|
-
const client = createClient();
|
|
1519
|
+
const client = await createClient();
|
|
1520
1520
|
const result = await safeCall(() => client.query("vault:list", {}), "Failed to list secrets");
|
|
1521
1521
|
if (opts.json) {
|
|
1522
1522
|
const safe = (result || []).map((s) => ({ ...s, encryptedValue: void 0 }));
|
|
@@ -1545,7 +1545,7 @@ function registerVaultCommand(program2) {
|
|
|
1545
1545
|
error("Value is required.");
|
|
1546
1546
|
process.exit(1);
|
|
1547
1547
|
}
|
|
1548
|
-
const client = createClient();
|
|
1548
|
+
const client = await createClient();
|
|
1549
1549
|
await safeCall(
|
|
1550
1550
|
() => client.mutation("vault:store", {
|
|
1551
1551
|
name,
|
|
@@ -1558,7 +1558,7 @@ function registerVaultCommand(program2) {
|
|
|
1558
1558
|
success(`Secret "${name}" stored securely.`);
|
|
1559
1559
|
});
|
|
1560
1560
|
vault.command("get").argument("<name>", "Secret name").option("--reveal", "Show the actual value (use with caution)").description("Retrieve a secret").action(async (name, opts) => {
|
|
1561
|
-
const client = createClient();
|
|
1561
|
+
const client = await createClient();
|
|
1562
1562
|
const result = await safeCall(() => client.query("vault:list", {}), "Failed");
|
|
1563
1563
|
const secret = (result || []).find((s) => s.name === name);
|
|
1564
1564
|
if (!secret) {
|
|
@@ -1585,7 +1585,7 @@ function registerVaultCommand(program2) {
|
|
|
1585
1585
|
return;
|
|
1586
1586
|
}
|
|
1587
1587
|
}
|
|
1588
|
-
const client = createClient();
|
|
1588
|
+
const client = await createClient();
|
|
1589
1589
|
const result = await safeCall(() => client.query("vault:list", {}), "Failed");
|
|
1590
1590
|
const secret = (result || []).find((s) => s.name === name);
|
|
1591
1591
|
if (!secret) {
|
|
@@ -1596,7 +1596,7 @@ function registerVaultCommand(program2) {
|
|
|
1596
1596
|
success(`Secret "${name}" deleted.`);
|
|
1597
1597
|
});
|
|
1598
1598
|
vault.command("rotate").argument("<name>", "Secret name").description("Rotate a secret (set a new value)").action(async (name) => {
|
|
1599
|
-
const client = createClient();
|
|
1599
|
+
const client = await createClient();
|
|
1600
1600
|
const result = await safeCall(() => client.query("vault:list", {}), "Failed");
|
|
1601
1601
|
const secret = (result || []).find((s) => s.name === name);
|
|
1602
1602
|
if (!secret) {
|
|
@@ -1616,6 +1616,212 @@ function registerVaultCommand(program2) {
|
|
|
1616
1616
|
});
|
|
1617
1617
|
}
|
|
1618
1618
|
|
|
1619
|
+
// src/commands/keys.ts
|
|
1620
|
+
function safeCall2(fn, msg) {
|
|
1621
|
+
return fn().catch((e) => {
|
|
1622
|
+
error(`${msg}: ${e.message}`);
|
|
1623
|
+
process.exit(1);
|
|
1624
|
+
});
|
|
1625
|
+
}
|
|
1626
|
+
function formatDate4(ts) {
|
|
1627
|
+
return new Date(ts).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" });
|
|
1628
|
+
}
|
|
1629
|
+
function maskKey(key) {
|
|
1630
|
+
if (key.length <= 12) return key.substring(0, 4) + "****";
|
|
1631
|
+
return key.substring(0, 8) + "..." + key.substring(key.length - 4);
|
|
1632
|
+
}
|
|
1633
|
+
function promptSecret2(question) {
|
|
1634
|
+
return new Promise((resolve2) => {
|
|
1635
|
+
const readline10 = __require("readline");
|
|
1636
|
+
if (process.stdin.isTTY) {
|
|
1637
|
+
process.stdout.write(question);
|
|
1638
|
+
process.stdin.setRawMode(true);
|
|
1639
|
+
process.stdin.resume();
|
|
1640
|
+
process.stdin.setEncoding("utf8");
|
|
1641
|
+
let input = "";
|
|
1642
|
+
const onData = (char) => {
|
|
1643
|
+
if (char === "\n" || char === "\r" || char === "") {
|
|
1644
|
+
process.stdin.setRawMode(false);
|
|
1645
|
+
process.stdin.pause();
|
|
1646
|
+
process.stdin.removeListener("data", onData);
|
|
1647
|
+
process.stdout.write("\n");
|
|
1648
|
+
resolve2(input);
|
|
1649
|
+
} else if (char === "") {
|
|
1650
|
+
process.exit(0);
|
|
1651
|
+
} else if (char === "\x7F" || char === "\b") {
|
|
1652
|
+
if (input.length > 0) {
|
|
1653
|
+
input = input.slice(0, -1);
|
|
1654
|
+
process.stdout.write("\b \b");
|
|
1655
|
+
}
|
|
1656
|
+
} else {
|
|
1657
|
+
input += char;
|
|
1658
|
+
process.stdout.write("*");
|
|
1659
|
+
}
|
|
1660
|
+
};
|
|
1661
|
+
process.stdin.on("data", onData);
|
|
1662
|
+
} else {
|
|
1663
|
+
const rl = readline10.createInterface({ input: process.stdin, output: process.stdout });
|
|
1664
|
+
rl.question(question, (ans) => {
|
|
1665
|
+
rl.close();
|
|
1666
|
+
resolve2(ans.trim());
|
|
1667
|
+
});
|
|
1668
|
+
}
|
|
1669
|
+
});
|
|
1670
|
+
}
|
|
1671
|
+
var PROVIDERS = [
|
|
1672
|
+
{ id: "openai", name: "OpenAI", prefix: "sk-" },
|
|
1673
|
+
{ id: "anthropic", name: "Anthropic", prefix: "sk-ant-" },
|
|
1674
|
+
{ id: "openrouter", name: "OpenRouter", prefix: "sk-or-" },
|
|
1675
|
+
{ id: "google", name: "Google AI", prefix: "AIza" },
|
|
1676
|
+
{ id: "xai", name: "xAI", prefix: "xai-" },
|
|
1677
|
+
{ id: "groq", name: "Groq", prefix: "gsk_" },
|
|
1678
|
+
{ id: "together", name: "Together AI", prefix: "" },
|
|
1679
|
+
{ id: "perplexity", name: "Perplexity", prefix: "pplx-" }
|
|
1680
|
+
];
|
|
1681
|
+
function registerKeysCommand(program2) {
|
|
1682
|
+
const keys = program2.command("keys").description("Manage AI provider API keys");
|
|
1683
|
+
keys.command("list").option("--provider <provider>", "Filter by provider").option("--json", "Output as JSON").description("List all configured API keys").action(async (opts) => {
|
|
1684
|
+
const client = await createClient();
|
|
1685
|
+
const result = await safeCall2(
|
|
1686
|
+
() => client.query("apiKeys:list", opts.provider ? { provider: opts.provider } : {}),
|
|
1687
|
+
"Failed to list API keys"
|
|
1688
|
+
);
|
|
1689
|
+
const items = result || [];
|
|
1690
|
+
if (opts.json) {
|
|
1691
|
+
const safe = items.map((k) => ({ ...k, encryptedKey: maskKey(k.encryptedKey) }));
|
|
1692
|
+
console.log(JSON.stringify(safe, null, 2));
|
|
1693
|
+
return;
|
|
1694
|
+
}
|
|
1695
|
+
header("API Keys");
|
|
1696
|
+
if (items.length === 0) {
|
|
1697
|
+
info("No API keys configured.");
|
|
1698
|
+
dim(" Add one with: agentforge keys add <provider> [key]");
|
|
1699
|
+
dim("");
|
|
1700
|
+
dim(" Supported providers:");
|
|
1701
|
+
PROVIDERS.forEach((p) => dim(` ${p.id.padEnd(12)} ${p.name}`));
|
|
1702
|
+
return;
|
|
1703
|
+
}
|
|
1704
|
+
table(items.map((k) => ({
|
|
1705
|
+
Provider: k.provider,
|
|
1706
|
+
Name: k.keyName,
|
|
1707
|
+
Key: maskKey(k.encryptedKey),
|
|
1708
|
+
Active: k.isActive ? "\u2713" : "\u2717",
|
|
1709
|
+
Created: formatDate4(k.createdAt),
|
|
1710
|
+
"Last Used": k.lastUsedAt ? formatDate4(k.lastUsedAt) : "Never"
|
|
1711
|
+
})));
|
|
1712
|
+
});
|
|
1713
|
+
keys.command("add").argument("<provider>", `Provider (${PROVIDERS.map((p) => p.id).join(", ")})`).argument("[key]", "API key value (omit for secure prompt)").option("--name <name>", "Key display name").description("Add an AI provider API key").action(async (provider, key, opts) => {
|
|
1714
|
+
const providerInfo = PROVIDERS.find((p) => p.id === provider);
|
|
1715
|
+
if (!providerInfo) {
|
|
1716
|
+
error(`Unknown provider "${provider}". Supported: ${PROVIDERS.map((p) => p.id).join(", ")}`);
|
|
1717
|
+
process.exit(1);
|
|
1718
|
+
}
|
|
1719
|
+
if (!key) {
|
|
1720
|
+
key = await promptSecret2(`Enter ${providerInfo.name} API key: `);
|
|
1721
|
+
}
|
|
1722
|
+
if (!key) {
|
|
1723
|
+
error("API key is required.");
|
|
1724
|
+
process.exit(1);
|
|
1725
|
+
}
|
|
1726
|
+
if (providerInfo.prefix && !key.startsWith(providerInfo.prefix)) {
|
|
1727
|
+
info(`Warning: ${providerInfo.name} keys typically start with "${providerInfo.prefix}".`);
|
|
1728
|
+
}
|
|
1729
|
+
const keyName = opts.name || `${providerInfo.name} Key`;
|
|
1730
|
+
const client = await createClient();
|
|
1731
|
+
await safeCall2(
|
|
1732
|
+
() => client.mutation("apiKeys:create", {
|
|
1733
|
+
provider,
|
|
1734
|
+
keyName,
|
|
1735
|
+
encryptedKey: key
|
|
1736
|
+
}),
|
|
1737
|
+
"Failed to store API key"
|
|
1738
|
+
);
|
|
1739
|
+
success(`${providerInfo.name} API key "${keyName}" stored successfully.`);
|
|
1740
|
+
});
|
|
1741
|
+
keys.command("remove").argument("<provider>", "Provider name").option("-f, --force", "Skip confirmation").description("Remove an API key").action(async (provider, opts) => {
|
|
1742
|
+
const client = await createClient();
|
|
1743
|
+
const result = await safeCall2(
|
|
1744
|
+
() => client.query("apiKeys:list", { provider }),
|
|
1745
|
+
"Failed to list keys"
|
|
1746
|
+
);
|
|
1747
|
+
const items = result || [];
|
|
1748
|
+
if (items.length === 0) {
|
|
1749
|
+
error(`No API keys found for "${provider}".`);
|
|
1750
|
+
process.exit(1);
|
|
1751
|
+
}
|
|
1752
|
+
const target = items[0];
|
|
1753
|
+
if (!opts.force) {
|
|
1754
|
+
const readline10 = __require("readline");
|
|
1755
|
+
const rl = readline10.createInterface({ input: process.stdin, output: process.stdout });
|
|
1756
|
+
const answer = await new Promise((resolve2) => {
|
|
1757
|
+
rl.question(`Delete "${target.keyName}" for ${provider}? (y/N): `, (ans) => {
|
|
1758
|
+
rl.close();
|
|
1759
|
+
resolve2(ans.trim());
|
|
1760
|
+
});
|
|
1761
|
+
});
|
|
1762
|
+
if (answer.toLowerCase() !== "y") {
|
|
1763
|
+
info("Cancelled.");
|
|
1764
|
+
return;
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1767
|
+
await safeCall2(
|
|
1768
|
+
() => client.mutation("apiKeys:remove", { id: target._id }),
|
|
1769
|
+
"Failed to remove API key"
|
|
1770
|
+
);
|
|
1771
|
+
success(`API key "${target.keyName}" removed.`);
|
|
1772
|
+
});
|
|
1773
|
+
keys.command("test").argument("<provider>", "Provider to test").description("Test an API key by making a simple request").action(async (provider) => {
|
|
1774
|
+
const client = await createClient();
|
|
1775
|
+
const result = await safeCall2(
|
|
1776
|
+
() => client.query("apiKeys:getActiveForProvider", { provider }),
|
|
1777
|
+
"Failed to get key"
|
|
1778
|
+
);
|
|
1779
|
+
if (!result) {
|
|
1780
|
+
error(`No active API key for "${provider}". Add one with: agentforge keys add ${provider}`);
|
|
1781
|
+
process.exit(1);
|
|
1782
|
+
}
|
|
1783
|
+
const key = result.encryptedKey;
|
|
1784
|
+
info(`Testing ${provider} API key...`);
|
|
1785
|
+
try {
|
|
1786
|
+
let ok = false;
|
|
1787
|
+
if (provider === "openai") {
|
|
1788
|
+
const res = await fetch("https://api.openai.com/v1/models", { headers: { Authorization: `Bearer ${key}` } });
|
|
1789
|
+
ok = res.ok;
|
|
1790
|
+
} else if (provider === "anthropic") {
|
|
1791
|
+
const res = await fetch("https://api.anthropic.com/v1/messages", {
|
|
1792
|
+
method: "POST",
|
|
1793
|
+
headers: { "x-api-key": key, "anthropic-version": "2023-06-01", "Content-Type": "application/json" },
|
|
1794
|
+
body: JSON.stringify({ model: "claude-3-haiku-20240307", max_tokens: 1, messages: [{ role: "user", content: "hi" }] })
|
|
1795
|
+
});
|
|
1796
|
+
ok = res.ok;
|
|
1797
|
+
} else if (provider === "openrouter") {
|
|
1798
|
+
const res = await fetch("https://openrouter.ai/api/v1/models", { headers: { Authorization: `Bearer ${key}` } });
|
|
1799
|
+
ok = res.ok;
|
|
1800
|
+
} else if (provider === "google") {
|
|
1801
|
+
const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models?key=${key}`);
|
|
1802
|
+
ok = res.ok;
|
|
1803
|
+
} else if (provider === "groq") {
|
|
1804
|
+
const res = await fetch("https://api.groq.com/openai/v1/models", { headers: { Authorization: `Bearer ${key}` } });
|
|
1805
|
+
ok = res.ok;
|
|
1806
|
+
} else {
|
|
1807
|
+
info(`No test endpoint configured for "${provider}". Key is stored.`);
|
|
1808
|
+
return;
|
|
1809
|
+
}
|
|
1810
|
+
if (ok) {
|
|
1811
|
+
success(`${provider} API key is valid and working.`);
|
|
1812
|
+
await safeCall2(
|
|
1813
|
+
() => client.mutation("apiKeys:updateLastUsed", { id: result._id }),
|
|
1814
|
+
"Failed to update last used"
|
|
1815
|
+
);
|
|
1816
|
+
} else {
|
|
1817
|
+
error(`${provider} API key returned an error. Check that the key is valid.`);
|
|
1818
|
+
}
|
|
1819
|
+
} catch (e) {
|
|
1820
|
+
error(`Connection failed: ${e.message}`);
|
|
1821
|
+
}
|
|
1822
|
+
});
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1619
1825
|
// src/commands/status.ts
|
|
1620
1826
|
import { spawn as spawn2 } from "child_process";
|
|
1621
1827
|
import path8 from "path";
|
|
@@ -1632,7 +1838,7 @@ function registerStatusCommand(program2) {
|
|
|
1632
1838
|
checks["Dashboard Dir"] = fs8.existsSync(path8.join(cwd, "dashboard")) ? "\u2714 Found" : "\u2716 Not found";
|
|
1633
1839
|
checks["Env Config"] = fs8.existsSync(path8.join(cwd, ".env.local")) || fs8.existsSync(path8.join(cwd, ".env")) ? "\u2714 Found" : "\u2716 Not found";
|
|
1634
1840
|
try {
|
|
1635
|
-
const client = createClient();
|
|
1841
|
+
const client = await createClient();
|
|
1636
1842
|
const agents = await client.query("agents:list", {});
|
|
1637
1843
|
checks["Convex Connection"] = `\u2714 Connected (${agents?.length || 0} agents)`;
|
|
1638
1844
|
} catch {
|
|
@@ -1742,7 +1948,7 @@ function registerStatusCommand(program2) {
|
|
|
1742
1948
|
});
|
|
1743
1949
|
});
|
|
1744
1950
|
program2.command("logs").description("Show recent activity logs").option("-n, --lines <count>", "Number of log entries", "20").option("--agent <id>", "Filter by agent ID").option("--json", "Output as JSON").action(async (opts) => {
|
|
1745
|
-
const client = createClient();
|
|
1951
|
+
const client = await createClient();
|
|
1746
1952
|
const args = {};
|
|
1747
1953
|
if (opts.agent) args.agentId = opts.agent;
|
|
1748
1954
|
const result = await safeCall(
|
|
@@ -1769,7 +1975,7 @@ function registerStatusCommand(program2) {
|
|
|
1769
1975
|
console.log();
|
|
1770
1976
|
});
|
|
1771
1977
|
program2.command("heartbeat").description("Check and resume pending agent tasks").option("--agent <id>", "Check specific agent").action(async (opts) => {
|
|
1772
|
-
const client = createClient();
|
|
1978
|
+
const client = await createClient();
|
|
1773
1979
|
header("Heartbeat Check");
|
|
1774
1980
|
const args = {};
|
|
1775
1981
|
if (opts.agent) args.agentId = opts.agent;
|
|
@@ -1835,6 +2041,7 @@ registerFilesCommand(program);
|
|
|
1835
2041
|
registerProjectsCommand(program);
|
|
1836
2042
|
registerConfigCommand(program);
|
|
1837
2043
|
registerVaultCommand(program);
|
|
2044
|
+
registerKeysCommand(program);
|
|
1838
2045
|
registerStatusCommand(program);
|
|
1839
2046
|
program.parse();
|
|
1840
2047
|
//# sourceMappingURL=index.js.map
|