totemlayer 0.1.3 → 0.1.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 -11
- package/bin/agent-profile.mjs +466 -0
- package/bin/agent-runner.mjs +609 -0
- package/bin/agent-setup.mjs +659 -0
- package/bin/collaboration-companion.mjs +14 -33
- package/bin/collaboration-listener.mjs +13 -27
- package/bin/device-approval.mjs +93 -0
- package/bin/docker-test-sandbox.mjs +61 -0
- package/bin/local-mcp.mjs +1 -1
- package/bin/local-model-provider.mjs +29 -0
- package/bin/mcp-install.mjs +257 -14
- package/bin/mcp.mjs +1 -1
- package/bin/mission-agent-service.mjs +441 -0
- package/bin/mission-agent-session.mjs +188 -0
- package/bin/mission-supervisor.mjs +166 -0
- package/bin/mission-worker.mjs +3383 -0
- package/bin/network-runtime.mjs +86 -27
- package/bin/network.mjs +96 -5
- package/bin/platform-client.mjs +84 -0
- package/bin/sdk/action-types.js +1 -0
- package/bin/sdk/actions.js +84 -0
- package/bin/sdk/index.js +75 -0
- package/bin/sdk/request-options.js +36 -0
- package/bin/sdk/transport.js +8 -3
- package/bin/totem.mjs +23 -2
- package/package.json +1 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { TotemError } from "./errors.js";
|
|
2
|
+
export function requireActionChecksKey(apiKey) {
|
|
3
|
+
if (typeof apiKey !== "string" || !/^at_(?:test|live)_[A-Za-z0-9_-]{43}$/.test(apiKey)) {
|
|
4
|
+
throw new TotemError("A separate scoped Action Checks API key (at_test_ or at_live_) is required; Network credentials cannot authorize actions.", { code: "INVALID_CONFIG" });
|
|
5
|
+
}
|
|
6
|
+
return apiKey;
|
|
7
|
+
}
|
|
8
|
+
export function assistantCheckOptions(options) {
|
|
9
|
+
const { actionChecksApiKey, ...requestOptions } = options ?? {};
|
|
10
|
+
return {
|
|
11
|
+
...signalOnlyOptions(requestOptions),
|
|
12
|
+
headers: { "X-Totem-Action-Key": requireActionChecksKey(actionChecksApiKey) },
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
export function assertInputFields(input, allowed) {
|
|
16
|
+
if (!input ||
|
|
17
|
+
typeof input !== "object" ||
|
|
18
|
+
Array.isArray(input) ||
|
|
19
|
+
Object.keys(input).some((key) => !allowed.includes(key))) {
|
|
20
|
+
throw new TotemError("The request contains unsupported fields; caller identity comes from credentials.", {
|
|
21
|
+
code: "INVALID_INPUT",
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** These APIs derive caller identity from credentials, never from caller options. */
|
|
26
|
+
export function signalOnlyOptions(options = {}) {
|
|
27
|
+
if (!options ||
|
|
28
|
+
typeof options !== "object" ||
|
|
29
|
+
Array.isArray(options) ||
|
|
30
|
+
Object.keys(options).some((key) => key !== "signal")) {
|
|
31
|
+
throw new TotemError("Only an abort signal may be supplied as request options.", {
|
|
32
|
+
code: "INVALID_REQUEST_OPTIONS",
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return { signal: options.signal };
|
|
36
|
+
}
|
package/bin/sdk/transport.js
CHANGED
|
@@ -25,7 +25,8 @@ export class Transport {
|
|
|
25
25
|
#timeoutMs;
|
|
26
26
|
#maxRetries;
|
|
27
27
|
#retryDelayMs;
|
|
28
|
-
|
|
28
|
+
#responseEnvelope;
|
|
29
|
+
constructor(options, api = undefined) {
|
|
29
30
|
if (!options.apiKey?.trim())
|
|
30
31
|
throw new TotemError("An agent API key is required.", { code: "INVALID_CONFIG" });
|
|
31
32
|
const url = new URL(options.baseUrl ?? "https://totemlayer.com");
|
|
@@ -41,7 +42,8 @@ export class Transport {
|
|
|
41
42
|
});
|
|
42
43
|
}
|
|
43
44
|
this.#apiKey = options.apiKey;
|
|
44
|
-
this.#baseUrl = `${url.origin}/api/v1/network`;
|
|
45
|
+
this.#baseUrl = `${url.origin}${api?.basePath ?? "/api/v1/network"}`;
|
|
46
|
+
this.#responseEnvelope = api?.responseEnvelope ?? "data";
|
|
45
47
|
this.#fetch = options.fetch ?? globalThis.fetch.bind(globalThis);
|
|
46
48
|
this.#timeoutMs = options.timeoutMs ?? 15_000;
|
|
47
49
|
this.#maxRetries = options.maxRetries ?? 2;
|
|
@@ -117,7 +119,10 @@ export class Transport {
|
|
|
117
119
|
}
|
|
118
120
|
if (!result.ok)
|
|
119
121
|
throw apiError(result.status, payload, requestId);
|
|
120
|
-
if (!payload ||
|
|
122
|
+
if (!payload ||
|
|
123
|
+
typeof payload !== "object" ||
|
|
124
|
+
Array.isArray(payload) ||
|
|
125
|
+
(this.#responseEnvelope === "data" && !("data" in payload))) {
|
|
121
126
|
throw new TotemError("Totem returned an invalid response envelope.", {
|
|
122
127
|
code: "INVALID_RESPONSE",
|
|
123
128
|
requestId,
|
package/bin/totem.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
4
4
|
import { createReadStream } from "node:fs";
|
|
5
5
|
import { stripVTControlCharacters } from "node:util";
|
|
6
6
|
|
|
7
|
-
const CLI_VERSION = "0.1.
|
|
7
|
+
const CLI_VERSION = "0.1.5";
|
|
8
8
|
const DEFAULT_BASE_URL = "https://totemlayer.com";
|
|
9
9
|
const API_KEY_PATTERN = /^at_(?:live|test)_[A-Za-z0-9_-]{20,}$/;
|
|
10
10
|
const ACTION_PATTERN = /^[a-z0-9][a-z0-9._:-]*$/;
|
|
@@ -241,9 +241,16 @@ function help() {
|
|
|
241
241
|
Confirm installation totem --version
|
|
242
242
|
Run one-off npx --yes totemlayer --help
|
|
243
243
|
|
|
244
|
+
Connect once and receive Mission work (local preview)
|
|
245
|
+
Requires the matching local package; not yet published to npm.
|
|
246
|
+
totem setup
|
|
247
|
+
totem status
|
|
248
|
+
totem start --background
|
|
249
|
+
totem stop
|
|
250
|
+
|
|
244
251
|
Agent messaging and local runtime
|
|
245
252
|
totem network --help
|
|
246
|
-
totem network run --provider
|
|
253
|
+
totem network run --provider qwen-local --model qwen3.5-9b
|
|
247
254
|
|
|
248
255
|
Connect an AI app through MCP
|
|
249
256
|
totem mcp
|
|
@@ -1741,6 +1748,20 @@ async function runRfq(options, baseUrl) {
|
|
|
1741
1748
|
}
|
|
1742
1749
|
|
|
1743
1750
|
async function main() {
|
|
1751
|
+
if (["setup", "status", "doctor"].includes(process.argv[2])) {
|
|
1752
|
+
const { agentSetupMain, agentStatusMain } = await import("./agent-setup.mjs");
|
|
1753
|
+
const { readAgentRuntimeStatus } = await import("./agent-runner.mjs");
|
|
1754
|
+
const command = process.argv[2] === "setup" ? agentSetupMain : agentStatusMain;
|
|
1755
|
+
process.exitCode = await command(process.argv.slice(3), {
|
|
1756
|
+
readRuntimeStatus: readAgentRuntimeStatus,
|
|
1757
|
+
});
|
|
1758
|
+
return;
|
|
1759
|
+
}
|
|
1760
|
+
if (["start", "stop"].includes(process.argv[2])) {
|
|
1761
|
+
const { agentRunnerMain } = await import("./agent-runner.mjs");
|
|
1762
|
+
process.exitCode = await agentRunnerMain(process.argv[2], process.argv.slice(3));
|
|
1763
|
+
return;
|
|
1764
|
+
}
|
|
1744
1765
|
if (process.argv[2] === "mcp") {
|
|
1745
1766
|
if (process.argv[3] === "install" || process.argv[3] === "--help" || process.argv[3] === "-h") {
|
|
1746
1767
|
const { installTotemMcp } = await import("./mcp-install.mjs");
|