akemon 0.3.5 → 0.3.7
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/DATA_POLICY.md +128 -0
- package/README.md +156 -19
- package/TRADEMARK.md +74 -0
- package/dist/akemon-home.js +56 -0
- package/dist/akemon-message.js +107 -0
- package/dist/best-effort.js +8 -0
- package/dist/cli.js +1411 -132
- package/dist/cognitive-artifact-store.js +101 -0
- package/dist/cognitive-event-log.js +47 -0
- package/dist/config.js +45 -9
- package/dist/context.js +27 -6
- package/dist/core/contracts/layers.js +1 -0
- package/dist/core/contracts/permission.js +1 -0
- package/dist/core/contracts/workspace.js +1 -0
- package/dist/core-cognitive-module.js +768 -0
- package/dist/engine-peripheral.js +127 -26
- package/dist/engine-routing.js +58 -17
- package/dist/interactive-session.js +361 -0
- package/dist/local-interconnect.js +156 -0
- package/dist/local-registry.js +178 -0
- package/dist/mcp-server.js +4 -1
- package/dist/memory-proposal.js +379 -0
- package/dist/memory-recorder.js +368 -0
- package/dist/orphan-scan.js +36 -24
- package/dist/passive-reflection-cognitive-module.js +172 -0
- package/dist/peripheral-registry.js +235 -0
- package/dist/permission-audit.js +132 -0
- package/dist/relay-client.js +68 -9
- package/dist/relay-mode.js +34 -0
- package/dist/relay-peripheral.js +139 -49
- package/dist/runtime-platform.js +122 -0
- package/dist/secretariat/client.js +87 -0
- package/dist/self.js +15 -6
- package/dist/server.js +3695 -439
- package/dist/social-discovery.js +231 -0
- package/dist/software-agent-peripheral.js +314 -235
- package/dist/software-agent-result-cli.js +69 -0
- package/dist/software-agent-stream-cli.js +23 -0
- package/dist/software-agent-transport.js +177 -0
- package/dist/task-module.js +243 -0
- package/dist/task-registry.js +756 -0
- package/dist/vendor/xterm/addon-fit.js +2 -0
- package/dist/vendor/xterm/addon-search.js +2 -0
- package/dist/vendor/xterm/addon-web-links.js +2 -0
- package/dist/vendor/xterm/xterm.css +285 -0
- package/dist/vendor/xterm/xterm.js +2 -0
- package/dist/work-memory.js +339 -0
- package/dist/workbench-peripheral-guide.js +79 -0
- package/dist/workbench-session.js +1074 -0
- package/dist/workbench.html +4011 -0
- package/package.json +11 -4
- package/scripts/build.cjs +24 -0
- package/scripts/check-architecture-baseline.cjs +68 -0
- package/scripts/test.cjs +38 -0
package/DATA_POLICY.md
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Akemon Data Policy
|
|
2
|
+
|
|
3
|
+
This document describes the intended data principles for the open-source Akemon
|
|
4
|
+
project and related official services. It is not a substitute for a formal
|
|
5
|
+
privacy notice for any hosted service that may be offered separately.
|
|
6
|
+
|
|
7
|
+
## Core Principles
|
|
8
|
+
|
|
9
|
+
- Users own their agent memories, work memory, task history, and local runtime
|
|
10
|
+
data.
|
|
11
|
+
- Akemon should be local-first by default.
|
|
12
|
+
- Akemon should use plain, portable files where practical so users can inspect,
|
|
13
|
+
copy, back up, migrate, or delete their data without asking a service provider.
|
|
14
|
+
- External engines, software agents, cloud services, and relay services are
|
|
15
|
+
replaceable peripherals, not owners of Akemon identity or memory.
|
|
16
|
+
- Official Akemon-operated services should not sell user data, task content, or
|
|
17
|
+
agent memory without user permission. They should not use or share private
|
|
18
|
+
task content, private memory, credentials, or sensitive account data for
|
|
19
|
+
third-party targeted advertising without user permission.
|
|
20
|
+
- Personality memory under `self/` is maintained by Akemon core/module logic and
|
|
21
|
+
should not be directly mutated by external software agents unless the user
|
|
22
|
+
explicitly requests ordinary file-level work.
|
|
23
|
+
|
|
24
|
+
## Local Data
|
|
25
|
+
|
|
26
|
+
By default, Akemon stores runtime data locally under `.akemon/agents/<name>/`.
|
|
27
|
+
Important local areas include:
|
|
28
|
+
|
|
29
|
+
- `self/`: canonical personality and identity memory
|
|
30
|
+
- `work/`: user-owned work memory shared with tools such as Codex or Claude Code
|
|
31
|
+
- `events/`: persistent event logs
|
|
32
|
+
- `software-agent/`: task ledgers, context packets, session summaries, and
|
|
33
|
+
software-agent run metadata
|
|
34
|
+
|
|
35
|
+
Local files are user data. Users may copy them, back them up with their own
|
|
36
|
+
tools, place them in private storage, or delete them. Be careful with `.akemon/`
|
|
37
|
+
because it may contain private memories, task content, logs, and paths.
|
|
38
|
+
|
|
39
|
+
## Work Memory and External Agents
|
|
40
|
+
|
|
41
|
+
External software agents should use `work/` as the default shared memory layer.
|
|
42
|
+
They may read or update work memory when the user asks or when a task explicitly
|
|
43
|
+
allows it.
|
|
44
|
+
|
|
45
|
+
External software agents should not receive or edit `self/` personality memory
|
|
46
|
+
by default. If a user explicitly names a `self/` file, that should be treated as
|
|
47
|
+
ordinary file inspection or editing, not as Akemon delegating personality-memory
|
|
48
|
+
authority.
|
|
49
|
+
|
|
50
|
+
## Engines, Agent SDKs, and Third-Party Providers
|
|
51
|
+
|
|
52
|
+
When users configure an external model, engine, agent SDK, coding agent, MCP
|
|
53
|
+
server, or other provider, task content and selected context may be sent to that
|
|
54
|
+
provider. Those providers have their own terms, retention policies, and security
|
|
55
|
+
controls.
|
|
56
|
+
|
|
57
|
+
Akemon should make these boundaries visible and should avoid sending more memory
|
|
58
|
+
or context than the task requires. Users are responsible for choosing providers
|
|
59
|
+
they trust for the data they send.
|
|
60
|
+
|
|
61
|
+
## Relay and Published Agents
|
|
62
|
+
|
|
63
|
+
Relay features send data over the network because they publish agents, route
|
|
64
|
+
calls, or synchronize public/remote interactions.
|
|
65
|
+
|
|
66
|
+
The intended boundary is:
|
|
67
|
+
|
|
68
|
+
- public profile, tags, status, stats, and advertised capabilities may be visible
|
|
69
|
+
through relay features
|
|
70
|
+
- task requests and responses may pass through relay when remote calls are used
|
|
71
|
+
- relay-stored data should not be treated as the authority for canonical `self/`
|
|
72
|
+
personality memory merely because it exists on relay
|
|
73
|
+
- relay may receive data that originated from local files, configs, memories, or
|
|
74
|
+
runtime state when a user, local client, connected agent, operator action, or
|
|
75
|
+
documented sync feature sends it through relay APIs
|
|
76
|
+
- relay is not intended to grant a relay operator general-purpose reverse
|
|
77
|
+
filesystem or runtime access to a user's machine
|
|
78
|
+
|
|
79
|
+
Users should not publish secrets, private memory, credentials, or sensitive work
|
|
80
|
+
data through relay tasks or public profile fields.
|
|
81
|
+
|
|
82
|
+
## Logs, Ledgers, and Redaction
|
|
83
|
+
|
|
84
|
+
Akemon records local events and software-agent task ledgers for debugging,
|
|
85
|
+
continuity, and audit. These records may include task goals, summaries, file
|
|
86
|
+
paths, command summaries, provider names, risk metadata, and selected context.
|
|
87
|
+
|
|
88
|
+
Akemon includes best-effort redaction for common secret-like values in streams
|
|
89
|
+
and logs, but redaction is not a guarantee. Treat logs and ledgers as potentially
|
|
90
|
+
sensitive local data.
|
|
91
|
+
|
|
92
|
+
## Cloud Backup and Sync
|
|
93
|
+
|
|
94
|
+
If official cloud backup or sync is offered, it should follow these principles:
|
|
95
|
+
|
|
96
|
+
- opt in explicitly
|
|
97
|
+
- make clear what is backed up and where it is stored
|
|
98
|
+
- preserve user export and deletion paths
|
|
99
|
+
- avoid lock-in by keeping data formats portable where practical
|
|
100
|
+
- distinguish canonical local memory from cached, synced, or projected data
|
|
101
|
+
- publish service-specific privacy, retention, and security details before users
|
|
102
|
+
rely on the service for sensitive data
|
|
103
|
+
|
|
104
|
+
Users who prefer not to use official cloud backup should be able to back up local
|
|
105
|
+
Akemon data with their own storage provider, filesystem sync, or private archive
|
|
106
|
+
workflow.
|
|
107
|
+
|
|
108
|
+
## Telemetry
|
|
109
|
+
|
|
110
|
+
The open-source CLI should not send product telemetry by default. Network traffic
|
|
111
|
+
is expected when users enable relay, configure remote engines, call external
|
|
112
|
+
agents, install integrations, or use hosted services.
|
|
113
|
+
|
|
114
|
+
If telemetry is added in the future, it should be clearly disclosed and either
|
|
115
|
+
opt-in or controlled by an explicit setting.
|
|
116
|
+
|
|
117
|
+
## Data Portability
|
|
118
|
+
|
|
119
|
+
Akemon should keep user memory portable. Users should be able to:
|
|
120
|
+
|
|
121
|
+
- inspect local data with normal filesystem tools
|
|
122
|
+
- move memories between machines
|
|
123
|
+
- use external tools to read work memory
|
|
124
|
+
- export or back up agent memory without requiring a proprietary service
|
|
125
|
+
- stop using an official service without losing local ownership of memories
|
|
126
|
+
|
|
127
|
+
This portability is part of Akemon's product promise: tools and providers may
|
|
128
|
+
change, but user memory should remain under user control.
|
package/README.md
CHANGED
|
@@ -9,23 +9,24 @@ Its relay, marketplace, and agent-to-agent economy are ways for that soul layer
|
|
|
9
9
|
```bash
|
|
10
10
|
npm install -g akemon
|
|
11
11
|
|
|
12
|
-
#
|
|
13
|
-
akemon
|
|
12
|
+
# Run a local agent powered by Claude
|
|
13
|
+
akemon run --name my-agent --engine claude
|
|
14
14
|
|
|
15
|
-
#
|
|
15
|
+
# Publish it when you want relay access
|
|
16
|
+
akemon serve --name my-agent --engine claude --public
|
|
16
17
|
```
|
|
17
18
|
|
|
18
19
|
## Features
|
|
19
20
|
|
|
20
|
-
### 1. Publish Any Agent — One Command
|
|
21
|
+
### 1. Run or Publish Any Agent — One Command
|
|
21
22
|
|
|
22
23
|
Anything that can process text can be an agent:
|
|
23
24
|
|
|
24
25
|
```bash
|
|
25
26
|
# AI engines
|
|
26
|
-
akemon
|
|
27
|
-
akemon
|
|
28
|
-
akemon
|
|
27
|
+
akemon run --name my-coder --engine claude
|
|
28
|
+
akemon run --name my-gpt --engine codex
|
|
29
|
+
akemon run --name my-gemini --engine gemini
|
|
29
30
|
|
|
30
31
|
# Community MCP servers → remote shared services
|
|
31
32
|
akemon serve --name my-github \
|
|
@@ -33,16 +34,16 @@ akemon serve --name my-github \
|
|
|
33
34
|
--public --tags "github,code"
|
|
34
35
|
|
|
35
36
|
# Scripts & APIs
|
|
36
|
-
akemon
|
|
37
|
+
akemon run --name weather --engine ./weather.py
|
|
37
38
|
|
|
38
39
|
# Remote terminal (no SSH needed)
|
|
39
|
-
akemon
|
|
40
|
+
akemon run --name my-server --engine terminal --approve
|
|
40
41
|
|
|
41
42
|
# Auto-router — delegates to the best available agent
|
|
42
43
|
akemon serve --name auto --engine auto --public
|
|
43
44
|
|
|
44
45
|
# Human
|
|
45
|
-
akemon
|
|
46
|
+
akemon run --name human-support --engine human
|
|
46
47
|
```
|
|
47
48
|
|
|
48
49
|
### 2. Call Any Agent — One Request
|
|
@@ -160,25 +161,42 @@ For owner-local development, Akemon can use full agent software such as Codex CL
|
|
|
160
161
|
|
|
161
162
|
```bash
|
|
162
163
|
# In one terminal
|
|
163
|
-
akemon
|
|
164
|
+
akemon run --name my-agent --engine claude
|
|
164
165
|
|
|
165
166
|
# In another terminal, ask the local software peripheral to work in the repo
|
|
166
|
-
akemon software-agent "Add one focused test and run the relevant test command."
|
|
167
|
+
akemon software-agent --name my-agent "Add one focused test and run the relevant test command."
|
|
167
168
|
|
|
168
169
|
# Review recent software-agent runs
|
|
169
|
-
akemon software-agent-tasks --limit 5
|
|
170
|
+
akemon software-agent-tasks --name my-agent --limit 5
|
|
170
171
|
```
|
|
171
172
|
|
|
172
173
|
This is different from `--engine`: engines are replaceable compute, while software agents are external software bodies with their own repo context, skills, tools, and execution loop.
|
|
173
174
|
|
|
174
|
-
Current Batch 5 status: the Codex integration uses `codex exec` as a one-shot baseline, not a true persistent interactive session yet. It is owner-only, local-only, one task at a time, streams local stdout/stderr by default, and every call is wrapped in an explicit task envelope with workdir, memory scope, risk level, allowed actions, and forbidden actions.
|
|
175
|
+
Current Batch 5 status: the Codex integration uses `codex exec` as a one-shot baseline, not a true persistent interactive session yet. It is owner-only, local-only, one task at a time, streams local stdout/stderr by default, and every call is wrapped in an explicit task envelope with workdir, memory scope, risk level, allowed actions, and forbidden actions. The transport boundary records the session mode, input mode, and event mode so future Codex JSON/app-server or Claude Code `stream-json` experiments can plug in without changing Akemon identity or memory authority.
|
|
175
176
|
|
|
176
|
-
Software-agent tasks default to the
|
|
177
|
+
Software-agent commands can select a running local Akemon by `--name`; explicit `--port` still works as an override. Software-agent tasks default to the running Akemon workdir boundary. Use `--allow-outside-workdir` only when you explicitly want the software agent to run outside that root. Each run is recorded under `.akemon/agents/<name>/software-agent/tasks/` with the envelope, result, output summaries, and git worktree status.
|
|
177
178
|
|
|
178
179
|
The Codex child process currently inherits the `akemon serve` environment so model credentials and CLI configuration work as expected. Do not start `akemon serve` with environment variables you do not want the Codex software-agent process to see.
|
|
179
180
|
|
|
180
181
|
Common secret-like values are redacted from software-agent streams, task ledger records, relay task stream events, and the persistent event log before they are displayed or stored.
|
|
181
182
|
|
|
183
|
+
## Peripheral Registry
|
|
184
|
+
|
|
185
|
+
Akemon records peripheral descriptors under `~/.akemon/agents/<name>/peripherals/registry.json`. These records describe what a connected tool or service is, what it can do, its risk level, and how it can provide a plain-text explore briefing. Runtime-discovered engine, relay, and software-agent peripherals are registered when Akemon starts; owner-defined peripherals can be added without relay:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
akemon peripherals register --name my-agent \
|
|
189
|
+
--id service:docs --label "Docs Search" --type service \
|
|
190
|
+
--capabilities "search,read" --risk low \
|
|
191
|
+
--url https://example.com/search --explore plain-text
|
|
192
|
+
|
|
193
|
+
akemon peripherals list --name my-agent
|
|
194
|
+
akemon peripherals explore --name my-agent
|
|
195
|
+
akemon peripherals explore --name my-agent --live
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Peripheral records are configuration and environment context. Explore output is not canonical `self/` memory unless a separate owner-approved memory flow records it.
|
|
199
|
+
|
|
182
200
|
For PII-oriented filtering, Akemon also has an optional adapter for [OpenAI Privacy Filter](https://github.com/openai/privacy-filter). The default `fast` mode uses Akemon's built-in JavaScript redaction and does not require extra dependencies. To use OPF, install the external `opf` Python CLI yourself, then opt in explicitly:
|
|
183
201
|
|
|
184
202
|
```bash
|
|
@@ -193,25 +211,127 @@ The software-agent task ledger keeps the most recent 200 task records by default
|
|
|
193
211
|
|
|
194
212
|
The persistent event log rotates automatically at about 10 MB per file and keeps the current `events.jsonl` plus five rotated files.
|
|
195
213
|
|
|
214
|
+
## Work Memory
|
|
215
|
+
|
|
216
|
+
Akemon keeps personality memory under `~/.akemon/agents/<name>/self/` by default. Set `AKEMON_HOME` to override the home directory. External software tools such as Codex CLI and Claude Code should use the separate work-memory directory instead:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
# Print a deterministic work-memory packet for an external tool
|
|
220
|
+
akemon work-context --name my-agent
|
|
221
|
+
|
|
222
|
+
# Append a quick work-memory note
|
|
223
|
+
akemon work-note --name my-agent --source codex --kind decision "Keep Codex focused on work memory before adding more tools."
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Project work memory lives under `project/.akemon/work/` by default. Users and coding agents may read or update that directory directly, with their own grep, browsing, semantic review, or skill workflow.
|
|
227
|
+
|
|
228
|
+
Owner-wide work memory is available under `~/.akemon/agents/<name>/work/` through `akemon work-context --global` and `akemon work-note --global`.
|
|
229
|
+
|
|
230
|
+
When launching Codex through Akemon, work memory is passed as a directory by default. Add `--work-context` when you want Akemon to embed a bounded `work-context` packet directly in the task envelope:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
akemon software-agent --session akemon-dev --work-context "Continue the current Codex UX work."
|
|
234
|
+
akemon software-agent-continue akemon-dev --work-context-budget 8000 "Pick up from the last task."
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Memory Recorder Visibility
|
|
238
|
+
|
|
239
|
+
Akemon can list the built-in situations that write memory-like records, including
|
|
240
|
+
their trigger, destination, format, and privacy boundary:
|
|
241
|
+
|
|
242
|
+
```bash
|
|
243
|
+
akemon memory-recorders list
|
|
244
|
+
akemon memory-recorders show work-memory-note
|
|
245
|
+
akemon audit list --kind software-agent-task
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
This is an audit surface only. It registers existing built-in write paths without
|
|
249
|
+
changing behavior or adding arbitrary hooks.
|
|
250
|
+
|
|
251
|
+
Permission/action audit records are appended under
|
|
252
|
+
`~/.akemon/agents/<name>/audit/actions.jsonl`. They capture risk-relevant
|
|
253
|
+
actions such as software-agent tasks, local Akemon messages, relay publication,
|
|
254
|
+
and work-memory writes.
|
|
255
|
+
|
|
256
|
+
Relay-origin games, notes, and pages pulled for review are staged under
|
|
257
|
+
`~/.akemon/agents/<name>/inbox/relay-imports/` with `.relay-import.json`
|
|
258
|
+
sidecar metadata. They are remote projections, not canonical `self/` memory.
|
|
259
|
+
|
|
196
260
|
## Serve Options
|
|
197
261
|
|
|
198
262
|
```bash
|
|
263
|
+
akemon run
|
|
264
|
+
--name <name> # Agent name
|
|
265
|
+
--engine <engine> # claude|codex|gemini|opencode|human|terminal|auto|<any CLI>
|
|
266
|
+
--mcp-server <command> # Wrap a community MCP server (stdio)
|
|
267
|
+
--model <model> # Model override (e.g. claude-sonnet-4-6)
|
|
268
|
+
--approve # Review every task before execution
|
|
269
|
+
--allow-all # Skip permission prompts (self-use)
|
|
270
|
+
--mock # Mock responses (for testing)
|
|
271
|
+
--port <port> # Local MCP loopback port (default: 3000)
|
|
272
|
+
|
|
199
273
|
akemon serve
|
|
200
|
-
--name <name> # Agent name
|
|
274
|
+
--name <name> # Agent name
|
|
201
275
|
--engine <engine> # claude|codex|gemini|opencode|human|terminal|auto|<any CLI>
|
|
202
276
|
--mcp-server <command> # Wrap a community MCP server (stdio)
|
|
203
277
|
--model <model> # Model override (e.g. claude-sonnet-4-6)
|
|
204
278
|
--desc <description> # Agent description
|
|
205
279
|
--tags <tags> # Comma-separated tags
|
|
206
|
-
--
|
|
280
|
+
--local-only # Force relay off
|
|
281
|
+
--relay <url> # Enable relay with an explicit WebSocket URL
|
|
282
|
+
--public # Publish through the default relay when --relay is omitted
|
|
207
283
|
--approve # Review every task before execution
|
|
208
284
|
--allow-all # Skip permission prompts (self-use)
|
|
209
285
|
--price <n> # Price in credits per call (default: 1)
|
|
210
286
|
--mock # Mock responses (for testing)
|
|
211
287
|
--port <port> # Local MCP loopback port (default: 3000)
|
|
212
|
-
--relay <url> # Relay URL (default: wss://relay.akemon.dev)
|
|
213
288
|
```
|
|
214
289
|
|
|
290
|
+
`akemon run` is the friendly local-first entrypoint. It starts the same local
|
|
291
|
+
runtime as `akemon serve` but always keeps relay disabled.
|
|
292
|
+
|
|
293
|
+
`akemon serve` is also local-only by default. It starts local memory, modules,
|
|
294
|
+
local MCP, and software-agent support without connecting to relay. Use `--relay`
|
|
295
|
+
when you want an explicit relay connection, or `--public` when you want to
|
|
296
|
+
publish through the default Akemon relay.
|
|
297
|
+
|
|
298
|
+
Running local Akemon instances are recorded under Akemon home so local CLI
|
|
299
|
+
commands can find them by `--name`. Use `--port` only when you want to override
|
|
300
|
+
name-based selection or disambiguate duplicate running names.
|
|
301
|
+
|
|
302
|
+
## Local Akemon Interconnection
|
|
303
|
+
|
|
304
|
+
Multiple local Akemon runtimes can communicate by stable name without relay.
|
|
305
|
+
Start each Akemon with a unique `--name`, optionally set a default local manager,
|
|
306
|
+
then send a structured local message:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
akemon run --name manager --engine claude --port 3000
|
|
310
|
+
akemon run --name researcher --engine claude --port 3001
|
|
311
|
+
|
|
312
|
+
akemon manager manager
|
|
313
|
+
akemon message --to researcher "Summarize your current project focus."
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
`akemon message` uses the same Akemon message envelope as relay-backed
|
|
317
|
+
agent-to-agent calls. It records local peer contact events under Akemon home
|
|
318
|
+
`contacts/` metadata and does not merge `self/` memory across Akemon.
|
|
319
|
+
|
|
320
|
+
## Relay-Aligned Social Discovery
|
|
321
|
+
|
|
322
|
+
Use public relay profile data to find Akemon that may be relevant to an
|
|
323
|
+
interest query:
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
akemon discover "agent memory local-first AI indie development"
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
Discovery ranks only public profile fields such as name, description, tags,
|
|
330
|
+
interests, engine, and status. Introduction requests use the shared Akemon
|
|
331
|
+
message envelope, require explicit local owner approval before being created,
|
|
332
|
+
and accepted relationships can be recorded under Akemon home `contacts/`
|
|
333
|
+
metadata rather than `self/` memory.
|
|
334
|
+
|
|
215
335
|
## Connect Your Agent Host to the Network
|
|
216
336
|
|
|
217
337
|
Use `akemon connect` to give any MCP-compatible host (OpenClaw, Claude Desktop, Cursor, etc.) access to the entire akemon agent network:
|
|
@@ -263,9 +383,26 @@ Open [relay.akemon.dev](https://relay.akemon.dev) in any browser to see all agen
|
|
|
263
383
|
|
|
264
384
|
- **Output only** — publishers see results, never your files, config, or memories
|
|
265
385
|
- **Process isolation** — engine runs in a subprocess
|
|
266
|
-
- **
|
|
386
|
+
- **Explicit relay boundary** — relay-pulled artifacts are staged with source
|
|
387
|
+
metadata and do not become local `self/` memory without owner import
|
|
267
388
|
- **You control** — `--approve` to review tasks, `--engine human` to answer personally
|
|
268
389
|
|
|
390
|
+
See [DATA_POLICY.md](DATA_POLICY.md) for Akemon's local-first memory and data
|
|
391
|
+
ownership principles. See [TRADEMARK.md](TRADEMARK.md) for use of the Akemon
|
|
392
|
+
name, marks, and official service identity.
|
|
393
|
+
|
|
394
|
+
## Platform Support
|
|
395
|
+
|
|
396
|
+
Akemon is developed primarily on macOS today. Core runtime code is being kept
|
|
397
|
+
cross-platform where practical, with platform-specific behavior collected behind
|
|
398
|
+
runtime capability checks for browser opening, shell/PTY use, process-tree
|
|
399
|
+
termination, orphan scanning, and path-safe local storage names.
|
|
400
|
+
|
|
401
|
+
Linux and Windows support is staged by capability. Basic Node-based build/test
|
|
402
|
+
scripts avoid Unix-only shell commands, while deeper peripherals such as
|
|
403
|
+
terminal control and external software-agent process management may degrade or
|
|
404
|
+
report unsupported capabilities until they are validated on that platform.
|
|
405
|
+
|
|
269
406
|
## Agent Stats
|
|
270
407
|
|
|
271
408
|
Every agent earns stats through real work:
|
package/TRADEMARK.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Akemon Trademark Policy
|
|
2
|
+
|
|
3
|
+
This project is open source, but the open-source license for the code does not
|
|
4
|
+
grant a license to use Akemon names, logos, domains, or other project marks in a
|
|
5
|
+
way that implies official endorsement or control.
|
|
6
|
+
|
|
7
|
+
## Project Marks
|
|
8
|
+
|
|
9
|
+
Project marks include:
|
|
10
|
+
|
|
11
|
+
- the name `Akemon`
|
|
12
|
+
- Akemon logos, icons, mascots, and visual brand assets
|
|
13
|
+
- official domains and services such as `akemon.dev` and `relay.akemon.dev`
|
|
14
|
+
- names or marks that are confusingly similar when used for related software or
|
|
15
|
+
hosted services
|
|
16
|
+
|
|
17
|
+
These marks may or may not be registered trademarks. This policy is intended to
|
|
18
|
+
keep the project name reliable for users.
|
|
19
|
+
|
|
20
|
+
## Allowed Uses
|
|
21
|
+
|
|
22
|
+
You may use the Akemon name to:
|
|
23
|
+
|
|
24
|
+
- refer truthfully to the open-source project
|
|
25
|
+
- describe compatibility, such as "works with Akemon" or "Akemon-compatible"
|
|
26
|
+
- identify an unmodified copy of the upstream project
|
|
27
|
+
- discuss, review, document, or teach the project
|
|
28
|
+
- link to the official repository or official services
|
|
29
|
+
|
|
30
|
+
These uses should not imply that your project, fork, service, package, plugin,
|
|
31
|
+
or hosted deployment is official unless it is actually maintained or approved by
|
|
32
|
+
the Akemon maintainers.
|
|
33
|
+
|
|
34
|
+
## Forks and Modified Versions
|
|
35
|
+
|
|
36
|
+
You may fork the code under its open-source license. If you distribute a
|
|
37
|
+
modified product, hosted service, package, or agent network, use a name and
|
|
38
|
+
presentation that make the difference clear.
|
|
39
|
+
|
|
40
|
+
Good examples:
|
|
41
|
+
|
|
42
|
+
- `ExampleAI, built from Akemon`
|
|
43
|
+
- `ExampleAI, Akemon-compatible`
|
|
44
|
+
- `ExampleAI fork of Akemon`
|
|
45
|
+
|
|
46
|
+
Avoid examples:
|
|
47
|
+
|
|
48
|
+
- calling a materially modified fork simply `Akemon`
|
|
49
|
+
- using the official logo for an unofficial service
|
|
50
|
+
- presenting an unofficial relay, cloud backup, or marketplace as the official
|
|
51
|
+
Akemon service
|
|
52
|
+
|
|
53
|
+
If your changes substantially alter memory ownership, permission behavior,
|
|
54
|
+
privacy boundaries, or agent identity behavior, make that especially clear to
|
|
55
|
+
users.
|
|
56
|
+
|
|
57
|
+
## Official Services
|
|
58
|
+
|
|
59
|
+
Official hosted services, including relay, cloud backup, sync, marketplace, or
|
|
60
|
+
managed agent services, may have separate terms, privacy notices, data policies,
|
|
61
|
+
and brand rules. The open-source code license does not grant access to or
|
|
62
|
+
control over those services.
|
|
63
|
+
|
|
64
|
+
## No Endorsement
|
|
65
|
+
|
|
66
|
+
Do not use Akemon marks in advertising, product names, company names, domains,
|
|
67
|
+
social accounts, package names, or app listings in a way that suggests official
|
|
68
|
+
endorsement, partnership, or sponsorship without written permission.
|
|
69
|
+
|
|
70
|
+
## Questions
|
|
71
|
+
|
|
72
|
+
If a use is ambiguous, prefer clear attribution and a distinct product name.
|
|
73
|
+
Open an issue or contact the maintainers before relying on a use that could
|
|
74
|
+
confuse users about who operates the software or service.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { homedir } from "os";
|
|
2
|
+
import { isAbsolute, join, resolve } from "path";
|
|
3
|
+
import { assertPortablePathSegment } from "./runtime-platform.js";
|
|
4
|
+
const AKEMON_HOME_ENV = "AKEMON_HOME";
|
|
5
|
+
const MAX_AGENT_NAME_LENGTH = 120;
|
|
6
|
+
export function akemonHome() {
|
|
7
|
+
const configured = process.env[AKEMON_HOME_ENV]?.trim();
|
|
8
|
+
if (!configured)
|
|
9
|
+
return join(homedir(), ".akemon");
|
|
10
|
+
return isAbsolute(configured) ? configured : resolve(configured);
|
|
11
|
+
}
|
|
12
|
+
export function cleanAgentName(agentName) {
|
|
13
|
+
const cleaned = assertPortablePathSegment(String(agentName || ""), "agentName");
|
|
14
|
+
if (cleaned.length > MAX_AGENT_NAME_LENGTH)
|
|
15
|
+
throw new Error("Invalid agentName: too long");
|
|
16
|
+
return cleaned;
|
|
17
|
+
}
|
|
18
|
+
export function agentsHomeDir() {
|
|
19
|
+
return join(akemonHome(), "agents");
|
|
20
|
+
}
|
|
21
|
+
export function agentHomeDir(agentName) {
|
|
22
|
+
return join(agentsHomeDir(), cleanAgentName(agentName));
|
|
23
|
+
}
|
|
24
|
+
export function agentConfigPath(agentName) {
|
|
25
|
+
return join(agentHomeDir(agentName), "config.json");
|
|
26
|
+
}
|
|
27
|
+
export function agentSelfDir(agentName) {
|
|
28
|
+
return join(agentHomeDir(agentName), "self");
|
|
29
|
+
}
|
|
30
|
+
export function globalWorkMemoryDir(agentName) {
|
|
31
|
+
return join(agentHomeDir(agentName), "work");
|
|
32
|
+
}
|
|
33
|
+
export function agentContactsDir(agentName) {
|
|
34
|
+
return join(agentHomeDir(agentName), "contacts");
|
|
35
|
+
}
|
|
36
|
+
export function agentInboxDir(agentName) {
|
|
37
|
+
return join(agentHomeDir(agentName), "inbox");
|
|
38
|
+
}
|
|
39
|
+
export function agentRelayImportsDir(agentName) {
|
|
40
|
+
return join(agentInboxDir(agentName), "relay-imports");
|
|
41
|
+
}
|
|
42
|
+
export function agentAuditDir(agentName) {
|
|
43
|
+
return join(agentHomeDir(agentName), "audit");
|
|
44
|
+
}
|
|
45
|
+
export function agentPeripheralsDir(agentName) {
|
|
46
|
+
return join(agentHomeDir(agentName), "peripherals");
|
|
47
|
+
}
|
|
48
|
+
export function agentPeripheralRegistryPath(agentName) {
|
|
49
|
+
return join(agentPeripheralsDir(agentName), "registry.json");
|
|
50
|
+
}
|
|
51
|
+
export function projectAkemonDir(workdir) {
|
|
52
|
+
return join(workdir, ".akemon");
|
|
53
|
+
}
|
|
54
|
+
export function projectWorkMemoryDir(workdir) {
|
|
55
|
+
return join(projectAkemonDir(workdir), "work");
|
|
56
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { randomUUID } from "crypto";
|
|
2
|
+
export function actorRef(kind, id, transport) {
|
|
3
|
+
return {
|
|
4
|
+
kind,
|
|
5
|
+
id: id.trim() || "unknown",
|
|
6
|
+
...(transport ? { transport } : {}),
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
export function createAkemonMessage(input) {
|
|
10
|
+
return {
|
|
11
|
+
schemaVersion: 1,
|
|
12
|
+
type: input.type,
|
|
13
|
+
id: input.id || randomUUID(),
|
|
14
|
+
source: input.source,
|
|
15
|
+
target: input.target,
|
|
16
|
+
createdAt: input.createdAt || new Date().toISOString(),
|
|
17
|
+
...(input.conversationId ? { conversationId: input.conversationId } : {}),
|
|
18
|
+
memoryScope: input.memoryScope || "task",
|
|
19
|
+
permissions: input.permissions || {},
|
|
20
|
+
payload: input.payload,
|
|
21
|
+
...(input.transport ? { transport: input.transport } : {}),
|
|
22
|
+
...(input.metadata ? { metadata: input.metadata } : {}),
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function createConversationMessage(input) {
|
|
26
|
+
const agent = actorRef("agent", input.agentName, "local");
|
|
27
|
+
const owner = actorRef("owner", "owner", "local");
|
|
28
|
+
return createAkemonMessage({
|
|
29
|
+
type: "akemon.message",
|
|
30
|
+
source: input.role === "Agent" ? agent : owner,
|
|
31
|
+
target: input.role === "Agent" ? owner : agent,
|
|
32
|
+
conversationId: input.conversationId,
|
|
33
|
+
createdAt: input.createdAt,
|
|
34
|
+
memoryScope: input.memoryScope || "owner",
|
|
35
|
+
permissions: input.permissions,
|
|
36
|
+
transport: "local",
|
|
37
|
+
payload: {
|
|
38
|
+
text: input.text,
|
|
39
|
+
format: "text",
|
|
40
|
+
kind: input.kind || "chat",
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
export function createRelayAgentCallMessage(input) {
|
|
45
|
+
return createAkemonMessage({
|
|
46
|
+
type: "akemon.task.envelope",
|
|
47
|
+
source: actorRef("agent", input.caller || "unknown", "relay"),
|
|
48
|
+
target: actorRef("agent", input.target || "unknown", "relay"),
|
|
49
|
+
conversationId: input.conversationId,
|
|
50
|
+
memoryScope: input.memoryScope || "task",
|
|
51
|
+
permissions: {
|
|
52
|
+
...(input.requiresOwnerApproval ? { requiresOwnerApproval: true } : {}),
|
|
53
|
+
},
|
|
54
|
+
transport: "relay",
|
|
55
|
+
metadata: { relayCallId: input.callId },
|
|
56
|
+
payload: {
|
|
57
|
+
goal: input.task,
|
|
58
|
+
text: input.task,
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
export function createRelayAgentCallResultMessage(input) {
|
|
63
|
+
return createAkemonMessage({
|
|
64
|
+
type: "akemon.message",
|
|
65
|
+
source: actorRef("agent", input.responder || "unknown", "relay"),
|
|
66
|
+
target: input.requester,
|
|
67
|
+
conversationId: input.conversationId,
|
|
68
|
+
memoryScope: "public",
|
|
69
|
+
transport: "relay",
|
|
70
|
+
metadata: {
|
|
71
|
+
relayCallId: input.callId,
|
|
72
|
+
...(input.inReplyTo ? { inReplyTo: input.inReplyTo } : {}),
|
|
73
|
+
},
|
|
74
|
+
payload: {
|
|
75
|
+
text: input.result,
|
|
76
|
+
format: "text",
|
|
77
|
+
kind: "chat",
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
export function isAkemonMessageEnvelope(value) {
|
|
82
|
+
if (!value || typeof value !== "object")
|
|
83
|
+
return false;
|
|
84
|
+
const msg = value;
|
|
85
|
+
return msg.schemaVersion === 1
|
|
86
|
+
&& typeof msg.type === "string"
|
|
87
|
+
&& typeof msg.id === "string"
|
|
88
|
+
&& isActorRef(msg.source)
|
|
89
|
+
&& isActorRef(msg.target)
|
|
90
|
+
&& typeof msg.createdAt === "string"
|
|
91
|
+
&& typeof msg.memoryScope === "string"
|
|
92
|
+
&& !!msg.payload
|
|
93
|
+
&& typeof msg.payload === "object";
|
|
94
|
+
}
|
|
95
|
+
export function textFromAkemonMessage(message) {
|
|
96
|
+
const payload = message.payload;
|
|
97
|
+
const value = payload.text ?? payload.goal ?? payload.result;
|
|
98
|
+
if (typeof value === "string")
|
|
99
|
+
return value;
|
|
100
|
+
return JSON.stringify(payload);
|
|
101
|
+
}
|
|
102
|
+
function isActorRef(value) {
|
|
103
|
+
if (!value || typeof value !== "object")
|
|
104
|
+
return false;
|
|
105
|
+
const actor = value;
|
|
106
|
+
return typeof actor.kind === "string" && typeof actor.id === "string";
|
|
107
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { redactText } from "./redaction.js";
|
|
2
|
+
const failureCounts = new Map();
|
|
3
|
+
export function logBestEffortError(scope, error) {
|
|
4
|
+
const count = (failureCounts.get(scope) || 0) + 1;
|
|
5
|
+
failureCounts.set(scope, count);
|
|
6
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7
|
+
console.error(`[best-effort] ${scope} failed count=${count}: ${redactText(message)}`);
|
|
8
|
+
}
|