agor-live 0.3.15 → 0.4.2

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.
@@ -7,8 +7,14 @@
7
7
  * The daemon is compiled from apps/agor-daemon and bundled during build.
8
8
  */
9
9
 
10
- import path from 'node:path';
11
- import { fileURLToPath } from 'node:url';
10
+ // Check Node.js version requirement before loading any dependencies
11
+ import { checkNodeVersion } from './version-check.js';
12
+
13
+ checkNodeVersion();
14
+
15
+ // Use dynamic imports to ensure version check runs first
16
+ const path = await import('node:path');
17
+ const { fileURLToPath } = await import('node:url');
12
18
 
13
19
  // Get directory of this file
14
20
  const dirname = path.dirname(fileURLToPath(import.meta.url));
package/bin/agor.js CHANGED
@@ -7,7 +7,13 @@
7
7
  * The CLI commands are compiled from apps/agor-cli and bundled during build.
8
8
  */
9
9
 
10
- import { execute } from '@oclif/core';
10
+ // Check Node.js version requirement before loading any dependencies
11
+ import { checkNodeVersion } from './version-check.js';
12
+
13
+ checkNodeVersion();
14
+
15
+ // Use dynamic import to ensure version check runs first
16
+ const { execute } = await import('@oclif/core');
11
17
 
12
18
  // oclif will resolve commands relative to this file
13
19
  // Commands are at ../dist/cli/commands (configured in package.json)
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Node.js version check utility
3
+ * Used by CLI and daemon entry points to ensure Node 20+ requirement
4
+ */
5
+
6
+ import chalk from 'chalk';
7
+
8
+ export function checkNodeVersion() {
9
+ const nodeVersion = process.versions.node;
10
+ const majorVersion = parseInt(nodeVersion.split('.')[0], 10);
11
+
12
+ if (majorVersion < 20) {
13
+ console.error(chalk.red('✖ Error: Agor requires Node.js v20.0.0 or higher'));
14
+ console.error(chalk.yellow(` Current version: v${nodeVersion}\n`));
15
+ console.error('Please upgrade Node.js:');
16
+ console.error(` • Using nvm: ${chalk.cyan('nvm install 20 && nvm use 20')}`);
17
+ console.error(` • Download: ${chalk.cyan('https://nodejs.org/')}\n`);
18
+ process.exit(1);
19
+ }
20
+ }
@@ -214,6 +214,10 @@ var Init = class _Init extends Command {
214
214
  if (!skipPrompts) {
215
215
  await this.promptAuthSetup(dbPath);
216
216
  await this.promptApiKeys();
217
+ } else {
218
+ await setConfigValue("daemon.requireAuth", true);
219
+ await setConfigValue("daemon.allowAnonymous", false);
220
+ this.log(`${chalk.green(" \u2713")} Enabled authentication (multiplayer mode)`);
217
221
  }
218
222
  this.log("");
219
223
  this.log(chalk.green.bold("\u2705 Agor initialized successfully!"));
@@ -0,0 +1,13 @@
1
+ import { Command } from '@oclif/core';
2
+
3
+ /**
4
+ * `agor open` - Open Agor UI in browser
5
+ */
6
+
7
+ declare class Open extends Command {
8
+ static description: string;
9
+ static examples: string[];
10
+ run(): Promise<void>;
11
+ }
12
+
13
+ export { Open as default };
@@ -0,0 +1,90 @@
1
+ // src/commands/open.ts
2
+ import { exec } from "child_process";
3
+ import { promisify } from "util";
4
+ import { isDaemonRunning } from "@agor/core/api";
5
+ import { getDaemonUrl } from "@agor/core/config";
6
+ import { Command } from "@oclif/core";
7
+ import chalk from "chalk";
8
+
9
+ // src/lib/context.ts
10
+ import path from "path";
11
+ import { fileURLToPath } from "url";
12
+ function isInstalledPackage() {
13
+ const dirname = typeof __dirname !== "undefined" ? __dirname : path.dirname(fileURLToPath(import.meta.url));
14
+ const isInMonorepoSource = dirname.includes("/apps/agor-cli/") || dirname.includes("\\apps\\agor-cli\\");
15
+ return !isInMonorepoSource;
16
+ }
17
+ function isCodespaces() {
18
+ return !!process.env.CODESPACE_NAME && !!process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN;
19
+ }
20
+ function getUIUrl() {
21
+ if (isCodespaces()) {
22
+ const codespaceName = process.env.CODESPACE_NAME;
23
+ const domain = process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN;
24
+ if (isInstalledPackage()) {
25
+ return `https://${codespaceName}-3030.${domain}/ui`;
26
+ } else {
27
+ return `https://${codespaceName}-5173.${domain}`;
28
+ }
29
+ }
30
+ if (isInstalledPackage()) {
31
+ return "http://localhost:3030/ui";
32
+ } else {
33
+ return "http://localhost:5173";
34
+ }
35
+ }
36
+
37
+ // src/commands/open.ts
38
+ var execAsync = promisify(exec);
39
+ var Open = class extends Command {
40
+ static description = "Open Agor UI in browser";
41
+ static examples = ["<%= config.bin %> <%= command.id %>"];
42
+ async run() {
43
+ const daemonUrl = await getDaemonUrl();
44
+ const running = await isDaemonRunning(daemonUrl);
45
+ if (!running) {
46
+ this.log(chalk.red("\u2717 Daemon is not running"));
47
+ this.log("");
48
+ this.log("Start the daemon first:");
49
+ this.log(" " + chalk.cyan("agor daemon start"));
50
+ this.log("");
51
+ this.exit(1);
52
+ }
53
+ const uiUrl = getUIUrl();
54
+ if (isCodespaces()) {
55
+ this.log(chalk.green("\u2713 Agor UI is ready"));
56
+ this.log("");
57
+ this.log("Open this URL in your browser:");
58
+ this.log(" " + chalk.cyan(uiUrl));
59
+ this.log("");
60
+ this.log(chalk.dim("(GitHub Codespaces will automatically forward the port)"));
61
+ this.log("");
62
+ return;
63
+ }
64
+ try {
65
+ this.log(chalk.green("Opening Agor UI in browser..."));
66
+ this.log(chalk.dim(`URL: ${uiUrl}`));
67
+ this.log("");
68
+ const platform = process.platform;
69
+ let command;
70
+ if (platform === "darwin") {
71
+ command = `open "${uiUrl}"`;
72
+ } else if (platform === "win32") {
73
+ command = `start "" "${uiUrl}"`;
74
+ } else {
75
+ command = `xdg-open "${uiUrl}"`;
76
+ }
77
+ await execAsync(command);
78
+ this.log(chalk.green("\u2713 Browser opened"));
79
+ } catch (error) {
80
+ this.log(chalk.yellow("\u26A0 Could not open browser automatically"));
81
+ this.log("");
82
+ this.log("Visit this URL manually:");
83
+ this.log(" " + chalk.cyan(uiUrl));
84
+ this.log("");
85
+ }
86
+ }
87
+ };
88
+ export {
89
+ Open as default
90
+ };
@@ -17,6 +17,12 @@ declare function isInstalledPackage(): boolean;
17
17
  * @returns path to daemon binary, or null if in development
18
18
  */
19
19
  declare function getDaemonPath(): string | null;
20
+ /**
21
+ * Check if running in GitHub Codespaces
22
+ *
23
+ * @returns true if running in Codespaces
24
+ */
25
+ declare function isCodespaces(): boolean;
20
26
  /**
21
27
  * Get appropriate UI URL based on context
22
28
  *
@@ -24,4 +30,4 @@ declare function getDaemonPath(): string | null;
24
30
  */
25
31
  declare function getUIUrl(): string;
26
32
 
27
- export { getDaemonPath, getUIUrl, isInstalledPackage };
33
+ export { getDaemonPath, getUIUrl, isCodespaces, isInstalledPackage };
@@ -18,7 +18,19 @@ function getDaemonPath() {
18
18
  const packageRoot = dirname.substring(0, cliDistIndex);
19
19
  return path.join(packageRoot, "dist", "daemon", "index.js");
20
20
  }
21
+ function isCodespaces() {
22
+ return !!process.env.CODESPACE_NAME && !!process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN;
23
+ }
21
24
  function getUIUrl() {
25
+ if (isCodespaces()) {
26
+ const codespaceName = process.env.CODESPACE_NAME;
27
+ const domain = process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN;
28
+ if (isInstalledPackage()) {
29
+ return `https://${codespaceName}-3030.${domain}/ui`;
30
+ } else {
31
+ return `https://${codespaceName}-5173.${domain}`;
32
+ }
33
+ }
22
34
  if (isInstalledPackage()) {
23
35
  return "http://localhost:3030/ui";
24
36
  } else {
@@ -28,5 +40,6 @@ function getUIUrl() {
28
40
  export {
29
41
  getDaemonPath,
30
42
  getUIUrl,
43
+ isCodespaces,
31
44
  isInstalledPackage
32
45
  };
@@ -733,6 +733,7 @@ import { homedir as homedir2 } from "os";
733
733
  import { join as join3 } from "path";
734
734
  import cors from "cors";
735
735
  import express from "express";
736
+ import swagger from "feathers-swagger";
736
737
  import jwt from "jsonwebtoken";
737
738
 
738
739
  // src/services/board-comments.ts
@@ -3066,6 +3067,31 @@ async function main() {
3066
3067
  app.publish(() => {
3067
3068
  return app.channel("everybody");
3068
3069
  });
3070
+ app.configure(
3071
+ swagger({
3072
+ openApiVersion: 3,
3073
+ docsPath: "/docs",
3074
+ docsJsonPath: "/docs.json",
3075
+ ui: swagger.swaggerUI({ docsPath: "/docs" }),
3076
+ specs: {
3077
+ info: {
3078
+ title: "Agor API",
3079
+ description: "REST and WebSocket API for Agor agent orchestration platform",
3080
+ version: DAEMON_VERSION
3081
+ },
3082
+ servers: [{ url: `http://localhost:${DAEMON_PORT}`, description: "Local daemon" }],
3083
+ components: {
3084
+ securitySchemes: {
3085
+ BearerAuth: {
3086
+ type: "http",
3087
+ scheme: "bearer",
3088
+ bearerFormat: "JWT"
3089
+ }
3090
+ }
3091
+ }
3092
+ }
3093
+ })
3094
+ );
3069
3095
  console.log(`\u{1F4E6} Connecting to database: ${DB_PATH}`);
3070
3096
  const dbFilePath = DB_PATH.startsWith("file:") ? DB_PATH.slice(5) : DB_PATH;
3071
3097
  const dbDir = dbFilePath.substring(0, dbFilePath.lastIndexOf("/"));
@@ -3101,7 +3127,28 @@ async function main() {
3101
3127
  app.use("/tasks", createTasksService(db));
3102
3128
  const messagesService = createMessagesService(db);
3103
3129
  app.use("/messages", messagesService, {
3104
- events: ["streaming:start", "streaming:chunk", "streaming:end", "streaming:error"]
3130
+ events: ["streaming:start", "streaming:chunk", "streaming:end", "streaming:error"],
3131
+ docs: {
3132
+ description: "Conversation messages within AI agent sessions",
3133
+ definitions: {
3134
+ messages: {
3135
+ type: "object",
3136
+ properties: {
3137
+ message_id: { type: "string", format: "uuid" },
3138
+ session_id: { type: "string", format: "uuid" },
3139
+ task_id: { type: "string", format: "uuid" },
3140
+ type: {
3141
+ type: "string",
3142
+ enum: ["user", "assistant", "system", "tool_use", "tool_result"]
3143
+ },
3144
+ role: { type: "string" },
3145
+ content: { type: "string" },
3146
+ created_at: { type: "string", format: "date-time" }
3147
+ }
3148
+ }
3149
+ }
3150
+ }
3151
+ // biome-ignore lint/suspicious/noExplicitAny: feathers-swagger docs option not typed in FeathersJS
3105
3152
  });
3106
3153
  app.use("/boards", createBoardsService(db));
3107
3154
  app.use("/board-objects", createBoardObjectsService(db));