electric-ax 0.1.17 → 0.2.0
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/completions.d.cts +1 -1
- package/dist/completions.d.ts +1 -1
- package/dist/entity-api-ClpnLxWJ.cjs +38 -0
- package/dist/entity-api-Dh28Mz7H.js +19 -0
- package/dist/{entity-stream-db-Djo-7a11.cjs → entity-stream-db-BLbPedyR.cjs} +11 -3
- package/dist/{entity-stream-db-BRwzIuHl.d.ts → entity-stream-db-CmDwc49J.d.cts} +4 -1
- package/dist/{entity-stream-db-CGP2xVeJ.js → entity-stream-db-Czz3S8YF.js} +12 -4
- package/dist/{entity-stream-db-C2C3t_hD.d.cts → entity-stream-db-DgzxI6C_.d.ts} +4 -1
- package/dist/entity-stream-db.cjs +2 -1
- package/dist/entity-stream-db.d.cts +1 -1
- package/dist/entity-stream-db.d.ts +1 -1
- package/dist/entity-stream-db.js +2 -1
- package/dist/{index-B2MsxFCW.d.cts → index-BQ4JyfkG.d.cts} +8 -5
- package/dist/{index-BDO8dHhT.d.ts → index-D6TZ88Yg.d.ts} +8 -5
- package/dist/index.cjs +46 -11
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +46 -11
- package/dist/observe-ui.cjs +61 -11
- package/dist/observe-ui.d.cts +10 -1
- package/dist/observe-ui.d.ts +10 -1
- package/dist/observe-ui.js +61 -11
- package/dist/start.cjs +97 -29
- package/dist/start.d.cts +2 -2
- package/dist/start.d.ts +2 -2
- package/dist/start.js +96 -28
- package/docker-compose.full.yml +4 -1
- package/package.json +6 -6
- /package/dist/{env-BXUgom_C.cjs → env-CFKgT8o2.cjs} +0 -0
- /package/dist/{env-LZtIfFz1.js → env-DIhTv987.js} +0 -0
package/dist/start.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { readDotEnvFile$1 as readDotEnvFile, resolveAnthropicApiKey$1 as resolveAnthropicApiKey } from "./env-
|
|
1
|
+
import { readDotEnvFile$1 as readDotEnvFile, resolveAnthropicApiKey$1 as resolveAnthropicApiKey } from "./env-DIhTv987.js";
|
|
2
|
+
import { appendPathToUrl } from "@electric-ax/agents-runtime";
|
|
2
3
|
import { fileURLToPath } from "node:url";
|
|
3
4
|
import { spawn } from "node:child_process";
|
|
4
5
|
import { BuiltinAgentsServer } from "@electric-ax/agents";
|
|
@@ -17,19 +18,11 @@ const ELECTRIC_AGENTS_SERVER_IMAGE_TAG = `latest`;
|
|
|
17
18
|
//#endregion
|
|
18
19
|
//#region src/start.ts
|
|
19
20
|
const DEFAULT_ELECTRIC_AGENTS_PORT = 4437;
|
|
20
|
-
const DEFAULT_BUILTIN_AGENTS_PORT = 4448;
|
|
21
|
-
const DEFAULT_BUILTIN_AGENTS_HOST = `0.0.0.0`;
|
|
22
21
|
const DEFAULT_COMPOSE_PROJECT_NAME = `electric-agents`;
|
|
22
|
+
const DEFAULT_PULL_WAKE_RUNNER_ID = `builtin-agents`;
|
|
23
|
+
const DEFAULT_PULL_WAKE_OWNER_ID = `builtin-agents`;
|
|
24
|
+
const DEFAULT_PULL_WAKE_OWNER_NAME = `Built-in agents`;
|
|
23
25
|
const DOCKER_COMPOSE_FILE = fileURLToPath(new URL(`../docker-compose.full.yml`, import.meta.url));
|
|
24
|
-
function resolveBuiltinAgentsPort(env = process.env, fileEnv = readDotEnvFile()) {
|
|
25
|
-
const raw = env.ELECTRIC_AGENTS_BUILTIN_PORT?.trim() || fileEnv.ELECTRIC_AGENTS_BUILTIN_PORT?.trim();
|
|
26
|
-
const parsed = raw ? Number(raw) : DEFAULT_BUILTIN_AGENTS_PORT;
|
|
27
|
-
if (!Number.isInteger(parsed) || parsed <= 0) throw new Error(`ELECTRIC_AGENTS_BUILTIN_PORT must be a positive integer`);
|
|
28
|
-
return parsed;
|
|
29
|
-
}
|
|
30
|
-
function resolveBuiltinAgentsHost(env = process.env, fileEnv = readDotEnvFile()) {
|
|
31
|
-
return env.ELECTRIC_AGENTS_BUILTIN_HOST?.trim() || fileEnv.ELECTRIC_AGENTS_BUILTIN_HOST?.trim() || DEFAULT_BUILTIN_AGENTS_HOST;
|
|
32
|
-
}
|
|
33
26
|
function resolveElectricAgentsPort(env = process.env, fileEnv = readDotEnvFile()) {
|
|
34
27
|
const raw = env.ELECTRIC_AGENTS_PORT?.trim() || fileEnv.ELECTRIC_AGENTS_PORT?.trim();
|
|
35
28
|
const parsed = raw ? Number(raw) : DEFAULT_ELECTRIC_AGENTS_PORT;
|
|
@@ -52,12 +45,73 @@ function getStoppedEnvironmentMessage(stopped) {
|
|
|
52
45
|
}
|
|
53
46
|
function getStartedBuiltinAgentsMessage(started) {
|
|
54
47
|
return [
|
|
55
|
-
`Builtin
|
|
56
|
-
`
|
|
48
|
+
`Builtin agents pull-wake runner is up.`,
|
|
49
|
+
`Runner: ${started.runnerId}`,
|
|
50
|
+
`Runtime: ${started.url}`,
|
|
57
51
|
`Registers with: ${started.agentServerUrl}`,
|
|
58
52
|
`Press Ctrl-C to stop.`
|
|
59
53
|
].join(`\n`);
|
|
60
54
|
}
|
|
55
|
+
function readConfigValue(env, fileEnv, names) {
|
|
56
|
+
for (const name of names) {
|
|
57
|
+
const value = env[name]?.trim() || fileEnv[name]?.trim();
|
|
58
|
+
if (value) return value;
|
|
59
|
+
}
|
|
60
|
+
return void 0;
|
|
61
|
+
}
|
|
62
|
+
function runnerIdFromIdentity(identity) {
|
|
63
|
+
if (!identity) return DEFAULT_PULL_WAKE_RUNNER_ID;
|
|
64
|
+
const slug = identity.toLowerCase().replace(/[^a-z0-9._-]+/g, `-`).replace(/^-+|-+$/g, ``);
|
|
65
|
+
return slug ? `builtin-${slug}` : DEFAULT_PULL_WAKE_RUNNER_ID;
|
|
66
|
+
}
|
|
67
|
+
function resolvePullWakeRunnerId(env = process.env, fileEnv = readDotEnvFile()) {
|
|
68
|
+
return readConfigValue(env, fileEnv, [`ELECTRIC_AGENTS_PULL_WAKE_RUNNER_ID`, `PULL_WAKE_RUNNER_ID`]) ?? runnerIdFromIdentity(readConfigValue(env, fileEnv, [`ELECTRIC_ASSERTED_AUTH_EMAIL`, `ELECTRIC_AGENTS_IDENTITY`]));
|
|
69
|
+
}
|
|
70
|
+
function resolvePullWakeOwnerId(env = process.env, fileEnv = readDotEnvFile()) {
|
|
71
|
+
return readConfigValue(env, fileEnv, [`ELECTRIC_ASSERTED_AUTH_EMAIL`, `ELECTRIC_AGENTS_IDENTITY`]) ?? DEFAULT_PULL_WAKE_OWNER_ID;
|
|
72
|
+
}
|
|
73
|
+
function buildAssertedAuthHeaders(env, fileEnv) {
|
|
74
|
+
const email = resolvePullWakeOwnerId(env, fileEnv);
|
|
75
|
+
const name = readConfigValue(env, fileEnv, [`ELECTRIC_ASSERTED_AUTH_NAME`]) ?? DEFAULT_PULL_WAKE_OWNER_NAME;
|
|
76
|
+
const headers = {};
|
|
77
|
+
headers[`X-Electric-Asserted-Email`] = email;
|
|
78
|
+
headers[`X-Electric-Asserted-Name`] = name;
|
|
79
|
+
return {
|
|
80
|
+
headers,
|
|
81
|
+
ownerUserId: email,
|
|
82
|
+
name
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function parseAdditionalServerHeaders(env, fileEnv) {
|
|
86
|
+
const raw = readConfigValue(env, fileEnv, [`ELECTRIC_AGENTS_SERVER_HEADERS`]);
|
|
87
|
+
if (!raw) return void 0;
|
|
88
|
+
let parsed;
|
|
89
|
+
try {
|
|
90
|
+
parsed = JSON.parse(raw);
|
|
91
|
+
} catch {
|
|
92
|
+
throw new Error(`Invalid ELECTRIC_AGENTS_SERVER_HEADERS: expected JSON`);
|
|
93
|
+
}
|
|
94
|
+
if (!parsed || typeof parsed !== `object` || Array.isArray(parsed)) throw new Error(`Invalid ELECTRIC_AGENTS_SERVER_HEADERS: expected a JSON object`);
|
|
95
|
+
const headers = new Headers();
|
|
96
|
+
for (const [name, value] of Object.entries(parsed)) {
|
|
97
|
+
if (typeof value !== `string`) throw new Error(`Invalid ELECTRIC_AGENTS_SERVER_HEADERS: header "${name}" must be a string`);
|
|
98
|
+
headers.set(name, value);
|
|
99
|
+
}
|
|
100
|
+
const normalized = Object.fromEntries(headers.entries());
|
|
101
|
+
return Object.keys(normalized).length > 0 ? normalized : void 0;
|
|
102
|
+
}
|
|
103
|
+
function mergeHeaders(...sources) {
|
|
104
|
+
const headers = new Headers();
|
|
105
|
+
for (const source of sources) {
|
|
106
|
+
if (!source) continue;
|
|
107
|
+
new Headers(source).forEach((value, key) => headers.set(key, value));
|
|
108
|
+
}
|
|
109
|
+
const merged = Object.fromEntries(headers.entries());
|
|
110
|
+
return Object.keys(merged).length > 0 ? merged : void 0;
|
|
111
|
+
}
|
|
112
|
+
function hasHeader(headers, name) {
|
|
113
|
+
return headers ? new Headers(headers).has(name) : false;
|
|
114
|
+
}
|
|
61
115
|
function resolveComposeProjectName(_cwd = process.cwd(), env = process.env) {
|
|
62
116
|
const explicit = env.ELECTRIC_AGENTS_COMPOSE_PROJECT?.trim();
|
|
63
117
|
if (explicit) return explicit;
|
|
@@ -92,11 +146,14 @@ async function waitForElectricAgentsServer(baseUrl, options = {}) {
|
|
|
92
146
|
const timeoutMs = options.timeoutMs ?? 6e4;
|
|
93
147
|
const intervalMs = options.intervalMs ?? 1e3;
|
|
94
148
|
const deadline = Date.now() + timeoutMs;
|
|
95
|
-
const healthUrl =
|
|
149
|
+
const healthUrl = appendPathToUrl(baseUrl, `/_electric/health`);
|
|
96
150
|
let lastError = null;
|
|
97
151
|
while (Date.now() < deadline) {
|
|
98
152
|
try {
|
|
99
|
-
const response = await fetchImpl(healthUrl, {
|
|
153
|
+
const response = await fetchImpl(healthUrl, {
|
|
154
|
+
headers: options.headers,
|
|
155
|
+
signal: AbortSignal.timeout(5e3)
|
|
156
|
+
});
|
|
100
157
|
if (response.ok) return;
|
|
101
158
|
lastError = `healthcheck returned ${response.status}`;
|
|
102
159
|
} catch (error) {
|
|
@@ -110,6 +167,7 @@ async function startElectricAgentsDevEnvironment(_options = {}, env = process.en
|
|
|
110
167
|
const fileEnv = readDotEnvFile(cwd);
|
|
111
168
|
const port = resolveElectricAgentsPort(env, fileEnv);
|
|
112
169
|
const composeProjectName = resolveComposeProjectName(cwd, env);
|
|
170
|
+
const assertedAuth = buildAssertedAuthHeaders(env, fileEnv);
|
|
113
171
|
await runDockerCompose([
|
|
114
172
|
`compose`,
|
|
115
173
|
`-f`,
|
|
@@ -121,7 +179,10 @@ async function startElectricAgentsDevEnvironment(_options = {}, env = process.en
|
|
|
121
179
|
COMPOSE_PROJECT_NAME: composeProjectName,
|
|
122
180
|
ELECTRIC_AGENTS_PORT: String(port),
|
|
123
181
|
ELECTRIC_IMAGE_TAG: env.ELECTRIC_IMAGE_TAG ?? ELECTRIC_IMAGE_TAG,
|
|
124
|
-
ELECTRIC_AGENTS_SERVER_IMAGE_TAG: env.ELECTRIC_AGENTS_SERVER_IMAGE_TAG ?? ELECTRIC_AGENTS_SERVER_IMAGE_TAG
|
|
182
|
+
ELECTRIC_AGENTS_SERVER_IMAGE_TAG: env.ELECTRIC_AGENTS_SERVER_IMAGE_TAG ?? ELECTRIC_AGENTS_SERVER_IMAGE_TAG,
|
|
183
|
+
ELECTRIC_AGENTS_DEV_ASSERTED_AUTH: env.ELECTRIC_AGENTS_DEV_ASSERTED_AUTH ?? fileEnv.ELECTRIC_AGENTS_DEV_ASSERTED_AUTH ?? `1`,
|
|
184
|
+
ELECTRIC_ASSERTED_AUTH_EMAIL: env.ELECTRIC_ASSERTED_AUTH_EMAIL ?? fileEnv.ELECTRIC_ASSERTED_AUTH_EMAIL ?? assertedAuth.ownerUserId,
|
|
185
|
+
ELECTRIC_ASSERTED_AUTH_NAME: env.ELECTRIC_ASSERTED_AUTH_NAME ?? fileEnv.ELECTRIC_ASSERTED_AUTH_NAME ?? assertedAuth.name
|
|
125
186
|
});
|
|
126
187
|
const uiUrl = `http://localhost:${port}`;
|
|
127
188
|
await waitForElectricAgentsServer(uiUrl);
|
|
@@ -179,22 +240,29 @@ async function startBuiltinAgentsServer(options, params = {}) {
|
|
|
179
240
|
const cwd = params.cwd ?? process.cwd();
|
|
180
241
|
const fileEnv = readDotEnvFile(cwd);
|
|
181
242
|
const anthropicApiKey = resolveAnthropicApiKey(options, env, fileEnv);
|
|
182
|
-
const
|
|
183
|
-
const
|
|
243
|
+
const runnerId = resolvePullWakeRunnerId(env, fileEnv);
|
|
244
|
+
const assertedAuth = buildAssertedAuthHeaders(env, fileEnv);
|
|
245
|
+
const serverHeaders = mergeHeaders(assertedAuth.headers, parseAdditionalServerHeaders(env, fileEnv));
|
|
184
246
|
const agentServerUrl = params.agentServerUrl ?? env.ELECTRIC_AGENTS_URL?.trim() ?? `http://localhost:${resolveElectricAgentsPort(env, fileEnv)}`;
|
|
185
247
|
process.env.ANTHROPIC_API_KEY = anthropicApiKey;
|
|
186
|
-
await waitForElectricAgentsServer(agentServerUrl);
|
|
248
|
+
await waitForElectricAgentsServer(agentServerUrl, { headers: serverHeaders });
|
|
187
249
|
const server = new BuiltinAgentsServer({
|
|
188
250
|
agentServerUrl,
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
251
|
+
workingDirectory: cwd,
|
|
252
|
+
loadProjectMcpConfig: true,
|
|
253
|
+
pullWake: {
|
|
254
|
+
runnerId,
|
|
255
|
+
ownerUserId: assertedAuth.ownerUserId,
|
|
256
|
+
registerRunner: true,
|
|
257
|
+
headers: serverHeaders,
|
|
258
|
+
claimHeaders: serverHeaders,
|
|
259
|
+
claimTokenHeader: hasHeader(serverHeaders, `authorization`) ? `electric-claim-token` : void 0
|
|
260
|
+
}
|
|
192
261
|
});
|
|
193
|
-
await server.start();
|
|
262
|
+
const url = await server.start();
|
|
194
263
|
const started = {
|
|
195
|
-
|
|
196
|
-
url
|
|
197
|
-
registeredBaseUrl: server.registeredBaseUrl,
|
|
264
|
+
runnerId,
|
|
265
|
+
url,
|
|
198
266
|
agentServerUrl
|
|
199
267
|
};
|
|
200
268
|
if (params.printStartedMessage ?? true) console.log(getStartedBuiltinAgentsMessage(started));
|
|
@@ -203,4 +271,4 @@ async function startBuiltinAgentsServer(options, params = {}) {
|
|
|
203
271
|
}
|
|
204
272
|
|
|
205
273
|
//#endregion
|
|
206
|
-
export { getStartedBuiltinAgentsMessage, getStartedEnvironmentMessage, getStoppedEnvironmentMessage, readDotEnvFile, resolveAnthropicApiKey,
|
|
274
|
+
export { getStartedBuiltinAgentsMessage, getStartedEnvironmentMessage, getStoppedEnvironmentMessage, readDotEnvFile, resolveAnthropicApiKey, resolveComposeProjectName, resolveElectricAgentsPort, resolvePullWakeOwnerId, resolvePullWakeRunnerId, startBuiltinAgentsServer, startElectricAgentsDevEnvironment, stopElectricAgentsDevEnvironment, waitForElectricAgentsServer };
|
package/docker-compose.full.yml
CHANGED
|
@@ -38,7 +38,7 @@ services:
|
|
|
38
38
|
|
|
39
39
|
electric-agents:
|
|
40
40
|
image: electricax/agents-server:${ELECTRIC_AGENTS_SERVER_IMAGE_TAG:-latest}
|
|
41
|
-
pull_policy:
|
|
41
|
+
pull_policy: ${ELECTRIC_AGENTS_SERVER_PULL_POLICY:-missing}
|
|
42
42
|
restart: unless-stopped
|
|
43
43
|
extra_hosts:
|
|
44
44
|
- 'host.docker.internal:host-gateway'
|
|
@@ -59,6 +59,9 @@ services:
|
|
|
59
59
|
ELECTRIC_AGENTS_STREAMS_PORT: ${ELECTRIC_AGENTS_STREAMS_PORT:-0}
|
|
60
60
|
ELECTRIC_AGENTS_ELECTRIC_URL: ${ELECTRIC_AGENTS_ELECTRIC_URL:-http://electric:3000}
|
|
61
61
|
ELECTRIC_AGENTS_REWRITE_LOOPBACK_WEBHOOKS_TO: ${ELECTRIC_AGENTS_REWRITE_LOOPBACK_WEBHOOKS_TO:-host.docker.internal}
|
|
62
|
+
ELECTRIC_AGENTS_DEV_ASSERTED_AUTH: ${ELECTRIC_AGENTS_DEV_ASSERTED_AUTH:-1}
|
|
63
|
+
ELECTRIC_ASSERTED_AUTH_EMAIL: ${ELECTRIC_ASSERTED_AUTH_EMAIL:-builtin-agents}
|
|
64
|
+
ELECTRIC_ASSERTED_AUTH_NAME: ${ELECTRIC_ASSERTED_AUTH_NAME:-Built-in agents}
|
|
62
65
|
ports:
|
|
63
66
|
- '${ELECTRIC_AGENTS_PORT:-4437}:4437'
|
|
64
67
|
volumes:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "electric-ax",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "CLI for Electric Agents",
|
|
5
5
|
"author": "ElectricSQL team and contributors",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -37,17 +37,17 @@
|
|
|
37
37
|
"./package.json": "./package.json"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@durable-streams/client": "
|
|
41
|
-
"@durable-streams/state": "
|
|
42
|
-
"@electric-sql/client": "^1.5.
|
|
40
|
+
"@durable-streams/client": "https://pkg.pr.new/durable-streams/durable-streams/@durable-streams/client@350",
|
|
41
|
+
"@durable-streams/state": "https://pkg.pr.new/durable-streams/durable-streams/@durable-streams/state@350",
|
|
42
|
+
"@electric-sql/client": "^1.5.17",
|
|
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.
|
|
50
|
-
"@electric-ax/agents-runtime": "0.
|
|
49
|
+
"@electric-ax/agents": "0.4.0",
|
|
50
|
+
"@electric-ax/agents-runtime": "0.2.0"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@vitest/coverage-v8": "^4.1.0",
|
|
File without changes
|
|
File without changes
|