totemlayer 0.1.37 → 0.1.38
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 +3 -3
- package/bin/connected-agent-service.mjs +18 -7
- package/bin/mcp.mjs +1 -1
- package/bin/mission-agent-service.mjs +2 -0
- package/bin/mission-worker.mjs +11 -1
- package/bin/network-runtime.mjs +3 -0
- package/bin/runtime-diagnostics.mjs +17 -1
- package/bin/totem.mjs +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ The hosted connection needs no local installation. Sign in to Totem, select your
|
|
|
18
18
|
For a local stdio connection, install the CLI with Node.js 22.14 or newer:
|
|
19
19
|
|
|
20
20
|
```sh
|
|
21
|
-
npm install --global --ignore-scripts https://totemlayer.com/downloads/totemlayer-0.1.
|
|
21
|
+
npm install --global --ignore-scripts https://totemlayer.com/downloads/totemlayer-0.1.38.tgz
|
|
22
22
|
```
|
|
23
23
|
|
|
24
24
|
Save your agent's connection key in a private file. Protect it with mode 0600 on macOS/Linux or your user's filesystem ACL on Windows. Configure these fields in your client's MCP settings:
|
|
@@ -37,7 +37,7 @@ Reload the client if needed, discover the available tools, and call `totem_get_i
|
|
|
37
37
|
Run the guided installer on the host where your agent will execute work:
|
|
38
38
|
|
|
39
39
|
```sh
|
|
40
|
-
npx --yes --package=https://totemlayer.com/downloads/totemlayer-0.1.
|
|
40
|
+
npx --yes --package=https://totemlayer.com/downloads/totemlayer-0.1.38.tgz totem install
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
The installer opens Totem sign-in and saves the approved connection privately. It checks your configured agent runtime, configures supported clients, and starts the listener when an authorized executor is available. The supervised listener is enabled by default for this setup and starts when you sign in to the computer on hosts with a supported user service manager. It recovers after a process exit and retries temporary connection failures. An explicit stop stays paused across restarts.
|
|
@@ -47,7 +47,7 @@ For manual setup, use `totem mcp install` with a supported client and the privat
|
|
|
47
47
|
For a host without a browser:
|
|
48
48
|
|
|
49
49
|
```sh
|
|
50
|
-
npx --yes --package=https://totemlayer.com/downloads/totemlayer-0.1.
|
|
50
|
+
npx --yes --package=https://totemlayer.com/downloads/totemlayer-0.1.38.tgz totem login --device-login --no-browser
|
|
51
51
|
```
|
|
52
52
|
|
|
53
53
|
Open the printed link on your own device and compare the connection code. Preserve existing MCP entries; inspect conflicts before replacing them. If an executor is unavailable, the saved connection remains available while you complete runtime setup.
|
|
@@ -2,6 +2,7 @@ import { setTimeout as sleep } from "node:timers/promises";
|
|
|
2
2
|
import { runMissionAgentService } from "./mission-agent-service.mjs";
|
|
3
3
|
import { runRuntime } from "./network-runtime.mjs";
|
|
4
4
|
import { acquireMissionAgentSession } from "./mission-agent-session.mjs";
|
|
5
|
+
import { runtimeErrorCode } from "./runtime-diagnostics.mjs";
|
|
5
6
|
|
|
6
7
|
// Both queues use the same verified identity and private profile. A stopped or
|
|
7
8
|
// revoked connection cancels both consumers; Missions retains its own leases.
|
|
@@ -20,9 +21,11 @@ export async function runConnectedAgentService(settings, dependencies = {}) {
|
|
|
20
21
|
? AbortSignal.any([settings.signal, controller.signal])
|
|
21
22
|
: controller.signal;
|
|
22
23
|
const emit = settings.emit ?? (() => {});
|
|
23
|
-
const
|
|
24
|
-
messages: "starting",
|
|
25
|
-
missions:
|
|
24
|
+
const consumers = {
|
|
25
|
+
messages: { type: "starting" },
|
|
26
|
+
missions: {
|
|
27
|
+
type: settings.connectionOnly || settings.codexThreadId ? "waiting" : "starting",
|
|
28
|
+
},
|
|
26
29
|
};
|
|
27
30
|
let releaseMissions;
|
|
28
31
|
const messageReady = new Promise((resolve) => {
|
|
@@ -42,13 +45,21 @@ export async function runConnectedAgentService(settings, dependencies = {}) {
|
|
|
42
45
|
emit(event);
|
|
43
46
|
return;
|
|
44
47
|
}
|
|
45
|
-
|
|
46
|
-
|
|
48
|
+
consumers[queue] = {
|
|
49
|
+
...event,
|
|
50
|
+
type: event.type === "completed" ? "waiting" : event.type,
|
|
51
|
+
...(event.type === "blocked" ? { code: runtimeErrorCode(event) } : {}),
|
|
52
|
+
};
|
|
53
|
+
const values = Object.values(consumers);
|
|
47
54
|
const type =
|
|
48
55
|
["reconnecting", "starting", "blocked", "working"].find((phase) =>
|
|
49
|
-
values.
|
|
56
|
+
values.some((consumer) => consumer.type === phase),
|
|
50
57
|
) ?? "waiting";
|
|
51
|
-
|
|
58
|
+
// A healthy sibling poll must not replace the blocked consumer's code or IDs.
|
|
59
|
+
const current = consumers[queue];
|
|
60
|
+
const selected =
|
|
61
|
+
current.type === type ? current : values.find((consumer) => consumer.type === type);
|
|
62
|
+
emit({ ...(selected ?? current), type });
|
|
52
63
|
};
|
|
53
64
|
const messages = async () => {
|
|
54
65
|
let attempts = 0;
|
package/bin/mcp.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { Totem } from "./sdk/index.js";
|
|
|
7
7
|
import { inspectLocalRepository, verifyLocalRepoClaim } from "./repository.mjs";
|
|
8
8
|
import { createApprovalReview } from "./mcp-approval-review.mjs";
|
|
9
9
|
import { loadMcpIdentityBinding, createMcpIdentityGuard } from "./mcp-identity-binding.mjs";
|
|
10
|
-
const VERSION = "0.1.
|
|
10
|
+
const VERSION = "0.1.38";
|
|
11
11
|
const MAX_KEY_BYTES = 8 * 1024;
|
|
12
12
|
const MAX_ATTACHMENT_BYTES = 2 * 1024 * 1024;
|
|
13
13
|
const MAX_TOOL_INPUT_ELEMENTS = 10_000;
|
|
@@ -153,6 +153,7 @@ export async function runMissionAgentService(
|
|
|
153
153
|
ollamaUrl,
|
|
154
154
|
reasoning = false,
|
|
155
155
|
adapterSettings = {},
|
|
156
|
+
diagnosticDirectory,
|
|
156
157
|
stateDirectory = join(homedir(), ".totem", "missions"),
|
|
157
158
|
pollMs = 5000,
|
|
158
159
|
signal,
|
|
@@ -316,6 +317,7 @@ export async function runMissionAgentService(
|
|
|
316
317
|
ollamaUrl,
|
|
317
318
|
reasoning,
|
|
318
319
|
adapterSettings,
|
|
320
|
+
diagnosticDirectory,
|
|
319
321
|
signal,
|
|
320
322
|
candidateWorkItem: workItem,
|
|
321
323
|
recoveryOnly,
|
package/bin/mission-worker.mjs
CHANGED
|
@@ -1624,6 +1624,7 @@ async function runStructuredMissionAgent({
|
|
|
1624
1624
|
reasoning = false,
|
|
1625
1625
|
rejectionEvidenceDirectory,
|
|
1626
1626
|
adapterSettings = {},
|
|
1627
|
+
diagnosticDirectory,
|
|
1627
1628
|
inspector = customerInspector(),
|
|
1628
1629
|
task,
|
|
1629
1630
|
}) {
|
|
@@ -1669,6 +1670,7 @@ async function runStructuredMissionAgent({
|
|
|
1669
1670
|
schema: body.response_format?.json_schema?.schema,
|
|
1670
1671
|
signal: options.signal,
|
|
1671
1672
|
timeoutMs,
|
|
1673
|
+
diagnosticDirectory,
|
|
1672
1674
|
});
|
|
1673
1675
|
return { choices: [{ message: { content } }] };
|
|
1674
1676
|
}
|
|
@@ -2594,6 +2596,7 @@ export async function runMissionWorker({
|
|
|
2594
2596
|
emit = () => {},
|
|
2595
2597
|
runAgent = runLocalMissionAgent,
|
|
2596
2598
|
adapterSettings = {},
|
|
2599
|
+
diagnosticDirectory,
|
|
2597
2600
|
inspector,
|
|
2598
2601
|
inspectorOptions,
|
|
2599
2602
|
}) {
|
|
@@ -2612,7 +2615,14 @@ export async function runMissionWorker({
|
|
|
2612
2615
|
write: input.write ?? false,
|
|
2613
2616
|
stage: input.stage,
|
|
2614
2617
|
},
|
|
2615
|
-
(snapshot) =>
|
|
2618
|
+
(snapshot) =>
|
|
2619
|
+
uncheckedRunAgent({
|
|
2620
|
+
...input,
|
|
2621
|
+
...snapshot,
|
|
2622
|
+
inspector,
|
|
2623
|
+
task: originalTask,
|
|
2624
|
+
diagnosticDirectory,
|
|
2625
|
+
}),
|
|
2616
2626
|
{ task: originalTask, signal: input.signal },
|
|
2617
2627
|
);
|
|
2618
2628
|
await inspector.assertAllowed("output", result, { task: originalTask, signal: input.signal });
|
package/bin/network-runtime.mjs
CHANGED
|
@@ -95,6 +95,7 @@ export async function modelReply({
|
|
|
95
95
|
timeoutMs,
|
|
96
96
|
fetcher = fetch,
|
|
97
97
|
adapterSettings = {},
|
|
98
|
+
diagnosticDirectory,
|
|
98
99
|
}) {
|
|
99
100
|
if (isExternalModelProvider(provider))
|
|
100
101
|
return {
|
|
@@ -106,6 +107,7 @@ export async function modelReply({
|
|
|
106
107
|
messages,
|
|
107
108
|
signal,
|
|
108
109
|
timeoutMs,
|
|
110
|
+
diagnosticDirectory,
|
|
109
111
|
}),
|
|
110
112
|
};
|
|
111
113
|
const timeout = AbortSignal.timeout(timeoutMs);
|
|
@@ -438,6 +440,7 @@ async function generate({
|
|
|
438
440
|
signal,
|
|
439
441
|
timeoutMs: settings.modelTimeoutMs,
|
|
440
442
|
adapterSettings: settings.adapterSettings,
|
|
443
|
+
diagnosticDirectory: settings.diagnosticDirectory,
|
|
441
444
|
});
|
|
442
445
|
} catch (error) {
|
|
443
446
|
// Keep unknown execution outcomes guarded, including across restarts.
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
+
const MISSION_ERROR_CODES = new Map([
|
|
2
|
+
["permission_denied", "MISSION_PERMISSION_DENIED"],
|
|
3
|
+
["repository_configuration_invalid", "MISSION_REPOSITORY_CONFIGURATION_INVALID"],
|
|
4
|
+
["needs_attention", "MISSION_NEEDS_ATTENTION"],
|
|
5
|
+
["work_failed", "MISSION_WORK_FAILED"],
|
|
6
|
+
["recovery_waiting", "MISSION_RECOVERY_WAITING"],
|
|
7
|
+
]);
|
|
8
|
+
|
|
1
9
|
export const RUNTIME_ERROR_CODES = new Set([
|
|
10
|
+
...MISSION_ERROR_CODES.values(),
|
|
2
11
|
"AGENT_START_FAILED",
|
|
3
12
|
"AGENT_EXIT_FAILED",
|
|
4
13
|
"AGENT_REPORTED_FAILURE",
|
|
@@ -36,8 +45,15 @@ export const RUNTIME_ERROR_CODES = new Set([
|
|
|
36
45
|
"READINESS_PROBE_FAILED",
|
|
37
46
|
"RUNTIME_AUTHORIZATION_REJECTED",
|
|
38
47
|
"RUNTIME_SUPERSEDED",
|
|
48
|
+
"COMMUNICATION_POLICY_DENIED",
|
|
49
|
+
"SENDER_DENIED",
|
|
50
|
+
"ENVIRONMENT_MISMATCH",
|
|
51
|
+
"SENDER_INACTIVE",
|
|
52
|
+
"RECIPIENT_INACTIVE",
|
|
53
|
+
"INVALID_COMMUNICATION_POLICY",
|
|
39
54
|
"INTERNAL_ERROR",
|
|
40
55
|
]);
|
|
41
56
|
export function runtimeErrorCode(error) {
|
|
42
|
-
|
|
57
|
+
const code = MISSION_ERROR_CODES.get(error?.code) ?? error?.code;
|
|
58
|
+
return RUNTIME_ERROR_CODES.has(code) ? code : "INTERNAL_ERROR";
|
|
43
59
|
}
|
package/bin/totem.mjs
CHANGED
|
@@ -237,9 +237,9 @@ function compactDigest(value) {
|
|
|
237
237
|
function help() {
|
|
238
238
|
writeBrand();
|
|
239
239
|
writeHelpBody(`Start here
|
|
240
|
-
Install once npm install --global https://totemlayer.com/downloads/totemlayer-0.1.
|
|
240
|
+
Install once npm install --global https://totemlayer.com/downloads/totemlayer-0.1.38.tgz
|
|
241
241
|
Confirm installation totem --version
|
|
242
|
-
Run one-off npx --yes --package https://totemlayer.com/downloads/totemlayer-0.1.
|
|
242
|
+
Run one-off npx --yes --package https://totemlayer.com/downloads/totemlayer-0.1.38.tgz totem --help
|
|
243
243
|
|
|
244
244
|
Connect once and receive messages and approved Mission work
|
|
245
245
|
Select Codex, Claude, a local model, or an owner-configured CLI/HTTP agent.
|