nemoris 0.1.0 → 0.1.2
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/.env.example +49 -49
- package/LICENSE +21 -21
- package/README.md +209 -209
- package/SECURITY.md +59 -119
- package/bin/nemoris +46 -46
- package/config/agents/agent.toml.example +28 -28
- package/config/agents/content.toml +23 -0
- package/config/agents/default.toml +22 -22
- package/config/agents/heartbeat.toml +35 -0
- package/config/agents/iris.toml +23 -0
- package/config/agents/lab.toml +23 -0
- package/config/agents/main.toml +45 -0
- package/config/agents/nemo.toml +21 -0
- package/config/agents/ops.toml +38 -0
- package/config/agents/orchestrator.toml +18 -18
- package/config/agents/revenue.toml +23 -0
- package/config/agents/testyboo.toml +19 -0
- package/config/delivery.toml +73 -73
- package/config/embeddings.toml +5 -5
- package/config/identity/content-purpose.md +11 -0
- package/config/identity/content-soul.md +45 -0
- package/config/identity/default-purpose.md +1 -1
- package/config/identity/default-soul.md +3 -3
- package/config/identity/heartbeat-purpose.md +9 -0
- package/config/identity/heartbeat-soul.md +16 -0
- package/config/identity/iris-purpose.md +17 -0
- package/config/identity/iris-soul.md +68 -0
- package/config/identity/lab-purpose.md +10 -0
- package/config/identity/lab-soul.md +38 -0
- package/config/identity/main-purpose.md +17 -0
- package/config/identity/main-soul.md +66 -0
- package/config/identity/main-user.md +22 -0
- package/config/identity/ops-purpose.md +9 -0
- package/config/identity/ops-soul.md +16 -0
- package/config/identity/orchestrator-purpose.md +1 -1
- package/config/identity/orchestrator-soul.md +1 -1
- package/config/identity/revenue-purpose.md +9 -0
- package/config/identity/revenue-soul.md +41 -0
- package/config/identity/testyboo-purpose.md +13 -0
- package/config/identity/testyboo-soul.md +20 -0
- package/config/improvement-targets.toml +15 -15
- package/config/jobs/heartbeat-check.toml +30 -30
- package/config/jobs/memory-rollup.toml +46 -46
- package/config/jobs/workspace-health.toml +63 -63
- package/config/mcp.toml +16 -16
- package/config/output-contracts.toml +17 -17
- package/config/peers.toml +32 -32
- package/config/peers.toml.example +32 -32
- package/config/policies/memory-default.toml +10 -10
- package/config/policies/memory-heartbeat.toml +5 -5
- package/config/policies/memory-ops.toml +10 -10
- package/config/policies/tools-heartbeat-minimal.toml +8 -8
- package/config/policies/tools-interactive-safe.toml +8 -8
- package/config/policies/tools-ops-bounded.toml +8 -8
- package/config/policies/tools-orchestrator.toml +7 -7
- package/config/providers/anthropic.toml +15 -15
- package/config/providers/ollama.toml +5 -5
- package/config/providers/openai-codex.toml +9 -9
- package/config/providers/openrouter.toml +5 -5
- package/config/router.toml +22 -22
- package/config/runtime.toml +114 -114
- package/config/skills/self-improvement.toml +15 -15
- package/config/skills/telegram-onboarding-spec.md +240 -240
- package/config/skills/workspace-monitor.toml +15 -15
- package/config/task-router.toml +42 -42
- package/install.sh +50 -50
- package/package.json +91 -90
- package/src/auth/auth-profiles.js +169 -169
- package/src/auth/openai-codex-oauth.js +285 -285
- package/src/battle.js +449 -449
- package/src/cli/help.js +265 -265
- package/src/cli/output-filter.js +49 -49
- package/src/cli/runtime-control.js +704 -704
- package/src/cli-main.js +2763 -2763
- package/src/cli.js +78 -78
- package/src/config/loader.js +332 -332
- package/src/config/schema-validator.js +214 -214
- package/src/config/toml-lite.js +8 -8
- package/src/daemon/action-handlers.js +71 -71
- package/src/daemon/healing-tick.js +87 -87
- package/src/daemon/health-probes.js +90 -90
- package/src/daemon/notifier.js +57 -57
- package/src/daemon/nurse.js +218 -218
- package/src/daemon/repair-log.js +106 -106
- package/src/daemon/rule-staging.js +90 -90
- package/src/daemon/rules.js +29 -29
- package/src/daemon/telegram-commands.js +54 -54
- package/src/daemon/updater.js +85 -85
- package/src/jobs/job-runner.js +78 -78
- package/src/mcp/consumer.js +129 -129
- package/src/memory/active-recall.js +171 -171
- package/src/memory/backend-manager.js +97 -97
- package/src/memory/backends/file-backend.js +38 -38
- package/src/memory/backends/qmd-backend.js +219 -219
- package/src/memory/embedding-guards.js +24 -24
- package/src/memory/embedding-index.js +118 -118
- package/src/memory/embedding-service.js +179 -179
- package/src/memory/file-index.js +177 -177
- package/src/memory/memory-signature.js +5 -5
- package/src/memory/memory-store.js +648 -648
- package/src/memory/retrieval-planner.js +66 -66
- package/src/memory/scoring.js +145 -145
- package/src/memory/simhash.js +78 -78
- package/src/memory/sqlite-active-store.js +824 -824
- package/src/memory/write-policy.js +36 -36
- package/src/onboarding/aliases.js +33 -33
- package/src/onboarding/auth/api-key.js +224 -224
- package/src/onboarding/auth/ollama-detect.js +42 -42
- package/src/onboarding/clack-prompter.js +77 -77
- package/src/onboarding/doctor.js +530 -530
- package/src/onboarding/lock.js +42 -42
- package/src/onboarding/model-catalog.js +344 -344
- package/src/onboarding/phases/auth.js +576 -589
- package/src/onboarding/phases/build.js +130 -130
- package/src/onboarding/phases/choose.js +82 -82
- package/src/onboarding/phases/detect.js +98 -98
- package/src/onboarding/phases/hatch.js +216 -216
- package/src/onboarding/phases/identity.js +79 -79
- package/src/onboarding/phases/ollama.js +345 -345
- package/src/onboarding/phases/scaffold.js +99 -99
- package/src/onboarding/phases/telegram.js +377 -377
- package/src/onboarding/phases/validate.js +204 -204
- package/src/onboarding/phases/verify.js +206 -206
- package/src/onboarding/platform.js +482 -482
- package/src/onboarding/status-bar.js +95 -95
- package/src/onboarding/templates.js +794 -794
- package/src/onboarding/toml-writer.js +38 -38
- package/src/onboarding/tui.js +250 -250
- package/src/onboarding/uninstall.js +153 -153
- package/src/onboarding/wizard.js +516 -499
- package/src/providers/anthropic.js +168 -168
- package/src/providers/base.js +247 -247
- package/src/providers/circuit-breaker.js +136 -136
- package/src/providers/ollama.js +163 -163
- package/src/providers/openai-codex.js +149 -149
- package/src/providers/openrouter.js +136 -136
- package/src/providers/registry.js +36 -36
- package/src/providers/router.js +16 -16
- package/src/runtime/bootstrap-cache.js +47 -47
- package/src/runtime/capabilities-prompt.js +25 -25
- package/src/runtime/completion-ping.js +99 -99
- package/src/runtime/config-validator.js +121 -121
- package/src/runtime/context-ledger.js +360 -360
- package/src/runtime/cutover-readiness.js +42 -42
- package/src/runtime/daemon.js +729 -729
- package/src/runtime/delivery-ack.js +195 -195
- package/src/runtime/delivery-adapters/local-file.js +41 -41
- package/src/runtime/delivery-adapters/openclaw-cli.js +94 -94
- package/src/runtime/delivery-adapters/openclaw-peer.js +98 -98
- package/src/runtime/delivery-adapters/shadow.js +13 -13
- package/src/runtime/delivery-adapters/standalone-http.js +98 -98
- package/src/runtime/delivery-adapters/telegram.js +104 -104
- package/src/runtime/delivery-adapters/tui.js +128 -128
- package/src/runtime/delivery-manager.js +807 -807
- package/src/runtime/delivery-store.js +168 -168
- package/src/runtime/dependency-health.js +118 -118
- package/src/runtime/envelope.js +114 -114
- package/src/runtime/evaluation.js +1089 -1089
- package/src/runtime/exec-approvals.js +216 -216
- package/src/runtime/executor.js +500 -500
- package/src/runtime/failure-ping.js +67 -67
- package/src/runtime/flows.js +83 -83
- package/src/runtime/guards.js +45 -45
- package/src/runtime/handoff.js +51 -51
- package/src/runtime/identity-cache.js +28 -28
- package/src/runtime/improvement-engine.js +109 -109
- package/src/runtime/improvement-harness.js +581 -581
- package/src/runtime/input-sanitiser.js +72 -72
- package/src/runtime/interaction-contract.js +347 -347
- package/src/runtime/lane-readiness.js +226 -226
- package/src/runtime/migration.js +323 -323
- package/src/runtime/model-resolution.js +78 -78
- package/src/runtime/network.js +64 -64
- package/src/runtime/notification-store.js +97 -97
- package/src/runtime/notifier.js +256 -256
- package/src/runtime/orchestrator.js +53 -53
- package/src/runtime/orphan-reaper.js +41 -41
- package/src/runtime/output-contract-schema.js +139 -139
- package/src/runtime/output-contract-validator.js +439 -439
- package/src/runtime/peer-readiness.js +69 -69
- package/src/runtime/peer-registry.js +133 -133
- package/src/runtime/pilot-status.js +108 -108
- package/src/runtime/prompt-builder.js +261 -261
- package/src/runtime/provider-attempt.js +582 -582
- package/src/runtime/report-fallback.js +71 -71
- package/src/runtime/result-normalizer.js +183 -183
- package/src/runtime/retention.js +74 -74
- package/src/runtime/review.js +244 -244
- package/src/runtime/route-job.js +15 -15
- package/src/runtime/run-store.js +38 -38
- package/src/runtime/schedule.js +88 -88
- package/src/runtime/scheduler-state.js +434 -434
- package/src/runtime/scheduler.js +656 -656
- package/src/runtime/session-compactor.js +182 -182
- package/src/runtime/session-search.js +155 -155
- package/src/runtime/slack-inbound.js +249 -249
- package/src/runtime/ssrf.js +102 -102
- package/src/runtime/status-aggregator.js +330 -330
- package/src/runtime/task-contract.js +140 -140
- package/src/runtime/task-packet.js +107 -107
- package/src/runtime/task-router.js +140 -140
- package/src/runtime/telegram-inbound.js +1565 -1565
- package/src/runtime/token-counter.js +134 -134
- package/src/runtime/token-estimator.js +59 -59
- package/src/runtime/tool-loop.js +200 -200
- package/src/runtime/transport-server.js +311 -311
- package/src/runtime/tui-server.js +411 -411
- package/src/runtime/ulid.js +44 -44
- package/src/security/ssrf-check.js +197 -197
- package/src/setup.js +369 -369
- package/src/shadow/bridge.js +303 -303
- package/src/skills/loader.js +84 -84
- package/src/tools/catalog.json +49 -49
- package/src/tools/cli-delegate.js +44 -44
- package/src/tools/mcp-client.js +106 -106
- package/src/tools/micro/cancel-task.js +6 -6
- package/src/tools/micro/complete-task.js +6 -6
- package/src/tools/micro/fail-task.js +6 -6
- package/src/tools/micro/http-fetch.js +74 -74
- package/src/tools/micro/index.js +36 -36
- package/src/tools/micro/lcm-recall.js +60 -60
- package/src/tools/micro/list-dir.js +17 -17
- package/src/tools/micro/list-skills.js +46 -46
- package/src/tools/micro/load-skill.js +38 -38
- package/src/tools/micro/memory-search.js +45 -45
- package/src/tools/micro/read-file.js +11 -11
- package/src/tools/micro/session-search.js +54 -54
- package/src/tools/micro/shell-exec.js +43 -43
- package/src/tools/micro/trigger-job.js +79 -79
- package/src/tools/micro/web-search.js +58 -58
- package/src/tools/micro/workspace-paths.js +39 -39
- package/src/tools/micro/write-file.js +14 -14
- package/src/tools/micro/write-memory.js +41 -41
- package/src/tools/registry.js +348 -348
- package/src/tools/tool-result-contract.js +36 -36
- package/src/tui/chat.js +835 -835
- package/src/tui/renderer.js +175 -175
- package/src/tui/socket-client.js +217 -217
- package/src/utils/canonical-json.js +29 -29
- package/src/utils/compaction.js +30 -30
- package/src/utils/env-loader.js +5 -5
- package/src/utils/errors.js +80 -80
- package/src/utils/fs.js +101 -101
- package/src/utils/ids.js +5 -5
- package/src/utils/model-context-limits.js +30 -30
- package/src/utils/token-budget.js +74 -74
- package/src/utils/usage-cost.js +25 -25
- package/src/utils/usage-metrics.js +14 -14
package/install.sh
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
set -euo pipefail
|
|
3
|
-
|
|
4
|
-
echo ""
|
|
5
|
-
echo " 🌿 Nemoris Installer"
|
|
6
|
-
echo ""
|
|
7
|
-
|
|
8
|
-
OS="unknown"
|
|
9
|
-
case "$(uname -s)" in
|
|
10
|
-
Darwin*) OS="macOS" ;;
|
|
11
|
-
Linux*) OS="Linux" ;;
|
|
12
|
-
MINGW*|MSYS*|CYGWIN*) OS="Windows (WSL recommended)" ;;
|
|
13
|
-
esac
|
|
14
|
-
echo " Platform: $OS ($(uname -m))"
|
|
15
|
-
|
|
16
|
-
check_node() {
|
|
17
|
-
if ! command -v node &>/dev/null; then
|
|
18
|
-
return 1
|
|
19
|
-
fi
|
|
20
|
-
local major
|
|
21
|
-
major=$(node -e "console.log(process.version.split('.')[0].replace('v',''))")
|
|
22
|
-
[ "$major" -ge 22 ]
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
if check_node; then
|
|
26
|
-
echo " Node.js: $(node --version) ✓"
|
|
27
|
-
else
|
|
28
|
-
echo " Node.js >= 22.5 required."
|
|
29
|
-
if command -v nvm &>/dev/null; then
|
|
30
|
-
echo " nvm detected — installing Node.js 22..."
|
|
31
|
-
nvm install 22
|
|
32
|
-
nvm use 22
|
|
33
|
-
else
|
|
34
|
-
echo " Install Node.js 22+: https://nodejs.org"
|
|
35
|
-
echo " Or install nvm: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash"
|
|
36
|
-
exit 1
|
|
37
|
-
fi
|
|
38
|
-
fi
|
|
39
|
-
|
|
40
|
-
if ! command -v git &>/dev/null; then
|
|
41
|
-
echo " ⚠ Git required: https://git-scm.com"
|
|
42
|
-
exit 1
|
|
43
|
-
fi
|
|
44
|
-
|
|
45
|
-
echo ""
|
|
46
|
-
echo " Installing nemoris..."
|
|
47
|
-
npm install -g nemoris
|
|
48
|
-
|
|
49
|
-
echo ""
|
|
50
|
-
nemoris setup
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
echo ""
|
|
5
|
+
echo " 🌿 Nemoris Installer"
|
|
6
|
+
echo ""
|
|
7
|
+
|
|
8
|
+
OS="unknown"
|
|
9
|
+
case "$(uname -s)" in
|
|
10
|
+
Darwin*) OS="macOS" ;;
|
|
11
|
+
Linux*) OS="Linux" ;;
|
|
12
|
+
MINGW*|MSYS*|CYGWIN*) OS="Windows (WSL recommended)" ;;
|
|
13
|
+
esac
|
|
14
|
+
echo " Platform: $OS ($(uname -m))"
|
|
15
|
+
|
|
16
|
+
check_node() {
|
|
17
|
+
if ! command -v node &>/dev/null; then
|
|
18
|
+
return 1
|
|
19
|
+
fi
|
|
20
|
+
local major
|
|
21
|
+
major=$(node -e "console.log(process.version.split('.')[0].replace('v',''))")
|
|
22
|
+
[ "$major" -ge 22 ]
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if check_node; then
|
|
26
|
+
echo " Node.js: $(node --version) ✓"
|
|
27
|
+
else
|
|
28
|
+
echo " Node.js >= 22.5 required."
|
|
29
|
+
if command -v nvm &>/dev/null; then
|
|
30
|
+
echo " nvm detected — installing Node.js 22..."
|
|
31
|
+
nvm install 22
|
|
32
|
+
nvm use 22
|
|
33
|
+
else
|
|
34
|
+
echo " Install Node.js 22+: https://nodejs.org"
|
|
35
|
+
echo " Or install nvm: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash"
|
|
36
|
+
exit 1
|
|
37
|
+
fi
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
if ! command -v git &>/dev/null; then
|
|
41
|
+
echo " ⚠ Git required: https://git-scm.com"
|
|
42
|
+
exit 1
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
echo ""
|
|
46
|
+
echo " Installing nemoris..."
|
|
47
|
+
npm install -g nemoris
|
|
48
|
+
|
|
49
|
+
echo ""
|
|
50
|
+
nemoris setup
|
package/package.json
CHANGED
|
@@ -1,90 +1,91 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "nemoris",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"type": "module",
|
|
5
|
-
"description": "Personal AI agent runtime — persistent memory, delivery guarantees, task contracts, self-healing. Local-first, no cloud.",
|
|
6
|
-
"license": "MIT",
|
|
7
|
-
"author": "Lee <amzer24@gmail.com> (https://github.com/amzer24)",
|
|
8
|
-
"repository": {
|
|
9
|
-
"type": "git",
|
|
10
|
-
"url": "git+https://github.com/amzer24/nemoris.git"
|
|
11
|
-
},
|
|
12
|
-
"homepage": "https://nemoris.dev",
|
|
13
|
-
"bugs": {
|
|
14
|
-
"url": "https://github.com/amzer24/nemoris/issues"
|
|
15
|
-
},
|
|
16
|
-
"keywords": [
|
|
17
|
-
"ai",
|
|
18
|
-
"agent",
|
|
19
|
-
"runtime",
|
|
20
|
-
"personal-agent",
|
|
21
|
-
"llm",
|
|
22
|
-
"anthropic",
|
|
23
|
-
"claude",
|
|
24
|
-
"ollama",
|
|
25
|
-
"telegram",
|
|
26
|
-
"memory",
|
|
27
|
-
"self-healing",
|
|
28
|
-
"daemon",
|
|
29
|
-
"local-first",
|
|
30
|
-
"mcp"
|
|
31
|
-
],
|
|
32
|
-
"bin": {
|
|
33
|
-
"nemoris": "bin/nemoris"
|
|
34
|
-
},
|
|
35
|
-
"files": [
|
|
36
|
-
".env.example",
|
|
37
|
-
"bin/",
|
|
38
|
-
"src/",
|
|
39
|
-
"config/",
|
|
40
|
-
"vendor/",
|
|
41
|
-
"install.sh",
|
|
42
|
-
"LICENSE",
|
|
43
|
-
"README.md",
|
|
44
|
-
"SECURITY.md"
|
|
45
|
-
],
|
|
46
|
-
"scripts": {
|
|
47
|
-
"init": "node src/cli.js init",
|
|
48
|
-
"demo": "node src/cli.js demo",
|
|
49
|
-
"run:heartbeat": "node src/cli.js execute-job heartbeat-check dry-run",
|
|
50
|
-
"run:heartbeat:provider": "NEMORIS_ALLOW_PROVIDER_MODE=1 node src/cli.js execute-job heartbeat-check provider",
|
|
51
|
-
"compare:heartbeat": "node src/cli.js shadow-compare heartbeat-check",
|
|
52
|
-
"scheduler:due": "node src/cli.js due-jobs",
|
|
53
|
-
"scheduler:tick": "node src/cli.js tick-scheduler dry-run",
|
|
54
|
-
"runs:review": "node src/cli.js review-runs 10",
|
|
55
|
-
"runs:evaluate": "node src/cli.js evaluate-runs 20",
|
|
56
|
-
"embeddings:index": "NEMORIS_ALLOW_EMBEDDINGS=1 node src/cli.js index-embeddings heartbeat",
|
|
57
|
-
"embeddings:query": "NEMORIS_ALLOW_EMBEDDINGS=1 node src/cli.js query-embeddings heartbeat \"heartbeat memory\"",
|
|
58
|
-
"memory:backends": "node src/cli.js memory-backends heartbeat",
|
|
59
|
-
"memory:qmd": "node src/cli.js query-qmd heartbeat \"memory heartbeat\"",
|
|
60
|
-
"memory:plan": "node src/cli.js plan-job heartbeat-check",
|
|
61
|
-
"inspect": "node src/cli.js inspect-memory main \"memory heartbeat\"",
|
|
62
|
-
"manifest:summary": "node src/cli.js manifest-summary",
|
|
63
|
-
"plan:heartbeat": "node src/cli.js plan-job heartbeat-check",
|
|
64
|
-
"cron:live": "node src/cli.js live-cron-summary",
|
|
65
|
-
"compare:jobs": "node src/cli.js compare-jobs",
|
|
66
|
-
"shadow:summary": "node src/cli.js shadow-summary main",
|
|
67
|
-
"shadow:import": "node src/cli.js shadow-import main",
|
|
68
|
-
"provider:policy": "node src/cli.js provider-mode-policy",
|
|
69
|
-
"setup": "node src/cli.js setup",
|
|
70
|
-
"battle": "NEMORIS_ALLOW_PROVIDER_MODE=1 node src/cli.js battle",
|
|
71
|
-
"lint": "eslint .",
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"test
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
"@
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
"eslint": "^10.0.
|
|
89
|
-
|
|
90
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "nemoris",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Personal AI agent runtime — persistent memory, delivery guarantees, task contracts, self-healing. Local-first, no cloud.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Lee <amzer24@gmail.com> (https://github.com/amzer24)",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/amzer24/nemoris.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://nemoris.dev",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/amzer24/nemoris/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"ai",
|
|
18
|
+
"agent",
|
|
19
|
+
"runtime",
|
|
20
|
+
"personal-agent",
|
|
21
|
+
"llm",
|
|
22
|
+
"anthropic",
|
|
23
|
+
"claude",
|
|
24
|
+
"ollama",
|
|
25
|
+
"telegram",
|
|
26
|
+
"memory",
|
|
27
|
+
"self-healing",
|
|
28
|
+
"daemon",
|
|
29
|
+
"local-first",
|
|
30
|
+
"mcp"
|
|
31
|
+
],
|
|
32
|
+
"bin": {
|
|
33
|
+
"nemoris": "bin/nemoris"
|
|
34
|
+
},
|
|
35
|
+
"files": [
|
|
36
|
+
".env.example",
|
|
37
|
+
"bin/",
|
|
38
|
+
"src/",
|
|
39
|
+
"config/",
|
|
40
|
+
"vendor/",
|
|
41
|
+
"install.sh",
|
|
42
|
+
"LICENSE",
|
|
43
|
+
"README.md",
|
|
44
|
+
"SECURITY.md"
|
|
45
|
+
],
|
|
46
|
+
"scripts": {
|
|
47
|
+
"init": "node src/cli.js init",
|
|
48
|
+
"demo": "node src/cli.js demo",
|
|
49
|
+
"run:heartbeat": "node src/cli.js execute-job heartbeat-check dry-run",
|
|
50
|
+
"run:heartbeat:provider": "NEMORIS_ALLOW_PROVIDER_MODE=1 node src/cli.js execute-job heartbeat-check provider",
|
|
51
|
+
"compare:heartbeat": "node src/cli.js shadow-compare heartbeat-check",
|
|
52
|
+
"scheduler:due": "node src/cli.js due-jobs",
|
|
53
|
+
"scheduler:tick": "node src/cli.js tick-scheduler dry-run",
|
|
54
|
+
"runs:review": "node src/cli.js review-runs 10",
|
|
55
|
+
"runs:evaluate": "node src/cli.js evaluate-runs 20",
|
|
56
|
+
"embeddings:index": "NEMORIS_ALLOW_EMBEDDINGS=1 node src/cli.js index-embeddings heartbeat",
|
|
57
|
+
"embeddings:query": "NEMORIS_ALLOW_EMBEDDINGS=1 node src/cli.js query-embeddings heartbeat \"heartbeat memory\"",
|
|
58
|
+
"memory:backends": "node src/cli.js memory-backends heartbeat",
|
|
59
|
+
"memory:qmd": "node src/cli.js query-qmd heartbeat \"memory heartbeat\"",
|
|
60
|
+
"memory:plan": "node src/cli.js plan-job heartbeat-check",
|
|
61
|
+
"inspect": "node src/cli.js inspect-memory main \"memory heartbeat\"",
|
|
62
|
+
"manifest:summary": "node src/cli.js manifest-summary",
|
|
63
|
+
"plan:heartbeat": "node src/cli.js plan-job heartbeat-check",
|
|
64
|
+
"cron:live": "node src/cli.js live-cron-summary",
|
|
65
|
+
"compare:jobs": "node src/cli.js compare-jobs",
|
|
66
|
+
"shadow:summary": "node src/cli.js shadow-summary main",
|
|
67
|
+
"shadow:import": "node src/cli.js shadow-import main",
|
|
68
|
+
"provider:policy": "node src/cli.js provider-mode-policy",
|
|
69
|
+
"setup": "node src/cli.js setup",
|
|
70
|
+
"battle": "NEMORIS_ALLOW_PROVIDER_MODE=1 node src/cli.js battle",
|
|
71
|
+
"lint": "eslint .",
|
|
72
|
+
"prepack": "node scripts/check-publish-dry-run.js",
|
|
73
|
+
"publish:check": "node scripts/check-publish-dry-run.js",
|
|
74
|
+
"status": "node src/cli.js runtime-status",
|
|
75
|
+
"test": "node --test",
|
|
76
|
+
"test:e2e": "node tests/e2e/run-report.js"
|
|
77
|
+
},
|
|
78
|
+
"engines": {
|
|
79
|
+
"node": ">=22.5.0"
|
|
80
|
+
},
|
|
81
|
+
"dependencies": {
|
|
82
|
+
"@clack/prompts": "^1.1.0",
|
|
83
|
+
"@mariozechner/pi-ai": "^0.60.0",
|
|
84
|
+
"js-tiktoken": "^1.0.21",
|
|
85
|
+
"smol-toml": "file:vendor/smol-toml-1.5.2.tgz"
|
|
86
|
+
},
|
|
87
|
+
"devDependencies": {
|
|
88
|
+
"@eslint/js": "^10.0.1",
|
|
89
|
+
"eslint": "^10.0.3"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -1,169 +1,169 @@
|
|
|
1
|
-
import fs from "node:fs";
|
|
2
|
-
import os from "node:os";
|
|
3
|
-
import path from "node:path";
|
|
4
|
-
|
|
5
|
-
export const AUTH_PROFILE_FILE_NAME = "auth-profiles.json";
|
|
6
|
-
export const AUTH_PROFILE_DIR_NAME = "state";
|
|
7
|
-
|
|
8
|
-
function dedupe(items = []) {
|
|
9
|
-
return [...new Set(items.filter(Boolean))];
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function resolveInstallDir({ env = process.env, cwd: _cwd = process.cwd() } = {}) {
|
|
13
|
-
if (env.NEMORIS_INSTALL_DIR) {
|
|
14
|
-
return env.NEMORIS_INSTALL_DIR;
|
|
15
|
-
}
|
|
16
|
-
if (_cwd) {
|
|
17
|
-
const hasPackageJson = fs.existsSync(path.join(_cwd, "package.json"));
|
|
18
|
-
const hasCliEntry = fs.existsSync(path.join(_cwd, "src", "cli.js"));
|
|
19
|
-
if (hasPackageJson && hasCliEntry) {
|
|
20
|
-
return _cwd;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return path.join(os.homedir(), ".nemoris");
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function resolveAuthProfilesPath({ env = process.env, cwd = process.cwd() } = {}) {
|
|
27
|
-
if (env.NEMORIS_AUTH_PROFILES_PATH) {
|
|
28
|
-
return path.resolve(env.NEMORIS_AUTH_PROFILES_PATH);
|
|
29
|
-
}
|
|
30
|
-
const installDir = resolveInstallDir({ env, cwd });
|
|
31
|
-
return path.join(installDir, AUTH_PROFILE_DIR_NAME, AUTH_PROFILE_FILE_NAME);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function defaultAuthProfilesPath() {
|
|
35
|
-
return resolveAuthProfilesPath();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export function defaultAuthProfileSearchPaths({ env = process.env, cwd = process.cwd() } = {}) {
|
|
39
|
-
const installDir = resolveInstallDir({ env, cwd });
|
|
40
|
-
return dedupe([
|
|
41
|
-
resolveAuthProfilesPath({ env, cwd }),
|
|
42
|
-
path.join(cwd, AUTH_PROFILE_DIR_NAME, AUTH_PROFILE_FILE_NAME),
|
|
43
|
-
path.join(installDir, AUTH_PROFILE_DIR_NAME, AUTH_PROFILE_FILE_NAME),
|
|
44
|
-
path.join(os.homedir(), ".openclaw", "agents", "main", "agent", AUTH_PROFILE_FILE_NAME)
|
|
45
|
-
]);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
function readJsonFile(filePath) {
|
|
49
|
-
try {
|
|
50
|
-
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
51
|
-
} catch {
|
|
52
|
-
return {};
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
function secureChmod(filePath) {
|
|
57
|
-
if (process.platform === "win32") return;
|
|
58
|
-
try {
|
|
59
|
-
fs.chmodSync(filePath, 0o600);
|
|
60
|
-
} catch {
|
|
61
|
-
// Best effort only.
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function writeFileAtomic(filePath, content) {
|
|
66
|
-
const dirPath = path.dirname(filePath);
|
|
67
|
-
fs.mkdirSync(dirPath, { recursive: true, mode: 0o700 });
|
|
68
|
-
const tempPath = path.join(dirPath, `.${path.basename(filePath)}.${process.pid}.${Date.now()}.tmp`);
|
|
69
|
-
fs.writeFileSync(tempPath, content, { encoding: "utf8", mode: 0o600 });
|
|
70
|
-
secureChmod(tempPath);
|
|
71
|
-
fs.renameSync(tempPath, filePath);
|
|
72
|
-
secureChmod(filePath);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function resolveEnvRef(ref) {
|
|
76
|
-
if (!ref || typeof ref !== "object") return null;
|
|
77
|
-
if (ref.source !== "env" || !ref.id) return null;
|
|
78
|
-
return process.env[ref.id] || null;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
export function readAuthProfiles(filePath = defaultAuthProfilesPath()) {
|
|
82
|
-
const parsed = readJsonFile(filePath);
|
|
83
|
-
const profiles = parsed?.profiles && typeof parsed.profiles === "object" ? parsed.profiles : {};
|
|
84
|
-
return {
|
|
85
|
-
version: Number(parsed?.version || 1),
|
|
86
|
-
profiles
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export function writeAuthProfiles(document, filePath = defaultAuthProfilesPath()) {
|
|
91
|
-
writeFileAtomic(filePath, `${JSON.stringify(document, null, 2)}\n`);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export function updateAuthProfile(profileId, updater, filePath = defaultAuthProfilesPath()) {
|
|
95
|
-
const document = readAuthProfiles(filePath);
|
|
96
|
-
const nextProfile = updater(document.profiles?.[profileId] || null);
|
|
97
|
-
if (nextProfile === null) {
|
|
98
|
-
delete document.profiles[profileId];
|
|
99
|
-
} else {
|
|
100
|
-
document.profiles[profileId] = nextProfile;
|
|
101
|
-
}
|
|
102
|
-
writeAuthProfiles(document, filePath);
|
|
103
|
-
return document;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export function upsertAuthProfile(profileId, profile, filePath = defaultAuthProfilesPath()) {
|
|
107
|
-
return updateAuthProfile(profileId, () => profile, filePath);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export function getAuthProfile(profileId, filePath = defaultAuthProfilesPath()) {
|
|
111
|
-
return readAuthProfiles(filePath).profiles?.[profileId] || null;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export function resolveProfileSecret(profile) {
|
|
115
|
-
if (!profile || typeof profile !== "object") return null;
|
|
116
|
-
if (profile.type === "oauth") return profile.access || resolveEnvRef(profile.accessRef) || null;
|
|
117
|
-
if (profile.type === "api_key") return profile.key || resolveEnvRef(profile.keyRef) || null;
|
|
118
|
-
if (profile.type === "token") return profile.token || resolveEnvRef(profile.tokenRef) || null;
|
|
119
|
-
return (
|
|
120
|
-
profile.access ||
|
|
121
|
-
profile.key ||
|
|
122
|
-
profile.token ||
|
|
123
|
-
resolveEnvRef(profile.accessRef) ||
|
|
124
|
-
resolveEnvRef(profile.keyRef) ||
|
|
125
|
-
resolveEnvRef(profile.tokenRef) ||
|
|
126
|
-
null
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export function describeAuthRef(authRef, { filePath = defaultAuthProfilesPath() } = {}) {
|
|
131
|
-
if (!authRef) {
|
|
132
|
-
return {
|
|
133
|
-
authRef: null,
|
|
134
|
-
present: false,
|
|
135
|
-
source: null,
|
|
136
|
-
detail: "missing_auth_ref"
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (String(authRef).startsWith("env:")) {
|
|
141
|
-
const envName = String(authRef).slice(4);
|
|
142
|
-
return {
|
|
143
|
-
authRef,
|
|
144
|
-
present: Boolean(process.env[envName]),
|
|
145
|
-
source: "env",
|
|
146
|
-
envName,
|
|
147
|
-
detail: process.env[envName] ? "ok" : `missing ${envName}`
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
if (String(authRef).startsWith("profile:")) {
|
|
152
|
-
const profileId = String(authRef).slice("profile:".length);
|
|
153
|
-
const profile = getAuthProfile(profileId, filePath);
|
|
154
|
-
return {
|
|
155
|
-
authRef,
|
|
156
|
-
present: Boolean(resolveProfileSecret(profile)),
|
|
157
|
-
source: "profile",
|
|
158
|
-
profileId,
|
|
159
|
-
detail: profile ? "ok" : `missing profile ${profileId}`
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return {
|
|
164
|
-
authRef,
|
|
165
|
-
present: false,
|
|
166
|
-
source: "unknown",
|
|
167
|
-
detail: "unsupported_auth_ref"
|
|
168
|
-
};
|
|
169
|
-
}
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
export const AUTH_PROFILE_FILE_NAME = "auth-profiles.json";
|
|
6
|
+
export const AUTH_PROFILE_DIR_NAME = "state";
|
|
7
|
+
|
|
8
|
+
function dedupe(items = []) {
|
|
9
|
+
return [...new Set(items.filter(Boolean))];
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function resolveInstallDir({ env = process.env, cwd: _cwd = process.cwd() } = {}) {
|
|
13
|
+
if (env.NEMORIS_INSTALL_DIR) {
|
|
14
|
+
return env.NEMORIS_INSTALL_DIR;
|
|
15
|
+
}
|
|
16
|
+
if (_cwd) {
|
|
17
|
+
const hasPackageJson = fs.existsSync(path.join(_cwd, "package.json"));
|
|
18
|
+
const hasCliEntry = fs.existsSync(path.join(_cwd, "src", "cli.js"));
|
|
19
|
+
if (hasPackageJson && hasCliEntry) {
|
|
20
|
+
return _cwd;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return path.join(os.homedir(), ".nemoris");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function resolveAuthProfilesPath({ env = process.env, cwd = process.cwd() } = {}) {
|
|
27
|
+
if (env.NEMORIS_AUTH_PROFILES_PATH) {
|
|
28
|
+
return path.resolve(env.NEMORIS_AUTH_PROFILES_PATH);
|
|
29
|
+
}
|
|
30
|
+
const installDir = resolveInstallDir({ env, cwd });
|
|
31
|
+
return path.join(installDir, AUTH_PROFILE_DIR_NAME, AUTH_PROFILE_FILE_NAME);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function defaultAuthProfilesPath() {
|
|
35
|
+
return resolveAuthProfilesPath();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export function defaultAuthProfileSearchPaths({ env = process.env, cwd = process.cwd() } = {}) {
|
|
39
|
+
const installDir = resolveInstallDir({ env, cwd });
|
|
40
|
+
return dedupe([
|
|
41
|
+
resolveAuthProfilesPath({ env, cwd }),
|
|
42
|
+
path.join(cwd, AUTH_PROFILE_DIR_NAME, AUTH_PROFILE_FILE_NAME),
|
|
43
|
+
path.join(installDir, AUTH_PROFILE_DIR_NAME, AUTH_PROFILE_FILE_NAME),
|
|
44
|
+
path.join(os.homedir(), ".openclaw", "agents", "main", "agent", AUTH_PROFILE_FILE_NAME)
|
|
45
|
+
]);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function readJsonFile(filePath) {
|
|
49
|
+
try {
|
|
50
|
+
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
51
|
+
} catch {
|
|
52
|
+
return {};
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function secureChmod(filePath) {
|
|
57
|
+
if (process.platform === "win32") return;
|
|
58
|
+
try {
|
|
59
|
+
fs.chmodSync(filePath, 0o600);
|
|
60
|
+
} catch {
|
|
61
|
+
// Best effort only.
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function writeFileAtomic(filePath, content) {
|
|
66
|
+
const dirPath = path.dirname(filePath);
|
|
67
|
+
fs.mkdirSync(dirPath, { recursive: true, mode: 0o700 });
|
|
68
|
+
const tempPath = path.join(dirPath, `.${path.basename(filePath)}.${process.pid}.${Date.now()}.tmp`);
|
|
69
|
+
fs.writeFileSync(tempPath, content, { encoding: "utf8", mode: 0o600 });
|
|
70
|
+
secureChmod(tempPath);
|
|
71
|
+
fs.renameSync(tempPath, filePath);
|
|
72
|
+
secureChmod(filePath);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function resolveEnvRef(ref) {
|
|
76
|
+
if (!ref || typeof ref !== "object") return null;
|
|
77
|
+
if (ref.source !== "env" || !ref.id) return null;
|
|
78
|
+
return process.env[ref.id] || null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function readAuthProfiles(filePath = defaultAuthProfilesPath()) {
|
|
82
|
+
const parsed = readJsonFile(filePath);
|
|
83
|
+
const profiles = parsed?.profiles && typeof parsed.profiles === "object" ? parsed.profiles : {};
|
|
84
|
+
return {
|
|
85
|
+
version: Number(parsed?.version || 1),
|
|
86
|
+
profiles
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function writeAuthProfiles(document, filePath = defaultAuthProfilesPath()) {
|
|
91
|
+
writeFileAtomic(filePath, `${JSON.stringify(document, null, 2)}\n`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export function updateAuthProfile(profileId, updater, filePath = defaultAuthProfilesPath()) {
|
|
95
|
+
const document = readAuthProfiles(filePath);
|
|
96
|
+
const nextProfile = updater(document.profiles?.[profileId] || null);
|
|
97
|
+
if (nextProfile === null) {
|
|
98
|
+
delete document.profiles[profileId];
|
|
99
|
+
} else {
|
|
100
|
+
document.profiles[profileId] = nextProfile;
|
|
101
|
+
}
|
|
102
|
+
writeAuthProfiles(document, filePath);
|
|
103
|
+
return document;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function upsertAuthProfile(profileId, profile, filePath = defaultAuthProfilesPath()) {
|
|
107
|
+
return updateAuthProfile(profileId, () => profile, filePath);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function getAuthProfile(profileId, filePath = defaultAuthProfilesPath()) {
|
|
111
|
+
return readAuthProfiles(filePath).profiles?.[profileId] || null;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function resolveProfileSecret(profile) {
|
|
115
|
+
if (!profile || typeof profile !== "object") return null;
|
|
116
|
+
if (profile.type === "oauth") return profile.access || resolveEnvRef(profile.accessRef) || null;
|
|
117
|
+
if (profile.type === "api_key") return profile.key || resolveEnvRef(profile.keyRef) || null;
|
|
118
|
+
if (profile.type === "token") return profile.token || resolveEnvRef(profile.tokenRef) || null;
|
|
119
|
+
return (
|
|
120
|
+
profile.access ||
|
|
121
|
+
profile.key ||
|
|
122
|
+
profile.token ||
|
|
123
|
+
resolveEnvRef(profile.accessRef) ||
|
|
124
|
+
resolveEnvRef(profile.keyRef) ||
|
|
125
|
+
resolveEnvRef(profile.tokenRef) ||
|
|
126
|
+
null
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function describeAuthRef(authRef, { filePath = defaultAuthProfilesPath() } = {}) {
|
|
131
|
+
if (!authRef) {
|
|
132
|
+
return {
|
|
133
|
+
authRef: null,
|
|
134
|
+
present: false,
|
|
135
|
+
source: null,
|
|
136
|
+
detail: "missing_auth_ref"
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (String(authRef).startsWith("env:")) {
|
|
141
|
+
const envName = String(authRef).slice(4);
|
|
142
|
+
return {
|
|
143
|
+
authRef,
|
|
144
|
+
present: Boolean(process.env[envName]),
|
|
145
|
+
source: "env",
|
|
146
|
+
envName,
|
|
147
|
+
detail: process.env[envName] ? "ok" : `missing ${envName}`
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (String(authRef).startsWith("profile:")) {
|
|
152
|
+
const profileId = String(authRef).slice("profile:".length);
|
|
153
|
+
const profile = getAuthProfile(profileId, filePath);
|
|
154
|
+
return {
|
|
155
|
+
authRef,
|
|
156
|
+
present: Boolean(resolveProfileSecret(profile)),
|
|
157
|
+
source: "profile",
|
|
158
|
+
profileId,
|
|
159
|
+
detail: profile ? "ok" : `missing profile ${profileId}`
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return {
|
|
164
|
+
authRef,
|
|
165
|
+
present: false,
|
|
166
|
+
source: "unknown",
|
|
167
|
+
detail: "unsupported_auth_ref"
|
|
168
|
+
};
|
|
169
|
+
}
|