electric-ax 0.2.5 → 0.2.8

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.
@@ -30,6 +30,7 @@ const AGENTS_COMMANDS = [
30
30
  `observe`,
31
31
  `inspect`,
32
32
  `ps`,
33
+ `signal`,
33
34
  `kill`,
34
35
  `start`,
35
36
  `start-builtin`,
@@ -43,6 +44,7 @@ const COMMAND_FLAGS = {
43
44
  spawn: [`--args`],
44
45
  send: [`--type`, `--json`],
45
46
  observe: [`--from`],
47
+ signal: [`--reason`, `--payload`],
46
48
  ps: [
47
49
  `--type`,
48
50
  `--status`,
@@ -74,8 +76,18 @@ const ENTITY_URL_COMMANDS = new Set([
74
76
  `send`,
75
77
  `observe`,
76
78
  `inspect`,
79
+ `signal`,
77
80
  `kill`
78
81
  ]);
82
+ const ENTITY_SIGNALS = [
83
+ `SIGINT`,
84
+ `SIGHUP`,
85
+ `SIGTERM`,
86
+ `SIGKILL`,
87
+ `SIGSTOP`,
88
+ `SIGCONT`,
89
+ `SIGUSR`
90
+ ];
79
91
  function setupCompletions(env, commandName) {
80
92
  const completion = omelette(`${commandName} <namespace> <command> <arg1> <arg2>`);
81
93
  completion.on(`namespace`, ({ reply }) => {
@@ -125,6 +137,10 @@ function setupCompletions(env, commandName) {
125
137
  reply(fetchEntityTypeNames(env));
126
138
  return;
127
139
  }
140
+ if (command === `signal`) {
141
+ reply(Promise.resolve(ENTITY_SIGNALS));
142
+ return;
143
+ }
128
144
  reply(Promise.resolve([]));
129
145
  });
130
146
  completion.init();
@@ -32,6 +32,7 @@ const AGENTS_COMMANDS = [
32
32
  `observe`,
33
33
  `inspect`,
34
34
  `ps`,
35
+ `signal`,
35
36
  `kill`,
36
37
  `start`,
37
38
  `start-builtin`,
@@ -45,6 +46,7 @@ const COMMAND_FLAGS = {
45
46
  spawn: [`--args`],
46
47
  send: [`--type`, `--json`],
47
48
  observe: [`--from`],
49
+ signal: [`--reason`, `--payload`],
48
50
  ps: [
49
51
  `--type`,
50
52
  `--status`,
@@ -76,8 +78,18 @@ const ENTITY_URL_COMMANDS = new Set([
76
78
  `send`,
77
79
  `observe`,
78
80
  `inspect`,
81
+ `signal`,
79
82
  `kill`
80
83
  ]);
84
+ const ENTITY_SIGNALS = [
85
+ `SIGINT`,
86
+ `SIGHUP`,
87
+ `SIGTERM`,
88
+ `SIGKILL`,
89
+ `SIGSTOP`,
90
+ `SIGCONT`,
91
+ `SIGUSR`
92
+ ];
81
93
  function setupCompletions(env, commandName) {
82
94
  const completion = (0, omelette.default)(`${commandName} <namespace> <command> <arg1> <arg2>`);
83
95
  completion.on(`namespace`, ({ reply }) => {
@@ -127,6 +139,10 @@ function setupCompletions(env, commandName) {
127
139
  reply(fetchEntityTypeNames(env));
128
140
  return;
129
141
  }
142
+ if (command === `signal`) {
143
+ reply(Promise.resolve(ENTITY_SIGNALS));
144
+ return;
145
+ }
130
146
  reply(Promise.resolve([]));
131
147
  });
132
148
  completion.init();
@@ -1,4 +1,4 @@
1
- const require_completions = require('./completions-Bj4D5DRa.cjs');
1
+ const require_completions = require('./completions-BeohCOLD.cjs');
2
2
 
3
3
  exports.fetchEntityTypeNames = require_completions.fetchEntityTypeNames
4
4
  exports.fetchEntityUrls = require_completions.fetchEntityUrls
@@ -1,4 +1,4 @@
1
- import { ElectricCliEnv } from "./index-OgX1QS9Q.cjs";
1
+ import { ElectricCliEnv } from "./index-DmR3DeFk.cjs";
2
2
 
3
3
  //#region src/completions.d.ts
4
4
  declare function fetchEntityTypeNames(env: ElectricCliEnv): Promise<Array<string>>;
@@ -1,4 +1,4 @@
1
- import { ElectricCliEnv } from "./index-CwRI9tWl.js";
1
+ import { ElectricCliEnv } from "./index-BsITLCxF.js";
2
2
 
3
3
  //#region src/completions.d.ts
4
4
  declare function fetchEntityTypeNames(env: ElectricCliEnv): Promise<Array<string>>;
@@ -1,3 +1,3 @@
1
- import { fetchEntityTypeNames, fetchEntityUrls, installCompletions, setupCompletions } from "./completions-B-Lf28Wy.js";
1
+ import { fetchEntityTypeNames, fetchEntityUrls, installCompletions, setupCompletions } from "./completions-3RE2mC2p.js";
2
2
 
3
3
  export { fetchEntityTypeNames, fetchEntityUrls, installCompletions, setupCompletions };
@@ -61,6 +61,11 @@ interface SendCommandOptions {
61
61
  type?: string;
62
62
  json?: boolean;
63
63
  }
64
+ type EntitySignal = `SIGINT` | `SIGHUP` | `SIGTERM` | `SIGKILL` | `SIGSTOP` | `SIGCONT` | `SIGUSR`;
65
+ interface SignalCommandOptions {
66
+ reason?: string;
67
+ payload?: string;
68
+ }
64
69
  interface ObserveCommandOptions {
65
70
  from?: string;
66
71
  }
@@ -85,6 +90,7 @@ interface ElectricCliHandlers {
85
90
  observe: (url: string, options: ObserveCommandOptions) => Promise<void>;
86
91
  inspect: (url: string) => Promise<void>;
87
92
  ps: (options: PsCommandOptions) => Promise<void>;
93
+ signal: (url: string, signal: string, options: SignalCommandOptions) => Promise<void>;
88
94
  kill: (url: string) => Promise<void>;
89
95
  start: (options: StartCommandOptions) => Promise<StartedDevEnvironment>;
90
96
  startBuiltin: (options: StartBuiltinCommandOptions) => Promise<StartedBuiltinAgentsEnvironment>;
@@ -125,4 +131,4 @@ declare function createElectricProgram({
125
131
  declare function run(argv?: Array<string>): Promise<void>;
126
132
 
127
133
  //#endregion
128
- export { DEFAULT_ELECTRIC_AGENTS_URL, ElectricCliEnv, ElectricCliHandlers, ObserveCommandOptions, PsCommandOptions, SendCommandOptions, SpawnCommandOptions, StartBuiltinCommandOptions, StartCommandOptions, StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StopCommandOptions, StoppedDevEnvironment, createElectricCliHandlers, createElectricProgram, formatQuickstartBackendStartedMessage, getElectricCliEnv, getStartedBuiltinAgentsMessage, getStartedEnvironmentMessage, getStoppedEnvironmentMessage, readDotEnvFile, resolveAnthropicApiKey, resolveCommandPrefix, resolveComposeProjectName, resolveElectricAgentsPort, resolvePullWakeOwnerPrincipal, resolvePullWakeRunnerId, run, startBuiltinAgentsServer, startElectricAgentsDevEnvironment, stopElectricAgentsDevEnvironment, waitForElectricAgentsServer };
134
+ export { DEFAULT_ELECTRIC_AGENTS_URL, ElectricCliEnv, ElectricCliHandlers, EntitySignal, ObserveCommandOptions, PsCommandOptions, SendCommandOptions, SignalCommandOptions, SpawnCommandOptions, StartBuiltinCommandOptions, StartCommandOptions, StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StopCommandOptions, StoppedDevEnvironment, createElectricCliHandlers, createElectricProgram, formatQuickstartBackendStartedMessage, getElectricCliEnv, getStartedBuiltinAgentsMessage, getStartedEnvironmentMessage, getStoppedEnvironmentMessage, readDotEnvFile, resolveAnthropicApiKey, resolveCommandPrefix, resolveComposeProjectName, resolveElectricAgentsPort, resolvePullWakeOwnerPrincipal, resolvePullWakeRunnerId, run, startBuiltinAgentsServer, startElectricAgentsDevEnvironment, stopElectricAgentsDevEnvironment, waitForElectricAgentsServer };
@@ -61,6 +61,11 @@ interface SendCommandOptions {
61
61
  type?: string;
62
62
  json?: boolean;
63
63
  }
64
+ type EntitySignal = `SIGINT` | `SIGHUP` | `SIGTERM` | `SIGKILL` | `SIGSTOP` | `SIGCONT` | `SIGUSR`;
65
+ interface SignalCommandOptions {
66
+ reason?: string;
67
+ payload?: string;
68
+ }
64
69
  interface ObserveCommandOptions {
65
70
  from?: string;
66
71
  }
@@ -85,6 +90,7 @@ interface ElectricCliHandlers {
85
90
  observe: (url: string, options: ObserveCommandOptions) => Promise<void>;
86
91
  inspect: (url: string) => Promise<void>;
87
92
  ps: (options: PsCommandOptions) => Promise<void>;
93
+ signal: (url: string, signal: string, options: SignalCommandOptions) => Promise<void>;
88
94
  kill: (url: string) => Promise<void>;
89
95
  start: (options: StartCommandOptions) => Promise<StartedDevEnvironment>;
90
96
  startBuiltin: (options: StartBuiltinCommandOptions) => Promise<StartedBuiltinAgentsEnvironment>;
@@ -125,4 +131,4 @@ declare function createElectricProgram({
125
131
  declare function run(argv?: Array<string>): Promise<void>;
126
132
 
127
133
  //#endregion
128
- export { DEFAULT_ELECTRIC_AGENTS_URL, ElectricCliEnv, ElectricCliHandlers, ObserveCommandOptions, PsCommandOptions, SendCommandOptions, SpawnCommandOptions, StartBuiltinCommandOptions, StartCommandOptions, StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StopCommandOptions, StoppedDevEnvironment, createElectricCliHandlers, createElectricProgram, formatQuickstartBackendStartedMessage, getElectricCliEnv, getStartedBuiltinAgentsMessage, getStartedEnvironmentMessage, getStoppedEnvironmentMessage, readDotEnvFile, resolveAnthropicApiKey, resolveCommandPrefix, resolveComposeProjectName, resolveElectricAgentsPort, resolvePullWakeOwnerPrincipal, resolvePullWakeRunnerId, run, startBuiltinAgentsServer, startElectricAgentsDevEnvironment, stopElectricAgentsDevEnvironment, waitForElectricAgentsServer };
134
+ export { DEFAULT_ELECTRIC_AGENTS_URL, ElectricCliEnv, ElectricCliHandlers, EntitySignal, ObserveCommandOptions, PsCommandOptions, SendCommandOptions, SignalCommandOptions, SpawnCommandOptions, StartBuiltinCommandOptions, StartCommandOptions, StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StopCommandOptions, StoppedDevEnvironment, createElectricCliHandlers, createElectricProgram, formatQuickstartBackendStartedMessage, getElectricCliEnv, getStartedBuiltinAgentsMessage, getStartedEnvironmentMessage, getStoppedEnvironmentMessage, readDotEnvFile, resolveAnthropicApiKey, resolveCommandPrefix, resolveComposeProjectName, resolveElectricAgentsPort, resolvePullWakeOwnerPrincipal, resolvePullWakeRunnerId, run, startBuiltinAgentsServer, startElectricAgentsDevEnvironment, stopElectricAgentsDevEnvironment, waitForElectricAgentsServer };
package/dist/index.cjs CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
  const require_chunk = require('./chunk-BCwAaXi7.cjs');
4
- const require_completions = require('./completions-Bj4D5DRa.cjs');
4
+ const require_completions = require('./completions-BeohCOLD.cjs');
5
5
  const require_entity_api = require('./entity-api-Cvo55yZx.cjs');
6
6
  const require_env = require('./env-CFKgT8o2.cjs');
7
7
  const __electric_ax_agents_runtime = require_chunk.__toESM(require("@electric-ax/agents-runtime"));
@@ -139,6 +139,15 @@ function writeApiKeyToDotEnv(key, cwd) {
139
139
  //#endregion
140
140
  //#region src/index.ts
141
141
  const DEFAULT_ELECTRIC_AGENTS_URL = `http://localhost:4437`;
142
+ const ENTITY_SIGNALS = [
143
+ `SIGINT`,
144
+ `SIGHUP`,
145
+ `SIGTERM`,
146
+ `SIGKILL`,
147
+ `SIGSTOP`,
148
+ `SIGCONT`,
149
+ `SIGUSR`
150
+ ];
142
151
  var CliError = class extends Error {};
143
152
  function getDefaultElectricAgentsIdentity() {
144
153
  return `${(0, node_os.userInfo)().username}@${(0, node_os.hostname)()}`;
@@ -197,6 +206,17 @@ function parsePayload(input, json) {
197
206
  }
198
207
  return { text: input };
199
208
  }
209
+ function parseJsonOption(name, input) {
210
+ try {
211
+ return JSON.parse(input);
212
+ } catch (error) {
213
+ fail(`${name} must be valid JSON: ${getErrorMessage(error)}`);
214
+ }
215
+ }
216
+ function assertEntitySignal(signal) {
217
+ if (ENTITY_SIGNALS.includes(signal)) return signal;
218
+ fail(`Invalid signal "${signal}". Expected one of: ${ENTITY_SIGNALS.join(`, `)}`);
219
+ }
200
220
  function normalizeVariadicArg(value) {
201
221
  if (value === void 0) return [];
202
222
  return Array.isArray(value) ? value : [value];
@@ -458,13 +478,34 @@ async function listEntities(env, options) {
458
478
  }
459
479
  }
460
480
  async function killEntity(env, url) {
461
- const res = await electricAgentsFetch(env, require_entity_api.entityApiPath(url), { method: `DELETE` });
481
+ const res = await electricAgentsFetch(env, require_entity_api.entityApiPath(url, `/signal`), {
482
+ method: `POST`,
483
+ body: JSON.stringify({
484
+ signal: `SIGKILL`,
485
+ reason: `Killed from CLI`
486
+ })
487
+ });
462
488
  if (!res.ok) {
463
489
  const data = await parseJsonResponse(res);
464
490
  failFromResponse(data, res);
465
491
  }
466
492
  console.log(`Killed ${url}`);
467
493
  }
494
+ async function signalEntity(env, url, rawSignal, options) {
495
+ const signal = assertEntitySignal(rawSignal);
496
+ const body = { signal };
497
+ if (options.reason !== void 0) body.reason = options.reason;
498
+ if (options.payload !== void 0) body.payload = parseJsonOption(`--payload`, options.payload);
499
+ const res = await electricAgentsFetch(env, require_entity_api.entityApiPath(url, `/signal`), {
500
+ method: `POST`,
501
+ body: JSON.stringify(body)
502
+ });
503
+ if (!res.ok) {
504
+ const data = await parseJsonResponse(res);
505
+ failFromResponse(data, res);
506
+ }
507
+ console.log(`Sent ${signal} to ${url}`);
508
+ }
468
509
  function printStartedEnvironment(env) {
469
510
  console.log([
470
511
  `Electric Agents dev environment is up.`,
@@ -494,6 +535,7 @@ function createElectricCliHandlers(env, commandPrefix = commandExample(`electric
494
535
  observe: (url, options) => observeEntity(env, url, options),
495
536
  inspect: (url) => inspectEntity(env, url),
496
537
  ps: (options) => listEntities(env, options),
538
+ signal: (url, signal, options) => signalEntity(env, url, signal, options),
497
539
  kill: (url) => killEntity(env, url),
498
540
  start: async (options) => {
499
541
  const { startElectricAgentsDevEnvironment } = await loadStartModule();
@@ -556,6 +598,7 @@ Examples:
556
598
  $ ${agentsCommand} types
557
599
  $ ${agentsCommand} spawn /horton/onboarding
558
600
  $ ${agentsCommand} send /horton/onboarding "Help me onboard to Electric Agents"
601
+ $ ${agentsCommand} signal /horton/onboarding SIGINT --reason "stop current run"
559
602
  $ ${agentsCommand} observe /horton/onboarding
560
603
  $ ${agentsCommand} start
561
604
  $ ${agentsCommand} start-builtin --anthropic-api-key sk-ant-...
@@ -592,6 +635,12 @@ function createElectricProgram({ env = getElectricCliEnv(), commandName = `elect
592
635
  const command = getCommandActionArg(actionArgs);
593
636
  await handlers.observe(url, command.opts());
594
637
  });
638
+ agentsCommand.command(`signal <url> <signal>`).description(`Send a lifecycle signal to an entity`).option(`--reason <text>`, `Human-readable signal reason`).option(`--payload <json>`, `JSON payload to attach to the signal`).action(async (...actionArgs) => {
639
+ const url = actionArgs[0];
640
+ const signal = actionArgs[1];
641
+ const command = getCommandActionArg(actionArgs);
642
+ await handlers.signal(url, signal, command.opts());
643
+ });
595
644
  agentsCommand.command(`inspect <url>`).description(`Show entity details`).action(async (url) => {
596
645
  await handlers.inspect(url);
597
646
  });
@@ -599,7 +648,7 @@ function createElectricProgram({ env = getElectricCliEnv(), commandName = `elect
599
648
  const command = getCommandActionArg(actionArgs);
600
649
  await handlers.ps(command.opts());
601
650
  });
602
- agentsCommand.command(`kill <url>`).description(`Delete an entity`).action(async (url) => {
651
+ agentsCommand.command(`kill <url>`).description(`Send SIGKILL to an entity`).action(async (url) => {
603
652
  await handlers.kill(url);
604
653
  });
605
654
  agentsCommand.command(`start`).description(`Start the Electric Agents coordinator server`).action(async (...actionArgs) => {
package/dist/index.d.cts CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { DEFAULT_ELECTRIC_AGENTS_URL, ElectricCliEnv, ElectricCliHandlers, ObserveCommandOptions, PsCommandOptions, SendCommandOptions, SpawnCommandOptions, StartBuiltinCommandOptions, StartCommandOptions, StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StopCommandOptions, StoppedDevEnvironment, createElectricCliHandlers, createElectricProgram, formatQuickstartBackendStartedMessage, getElectricCliEnv, resolveCommandPrefix, run } from "./index-OgX1QS9Q.cjs";
3
- export { DEFAULT_ELECTRIC_AGENTS_URL, ElectricCliEnv, ElectricCliHandlers, ObserveCommandOptions, PsCommandOptions, SendCommandOptions, SpawnCommandOptions, StartBuiltinCommandOptions, StartCommandOptions, StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StopCommandOptions, StoppedDevEnvironment, createElectricCliHandlers, createElectricProgram, formatQuickstartBackendStartedMessage, getElectricCliEnv, resolveCommandPrefix, run };
2
+ import { DEFAULT_ELECTRIC_AGENTS_URL, ElectricCliEnv, ElectricCliHandlers, EntitySignal, ObserveCommandOptions, PsCommandOptions, SendCommandOptions, SignalCommandOptions, SpawnCommandOptions, StartBuiltinCommandOptions, StartCommandOptions, StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StopCommandOptions, StoppedDevEnvironment, createElectricCliHandlers, createElectricProgram, formatQuickstartBackendStartedMessage, getElectricCliEnv, resolveCommandPrefix, run } from "./index-DmR3DeFk.cjs";
3
+ export { DEFAULT_ELECTRIC_AGENTS_URL, ElectricCliEnv, ElectricCliHandlers, EntitySignal, ObserveCommandOptions, PsCommandOptions, SendCommandOptions, SignalCommandOptions, SpawnCommandOptions, StartBuiltinCommandOptions, StartCommandOptions, StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StopCommandOptions, StoppedDevEnvironment, createElectricCliHandlers, createElectricProgram, formatQuickstartBackendStartedMessage, getElectricCliEnv, resolveCommandPrefix, run };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  #!/usr/bin/env node
2
- import { DEFAULT_ELECTRIC_AGENTS_URL, ElectricCliEnv, ElectricCliHandlers, ObserveCommandOptions, PsCommandOptions, SendCommandOptions, SpawnCommandOptions, StartBuiltinCommandOptions, StartCommandOptions, StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StopCommandOptions, StoppedDevEnvironment, createElectricCliHandlers, createElectricProgram, formatQuickstartBackendStartedMessage, getElectricCliEnv, resolveCommandPrefix, run } from "./index-CwRI9tWl.js";
3
- export { DEFAULT_ELECTRIC_AGENTS_URL, ElectricCliEnv, ElectricCliHandlers, ObserveCommandOptions, PsCommandOptions, SendCommandOptions, SpawnCommandOptions, StartBuiltinCommandOptions, StartCommandOptions, StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StopCommandOptions, StoppedDevEnvironment, createElectricCliHandlers, createElectricProgram, formatQuickstartBackendStartedMessage, getElectricCliEnv, resolveCommandPrefix, run };
2
+ import { DEFAULT_ELECTRIC_AGENTS_URL, ElectricCliEnv, ElectricCliHandlers, EntitySignal, ObserveCommandOptions, PsCommandOptions, SendCommandOptions, SignalCommandOptions, SpawnCommandOptions, StartBuiltinCommandOptions, StartCommandOptions, StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StopCommandOptions, StoppedDevEnvironment, createElectricCliHandlers, createElectricProgram, formatQuickstartBackendStartedMessage, getElectricCliEnv, resolveCommandPrefix, run } from "./index-BsITLCxF.js";
3
+ export { DEFAULT_ELECTRIC_AGENTS_URL, ElectricCliEnv, ElectricCliHandlers, EntitySignal, ObserveCommandOptions, PsCommandOptions, SendCommandOptions, SignalCommandOptions, SpawnCommandOptions, StartBuiltinCommandOptions, StartCommandOptions, StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StopCommandOptions, StoppedDevEnvironment, createElectricCliHandlers, createElectricProgram, formatQuickstartBackendStartedMessage, getElectricCliEnv, resolveCommandPrefix, run };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { installCompletions, setupCompletions } from "./completions-B-Lf28Wy.js";
2
+ import { installCompletions, setupCompletions } from "./completions-3RE2mC2p.js";
3
3
  import { entityApiPath } from "./entity-api-DWMhkYbl.js";
4
4
  import { resolveAnthropicApiKey$1 as resolveAnthropicApiKey } from "./env-DIhTv987.js";
5
5
  import { appendPathToUrl } from "@electric-ax/agents-runtime";
@@ -137,6 +137,15 @@ function writeApiKeyToDotEnv(key, cwd) {
137
137
  //#endregion
138
138
  //#region src/index.ts
139
139
  const DEFAULT_ELECTRIC_AGENTS_URL = `http://localhost:4437`;
140
+ const ENTITY_SIGNALS = [
141
+ `SIGINT`,
142
+ `SIGHUP`,
143
+ `SIGTERM`,
144
+ `SIGKILL`,
145
+ `SIGSTOP`,
146
+ `SIGCONT`,
147
+ `SIGUSR`
148
+ ];
140
149
  var CliError = class extends Error {};
141
150
  function getDefaultElectricAgentsIdentity() {
142
151
  return `${userInfo().username}@${hostname()}`;
@@ -195,6 +204,17 @@ function parsePayload(input, json) {
195
204
  }
196
205
  return { text: input };
197
206
  }
207
+ function parseJsonOption(name, input) {
208
+ try {
209
+ return JSON.parse(input);
210
+ } catch (error) {
211
+ fail(`${name} must be valid JSON: ${getErrorMessage(error)}`);
212
+ }
213
+ }
214
+ function assertEntitySignal(signal) {
215
+ if (ENTITY_SIGNALS.includes(signal)) return signal;
216
+ fail(`Invalid signal "${signal}". Expected one of: ${ENTITY_SIGNALS.join(`, `)}`);
217
+ }
198
218
  function normalizeVariadicArg(value) {
199
219
  if (value === void 0) return [];
200
220
  return Array.isArray(value) ? value : [value];
@@ -456,13 +476,34 @@ async function listEntities(env, options) {
456
476
  }
457
477
  }
458
478
  async function killEntity(env, url) {
459
- const res = await electricAgentsFetch(env, entityApiPath(url), { method: `DELETE` });
479
+ const res = await electricAgentsFetch(env, entityApiPath(url, `/signal`), {
480
+ method: `POST`,
481
+ body: JSON.stringify({
482
+ signal: `SIGKILL`,
483
+ reason: `Killed from CLI`
484
+ })
485
+ });
460
486
  if (!res.ok) {
461
487
  const data = await parseJsonResponse(res);
462
488
  failFromResponse(data, res);
463
489
  }
464
490
  console.log(`Killed ${url}`);
465
491
  }
492
+ async function signalEntity(env, url, rawSignal, options) {
493
+ const signal = assertEntitySignal(rawSignal);
494
+ const body = { signal };
495
+ if (options.reason !== void 0) body.reason = options.reason;
496
+ if (options.payload !== void 0) body.payload = parseJsonOption(`--payload`, options.payload);
497
+ const res = await electricAgentsFetch(env, entityApiPath(url, `/signal`), {
498
+ method: `POST`,
499
+ body: JSON.stringify(body)
500
+ });
501
+ if (!res.ok) {
502
+ const data = await parseJsonResponse(res);
503
+ failFromResponse(data, res);
504
+ }
505
+ console.log(`Sent ${signal} to ${url}`);
506
+ }
466
507
  function printStartedEnvironment(env) {
467
508
  console.log([
468
509
  `Electric Agents dev environment is up.`,
@@ -492,6 +533,7 @@ function createElectricCliHandlers(env, commandPrefix = commandExample(`electric
492
533
  observe: (url, options) => observeEntity(env, url, options),
493
534
  inspect: (url) => inspectEntity(env, url),
494
535
  ps: (options) => listEntities(env, options),
536
+ signal: (url, signal, options) => signalEntity(env, url, signal, options),
495
537
  kill: (url) => killEntity(env, url),
496
538
  start: async (options) => {
497
539
  const { startElectricAgentsDevEnvironment } = await loadStartModule();
@@ -554,6 +596,7 @@ Examples:
554
596
  $ ${agentsCommand} types
555
597
  $ ${agentsCommand} spawn /horton/onboarding
556
598
  $ ${agentsCommand} send /horton/onboarding "Help me onboard to Electric Agents"
599
+ $ ${agentsCommand} signal /horton/onboarding SIGINT --reason "stop current run"
557
600
  $ ${agentsCommand} observe /horton/onboarding
558
601
  $ ${agentsCommand} start
559
602
  $ ${agentsCommand} start-builtin --anthropic-api-key sk-ant-...
@@ -590,6 +633,12 @@ function createElectricProgram({ env = getElectricCliEnv(), commandName = `elect
590
633
  const command = getCommandActionArg(actionArgs);
591
634
  await handlers.observe(url, command.opts());
592
635
  });
636
+ agentsCommand.command(`signal <url> <signal>`).description(`Send a lifecycle signal to an entity`).option(`--reason <text>`, `Human-readable signal reason`).option(`--payload <json>`, `JSON payload to attach to the signal`).action(async (...actionArgs) => {
637
+ const url = actionArgs[0];
638
+ const signal = actionArgs[1];
639
+ const command = getCommandActionArg(actionArgs);
640
+ await handlers.signal(url, signal, command.opts());
641
+ });
593
642
  agentsCommand.command(`inspect <url>`).description(`Show entity details`).action(async (url) => {
594
643
  await handlers.inspect(url);
595
644
  });
@@ -597,7 +646,7 @@ function createElectricProgram({ env = getElectricCliEnv(), commandName = `elect
597
646
  const command = getCommandActionArg(actionArgs);
598
647
  await handlers.ps(command.opts());
599
648
  });
600
- agentsCommand.command(`kill <url>`).description(`Delete an entity`).action(async (url) => {
649
+ agentsCommand.command(`kill <url>`).description(`Send SIGKILL to an entity`).action(async (url) => {
601
650
  await handlers.kill(url);
602
651
  });
603
652
  agentsCommand.command(`start`).description(`Start the Electric Agents coordinator server`).action(async (...actionArgs) => {
@@ -261,6 +261,12 @@ function WakeView({ section }) {
261
261
  })]
262
262
  });
263
263
  }
264
+ function ObserveExitHotkey({ onExit }) {
265
+ (0, ink.useInput)((_input, key) => {
266
+ if (key.escape) onExit();
267
+ });
268
+ return null;
269
+ }
264
270
  function ObserveView({ db, entityUrl, baseUrl, identity, headers }) {
265
271
  const timelineQuery = (0, react.useMemo)(() => (0, __electric_ax_agents_runtime.createEntityIncludesQuery)(db), [db]);
266
272
  const { data: timelineRows = [] } = (0, __tanstack_react_db.useLiveQuery)(timelineQuery, [timelineQuery]);
@@ -268,6 +274,9 @@ function ObserveView({ db, entityUrl, baseUrl, identity, headers }) {
268
274
  runs: [],
269
275
  inbox: [],
270
276
  wakes: [],
277
+ signals: [],
278
+ contextInserted: [],
279
+ contextRemoved: [],
271
280
  entities: []
272
281
  });
273
282
  const typedRuns = timelineData.runs;
@@ -340,7 +349,7 @@ function ObserveView({ db, entityUrl, baseUrl, identity, headers }) {
340
349
  ]
341
350
  });
342
351
  }
343
- function ObserveApp({ entityUrl, baseUrl, identity, headers, initialOffset }) {
352
+ function ObserveApp({ entityUrl, baseUrl, identity, headers, initialOffset, onExit }) {
344
353
  const [db, setDb] = (0, react.useState)(null);
345
354
  const [error, setError] = (0, react.useState)(null);
346
355
  const closeRef = (0, react.useRef)(null);
@@ -371,43 +380,47 @@ function ObserveApp({ entityUrl, baseUrl, identity, headers, initialOffset }) {
371
380
  initialOffset,
372
381
  headers
373
382
  ]);
374
- if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ink.Box, {
383
+ if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ink.Box, {
375
384
  flexDirection: "column",
376
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ink.Text, {
385
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ObserveExitHotkey, { onExit }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ink.Text, {
377
386
  color: "red",
378
387
  children: `Error: ${error}`
379
- })
388
+ })]
380
389
  });
381
- if (!db) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ink.Box, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ink.Text, {
390
+ if (!db) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ink.Box, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ObserveExitHotkey, { onExit }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ink.Text, {
382
391
  dimColor: true,
383
392
  children: `Connecting to ${entityUrl}...`
384
- }) });
385
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ObserveView, {
393
+ })] });
394
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ObserveExitHotkey, { onExit }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ObserveView, {
386
395
  db,
387
396
  entityUrl,
388
397
  baseUrl,
389
398
  identity,
390
399
  headers
391
- });
400
+ })] });
392
401
  }
393
402
  function renderObserve(opts) {
394
403
  const { entityUrl, baseUrl, identity, headers, initialOffset } = opts;
395
- const app = (0, ink.render)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ObserveApp, {
404
+ let app;
405
+ const exit = () => {
406
+ app.unmount();
407
+ process.exit(0);
408
+ };
409
+ app = (0, ink.render)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ObserveApp, {
396
410
  entityUrl,
397
411
  baseUrl,
398
412
  identity,
399
413
  headers,
400
- initialOffset
414
+ initialOffset,
415
+ onExit: exit
401
416
  }));
402
- process.on(`SIGINT`, () => {
403
- app.unmount();
404
- process.exit(0);
405
- });
417
+ process.on(`SIGINT`, exit);
406
418
  }
407
419
 
408
420
  //#endregion
409
421
  exports.AgentTextView = AgentTextView
410
422
  exports.MessageInput = MessageInput
423
+ exports.ObserveExitHotkey = ObserveExitHotkey
411
424
  exports.ToolCallView = ToolCallView
412
425
  exports.ToolResultView = ToolResultView
413
426
  exports.UserMessageView = UserMessageView
@@ -50,6 +50,11 @@ declare function MessageInput({
50
50
  headers?: Record<string, string>;
51
51
  disabled: boolean;
52
52
  }): React.ReactElement;
53
+ declare function ObserveExitHotkey({
54
+ onExit
55
+ }: {
56
+ onExit: () => void;
57
+ }): React.ReactElement | null;
53
58
  declare function renderObserve(opts: {
54
59
  entityUrl: string;
55
60
  baseUrl: string;
@@ -59,4 +64,4 @@ declare function renderObserve(opts: {
59
64
  }): void;
60
65
 
61
66
  //#endregion
62
- export { AgentTextView, MessageInput, ToolCallView, ToolResultView, UserMessageView, formatTime, renderObserve, truncate };
67
+ export { AgentTextView, MessageInput, ObserveExitHotkey, ToolCallView, ToolResultView, UserMessageView, formatTime, renderObserve, truncate };
@@ -50,6 +50,11 @@ declare function MessageInput({
50
50
  headers?: Record<string, string>;
51
51
  disabled: boolean;
52
52
  }): React.ReactElement;
53
+ declare function ObserveExitHotkey({
54
+ onExit
55
+ }: {
56
+ onExit: () => void;
57
+ }): React.ReactElement | null;
53
58
  declare function renderObserve(opts: {
54
59
  entityUrl: string;
55
60
  baseUrl: string;
@@ -59,4 +64,4 @@ declare function renderObserve(opts: {
59
64
  }): void;
60
65
 
61
66
  //#endregion
62
- export { AgentTextView, MessageInput, ToolCallView, ToolResultView, UserMessageView, formatTime, renderObserve, truncate };
67
+ export { AgentTextView, MessageInput, ObserveExitHotkey, ToolCallView, ToolResultView, UserMessageView, formatTime, renderObserve, truncate };
@@ -259,6 +259,12 @@ function WakeView({ section }) {
259
259
  })]
260
260
  });
261
261
  }
262
+ function ObserveExitHotkey({ onExit }) {
263
+ useInput((_input, key) => {
264
+ if (key.escape) onExit();
265
+ });
266
+ return null;
267
+ }
262
268
  function ObserveView({ db, entityUrl, baseUrl, identity, headers }) {
263
269
  const timelineQuery = useMemo(() => createEntityIncludesQuery(db), [db]);
264
270
  const { data: timelineRows = [] } = useLiveQuery(timelineQuery, [timelineQuery]);
@@ -266,6 +272,9 @@ function ObserveView({ db, entityUrl, baseUrl, identity, headers }) {
266
272
  runs: [],
267
273
  inbox: [],
268
274
  wakes: [],
275
+ signals: [],
276
+ contextInserted: [],
277
+ contextRemoved: [],
269
278
  entities: []
270
279
  });
271
280
  const typedRuns = timelineData.runs;
@@ -338,7 +347,7 @@ function ObserveView({ db, entityUrl, baseUrl, identity, headers }) {
338
347
  ]
339
348
  });
340
349
  }
341
- function ObserveApp({ entityUrl, baseUrl, identity, headers, initialOffset }) {
350
+ function ObserveApp({ entityUrl, baseUrl, identity, headers, initialOffset, onExit }) {
342
351
  const [db, setDb] = useState(null);
343
352
  const [error, setError] = useState(null);
344
353
  const closeRef = useRef(null);
@@ -369,39 +378,42 @@ function ObserveApp({ entityUrl, baseUrl, identity, headers, initialOffset }) {
369
378
  initialOffset,
370
379
  headers
371
380
  ]);
372
- if (error) return /* @__PURE__ */ jsx(Box, {
381
+ if (error) return /* @__PURE__ */ jsxs(Box, {
373
382
  flexDirection: "column",
374
- children: /* @__PURE__ */ jsx(Text, {
383
+ children: [/* @__PURE__ */ jsx(ObserveExitHotkey, { onExit }), /* @__PURE__ */ jsx(Text, {
375
384
  color: "red",
376
385
  children: `Error: ${error}`
377
- })
386
+ })]
378
387
  });
379
- if (!db) return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, {
388
+ if (!db) return /* @__PURE__ */ jsxs(Box, { children: [/* @__PURE__ */ jsx(ObserveExitHotkey, { onExit }), /* @__PURE__ */ jsx(Text, {
380
389
  dimColor: true,
381
390
  children: `Connecting to ${entityUrl}...`
382
- }) });
383
- return /* @__PURE__ */ jsx(ObserveView, {
391
+ })] });
392
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(ObserveExitHotkey, { onExit }), /* @__PURE__ */ jsx(ObserveView, {
384
393
  db,
385
394
  entityUrl,
386
395
  baseUrl,
387
396
  identity,
388
397
  headers
389
- });
398
+ })] });
390
399
  }
391
400
  function renderObserve(opts) {
392
401
  const { entityUrl, baseUrl, identity, headers, initialOffset } = opts;
393
- const app = render(/* @__PURE__ */ jsx(ObserveApp, {
402
+ let app;
403
+ const exit = () => {
404
+ app.unmount();
405
+ process.exit(0);
406
+ };
407
+ app = render(/* @__PURE__ */ jsx(ObserveApp, {
394
408
  entityUrl,
395
409
  baseUrl,
396
410
  identity,
397
411
  headers,
398
- initialOffset
412
+ initialOffset,
413
+ onExit: exit
399
414
  }));
400
- process.on(`SIGINT`, () => {
401
- app.unmount();
402
- process.exit(0);
403
- });
415
+ process.on(`SIGINT`, exit);
404
416
  }
405
417
 
406
418
  //#endregion
407
- export { AgentTextView, MessageInput, ToolCallView, ToolResultView, UserMessageView, formatTime, renderObserve, truncate };
419
+ export { AgentTextView, MessageInput, ObserveExitHotkey, ToolCallView, ToolResultView, UserMessageView, formatTime, renderObserve, truncate };
package/dist/start.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StoppedDevEnvironment, getStartedBuiltinAgentsMessage, getStartedEnvironmentMessage, getStoppedEnvironmentMessage, readDotEnvFile, resolveAnthropicApiKey, resolveComposeProjectName, resolveElectricAgentsPort, resolvePullWakeOwnerPrincipal, resolvePullWakeRunnerId, startBuiltinAgentsServer, startElectricAgentsDevEnvironment, stopElectricAgentsDevEnvironment, waitForElectricAgentsServer } from "./index-OgX1QS9Q.cjs";
1
+ import { StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StoppedDevEnvironment, getStartedBuiltinAgentsMessage, getStartedEnvironmentMessage, getStoppedEnvironmentMessage, readDotEnvFile, resolveAnthropicApiKey, resolveComposeProjectName, resolveElectricAgentsPort, resolvePullWakeOwnerPrincipal, resolvePullWakeRunnerId, startBuiltinAgentsServer, startElectricAgentsDevEnvironment, stopElectricAgentsDevEnvironment, waitForElectricAgentsServer } from "./index-DmR3DeFk.cjs";
2
2
  export { StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StoppedDevEnvironment, getStartedBuiltinAgentsMessage, getStartedEnvironmentMessage, getStoppedEnvironmentMessage, readDotEnvFile, resolveAnthropicApiKey, resolveComposeProjectName, resolveElectricAgentsPort, resolvePullWakeOwnerPrincipal, resolvePullWakeRunnerId, startBuiltinAgentsServer, startElectricAgentsDevEnvironment, stopElectricAgentsDevEnvironment, waitForElectricAgentsServer };
package/dist/start.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StoppedDevEnvironment, getStartedBuiltinAgentsMessage, getStartedEnvironmentMessage, getStoppedEnvironmentMessage, readDotEnvFile, resolveAnthropicApiKey, resolveComposeProjectName, resolveElectricAgentsPort, resolvePullWakeOwnerPrincipal, resolvePullWakeRunnerId, startBuiltinAgentsServer, startElectricAgentsDevEnvironment, stopElectricAgentsDevEnvironment, waitForElectricAgentsServer } from "./index-CwRI9tWl.js";
1
+ import { StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StoppedDevEnvironment, getStartedBuiltinAgentsMessage, getStartedEnvironmentMessage, getStoppedEnvironmentMessage, readDotEnvFile, resolveAnthropicApiKey, resolveComposeProjectName, resolveElectricAgentsPort, resolvePullWakeOwnerPrincipal, resolvePullWakeRunnerId, startBuiltinAgentsServer, startElectricAgentsDevEnvironment, stopElectricAgentsDevEnvironment, waitForElectricAgentsServer } from "./index-BsITLCxF.js";
2
2
  export { StartedBuiltinAgentsEnvironment, StartedDevEnvironment, StoppedDevEnvironment, getStartedBuiltinAgentsMessage, getStartedEnvironmentMessage, getStoppedEnvironmentMessage, readDotEnvFile, resolveAnthropicApiKey, resolveComposeProjectName, resolveElectricAgentsPort, resolvePullWakeOwnerPrincipal, resolvePullWakeRunnerId, startBuiltinAgentsServer, startElectricAgentsDevEnvironment, stopElectricAgentsDevEnvironment, waitForElectricAgentsServer };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "electric-ax",
3
- "version": "0.2.5",
3
+ "version": "0.2.8",
4
4
  "description": "CLI for Electric Agents",
5
5
  "author": "ElectricSQL team and contributors",
6
6
  "license": "Apache-2.0",
@@ -39,15 +39,15 @@
39
39
  "dependencies": {
40
40
  "@durable-streams/client": "https://pkg.pr.new/durable-streams/durable-streams/@durable-streams/client@5d5c217",
41
41
  "@durable-streams/state": "https://pkg.pr.new/durable-streams/durable-streams/@durable-streams/state@5d5c217",
42
- "@electric-sql/client": "^1.5.18",
42
+ "@electric-sql/client": "^1.5.19",
43
43
  "@tanstack/db": "^0.6.4",
44
44
  "@tanstack/react-db": "^0.1.82",
45
45
  "commander": "^13.1.0",
46
46
  "ink": "^6.8.0",
47
47
  "omelette": "^0.4.17",
48
48
  "react": "^19.2.0",
49
- "@electric-ax/agents": "0.4.5",
50
- "@electric-ax/agents-runtime": "0.3.1"
49
+ "@electric-ax/agents": "0.4.8",
50
+ "@electric-ax/agents-runtime": "0.3.4"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@vitest/coverage-v8": "^4.1.0",