ework-aio 0.5.9 → 0.5.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ework-aio",
3
- "version": "0.5.9",
3
+ "version": "0.5.11",
4
4
  "description": "All-in-one installer for ework (issue tracker) + ework-daemon (AI bridge) + opencode-ework (plugin). One command: npm i -g ework-aio && ework-aio install.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -47,6 +47,7 @@
47
47
  },
48
48
  "dependencies": {
49
49
  "ework-daemon": "^0.4.1",
50
+ "ework-router": "^0.1.0",
50
51
  "ework-web": "^0.10.1",
51
52
  "opencode-ework": "^0.1.0",
52
53
  "zod": "^3.23.0"
package/src/cli.ts CHANGED
@@ -62,12 +62,12 @@ Commands:
62
62
  config get <KEY> Print current value of one key
63
63
  config set <KEY> <VALUE> Set a key, then restart affected service
64
64
  (unless --no-restart is given)
65
- config restart <web|daemon|both>
66
- Restart one or both services
65
+ config restart <web|daemon|router|both>
66
+ Restart one or all services
67
67
 
68
- start [web|daemon|both] Start services in PID-file mode (default both)
69
- stop [web|daemon|both] Stop services (SIGTERM, 5s grace, then SIGKILL)
70
- restart [web|daemon|both] Stop + start
68
+ start [web|daemon|router|both] Start services in PID-file mode (default both)
69
+ stop [web|daemon|router|both] Stop services (SIGTERM, 5s grace, then SIGKILL)
70
+ restart [web|daemon|router|both] Stop + start
71
71
  add-daemon [port] Start an additional daemon instance
72
72
  ps Show PID-file mode status (alias for 'status')
73
73
 
@@ -306,9 +306,9 @@ export function parseArgs(argv: string[]): ParsedArgs {
306
306
 
307
307
  function parseServiceTarget(arg: string | undefined): ServiceTarget {
308
308
  if (arg === undefined || arg === "") return "both";
309
- if (arg === "web" || arg === "daemon" || arg === "both") return arg;
309
+ if (arg === "web" || arg === "daemon" || arg === "router" || arg === "both") return arg;
310
310
  throw new InstallError(
311
- `Invalid service target '${arg}'. Expected: web | daemon | both`,
311
+ `Invalid service target '${arg}'. Expected: web | daemon | router | both`,
312
312
  );
313
313
  }
314
314
 
@@ -36,7 +36,7 @@ export interface ServicePaths {
36
36
  portKey: string | null;
37
37
  }
38
38
 
39
- function servicePaths(paths: PathConfig, svc: "web" | "daemon"): ServicePaths {
39
+ function servicePaths(paths: PathConfig, svc: "web" | "daemon" | "router"): ServicePaths {
40
40
  if (svc === "web") {
41
41
  return {
42
42
  bin: "ework-web",
@@ -49,6 +49,18 @@ function servicePaths(paths: PathConfig, svc: "web" | "daemon"): ServicePaths {
49
49
  portKey: "WORK_PORT",
50
50
  };
51
51
  }
52
+ if (svc === "router") {
53
+ return {
54
+ bin: "ework-router",
55
+ pkg: "ework-router",
56
+ binRelPath: "bin/ework-router.js",
57
+ dataDir: paths.routerDataDir,
58
+ envFile: paths.routerEnvFile,
59
+ pidFile: paths.routerPidFile,
60
+ logFile: paths.routerLogFile,
61
+ portKey: "ROUTER_PORT",
62
+ };
63
+ }
52
64
  return {
53
65
  bin: "ework-daemon-server",
54
66
  pkg: "ework-daemon",
@@ -95,7 +107,7 @@ async function readLogTail(logFile: string, maxLines: number): Promise<string |
95
107
  }
96
108
 
97
109
  async function startOne(
98
- svc: "web" | "daemon",
110
+ svc: "web" | "daemon" | "router",
99
111
  paths: PathConfig,
100
112
  logger: Logger,
101
113
  ): Promise<boolean> {
@@ -140,7 +152,7 @@ export async function startFromSp(
140
152
  return true;
141
153
  }
142
154
 
143
- async function stopOne(svc: "web" | "daemon", paths: PathConfig, logger: Logger): Promise<boolean> {
155
+ async function stopOne(svc: "web" | "daemon" | "router", paths: PathConfig, logger: Logger): Promise<boolean> {
144
156
  const sp = servicePaths(paths, svc);
145
157
  return stopFromSp(sp, svc, logger);
146
158
  }
@@ -194,8 +206,9 @@ function iterDaemonInstances(
194
206
  }));
195
207
  }
196
208
 
197
- function targets(target: ServiceTarget): Array<"web" | "daemon"> {
198
- return target === "both" ? ["web", "daemon"] : [target];
209
+ function targets(target: ServiceTarget): Array<"web" | "daemon" | "router"> {
210
+ if (target === "both") return ["web", "daemon", "router"];
211
+ return [target];
199
212
  }
200
213
 
201
214
  function iterTargets(
@@ -206,6 +219,8 @@ function iterTargets(
206
219
  for (const svc of targets(target)) {
207
220
  if (svc === "web") {
208
221
  out.push({ sp: servicePaths(paths, "web"), label: "web" });
222
+ } else if (svc === "router") {
223
+ out.push({ sp: servicePaths(paths, "router"), label: "router" });
209
224
  } else {
210
225
  const insts = iterDaemonInstances(paths);
211
226
  if (insts.length === 0) {
@@ -269,6 +284,7 @@ export async function runStatus(opts: GlobalOptions, logger: Logger): Promise<St
269
284
 
270
285
  const probeTargets: Array<{ sp: ServicePaths; label: string }> = [
271
286
  { sp: servicePaths(paths, "web"), label: "web" },
287
+ { sp: servicePaths(paths, "router"), label: "router" },
272
288
  ];
273
289
  const daemonInsts = iterDaemonInstances(paths);
274
290
  if (daemonInsts.length === 0) {
package/src/config.ts CHANGED
@@ -81,6 +81,7 @@ export const DAEMON_ENV_KEYS: readonly EnvKeySpec[] = [
81
81
  { envVar: "DAEMON_ENV", file: "daemon", generate: () => "production" },
82
82
  { envVar: "DAEMON_PORT", file: "daemon", generate: (c) => String(c.daemonPort) },
83
83
  { envVar: "DAEMON_HOST", file: "daemon", generate: () => "127.0.0.1" },
84
+ { envVar: "DAEMON_ENDPOINT", file: "daemon", generate: (c) => `127.0.0.1:${c.daemonPort}` },
84
85
  { envVar: "DAEMON_DB_PATH", file: "daemon", generate: (c) => c.paths.daemonDbPath },
85
86
  { envVar: "GITEA_URL", file: "daemon", generate: (c) => `http://127.0.0.1:${c.workPort}` },
86
87
  // These tokens come from the bot bootstrap flow — empty placeholder here,
package/src/paths.ts CHANGED
@@ -24,8 +24,10 @@ export interface PathConfig {
24
24
  dataDir: string;
25
25
  webDataDir: string;
26
26
  daemonDataDir: string;
27
+ routerDataDir: string;
27
28
  webEnvFile: string;
28
29
  daemonEnvFile: string;
30
+ routerEnvFile: string;
29
31
  runDir: string;
30
32
  botTokenFile: string;
31
33
  opencodeWorkdir: string;
@@ -35,10 +37,13 @@ export interface PathConfig {
35
37
  webAttachmentRoot: string;
36
38
  webPidFile: string;
37
39
  daemonPidFile: string;
40
+ routerPidFile: string;
38
41
  webLogFile: string;
39
42
  daemonLogFile: string;
40
- webUnitFile: string | null; // null when not using systemd
43
+ routerLogFile: string;
44
+ webUnitFile: string | null;
41
45
  daemonUnitFile: string | null;
46
+ routerUnitFile: string | null;
42
47
  }
43
48
 
44
49
  export interface ResolvePathsOptions {
@@ -63,6 +68,7 @@ export function resolvePaths(opts: ResolvePathsOptions): PathConfig {
63
68
  const dataDir = opts.dataDir || path.join(xdgDataHome, "ework-aio");
64
69
  const webDataDir = path.join(dataDir, "ework-web");
65
70
  const daemonDataDir = path.join(dataDir, "ework-daemon");
71
+ const routerDataDir = path.join(dataDir, "ework-router");
66
72
  const runDir = path.join(dataDir, "run");
67
73
 
68
74
  // Unit file location depends on scope and whether systemd is opted-in
@@ -77,8 +83,10 @@ export function resolvePaths(opts: ResolvePathsOptions): PathConfig {
77
83
  dataDir,
78
84
  webDataDir,
79
85
  daemonDataDir,
86
+ routerDataDir,
80
87
  webEnvFile: path.join(webDataDir, ".env"),
81
88
  daemonEnvFile: path.join(daemonDataDir, ".env"),
89
+ routerEnvFile: path.join(routerDataDir, ".env"),
82
90
  runDir,
83
91
  botTokenFile: path.join(dataDir, "bot-token"),
84
92
  opencodeWorkdir: path.join(dataDir, "opencode-workdir"),
@@ -88,10 +96,13 @@ export function resolvePaths(opts: ResolvePathsOptions): PathConfig {
88
96
  webAttachmentRoot: path.join(webDataDir, "attachments"),
89
97
  webPidFile: path.join(runDir, "web.pid"),
90
98
  daemonPidFile: path.join(runDir, "daemon.pid"),
99
+ routerPidFile: path.join(runDir, "router.pid"),
91
100
  webLogFile: path.join(runDir, "web.log"),
92
101
  daemonLogFile: path.join(runDir, "daemon.log"),
102
+ routerLogFile: path.join(runDir, "router.log"),
93
103
  webUnitFile: unitDir ? path.join(unitDir, "ework-web.service") : null,
94
104
  daemonUnitFile: unitDir ? path.join(unitDir, "ework-daemon.service") : null,
105
+ routerUnitFile: unitDir ? path.join(unitDir, "ework-router.service") : null,
95
106
  };
96
107
  }
97
108
 
package/src/types.ts CHANGED
@@ -10,7 +10,7 @@ export type Scope = "user" | "system";
10
10
 
11
11
  // Which service(s) a command targets. `ps` and `status` use "both";
12
12
  // `start web`/`stop daemon` use a single target.
13
- export type ServiceTarget = "web" | "daemon" | "both";
13
+ export type ServiceTarget = "web" | "daemon" | "router" | "both";
14
14
 
15
15
  export interface GlobalOptions {
16
16
  // Install-time knobs (defaults live in src/types.ts DEFAULTS).