totemlayer 0.1.37 → 0.1.39

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 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.37.tgz
21
+ npm install --global --ignore-scripts https://totemlayer.com/downloads/totemlayer-0.1.39.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.37.tgz totem install
40
+ npx --yes --package=https://totemlayer.com/downloads/totemlayer-0.1.39.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.37.tgz totem login --device-login --no-browser
50
+ npx --yes --package=https://totemlayer.com/downloads/totemlayer-0.1.39.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 phases = {
24
- messages: "starting",
25
- missions: settings.connectionOnly || settings.codexThreadId ? "waiting" : "starting",
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
- phases[queue] = event.type === "completed" ? "waiting" : event.type;
46
- const values = Object.values(phases);
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.includes(phase),
56
+ values.some((consumer) => consumer.type === phase),
50
57
  ) ?? "waiting";
51
- emit({ ...event, type });
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.37";
10
+ const VERSION = "0.1.39";
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,
@@ -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) => uncheckedRunAgent({ ...input, ...snapshot, inspector, task: originalTask }),
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 });
@@ -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,17 @@ 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",
54
+ "INBOX_CAPACITY_REACHED",
55
+ "WORK_RATE_LIMITED",
39
56
  "INTERNAL_ERROR",
40
57
  ]);
41
58
  export function runtimeErrorCode(error) {
42
- return RUNTIME_ERROR_CODES.has(error?.code) ? error.code : "INTERNAL_ERROR";
59
+ const code = MISSION_ERROR_CODES.get(error?.code) ?? error?.code;
60
+ return RUNTIME_ERROR_CODES.has(code) ? code : "INTERNAL_ERROR";
43
61
  }
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.37.tgz
240
+ Install once npm install --global https://totemlayer.com/downloads/totemlayer-0.1.39.tgz
241
241
  Confirm installation totem --version
242
- Run one-off npx --yes --package https://totemlayer.com/downloads/totemlayer-0.1.37.tgz totem --help
242
+ Run one-off npx --yes --package https://totemlayer.com/downloads/totemlayer-0.1.39.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "totemlayer",
3
- "version": "0.1.37",
3
+ "version": "0.1.39",
4
4
  "description": "Cross-platform CLI for TotemLayer agent identity and authorization",
5
5
  "type": "module",
6
6
  "bin": {