@electric-ax/agents 0.4.1 → 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.
@@ -885,11 +885,11 @@ function createSpawnWorkerTool(ctx, modelConfig) {
885
885
  return {
886
886
  name: `spawn_worker`,
887
887
  label: `Spawn Worker`,
888
- description: `Dispatch a subagent (worker) to perform an isolated subtask. Provide a system prompt that briefs the worker like a colleague who just walked into the room (file paths, line numbers, what specifically to do, what form of answer you want back) and pick the subset of tools the worker needs.`,
888
+ description: `Dispatch a subagent (worker) to perform an isolated subtask. Provide a brief system prompt to give it its role and then a detailed initialMessage which briefs the worker like a colleague who just walked into the room (file paths, line numbers, what specifically to do, what form of answer you want back) and pick the subset of tools the worker needs.`,
889
889
  parameters: Type.Object({
890
- systemPrompt: Type.String({ description: `System prompt for the worker. Be concrete: include file paths, line numbers, and the form of answer you want back.` }),
890
+ systemPrompt: Type.String({ description: `System prompt for the worker.` }),
891
891
  tools: Type.Array(Type.Union(WORKER_TOOL_NAMES.map((n) => Type.Literal(n))), { description: `Subset of tool names to enable for the worker. Must include at least one.` }),
892
- initialMessage: Type.String({ description: `First user message sent to the worker. This is what kicks off its run — without it the worker will idle. Describe the concrete task to perform.` })
892
+ initialMessage: Type.String({ description: `First user message sent to the worker. Be concrete: include file paths, line numbers, and the form of answer you want back. This is what kicks off its run — without it the worker will idle. Describe the concrete task to perform and what form of message you want back.` })
893
893
  }),
894
894
  execute: async (_toolCallId, params) => {
895
895
  const { systemPrompt, tools, initialMessage } = params;
@@ -1963,6 +1963,19 @@ async function registerBuiltinAgentTypes(bootstrap) {
1963
1963
 
1964
1964
  //#endregion
1965
1965
  //#region src/server.ts
1966
+ const PRINCIPAL_KEY_PREFIXES = new Set([
1967
+ `user`,
1968
+ `agent`,
1969
+ `service`,
1970
+ `system`
1971
+ ]);
1972
+ function normalizeOwnerUserId(ownerUserId) {
1973
+ const trimmed = ownerUserId?.trim();
1974
+ if (!trimmed) return void 0;
1975
+ const colon = trimmed.indexOf(`:`);
1976
+ if (colon > 0 && PRINCIPAL_KEY_PREFIXES.has(trimmed.slice(0, colon))) return trimmed;
1977
+ return `user:${trimmed}`;
1978
+ }
1966
1979
  var BuiltinAgentsServer = class {
1967
1980
  bootstrap = null;
1968
1981
  _mcpRegistry = null;
@@ -2167,22 +2180,35 @@ var BuiltinAgentsServer = class {
2167
2180
  async registerPullWakeRunner(pullWake) {
2168
2181
  const headers = new Headers(typeof pullWake.headers === `function` ? await pullWake.headers() : pullWake.headers);
2169
2182
  headers.set(`content-type`, `application/json`);
2183
+ const ownerUserId = normalizeOwnerUserId(pullWake.ownerUserId);
2184
+ const body = {
2185
+ id: pullWake.runnerId,
2186
+ label: pullWake.label ?? `Built-in agents`,
2187
+ kind: `local`,
2188
+ admin_status: `enabled`
2189
+ };
2190
+ if (ownerUserId) body.owner_user_id = ownerUserId;
2170
2191
  const response = await fetch(appendPathToUrl(this.options.agentServerUrl, `/_electric/runners`), {
2171
2192
  method: `POST`,
2172
2193
  headers,
2173
- body: JSON.stringify({
2174
- id: pullWake.runnerId,
2175
- owner_user_id: pullWake.ownerUserId,
2176
- label: pullWake.label ?? `Built-in agents`,
2177
- kind: `local`,
2178
- admin_status: `enabled`
2179
- })
2194
+ body: JSON.stringify(body)
2180
2195
  });
2181
2196
  if (!response.ok) throw new Error(`Failed to register pull-wake runner ${pullWake.runnerId}: ${response.status} ${await response.text()}`);
2182
2197
  return await response.json();
2183
2198
  }
2184
2199
  };
2185
2200
 
2201
+ //#endregion
2202
+ //#region src/server-headers.ts
2203
+ const ELECTRIC_PRINCIPAL_HEADER = `electric-principal`;
2204
+ function mergeElectricPrincipalHeader(headers, principal) {
2205
+ const merged = new Headers(headers);
2206
+ const trimmedPrincipal = principal?.trim();
2207
+ if (trimmedPrincipal !== void 0 && trimmedPrincipal.length > 0) merged.set(ELECTRIC_PRINCIPAL_HEADER, trimmedPrincipal);
2208
+ const normalized = Object.fromEntries(merged.entries());
2209
+ return Object.keys(normalized).length > 0 ? normalized : void 0;
2210
+ }
2211
+
2186
2212
  //#endregion
2187
2213
  //#region src/entrypoint-lib.ts
2188
2214
  function readEnv(env, names) {
@@ -2238,7 +2264,7 @@ function hasHeader(headers, name) {
2238
2264
  function resolveBuiltinAgentsEntrypointOptions(env = process.env, cwd = process.cwd()) {
2239
2265
  const agentServerUrl = validateUrl(`agent server URL`, readRequiredEnv(env, [`ELECTRIC_AGENTS_SERVER_URL`, `ELECTRIC_AGENTS_BASE_URL`], `agent server base URL`));
2240
2266
  const runnerId = readRequiredEnv(env, [`ELECTRIC_AGENTS_PULL_WAKE_RUNNER_ID`, `PULL_WAKE_RUNNER_ID`], `pull-wake runner id`);
2241
- const serverHeaders = mergeHeaders(parseAdditionalServerHeaders(env));
2267
+ const serverHeaders = mergeHeaders(mergeElectricPrincipalHeader(parseAdditionalServerHeaders(env), readEnv(env, [`ELECTRIC_AGENTS_PRINCIPAL`])));
2242
2268
  return {
2243
2269
  agentServerUrl,
2244
2270
  workingDirectory: readEnv(env, [`ELECTRIC_AGENTS_WORKING_DIRECTORY`, `WORKING_DIRECTORY`]) ?? cwd,
package/dist/index.cjs CHANGED
@@ -22,6 +22,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
  }) : target, mod));
23
23
 
24
24
  //#endregion
25
+ const require_server_headers = require('./server-headers-65vIhxvJ.cjs');
25
26
  const node_path = __toESM(require("node:path"));
26
27
  const node_url = __toESM(require("node:url"));
27
28
  const __electric_ax_agents_runtime = __toESM(require("@electric-ax/agents-runtime"));
@@ -908,11 +909,11 @@ function createSpawnWorkerTool(ctx, modelConfig) {
908
909
  return {
909
910
  name: `spawn_worker`,
910
911
  label: `Spawn Worker`,
911
- description: `Dispatch a subagent (worker) to perform an isolated subtask. Provide a system prompt that briefs the worker like a colleague who just walked into the room (file paths, line numbers, what specifically to do, what form of answer you want back) and pick the subset of tools the worker needs.`,
912
+ description: `Dispatch a subagent (worker) to perform an isolated subtask. Provide a brief system prompt to give it its role and then a detailed initialMessage which briefs the worker like a colleague who just walked into the room (file paths, line numbers, what specifically to do, what form of answer you want back) and pick the subset of tools the worker needs.`,
912
913
  parameters: __sinclair_typebox.Type.Object({
913
- systemPrompt: __sinclair_typebox.Type.String({ description: `System prompt for the worker. Be concrete: include file paths, line numbers, and the form of answer you want back.` }),
914
+ systemPrompt: __sinclair_typebox.Type.String({ description: `System prompt for the worker.` }),
914
915
  tools: __sinclair_typebox.Type.Array(__sinclair_typebox.Type.Union(WORKER_TOOL_NAMES.map((n) => __sinclair_typebox.Type.Literal(n))), { description: `Subset of tool names to enable for the worker. Must include at least one.` }),
915
- initialMessage: __sinclair_typebox.Type.String({ description: `First user message sent to the worker. This is what kicks off its run — without it the worker will idle. Describe the concrete task to perform.` })
916
+ initialMessage: __sinclair_typebox.Type.String({ description: `First user message sent to the worker. Be concrete: include file paths, line numbers, and the form of answer you want back. This is what kicks off its run — without it the worker will idle. Describe the concrete task to perform and what form of message you want back.` })
916
917
  }),
917
918
  execute: async (_toolCallId, params) => {
918
919
  const { systemPrompt, tools, initialMessage } = params;
@@ -1998,6 +1999,19 @@ const registerAgentTypes = registerBuiltinAgentTypes;
1998
1999
 
1999
2000
  //#endregion
2000
2001
  //#region src/server.ts
2002
+ const PRINCIPAL_KEY_PREFIXES = new Set([
2003
+ `user`,
2004
+ `agent`,
2005
+ `service`,
2006
+ `system`
2007
+ ]);
2008
+ function normalizeOwnerUserId(ownerUserId) {
2009
+ const trimmed = ownerUserId?.trim();
2010
+ if (!trimmed) return void 0;
2011
+ const colon = trimmed.indexOf(`:`);
2012
+ if (colon > 0 && PRINCIPAL_KEY_PREFIXES.has(trimmed.slice(0, colon))) return trimmed;
2013
+ return `user:${trimmed}`;
2014
+ }
2001
2015
  var BuiltinAgentsServer = class {
2002
2016
  bootstrap = null;
2003
2017
  _mcpRegistry = null;
@@ -2202,16 +2216,18 @@ var BuiltinAgentsServer = class {
2202
2216
  async registerPullWakeRunner(pullWake) {
2203
2217
  const headers = new Headers(typeof pullWake.headers === `function` ? await pullWake.headers() : pullWake.headers);
2204
2218
  headers.set(`content-type`, `application/json`);
2219
+ const ownerUserId = normalizeOwnerUserId(pullWake.ownerUserId);
2220
+ const body = {
2221
+ id: pullWake.runnerId,
2222
+ label: pullWake.label ?? `Built-in agents`,
2223
+ kind: `local`,
2224
+ admin_status: `enabled`
2225
+ };
2226
+ if (ownerUserId) body.owner_user_id = ownerUserId;
2205
2227
  const response = await fetch((0, __electric_ax_agents_runtime.appendPathToUrl)(this.options.agentServerUrl, `/_electric/runners`), {
2206
2228
  method: `POST`,
2207
2229
  headers,
2208
- body: JSON.stringify({
2209
- id: pullWake.runnerId,
2210
- owner_user_id: pullWake.ownerUserId,
2211
- label: pullWake.label ?? `Built-in agents`,
2212
- kind: `local`,
2213
- admin_status: `enabled`
2214
- })
2230
+ body: JSON.stringify(body)
2215
2231
  });
2216
2232
  if (!response.ok) throw new Error(`Failed to register pull-wake runner ${pullWake.runnerId}: ${response.status} ${await response.text()}`);
2217
2233
  return await response.json();
@@ -2273,7 +2289,7 @@ function hasHeader(headers, name) {
2273
2289
  function resolveBuiltinAgentsEntrypointOptions(env = process.env, cwd = process.cwd()) {
2274
2290
  const agentServerUrl = validateUrl(`agent server URL`, readRequiredEnv(env, [`ELECTRIC_AGENTS_SERVER_URL`, `ELECTRIC_AGENTS_BASE_URL`], `agent server base URL`));
2275
2291
  const runnerId = readRequiredEnv(env, [`ELECTRIC_AGENTS_PULL_WAKE_RUNNER_ID`, `PULL_WAKE_RUNNER_ID`], `pull-wake runner id`);
2276
- const serverHeaders = mergeHeaders(parseAdditionalServerHeaders(env));
2292
+ const serverHeaders = mergeHeaders(require_server_headers.mergeElectricPrincipalHeader(parseAdditionalServerHeaders(env), readEnv(env, [`ELECTRIC_AGENTS_PRINCIPAL`])));
2277
2293
  return {
2278
2294
  agentServerUrl,
2279
2295
  workingDirectory: readEnv(env, [`ELECTRIC_AGENTS_WORKING_DIRECTORY`, `WORKING_DIRECTORY`]) ?? cwd,
package/dist/index.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { mergeElectricPrincipalHeader } from "./server-headers-KD5yHFYT.js";
1
2
  import path from "node:path";
2
3
  import { fileURLToPath } from "node:url";
3
4
  import { appendPathToUrl, completeWithLowCostModel, createEntityRegistry, createPullWakeRunner, createRuntimeHandler, db, detectAvailableProviders, readCodexAccessToken, registerToolProvider, unregisterToolProvider } from "@electric-ax/agents-runtime";
@@ -884,11 +885,11 @@ function createSpawnWorkerTool(ctx, modelConfig) {
884
885
  return {
885
886
  name: `spawn_worker`,
886
887
  label: `Spawn Worker`,
887
- description: `Dispatch a subagent (worker) to perform an isolated subtask. Provide a system prompt that briefs the worker like a colleague who just walked into the room (file paths, line numbers, what specifically to do, what form of answer you want back) and pick the subset of tools the worker needs.`,
888
+ description: `Dispatch a subagent (worker) to perform an isolated subtask. Provide a brief system prompt to give it its role and then a detailed initialMessage which briefs the worker like a colleague who just walked into the room (file paths, line numbers, what specifically to do, what form of answer you want back) and pick the subset of tools the worker needs.`,
888
889
  parameters: Type.Object({
889
- systemPrompt: Type.String({ description: `System prompt for the worker. Be concrete: include file paths, line numbers, and the form of answer you want back.` }),
890
+ systemPrompt: Type.String({ description: `System prompt for the worker.` }),
890
891
  tools: Type.Array(Type.Union(WORKER_TOOL_NAMES.map((n) => Type.Literal(n))), { description: `Subset of tool names to enable for the worker. Must include at least one.` }),
891
- initialMessage: Type.String({ description: `First user message sent to the worker. This is what kicks off its run — without it the worker will idle. Describe the concrete task to perform.` })
892
+ initialMessage: Type.String({ description: `First user message sent to the worker. Be concrete: include file paths, line numbers, and the form of answer you want back. This is what kicks off its run — without it the worker will idle. Describe the concrete task to perform and what form of message you want back.` })
892
893
  }),
893
894
  execute: async (_toolCallId, params) => {
894
895
  const { systemPrompt, tools, initialMessage } = params;
@@ -1974,6 +1975,19 @@ const registerAgentTypes = registerBuiltinAgentTypes;
1974
1975
 
1975
1976
  //#endregion
1976
1977
  //#region src/server.ts
1978
+ const PRINCIPAL_KEY_PREFIXES = new Set([
1979
+ `user`,
1980
+ `agent`,
1981
+ `service`,
1982
+ `system`
1983
+ ]);
1984
+ function normalizeOwnerUserId(ownerUserId) {
1985
+ const trimmed = ownerUserId?.trim();
1986
+ if (!trimmed) return void 0;
1987
+ const colon = trimmed.indexOf(`:`);
1988
+ if (colon > 0 && PRINCIPAL_KEY_PREFIXES.has(trimmed.slice(0, colon))) return trimmed;
1989
+ return `user:${trimmed}`;
1990
+ }
1977
1991
  var BuiltinAgentsServer = class {
1978
1992
  bootstrap = null;
1979
1993
  _mcpRegistry = null;
@@ -2178,16 +2192,18 @@ var BuiltinAgentsServer = class {
2178
2192
  async registerPullWakeRunner(pullWake) {
2179
2193
  const headers = new Headers(typeof pullWake.headers === `function` ? await pullWake.headers() : pullWake.headers);
2180
2194
  headers.set(`content-type`, `application/json`);
2195
+ const ownerUserId = normalizeOwnerUserId(pullWake.ownerUserId);
2196
+ const body = {
2197
+ id: pullWake.runnerId,
2198
+ label: pullWake.label ?? `Built-in agents`,
2199
+ kind: `local`,
2200
+ admin_status: `enabled`
2201
+ };
2202
+ if (ownerUserId) body.owner_user_id = ownerUserId;
2181
2203
  const response = await fetch(appendPathToUrl(this.options.agentServerUrl, `/_electric/runners`), {
2182
2204
  method: `POST`,
2183
2205
  headers,
2184
- body: JSON.stringify({
2185
- id: pullWake.runnerId,
2186
- owner_user_id: pullWake.ownerUserId,
2187
- label: pullWake.label ?? `Built-in agents`,
2188
- kind: `local`,
2189
- admin_status: `enabled`
2190
- })
2206
+ body: JSON.stringify(body)
2191
2207
  });
2192
2208
  if (!response.ok) throw new Error(`Failed to register pull-wake runner ${pullWake.runnerId}: ${response.status} ${await response.text()}`);
2193
2209
  return await response.json();
@@ -2249,7 +2265,7 @@ function hasHeader(headers, name) {
2249
2265
  function resolveBuiltinAgentsEntrypointOptions(env = process.env, cwd = process.cwd()) {
2250
2266
  const agentServerUrl = validateUrl(`agent server URL`, readRequiredEnv(env, [`ELECTRIC_AGENTS_SERVER_URL`, `ELECTRIC_AGENTS_BASE_URL`], `agent server base URL`));
2251
2267
  const runnerId = readRequiredEnv(env, [`ELECTRIC_AGENTS_PULL_WAKE_RUNNER_ID`, `PULL_WAKE_RUNNER_ID`], `pull-wake runner id`);
2252
- const serverHeaders = mergeHeaders(parseAdditionalServerHeaders(env));
2268
+ const serverHeaders = mergeHeaders(mergeElectricPrincipalHeader(parseAdditionalServerHeaders(env), readEnv(env, [`ELECTRIC_AGENTS_PRINCIPAL`])));
2253
2269
  return {
2254
2270
  agentServerUrl,
2255
2271
  workingDirectory: readEnv(env, [`ELECTRIC_AGENTS_WORKING_DIRECTORY`, `WORKING_DIRECTORY`]) ?? cwd,
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+
3
+ //#region src/server-headers.ts
4
+ const ELECTRIC_PRINCIPAL_HEADER = `electric-principal`;
5
+ function mergeElectricPrincipalHeader(headers, principal) {
6
+ const merged = new Headers(headers);
7
+ const trimmedPrincipal = principal?.trim();
8
+ if (trimmedPrincipal !== void 0 && trimmedPrincipal.length > 0) merged.set(ELECTRIC_PRINCIPAL_HEADER, trimmedPrincipal);
9
+ const normalized = Object.fromEntries(merged.entries());
10
+ return Object.keys(normalized).length > 0 ? normalized : void 0;
11
+ }
12
+
13
+ //#endregion
14
+ Object.defineProperty(exports, 'ELECTRIC_PRINCIPAL_HEADER', {
15
+ enumerable: true,
16
+ get: function () {
17
+ return ELECTRIC_PRINCIPAL_HEADER;
18
+ }
19
+ });
20
+ Object.defineProperty(exports, 'mergeElectricPrincipalHeader', {
21
+ enumerable: true,
22
+ get: function () {
23
+ return mergeElectricPrincipalHeader;
24
+ }
25
+ });
@@ -0,0 +1,12 @@
1
+ //#region src/server-headers.ts
2
+ const ELECTRIC_PRINCIPAL_HEADER = `electric-principal`;
3
+ function mergeElectricPrincipalHeader(headers, principal) {
4
+ const merged = new Headers(headers);
5
+ const trimmedPrincipal = principal?.trim();
6
+ if (trimmedPrincipal !== void 0 && trimmedPrincipal.length > 0) merged.set(ELECTRIC_PRINCIPAL_HEADER, trimmedPrincipal);
7
+ const normalized = Object.fromEntries(merged.entries());
8
+ return Object.keys(normalized).length > 0 ? normalized : void 0;
9
+ }
10
+
11
+ //#endregion
12
+ export { ELECTRIC_PRINCIPAL_HEADER, mergeElectricPrincipalHeader };
@@ -0,0 +1,4 @@
1
+ const require_server_headers = require('./server-headers-65vIhxvJ.cjs');
2
+
3
+ exports.ELECTRIC_PRINCIPAL_HEADER = require_server_headers.ELECTRIC_PRINCIPAL_HEADER
4
+ exports.mergeElectricPrincipalHeader = require_server_headers.mergeElectricPrincipalHeader
@@ -0,0 +1,6 @@
1
+ //#region src/server-headers.d.ts
2
+ declare const ELECTRIC_PRINCIPAL_HEADER = "electric-principal";
3
+ declare function mergeElectricPrincipalHeader(headers: HeadersInit | undefined, principal: string | undefined): Record<string, string> | undefined;
4
+
5
+ //#endregion
6
+ export { ELECTRIC_PRINCIPAL_HEADER, mergeElectricPrincipalHeader };
@@ -0,0 +1,6 @@
1
+ //#region src/server-headers.d.ts
2
+ declare const ELECTRIC_PRINCIPAL_HEADER = "electric-principal";
3
+ declare function mergeElectricPrincipalHeader(headers: HeadersInit | undefined, principal: string | undefined): Record<string, string> | undefined;
4
+
5
+ //#endregion
6
+ export { ELECTRIC_PRINCIPAL_HEADER, mergeElectricPrincipalHeader };
@@ -0,0 +1,3 @@
1
+ import { ELECTRIC_PRINCIPAL_HEADER, mergeElectricPrincipalHeader } from "./server-headers-KD5yHFYT.js";
2
+
3
+ export { ELECTRIC_PRINCIPAL_HEADER, mergeElectricPrincipalHeader };
@@ -20,6 +20,8 @@ npm install -g electric-ax
20
20
  | -------------------------------- | ----------------------- | -------------------------------------------- |
21
21
  | `ELECTRIC_AGENTS_URL` | `http://localhost:4437` | Server URL for entity commands and built-ins |
22
22
  | `ELECTRIC_AGENTS_IDENTITY` | `user@hostname` | Sender identity for messages |
23
+ | `ELECTRIC_AGENTS_PRINCIPAL` | - | Optional principal key sent as `Electric-Principal` |
24
+ | `ELECTRIC_AGENTS_SERVER_HEADERS` | - | Optional JSON object of additional server headers |
23
25
  | `ELECTRIC_AGENTS_PORT` | `4437` | Port used by `start` / `quickstart` |
24
26
  | `ELECTRIC_AGENTS_BUILTIN_PORT` | `4448` | Webhook port for `start-builtin` |
25
27
  | `ELECTRIC_AGENTS_COMPOSE_PROJECT` | `electric-agents` | Docker Compose project name |
@@ -168,6 +168,8 @@ Environment variables:
168
168
  | Variable | Description |
169
169
  | -------------------------------- | ----------------------------------------------------- |
170
170
  | `ELECTRIC_AGENTS_SERVER_URL` | Required coordinator server URL. |
171
+ | `ELECTRIC_AGENTS_PRINCIPAL` | Optional principal key sent as `Electric-Principal`. |
172
+ | `ELECTRIC_AGENTS_SERVER_HEADERS` | Optional JSON object of additional server headers. |
171
173
  | `ELECTRIC_AGENTS_BUILTIN_BASE_URL` | Public webhook base URL for the built-in server. |
172
174
  | `ELECTRIC_AGENTS_BUILTIN_HOST` | Bind host. |
173
175
  | `ELECTRIC_AGENTS_BUILTIN_PORT` | Built-in server port. Defaults to `4448`. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electric-ax/agents",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "Built-in Electric Agents runtimes such as Horton and worker",
5
5
  "repository": {
6
6
  "type": "git",
@@ -25,6 +25,16 @@
25
25
  "default": "./dist/index.cjs"
26
26
  }
27
27
  },
28
+ "./server-headers": {
29
+ "import": {
30
+ "types": "./dist/server-headers.d.ts",
31
+ "default": "./dist/server-headers.js"
32
+ },
33
+ "require": {
34
+ "types": "./dist/server-headers.d.cts",
35
+ "default": "./dist/server-headers.cjs"
36
+ }
37
+ },
28
38
  "./package.json": "./package.json"
29
39
  },
30
40
  "dependencies": {