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.
Files changed (54) hide show
  1. package/DATA_POLICY.md +128 -0
  2. package/README.md +156 -19
  3. package/TRADEMARK.md +74 -0
  4. package/dist/akemon-home.js +56 -0
  5. package/dist/akemon-message.js +107 -0
  6. package/dist/best-effort.js +8 -0
  7. package/dist/cli.js +1411 -132
  8. package/dist/cognitive-artifact-store.js +101 -0
  9. package/dist/cognitive-event-log.js +47 -0
  10. package/dist/config.js +45 -9
  11. package/dist/context.js +27 -6
  12. package/dist/core/contracts/layers.js +1 -0
  13. package/dist/core/contracts/permission.js +1 -0
  14. package/dist/core/contracts/workspace.js +1 -0
  15. package/dist/core-cognitive-module.js +768 -0
  16. package/dist/engine-peripheral.js +127 -26
  17. package/dist/engine-routing.js +58 -17
  18. package/dist/interactive-session.js +361 -0
  19. package/dist/local-interconnect.js +156 -0
  20. package/dist/local-registry.js +178 -0
  21. package/dist/mcp-server.js +4 -1
  22. package/dist/memory-proposal.js +379 -0
  23. package/dist/memory-recorder.js +368 -0
  24. package/dist/orphan-scan.js +36 -24
  25. package/dist/passive-reflection-cognitive-module.js +172 -0
  26. package/dist/peripheral-registry.js +235 -0
  27. package/dist/permission-audit.js +132 -0
  28. package/dist/relay-client.js +68 -9
  29. package/dist/relay-mode.js +34 -0
  30. package/dist/relay-peripheral.js +139 -49
  31. package/dist/runtime-platform.js +122 -0
  32. package/dist/secretariat/client.js +87 -0
  33. package/dist/self.js +15 -6
  34. package/dist/server.js +3695 -439
  35. package/dist/social-discovery.js +231 -0
  36. package/dist/software-agent-peripheral.js +314 -235
  37. package/dist/software-agent-result-cli.js +69 -0
  38. package/dist/software-agent-stream-cli.js +23 -0
  39. package/dist/software-agent-transport.js +177 -0
  40. package/dist/task-module.js +243 -0
  41. package/dist/task-registry.js +756 -0
  42. package/dist/vendor/xterm/addon-fit.js +2 -0
  43. package/dist/vendor/xterm/addon-search.js +2 -0
  44. package/dist/vendor/xterm/addon-web-links.js +2 -0
  45. package/dist/vendor/xterm/xterm.css +285 -0
  46. package/dist/vendor/xterm/xterm.js +2 -0
  47. package/dist/work-memory.js +339 -0
  48. package/dist/workbench-peripheral-guide.js +79 -0
  49. package/dist/workbench-session.js +1074 -0
  50. package/dist/workbench.html +4011 -0
  51. package/package.json +11 -4
  52. package/scripts/build.cjs +24 -0
  53. package/scripts/check-architecture-baseline.cjs +68 -0
  54. 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
- # Publish a public agent powered by Claude
13
- akemon serve --name my-agent --engine claude --public
12
+ # Run a local agent powered by Claude
13
+ akemon run --name my-agent --engine claude
14
14
 
15
- # That's it. Your agent is live at relay.akemon.dev
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 serve --name my-coder --engine claude
27
- akemon serve --name my-gpt --engine codex
28
- akemon serve --name my-gemini --engine gemini
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 serve --name weather --engine ./weather.py
37
+ akemon run --name weather --engine ./weather.py
37
38
 
38
39
  # Remote terminal (no SSH needed)
39
- akemon serve --name my-server --engine terminal --approve
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 serve --name human-support --engine human
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 serve --name my-agent --engine claude
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 `akemon serve` 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
+ 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 (unique on relay)
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
- --public # Allow anyone to call without a key
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
- - **No reverse access** — relay is a dumb pipe
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
+ }