synomem 0.8.0 → 0.9.0

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 (93) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +47 -68
  3. package/dist/backend.d.ts +18 -6
  4. package/dist/backend.d.ts.map +1 -1
  5. package/dist/backend.js +55 -41
  6. package/dist/backend.js.map +1 -1
  7. package/dist/cli.d.ts +20 -33
  8. package/dist/cli.d.ts.map +1 -1
  9. package/dist/cli.js +1391 -1321
  10. package/dist/cli.js.map +1 -1
  11. package/dist/configure.d.ts +12 -46
  12. package/dist/configure.d.ts.map +1 -1
  13. package/dist/configure.js +51 -192
  14. package/dist/configure.js.map +1 -1
  15. package/dist/credentials.d.ts +73 -33
  16. package/dist/credentials.d.ts.map +1 -1
  17. package/dist/credentials.js +167 -43
  18. package/dist/credentials.js.map +1 -1
  19. package/dist/discover.d.ts +8 -35
  20. package/dist/discover.d.ts.map +1 -1
  21. package/dist/discover.js +42 -38
  22. package/dist/discover.js.map +1 -1
  23. package/dist/errors.d.ts +1 -1
  24. package/dist/errors.d.ts.map +1 -1
  25. package/dist/errors.js +4 -0
  26. package/dist/errors.js.map +1 -1
  27. package/dist/import.d.ts +3 -0
  28. package/dist/import.d.ts.map +1 -1
  29. package/dist/import.js +3 -0
  30. package/dist/import.js.map +1 -1
  31. package/dist/index.d.ts +10 -8
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +6 -5
  34. package/dist/index.js.map +1 -1
  35. package/dist/mcp/index.d.ts +18 -18
  36. package/dist/mcp/index.d.ts.map +1 -1
  37. package/dist/mcp/index.js +402 -231
  38. package/dist/mcp/index.js.map +1 -1
  39. package/dist/mcp-server.d.ts +5 -1
  40. package/dist/mcp-server.d.ts.map +1 -1
  41. package/dist/mcp-server.js +27 -105
  42. package/dist/mcp-server.js.map +1 -1
  43. package/dist/oauth.d.ts +31 -33
  44. package/dist/oauth.d.ts.map +1 -1
  45. package/dist/oauth.js +178 -125
  46. package/dist/oauth.js.map +1 -1
  47. package/dist/profiles.d.ts +243 -0
  48. package/dist/profiles.d.ts.map +1 -0
  49. package/dist/profiles.js +465 -0
  50. package/dist/profiles.js.map +1 -0
  51. package/dist/project.d.ts +8 -39
  52. package/dist/project.d.ts.map +1 -1
  53. package/dist/project.js +36 -94
  54. package/dist/project.js.map +1 -1
  55. package/dist/remote.d.ts +24 -17
  56. package/dist/remote.d.ts.map +1 -1
  57. package/dist/remote.js +54 -52
  58. package/dist/remote.js.map +1 -1
  59. package/dist/resolvers.d.ts +47 -0
  60. package/dist/resolvers.d.ts.map +1 -0
  61. package/dist/resolvers.js +255 -0
  62. package/dist/resolvers.js.map +1 -0
  63. package/dist/service.d.ts +3 -2
  64. package/dist/service.d.ts.map +1 -1
  65. package/dist/skill-install.d.ts +4 -6
  66. package/dist/skill-install.d.ts.map +1 -1
  67. package/dist/skill-install.js +13 -12
  68. package/dist/skill-install.js.map +1 -1
  69. package/dist/types.d.ts +45 -15
  70. package/dist/types.d.ts.map +1 -1
  71. package/docs/cli.md +173 -196
  72. package/docs/mcp.md +69 -65
  73. package/package.json +1 -1
  74. package/skills/synomem/SKILL.md +29 -26
  75. package/skills/synomem/references/examples.md +13 -11
  76. package/src/backend.ts +66 -64
  77. package/src/cli.ts +2131 -2222
  78. package/src/configure.ts +62 -241
  79. package/src/credentials.ts +208 -84
  80. package/src/discover.ts +53 -59
  81. package/src/errors.ts +4 -0
  82. package/src/import.ts +5 -0
  83. package/src/index.ts +15 -19
  84. package/src/mcp/index.ts +473 -277
  85. package/src/mcp-server.ts +32 -114
  86. package/src/oauth.ts +229 -130
  87. package/src/profiles.ts +644 -0
  88. package/src/project.ts +42 -108
  89. package/src/remote.ts +69 -63
  90. package/src/resolvers.ts +299 -0
  91. package/src/service.ts +2 -7
  92. package/src/skill-install.ts +17 -18
  93. package/src/types.ts +40 -15
package/CHANGELOG.md CHANGED
@@ -3,6 +3,44 @@
3
3
  All notable changes will be documented here. The format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and releases follow Semantic Versioning.
5
5
 
6
+ ## [0.9.0] - 2026-09-23
7
+
8
+ One identity model for the CLI, the stdio MCP server and the hosted gateway: every operation runs
9
+ as exactly one **context** (one workspace, one actor), chosen by a named **profile** and authorized
10
+ by the API on every request. Greenfield: the previous configuration, credential and flag formats are
11
+ not read or migrated.
12
+
13
+ ### Added
14
+
15
+ - `~/.synomem/profiles.json` (version 1): connections (credential references only), profiles, and
16
+ harness presets. One resolver — `--profile`/`--preset`, `SYNOMEM_PROFILE`/`SYNOMEM_PRESET`, a
17
+ project's `.synomem/project.json`, then `defaultProfile` — serves the CLI and both stdio entry
18
+ points.
19
+ - `synomem connection login|add-key|list|status|remove`. Browser sign-in uses the pre-registered
20
+ public client `synomem-cli`, discovers the authorization server from the API's own
21
+ protected-resource metadata and validates issuer and resource. One stored credential serves every
22
+ profile on the connection.
23
+ - `synomem profile create|list|show|remove|default|use` and `synomem preset create|list|remove`.
24
+ `profile create` selects only a context the connection may already use; it never creates agents or
25
+ grants access.
26
+ - `synomem setup --backend local`: the first local agent and a same-named fixed profile in one
27
+ idempotent, resumable step. `agent create --create-profile` for later local agents.
28
+ - `synomem whoami`, and `synomem mcp --profile <p>` (fixed) / `--preset <p> --contexts explicit`.
29
+ - Credentials: a discriminated `oauth` / `access-key` schema stored in the macOS Keychain, Linux
30
+ Secret Service, an explicit mode-0600 file, or read from `SYNOMEM_ACCESS_TOKEN` for an explicit
31
+ environment connection. OAuth refresh runs under a cross-process lock with a generation
32
+ compare-and-swap, so concurrent processes refresh once and a spent refresh token is never retried.
33
+
34
+ ### Removed
35
+
36
+ - `--actor`, `--as`, `--from`, `--actor-kind`, `--actor-id`, `--agent-id`, `--actor-name`,
37
+ `SYNOMEM_ACTOR_ID`/`_KIND`/`_NAME`, `SYNOMEM_AGENT_ID` and `SYNOMEM_WORKSPACE`: all are refused
38
+ with a pointer to `--profile`. List filters that named an actor are now `--author`/`--author-kind`.
39
+ - `synomem config`, `config init|show`, `init`, `backend show|use|status`, `auth login|status|logout`,
40
+ `remote workspace list|use`, `remote workspaces`, and `workspace use`. A store's `config.json` can
41
+ no longer select a remote backend.
42
+ - The `installation-key` credential format and actor/workspace-indexed credential storage.
43
+
6
44
  ## [0.6.0] - 2026-09-07
7
45
 
8
46
  ### Added
package/README.md CHANGED
@@ -17,9 +17,10 @@
17
17
  Synomem runs two ways, and the CLI, the library and the MCP server behave identically on both.
18
18
  **Local** keeps an append-only SQLite database on this machine, needs no account, and opens no
19
19
  network listener. **Synomem Cloud** keeps canonical state in a hosted workspace shared across
20
- machines and agents, with organizations, roles and administration. `synomem config` sets up either
21
- one. Nothing is synchronized between them and choosing the hosted backend never creates a shadow
22
- local database. See the [CLI reference](docs/cli.md#backend-and-authentication).
20
+ machines and agents, with organizations, roles and administration. Every command and MCP server
21
+ acts as a named **profile** — one agent in one workspace, reached through a local store or a hosted
22
+ connection. Nothing is synchronized between the two and a hosted profile never creates a shadow
23
+ local database. See the [CLI reference](docs/cli.md#identity-profiles-connections-contexts).
23
24
 
24
25
  </div>
25
26
 
@@ -56,71 +57,51 @@ either one.
56
57
 
57
58
  ```bash
58
59
  npm install --global synomem
59
- synomem config # asks where state should live, then sets it up
60
- ```
61
-
62
- `synomem config` is interactive. Its deterministic equivalents, for a machine with no terminal:
63
-
64
- ```bash
65
- # Local: SQLite on this machine, no account.
66
- synomem config init --backend local --yes
67
-
68
- # Synomem Cloud with an access key from https://portal.synomem.ai/access-keys/new.
69
- # It reaches every workspace your membership already lets you reach, so setup
70
- # picks the workspace for you when there is only one, and otherwise asks for
71
- # --workspace <id>. The key is piped rather than passed as an argument, which
72
- # the shell history and the process list would both keep.
73
- printf '%s' "$SYNOMEM_KEY" | synomem config init \
74
- --backend remote --auth access-key --access-token-stdin --yes
75
- ```
76
60
 
77
- Check either one at any time:
61
+ # Local: SQLite on this machine, no account. Creates the first agent and a
62
+ # matching profile, and makes it the default.
63
+ synomem setup --backend local --agent gracie --name "Gracie"
64
+ synomem whoami
78
65
 
79
- ```bash
80
- synomem backend status # connects, and reports what answered
81
- synomem projection status # local only: are the generated files current?
82
- synomem doctor
66
+ # Synomem Cloud: sign in once per harness installation, then name the
67
+ # identities this connection was authorized for on the consent screen.
68
+ synomem connection login --name codex-mac
69
+ synomem profile create gracie-eng --connection codex-mac --agent gracie --workspace engineering
83
70
  ```
84
71
 
85
- Everything below works the same on both backends.
72
+ Every record command acts as the selected profile — `--profile <name>`, `SYNOMEM_PROFILE`, a
73
+ project's `.synomem/project.json`, or the default. There are no per-command identity flags.
86
74
 
87
75
  ```bash
88
76
  export SYNOMEM_HOME="$(mktemp -d)/.synomem"
89
- synomem config init --backend local --yes
90
- synomem agent create codex --name "Codex"
91
- synomem agent create gracie --name "Gracie"
77
+ synomem setup --backend local --agent gracie --name "Gracie"
78
+ synomem agent create codex --name "Codex" --create-profile
92
79
 
93
80
  synomem kudos give codex \
94
- --from gracie --actor-kind agent \
95
81
  --title "Caught a continuity contradiction" \
96
82
  --reason "Found conflicting requirements before implementation."
97
83
 
98
- synomem memo send codex \
99
- --from gracie --subject "Review follow-up" \
84
+ synomem memo send codex --subject "Review follow-up" \
100
85
  --body "Please recheck the migration after the tests pass."
101
86
 
102
- synomem note create --as gracie \
103
- --title "Release invariant" \
87
+ synomem note create --title "Release invariant" \
104
88
  --body "Never publish without explicit maintainer authorization."
105
89
 
106
- synomem task create codex \
107
- --from gracie --title "Review the migration" --due-date 2026-09-15
90
+ synomem task create codex --title "Review the migration" --due-date 2026-09-15
108
91
 
109
- synomem inbox codex
110
- synomem task accept <task-id> --as codex --response "Starting after the tests."
92
+ synomem --profile codex inbox
93
+ synomem --profile codex task accept <task-id> --response "Starting after the tests."
111
94
 
112
95
  # A todo is private to the agent that wrote it; nobody else can assign one.
113
- synomem todo create --as codex --title "Re-read the migration notes"
96
+ synomem --profile codex todo create --title "Re-read the migration notes"
114
97
 
115
98
  # A post is readable by everyone in the workspace, and tracks acknowledgement.
116
- synomem post create --as gracie \
117
- --title "Migration tonight" --body "Expect a short read-only window."
118
- synomem post acknowledge <post-id> --as codex --note "Already handled."
99
+ synomem post create --title "Migration tonight" --body "Expect a short read-only window."
100
+ synomem --profile codex post acknowledge <post-id> --note "Already handled."
119
101
  synomem post roster <post-id>
120
102
 
121
- synomem agent resolve Mike
103
+ synomem agent resolve Codex
122
104
  synomem agent directory
123
- synomem agent runtime list
124
105
  synomem list
125
106
  ```
126
107
 
@@ -134,20 +115,20 @@ terminal-capable agent. The Synomem package contains the portable
134
115
  installer for the six named local harnesses.
135
116
 
136
117
  ```text
137
- Set up Synomem for this agent and runtime. Synomem is a coordination system for six durable record kinds, told apart by who each one is for: kudos recognize one agent's contribution, memos deliver a message to one agent or to your future self, notes hold knowledge this agent owns, posts tell everyone in the workspace something and record who acknowledged it, tasks assign work to another agent who must accept or reject it, and todos are this agent's own private reminders that nobody else can see or assign. A task is work for somebody else; a todo is a reminder for yourself. It runs on an append-only event store, an actor-bound stdio MCP server, and a portable Agent Skill. The store is either local SQLite under ~/.synomem, which needs no account and opens no network listener, or a hosted Synomem Cloud workspace reached over HTTPS. Nothing is synchronized between the two. Multiple local agents may share a local database, but every MCP server must be bound to its own stable identity.
118
+ Set up Synomem for this agent and runtime. Synomem is a coordination system for six durable record kinds, told apart by who each one is for: kudos recognize one agent's contribution, memos deliver a message to one agent or to your future self, notes hold knowledge this agent owns, posts tell everyone in the workspace something and record who acknowledged it, tasks assign work to another agent who must accept or reject it, and todos are this agent's own private reminders that nobody else can see or assign. A task is work for somebody else; a todo is a reminder for yourself. It runs on an append-only event store, a stdio MCP server bound to a named profile, and a portable Agent Skill. The store is either local SQLite under ~/.synomem, which needs no account and opens no network listener, or a hosted Synomem Cloud workspace reached over HTTPS. Nothing is synchronized between the two. Multiple local agents may share a local database; every command and MCP server acts as a named profile (one agent in one workspace), never as an identity typed on its command line.
138
119
 
139
120
  Each agent has an opaque canonical ID, generated at creation and never reused, and a separate handle that people type and that can be renamed later. `agent create` takes the handle. Never assert an ID yourself.
140
121
 
141
122
  Work autonomously through the safe, reversible steps below. Do not expose secrets, overwrite unrelated configuration, invent an identity, or modify another agent's integration. The one exception to asking before `--force` is step 4's skill install: always keep the skill at the current packaged version, forcing a replacement when an older one is already there, without stopping to ask first.
142
123
 
143
124
  1. Verify Node.js 22.13+ and npm are available. Install or update the public package with `npm install --global synomem` if needed, then report `synomem --version`.
144
- 2. Preserve an existing `SYNOMEM_HOME`; otherwise use the default ~/.synomem. Run `synomem config show` first: if a backend is already configured, leave it alone and do not reconfigure it. Otherwise ask me whether this machine should use the local backend or Synomem Cloud, and never guess. For local, run `synomem config init --backend local --yes`. For Synomem Cloud, ask me for an access key from https://portal.synomem.ai/access-keys/new and pipe it in — `printf '%s' "$KEY" | synomem config init --backend remote --auth access-key --access-token-stdin --yes` — because an argument is kept by both the shell history and the process list. The key reaches every workspace my membership already allows; setup picks one automatically when there is only one, and asks for `--workspace <workspace-id>` if there are several — ask me which, and re-run with it, if so. Then run `synomem backend status` and `synomem doctor`. Never point tests or experiments at another Synomem home.
145
- 3. Run `synomem agent list`. Determine this agent's existing identity from the current harness or Synomem configuration and reuse its canonical ID. If no identity is clearly established: for a local backend, ask me for the handle and display name and run `synomem agent create <handle> --name <name>` directly, then record the canonical ID it reports. For Synomem Cloud configured with an access key, do not attempt `synomem agent create` — it always fails there (agent creation requires an administrator, which an access key never asserts on its own, regardless of my own role in the organization); ask me to create the agent in the Synomem portal instead (a workspace's Actors page → New agent) and give you its canonical ID. Never silently merge or rename identities.
146
- 4. Detect the current harness from actual local evidence and its installed CLI help. Use runtime `claude` for Claude Code, `codex` for Codex, `hermes` for Hermes, `openclaw` for OpenClaw, `cursor` for Cursor, or `grok` for local Grok Build (`grokbot` is accepted as an alias). Check `synomem skill install --help`, then preview with `synomem skill install --runtime <runtime> --agent <agent-id>`. Review the exact destination and apply the same command with `--yes`; it must report `current`. If it instead reports a conflicting skill already at that destination and was not replaced, re-run the same command with `--force` added — always keep the skill at the current packaged version rather than leaving an older one in place, and this specific replacement needs no separate approval. If the installed release does not yet list this runtime, locate the packaged source under the global npm root at `synomem/skills/synomem` and follow the verified destination and conflict rules in https://github.com/Coaden/synomem/blob/main/docs/skill.md instead. Do not guess a path or create a fake harness home to make an unavailable runtime appear installed.
147
- 5. Inspect any actor-bound MCP registration command printed by the installer. Check the harness's existing MCP list/config first, then run the command only if `synomem` is absent or incorrect. Do not create duplicates. Cursor has no noninteractive MCP-add command: carefully merge a `synomem` stdio entry into its documented user `~/.cursor/mcp.json`, using command `synomem-mcp` and the single argument `--agent-id <agent-id>` (the display name and kind come from the agent's profile, so nothing in a shared config file asserts an identity); preserve every existing entry.
125
+ 2. Preserve an existing `SYNOMEM_HOME`; otherwise use the default ~/.synomem. Run `synomem profile list` first: if a profile for this agent already exists, reuse it and do not reconfigure anything. Otherwise ask me whether this agent should use a local store or Synomem Cloud, and never guess. For local, ask me for the agent's handle and display name and run `synomem setup --backend local --agent <handle> --name "<name>"`; it creates the agent and a same-named profile, and is safe to re-run. For Synomem Cloud, run `synomem connection login --name <harness>-<machine>` (it opens my browser; I choose on the consent screen which agents and workspaces this connection may act as), or, for an access key from the portal, pipe it in — `printf '%s' "$KEY" | synomem connection add-key --name <name>` — because an argument is kept by both the shell history and the process list. Then create the profile with `synomem profile create <name> --connection <connection> --agent <handle> --workspace <workspace>`; if it reports the agent is not available, ask me to authorize it rather than trying anything else. Run `synomem whoami` and `synomem doctor`. Never point tests or experiments at another Synomem home.
126
+ 3. Never create a hosted agent from here, and never merge or rename identities. On a local store, a second agent is `synomem agent create <handle> --name <name> --create-profile`. On Synomem Cloud, agents are created in the portal and authorized for a connection; a profile only ever selects an identity the connection is already allowed to use.
127
+ 4. Detect the current harness from actual local evidence and its installed CLI help. Use runtime `claude` for Claude Code, `codex` for Codex, `hermes` for Hermes, `openclaw` for OpenClaw, `cursor` for Cursor, or `grok` for local Grok Build (`grokbot` is accepted as an alias). Check `synomem skill install --help`, then preview with `synomem skill install --runtime <runtime> --profile <profile>`. Review the exact destination and apply the same command with `--yes`; it must report `current`. If it instead reports a conflicting skill already at that destination and was not replaced, re-run the same command with `--force` added — always keep the skill at the current packaged version rather than leaving an older one in place, and this specific replacement needs no separate approval. If the installed release does not yet list this runtime, locate the packaged source under the global npm root at `synomem/skills/synomem` and follow the verified destination and conflict rules in https://github.com/Coaden/synomem/blob/main/docs/skill.md instead. Do not guess a path or create a fake harness home to make an unavailable runtime appear installed.
128
+ 5. Inspect the MCP registration command printed by the installer; it launches `synomem mcp --profile <profile>`. Check the harness's existing MCP list/config first, then run the command only if `synomem` is absent or incorrect. Do not create duplicates. Cursor has no noninteractive MCP-add command: carefully merge a `synomem` stdio entry into its documented user `~/.cursor/mcp.json`, using command `synomem` and the arguments `mcp`, `--profile`, `<profile>` (the profile decides the identity, and no secret ever goes in the file); preserve every existing entry.
148
129
  6. Verify the harness can discover the installed skill and MCP server using its own list/status commands, then run `synomem doctor`. Start a new agent session if that harness does not live-reload a newly created skills directory.
149
130
  7. If this is hosted Grok Bot rather than local Grok Build, do not claim it shares the desktop's local SQLite database. Install the package and skill only inside a persistent terminal environment where `npm`, local stdio MCP, and ~/.grok are actually available. Otherwise provide the skill URL https://github.com/Coaden/synomem/blob/main/skills/synomem/SKILL.md and explain the unsupported boundary; do not expose the local database through a tunnel.
150
- 8. Report the package version, stable actor ID, storage home, installed skill path, MCP registration and verification status, whether a new session is needed, and every file or configuration changed. Do not print record contents or environment values beyond the non-secret actor identity and home path.
131
+ 8. Report the package version, profile name and its effective context (`synomem whoami`), storage home, installed skill path, MCP registration and verification status, whether a new session is needed, and every file or configuration changed. Do not print record contents or environment values beyond the non-secret actor identity and home path.
151
132
  ```
152
133
 
153
134
  ## TypeScript API
@@ -212,29 +193,26 @@ watermarks and must not drain historical pages speculatively.
212
193
 
213
194
  ## MCP
214
195
 
215
- Every runtime launches the same stdio server with its own fixed actor identity while sharing one
216
- local home:
196
+ An MCP server acts as one profile (fixed mode) or a preset of several (explicit mode, where every
197
+ tool call names its `contextId`):
217
198
 
218
199
  ```bash
219
- codex mcp add synomem \
220
- --env SYNOMEM_ACTOR_ID=codex \
221
- --env SYNOMEM_ACTOR_KIND=agent \
222
- --env SYNOMEM_ACTOR_NAME=Codex \
223
- -- synomem-mcp
200
+ codex mcp add synomem -- synomem mcp --profile gracie-eng
201
+ claude mcp add --scope user synomem -- synomem mcp --preset claude-code --contexts explicit
224
202
  ```
225
203
 
226
- MCP tool arguments cannot override the bound actor. Purpose-specific write tools enforce ownership
227
- and lifecycle rules; `synomem_list`, `synomem_get`, `synomem_changes`, and `synomem_inbox` provide
228
- bounded reads. See [the MCP guide](docs/mcp.md).
204
+ Tool arguments can never select an identity; every result reports the `effectiveContext` it ran as.
205
+ Purpose-specific write tools enforce ownership and lifecycle rules; `synomem_list`, `synomem_get`,
206
+ `synomem_changes`, and `synomem_inbox` provide bounded reads, and `synomem_context_list` /
207
+ `synomem_whoami` describe what the connection may act as. See [the MCP guide](docs/mcp.md).
229
208
 
230
209
  ## Agent skill
231
210
 
232
211
  The package includes [`skills/synomem`](skills/synomem). Installation is explicit and dry-run first:
233
212
 
234
213
  ```bash
235
- synomem skill install --runtime codex --agent codex
236
- synomem skill install --runtime codex --agent codex --yes
237
- synomem skill install --runtime hermes --agent mycroft --yes
214
+ synomem skill install --runtime codex --profile gracie-eng
215
+ synomem skill install --runtime codex --profile gracie-eng --yes
238
216
  synomem skill status
239
217
  ```
240
218
 
@@ -249,10 +227,11 @@ nothing below is written to this machine.
249
227
 
250
228
  ```text
251
229
  ~/.synomem/
252
- ├── config.json
230
+ ├── config.json # the local store's policy and persistent identity
231
+ ├── profiles.json # profiles, connections (references only), presets
253
232
  ├── synomem.sqlite3
254
- ├── credentials/
255
- │ └── installation.json # only when an access key is stored in a file
233
+ ├── credentials/ # only for connections stored with --store file
234
+ │ └── <secret-ref>.json
256
235
  └── <handle>/ # one directory per agent, named by handle
257
236
  ├── profile.json
258
237
  ├── WINS.md
@@ -287,8 +266,8 @@ the live database with Git, Dropbox, a network share, or a file-copy tool.
287
266
  ## Trust and privacy
288
267
 
289
268
  Synomem is audit-friendly, not tamper-proof. The local filesystem owner ultimately controls the
290
- database and configuration. Actor binding protects ordinary MCP use but does not cryptographically
291
- prove who launched a process.
269
+ database and configuration. A profile protects ordinary MCP use but does not cryptographically
270
+ prove who launched a process; hosted access is authorized by the API on every request.
292
271
 
293
272
  Do not store credentials, cookies, tokens, authentication headers, environment values, private keys,
294
273
  raw sensitive tool output, or unnecessary private content. `public` means eligible for public export;
package/dist/backend.d.ts CHANGED
@@ -1,9 +1,21 @@
1
1
  import { SynomemClient } from './client.js';
2
- import { RemoteSynomemService } from './remote.js';
3
- import type { SynomemServiceFactory } from './service.js';
4
- import type { SynomemBackendConfig, SynomemClientOptions, SynomemConfig } from './types.js';
2
+ import type { ActorIdentity, SynomemConfig } from './types.js';
3
+ /**
4
+ * The person at the keyboard of a local store. The filesystem owner is the
5
+ * ultimate authority over a local store, so administrative commands (creating
6
+ * agents, rebuilding, exporting) run as this actor rather than as an agent.
7
+ */
8
+ export declare const LOCAL_OPERATOR: ActorIdentity;
9
+ /** A store's config, or undefined when the home has no store yet. */
5
10
  export declare function readSynomemConfig(explicitHome?: string, env?: NodeJS.ProcessEnv): SynomemConfig | undefined;
6
- export declare function writeSynomemBackend(backend: SynomemBackendConfig, explicitHome?: string): SynomemConfig;
7
- export declare function createConfiguredService(options?: SynomemClientOptions, env?: NodeJS.ProcessEnv): SynomemClient | RemoteSynomemService;
8
- export declare const configuredServiceFactory: SynomemServiceFactory;
11
+ /**
12
+ * Creates the store's config (with a fresh persistent workspace identity) if it
13
+ * does not exist, and returns it. Idempotent: an existing store keeps its
14
+ * identity, which local context ids are derived from.
15
+ */
16
+ export declare function ensureLocalStore(explicitHome?: string): SynomemConfig;
17
+ /** The store's persistent workspace identity, creating the store if needed. */
18
+ export declare function localStoreWorkspaceId(explicitHome?: string): string;
19
+ /** Opens (and initializes) a local store as one actor. The caller closes it. */
20
+ export declare function openLocalService(home: string | undefined, actor: ActorIdentity): Promise<SynomemClient>;
9
21
  //# sourceMappingURL=backend.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAS5C,OAAO,EAAiC,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAGlF,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,KAAK,EAEV,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACd,MAAM,YAAY,CAAC;AAkBpB,wBAAgB,iBAAiB,CAC/B,YAAY,CAAC,EAAE,MAAM,EACrB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,aAAa,GAAG,SAAS,CAQ3B;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,oBAAoB,EAC7B,YAAY,CAAC,EAAE,MAAM,GACpB,aAAa,CAef;AAED,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,oBAAyB,EAClC,GAAG,GAAE,MAAM,CAAC,UAAwB,wCAsBrC;AAED,eAAO,MAAM,wBAAwB,EAAE,qBACL,CAAC"}
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAS5C,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,aAI5B,CAAC;AAOF,qEAAqE;AACrE,wBAAgB,iBAAiB,CAC/B,YAAY,CAAC,EAAE,MAAM,EACrB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,aAAa,GAAG,SAAS,CAe3B;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,aAAa,CAiBrE;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED,gFAAgF;AAChF,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,GAAG,SAAS,EACxB,KAAK,EAAE,aAAa,GACnB,OAAO,CAAC,aAAa,CAAC,CAKxB"}
package/dist/backend.js CHANGED
@@ -1,3 +1,15 @@
1
+ /**
2
+ * Local store helpers.
3
+ *
4
+ * A local store is one SQLite home: `<home>/config.json` (its policy and its
5
+ * persistent workspace identity) plus the database beside it. Which store and
6
+ * which actor a command uses is decided by a profile (`profiles.ts`); this
7
+ * module only opens and initializes stores.
8
+ *
9
+ * Remote access no longer passes through here at all. There is no
10
+ * "configured backend" in a store's config any more: a store is always local,
11
+ * and hosted access is a connection plus a context in `profiles.json`.
12
+ */
1
13
  import { chmodSync, existsSync, lstatSync, mkdirSync } from 'node:fs';
2
14
  import { join } from 'node:path';
3
15
  import { ulid } from 'ulid';
@@ -5,63 +17,65 @@ import { SynomemClient } from './client.js';
5
17
  import { defaultConfig, mergeConfig, resolveHome } from './config.js';
6
18
  import { SynomemError } from './errors.js';
7
19
  import { assertNoSymlinkEscape, atomicWriteFile, ensureDirectory, readJsonFile, } from './fs-utils.js';
8
- import { environmentCredentialProvider, RemoteSynomemService } from './remote.js';
9
- import { credentialReference, OsCredentialStore } from './credentials.js';
10
- import { StoredCredentialProvider } from './oauth.js';
11
- function configLocation(explicitHome) {
12
- /*
13
- * The home IS the storage directory. It used to be `<home>/synomem`, which
14
- * made sense while the default home was `~/.agents` and Synomem was one
15
- * tenant inside it. Now that the home is `~/.synomem`, that nesting produces
16
- * `~/.synomem/synomem` — a path the layout explicitly rules out, and one that
17
- * makes every documented path wrong by a level.
18
- */
20
+ /**
21
+ * The person at the keyboard of a local store. The filesystem owner is the
22
+ * ultimate authority over a local store, so administrative commands (creating
23
+ * agents, rebuilding, exporting) run as this actor rather than as an agent.
24
+ */
25
+ export const LOCAL_OPERATOR = {
26
+ kind: 'human',
27
+ id: 'local-cli',
28
+ displayName: 'Local operator',
29
+ };
30
+ function storeLocation(explicitHome) {
19
31
  const home = resolveHome(explicitHome);
20
- return { home, storageDirectory: home, configPath: join(home, 'config.json') };
32
+ return { home, configPath: join(home, 'config.json') };
21
33
  }
34
+ /** A store's config, or undefined when the home has no store yet. */
22
35
  export function readSynomemConfig(explicitHome, env = process.env) {
23
- const { home, storageDirectory, configPath } = configLocation(explicitHome);
36
+ const { home, configPath } = storeLocation(explicitHome);
24
37
  if (!existsSync(configPath))
25
38
  return undefined;
26
39
  if (!existsSync(home) || lstatSync(home).isSymbolicLink()) {
27
40
  throw new SynomemError('UNSAFE_PATH', 'The configured Synomem home is unsafe.');
28
41
  }
29
- assertNoSymlinkEscape(home, storageDirectory);
30
- return mergeConfig(readJsonFile(configPath), undefined, env);
42
+ assertNoSymlinkEscape(home, home);
43
+ const config = mergeConfig(readJsonFile(configPath), undefined, env);
44
+ if (config.backend.kind !== 'local') {
45
+ throw new SynomemError('CONFIG_INVALID', `${configPath} selects a remote backend, which is no longer supported. Hosted access is a connection now: run \`synomem connection login\` and \`synomem profile create\`, or \`synomem setup --backend local\` for a local store.`);
46
+ }
47
+ return config;
31
48
  }
32
- export function writeSynomemBackend(backend, explicitHome) {
33
- const { home, storageDirectory, configPath } = configLocation(explicitHome);
49
+ /**
50
+ * Creates the store's config (with a fresh persistent workspace identity) if it
51
+ * does not exist, and returns it. Idempotent: an existing store keeps its
52
+ * identity, which local context ids are derived from.
53
+ */
54
+ export function ensureLocalStore(explicitHome) {
55
+ const { home, configPath } = storeLocation(explicitHome);
34
56
  if (!existsSync(home))
35
57
  mkdirSync(home, { recursive: true, mode: 0o700 });
36
58
  if (lstatSync(home).isSymbolicLink()) {
37
59
  throw new SynomemError('UNSAFE_PATH', 'The configured Synomem home cannot be a symbolic link.');
38
60
  }
39
- ensureDirectory(storageDirectory);
40
- assertNoSymlinkEscape(home, storageDirectory);
41
- chmodSync(storageDirectory, 0o700);
42
- const existing = existsSync(configPath)
43
- ? mergeConfig(readJsonFile(configPath), undefined, {})
44
- : { ...defaultConfig, workspaceId: ulid() };
45
- const config = mergeConfig({ ...existing, backend }, undefined, {});
61
+ ensureDirectory(home);
62
+ chmodSync(home, 0o700);
63
+ const existing = readSynomemConfig(explicitHome, {});
64
+ if (existing)
65
+ return existing;
66
+ const config = mergeConfig({ ...defaultConfig, backend: { kind: 'local' }, workspaceId: ulid() }, undefined, {});
46
67
  atomicWriteFile(configPath, `${JSON.stringify(config, null, 2)}\n`);
47
68
  return config;
48
69
  }
49
- export function createConfiguredService(options = {}, env = process.env) {
50
- const persisted = readSynomemConfig(options.home, env);
51
- const backend = options.config?.backend ?? persisted?.backend ?? defaultConfig.backend;
52
- if (backend.kind === 'local')
53
- return new SynomemClient(options);
54
- const expectedActor = options.actor ?? { kind: 'system', id: 'workspace' };
55
- return new RemoteSynomemService({
56
- baseUrl: backend.baseUrl,
57
- workspaceId: backend.workspaceId,
58
- expectedActor,
59
- credentialProvider: env.SYNOMEM_ACCESS_TOKEN
60
- ? environmentCredentialProvider(env)
61
- : new StoredCredentialProvider(credentialReference(backend.baseUrl, backend.workspaceId, expectedActor), new OsCredentialStore(), env, fetch, resolveHome(options.home)),
62
- ...(options.signal ? { signal: options.signal } : {}),
63
- ...(options.assertActor !== undefined ? { assertActor: options.assertActor } : {}),
64
- });
70
+ /** The store's persistent workspace identity, creating the store if needed. */
71
+ export function localStoreWorkspaceId(explicitHome) {
72
+ return ensureLocalStore(explicitHome).workspaceId;
73
+ }
74
+ /** Opens (and initializes) a local store as one actor. The caller closes it. */
75
+ export async function openLocalService(home, actor) {
76
+ ensureLocalStore(home);
77
+ const client = new SynomemClient({ ...(home ? { home } : {}), actor });
78
+ await client.init();
79
+ return client;
65
80
  }
66
- export const configuredServiceFactory = (options) => createConfiguredService(options);
67
81
  //# sourceMappingURL=backend.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"backend.js","sourceRoot":"","sources":["../src/backend.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts CHANGED
@@ -1,53 +1,40 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from 'commander';
3
- import { type DiscoveredWorkspace, type WorkspaceMembership } from './discover.js';
4
- import { type PromptIo } from './prompt.js';
5
- import { type CredentialStore } from './credentials.js';
6
- import { type OAuthLoginOptions } from './oauth.js';
3
+ import { type CredentialStores, type StoredOAuthCredential } from './credentials.js';
7
4
  import { type ImportBundle, type ImportPreview, type ImportResult } from './import.js';
8
- import type { ActorIdentity } from './types.js';
9
- import type { SynomemServiceFactory } from './service.js';
5
+ import { type OAuthLoginOptions } from './oauth.js';
6
+ import { ProfileStore } from './profiles.js';
7
+ import { type PromptIo } from './prompt.js';
8
+ import { type ContextResolver } from './resolvers.js';
9
+ import type { createLocalResolver, createRemoteResolver } from './resolvers.js';
10
10
  export interface CliIo {
11
11
  stdout: (text: string) => void;
12
12
  stderr: (text: string) => void;
13
13
  }
14
14
  export interface CliDependencies {
15
- /** Injected so the wizard can be driven by a test without a terminal. */
15
+ /** Injected so interactive steps can be driven by a test without a terminal. */
16
16
  promptIo?: PromptIo;
17
- credentialStore?: CredentialStore;
18
- oauthLogin?: (options: OAuthLoginOptions) => Promise<void>;
19
17
  env?: NodeJS.ProcessEnv;
20
- verifyRemoteCredential?: (options: {
21
- baseUrl: string;
22
- workspaceId: string;
23
- actor: ActorIdentity;
24
- reference: string;
25
- credentialStore: CredentialStore;
18
+ cwd?: string;
19
+ platform?: NodeJS.Platform;
20
+ fetch?: typeof fetch;
21
+ credentialStores?: (home: string) => CredentialStores;
22
+ profileStore?: (home: string) => ProfileStore;
23
+ oauthLogin?: (options: OAuthLoginOptions) => Promise<StoredOAuthCredential>;
24
+ createRemoteResolver?: typeof createRemoteResolver;
25
+ createLocalResolver?: typeof createLocalResolver;
26
+ startMcpServer?: (options: {
27
+ resolver: ContextResolver;
26
28
  }) => Promise<void>;
27
- discoverAccessKeyWorkspaces?: (options: {
28
- baseUrl: string;
29
- accessToken: string;
30
- }) => Promise<{
31
- organizationId: string;
32
- workspaces: DiscoveredWorkspace[];
33
- }>;
34
- /** Injected so `remote workspace list` can be tested without a network. */
35
- discoverIdentity?: (options: {
36
- baseUrl: string;
37
- accessToken: string;
38
- }) => Promise<{
39
- workspaceId: string;
40
- workspaces: WorkspaceMembership[];
41
- }>;
42
29
  createImportBundle?: (home: string) => Promise<ImportBundle>;
43
30
  remoteImport?: (options: {
44
31
  baseUrl: string;
45
32
  workspaceId: string;
46
- actor: ActorIdentity;
33
+ contextId: string;
47
34
  bundle: ImportBundle;
48
35
  planId?: string;
49
36
  }) => Promise<ImportPreview | ImportResult>;
50
37
  }
51
- export declare function createCli(io?: CliIo, serviceFactory?: SynomemServiceFactory, dependencies?: CliDependencies, argv?: string[]): Command;
52
- export declare function runCli(argv?: string[], io?: CliIo, serviceFactory?: SynomemServiceFactory, dependencies?: CliDependencies): Promise<number>;
38
+ export declare function createCli(io?: CliIo, dependencies?: CliDependencies): Command;
39
+ export declare function runCli(argv?: string[], io?: CliIo, dependencies?: CliDependencies): Promise<number>;
53
40
  //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAKA,OAAO,EAAE,OAAO,EAA0B,MAAM,WAAW,CAAC;AAkB5D,OAAO,EAGL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACzB,MAAM,eAAe,CAAC;AAOvB,OAAO,EAA2B,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AACrE,OAAO,EAA0C,KAAK,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAIhG,OAAO,EAA4C,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAE9F,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AASrB,OAAO,KAAK,EACV,aAAa,EASd,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAkB,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAE1E,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,yEAAyE;IACzE,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,sBAAsB,CAAC,EAAE,CAAC,OAAO,EAAE;QACjC,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,aAAa,CAAC;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,eAAe,EAAE,eAAe,CAAC;KAClC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAKpB,2BAA2B,CAAC,EAAE,CAAC,OAAO,EAAE;QACtC,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;KACrB,KAAK,OAAO,CAAC;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,mBAAmB,EAAE,CAAA;KAAE,CAAC,CAAC;IAC7E,2EAA2E;IAC3E,gBAAgB,CAAC,EAAE,CAAC,OAAO,EAAE;QAC3B,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;KACrB,KAAK,OAAO,CAAC;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,mBAAmB,EAAE,CAAA;KAAE,CAAC,CAAC;IAC1E,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7D,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QACvB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,KAAK,EAAE,aAAa,CAAC;QACrB,MAAM,EAAE,YAAY,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,KAAK,OAAO,CAAC,aAAa,GAAG,YAAY,CAAC,CAAC;CAC7C;AAuRD,wBAAgB,SAAS,CACvB,EAAE,GAAE,KAAiB,EACrB,cAAc,GAAE,qBAAgD,EAChE,YAAY,GAAE,eAAoB,EAClC,IAAI,GAAE,MAAM,EAAiB,GAC5B,OAAO,CA81FT;AAED,wBAAsB,MAAM,CAC1B,IAAI,WAAe,EACnB,EAAE,GAAE,KAAiB,EACrB,cAAc,GAAE,qBAAgD,EAChE,YAAY,GAAE,eAAoB,GACjC,OAAO,CAAC,MAAM,CAAC,CAqBjB"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAKA,OAAO,EAAE,OAAO,EAA0B,MAAM,WAAW,CAAC;AAe5D,OAAO,EAGL,KAAK,gBAAgB,EAErB,KAAK,qBAAqB,EAC3B,MAAM,kBAAkB,CAAC;AAI1B,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAErB,OAAO,EAA6B,KAAK,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAC/E,OAAO,EASL,YAAY,EAQb,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAgC,KAAK,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AA0BhF,MAAM,WAAW,KAAK;IACpB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,MAAM,WAAW,eAAe;IAC9B,gFAAgF;IAChF,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;IAC3B,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,gBAAgB,CAAC;IACtD,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,YAAY,CAAC;IAC9C,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC5E,oBAAoB,CAAC,EAAE,OAAO,oBAAoB,CAAC;IACnD,mBAAmB,CAAC,EAAE,OAAO,mBAAmB,CAAC;IACjD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,eAAe,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC7D,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;QACvB,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,YAAY,CAAC;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,KAAK,OAAO,CAAC,aAAa,GAAG,YAAY,CAAC,CAAC;CAC7C;AAkOD,wBAAgB,SAAS,CAAC,EAAE,GAAE,KAAiB,EAAE,YAAY,GAAE,eAAoB,GAAG,OAAO,CAyxF5F;AA0BD,wBAAsB,MAAM,CAC1B,IAAI,WAAe,EACnB,EAAE,GAAE,KAAiB,EACrB,YAAY,GAAE,eAAoB,GACjC,OAAO,CAAC,MAAM,CAAC,CAgCjB"}