@volter/supercode-interchange 0.1.22 → 0.1.24
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/LICENSE-diffy-MIT +23 -0
- package/README.md +422 -2
- package/channel-records.mjs +71 -0
- package/channel-session-counts.mjs +81 -0
- package/channels-read.mjs +90 -0
- package/corpus-audit-records.mjs +192 -0
- package/corpus-audit-render.mjs +47 -0
- package/corpus-audit-schema.mjs +89 -0
- package/corpus-audit.d.ts +16 -0
- package/corpus-audit.mjs +132 -0
- package/file-io.mjs +21 -2
- package/harness-settings.mjs +19 -0
- package/hermes-fire-links.mjs +135 -0
- package/hermes-fires.mjs +106 -0
- package/hermes-read-home.d.ts +3 -0
- package/hermes-read-home.mjs +235 -0
- package/hermes-read-store.mjs +49 -0
- package/hermes-read-validation.mjs +170 -0
- package/hermes-read-workflow.mjs +164 -0
- package/hermes-read-yaml.mjs +68 -0
- package/hermes-store.mjs +1 -1
- package/homes.mjs +2 -2
- package/index.d.ts +14 -1
- package/index.mjs +1 -1
- package/inspection-builtin-tools.json +261 -0
- package/inspection-config-fields.json +765 -0
- package/inspection-schemas.d.ts +4 -0
- package/inspection-schemas.mjs +117 -0
- package/job-notepad-read.mjs +97 -0
- package/jobs-control.mjs +250 -0
- package/jobs-read.mjs +198 -0
- package/jsonl.mjs +4 -3
- package/memory-show.mjs +187 -0
- package/metadata.mjs +45 -3
- package/native-json.mjs +46 -3
- package/ontology-contracts.d.ts +5 -0
- package/ontology-contracts.mjs +29 -0
- package/ontology-operations.json +198 -0
- package/ontology-schemas.json +7946 -0
- package/openclaw-jobs-read.mjs +117 -0
- package/openclaw-profile-home.mjs +142 -0
- package/orchestrator-read-records.mjs +112 -0
- package/orchestrator-store.mjs +21 -9
- package/package.json +59 -4
- package/parity-ledger.json +6984 -0
- package/parity-orchestration.json +5538 -0
- package/parity-report.d.ts +7 -0
- package/parity-report.mjs +46 -0
- package/preset-profiles.mjs +27 -0
- package/profile-command.mjs +32 -0
- package/profile-orchestrator-door.mjs +104 -0
- package/profile-paths.mjs +25 -0
- package/profiles-control.mjs +98 -0
- package/profiles-read.mjs +119 -0
- package/reduction-attribution.mjs +54 -0
- package/reduction-diff.mjs +165 -0
- package/reduction-log.mjs +177 -0
- package/reduction-view.mjs +145 -0
- package/retained-projection.mjs +9 -0
- package/routes-read.mjs +103 -0
- package/runs-read.mjs +224 -0
- package/session-activity.d.ts +23 -0
- package/session-activity.mjs +124 -0
- package/session-append-scan.mjs +27 -17
- package/session-branch-handoff.mjs +115 -0
- package/session-claude-graph.mjs +29 -7
- package/session-claude-index.mjs +732 -114
- package/session-claude-runtime.d.ts +28 -0
- package/session-claude-runtime.mjs +171 -6
- package/session-claude-scan-store.mjs +164 -0
- package/session-claude.mjs +9 -0
- package/session-codex-activity.d.ts +6 -0
- package/session-codex-activity.mjs +120 -0
- package/session-codex-window.mjs +24 -4
- package/session-config-scan.mjs +141 -0
- package/session-convert.d.ts +33 -0
- package/session-convert.mjs +179 -0
- package/session-emission-version.json +1 -0
- package/session-file.mjs +11 -1
- package/session-follower.mjs +17 -5
- package/session-fresh-id.mjs +15 -0
- package/session-hermes-import.mjs +61 -0
- package/session-hermes.mjs +1 -1
- package/session-import.mjs +37 -0
- package/session-inspect.d.ts +18 -0
- package/session-inspect.mjs +122 -0
- package/session-machine-tree.d.ts +33 -0
- package/session-machine-tree.mjs +274 -0
- package/session-materialize-files.mjs +78 -0
- package/session-materialize-opencode.mjs +137 -0
- package/session-materialize.mjs +186 -0
- package/session-message.mjs +85 -0
- package/session-model.d.ts +9 -0
- package/session-model.mjs +1 -0
- package/session-opencode-store.mjs +39 -3
- package/session-path.mjs +6 -3
- package/session-pi-content.mjs +7 -2
- package/session-read.d.ts +134 -2
- package/session-read.mjs +86 -9
- package/session-recorded-config.mjs +3 -2
- package/session-records.mjs +12 -6
- package/session-residue-store.mjs +90 -0
- package/session-residue.mjs +150 -0
- package/session-resume-instructions.mjs +1 -1
- package/session-saved-read.mjs +105 -0
- package/session-transfer.mjs +141 -0
- package/session-views.mjs +1 -0
- package/session-write-claude.mjs +135 -0
- package/session-write-codex.mjs +146 -0
- package/session-write-gemini.mjs +77 -0
- package/session-write-goose.mjs +99 -0
- package/session-write-grok.mjs +70 -0
- package/session-write-native.mjs +41 -0
- package/session-write-opencode.mjs +197 -0
- package/session-write-pi.mjs +130 -0
- package/session-write-residue.mjs +19 -0
- package/session-write-utils.mjs +77 -0
- package/session-write.d.ts +10 -0
- package/session-write.mjs +37 -0
- package/skill-toml.mjs +80 -0
- package/skills-control.mjs +193 -0
- package/skills-list.mjs +237 -0
- package/source-files.mjs +12 -2
- package/sqlite-reader.mjs +134 -18
- package/support-registry.json +402 -0
- package/support-report.mjs +69 -0
- package/trigger-records.mjs +77 -0
- package/triggers-read.mjs +67 -0
- package/workflow-read.mjs +165 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
Permission is hereby granted, free of charge, to any
|
|
2
|
+
person obtaining a copy of this software and associated
|
|
3
|
+
documentation files (the "Software"), to deal in the
|
|
4
|
+
Software without restriction, including without
|
|
5
|
+
limitation the rights to use, copy, modify, merge,
|
|
6
|
+
publish, distribute, sublicense, and/or sell copies of
|
|
7
|
+
the Software, and to permit persons to whom the Software
|
|
8
|
+
is furnished to do so, subject to the following
|
|
9
|
+
conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice
|
|
12
|
+
shall be included in all copies or substantial portions
|
|
13
|
+
of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
|
16
|
+
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
|
17
|
+
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
18
|
+
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
|
19
|
+
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
20
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
|
22
|
+
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
23
|
+
DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
1
|
# Supercode interchange
|
|
2
2
|
|
|
3
|
+
The `./parity-report` subpath owns the frozen capability/orchestration ledger
|
|
4
|
+
report printed by `supercode harness parity`. The native evidence-audit helpers
|
|
5
|
+
retain their configuration/tool/runtime consumers and read the same unchanged
|
|
6
|
+
ledgers. This report does not execute the evidence resolver or verify runtime
|
|
7
|
+
support. [Original records](../../docs/evidence/parity-report-port-2026-10-09.md) and
|
|
8
|
+
[current-main recordings](../../docs/evidence/parity-report-integration-2026-10-15.md)
|
|
9
|
+
retain their distinct source and native/handoff scopes.
|
|
10
|
+
|
|
11
|
+
The `./ontology-contracts` subpath owns the committed schema and operation
|
|
12
|
+
inventory printed by `supercode ontology schema|operations`. Record-specific
|
|
13
|
+
definition sets and native JSON numeric facts are retained. The orchestrator
|
|
14
|
+
type generator and harness SDK operation generator read these contracts by
|
|
15
|
+
default; an explicit `SUPERCODE_BIN` still selects an external product's output.
|
|
16
|
+
The native schema functions and derives retire. Native serde models and operation
|
|
17
|
+
execution retain their unported runtime/codec owners. [Original records](../../docs/evidence/ontology-contracts-port-2026-10-09.md)
|
|
18
|
+
and [current-main integration](../../docs/evidence/ontology-contracts-integration-2026-10-15.md)
|
|
19
|
+
retain distinct scopes; schema availability is not runtime support.
|
|
20
|
+
|
|
3
21
|
Read-only metadata and discovery projection for the daemon-owned session index in
|
|
4
22
|
[TypeScript architecture step 4](../../docs/plans/typescript-architecture.md#order).
|
|
5
23
|
The port branch routes discovery and index windows through this library and the Teams owner.
|
|
6
24
|
[Dated private Mac/Windows observations](../../docs/evidence/session-index-owner-2026-10-08.md)
|
|
7
25
|
cover selected small homes; publication, all-format and large-home qualification remain open.
|
|
8
|
-
Full session translation codecs remain at their later boundary.
|
|
9
26
|
|
|
10
27
|
The `./session-model` subpath supplies the step-5 read service's typed message
|
|
11
28
|
and retained-session representation, native raw-line framing, normalized views,
|
|
@@ -67,8 +84,24 @@ the external revert sidecar and verifies both identities; malformed JSON columns
|
|
|
67
84
|
remain diagnostic. Legacy JSON-tree directories retain their native
|
|
68
85
|
unsupported-source refusal. The small envelope observation does not qualify
|
|
69
86
|
concurrent SQLite/revert changes or all compaction/tool shapes.
|
|
87
|
+
Foreign-store snapshots share a 256 MiB cumulative row charge across scalar,
|
|
88
|
+
iterator and array reads. Accepted native rows remain complete; capacity
|
|
89
|
+
refuses the snapshot with the existing unreadable-session code. Failed close
|
|
90
|
+
keeps the exact owner and refuses successor snapshots. The
|
|
91
|
+
[row-admission source record](../../docs/evidence/session-store-row-admission-2026-10-12.md)
|
|
92
|
+
separates this charge from SQLite's own allocations and runtime qualification.
|
|
70
93
|
The path layer selects formats structurally, pins native store selectors and
|
|
71
|
-
reads compressed transcripts through Node's zstd support.
|
|
94
|
+
reads compressed transcripts through Node's zstd support.
|
|
95
|
+
The read library admits compressed input, decompressed output and an individual
|
|
96
|
+
physical record at the smaller of Node's Buffer capacity and four times its
|
|
97
|
+
single-string UTF-16 capacity. Oversize reads refuse with `SESSION_UNREADABLE`
|
|
98
|
+
at that byte budget; accepted bytes stay complete and this
|
|
99
|
+
reader does not modify the source. This bounds these byte owners, rather than
|
|
100
|
+
the reconstructed graph or total process memory. The
|
|
101
|
+
[admission record](../../docs/evidence/session-read-byte-admission-2026-10-12.md)
|
|
102
|
+
states current qualification limits.
|
|
103
|
+
|
|
104
|
+
Native sidecars
|
|
72
105
|
validate framing and retain malformed appended turns as raw parse loss.
|
|
73
106
|
Grok summaries and OpenClaw path profiles keep their source meanings. Display
|
|
74
107
|
reads retain the native byte-window, human-anchor and fixed-byte-anchor rules;
|
|
@@ -110,6 +143,30 @@ cover recorded posture/policies through npm and operator streams, including
|
|
|
110
143
|
unknown posture for malformed records. The manifest's other branches,
|
|
111
144
|
corpus/scale, concurrent reads and independent source review remain open.
|
|
112
145
|
|
|
146
|
+
Plain Claude and Codex recorded-configuration reads retain append-validated
|
|
147
|
+
header and runtime folds. Unchanged reads parse no old records; appended complete
|
|
148
|
+
lines extend the folds, while an unfinished final line belongs only to its current
|
|
149
|
+
answer. Permission mode still requires a valid complete runtime reconstruction.
|
|
150
|
+
A runtime call that retroactively names an earlier result rebuilds the fold;
|
|
151
|
+
replacement, truncation and prefix changes use the existing append-scan validation.
|
|
152
|
+
The configuration cache keeps at most 32 files and charges 400,000 retained
|
|
153
|
+
reference/runtime entries, with the current-scan exception used by Claude scans.
|
|
154
|
+
It retains no ordinary message bodies. Claude option-based message windows now
|
|
155
|
+
share the retained replay scan, including native metadata residue. Requested
|
|
156
|
+
payloads still cost their returned size; no full-session payload cache is added.
|
|
157
|
+
|
|
158
|
+
Daemon one-shot reads share a retained worker across caller transports. A caller's
|
|
159
|
+
deadline rejects its wait without terminating that worker; duplicate pending
|
|
160
|
+
reads share one parse, and 64 distinct reads bound the pending queue. Followers
|
|
161
|
+
keep their own subscriptions. Closing a caller stream releases its followers,
|
|
162
|
+
while a daemon-owned scan finishes against its bounded file snapshot. One-shot
|
|
163
|
+
mail enrichment retains no resolved history: at most 16 in-flight session reads
|
|
164
|
+
are shared, with a 250 ms optional wait per result. Follower histories are removed
|
|
165
|
+
when their last subscription ends. Parse-fold retention is independent. Actual
|
|
166
|
+
worker failure and daemon shutdown still release its state. These are source
|
|
167
|
+
changes; large-transcript runtime and deadline qualification remain unperformed.
|
|
168
|
+
|
|
169
|
+
|
|
113
170
|
`sessions.launch_agent` reads `<harness home>/supercode/launches/<session id>.json`
|
|
114
171
|
in the same caller-owned load lane. Claude `projects` and Codex `sessions`
|
|
115
172
|
ancestors select the transcript's recorded home, independent of current vendor
|
|
@@ -186,9 +243,372 @@ read-only and observe DB/WAL changes. OpenCode and Goose compare native row mark
|
|
|
186
243
|
facts for query-time selection; orchestrator rows keep routing keys and the source change cursor. Codex names
|
|
187
244
|
and history topics, and late Claude rename aliases, have separate append-aware ledgers.
|
|
188
245
|
|
|
246
|
+
`readSourceJson(path, metrics, previous)` can reuse an earlier result produced by
|
|
247
|
+
this process when the current open file has the same fingerprint. The handle
|
|
248
|
+
and path are still verified, and readability failures remain failures. A copied
|
|
249
|
+
or deserialized result is reread: native integer-versus-float facts belong to the
|
|
250
|
+
original parsed object. The machine owner keeps this raw cache in memory and
|
|
251
|
+
persists only derived registry facts. [Source and package evidence](../../docs/evidence/session-index-invalidations-2026-10-10.md)
|
|
252
|
+
does not establish runtime or scale performance.
|
|
253
|
+
|
|
189
254
|
Bounded preview readers preserve source roles, provenance, native message cursors and Codex's adjacent
|
|
190
255
|
event/response pairing. Preview search enriches eligible rows before pagination. These readers and discovery
|
|
191
256
|
projection are connected to the owner; their presence is not a runtime or Windows qualification.
|
|
192
257
|
|
|
193
258
|
This package requires Node 22.15 or newer. It does not start a native harness, change a vendor home or own
|
|
194
259
|
a database. The machine daemon owns index state and subscriptions.
|
|
260
|
+
|
|
261
|
+
The machine-tree journal fold is exposed at `session-machine-tree`; the Teams
|
|
262
|
+
reader combines it with fresh local process/registry facts. Public
|
|
263
|
+
`sessions.tree` uses the caller-owned load worker and requires its separate
|
|
264
|
+
`tree` capability marker. The CLI and daemon writer share that TypeScript
|
|
265
|
+
reader; lineage records and remembered names grant no caller authority.
|
|
266
|
+
[Private Mac/Windows tree observations](../../docs/evidence/session-machine-tree-2026-10-08.md)
|
|
267
|
+
cover small registry/history inputs, the public SDK/CLI/operator doors, journal
|
|
268
|
+
rollover/heartbeat and an in-progress daemon offer at shutdown. The new Mac
|
|
269
|
+
native CLI handoff is operated; new Windows forwarding, real vendor/runtime
|
|
270
|
+
corpus, automatic scheduling, concurrency, scale and installed sets remain
|
|
271
|
+
unqualified.
|
|
272
|
+
|
|
273
|
+
The `session-activity` projection keeps presence and turn evidence separate
|
|
274
|
+
from transcript freshness. The Teams `sessions.activity_under` reader joins
|
|
275
|
+
it to the nearest proven Claude/Codex process beneath each requested root;
|
|
276
|
+
its caller-owned load lane advertises `activity_under` separately. It reads
|
|
277
|
+
existing registry, rollout and runtime metadata and adds no caller identity,
|
|
278
|
+
provider launch or receipt retirement. [Private Mac/Windows activity observations](../../docs/evidence/session-pane-activity-2026-10-08.md)
|
|
279
|
+
cover owned descendant/registry selection, runtime precedence, malformed
|
|
280
|
+
requests and older-service refusal through SDK and operator doors. Live
|
|
281
|
+
Codex/vendor ownership, corpus/scale, concurrency, natural shutdown and
|
|
282
|
+
installed sets remain unqualified.
|
|
283
|
+
|
|
284
|
+
The activity subscription branch also routes subscribe/unsubscribe and the
|
|
285
|
+
activity-event stream to a separate caller-owned worker, admitted by the
|
|
286
|
+
`activity` marker. It retains incremental Codex cursors, runtime precedence,
|
|
287
|
+
Hermes fire links, transition-only notifications and a background pane-prompt
|
|
288
|
+
cache. The Hermes projection reads the complete home's validity dependencies
|
|
289
|
+
without exporting or writing a home. The native activity service/module and
|
|
290
|
+
CLI poll lane are removed; their shared mail/runtime readers remain.
|
|
291
|
+
[Private Mac/Windows subscription records](../../docs/evidence/session-activity-subscriptions-2026-10-09.md)
|
|
292
|
+
cover snapshots, transitions, validation, unsubscribe/EOF and older-service
|
|
293
|
+
refusal through npm/SDK and real loopback operator streams. Owned Node fixtures
|
|
294
|
+
qualify Codex cursor/ownership mechanics; actual vendor sessions, pane/control
|
|
295
|
+
overrides, broader Hermes branches, concurrency/scale and installed sets remain
|
|
296
|
+
unqualified.
|
|
297
|
+
|
|
298
|
+
The shared method table also admits `sessions.inbox` through a separate
|
|
299
|
+
caller-owned Teams worker with an `inbox` marker. This bridge forwards to the
|
|
300
|
+
daemon's existing mailbox owner: operator reads consume unread messages,
|
|
301
|
+
while explicit session-address reads look only. It is not a pure transcript
|
|
302
|
+
read or a mailbox implementation in interchange. It preserves strict field
|
|
303
|
+
validation, the native positional-array forwarding and independent calls;
|
|
304
|
+
closing the caller aborts its sockets without retrying a consuming request.
|
|
305
|
+
[Private Mac/Windows inbox records](../../docs/evidence/session-inbox-port-2026-10-09.md)
|
|
306
|
+
cover the public SDK and loopback operator doors, admission/refusals and close
|
|
307
|
+
cancellation. Real mail delivery, all claim/channel branches, full timeout,
|
|
308
|
+
scale, remote grants and installed sets remain unqualified.
|
|
309
|
+
|
|
310
|
+
The shared method table also admits `sessions.message` through an independent
|
|
311
|
+
caller-owned Teams worker and a separate `message` marker. Admission and
|
|
312
|
+
Claude's user-level inbound report live in interchange; the worker forwards
|
|
313
|
+
one request to the existing machine mail owner, retains uncertain submitted
|
|
314
|
+
outcomes and never retries. It reads settings without changing policy.
|
|
315
|
+
[Private Mac/Windows message records](../../docs/evidence/session-message-port-2026-10-09.md)
|
|
316
|
+
qualify small owned operator-mail and settings cases, private operator streams,
|
|
317
|
+
loss/cancellation and the Mac native boundary. Vendor delivery, agent wake,
|
|
318
|
+
full deadlines, broader settings/store/grant branches and installed/published
|
|
319
|
+
sets remain unqualified.
|
|
320
|
+
|
|
321
|
+
[Current-main integration records](../../docs/evidence/session-message-integration-2026-10-15.md)
|
|
322
|
+
retain the independent message lane beside the explicit pure-read coalescer.
|
|
323
|
+
|
|
324
|
+
`sessions.import` admits an explicit document and transfer format in the
|
|
325
|
+
caller-owned load worker, using these same strict codecs and normalized model.
|
|
326
|
+
It accepts the native `open-code` alias; `hermes` selects the Codex import
|
|
327
|
+
document. It performs no home discovery, store mutation or vendor invocation.
|
|
328
|
+
The separate `import` capability marker refuses an older service rather than
|
|
329
|
+
routing the call back to a native parser. Export, translate, branch and handoff
|
|
330
|
+
use the separate transfer worker, including explicit continuation materialization.
|
|
331
|
+
|
|
332
|
+
[Private Windows-first/Mac import records](../../docs/evidence/session-document-import-2026-10-09.md)
|
|
333
|
+
cover small supplied documents, explicit admission, operator streams, retained
|
|
334
|
+
native normalized parity, older refusal and the new Mac native boundary. Broader
|
|
335
|
+
corpus, scale, transport interruptions, installed sets and a new Windows native
|
|
336
|
+
binary remain unqualified.
|
|
337
|
+
|
|
338
|
+
### Support inventory
|
|
339
|
+
|
|
340
|
+
`supportRegistryReport` and the public `harness.v1.support.report` reader
|
|
341
|
+
report the declared native-format, runtime and orchestration wiring in stable
|
|
342
|
+
product order. They construct launch specifications, never execute or probe
|
|
343
|
+
a vendor. The descriptor table is canonical in
|
|
344
|
+
`crates/harness/src/support-registry.json`; `scripts/support-registry.mjs`
|
|
345
|
+
maintains the package copy. Codex executable admission and Grok's symlink-home
|
|
346
|
+
hint use the caller's reader environment. An older service lacking the separate
|
|
347
|
+
`support` capability marker is refused. The npm `supercode harness report`
|
|
348
|
+
command serves this same reader. Retained native runtime/probe consumers still
|
|
349
|
+
read the shared typed descriptor data and their existing orchestration table.
|
|
350
|
+
[Private Windows-first/Mac finished-source records](../../docs/evidence/support-report-port-2026-10-09.md)
|
|
351
|
+
cover thirteen SDK reports per OS, selected CLI forms, private operator streams,
|
|
352
|
+
older admission, native descriptor/environment comparisons and the new Mac
|
|
353
|
+
forwarding boundary. Actual vendor/probe behavior, broader path/home branches,
|
|
354
|
+
new Windows forwarding and installed/published sets remain unqualified.
|
|
355
|
+
|
|
356
|
+
### User-level interoperation settings
|
|
357
|
+
|
|
358
|
+
`loadHarnessSettings` and public `harness.v1.harnesses.settings` read Claude's
|
|
359
|
+
user-level inbound setting through the same reader used by message admission.
|
|
360
|
+
The report hashes original file bytes, retains configured values and leaves
|
|
361
|
+
process-effective policy explicitly unknown. Other harness strings return
|
|
362
|
+
the native empty report; malformed parameters or invalid Claude settings
|
|
363
|
+
refuse. Separate SDK `settings` admission prevents an older service fallback.
|
|
364
|
+
The npm `supercode harness settings` command serves human or JSON output from
|
|
365
|
+
that reader. Configure and native runtime/mail consumers retain their own
|
|
366
|
+
active boundaries; this read executes no recommendation and writes no policy.
|
|
367
|
+
[Private Windows-first/Mac records](../../docs/evidence/harness-settings-port-2026-10-09.md)
|
|
368
|
+
cover selected SDK, CLI, operator, native report/refusal comparison and new
|
|
369
|
+
Mac forwarding cases. Effective policy, real configure/delivery, broader
|
|
370
|
+
path/concurrency branches, new Windows forwarding, installed sets and actual
|
|
371
|
+
machine upgrades remain unqualified.
|
|
372
|
+
|
|
373
|
+
### Named profiles
|
|
374
|
+
|
|
375
|
+
`listProfiles`/`getProfile` from the `session-read` subpath implement public
|
|
376
|
+
`harness.v1.profiles.list`/`get` in the caller-owned load worker. Supercode
|
|
377
|
+
presets, Codex TOML profiles, Hermes profiles, OpenClaw agents and orchestrator
|
|
378
|
+
profiles retain complete native home validity, model/default selection and
|
|
379
|
+
known/unknown counts. SDK admission requires `profiles:true` separately;
|
|
380
|
+
the npm CLI `profiles list`/`show` uses the same reading. Profile mutations
|
|
381
|
+
and native memory-search consumers retain their shared helpers.
|
|
382
|
+
[Private Mac/Windows product records](../../docs/evidence/profiles-read-port-2026-10-09.md)
|
|
383
|
+
qualify the named same-input native/TypeScript cases, CLI/operator readings,
|
|
384
|
+
older-service refusal, Windows routing-scope correction and new Mac native
|
|
385
|
+
forwarding/retirement. Broader corpus, concurrency, uncommon paths, new
|
|
386
|
+
Windows forwarding and published/installed sets remain unqualified.
|
|
387
|
+
|
|
388
|
+
### Recorded memory documents
|
|
389
|
+
|
|
390
|
+
`showMemory` from `session-read` implements public `harness.v1.memory.show`
|
|
391
|
+
in the caller-owned load worker, with separate `memory_show:true` SDK
|
|
392
|
+
admission. It selects Claude project/session stores, Hermes user/profile
|
|
393
|
+
stores and OpenClaw agent workspaces; reports ordered prose documents with
|
|
394
|
+
bounded preview or full text, size and recorded timestamp; and keeps native
|
|
395
|
+
empty/refusal meanings. The npm `memory show` CLI uses this reader. It writes
|
|
396
|
+
no memory, starts no provider and changes no caller authority. Native memory
|
|
397
|
+
search and its profile/store helpers remain separate.
|
|
398
|
+
[Private Mac/Windows product records](../../docs/evidence/memory-show-port-2026-10-09.md)
|
|
399
|
+
qualify the named same-input SDK, CLI/operator, older-service and new Mac
|
|
400
|
+
forwarding/retirement cases. Unusual paths, complete corpus/scale,
|
|
401
|
+
concurrent replacement, new Windows forwarding and installed sets remain
|
|
402
|
+
unqualified.
|
|
403
|
+
|
|
404
|
+
### Recorded job notepads
|
|
405
|
+
|
|
406
|
+
`readJobNotepad` from `session-read` implements public `harness.v1.jobs.notepad`
|
|
407
|
+
in the caller-owned load worker with separate `job_notepad:true` SDK admission.
|
|
408
|
+
It reads Hermes notepad entries after complete job-file validation and the
|
|
409
|
+
first job/profile selection, preserving SQLite TEXT and UTF-8 refusals.
|
|
410
|
+
The read-only `jobs notepad` CLI uses the same reader; set/delete and verified
|
|
411
|
+
native readback retain their owners. This reader writes no notepad or job.
|
|
412
|
+
[Original Mac/Windows records](../../docs/evidence/job-notepad-read-port-2026-10-09.md)
|
|
413
|
+
retain their exact source scope; current native/installed composition,
|
|
414
|
+
concurrent writers and the wider home/store corpus remain unqualified.
|
|
415
|
+
|
|
416
|
+
### Recorded run history
|
|
417
|
+
|
|
418
|
+
`listRuns`/`getRun` from `session-read` implement public `harness.v1.runs.list`
|
|
419
|
+
and `get` in the caller-owned worker, with separate `runs:true` admission.
|
|
420
|
+
They read Hermes, OpenClaw and orchestrator histories after complete home
|
|
421
|
+
validity, retaining source availability, execution/delivery separation,
|
|
422
|
+
ordering, limits and native record projection. The list/ls/get CLI uses the
|
|
423
|
+
same reader. No scheduler, claim, retry, pruning or writer runs here.
|
|
424
|
+
[Original Mac/Windows records](../../docs/evidence/runs-read-port-2026-10-09.md)
|
|
425
|
+
retain their source scope. Broader corpus/concurrency, native controls,
|
|
426
|
+
new Windows forwarding and current installed composition remain unqualified.
|
|
427
|
+
|
|
428
|
+
### Recorded scheduled jobs
|
|
429
|
+
|
|
430
|
+
`listJobs`/`getJob` from `session-read` implement public `harness.v1.jobs.list`
|
|
431
|
+
and `get` in the caller-owned load worker, with separate `jobs:true` admission.
|
|
432
|
+
They inspect Claude session cron/wakeup records and Hermes/OpenClaw/orchestrator
|
|
433
|
+
jobs, retaining native source availability, projections and refusal meanings.
|
|
434
|
+
The list/ls/get CLI uses the same reader. Shared native private job readback
|
|
435
|
+
and controls keep their owners; no scheduler, job writer or provider starts.
|
|
436
|
+
[Original Mac/Windows records](../../docs/evidence/jobs-read-port-2026-10-09.md)
|
|
437
|
+
retain their source scope, including exact wakeup delays and the SQLite UTF-8
|
|
438
|
+
pathname correction. Broader corpus/concurrency, native controls, new Windows
|
|
439
|
+
forwarding and current installed composition remain unqualified.
|
|
440
|
+
|
|
441
|
+
### Installed skill packages
|
|
442
|
+
|
|
443
|
+
`listInstalledSkills` and public `harness.v1.skills.list` report the skill
|
|
444
|
+
packages selected by harness, scope, working directory and config homes.
|
|
445
|
+
They read managed, user, project, plugin and bundled roots for Claude Code,
|
|
446
|
+
Codex, opencode, pi, Hermes and OpenClaw; frontmatter supplies the recorded
|
|
447
|
+
name, description, version and optional enablement. Codex config supplies a
|
|
448
|
+
sequential enablement overlay after a complete TOML parse. Invalid or unread
|
|
449
|
+
config leaves the recorded frontmatter enablement unchanged. Unknown harnesses
|
|
450
|
+
and malformed request fields refuse explicitly. SDK `listSkills` requires the
|
|
451
|
+
separate `skills:true` marker; an older service is refused while its catalog
|
|
452
|
+
remains available. The npm `supercode skills list`/`ls` command uses the same
|
|
453
|
+
reader. Runtime loading and install/remove retain their own native boundaries.
|
|
454
|
+
This listing writes no package or policy and executes no vendor. Product observations are recorded separately by source.
|
|
455
|
+
|
|
456
|
+
### Recorded routing inventory
|
|
457
|
+
|
|
458
|
+
`listRoutes` from the session-read entry projects recorded Hermes, OpenClaw
|
|
459
|
+
and orchestrator routes after complete owning-home validity. Public worker,
|
|
460
|
+
SDK `routes:true` admission and `routes list`/`ls` use the same reader.
|
|
461
|
+
Target filters, native source spelling, precedence and raw-number text retain
|
|
462
|
+
the native meanings. Listing resolves no live traffic and edits no route.
|
|
463
|
+
The complete native reader retires; shared codecs and control consumers stay.
|
|
464
|
+
[Original Mac/Windows records](../../docs/evidence/routes-read-port-2026-10-09.md)
|
|
465
|
+
retain their own source and lifecycle limits.
|
|
466
|
+
|
|
467
|
+
### Recorded inbound triggers
|
|
468
|
+
|
|
469
|
+
`listTriggers` uses complete owning-home readers and the caller-owned load
|
|
470
|
+
worker with separate `triggers:true` admission. Hermes root subscriptions and
|
|
471
|
+
static YAML routes, orchestrator profile order and OpenClaw duplicate-name/
|
|
472
|
+
mapping-position behavior retain native meaning. Rows return endpoint metadata
|
|
473
|
+
and secret presence; listing starts no endpoint and changes no store.
|
|
474
|
+
[Original records](../../docs/evidence/triggers-read-port-2026-10-09.md) retain
|
|
475
|
+
their own source, native comparison and lifecycle scopes.
|
|
476
|
+
|
|
477
|
+
### Recorded channel inventory
|
|
478
|
+
|
|
479
|
+
`listChannels` and `channelStatus` serve public channel list/status in the
|
|
480
|
+
caller-owned load worker with separate `channels:true` admission. The npm
|
|
481
|
+
list/ls/status CLI shares the reader. Complete owning-home validity precedes
|
|
482
|
+
projection; credentials and caller environment contribute presence only.
|
|
483
|
+
Unfiltered catalog counts preserve native source skips, mirror/child rules
|
|
484
|
+
and transport grouping. Status stays `unknown`; listing opens no gateway.
|
|
485
|
+
[Original records](../../docs/evidence/channels-read-port-2026-10-09.md) retain
|
|
486
|
+
their own source, native comparison and lifecycle scopes.
|
|
487
|
+
|
|
488
|
+
### Recorded workflow board
|
|
489
|
+
|
|
490
|
+
`loadWorkflow` serves public workflow load through the caller-owned worker
|
|
491
|
+
with separate `workflow:true` SDK admission and npm `workflow load`. Explicit
|
|
492
|
+
or inferred Hermes/supercode backing retains the complete read-only board,
|
|
493
|
+
task/run/review/comment/dependency and residue projection. The sole native
|
|
494
|
+
reader/codec retires; shared model/schema, mutations, dispatch and authority
|
|
495
|
+
retain their owners. Listing creates no board, index or task.
|
|
496
|
+
[Original records](../../docs/evidence/workflow-read-port-2026-10-09.md) retain
|
|
497
|
+
their own source, corrected metadata ordering and native/operator scopes.
|
|
498
|
+
|
|
499
|
+
## Corpus audit
|
|
500
|
+
|
|
501
|
+
`@volter/supercode-interchange/corpus-audit` owns the complete read-only audit
|
|
502
|
+
for Claude Code, Codex, Pi, OpenCode, Grok, Gemini and Goose. `auditCorpus(root,
|
|
503
|
+
{format, limit})` preserves typed envelope refusals, unknown fields,
|
|
504
|
+
per-instance block coverage, tools and notes; `corpusAuditJson` retains exact
|
|
505
|
+
native integer wire counts. `formatCorpusAudit` produces the compact CLI view,
|
|
506
|
+
while `formatCorpusAuditInventory` produces the full library inventory. The
|
|
507
|
+
[native selection contract and usage](../../docs/guides/corpus-audit.md) name
|
|
508
|
+
file/store limits and empty/error boundaries. The public CLI is `supercode
|
|
509
|
+
audit`; its remaining native parser forwards to this release's Node front door.
|
|
510
|
+
The audit-specific native models and classifiers have been removed. Shared
|
|
511
|
+
catalog, codecs, pricing and runtime owners remain separate. [Original records](../../docs/evidence/corpus-audit-port-2026-10-09.md)
|
|
512
|
+
retain their source and native scope. Product observations are recorded
|
|
513
|
+
separately by source; installed composition remains unqualified.
|
|
514
|
+
|
|
515
|
+
### Session emission and transfer
|
|
516
|
+
|
|
517
|
+
`@volter/supercode-interchange/session-write` exports the seven format writers,
|
|
518
|
+
same-format prefix splicing and native recovery containers. The `session-read`
|
|
519
|
+
entry exports `transferSession`, which loads the complete source and returns a
|
|
520
|
+
primary artifact, recovery files and an explicit fidelity/residue report.
|
|
521
|
+
A verified content-addressed residue cache can restore prior source records;
|
|
522
|
+
a cache miss, ambiguity or unsound prefix falls back to ordinary rendering.
|
|
523
|
+
|
|
524
|
+
Public `sessions.export` and `sessions.translate` run in a separate caller-owned
|
|
525
|
+
worker with separate capability markers. They are independent requests rather
|
|
526
|
+
than coalesced reads. Translation to Hermes returns an artifact; export to
|
|
527
|
+
Hermes invokes `hermes sessions import --from codex` through that vendor's CLI.
|
|
528
|
+
No other target is executed or installed. Shared native writer/model/residue
|
|
529
|
+
consumers in reduction, handoff and emulation remain until their owners move.
|
|
530
|
+
The emission version asset follows the interchange crate via the generator and
|
|
531
|
+
commit hook; bypassing generation can leave it stale.
|
|
532
|
+
|
|
533
|
+
### Complete conversion
|
|
534
|
+
|
|
535
|
+
The public `./session-convert` entry and `supercode convert` command share
|
|
536
|
+
literal-path and saved-family admission, all seven emitters, verified reduction
|
|
537
|
+
pointers and complete sidecar rehydration. Recorded reductions affect the view
|
|
538
|
+
token diagnostic; output uses the full source. A damaged literal may write
|
|
539
|
+
partial output to a distinct destination and then fail, but cannot overwrite
|
|
540
|
+
its own source. Saved Claude children are validated before primary output and
|
|
541
|
+
written afterward; concurrent failures do not imply transactional rollback.
|
|
542
|
+
Saved-family lookup may create an absent store directory, as the native reader
|
|
543
|
+
did. Literal Hermes conversion invokes its CLI; saved Hermes conversion retains
|
|
544
|
+
Codex emission without invoking a vendor. Shared runtime reduction decisions,
|
|
545
|
+
mutation, provider continuation and native library consumers remain separate.
|
|
546
|
+
|
|
547
|
+
### Offline inspection
|
|
548
|
+
|
|
549
|
+
The public `./session-inspect` entry and `supercode inspect` command report
|
|
550
|
+
complete literal sessions or saved working views after validating sidecar
|
|
551
|
+
reduction pointers. A persisted working transcript takes precedence over
|
|
552
|
+
mechanical reapplication. Partial literal reports end with failure.
|
|
553
|
+
`./inspection-schemas` reports fresh committed built-in schema definitions and
|
|
554
|
+
full/medium/minimal costs, after whole typed configuration admission when a
|
|
555
|
+
configured tier is requested. JSON inspection and parse-loss exits skip that
|
|
556
|
+
configuration read. No tool, hook, credential or provider runs. The generator
|
|
557
|
+
and commit hook maintain projections while native config/tool consumers remain.
|
|
558
|
+
Process ancestry keeps its current main owner and is outside this inspection
|
|
559
|
+
slice; no old ancestry operation qualifies current source here.
|
|
560
|
+
|
|
561
|
+
### Branch artifacts and handoff specifications
|
|
562
|
+
|
|
563
|
+
`sessions.branch` and `sessions.handoff`, including SDK `branchSession` and
|
|
564
|
+
`handoffSession`, use the caller-owned transfer worker with independent
|
|
565
|
+
`branch:true` and `handoff:true` markers. A cut names exactly one user message
|
|
566
|
+
by its recorded `claude_uuid`; other keys, absent or duplicated user IDs
|
|
567
|
+
refuse. It retains only preceding messages and children linked to their kept
|
|
568
|
+
tool calls. Whole-session raw records and cut-specific source residue are
|
|
569
|
+
dropped; the original source remains unchanged. An omitted branch target
|
|
570
|
+
returns `artifact:null`; a supplied target uses the complete artifact builder.
|
|
571
|
+
|
|
572
|
+
Handoff rewrites the target identity to a fresh UUID (OpenCode uses `ses_`
|
|
573
|
+
plus its undashed UUID) and returns structured launch/materialization
|
|
574
|
+
instructions for all eight targets. Explicit cwd, including empty, precedes
|
|
575
|
+
recorded cwd and `.`. Neither method invokes a vendor, writes a destination
|
|
576
|
+
session store or executes its instructions. Artifact construction may populate
|
|
577
|
+
the same best-effort source residue cache as translation. The exclusive native
|
|
578
|
+
request/dispatch/artifact/cut/instruction helpers retire together. Native
|
|
579
|
+
reduction, shared writers/residue and terminal-launch consumers remain.
|
|
580
|
+
[Current-main Windows/Mac recordings](../../docs/evidence/session-branch-handoff-integration-2026-10-15.md)
|
|
581
|
+
retain the named SDK/worker/stdio paths. Independent board review, native
|
|
582
|
+
composition and installed/runtime support remain separate.
|
|
583
|
+
|
|
584
|
+
### Continuation artifact materialization
|
|
585
|
+
|
|
586
|
+
`sessions.materialize` uses the caller-owned transfer worker and an independent
|
|
587
|
+
`materialize:true` marker. Claude, Codex, Pi and Grok get fresh-ID exclusive
|
|
588
|
+
files; OpenCode owns its import and read-only database confirmation. Source
|
|
589
|
+
recovery cache writes precede validation. Later bundle failure retains earlier
|
|
590
|
+
files and cancellation does not undo an import. No resume command executes.
|
|
591
|
+
Native materialization dispatch and the exclusive native module retire;
|
|
592
|
+
current native composition, used-home and actual vendor qualification remain
|
|
593
|
+
separate from the dated integration recordings.
|
|
594
|
+
|
|
595
|
+
### Controlled skill packages
|
|
596
|
+
|
|
597
|
+
`skills.install` and `skills.remove` use a separate caller-owned worker and
|
|
598
|
+
`skills_control:true` admission, independent of listing. Claude, Codex, Pi and
|
|
599
|
+
OpenCode local packages use their loader roots; Hermes/OpenClaw keep their own
|
|
600
|
+
CLI doors and verified inventory readback. Native control/rendering retires;
|
|
601
|
+
shared native runtime loading and frontmatter retain their owner. Explicit null
|
|
602
|
+
mutation structs refuse. The CLI preserves the bare release installer and
|
|
603
|
+
selected listing/mutation cwd. No actual vendor installation or current native
|
|
604
|
+
composition is implied by the dated integration records.
|
|
605
|
+
|
|
606
|
+
### Controlled profile commands
|
|
607
|
+
|
|
608
|
+
`profiles.create` and `profiles.delete` use an independent caller-owned worker
|
|
609
|
+
with `profiles_control:true` admission. Hermes/OpenClaw keep their own CLI
|
|
610
|
+
writers; the orchestrator keeps its package's live/cold operator and readback.
|
|
611
|
+
Native control and CLI decisions retire, with static support facts beside the
|
|
612
|
+
shared native profile reader. CLI cwd stays accepted grammar without redefining
|
|
613
|
+
profile homes. Current native/vendor/PTY/installed operation is separate from
|
|
614
|
+
these source ownership facts.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
// Narrow recorded channel facts. Credentials contribute presence only;
|
|
2
|
+
// their values and the rest of the owning configuration stay internal.
|
|
3
|
+
import { hermesYamlKeys } from './hermes-read-yaml.mjs';
|
|
4
|
+
import { stringifyNativeJsonMember } from './native-json.mjs';
|
|
5
|
+
import { nativeTrim } from './text.mjs';
|
|
6
|
+
|
|
7
|
+
const object = value => value != null && typeof value === 'object' && !Array.isArray(value);
|
|
8
|
+
const compare = (a, b) => Buffer.compare(Buffer.from(a), Buffer.from(b));
|
|
9
|
+
const placeholder = value => typeof value === 'string' && /^\$\{[A-Za-z_][A-Za-z0-9_]*\}(?![\s\S])/u.test(value);
|
|
10
|
+
const accountKeys = ['account', 'account_id', 'app_id', 'bot_id', 'client_id', 'corp_id', 'phone_number_id', 'user_id'];
|
|
11
|
+
const openclawAccountKeys = ['accountId', 'account_id', 'account', 'teamId', 'appId', 'userId'];
|
|
12
|
+
const credential = key => /token|secret|key|password|passwd|api_key|app_secret|signing|webhook_url|private/u.test(key.replace(/[A-Z]/gu, c => c.toLowerCase()));
|
|
13
|
+
const openclawPublicKeys = new Set(['sessionkey', 'session_key', 'storekey', 'store_key', 'metakey', 'meta_key', 'bindingkey', 'binding_key', 'declarationkey', 'declaration_key', 'idempotencykey', 'idempotency_key']);
|
|
14
|
+
const openclawCredential = key => {
|
|
15
|
+
const lower = key.replace(/[A-Z]/gu, c => c.toLowerCase());
|
|
16
|
+
return !openclawPublicKeys.has(lower) && /(?:token|key|secret|password|credential)$/u.test(lower);
|
|
17
|
+
};
|
|
18
|
+
const scalar = (parent, key) => typeof parent[key] === 'string' ? parent[key] : typeof parent[key] === 'number' ? stringifyNativeJsonMember(parent, key) : null;
|
|
19
|
+
|
|
20
|
+
export function folderChannelRecords(config, dotenv) {
|
|
21
|
+
const channels = new Map();
|
|
22
|
+
if (object(config.platforms)) for (const name of Object.keys(config.platforms).sort(compare)) {
|
|
23
|
+
const block = config.platforms[name], extra = new Map(); let configured = false;
|
|
24
|
+
const walk = (parent, prefix = '') => {
|
|
25
|
+
for (const key of hermesYamlKeys(parent)) {
|
|
26
|
+
const value = parent[key], field = `${prefix}${key}`;
|
|
27
|
+
if (!prefix && key === 'enabled') continue;
|
|
28
|
+
if (placeholder(value) || typeof value === 'string' && credential(key)) configured = true;
|
|
29
|
+
else if (!prefix && key === 'extra' && object(value)) walk(value, 'extra.');
|
|
30
|
+
else extra.set(field, scalar(parent, key));
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
walk(block);
|
|
34
|
+
let account = null;
|
|
35
|
+
for (const key of accountKeys) {
|
|
36
|
+
const value = extra.has(key) ? extra.get(key) : extra.get(`extra.${key}`);
|
|
37
|
+
if (value != null && value !== '') { account = value; break; }
|
|
38
|
+
}
|
|
39
|
+
channels.set(name, { name, account, enabled: block.enabled ?? true, configured });
|
|
40
|
+
}
|
|
41
|
+
for (const [name, token] of [['discord', 'DISCORD_BOT_TOKEN'], ['telegram', 'TELEGRAM_BOT_TOKEN'], ['slack', 'SLACK_BOT_TOKEN']]) {
|
|
42
|
+
if (!channels.has(name) && nativeTrim(dotenv.get(token) ?? '') !== '') channels.set(name, { name, account: null, enabled: true, configured: false });
|
|
43
|
+
}
|
|
44
|
+
return [...channels.values()].sort((a, b) => compare(a.name, b.name));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function openclawChannelRecords(config) {
|
|
48
|
+
const rows = new Map();
|
|
49
|
+
const credentials = block => object(block) && Object.keys(block).some(key => typeof block[key] === 'string'
|
|
50
|
+
&& (placeholder(block[key]) || openclawCredential(key)));
|
|
51
|
+
if (!object(config.channels)) return [];
|
|
52
|
+
for (const kind of Object.keys(config.channels).sort(compare)) {
|
|
53
|
+
const entry = config.channels[kind]; if (!object(entry)) continue;
|
|
54
|
+
const sharedEnabled = typeof entry.enabled === 'boolean' ? entry.enabled : null;
|
|
55
|
+
const accounts = object(entry.accounts) ? Object.keys(entry.accounts).map(id => [id, entry.accounts[id]])
|
|
56
|
+
: Array.isArray(entry.accounts) ? entry.accounts.flatMap(account => {
|
|
57
|
+
if (!object(account)) return [];
|
|
58
|
+
const id = Object.hasOwn(account, 'id') ? account.id : account.accountId;
|
|
59
|
+
return typeof id === 'string' && id !== '' ? [[id, account]] : [];
|
|
60
|
+
}) : [];
|
|
61
|
+
accounts.sort(([a], [b]) => compare(a, b));
|
|
62
|
+
if (!accounts.length) {
|
|
63
|
+
const key = openclawAccountKeys.find(key => typeof entry[key] === 'string');
|
|
64
|
+
rows.set(kind, { name: kind, kind, account: key == null ? null : entry[key], enabled: sharedEnabled, configured: credentials(entry) });
|
|
65
|
+
} else for (const [id, account] of accounts) {
|
|
66
|
+
const enabled = typeof account?.enabled === 'boolean' ? account.enabled : sharedEnabled;
|
|
67
|
+
rows.set(`${kind}/${id}`, { name: `${kind}/${id}`, kind, account: id, enabled, configured: credentials(account) || credentials(entry) });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return [...rows.keys()].sort(compare).map(name => rows.get(name));
|
|
71
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// The native channels reader used an unfiltered catalog reading, with children
|
|
2
|
+
// hidden. Reuse its source/noun contracts without creating an index or watcher.
|
|
3
|
+
import { readdirSync, readFileSync } from 'node:fs';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { readStore, statement, text, integer, jsonColumn } from './sqlite-reader.mjs';
|
|
6
|
+
import { selectStoreFiles } from './store-registry.mjs';
|
|
7
|
+
import { hermesSessionNouns } from './hermes-store.mjs';
|
|
8
|
+
import { readOrchestratorStore } from './orchestrator-store.mjs';
|
|
9
|
+
import { openclawNouns } from './openclaw.mjs';
|
|
10
|
+
import { parseNativeJson, nativeInteger } from './native-json.mjs';
|
|
11
|
+
import { nativeTrim } from './text.mjs';
|
|
12
|
+
|
|
13
|
+
const extended = ['session_key', 'chat_id', 'chat_type', 'thread_id', 'user_id', 'profile_name', 'handoff_state', 'handoff_platform', 'handoff_error'];
|
|
14
|
+
const utf8 = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true });
|
|
15
|
+
const add = (counts, platform) => { if (platform != null) counts.set(platform, (counts.get(platform) ?? 0n) + 1n); };
|
|
16
|
+
const entries = path => { try { return readdirSync(path); } catch { return []; } };
|
|
17
|
+
|
|
18
|
+
async function hermesPlatforms(path) {
|
|
19
|
+
const snapshot = await readStore(path, db => {
|
|
20
|
+
if (!['sessions', 'messages', 'schema_version'].every(name => db.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name=?").get(name))) return [];
|
|
21
|
+
const values = statement(db, 'SELECT id, cwd, title, model, message_count, started_at, ended_at, parent_session_id, source, model_config FROM sessions ORDER BY started_at DESC').all();
|
|
22
|
+
// A bad required/nullable column refuses the entire native store, including
|
|
23
|
+
// a malformed child that would subsequently be excluded from the count.
|
|
24
|
+
for (const row of values) {
|
|
25
|
+
text(row.id);
|
|
26
|
+
for (const key of ['cwd', 'title', 'model', 'parent_session_id', 'source', 'model_config']) text(row[key], true);
|
|
27
|
+
const count = integer(row.message_count, true);
|
|
28
|
+
if (count != null && (count < -(1n << 63n) || count >= (1n << 63n))) throw new Error('native i64 count required');
|
|
29
|
+
for (const key of ['started_at', 'ended_at']) if (row[key] != null && typeof row[key] !== 'number' && typeof row[key] !== 'bigint') throw new Error('native numeric epoch required');
|
|
30
|
+
}
|
|
31
|
+
let extendedRead = null;
|
|
32
|
+
try { extendedRead = statement(db, `SELECT ${extended.join(',')} FROM sessions WHERE id=?`); } catch { /* optional gateway schema */ }
|
|
33
|
+
return values.flatMap(row => {
|
|
34
|
+
const mirror = jsonColumn(row.model_config)?._supercode_mirror;
|
|
35
|
+
if (mirror != null) {
|
|
36
|
+
const amount = nativeInteger(mirror, 'messages', { signed: true });
|
|
37
|
+
const unchanged = amount == null || (row.message_count ?? 0n) <= amount;
|
|
38
|
+
if (unchanged && (mirror.harness === 'hermes' || Object.hasOwn(mirror, 'continued_as'))) return [];
|
|
39
|
+
}
|
|
40
|
+
if (row.parent_session_id != null) return [];
|
|
41
|
+
let fields;
|
|
42
|
+
try { fields = extendedRead?.get(row.id); } catch { /* no gateway nouns from a refused optional row */ }
|
|
43
|
+
const admitted = fields != null && extended.every(key => fields[key] == null || typeof fields[key] === 'string');
|
|
44
|
+
const nouns = hermesSessionNouns({ ...row, ...(admitted ? fields : {}) }, null, null, admitted);
|
|
45
|
+
return nouns.surface?.platform == null ? [] : [nouns.surface.platform];
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
return snapshot.result;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export async function channelSessionCounts(harness, homes) {
|
|
52
|
+
const counts = new Map();
|
|
53
|
+
if (harness === 'openclaw') {
|
|
54
|
+
for (const agent of entries(join(homes.openclaw, 'agents'))) {
|
|
55
|
+
const sessions = join(homes.openclaw, 'agents', agent, 'sessions');
|
|
56
|
+
for (const leaf of entries(sessions)) {
|
|
57
|
+
if (!leaf.endsWith('.jsonl') || leaf.endsWith('.trajectory.jsonl')) continue;
|
|
58
|
+
const path = join(sessions, leaf);
|
|
59
|
+
try {
|
|
60
|
+
const source = utf8.decode(readFileSync(path));
|
|
61
|
+
const header = parseNativeJson(source.split('\n').find(line => nativeTrim(line) !== '') ?? '');
|
|
62
|
+
if (header?.type === 'session') add(counts, openclawNouns(header, path).surface?.platform);
|
|
63
|
+
} catch { /* native discovery skips an unread/malformed session */ }
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
} else {
|
|
67
|
+
let stores;
|
|
68
|
+
try { stores = await selectStoreFiles(harness, homes); }
|
|
69
|
+
catch { stores = [{ path: harness === 'hermes' ? homes.hermes : join(homes.orchestrator, 'state.db'), profile: harness === 'hermes' ? null : 'default' }]; }
|
|
70
|
+
for (const store of stores) {
|
|
71
|
+
try {
|
|
72
|
+
if (harness === 'hermes') for (const platform of await hermesPlatforms(store.path)) add(counts, platform);
|
|
73
|
+
else {
|
|
74
|
+
const { result } = await readOrchestratorStore(store.path, store.profile, { surfaceOnly: true });
|
|
75
|
+
for (const { descriptor } of result.rows) add(counts, descriptor?.surface?.platform);
|
|
76
|
+
}
|
|
77
|
+
} catch { /* the native catalog skips the entire refused store */ }
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return counts;
|
|
81
|
+
}
|