@agent-assembly/sdk 0.0.1-beta.3 → 0.0.1-beta.5
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/README.md +36 -23
- package/dist/cjs/core/gateway-resolver.js +73 -3
- package/dist/cjs/core/init-assembly.js +155 -33
- package/dist/cjs/core/redact.js +63 -0
- package/dist/cjs/gateway/client.js +63 -1
- package/dist/cjs/gateway/index.js +2 -1
- package/dist/cjs/hooks/ai-sdk.js +46 -10
- package/dist/cjs/hooks/langchain.js +12 -3
- package/dist/cjs/hooks/mastra.js +10 -6
- package/dist/cjs/hooks/openai-agents.js +1 -3
- package/dist/cjs/index.js +9 -1
- package/dist/cjs/native/client.js +94 -25
- package/dist/cjs/op-control.js +159 -17
- package/dist/cjs/runtime.js +73 -7
- package/dist/cjs/wrappers/with-assembly.js +89 -32
- package/dist/esm/core/gateway-resolver.js +72 -3
- package/dist/esm/core/gateway-resolver.js.map +1 -1
- package/dist/esm/core/init-assembly.js +154 -32
- package/dist/esm/core/init-assembly.js.map +1 -1
- package/dist/esm/core/redact.js +59 -0
- package/dist/esm/core/redact.js.map +1 -0
- package/dist/esm/gateway/client.js +62 -1
- package/dist/esm/gateway/client.js.map +1 -1
- package/dist/esm/gateway/index.js +1 -1
- package/dist/esm/gateway/index.js.map +1 -1
- package/dist/esm/hooks/ai-sdk.js +46 -10
- package/dist/esm/hooks/ai-sdk.js.map +1 -1
- package/dist/esm/hooks/langchain.js +12 -3
- package/dist/esm/hooks/langchain.js.map +1 -1
- package/dist/esm/hooks/mastra.js +10 -6
- package/dist/esm/hooks/mastra.js.map +1 -1
- package/dist/esm/hooks/openai-agents.js +1 -3
- package/dist/esm/hooks/openai-agents.js.map +1 -1
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/native/client.js +91 -24
- package/dist/esm/native/client.js.map +1 -1
- package/dist/esm/op-control.js +124 -17
- package/dist/esm/op-control.js.map +1 -1
- package/dist/esm/runtime.js +72 -7
- package/dist/esm/runtime.js.map +1 -1
- package/dist/esm/wrappers/with-assembly.js +89 -32
- package/dist/esm/wrappers/with-assembly.js.map +1 -1
- package/dist/types/core/gateway-resolver.d.ts +18 -1
- package/dist/types/core/gateway-resolver.d.ts.map +1 -1
- package/dist/types/core/init-assembly.d.ts +2 -1
- package/dist/types/core/init-assembly.d.ts.map +1 -1
- package/dist/types/core/redact.d.ts +28 -0
- package/dist/types/core/redact.d.ts.map +1 -0
- package/dist/types/gateway/client.d.ts +17 -0
- package/dist/types/gateway/client.d.ts.map +1 -1
- package/dist/types/gateway/index.d.ts +1 -1
- package/dist/types/gateway/index.d.ts.map +1 -1
- package/dist/types/hooks/ai-sdk.d.ts +13 -0
- package/dist/types/hooks/ai-sdk.d.ts.map +1 -1
- package/dist/types/hooks/langchain.d.ts +11 -0
- package/dist/types/hooks/langchain.d.ts.map +1 -1
- package/dist/types/hooks/mastra.d.ts.map +1 -1
- package/dist/types/hooks/openai-agents.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/native/client.d.ts +44 -0
- package/dist/types/native/client.d.ts.map +1 -1
- package/dist/types/op-control.d.ts +71 -7
- package/dist/types/op-control.d.ts.map +1 -1
- package/dist/types/runtime.d.ts +27 -5
- package/dist/types/runtime.d.ts.map +1 -1
- package/dist/types/types/assembly-config.d.ts +6 -0
- package/dist/types/types/assembly-config.d.ts.map +1 -1
- package/dist/types/wrappers/index.d.ts +1 -1
- package/dist/types/wrappers/index.d.ts.map +1 -1
- package/dist/types/wrappers/with-assembly.d.ts +25 -0
- package/dist/types/wrappers/with-assembly.d.ts.map +1 -1
- package/native/aa-ffi-node/index.d.ts +82 -1
- package/package.json +18 -5
package/dist/cjs/runtime.js
CHANGED
|
@@ -9,9 +9,10 @@
|
|
|
9
9
|
* flow with `import { initAssembly } from "@agent-assembly/sdk/runtime"`.
|
|
10
10
|
*/
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.INSTALL_HINT = exports.RUNTIME_SUBPACKAGE = exports.RUNTIME_LOG_FILENAME = exports.DOCKER_BASE_BIN = exports.USER_LOCAL_BIN = exports.DEFAULT_RUNTIME_HOST = exports.DEFAULT_PORT = exports.BINARY_NAME = void 0;
|
|
12
|
+
exports.INSTALL_HINT = exports.RUNTIME_SUBPACKAGE = exports.RUNTIME_LOG_FILENAME = exports.DOCKER_BASE_BIN = exports.USER_LOCAL_BIN = exports.ENV_AUTO_START = exports.DEFAULT_RUNTIME_HOST = exports.DEFAULT_PORT = exports.BINARY_NAME = void 0;
|
|
13
13
|
exports.findAasmBinary = findAasmBinary;
|
|
14
14
|
exports.isRunning = isRunning;
|
|
15
|
+
exports.assertSafeBinaryPath = assertSafeBinaryPath;
|
|
15
16
|
exports.startRuntime = startRuntime;
|
|
16
17
|
exports.initAssembly = initAssembly;
|
|
17
18
|
const node_child_process_1 = require("node:child_process");
|
|
@@ -24,6 +25,13 @@ const node_process_1 = require("node:process");
|
|
|
24
25
|
exports.BINARY_NAME = "aasm";
|
|
25
26
|
exports.DEFAULT_PORT = 7878;
|
|
26
27
|
exports.DEFAULT_RUNTIME_HOST = "127.0.0.1";
|
|
28
|
+
/**
|
|
29
|
+
* Opt-in gate for spawning the `aasm` sidecar. Auto-start runs a binary
|
|
30
|
+
* discovered from `$PATH` / the filesystem, so it is a privileged side effect
|
|
31
|
+
* that must be explicitly enabled rather than triggered silently by every
|
|
32
|
+
* `initAssembly()` call. Set to `1`/`true`/`yes` to permit auto-start.
|
|
33
|
+
*/
|
|
34
|
+
exports.ENV_AUTO_START = "AA_AUTO_START";
|
|
27
35
|
exports.USER_LOCAL_BIN = (0, node_path_1.join)((0, node_os_1.homedir)(), ".local", "bin");
|
|
28
36
|
exports.DOCKER_BASE_BIN = "/usr/local/bin";
|
|
29
37
|
exports.RUNTIME_LOG_FILENAME = ".aasm-runtime.log";
|
|
@@ -100,6 +108,51 @@ function isRunning(port = exports.DEFAULT_PORT, host = exports.DEFAULT_RUNTIME_H
|
|
|
100
108
|
socket.once("error", () => settle(false));
|
|
101
109
|
});
|
|
102
110
|
}
|
|
111
|
+
/** Truthy values that enable {@link ENV_AUTO_START}. */
|
|
112
|
+
function autoStartEnabled() {
|
|
113
|
+
const raw = node_process_1.env[exports.ENV_AUTO_START]?.trim().toLowerCase();
|
|
114
|
+
return raw === "1" || raw === "true" || raw === "yes";
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Install roots an auto-started `aasm` binary is permitted to live in, in
|
|
118
|
+
* addition to the npm-bundled `node_modules/@agent-assembly/runtime-*` path
|
|
119
|
+
* (which is trusted because it ships with the SDK install). This blocks a
|
|
120
|
+
* `$PATH`-injected `./aasm` or a binary planted in an arbitrary writable
|
|
121
|
+
* directory from being spawned.
|
|
122
|
+
*/
|
|
123
|
+
function allowedInstallDirs() {
|
|
124
|
+
const home = (0, node_os_1.homedir)();
|
|
125
|
+
return [
|
|
126
|
+
"/usr/local/bin",
|
|
127
|
+
"/usr/bin",
|
|
128
|
+
"/opt/homebrew/bin",
|
|
129
|
+
exports.USER_LOCAL_BIN,
|
|
130
|
+
(0, node_path_1.join)(home, ".cargo", "bin"),
|
|
131
|
+
"/usr/local/cargo/bin",
|
|
132
|
+
exports.DOCKER_BASE_BIN,
|
|
133
|
+
];
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Throw `Error` unless `binaryPath` is safe to spawn: it must be absolute and
|
|
137
|
+
* either resolve inside an allow-listed install dir (see
|
|
138
|
+
* {@link allowedInstallDirs}) or be the npm-bundled runtime binary. This is the
|
|
139
|
+
* integrity gate for the auto-start subprocess — without it the SDK would
|
|
140
|
+
* execute whatever `aasm` happened to be first on `$PATH`.
|
|
141
|
+
*/
|
|
142
|
+
function assertSafeBinaryPath(binaryPath) {
|
|
143
|
+
if (!(0, node_path_1.isAbsolute)(binaryPath)) {
|
|
144
|
+
throw new Error(`Refusing to auto-start a non-absolute 'aasm' path: ${binaryPath}`);
|
|
145
|
+
}
|
|
146
|
+
const resolved = (0, node_path_1.resolve)(binaryPath);
|
|
147
|
+
const bundled = bundledRuntimeBinaryPath();
|
|
148
|
+
if (bundled !== null && (0, node_path_1.resolve)(bundled) === resolved)
|
|
149
|
+
return;
|
|
150
|
+
const ok = allowedInstallDirs().some((dir) => resolved.startsWith((0, node_path_1.resolve)(dir) + "/"));
|
|
151
|
+
if (!ok) {
|
|
152
|
+
throw new Error(`Refusing to auto-start 'aasm' from an untrusted location: ${resolved}. ` +
|
|
153
|
+
`Install it under one of: ${allowedInstallDirs().join(", ")}.`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
103
156
|
/**
|
|
104
157
|
* Spawn `aasm serve --port <port>` as a detached background subprocess.
|
|
105
158
|
*
|
|
@@ -126,19 +179,32 @@ function startRuntime(binaryPath, port = exports.DEFAULT_PORT, logDir = (0, node
|
|
|
126
179
|
* 2. Resolve the binary via {@link findAasmBinary}.
|
|
127
180
|
* 3. Spawn the sidecar via {@link startRuntime}.
|
|
128
181
|
*
|
|
129
|
-
* `
|
|
130
|
-
*
|
|
131
|
-
* `@agent-assembly/sdk` `initAssembly`
|
|
182
|
+
* `_agentId` is accepted to keep the ticket-specified signature stable but is
|
|
183
|
+
* intentionally not consumed at this lifecycle layer; actual register-and-connect
|
|
184
|
+
* is performed by the existing gateway-aware `@agent-assembly/sdk` `initAssembly`
|
|
185
|
+
* once the sidecar is reachable.
|
|
186
|
+
*
|
|
187
|
+
* Auto-start is **opt-in**: when the sidecar is not already running, this
|
|
188
|
+
* throws unless `AA_AUTO_START` is enabled. When it does spawn, the resolved
|
|
189
|
+
* binary path is logged and integrity-checked via {@link assertSafeBinaryPath}.
|
|
132
190
|
*
|
|
133
|
-
* Throws `Error` with {@link INSTALL_HINT} when no binary is found
|
|
191
|
+
* Throws `Error` with {@link INSTALL_HINT} when no binary is found, and a
|
|
192
|
+
* descriptive `Error` when auto-start is not opted in or the resolved binary
|
|
193
|
+
* fails the integrity check.
|
|
134
194
|
*/
|
|
135
|
-
async function initAssembly(
|
|
136
|
-
void agentId; // not consumed at the lifecycle layer; see jsdoc
|
|
195
|
+
async function initAssembly(_agentId, port = exports.DEFAULT_PORT) {
|
|
137
196
|
if (await isRunning(port))
|
|
138
197
|
return;
|
|
198
|
+
if (!autoStartEnabled()) {
|
|
199
|
+
throw new Error(`No aasm sidecar running on port ${port} and auto-start is disabled. ` +
|
|
200
|
+
`Start it with 'aasm serve --port ${port}', or set ${exports.ENV_AUTO_START}=1 ` +
|
|
201
|
+
"to allow the SDK to auto-start it.");
|
|
202
|
+
}
|
|
139
203
|
const binary = findAasmBinary();
|
|
140
204
|
if (binary === null) {
|
|
141
205
|
throw new Error(exports.INSTALL_HINT);
|
|
142
206
|
}
|
|
207
|
+
assertSafeBinaryPath(binary);
|
|
208
|
+
console.info(`[agent-assembly] auto-starting aasm sidecar from ${binary}`);
|
|
143
209
|
startRuntime(binary, port);
|
|
144
210
|
}
|
|
@@ -2,8 +2,64 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.withAssembly = withAssembly;
|
|
4
4
|
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const op_terminated_error_js_1 = require("../errors/op-terminated-error.js");
|
|
5
6
|
const policy_violation_error_js_1 = require("../errors/policy-violation-error.js");
|
|
6
7
|
const DEFAULT_APPROVAL_TIMEOUT_MS = 30_000;
|
|
8
|
+
/**
|
|
9
|
+
* Resolve the op id (`"{traceId}:{spanId}"`) for a wrapped tool call.
|
|
10
|
+
*
|
|
11
|
+
* Prefers an explicit `opId` on the call's first argument; otherwise composes
|
|
12
|
+
* it from `traceId` / `spanId` when an adapter threads them through. Returns
|
|
13
|
+
* `undefined` when no trace identity is present — the call is not part of a
|
|
14
|
+
* tracked op, so there is nothing for the kill switch to address and op control
|
|
15
|
+
* is skipped. Mirrors the Python companion's `_extract_op_id`.
|
|
16
|
+
*/
|
|
17
|
+
function extractOpId(args) {
|
|
18
|
+
const first = args[0];
|
|
19
|
+
if (typeof first !== "object" || first === null) {
|
|
20
|
+
return undefined;
|
|
21
|
+
}
|
|
22
|
+
const fields = first;
|
|
23
|
+
const opId = fields.opId;
|
|
24
|
+
if (typeof opId === "string" && opId.length > 0) {
|
|
25
|
+
return opId;
|
|
26
|
+
}
|
|
27
|
+
const traceId = fields.traceId;
|
|
28
|
+
if (typeof traceId === "string" && traceId.length > 0) {
|
|
29
|
+
const spanId = fields.spanId;
|
|
30
|
+
const span = typeof spanId === "string" ? spanId : "";
|
|
31
|
+
return `${traceId}:${span}`;
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Consult the live op-control kill switch before the gateway is queried.
|
|
37
|
+
*
|
|
38
|
+
* A terminated op throws {@link PolicyViolationError} so the tool is blocked
|
|
39
|
+
* (and the gateway is never reached — the kill switch short-circuits). A paused
|
|
40
|
+
* op blocks here in `waitForOp` until the gateway resumes (or terminates) it.
|
|
41
|
+
* A no-op when no subscriber is wired or the call carries no `opId`.
|
|
42
|
+
*
|
|
43
|
+
* @throws {PolicyViolationError} when the op has been terminated by the gateway.
|
|
44
|
+
*/
|
|
45
|
+
async function enforceOpControl(opControl, name, args) {
|
|
46
|
+
if (!opControl) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const opId = extractOpId(args);
|
|
50
|
+
if (!opId) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
try {
|
|
54
|
+
await opControl.waitForOp(opId);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (error instanceof op_terminated_error_js_1.OpTerminatedError) {
|
|
58
|
+
throw new policy_violation_error_js_1.PolicyViolationError(`Tool '${name}' terminated: ${error.message}`);
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
7
63
|
async function waitForApprovalWithTimeout(gateway, toolName, runId, timeoutMs) {
|
|
8
64
|
let timeoutId;
|
|
9
65
|
const timeoutPromise = new Promise((resolve) => {
|
|
@@ -27,49 +83,50 @@ function hasExecute(tool) {
|
|
|
27
83
|
function hasInvoke(tool) {
|
|
28
84
|
return typeof tool.invoke === "function";
|
|
29
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Run the full pre-execution governance chain for one wrapped tool call.
|
|
88
|
+
*
|
|
89
|
+
* Order is load-bearing: the live op-control kill switch (AAASM-3491) runs
|
|
90
|
+
* first so an operator terminate short-circuits *before* the gateway is queried
|
|
91
|
+
* and a pause blocks here until resume; only then does the pre-exec gateway
|
|
92
|
+
* check + approval flow run.
|
|
93
|
+
*
|
|
94
|
+
* @throws {PolicyViolationError} when the op is terminated, the gateway denies,
|
|
95
|
+
* or an approval is rejected / times out.
|
|
96
|
+
*/
|
|
97
|
+
async function enforceGovernance(name, args, gateway, opControl, approvalTimeoutMs) {
|
|
98
|
+
await enforceOpControl(opControl, name, args);
|
|
99
|
+
const runId = `run_${(0, node_crypto_1.randomUUID)()}`;
|
|
100
|
+
const decision = await gateway.check({
|
|
101
|
+
action: "tool_call",
|
|
102
|
+
toolName: name,
|
|
103
|
+
args,
|
|
104
|
+
runId
|
|
105
|
+
});
|
|
106
|
+
if (decision.denied) {
|
|
107
|
+
throw new policy_violation_error_js_1.PolicyViolationError(`Tool '${name}' blocked: ${decision.reason ?? "Denied"}`);
|
|
108
|
+
}
|
|
109
|
+
if (decision.pending) {
|
|
110
|
+
const finalDecision = await waitForApprovalWithTimeout(gateway, name, runId, approvalTimeoutMs);
|
|
111
|
+
if (finalDecision.denied) {
|
|
112
|
+
throw new policy_violation_error_js_1.PolicyViolationError(`Approval rejected for '${name}': ${finalDecision.reason ?? "Rejected"}`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
30
116
|
function wrapSingleTool(name, tool, gateway, options) {
|
|
31
117
|
const approvalTimeoutMs = options.approvalTimeoutMs ?? DEFAULT_APPROVAL_TIMEOUT_MS;
|
|
118
|
+
const opControl = options.opControl;
|
|
32
119
|
if (hasExecute(tool)) {
|
|
33
120
|
const originalExecute = tool.execute;
|
|
34
121
|
tool.execute = async (...args) => {
|
|
35
|
-
|
|
36
|
-
const decision = await gateway.check({
|
|
37
|
-
action: "tool_call",
|
|
38
|
-
toolName: name,
|
|
39
|
-
args,
|
|
40
|
-
runId
|
|
41
|
-
});
|
|
42
|
-
if (decision.denied) {
|
|
43
|
-
throw new policy_violation_error_js_1.PolicyViolationError(`Tool '${name}' blocked: ${decision.reason ?? "Denied"}`);
|
|
44
|
-
}
|
|
45
|
-
if (decision.pending) {
|
|
46
|
-
const finalDecision = await waitForApprovalWithTimeout(gateway, name, runId, approvalTimeoutMs);
|
|
47
|
-
if (finalDecision.denied) {
|
|
48
|
-
throw new policy_violation_error_js_1.PolicyViolationError(`Approval rejected for '${name}': ${finalDecision.reason ?? "Rejected"}`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
122
|
+
await enforceGovernance(name, args, gateway, opControl, approvalTimeoutMs);
|
|
51
123
|
return originalExecute(...args);
|
|
52
124
|
};
|
|
53
125
|
}
|
|
54
126
|
else if (hasInvoke(tool)) {
|
|
55
127
|
const originalInvoke = tool.invoke;
|
|
56
128
|
tool.invoke = async (...args) => {
|
|
57
|
-
|
|
58
|
-
const decision = await gateway.check({
|
|
59
|
-
action: "tool_call",
|
|
60
|
-
toolName: name,
|
|
61
|
-
args,
|
|
62
|
-
runId
|
|
63
|
-
});
|
|
64
|
-
if (decision.denied) {
|
|
65
|
-
throw new policy_violation_error_js_1.PolicyViolationError(`Tool '${name}' blocked: ${decision.reason ?? "Denied"}`);
|
|
66
|
-
}
|
|
67
|
-
if (decision.pending) {
|
|
68
|
-
const finalDecision = await waitForApprovalWithTimeout(gateway, name, runId, approvalTimeoutMs);
|
|
69
|
-
if (finalDecision.denied) {
|
|
70
|
-
throw new policy_violation_error_js_1.PolicyViolationError(`Approval rejected for '${name}': ${finalDecision.reason ?? "Rejected"}`);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
129
|
+
await enforceGovernance(name, args, gateway, opControl, approvalTimeoutMs);
|
|
73
130
|
return originalInvoke(...args);
|
|
74
131
|
};
|
|
75
132
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
|
-
import { join, resolve as resolvePath } from "node:path";
|
|
4
|
+
import { isAbsolute, join, resolve as resolvePath } from "node:path";
|
|
5
5
|
import { ConfigurationError, GatewayError } from "../errors/index.js";
|
|
6
6
|
/**
|
|
7
7
|
* Resolve the gateway URL and API key for ``initAssembly``.
|
|
@@ -19,7 +19,9 @@ import { ConfigurationError, GatewayError } from "../errors/index.js";
|
|
|
19
19
|
* as deprecated aliases (a one-time warning is logged when a legacy name
|
|
20
20
|
* supplies the value)
|
|
21
21
|
* 3. Config file (~/.aasm/config.yaml, optional js-yaml soft dep)
|
|
22
|
-
* 4. Local default: probe http://localhost:7391, auto-start
|
|
22
|
+
* 4. Local default: probe http://localhost:7391; when absent, auto-start the
|
|
23
|
+
* local `aasm` gateway ONLY if `AA_AUTO_START` is opted in and the binary
|
|
24
|
+
* resolves to an allow-listed install dir — otherwise raise an error.
|
|
23
25
|
*/
|
|
24
26
|
export const DEFAULT_GATEWAY_URL = "http://localhost:7391";
|
|
25
27
|
export const DEFAULT_HEALTHZ_PATH = "/healthz";
|
|
@@ -28,6 +30,56 @@ export const DEFAULT_AUTO_START_TIMEOUT_MS = 5000;
|
|
|
28
30
|
export const DEFAULT_CONFIG_FILE_PATH = "~/.aasm/config.yaml";
|
|
29
31
|
export const ENV_GATEWAY_URL = "AA_GATEWAY_URL";
|
|
30
32
|
export const ENV_API_KEY = "AA_API_KEY";
|
|
33
|
+
/**
|
|
34
|
+
* Opt-in gate for auto-starting a local gateway. Auto-start spawns the `aasm`
|
|
35
|
+
* binary resolved from `$PATH`, so it is gated behind an explicit opt-in rather
|
|
36
|
+
* than running silently: a `$PATH` entry an attacker can write to would
|
|
37
|
+
* otherwise be executed by any process that calls `initAssembly()`. Set to
|
|
38
|
+
* `1`/`true`/`yes` to permit auto-start.
|
|
39
|
+
*/
|
|
40
|
+
export const ENV_AUTO_START = "AA_AUTO_START";
|
|
41
|
+
/** Truthy values that enable {@link ENV_AUTO_START}. */
|
|
42
|
+
function autoStartEnabled() {
|
|
43
|
+
const raw = process.env[ENV_AUTO_START]?.trim().toLowerCase();
|
|
44
|
+
return raw === "1" || raw === "true" || raw === "yes";
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Directories an auto-started `aasm` binary is permitted to live in. The
|
|
48
|
+
* resolved path must be absolute and sit inside one of these install roots,
|
|
49
|
+
* which blocks a `$PATH`-injected `./aasm` (cwd) or a binary planted in an
|
|
50
|
+
* arbitrary writable directory from being spawned. Mirrors the documented
|
|
51
|
+
* install locations (Homebrew, system, user-local, cargo).
|
|
52
|
+
*/
|
|
53
|
+
function allowedInstallDirs() {
|
|
54
|
+
const home = homedir();
|
|
55
|
+
return [
|
|
56
|
+
"/usr/local/bin",
|
|
57
|
+
"/usr/bin",
|
|
58
|
+
"/opt/homebrew/bin",
|
|
59
|
+
join(home, ".local", "bin"),
|
|
60
|
+
join(home, ".cargo", "bin"),
|
|
61
|
+
"/usr/local/cargo/bin",
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Throw {@link ConfigurationError} unless `aasmPath` is an absolute path inside
|
|
66
|
+
* an allow-listed install directory (see {@link allowedInstallDirs}). This is
|
|
67
|
+
* the integrity gate for the auto-start subprocess — without it the SDK would
|
|
68
|
+
* execute whatever `aasm` happened to be first on `$PATH`.
|
|
69
|
+
*/
|
|
70
|
+
export function assertAllowedAasmPath(aasmPath) {
|
|
71
|
+
if (!isAbsolute(aasmPath)) {
|
|
72
|
+
throw new ConfigurationError(`Refusing to auto-start a non-absolute 'aasm' path: ${aasmPath}. ` +
|
|
73
|
+
`Set ${ENV_GATEWAY_URL} to an already-running gateway instead.`);
|
|
74
|
+
}
|
|
75
|
+
const resolved = resolvePath(aasmPath);
|
|
76
|
+
const ok = allowedInstallDirs().some((dir) => resolved.startsWith(dir + "/"));
|
|
77
|
+
if (!ok) {
|
|
78
|
+
throw new ConfigurationError(`Refusing to auto-start 'aasm' from an untrusted location: ${resolved}. ` +
|
|
79
|
+
`Install it under one of: ${allowedInstallDirs().join(", ")}, ` +
|
|
80
|
+
`or set ${ENV_GATEWAY_URL} to an already-running gateway.`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
31
83
|
/**
|
|
32
84
|
* Deprecated environment-variable names, kept as backwards-compatible aliases.
|
|
33
85
|
*
|
|
@@ -112,7 +164,11 @@ export async function waitForHealthz(baseUrl, timeoutMs = DEFAULT_AUTO_START_TIM
|
|
|
112
164
|
return probeHealthz(baseUrl);
|
|
113
165
|
}
|
|
114
166
|
function expandHome(p) {
|
|
115
|
-
|
|
167
|
+
if (!p.startsWith("~")) {
|
|
168
|
+
return p;
|
|
169
|
+
}
|
|
170
|
+
const prefixLength = p.startsWith("~/") ? 2 : 1;
|
|
171
|
+
return resolvePath(homedir(), p.slice(prefixLength));
|
|
116
172
|
}
|
|
117
173
|
/**
|
|
118
174
|
* Load ``~/.aasm/config.yaml`` if present.
|
|
@@ -204,6 +260,11 @@ export async function autoStartGateway(baseUrl = DEFAULT_GATEWAY_URL, timeoutMs
|
|
|
204
260
|
throw new ConfigurationError(`No gateway found at ${baseUrl} and 'aasm' is not on PATH. ` +
|
|
205
261
|
"Install it with: npm install -g @agent-assembly/cli (or pnpm add -g)");
|
|
206
262
|
}
|
|
263
|
+
// Integrity gate: only spawn an absolute path from an allow-listed install
|
|
264
|
+
// dir, and surface the resolved path so the operator can see exactly which
|
|
265
|
+
// binary the SDK is about to execute.
|
|
266
|
+
assertAllowedAasmPath(aasmPath);
|
|
267
|
+
console.info(`[agent-assembly] auto-starting gateway from ${aasmPath}`);
|
|
207
268
|
_seams.spawnAasm(aasmPath);
|
|
208
269
|
if (!(await waitForHealthz(baseUrl, timeoutMs))) {
|
|
209
270
|
throw new GatewayError(`Auto-started gateway at ${baseUrl} did not become ready ` +
|
|
@@ -234,6 +295,14 @@ export async function resolveGatewayUrl(explicit) {
|
|
|
234
295
|
if (await _seams.probeHealthz(DEFAULT_GATEWAY_URL)) {
|
|
235
296
|
return DEFAULT_GATEWAY_URL;
|
|
236
297
|
}
|
|
298
|
+
// Auto-start is opt-in: spawning the local `aasm` binary is a privileged
|
|
299
|
+
// side effect, so a missing gateway is a hard error unless the operator has
|
|
300
|
+
// explicitly enabled AA_AUTO_START.
|
|
301
|
+
if (!autoStartEnabled()) {
|
|
302
|
+
throw new ConfigurationError(`No gateway found at ${DEFAULT_GATEWAY_URL}. Start one with 'aasm start ` +
|
|
303
|
+
`--mode local', set ${ENV_GATEWAY_URL} to a running gateway, or set ` +
|
|
304
|
+
`${ENV_AUTO_START}=1 to allow the SDK to auto-start a local gateway.`);
|
|
305
|
+
}
|
|
237
306
|
await _seams.autoStartGateway(DEFAULT_GATEWAY_URL);
|
|
238
307
|
return DEFAULT_GATEWAY_URL;
|
|
239
308
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway-resolver.js","sourceRoot":"","sources":["../../../src/core/gateway-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"gateway-resolver.js","sourceRoot":"","sources":["../../../src/core/gateway-resolver.ts"],"names":[],"mappings":"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"}
|