pi-jarvis 1.7.0 → 1.8.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.
- package/AGENTS.md +10 -1
- package/README.md +95 -3
- package/dist/archive-config.d.ts +15 -0
- package/dist/archive-config.d.ts.map +1 -0
- package/dist/archive-config.js +310 -0
- package/dist/archive-config.js.map +1 -0
- package/dist/archive-extension.d.ts +38 -0
- package/dist/archive-extension.d.ts.map +1 -0
- package/dist/archive-extension.js +334 -0
- package/dist/archive-extension.js.map +1 -0
- package/dist/archive-service.d.ts +60 -0
- package/dist/archive-service.d.ts.map +1 -0
- package/dist/archive-service.js +441 -0
- package/dist/archive-service.js.map +1 -0
- package/dist/archive-store.d.ts +53 -0
- package/dist/archive-store.d.ts.map +1 -0
- package/dist/archive-store.js +782 -0
- package/dist/archive-store.js.map +1 -0
- package/dist/archive-types.d.ts +57 -0
- package/dist/archive-types.d.ts.map +1 -0
- package/dist/archive-types.js +2 -0
- package/dist/archive-types.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -1
- package/dist/side-session.d.ts +6 -0
- package/dist/side-session.d.ts.map +1 -1
- package/dist/side-session.js +33 -3
- package/dist/side-session.js.map +1 -1
- package/package.json +7 -4
package/AGENTS.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Project Scope
|
|
4
4
|
- `pi-jarvis` is a Pi extension that opens a `/jarvis` side-conversation overlay.
|
|
5
|
-
- Core runtime files: `index.ts`, `side-session.ts`, `native-mcp.ts`, `overlay.ts`, `overlay-layout.ts`, `draft-editor.ts`, `transcript-viewport.ts`, `jarvis-branding.ts`, `model-picker.ts`, `jarvis-config.ts`, `session-ref.ts`,
|
|
5
|
+
- Core runtime files: `index.ts`, `side-session.ts`, `native-mcp.ts`, `overlay.ts`, `overlay-layout.ts`, `draft-editor.ts`, `transcript-viewport.ts`, `jarvis-branding.ts`, `model-picker.ts`, `jarvis-config.ts`, `session-ref.ts`, `memory-{types,config,content,store,service,extension}.ts`, and `archive-{types,config,store,service,extension}.ts`.
|
|
6
6
|
- Current baseline: Pi 1.0.0 (`@earendil-works` packages), Node.js >=22.19.0. Older Pi hosts are not supported.
|
|
7
7
|
|
|
8
8
|
## Current `/jarvis-model` and `/jarvis-thinking` Behavior
|
|
@@ -60,6 +60,15 @@
|
|
|
60
60
|
- Memory guidance is also request-local: use a custom advisory so Pi's later forced-prompt projection cannot discard it. Preserve other prompt/tool state; a mid-turn disable removes both advisory and recalled records from future requests.
|
|
61
61
|
- Model tools recheck live trust/settings/cancellation and permission generations at execution, including captured definitions. Broadcast observed policy changes across mounted lanes and revoke per-binding generations at session/tree boundaries; don't promise live push delivery across processes. Model forget requires cancellable human review and transactionally compares the reviewed version. Tombstones prevent identical event/title resurrection, not every semantic mention; Pi transcripts, backups and already-sent context remain. Do not promise encryption, a sandbox, or forensic erasure.
|
|
62
62
|
|
|
63
|
+
## Optional full-session archive (1.8.0)
|
|
64
|
+
- `archive-{types,config,store,service,extension}.ts` implement an independent OFF-by-default archive, explicitly mounted in main and Jarvis. Defaults enabled=false/capture=true/modelAccess=false; per-field project > global > defaults except explicit global enabled=false is master-off. Untrusted/config errors pause everything. Never enable/import real user data in tests.
|
|
65
|
+
- Separate settings: `<agentDir>/extensions/pi-jarvis-archive.json` and `.pi/jarvis-archive.json`, top-level `archive`. Controls default global. on/model-access on/clear require `--confirm-sensitive`; clear removes settings, not data, and fallback can re-enable. Archive tools are read-only and need modelAccess; humans can inspect with only capture/modelAccess off, but not full off.
|
|
66
|
+
- `/jarvis-archive` and overlay `/archive` commands are local, immediate, no provider/boot/queue work. Search/read/session default current-project; all-project access is explicit. Model tools cannot change controls, import, or delete. No auto context injection.
|
|
67
|
+
- Archive accepted finalized journal entries unredacted, including exposed thinking/tool/system/custom/error/inline-image data. Never capture intermediate message_end/tool_result/raw-provider payloads before later redactors. Baseline existing entry IDs on activation, never auto-backfill; parent/header provenance retained. Snapshots are not crash-safe audit logging and cannot recover unpersisted events, earlier truncation or external referenced files. Warn on storage/observation failures, not silent replay.
|
|
68
|
+
- Lazy private SQLite FTS5 at `<agentDir>/extensions/pi-jarvis-archive/archive.sqlite`, no automatic retention eviction. 64 MiB raw-entry/index budgets and 64K UTF-16 normalization-context hard rejection, no truncation of accepted raw JSON or silent partial indexing. Identical serialized payloads deduplicate across lanes; conflicting payloads for one identity fail without replacement. Search/read output max 24,000 JSON bytes plus notice; raw read offsets count Unicode codepoints and preserve pagination through output shrinking. Oversized display provenance is explicitly abbreviated; read(part=metadata) / read --metadata pages exact original metadata so every accepted entry stays accessible. Images/signatures are raw-retained, not text-indexed. Never load full payloads for search or scan all raw bodies on open.
|
|
69
|
+
- Explicit human import streams one selected regular v3 JSONL file, honors its header's project/session provenance, checks live capture/epoch/cancellation at chunk/record boundaries, reports partial commits, never mutates source. No directory scans/legacy auto-migration. Scoped forget-session/prune require --confirm; tombstones stop identical entry resurrection, not all copies. No encryption, sandbox, forensic erase, or hard total-disk-quota claims.
|
|
70
|
+
- Keep live trust/settings and per-binding stale-definition guards independent of Repo tools. Reader permission changes must not discard pending recording. Main owner closes storage after final archive snapshot; the side owner snapshots finalized entries before revoking its lifetime/context, without closing the shared service. Preserve archive finalization before main boot-generation invalidation. Settings observations propagate between mounted lanes, not by a cross-process watcher.
|
|
71
|
+
|
|
63
72
|
## Git and Release Policy
|
|
64
73
|
- Every new commit MUST have an annotated **stable version tag `vX.Y.Z`**. No `dev`, alpha, beta, release-candidate, build-metadata, or SHA-only tags. This is a released extension, not a prerelease channel.
|
|
65
74
|
- Before committing, choose the next unused stable version and update package metadata, lockfile, README, and a dated changelog entry together. Tag every commit, including intermediate and merge commits; never leave a new commit untagged. Run `npm run check:tags`, then push the commit and version tag atomically. Do not move or replace existing tags or rewrite shared history.
|
package/README.md
CHANGED
|
@@ -6,20 +6,23 @@
|
|
|
6
6
|
|
|
7
7
|
## A cinematic side-conversation overlay for Pi
|
|
8
8
|
|
|
9
|
-
**
|
|
9
|
+
**A second lane of thought—with shared memory and an optional searchable history archive.**
|
|
10
10
|
|
|
11
11
|
`pi-jarvis` adds `/jarvis`: a polished overlay where you can ask for status, inspect the repo when you explicitly allow it, and send a quiet note or a confirmed redirect back to the main lane.
|
|
12
12
|
|
|
13
|
+
**Remember what matters. Find the original history when you need it.** Main Pi and Jarvis share [persistent memory](#shared-memory); the separate, opt-in [full-session archive](#full-session-archive) adds indexed history search across sessions and, when explicitly requested, projects.
|
|
14
|
+
|
|
13
15
|
[](https://github.com/crustyhacker/pi-jarvis/actions/workflows/ci.yml)
|
|
14
16
|
[](https://www.npmjs.com/package/pi-jarvis)
|
|
15
17
|
[](./LICENSE)
|
|
16
18
|
[](https://github.com/crustyhacker/pi-jarvis)
|
|
17
19
|
[](./package.json)
|
|
18
20
|
|
|
19
|
-
<p><strong>Current version:</strong> 1.
|
|
21
|
+
<p><strong>Current version:</strong> 1.8.0</p>
|
|
20
22
|
|
|
21
23
|
<p>
|
|
22
24
|
<strong>Shared persistent memory</strong> ·
|
|
25
|
+
<strong>Optional indexed session archive</strong> ·
|
|
23
26
|
<strong>Persistent side session</strong> ·
|
|
24
27
|
<strong>Live main-session awareness</strong> ·
|
|
25
28
|
<strong>Opt-in local tools + native MCP</strong> ·
|
|
@@ -74,11 +77,28 @@ The main Pi session should stay on the critical path.
|
|
|
74
77
|
|
|
75
78
|
---
|
|
76
79
|
|
|
80
|
+
## Two complementary memory features
|
|
81
|
+
|
|
82
|
+
| | Shared memory | Optional full-session archive |
|
|
83
|
+
|---|---|---|
|
|
84
|
+
| **Purpose** | Remember useful preferences, corrections, decisions and references | Find original recorded conversations, tool activity and session history |
|
|
85
|
+
| **What it keeps** | Curated notes plus bounded finalized user/assistant text captures | Complete accepted finalized Pi journal entries, with provenance and paged raw reads |
|
|
86
|
+
| **Default** | **On in trusted projects**, with separate capture/recall controls | **Off**; recording and model access are separately controlled |
|
|
87
|
+
| **Retrieval** | Automatic recall from global/current-project memory; explicit broader search | Local indexed search and session browsing; no automatic context injection |
|
|
88
|
+
| **Manage it** | `/jarvis-memory` · overlay `/memory` | `/jarvis-archive` · overlay `/archive` |
|
|
89
|
+
|
|
90
|
+
Both work across main Pi and Jarvis, independently of **Repo tools** and whether the overlay is open. Each has its own local SQLite store and global/project controls. Turning one off does not turn the other off.
|
|
91
|
+
|
|
92
|
+
**Privacy matters:** storage is local plaintext. Archive content is unredacted and can include secrets; granting model access can send retrieved content to your model provider. “Full” means accepted finalized data exposed by Pi—not hidden provider reasoning or a crash-safe audit log. Historical import is explicit. See the [memory controls](#shared-memory) and [archive limits](#full-session-archive) before enabling more access.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
77
96
|
## At a glance
|
|
78
97
|
|
|
79
98
|
| Capability | What you get |
|
|
80
99
|
|---|---|
|
|
81
100
|
| **Shared memory** | Main Pi and Jarvis remember useful discussions across sessions; enabled by default, with global/project controls and a master off switch |
|
|
101
|
+
| **Optional full-session archive** | Off by default; raw finalized entries, local indexed cross-session search, separate model permission and explicit historical import |
|
|
82
102
|
| **Persistent side lane** | `/jarvis` keeps its own isolated conversation state and restores prior side-session history |
|
|
83
103
|
| **Live awareness** | Jarvis sees the current main-session summary plus a delta since the last `/jarvis` turn |
|
|
84
104
|
| **Permission-gated tools** | Local `read`, `bash`, `edit`, `write`, and configured native MCP stay off until you enable Repo tools |
|
|
@@ -97,6 +117,10 @@ flowchart LR
|
|
|
97
117
|
M -->|summary + recent delta| J
|
|
98
118
|
M <-->|independent memory controls| S[Shared local memory]
|
|
99
119
|
J <-->|independent memory controls| S
|
|
120
|
+
M -->|recording opt-in| A[Separate local history archive]
|
|
121
|
+
J -->|recording opt-in| A
|
|
122
|
+
A -. separately authorized model reads .-> M
|
|
123
|
+
A -. separately authorized model reads .-> J
|
|
100
124
|
J -->|Repo tools enabled| R[Local tools\nread • bash • edit • write]
|
|
101
125
|
J -->|Repo tools enabled| C[Configured native MCP\nside-owned connections]
|
|
102
126
|
J -. Note main .-> M
|
|
@@ -154,6 +178,8 @@ Requires **Pi 1.0.0** and **Node.js 22.19.0 or newer**. Version **1.6.0** suppor
|
|
|
154
178
|
`pi install` registers the package automatically. For local development, build and load `./dist/index.js` with `pi -e ./dist/index.js`.
|
|
155
179
|
**New in 1.7.0: shared memory is enabled by default in trusted projects**, including main Pi even if you never open the overlay. A first-use notice explains capture and recall. Already using another memory extension? Run `/jarvis-memory off` before your first prompt; this disables both main and Jarvis memory without deleting anything.
|
|
156
180
|
|
|
181
|
+
**New in 1.8.0: the separate full-session archive is OFF by default.** Nothing is imported or recorded by that subsystem until you opt in. See [Full-session archive](#full-session-archive).
|
|
182
|
+
|
|
157
183
|
### 3) Open Jarvis
|
|
158
184
|
|
|
159
185
|
```bash
|
|
@@ -207,6 +233,9 @@ Removes the selected scope so `/jarvis` thinking falls back through the remainin
|
|
|
207
233
|
### `/jarvis-memory`
|
|
208
234
|
Reports shared-memory status. Use `/jarvis-memory help` for controls and data-management commands. Memory controls default to **global**, unlike model/thinking controls. See [Shared memory](#shared-memory) below.
|
|
209
235
|
|
|
236
|
+
### `/jarvis-archive`
|
|
237
|
+
Reports the separate full-session archive's status. It defaults **OFF**, with independent capture and model-access controls. `/jarvis-archive help` documents enablement warnings, paging, explicit import, and deletion. See [Full-session archive](#full-session-archive).
|
|
238
|
+
|
|
210
239
|
### Side-session commands inside `/jarvis`
|
|
211
240
|
The `/jarvis` input handles a small set of built-in commands against the isolated side-session:
|
|
212
241
|
|
|
@@ -216,6 +245,69 @@ The `/jarvis` input handles a small set of built-in commands against the isolate
|
|
|
216
245
|
- `/tree --summarize <entry-id> [instructions]` navigates and summarizes the branch being left.
|
|
217
246
|
- `/new` starts a fresh `/jarvis` side-session without changing the main Pi session.
|
|
218
247
|
- `/memory …` or `/jarvis-memory …` manages shared memory immediately, without sending a model prompt or waiting for queued side work. Initial forms such as `/jarvis /memory off` are also handled locally, without booting a side session.
|
|
248
|
+
- `/archive …` or `/jarvis-archive …` manages the separate optional archive locally, without model/queue work; initial `/jarvis /archive …` works without booting a side session.
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Full-session archive
|
|
253
|
+
|
|
254
|
+
This is a **separate, optional subsystem**, not a change to shared memory's curated notes or bounded text captures. It is **OFF by default**, independent of Repo tools, Note main, Redirect, and overlay open/close. Model reads are **also off by default**, even after recording is enabled. No archive content is automatically injected into prompts.
|
|
255
|
+
|
|
256
|
+
### Enable only after reviewing the risks
|
|
257
|
+
|
|
258
|
+
```text
|
|
259
|
+
/jarvis-archive # status; no archive-record reads
|
|
260
|
+
/jarvis-archive --project on --confirm-sensitive # record here only
|
|
261
|
+
/jarvis-archive on --confirm-sensitive # enable globally
|
|
262
|
+
/jarvis-archive model-access on --confirm-sensitive # allow model search/read; recording alone doesn't
|
|
263
|
+
/jarvis-archive capture off # pause recording default, retain access
|
|
264
|
+
/jarvis-archive off # global MASTER OFF; keep stored data
|
|
265
|
+
/jarvis-archive clear --confirm-sensitive # remove global settings; fallback may re-enable
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Controls default to **global**; use `--project` for an override. Resolution is per-field project > global > defaults (`enabled: false`, `capture: true`, `modelAccess: false`), except an **explicit global off overrides every project**. `capture off` and `model-access off` set defaults that a project can override; inspect effective status. Use `clear --confirm-sensitive` to remove a scoped setting, never data. Malformed/unreadable settings and untrusted projects pause **all** archive access. Full off blocks even manual record inspection; recording-only/model-only pauses do not prevent explicit human reads. Separate files avoid interfering with memory/model settings:
|
|
269
|
+
|
|
270
|
+
- Global: `<active-agent-dir>/extensions/pi-jarvis-archive.json`
|
|
271
|
+
- Project: `.pi/jarvis-archive.json`
|
|
272
|
+
- Shape: `{ "archive": { "enabled": true, "capture": true, "modelAccess": false } }`
|
|
273
|
+
|
|
274
|
+
Enabling/model-access commands require the literal warning acknowledgment, and direct-file enablement shows a first-use warning. **This archive is unredacted plaintext and may retain passwords, tokens, private files, and sensitive tool output.** Model access can send retrieved data to the active provider. It is not a sandbox, encryption mechanism, or a substitute for carefully managing secrets.
|
|
275
|
+
|
|
276
|
+
### What “full” means
|
|
277
|
+
|
|
278
|
+
Accepted **new, finalized Pi journal entries** are retained as complete JSON, without memory's secret filtering, 16 KiB text cap, or 10,000-record eviction. This includes user/assistant/system messages, exposed thinking, tool calls/results and details, failed/aborted output that Pi retained, inline image payloads, custom entries, compaction/context edits, and branch metadata. Session headers retain provenance, including parent-session links. Search indexes textual content locally with SQLite FTS5; binary image data and opaque signatures are retained but not text-indexed. There is no OCR, embedding service, or background model call.
|
|
279
|
+
|
|
280
|
+
“Full” **does not mean an infallible wire/stream audit log**. Hidden provider reasoning, keystrokes, intermediate stream/tool updates, non-persisted commands/events, external attachment files, and output already truncated by Pi/tools are not recovered. Referenced files are **never automatically opened or copied**. Later message-redaction hooks run before capture. Raw history includes abandoned branches and superseded context, not just the effective current model context.
|
|
281
|
+
|
|
282
|
+
Recording begins after an activation baseline, never by importing pre-existing entries. Captures occur at finalized turn/settlement and supported session boundaries, not per token. The side owner takes a final snapshot of already-finalized entries before disposal, while recording remains authorized. Crashes, late shutdown hooks, unsupported journal APIs, failed storage, or permission transitions can leave gaps; warnings report observation/storage failures without replaying uncertain writes. Pending/disabled-period content is not backfilled after re-enable. Explicit **64 MiB raw-entry and indexing ceilings reject oversized work rather than truncating it**. Normalization uses bounded chunks; pathological Unicode combining/composition contexts beyond 64K UTF-16 units also reject explicitly. Conservative index budgeting can reject excessive whitespace/normalization expansion even if its final folded text would be smaller. No automatic eviction or strict total-disk quota is imposed: monitor space and prune deliberately. Large synchronous writes/indexing can pause the UI. Search/page order may change as other sessions append/delete records; pagination is not a frozen snapshot.
|
|
283
|
+
|
|
284
|
+
### Search and inspect
|
|
285
|
+
|
|
286
|
+
```text
|
|
287
|
+
/jarvis-archive search deployment decision
|
|
288
|
+
/jarvis-archive search --all --offset 20 deployment
|
|
289
|
+
/jarvis-archive session --all <session-id> 0
|
|
290
|
+
/jarvis-archive read --all <record-id> 0
|
|
291
|
+
/jarvis-archive read --all --metadata <record-id> 0
|
|
292
|
+
/jarvis-archive stats --all
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Search/session pages return bounded excerpts of normalized indexing text with IDs, project, lane, timestamps and parent entry IDs. Excerpts are not exact quotations; use `read` for original case and content. Follow `nextOffset` to continue. Exceptionally large/escape-heavy provenance is explicitly labeled with `abbreviated` field names, never allowed to block record access; `read --metadata` (model tool `part: "metadata"`) pages the exact original metadata. `read` returns complete raw JSON **through pages**; its offsets count Unicode codepoints, not bytes or UTF-16 units. Results are bounded to 24,000 bytes of JSON plus an untrusted-data notice; stored payloads are not shortened. Use explicit `--all` to access other projects. Models get only three read-only tools—`jarvis_archive_search`, `jarvis_archive_read`, and `jarvis_archive_session`—when model access is enabled. No model controls, import, or deletion tools exist. Tools recheck current permissions/trust/cancellation and reject stale definitions.
|
|
296
|
+
|
|
297
|
+
Global accessibility is within the **same active Pi agent directory**, not cloud sync or other users' machines. Project controls govern operations initiated here; existing records from a paused project remain accessible through explicit all-project queries from another allowed project. Disabling is not deletion. Returned model-tool results persist normally in Pi and can be captured again as part of a later journal entry.
|
|
298
|
+
|
|
299
|
+
### Explicit import and retention
|
|
300
|
+
|
|
301
|
+
```text
|
|
302
|
+
/jarvis-archive import --confirm-sensitive /absolute/path/to/session.jsonl
|
|
303
|
+
/jarvis-archive forget-session --confirm <session-id>
|
|
304
|
+
/jarvis-archive prune --confirm 2026-01-01T00:00:00.000Z
|
|
305
|
+
/jarvis-archive prune --all --confirm 2026-01-01T00:00:00.000Z
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
Import is **human-only**, requires enabled recording and an explicit regular v3 JSONL file, and preserves the source header's project/session identity—even if different from the current project. No directory scan or silent historical import occurs; legacy session versions require a separately reviewed conversion first. Completed entries survive a partial/cancelled import, with counts reported; duplicate entries are skipped, differing payloads for an existing identity are rejected, and originals are never modified. Deletion defaults to this project; `--all` is explicit. Stable identity tombstones prevent re-import of deleted entries, not every semantic copy or other previously unarchived entry.
|
|
309
|
+
|
|
310
|
+
Storage is lazy SQLite under `<active-agent-dir>/extensions/pi-jarvis-archive/archive.sqlite`, defaulting to `~/.pi/agent/extensions/pi-jarvis-archive/archive.sqlite`. Owned directories/files use private permissions where supported, with defensive link/type checks and concurrent-writer transactions. There is no background watcher: observed settings changes are propagated between mounted lanes, while other processes recheck at operation boundaries. Deletion does not erase original Pi files, prior search-result copies, already-sent model context or backups, and does not guarantee reclaimed disk space or forensic erasure. For a complete reset, stop all Pi processes using the store and remove only its archive directory yourself; that also removes tombstones. Shared memory stays separate and unchanged. To stop both Jarvis persistence layers, use both `/jarvis-archive off` and `/jarvis-memory off`; neither disables Pi's original session transcripts.
|
|
219
311
|
|
|
220
312
|
---
|
|
221
313
|
|
|
@@ -225,7 +317,7 @@ Main Pi and Jarvis use **one local memory service**, independent of the overlay
|
|
|
225
317
|
|
|
226
318
|
### What is remembered
|
|
227
319
|
|
|
228
|
-
- **
|
|
320
|
+
- **Bounded conversation captures (not the optional full-session archive):** only newly finalized user/assistant text observed after loading this feature, labeled with project, main/Jarvis lane, session ID, event identity and timestamps. No silent historical import or reconstruction from old session files.
|
|
229
321
|
- **Curated notes:** your active model can save concise preferences, corrections, project decisions and references during normal foreground work. Stable scoped titles update/deduplicate notes. You can save or edit notes explicitly too. Curation depends on the model choosing the tool; it is not a separate background summarizer.
|
|
230
322
|
- **Bounded recall:** a small request-local selection of global/current-project notes and matching conversation excerpts, using local keyword search. Other projects are available through explicit `search --all` or the model's cross-project search tool. Project scope uses the canonical working directory, not a remote repository name; separate worktrees remain separate scopes unless a note is global.
|
|
231
323
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { ArchivePolicy, ArchiveScope } from "./archive-types.js";
|
|
2
|
+
type Scope = ArchiveScope;
|
|
3
|
+
/** Caller-spelled settings path, without I/O. Access canonicalizes only the chosen root. */
|
|
4
|
+
export declare function archiveConfigPath(cwd: string, agentDir: string, scope: Scope): string;
|
|
5
|
+
/** Reads settings only. Archiving defaults off; trust/read/validation failures disable every permission. */
|
|
6
|
+
export declare function resolveArchivePolicy(cwd: string, agentDir: string, trusted?: boolean): {
|
|
7
|
+
policy: ArchivePolicy;
|
|
8
|
+
errors: string[];
|
|
9
|
+
};
|
|
10
|
+
/** Merges only supplied fields into this scope; never materializes inherited/default values. */
|
|
11
|
+
export declare function saveArchivePolicy(cwd: string, agentDir: string, scope: Scope, patch: Partial<ArchivePolicy>): void;
|
|
12
|
+
/** Removes only archive controls. Corrupt files are never repaired or removed. */
|
|
13
|
+
export declare function clearArchivePolicy(cwd: string, agentDir: string, scope: Scope): void;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=archive-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive-config.d.ts","sourceRoot":"","sources":["../archive-config.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEtE,KAAK,KAAK,GAAG,YAAY,CAAC;AAS1B,4FAA4F;AAC5F,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,CAGrF;AAED,4GAA4G;AAC5G,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,UAAO,GAAG;IACpF,MAAM,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAC;CACxC,CAoBA;AAED,gGAAgG;AAChG,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,IAAI,CAOlH;AAED,kFAAkF;AAClF,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAMpF"}
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { closeSync, constants, fstatSync, fsyncSync, lstatSync, mkdirSync, openSync, readSync, realpathSync, renameSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
2
|
+
import { isUtf8 } from "node:buffer";
|
|
3
|
+
import { randomUUID } from "node:crypto";
|
|
4
|
+
import { basename, dirname, join, parse, resolve } from "node:path";
|
|
5
|
+
const FIELDS = ["enabled", "capture", "modelAccess"];
|
|
6
|
+
const CONFIG_LIMIT_BYTES = 1024 * 1024;
|
|
7
|
+
const LOCK_WAIT_MS = 2_000;
|
|
8
|
+
const LOCK_POLL_MS = 20;
|
|
9
|
+
const sleep = new Int32Array(new SharedArrayBuffer(4));
|
|
10
|
+
const noFollow = constants.O_NOFOLLOW ?? 0;
|
|
11
|
+
/** Caller-spelled settings path, without I/O. Access canonicalizes only the chosen root. */
|
|
12
|
+
export function archiveConfigPath(cwd, agentDir, scope) {
|
|
13
|
+
if (scope !== "global" && scope !== "project")
|
|
14
|
+
throw new Error("Invalid archive settings scope.");
|
|
15
|
+
return scope === "global" ? join(agentDir, "extensions", "pi-jarvis-archive.json") : join(cwd, ".pi", "jarvis-archive.json");
|
|
16
|
+
}
|
|
17
|
+
/** Reads settings only. Archiving defaults off; trust/read/validation failures disable every permission. */
|
|
18
|
+
export function resolveArchivePolicy(cwd, agentDir, trusted = true) {
|
|
19
|
+
const errors = [];
|
|
20
|
+
const read = (scope) => {
|
|
21
|
+
try {
|
|
22
|
+
return parsePolicy(readConfig(settingsPath(cwd, agentDir, scope))?.archive);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// Never include parser messages, config contents, paths or underlying I/O errors.
|
|
26
|
+
errors.push(`Cannot read ${scope} archive settings; archive is disabled.`);
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const global = read("global");
|
|
31
|
+
const project = read("project");
|
|
32
|
+
if (errors.length || !trusted)
|
|
33
|
+
return { policy: { enabled: false, capture: false, modelAccess: false }, errors };
|
|
34
|
+
const base = { enabled: false, capture: true, modelAccess: false, ...global };
|
|
35
|
+
const policy = { ...base, ...project };
|
|
36
|
+
// Only explicit global enabled=false is a master switch; other fields remain independent preferences.
|
|
37
|
+
if (global.enabled === false)
|
|
38
|
+
policy.enabled = false;
|
|
39
|
+
return { policy, errors };
|
|
40
|
+
}
|
|
41
|
+
/** Merges only supplied fields into this scope; never materializes inherited/default values. */
|
|
42
|
+
export function saveArchivePolicy(cwd, agentDir, scope, patch) {
|
|
43
|
+
const parsed = parsePatch(patch);
|
|
44
|
+
changeConfig(cwd, agentDir, scope, (config) => {
|
|
45
|
+
if (!Object.keys(parsed).length)
|
|
46
|
+
return false;
|
|
47
|
+
config.archive = { ...config.archive, ...parsed };
|
|
48
|
+
return true;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/** Removes only archive controls. Corrupt files are never repaired or removed. */
|
|
52
|
+
export function clearArchivePolicy(cwd, agentDir, scope) {
|
|
53
|
+
changeConfig(cwd, agentDir, scope, (config) => {
|
|
54
|
+
if (!Object.hasOwn(config, "archive"))
|
|
55
|
+
return false;
|
|
56
|
+
delete config.archive;
|
|
57
|
+
return true;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
function parsePolicy(value) {
|
|
61
|
+
if (value === undefined)
|
|
62
|
+
return {};
|
|
63
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
64
|
+
throw new Error("Invalid archive controls.");
|
|
65
|
+
const policy = {};
|
|
66
|
+
for (const field of FIELDS) {
|
|
67
|
+
if (!Object.hasOwn(value, field))
|
|
68
|
+
continue;
|
|
69
|
+
const setting = value[field];
|
|
70
|
+
if (typeof setting !== "boolean")
|
|
71
|
+
throw new Error("Invalid archive controls.");
|
|
72
|
+
policy[field] = setting;
|
|
73
|
+
}
|
|
74
|
+
return policy;
|
|
75
|
+
}
|
|
76
|
+
function parsePatch(patch) {
|
|
77
|
+
if (!patch || typeof patch !== "object" || Array.isArray(patch)
|
|
78
|
+
|| Object.keys(patch).some((key) => !FIELDS.includes(key))) {
|
|
79
|
+
throw new Error("Invalid archive controls patch.");
|
|
80
|
+
}
|
|
81
|
+
return parsePolicy(patch);
|
|
82
|
+
}
|
|
83
|
+
function missing(error) {
|
|
84
|
+
return error?.code === "ENOENT";
|
|
85
|
+
}
|
|
86
|
+
/** Resolve user-selected roots (including ancestor links), but never appended settings paths. */
|
|
87
|
+
function settingsPath(cwd, agentDir, scope) {
|
|
88
|
+
// Validate scope before choosing/canonicalizing a root.
|
|
89
|
+
archiveConfigPath(cwd, agentDir, scope);
|
|
90
|
+
const root = canonicalRoot(scope === "global" ? agentDir : cwd);
|
|
91
|
+
return scope === "global" ? join(root, "extensions", "pi-jarvis-archive.json") : join(root, ".pi", "jarvis-archive.json");
|
|
92
|
+
}
|
|
93
|
+
/** Missing roots inherit the real path of their nearest existing directory ancestor. */
|
|
94
|
+
function canonicalRoot(path) {
|
|
95
|
+
let current = resolve(path);
|
|
96
|
+
const suffix = [];
|
|
97
|
+
for (;;) {
|
|
98
|
+
try {
|
|
99
|
+
lstatSync(current);
|
|
100
|
+
}
|
|
101
|
+
catch (error) {
|
|
102
|
+
if (!missing(error))
|
|
103
|
+
throw error;
|
|
104
|
+
const parent = dirname(current);
|
|
105
|
+
if (parent === current)
|
|
106
|
+
throw error;
|
|
107
|
+
suffix.unshift(basename(current));
|
|
108
|
+
current = parent;
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
// An existing dangling link or a nondirectory root is an error, not a missing config.
|
|
112
|
+
const canonical = realpathSync(current);
|
|
113
|
+
if (!lstatSync(canonical).isDirectory())
|
|
114
|
+
throw new Error("Unsafe archive settings root.");
|
|
115
|
+
return join(canonical, ...suffix);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/** Validate the canonical ancestry, missing root components and appended settings directories. */
|
|
119
|
+
function directories(path, create) {
|
|
120
|
+
const absolute = resolve(path);
|
|
121
|
+
const root = parse(absolute).root;
|
|
122
|
+
const parts = [];
|
|
123
|
+
let current = absolute;
|
|
124
|
+
while (current !== root) {
|
|
125
|
+
parts.push(current);
|
|
126
|
+
current = dirname(current);
|
|
127
|
+
}
|
|
128
|
+
parts.push(root);
|
|
129
|
+
for (const directory of parts.reverse()) {
|
|
130
|
+
let stat;
|
|
131
|
+
try {
|
|
132
|
+
stat = lstatSync(directory);
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
if (!missing(error))
|
|
136
|
+
throw error;
|
|
137
|
+
if (!create)
|
|
138
|
+
return false;
|
|
139
|
+
try {
|
|
140
|
+
mkdirSync(directory, { mode: 0o700 });
|
|
141
|
+
}
|
|
142
|
+
catch (mkdirError) {
|
|
143
|
+
if (mkdirError?.code !== "EEXIST")
|
|
144
|
+
throw mkdirError;
|
|
145
|
+
}
|
|
146
|
+
stat = lstatSync(directory);
|
|
147
|
+
}
|
|
148
|
+
if (!stat.isDirectory() || stat.isSymbolicLink())
|
|
149
|
+
throw new Error("Unsafe archive settings directory.");
|
|
150
|
+
}
|
|
151
|
+
return true;
|
|
152
|
+
}
|
|
153
|
+
function regularFile(path) {
|
|
154
|
+
let stat;
|
|
155
|
+
try {
|
|
156
|
+
stat = lstatSync(path);
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
if (missing(error))
|
|
160
|
+
return undefined;
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1)
|
|
164
|
+
throw new Error("Unsafe archive settings file.");
|
|
165
|
+
return stat;
|
|
166
|
+
}
|
|
167
|
+
function readConfig(path) {
|
|
168
|
+
if (!directories(dirname(path), false))
|
|
169
|
+
return undefined;
|
|
170
|
+
const stat = regularFile(path);
|
|
171
|
+
if (!stat)
|
|
172
|
+
return undefined;
|
|
173
|
+
if (stat.size > CONFIG_LIMIT_BYTES)
|
|
174
|
+
throw new Error("Archive settings exceed the size limit.");
|
|
175
|
+
// O_NONBLOCK prevents a raced special file from blocking before fstat rejects it.
|
|
176
|
+
const fd = openSync(path, constants.O_RDONLY | noFollow | constants.O_NONBLOCK);
|
|
177
|
+
let text;
|
|
178
|
+
try {
|
|
179
|
+
const opened = fstatSync(fd);
|
|
180
|
+
if (!opened.isFile() || opened.nlink !== 1 || opened.dev !== stat.dev || opened.ino !== stat.ino) {
|
|
181
|
+
throw new Error("Archive settings changed while opening.");
|
|
182
|
+
}
|
|
183
|
+
if (opened.size > CONFIG_LIMIT_BYTES)
|
|
184
|
+
throw new Error("Archive settings exceed the size limit.");
|
|
185
|
+
// A bounded buffer also handles growth after fstat: readFileSync could allocate
|
|
186
|
+
// without limit in that race. The extra byte detects growth without reading it all.
|
|
187
|
+
const bytes = Buffer.alloc(opened.size + 1);
|
|
188
|
+
let length = 0;
|
|
189
|
+
while (length < bytes.length) {
|
|
190
|
+
const count = readSync(fd, bytes, length, bytes.length - length, null);
|
|
191
|
+
if (!count)
|
|
192
|
+
break;
|
|
193
|
+
length += count;
|
|
194
|
+
}
|
|
195
|
+
if (length !== opened.size)
|
|
196
|
+
throw new Error("Archive settings changed while reading.");
|
|
197
|
+
if (!isUtf8(bytes.subarray(0, length)))
|
|
198
|
+
throw new Error("Invalid archive settings encoding.");
|
|
199
|
+
text = bytes.toString("utf8", 0, length);
|
|
200
|
+
}
|
|
201
|
+
finally {
|
|
202
|
+
closeSync(fd);
|
|
203
|
+
}
|
|
204
|
+
let config;
|
|
205
|
+
try {
|
|
206
|
+
config = JSON.parse(text);
|
|
207
|
+
}
|
|
208
|
+
catch {
|
|
209
|
+
throw new Error("Invalid archive settings JSON.");
|
|
210
|
+
}
|
|
211
|
+
if (!config || typeof config !== "object" || Array.isArray(config))
|
|
212
|
+
throw new Error("Invalid archive settings object.");
|
|
213
|
+
const record = config;
|
|
214
|
+
// Validate controls even for clear calls; no operation may repair an invalid file.
|
|
215
|
+
parsePolicy(record.archive);
|
|
216
|
+
return record;
|
|
217
|
+
}
|
|
218
|
+
function changeConfig(cwd, agentDir, scope, change) {
|
|
219
|
+
try {
|
|
220
|
+
const path = settingsPath(cwd, agentDir, scope);
|
|
221
|
+
// Avoid creating directories/lock files for absent clears or already-applied changes.
|
|
222
|
+
const existing = readConfig(path);
|
|
223
|
+
if (!change({ ...existing }))
|
|
224
|
+
return;
|
|
225
|
+
directories(dirname(path), true);
|
|
226
|
+
withLock(path, () => {
|
|
227
|
+
const config = readConfig(path) ?? {};
|
|
228
|
+
if (change(config))
|
|
229
|
+
writeConfig(path, config);
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
throw new Error(`Cannot update ${scope} archive settings.`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
/** Cooperative lock for archive writers only. Crashed writers leave locks; never steal a live lock. */
|
|
237
|
+
function withLock(path, run) {
|
|
238
|
+
const lock = `${path}.archive.lock`;
|
|
239
|
+
const deadline = performance.now() + LOCK_WAIT_MS;
|
|
240
|
+
let fd;
|
|
241
|
+
for (;;) {
|
|
242
|
+
try {
|
|
243
|
+
fd = openSync(lock, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | noFollow, 0o600);
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
if (error?.code !== "EEXIST")
|
|
248
|
+
throw error;
|
|
249
|
+
regularFile(lock); // Reject symlink/nonregular locks instead of waiting on them.
|
|
250
|
+
const remaining = deadline - performance.now();
|
|
251
|
+
if (remaining <= 0)
|
|
252
|
+
throw new Error("Archive settings lock timed out.");
|
|
253
|
+
Atomics.wait(sleep, 0, 0, Math.min(LOCK_POLL_MS, remaining));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
let owned;
|
|
257
|
+
try {
|
|
258
|
+
owned = fstatSync(fd);
|
|
259
|
+
if (!owned.isFile() || owned.nlink !== 1)
|
|
260
|
+
throw new Error("Unsafe archive settings lock.");
|
|
261
|
+
run();
|
|
262
|
+
}
|
|
263
|
+
finally {
|
|
264
|
+
try {
|
|
265
|
+
closeSync(fd);
|
|
266
|
+
}
|
|
267
|
+
catch { /* Cleanup must not mask the primary failure. */ }
|
|
268
|
+
try {
|
|
269
|
+
const current = lstatSync(lock);
|
|
270
|
+
if (owned && current.dev === owned.dev && current.ino === owned.ino && current.isFile() && !current.isSymbolicLink())
|
|
271
|
+
unlinkSync(lock);
|
|
272
|
+
}
|
|
273
|
+
catch { /* Failed cleanup can leave a lock; bounded waits still fail closed. */ }
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
function writeConfig(path, config) {
|
|
277
|
+
const text = `${JSON.stringify(config, null, "\t")}\n`;
|
|
278
|
+
if (Buffer.byteLength(text, "utf8") > CONFIG_LIMIT_BYTES)
|
|
279
|
+
throw new Error("Archive settings exceed the size limit.");
|
|
280
|
+
const temporary = `${path}.${randomUUID()}.tmp`;
|
|
281
|
+
let fd;
|
|
282
|
+
let created = false;
|
|
283
|
+
try {
|
|
284
|
+
fd = openSync(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | noFollow, 0o600);
|
|
285
|
+
created = true;
|
|
286
|
+
writeFileSync(fd, text, "utf8");
|
|
287
|
+
fsyncSync(fd);
|
|
288
|
+
closeSync(fd);
|
|
289
|
+
fd = undefined;
|
|
290
|
+
directories(dirname(path), false);
|
|
291
|
+
regularFile(path); // Recheck the target before replacement; never replace a symlink.
|
|
292
|
+
renameSync(temporary, path);
|
|
293
|
+
created = false;
|
|
294
|
+
}
|
|
295
|
+
finally {
|
|
296
|
+
if (fd !== undefined) {
|
|
297
|
+
try {
|
|
298
|
+
closeSync(fd);
|
|
299
|
+
}
|
|
300
|
+
catch { /* Keep the primary failure. */ }
|
|
301
|
+
}
|
|
302
|
+
if (created) {
|
|
303
|
+
try {
|
|
304
|
+
unlinkSync(temporary);
|
|
305
|
+
}
|
|
306
|
+
catch { /* Keep the primary failure. */ }
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=archive-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive-config.js","sourceRoot":"","sources":["../archive-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { ExtensionContext, ExtensionFactory } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { ArchivePolicy } from "./archive-types.js";
|
|
3
|
+
export declare const ARCHIVE_TOOL_NAMES: readonly ["jarvis_archive_search", "jarvis_archive_read", "jarvis_archive_session"];
|
|
4
|
+
type PageParameters = {
|
|
5
|
+
scope?: "current" | "all";
|
|
6
|
+
offset?: number;
|
|
7
|
+
limit?: number;
|
|
8
|
+
};
|
|
9
|
+
/** Structural contract: the shared service is owned by the host, not a lane. */
|
|
10
|
+
export interface ArchiveExtensionService {
|
|
11
|
+
readonly epoch: number;
|
|
12
|
+
policy(ctx: ExtensionContext): ArchivePolicy;
|
|
13
|
+
onChange(listener: () => void): () => void;
|
|
14
|
+
capture(entry: unknown, lane: "main" | "jarvis", ctx: ExtensionContext): void;
|
|
15
|
+
search(params: PageParameters & {
|
|
16
|
+
query: string;
|
|
17
|
+
sessionId?: string;
|
|
18
|
+
}, ctx: ExtensionContext, model?: boolean): string;
|
|
19
|
+
read(params: PageParameters & {
|
|
20
|
+
id: string;
|
|
21
|
+
part?: "entry" | "metadata";
|
|
22
|
+
}, ctx: ExtensionContext, model?: boolean): string;
|
|
23
|
+
session(params: PageParameters & {
|
|
24
|
+
sessionId: string;
|
|
25
|
+
}, ctx: ExtensionContext, model?: boolean): string;
|
|
26
|
+
close(): void;
|
|
27
|
+
}
|
|
28
|
+
export interface ArchiveExtensionOptions {
|
|
29
|
+
lifetimeSignal?: AbortSignal;
|
|
30
|
+
isProjectTrusted?: () => boolean;
|
|
31
|
+
onToolsChanged?: () => void;
|
|
32
|
+
/** Owner invokes this before SDK disposal/permission lifetime revocation. */
|
|
33
|
+
registerFinalSnapshot?: (snapshot: () => void) => void;
|
|
34
|
+
}
|
|
35
|
+
/** Mount separately in main and Jarvis. No streams, history import, or recall. */
|
|
36
|
+
export declare function createArchiveExtensionFactory(service: ArchiveExtensionService, lane: "main" | "jarvis", options?: ArchiveExtensionOptions): ExtensionFactory;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=archive-extension.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive-extension.d.ts","sourceRoot":"","sources":["../archive-extension.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAgB,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACxG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,eAAO,MAAM,kBAAkB,qFAAsF,CAAC;AAEtH,KAAK,cAAc,GAAG;IAAE,KAAK,CAAC,EAAE,SAAS,GAAG,KAAK,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACrF,gFAAgF;AAChF,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,GAAG,EAAE,gBAAgB,GAAG,aAAa,CAAC;IAC7C,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IAC3C,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC9E,MAAM,CAAC,MAAM,EAAE,cAAc,GAAG;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,EAAE,gBAAgB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACvH,IAAI,CAAC,MAAM,EAAE,cAAc,GAAG;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,OAAO,GAAG,UAAU,CAAA;KAAE,EAAE,GAAG,EAAE,gBAAgB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3H,OAAO,CAAC,MAAM,EAAE,cAAc,GAAG;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,EAAE,gBAAgB,EAAE,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IACxG,KAAK,IAAI,IAAI,CAAC;CACd;AACD,MAAM,WAAW,uBAAuB;IACvC,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,gBAAgB,CAAC,EAAE,MAAM,OAAO,CAAC;IACjC,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,6EAA6E;IAC7E,qBAAqB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;CACvD;AAMD,kFAAkF;AAClF,wBAAgB,6BAA6B,CAC5C,OAAO,EAAE,uBAAuB,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,OAAO,GAAE,uBAA4B,GAC9F,gBAAgB,CAoQlB"}
|