@agentmeshhq/agent 0.1.10 → 0.1.12
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/__tests__/injector.test.d.ts +1 -0
- package/dist/__tests__/injector.test.js +26 -0
- package/dist/__tests__/injector.test.js.map +1 -0
- package/dist/cli/build.d.ts +6 -0
- package/dist/cli/build.js +111 -0
- package/dist/cli/build.js.map +1 -0
- package/dist/cli/deploy.d.ts +9 -0
- package/dist/cli/deploy.js +130 -0
- package/dist/cli/deploy.js.map +1 -0
- package/dist/cli/index.js +155 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/list.js +18 -6
- package/dist/cli/list.js.map +1 -1
- package/dist/cli/local.d.ts +9 -0
- package/dist/cli/local.js +139 -0
- package/dist/cli/local.js.map +1 -0
- package/dist/cli/migrate.d.ts +8 -0
- package/dist/cli/migrate.js +167 -0
- package/dist/cli/migrate.js.map +1 -0
- package/dist/cli/slack.d.ts +3 -0
- package/dist/cli/slack.js +57 -0
- package/dist/cli/slack.js.map +1 -0
- package/dist/cli/start.d.ts +4 -0
- package/dist/cli/start.js +5 -0
- package/dist/cli/start.js.map +1 -1
- package/dist/cli/test.d.ts +8 -0
- package/dist/cli/test.js +110 -0
- package/dist/cli/test.js.map +1 -0
- package/dist/config/schema.d.ts +2 -0
- package/dist/core/daemon.d.ts +13 -0
- package/dist/core/daemon.js +100 -27
- package/dist/core/daemon.js.map +1 -1
- package/dist/core/injector.d.ts +6 -1
- package/dist/core/injector.js +64 -1
- package/dist/core/injector.js.map +1 -1
- package/dist/core/tmux.js +11 -13
- package/dist/core/tmux.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/injector.test.ts +29 -0
- package/src/cli/build.ts +137 -0
- package/src/cli/deploy.ts +153 -0
- package/src/cli/index.ts +156 -0
- package/src/cli/list.ts +18 -6
- package/src/cli/local.ts +174 -0
- package/src/cli/migrate.ts +210 -0
- package/src/cli/slack.ts +69 -0
- package/src/cli/start.ts +8 -0
- package/src/cli/test.ts +141 -0
- package/src/config/schema.ts +2 -0
- package/src/core/daemon.ts +123 -35
- package/src/core/injector.ts +98 -1
- package/src/core/tmux.ts +12 -14
package/src/cli/build.ts
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { spawnSync, execSync } from "node:child_process";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import pc from "picocolors";
|
|
4
|
+
|
|
5
|
+
function findProjectRoot(): string {
|
|
6
|
+
let dir = process.cwd();
|
|
7
|
+
for (let i = 0; i < 10; i++) {
|
|
8
|
+
const packageJson = path.join(dir, "package.json");
|
|
9
|
+
const pnpmWorkspace = path.join(dir, "pnpm-workspace.yaml");
|
|
10
|
+
try {
|
|
11
|
+
execSync(`test -f "${packageJson}" && test -f "${pnpmWorkspace}"`, { stdio: "ignore" });
|
|
12
|
+
return dir;
|
|
13
|
+
} catch {
|
|
14
|
+
dir = path.dirname(dir);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
throw new Error("Could not find AgentMesh project root. Make sure you're in the agentmesh repository.");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface BuildOptions {
|
|
21
|
+
docker?: boolean;
|
|
22
|
+
package?: string;
|
|
23
|
+
clean?: boolean;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function build(options: BuildOptions = {}): Promise<void> {
|
|
27
|
+
const projectRoot = findProjectRoot();
|
|
28
|
+
|
|
29
|
+
if (options.docker) {
|
|
30
|
+
await buildDocker(projectRoot, options);
|
|
31
|
+
} else {
|
|
32
|
+
await buildPackages(projectRoot, options);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async function buildPackages(projectRoot: string, options: BuildOptions): Promise<void> {
|
|
37
|
+
console.log(pc.cyan("Building AgentMesh packages..."));
|
|
38
|
+
console.log();
|
|
39
|
+
|
|
40
|
+
const args = ["pnpm"];
|
|
41
|
+
|
|
42
|
+
if (options.package) {
|
|
43
|
+
args.push("--filter", options.package);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (options.clean) {
|
|
47
|
+
console.log(pc.dim("Cleaning build artifacts..."));
|
|
48
|
+
const cleanResult = spawnSync("pnpm", ["-r", "exec", "rm", "-rf", "dist"], {
|
|
49
|
+
cwd: projectRoot,
|
|
50
|
+
stdio: "inherit",
|
|
51
|
+
});
|
|
52
|
+
if (cleanResult.status !== 0) {
|
|
53
|
+
console.warn(pc.yellow("Warning: Clean may have partially failed"));
|
|
54
|
+
}
|
|
55
|
+
console.log();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
args.push("build");
|
|
59
|
+
|
|
60
|
+
const result = spawnSync(args[0], args.slice(1), {
|
|
61
|
+
cwd: projectRoot,
|
|
62
|
+
stdio: "inherit",
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
if (result.status !== 0) {
|
|
66
|
+
console.error(pc.red("Build failed"));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
console.log();
|
|
71
|
+
console.log(pc.green("Build completed successfully!"));
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
async function buildDocker(projectRoot: string, options: BuildOptions): Promise<void> {
|
|
75
|
+
console.log(pc.cyan("Building Docker images..."));
|
|
76
|
+
console.log();
|
|
77
|
+
|
|
78
|
+
// Check if docker is available
|
|
79
|
+
try {
|
|
80
|
+
execSync("docker --version", { stdio: "ignore" });
|
|
81
|
+
} catch {
|
|
82
|
+
console.error(pc.red("Docker is not installed or not running"));
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Use docker buildx bake for multi-image builds
|
|
87
|
+
const dockerDir = path.join(projectRoot, "docker");
|
|
88
|
+
const dockerfilePath = path.join(dockerDir, "Dockerfile");
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
execSync(`test -f "${dockerfilePath}"`, { stdio: "ignore" });
|
|
92
|
+
} catch {
|
|
93
|
+
console.error(pc.red("Dockerfile not found at docker/Dockerfile"));
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Build using docker compose to leverage the existing setup
|
|
98
|
+
const composePath = path.join(dockerDir, "docker-compose.local.yml");
|
|
99
|
+
|
|
100
|
+
const args = ["compose", "-f", composePath, "build"];
|
|
101
|
+
if (options.package) {
|
|
102
|
+
// Map package names to service names
|
|
103
|
+
const serviceMap: Record<string, string> = {
|
|
104
|
+
"@agentmesh/hub": "hub-api",
|
|
105
|
+
"@agentmesh/admin": "admin",
|
|
106
|
+
hub: "hub-api",
|
|
107
|
+
admin: "admin",
|
|
108
|
+
};
|
|
109
|
+
const service = serviceMap[options.package] || options.package;
|
|
110
|
+
args.push(service);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const result = spawnSync("docker", args, {
|
|
114
|
+
cwd: projectRoot,
|
|
115
|
+
stdio: "inherit",
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
if (result.status !== 0) {
|
|
119
|
+
console.error(pc.red("Docker build failed"));
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
console.log();
|
|
124
|
+
console.log(pc.green("Docker images built successfully!"));
|
|
125
|
+
|
|
126
|
+
// List built images
|
|
127
|
+
console.log();
|
|
128
|
+
console.log(pc.bold("Built images:"));
|
|
129
|
+
const listResult = spawnSync(
|
|
130
|
+
"docker",
|
|
131
|
+
["images", "--filter", "reference=*agentmesh*", "--format", "{{.Repository}}:{{.Tag}}\t{{.Size}}"],
|
|
132
|
+
{ encoding: "utf-8" }
|
|
133
|
+
);
|
|
134
|
+
if (listResult.stdout) {
|
|
135
|
+
console.log(pc.dim(listResult.stdout));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { spawnSync, execSync } from "node:child_process";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import pc from "picocolors";
|
|
4
|
+
|
|
5
|
+
function findProjectRoot(): string {
|
|
6
|
+
let dir = process.cwd();
|
|
7
|
+
for (let i = 0; i < 10; i++) {
|
|
8
|
+
const scriptsDir = path.join(dir, "scripts");
|
|
9
|
+
const buildScript = path.join(scriptsDir, "build.sh");
|
|
10
|
+
try {
|
|
11
|
+
execSync(`test -f "${buildScript}"`, { stdio: "ignore" });
|
|
12
|
+
return dir;
|
|
13
|
+
} catch {
|
|
14
|
+
dir = path.dirname(dir);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
throw new Error("Could not find AgentMesh project root. Make sure you're in the agentmesh repository.");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export type DeployEnvironment = "dev" | "staging" | "prod";
|
|
21
|
+
|
|
22
|
+
export interface DeployOptions {
|
|
23
|
+
environment: DeployEnvironment;
|
|
24
|
+
skipBuild?: boolean;
|
|
25
|
+
skipPush?: boolean;
|
|
26
|
+
skipTests?: boolean;
|
|
27
|
+
dryRun?: boolean;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function deploy(options: DeployOptions): Promise<void> {
|
|
31
|
+
const projectRoot = findProjectRoot();
|
|
32
|
+
|
|
33
|
+
console.log(pc.cyan(`Deploying to ${options.environment}...`));
|
|
34
|
+
console.log();
|
|
35
|
+
|
|
36
|
+
// Safety checks
|
|
37
|
+
if (options.environment === "prod") {
|
|
38
|
+
console.log(pc.red("WARNING: You are about to deploy to PRODUCTION"));
|
|
39
|
+
console.log(pc.yellow("Make sure all tests pass and staging deployment is verified."));
|
|
40
|
+
console.log();
|
|
41
|
+
console.log(pc.dim("Press Ctrl+C to cancel, or wait 10 seconds to continue..."));
|
|
42
|
+
await new Promise((resolve) => setTimeout(resolve, 10000));
|
|
43
|
+
console.log();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (options.dryRun) {
|
|
47
|
+
console.log(pc.yellow("[DRY RUN] No actual deployment will be performed"));
|
|
48
|
+
console.log();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Step 1: Build
|
|
52
|
+
if (!options.skipBuild) {
|
|
53
|
+
console.log(pc.bold("Step 1: Building..."));
|
|
54
|
+
|
|
55
|
+
const buildScript = path.join(projectRoot, "scripts", "build.sh");
|
|
56
|
+
const buildArgs = [buildScript, options.environment];
|
|
57
|
+
|
|
58
|
+
if (options.dryRun) {
|
|
59
|
+
console.log(pc.dim(`Would run: ${buildArgs.join(" ")}`));
|
|
60
|
+
} else {
|
|
61
|
+
const result = spawnSync("bash", buildArgs, {
|
|
62
|
+
cwd: projectRoot,
|
|
63
|
+
stdio: "inherit",
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
if (result.status !== 0) {
|
|
67
|
+
console.error(pc.red("Build failed. Aborting deployment."));
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
console.log();
|
|
72
|
+
} else {
|
|
73
|
+
console.log(pc.dim("Skipping build (--skip-build)"));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Step 2: Push to registry
|
|
77
|
+
if (!options.skipPush) {
|
|
78
|
+
console.log(pc.bold("Step 2: Pushing to registry..."));
|
|
79
|
+
|
|
80
|
+
// Get the image tag from git commit
|
|
81
|
+
let tag: string;
|
|
82
|
+
try {
|
|
83
|
+
const commit = execSync("git rev-parse --short HEAD", { encoding: "utf-8" }).trim();
|
|
84
|
+
tag = `${options.environment}-${commit}`;
|
|
85
|
+
} catch {
|
|
86
|
+
console.error(pc.red("Failed to get git commit. Are you in a git repository?"));
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const pushScript = path.join(projectRoot, "scripts", "push.sh");
|
|
91
|
+
const pushArgs = [pushScript, tag];
|
|
92
|
+
|
|
93
|
+
if (options.dryRun) {
|
|
94
|
+
console.log(pc.dim(`Would run: ${pushArgs.join(" ")}`));
|
|
95
|
+
} else {
|
|
96
|
+
const result = spawnSync("bash", pushArgs, {
|
|
97
|
+
cwd: projectRoot,
|
|
98
|
+
stdio: "inherit",
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
if (result.status !== 0) {
|
|
102
|
+
console.error(pc.red("Push failed. Aborting deployment."));
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
console.log();
|
|
107
|
+
} else {
|
|
108
|
+
console.log(pc.dim("Skipping push (--skip-push)"));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Step 3: Deploy to server
|
|
112
|
+
console.log(pc.bold("Step 3: Deploying to server..."));
|
|
113
|
+
|
|
114
|
+
let tag: string;
|
|
115
|
+
try {
|
|
116
|
+
const commit = execSync("git rev-parse --short HEAD", { encoding: "utf-8" }).trim();
|
|
117
|
+
tag = `${options.environment}-${commit}`;
|
|
118
|
+
} catch {
|
|
119
|
+
console.error(pc.red("Failed to get git commit."));
|
|
120
|
+
process.exit(1);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const deployScript = path.join(projectRoot, "scripts", "deploy.sh");
|
|
124
|
+
const deployArgs = [deployScript, options.environment, tag];
|
|
125
|
+
|
|
126
|
+
if (options.dryRun) {
|
|
127
|
+
console.log(pc.dim(`Would run: ${deployArgs.join(" ")}`));
|
|
128
|
+
} else {
|
|
129
|
+
const result = spawnSync("bash", deployArgs, {
|
|
130
|
+
cwd: projectRoot,
|
|
131
|
+
stdio: "inherit",
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
if (result.status !== 0) {
|
|
135
|
+
console.error(pc.red("Deployment failed."));
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
console.log();
|
|
141
|
+
console.log(pc.green(`Successfully deployed to ${options.environment}!`));
|
|
142
|
+
|
|
143
|
+
// Show access info
|
|
144
|
+
const urls: Record<DeployEnvironment, string> = {
|
|
145
|
+
dev: "https://agentmeshhq.dev",
|
|
146
|
+
staging: "https://staging.agentmesh.ai",
|
|
147
|
+
prod: "https://agentmesh.ai",
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
console.log();
|
|
151
|
+
console.log(pc.bold("Access:"));
|
|
152
|
+
console.log(` URL: ${pc.cyan(urls[options.environment])}`);
|
|
153
|
+
}
|
package/src/cli/index.ts
CHANGED
|
@@ -4,16 +4,22 @@ import { createRequire } from "node:module";
|
|
|
4
4
|
import { Command } from "commander";
|
|
5
5
|
import pc from "picocolors";
|
|
6
6
|
import { attach } from "./attach.js";
|
|
7
|
+
import { build } from "./build.js";
|
|
7
8
|
import { configCmd } from "./config.js";
|
|
8
9
|
import { contextCmd } from "./context.js";
|
|
10
|
+
import { deploy } from "./deploy.js";
|
|
9
11
|
import { init } from "./init.js";
|
|
10
12
|
import { list } from "./list.js";
|
|
13
|
+
import { localUp, localDown, localStatus, localLogs } from "./local.js";
|
|
11
14
|
import { logs } from "./logs.js";
|
|
15
|
+
import { migrate } from "./migrate.js";
|
|
12
16
|
import { nudge } from "./nudge.js";
|
|
13
17
|
import { restart } from "./restart.js";
|
|
18
|
+
import { slack } from "./slack.js";
|
|
14
19
|
import { start } from "./start.js";
|
|
15
20
|
import { status } from "./status.js";
|
|
16
21
|
import { stop } from "./stop.js";
|
|
22
|
+
import { test } from "./test.js";
|
|
17
23
|
import { token } from "./token.js";
|
|
18
24
|
import { whoami } from "./whoami.js";
|
|
19
25
|
|
|
@@ -49,8 +55,14 @@ program
|
|
|
49
55
|
.option("-f, --foreground", "Run in foreground (blocking)")
|
|
50
56
|
.option("--no-context", "Start fresh without restoring previous context")
|
|
51
57
|
.option("--auto-setup", "Auto-clone repository for project assignments")
|
|
58
|
+
.option("--serve", "Run opencode serve instead of tmux TUI (for Integration Service)")
|
|
59
|
+
.option("--serve-port <port>", "Port for opencode serve (default: 3001)", "3001")
|
|
52
60
|
.action(async (options) => {
|
|
53
61
|
try {
|
|
62
|
+
// Parse serve port as number
|
|
63
|
+
if (options.servePort) {
|
|
64
|
+
options.servePort = parseInt(options.servePort, 10);
|
|
65
|
+
}
|
|
54
66
|
await start(options);
|
|
55
67
|
} catch (error) {
|
|
56
68
|
console.error(pc.red((error as Error).message));
|
|
@@ -209,4 +221,148 @@ program
|
|
|
209
221
|
}
|
|
210
222
|
});
|
|
211
223
|
|
|
224
|
+
program
|
|
225
|
+
.command("slack")
|
|
226
|
+
.description("Interact with Slack")
|
|
227
|
+
.argument("[action]", "Action: respond")
|
|
228
|
+
.argument("[channel]", "Slack channel ID")
|
|
229
|
+
.argument("[message]", "Message to send")
|
|
230
|
+
.option("-n, --name <name>", "Agent name (default: concierge)")
|
|
231
|
+
.action(async (action, channel, message, options) => {
|
|
232
|
+
try {
|
|
233
|
+
await slack(action || "help", channel, message, options);
|
|
234
|
+
} catch (error) {
|
|
235
|
+
console.error(pc.red((error as Error).message));
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Local development stack commands
|
|
241
|
+
const localCmd = program
|
|
242
|
+
.command("local")
|
|
243
|
+
.description("Manage local development stack (Postgres, Valkey, Hub)");
|
|
244
|
+
|
|
245
|
+
localCmd
|
|
246
|
+
.command("up")
|
|
247
|
+
.description("Start local development stack")
|
|
248
|
+
.option("--no-detach", "Run in foreground")
|
|
249
|
+
.action(async (options) => {
|
|
250
|
+
try {
|
|
251
|
+
await localUp({ detach: options.detach });
|
|
252
|
+
} catch (error) {
|
|
253
|
+
console.error(pc.red((error as Error).message));
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
|
|
258
|
+
localCmd
|
|
259
|
+
.command("down")
|
|
260
|
+
.description("Stop local development stack")
|
|
261
|
+
.action(async () => {
|
|
262
|
+
try {
|
|
263
|
+
await localDown();
|
|
264
|
+
} catch (error) {
|
|
265
|
+
console.error(pc.red((error as Error).message));
|
|
266
|
+
process.exit(1);
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
localCmd
|
|
271
|
+
.command("status")
|
|
272
|
+
.description("Show local stack status and ports")
|
|
273
|
+
.action(async () => {
|
|
274
|
+
try {
|
|
275
|
+
await localStatus();
|
|
276
|
+
} catch (error) {
|
|
277
|
+
console.error(pc.red((error as Error).message));
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
localCmd
|
|
283
|
+
.command("logs")
|
|
284
|
+
.description("View local stack logs")
|
|
285
|
+
.option("-f, --follow", "Follow log output")
|
|
286
|
+
.option("-s, --service <name>", "Specific service to show logs for")
|
|
287
|
+
.action(async (options) => {
|
|
288
|
+
try {
|
|
289
|
+
await localLogs({ follow: options.follow, service: options.service });
|
|
290
|
+
} catch (error) {
|
|
291
|
+
console.error(pc.red((error as Error).message));
|
|
292
|
+
process.exit(1);
|
|
293
|
+
}
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// Build commands
|
|
297
|
+
program
|
|
298
|
+
.command("build")
|
|
299
|
+
.description("Build packages or Docker images")
|
|
300
|
+
.option("--docker", "Build Docker images instead of packages")
|
|
301
|
+
.option("-p, --package <name>", "Build specific package")
|
|
302
|
+
.option("--clean", "Clean build artifacts before building")
|
|
303
|
+
.action(async (options) => {
|
|
304
|
+
try {
|
|
305
|
+
await build(options);
|
|
306
|
+
} catch (error) {
|
|
307
|
+
console.error(pc.red((error as Error).message));
|
|
308
|
+
process.exit(1);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
// Test commands
|
|
313
|
+
program
|
|
314
|
+
.command("test")
|
|
315
|
+
.description("Run tests")
|
|
316
|
+
.option("-p, --package <name>", "Test specific package")
|
|
317
|
+
.option("--e2e", "Run E2E tests")
|
|
318
|
+
.option("-w, --watch", "Watch mode")
|
|
319
|
+
.option("--coverage", "Generate coverage report")
|
|
320
|
+
.option("-u, --update-snapshots", "Update test snapshots")
|
|
321
|
+
.action(async (options) => {
|
|
322
|
+
try {
|
|
323
|
+
await test(options);
|
|
324
|
+
} catch (error) {
|
|
325
|
+
console.error(pc.red((error as Error).message));
|
|
326
|
+
process.exit(1);
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
|
|
330
|
+
// Migration commands
|
|
331
|
+
program
|
|
332
|
+
.command("migrate")
|
|
333
|
+
.description("Run database migrations")
|
|
334
|
+
.option("--dev", "Run against agentmeshhq.dev")
|
|
335
|
+
.option("--staging", "Run against staging")
|
|
336
|
+
.option("--generate", "Generate migration from schema changes")
|
|
337
|
+
.option("--status", "Show migration status")
|
|
338
|
+
.action(async (options) => {
|
|
339
|
+
try {
|
|
340
|
+
await migrate(options);
|
|
341
|
+
} catch (error) {
|
|
342
|
+
console.error(pc.red((error as Error).message));
|
|
343
|
+
process.exit(1);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
// Deploy commands
|
|
348
|
+
program
|
|
349
|
+
.command("deploy")
|
|
350
|
+
.description("Deploy to environment")
|
|
351
|
+
.argument("<environment>", "Target environment: dev, staging, prod")
|
|
352
|
+
.option("--skip-build", "Skip build step")
|
|
353
|
+
.option("--skip-push", "Skip push to registry")
|
|
354
|
+
.option("--dry-run", "Show what would be done without executing")
|
|
355
|
+
.action(async (environment, options) => {
|
|
356
|
+
try {
|
|
357
|
+
if (!["dev", "staging", "prod"].includes(environment)) {
|
|
358
|
+
console.error(pc.red(`Invalid environment: ${environment}. Use: dev, staging, or prod`));
|
|
359
|
+
process.exit(1);
|
|
360
|
+
}
|
|
361
|
+
await deploy({ environment, ...options });
|
|
362
|
+
} catch (error) {
|
|
363
|
+
console.error(pc.red((error as Error).message));
|
|
364
|
+
process.exit(1);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
|
|
212
368
|
program.parse();
|
package/src/cli/list.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { loadState, loadConfig } from "../config/loader.js";
|
|
2
2
|
import { sessionExists, getSessionName, getSessionInfo } from "../core/tmux.js";
|
|
3
|
-
import { checkInbox } from "../core/registry.js";
|
|
3
|
+
import { checkInbox, fetchAssignments } from "../core/registry.js";
|
|
4
4
|
import pc from "picocolors";
|
|
5
5
|
|
|
6
6
|
export async function list(): Promise<void> {
|
|
@@ -15,9 +15,9 @@ export async function list(): Promise<void> {
|
|
|
15
15
|
|
|
16
16
|
console.log(pc.bold("Running Agents:\n"));
|
|
17
17
|
console.log(
|
|
18
|
-
`${"NAME".padEnd(20)} ${"STATUS".padEnd(10)} ${"SESSION".padEnd(25)} ${"PENDING"}`
|
|
18
|
+
`${"NAME".padEnd(20)} ${"STATUS".padEnd(10)} ${"SESSION".padEnd(25)} ${"PENDING ID".padEnd(18)} ${"WORKDIR".padEnd(38)} ${"PROJECT"}`
|
|
19
19
|
);
|
|
20
|
-
console.log("-".repeat(
|
|
20
|
+
console.log("-".repeat(140));
|
|
21
21
|
|
|
22
22
|
for (const agent of state.agents) {
|
|
23
23
|
const sessionName = getSessionName(agent.name);
|
|
@@ -29,7 +29,8 @@ export async function list(): Promise<void> {
|
|
|
29
29
|
status = pc.red("offline");
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
let
|
|
32
|
+
let pendingId = pc.dim("-");
|
|
33
|
+
let assignedProject = agent.assignedProject || "-";
|
|
33
34
|
|
|
34
35
|
// Try to check inbox if we have a token
|
|
35
36
|
if (config && agent.token) {
|
|
@@ -40,7 +41,17 @@ export async function list(): Promise<void> {
|
|
|
40
41
|
agent.token
|
|
41
42
|
);
|
|
42
43
|
if (items.length > 0) {
|
|
43
|
-
|
|
44
|
+
const firstId = items[0]?.id || "-";
|
|
45
|
+
pendingId = pc.yellow(items.length === 1 ? firstId : `${firstId} (+${items.length - 1})`);
|
|
46
|
+
}
|
|
47
|
+
} catch {
|
|
48
|
+
// Ignore errors
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const assignments = await fetchAssignments(config.hubUrl, agent.token);
|
|
53
|
+
if (assignments.length > 0) {
|
|
54
|
+
assignedProject = assignments.map((a) => a.project.name).join(", ");
|
|
44
55
|
}
|
|
45
56
|
} catch {
|
|
46
57
|
// Ignore errors
|
|
@@ -48,9 +59,10 @@ export async function list(): Promise<void> {
|
|
|
48
59
|
}
|
|
49
60
|
|
|
50
61
|
const command = info.command ? pc.dim(`(${info.command})`) : "";
|
|
62
|
+
const workdir = agent.workdir || "-";
|
|
51
63
|
|
|
52
64
|
console.log(
|
|
53
|
-
`${agent.name.padEnd(20)} ${status.padEnd(19)} ${sessionName.padEnd(25)} ${
|
|
65
|
+
`${agent.name.padEnd(20)} ${status.padEnd(19)} ${sessionName.padEnd(25)} ${pendingId.padEnd(18)} ${workdir.padEnd(38)} ${assignedProject}`
|
|
54
66
|
);
|
|
55
67
|
|
|
56
68
|
if (command) {
|