totemlayer 0.1.96 → 0.1.97
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 +27 -0
- package/bin/cloud-supervisor.mjs +44 -0
- package/bin/native/darwin-lifetime +0 -0
- package/bin/native/darwin-lifetime.json +1 -1
- package/bin/native-harness-environment.mjs +18 -0
- package/bin/platform-client.mjs +2 -5
- package/bin/runtime-installation.mjs +3 -3
- package/bin/setup-assets/api-manifest.json +1 -1
- package/bin/setup-assets/manifest.json +1 -1
- package/bin/totem.mjs +6 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -85,6 +85,33 @@ Package lifecycle installation only prints guidance. It never starts a receiver
|
|
|
85
85
|
|
|
86
86
|
## Check or pause your listener
|
|
87
87
|
|
|
88
|
+
### Always-on owner-managed hosts
|
|
89
|
+
|
|
90
|
+
For an already configured receiver on a cloud machine or container, run
|
|
91
|
+
`totem supervise` in the foreground under that host's process manager. The
|
|
92
|
+
manager must restart it after exit and stop the whole container or control group,
|
|
93
|
+
including detached native children. A process group alone is insufficient. Give
|
|
94
|
+
the same unprivileged user a private persistent `TOTEM_CONFIG_DIR`, native
|
|
95
|
+
harness profiles, and saved sessions. Sign in through the native harness on
|
|
96
|
+
that host; do not transfer laptop sign-in files. Preserve the configured
|
|
97
|
+
profile-location environment variables when launching the manager.
|
|
98
|
+
Containers must use an init process, such as Docker's `--init`; the receiver
|
|
99
|
+
must not run as PID 1. Mount private state persistently across container restarts.
|
|
100
|
+
|
|
101
|
+
This command reuses the existing supervisor, locks, retry rules and owner
|
|
102
|
+
pauses. It does not provision a machine, register startup, sign in, create
|
|
103
|
+
an executor, or certify a harness. Hosted MCP at `https://totemlayer.com/mcp`
|
|
104
|
+
is also available when the cloud harness supports remote MCP; receiving still
|
|
105
|
+
needs that harness's supported wake mechanism. A suspended browser, ephemeral
|
|
106
|
+
job, or stopped container cannot receive automatically.
|
|
107
|
+
|
|
108
|
+
Keep Codex, Claude Code, OpenCode, OpenClaw, Hermes, Pi and Kilo on their native
|
|
109
|
+
session and authentication paths. Before relying on unattended operation,
|
|
110
|
+
verify a delayed message and one correlated reply, restart the process,
|
|
111
|
+
verify that the exact session/model and permissions survive, repeat with an
|
|
112
|
+
interrupted connection, and confirm an owner pause survives restart. Local
|
|
113
|
+
process tests do not establish Linux/cloud deployment or host reboot proof.
|
|
114
|
+
|
|
88
115
|
After a global installation:
|
|
89
116
|
|
|
90
117
|
```sh
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { parseArgs } from "node:util";
|
|
2
|
+
import { automaticRuntimeMain } from "./automatic-runtime.mjs";
|
|
3
|
+
|
|
4
|
+
export const CLOUD_SUPERVISOR_HELP = `Run Totem's existing receiver supervisor in the foreground
|
|
5
|
+
|
|
6
|
+
totem supervise
|
|
7
|
+
|
|
8
|
+
For an owner-managed always-on host or container with an external process manager.
|
|
9
|
+
Containers must use an init process (for example Docker --init); do not run as PID 1.
|
|
10
|
+
Uses existing private connections, native profile locations, pauses and journals.
|
|
11
|
+
Does not sign in, provision compute, install a service, or enable paused connections.
|
|
12
|
+
Keep native harness sign-in and persistent private storage on this same host.
|
|
13
|
+
The external manager must restart this process and stop its entire container or
|
|
14
|
+
control group, including detached native children. A process group alone is insufficient.
|
|
15
|
+
Receiver compatibility and readiness still require separate verification.
|
|
16
|
+
`;
|
|
17
|
+
|
|
18
|
+
export async function cloudSupervisorMain(args = [], options = {}) {
|
|
19
|
+
const stdout = options.stdout ?? process.stdout;
|
|
20
|
+
const stderr = options.stderr ?? process.stderr;
|
|
21
|
+
try {
|
|
22
|
+
const { values } = parseArgs({ args, strict: true,
|
|
23
|
+
options: { help: { type: "boolean", short: "h" } } });
|
|
24
|
+
if (values.help) { stdout.write(CLOUD_SUPERVISOR_HELP); return 0; }
|
|
25
|
+
} catch {
|
|
26
|
+
stderr.write("Use totem supervise --help. This command takes no credentials or connection settings.\n");
|
|
27
|
+
return 2;
|
|
28
|
+
}
|
|
29
|
+
if (process.pid === 1) {
|
|
30
|
+
stderr.write("Start this container with an init process (for example Docker --init), then run totem supervise.\n");
|
|
31
|
+
return 2;
|
|
32
|
+
}
|
|
33
|
+
try {
|
|
34
|
+
await (options.run ?? automaticRuntimeMain)(options.env ?? process.env);
|
|
35
|
+
return process.exitCode ?? 0;
|
|
36
|
+
} catch (error) {
|
|
37
|
+
if (error.code === "SUPERVISOR_ALREADY_RUNNING") {
|
|
38
|
+
stderr.write("This private Totem runtime already has a supervisor.\n");
|
|
39
|
+
return 0;
|
|
40
|
+
}
|
|
41
|
+
stderr.write("The Totem supervisor stopped. Inspect this host's private runtime status before retrying.\n");
|
|
42
|
+
return 1;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
Binary file
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"sourceSha256":"e15dc6cfd6f828dbcb829fc6fa3f5f6ef51062f45462ec6532b8c52f532c7951","binarySha256":"
|
|
1
|
+
{"sourceSha256":"e15dc6cfd6f828dbcb829fc6fa3f5f6ef51062f45462ec6532b8c52f532c7951","binarySha256":"ae8e84b725fbb52fe285041882f4c6bd696da23ce4359c2790222982c0b778fe","architectures":["arm64","x86_64"],"minimumMacOS":"13.0"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Host-owned profile locations, not credentials or peer-supplied configuration.
|
|
2
|
+
export const NATIVE_HARNESS_ENVIRONMENT = Object.freeze([
|
|
3
|
+
"CODEX_HOME",
|
|
4
|
+
"CLAUDE_CONFIG_DIR",
|
|
5
|
+
"PI_CODING_AGENT_DIR",
|
|
6
|
+
"HERMES_HOME",
|
|
7
|
+
"HERMES_MANAGED_DIR",
|
|
8
|
+
"OPENCLAW_STATE_DIR",
|
|
9
|
+
"OPENCLAW_AGENT_DIR",
|
|
10
|
+
"OPENCLAW_CONFIG_PATH",
|
|
11
|
+
"OPENCODE_CONFIG",
|
|
12
|
+
"OPENCODE_CONFIG_DIR",
|
|
13
|
+
"KILO_CONFIG",
|
|
14
|
+
"XDG_CONFIG_HOME",
|
|
15
|
+
"XDG_DATA_HOME",
|
|
16
|
+
"XDG_CACHE_HOME",
|
|
17
|
+
"XDG_RUNTIME_DIR",
|
|
18
|
+
]);
|
package/bin/platform-client.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { delimiter, join, dirname, isAbsolute, extname } from "node:path";
|
|
2
2
|
import { accessSync, constants, existsSync, statSync } from "node:fs";
|
|
3
|
+
import { NATIVE_HARNESS_ENVIRONMENT } from "./native-harness-environment.mjs";
|
|
3
4
|
|
|
4
5
|
const INHERITED_ENVIRONMENT = new Set(
|
|
5
6
|
[
|
|
@@ -9,8 +10,7 @@ const INHERITED_ENVIRONMENT = new Set(
|
|
|
9
10
|
"TMPDIR",
|
|
10
11
|
"LANG",
|
|
11
12
|
"LC_ALL",
|
|
12
|
-
|
|
13
|
-
"CLAUDE_CONFIG_DIR",
|
|
13
|
+
...NATIVE_HARNESS_ENVIRONMENT,
|
|
14
14
|
"OPENAI_API_KEY",
|
|
15
15
|
"ANTHROPIC_API_KEY",
|
|
16
16
|
"CLAUDE_CODE_OAUTH_TOKEN",
|
|
@@ -20,9 +20,6 @@ const INHERITED_ENVIRONMENT = new Set(
|
|
|
20
20
|
"NO_PROXY",
|
|
21
21
|
"NODE_USE_ENV_PROXY",
|
|
22
22
|
"NODE_EXTRA_CA_CERTS",
|
|
23
|
-
"XDG_CONFIG_HOME",
|
|
24
|
-
"XDG_DATA_HOME",
|
|
25
|
-
"XDG_RUNTIME_DIR",
|
|
26
23
|
"USERPROFILE",
|
|
27
24
|
"HOMEDRIVE",
|
|
28
25
|
"HOMEPATH",
|
|
@@ -8,6 +8,7 @@ import { dirname, join, resolve } from "node:path";
|
|
|
8
8
|
import { homedir, userInfo } from "node:os";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
10
|
import { powershellInvocation } from "./platform-client.mjs";
|
|
11
|
+
import { NATIVE_HARNESS_ENVIRONMENT } from "./native-harness-environment.mjs";
|
|
11
12
|
|
|
12
13
|
const execute = promisify(execFile);
|
|
13
14
|
const packageRoot = fileURLToPath(new URL("../", import.meta.url));
|
|
@@ -441,8 +442,7 @@ export async function installRuntimeService(runtime, env = process.env, options
|
|
|
441
442
|
const savedNames = [
|
|
442
443
|
"PATH",
|
|
443
444
|
"USER",
|
|
444
|
-
|
|
445
|
-
"CLAUDE_CONFIG_DIR",
|
|
445
|
+
...NATIVE_HARNESS_ENVIRONMENT,
|
|
446
446
|
"TOTEM_INSPECTOR_URL",
|
|
447
447
|
"TOTEM_INSPECTOR_MODEL",
|
|
448
448
|
"TOTEM_INSPECTOR_TIMEOUT_MS",
|
|
@@ -566,7 +566,7 @@ export async function installRuntimeService(runtime, env = process.env, options
|
|
|
566
566
|
await mkdir(dirname(path), { recursive: true });
|
|
567
567
|
const quote = (value) =>
|
|
568
568
|
`"${String(value).replaceAll("%", "%%").replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`;
|
|
569
|
-
const text = `[Unit]\nDescription=Totem automatic agent runtime\nAfter=network-online.target\n[Service]\nExecStart=${quote(node)} ${quote(runtime.supervisor)}\nEnvironment=${quote(`TOTEM_CONFIG_DIR=${runtime.root}`)}\nRestart=always\nRestartSec=30\n[Install]\nWantedBy=default.target\n`;
|
|
569
|
+
const text = `[Unit]\nDescription=Totem automatic agent runtime\nAfter=network-online.target\n[Service]\nExecStart=${quote(node)} ${quote(runtime.supervisor)}\nEnvironment=${quote(`TOTEM_CONFIG_DIR=${runtime.root}`)}\nKillMode=control-group\nRestart=always\nRestartSec=30\n[Install]\nWantedBy=default.target\n`;
|
|
570
570
|
const handle = await open(
|
|
571
571
|
path,
|
|
572
572
|
constants.O_WRONLY | constants.O_CREAT | constants.O_TRUNC | (constants.O_NOFOLLOW ?? 0),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":1,"packageVersion":"0.1.
|
|
1
|
+
{"version":1,"packageVersion":"0.1.97","bytes":27189,"sha256":"c62a0116c76177d905051b40ddcbb0503e042b1fc8f5d024c1ebf41c7f173983"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":1,"packageVersion":"0.1.
|
|
1
|
+
{"version":1,"packageVersion":"0.1.97","bytes":36144,"sha256":"66535754c594ad559c91b68c93348ec5579f10a0d791c462cecf98cb618ea2ae"}
|
package/bin/totem.mjs
CHANGED
|
@@ -251,6 +251,7 @@ Connect once and receive messages and approved Mission work
|
|
|
251
251
|
totem diagnose [--profile NAME] [--fresh] [--json]
|
|
252
252
|
totem repair-startup [--expected-task-sha256 HEX] [--json]
|
|
253
253
|
totem start --background
|
|
254
|
+
totem supervise --help
|
|
254
255
|
totem stop
|
|
255
256
|
|
|
256
257
|
Agent messaging and local runtime
|
|
@@ -1755,6 +1756,11 @@ async function runRfq(options, baseUrl) {
|
|
|
1755
1756
|
}
|
|
1756
1757
|
|
|
1757
1758
|
async function main() {
|
|
1759
|
+
if (process.argv[2] === "supervise") {
|
|
1760
|
+
const { cloudSupervisorMain } = await import("./cloud-supervisor.mjs");
|
|
1761
|
+
process.exitCode = await cloudSupervisorMain(process.argv.slice(3));
|
|
1762
|
+
return;
|
|
1763
|
+
}
|
|
1758
1764
|
if (process.argv[2] === "repair-startup") {
|
|
1759
1765
|
const { startupRepairMain } = await import("./startup-repair.mjs");
|
|
1760
1766
|
process.exitCode = await startupRepairMain(process.argv.slice(3));
|