Commit Graph

349 Commits

Author SHA1 Message Date
Peter Steinberger e0262e6aa4 feat(ui): add people session sorting (#121470)
* feat(ui): add people session sorting

Offer People sorting in the Control UI session sidebar when the Gateway reports multiple session-sharing identities.

* fix(ui): restore sidebar translation dependency

* fix(ui): preserve session sort ordering contracts
2026-08-10 00:18:02 -07:00
Peter Steinberger 3621c4b511 feat: browse and start sessions inside agent workspaces (#121417)
* feat(gateway): allow workspace-contained browsing

* fix(ui): preserve canonical workspace selections
2026-08-09 23:57:46 -07:00
Peter Steinberger 42283cb609 fix: completed tasks no longer block gateway suspension (#121267)
* fix(gateway): close task terminals at run end

* refactor(agents): keep terminal task ownership internal

* test(gateway): type task-owned terminal fixtures

* test(infra): split agent run task ownership coverage
2026-08-09 15:45:44 -07:00
Peter Steinberger b4104e29b5 fix(sessions): stop active runs before archiving (#120892)
* fix(sessions): stop active runs before archiving

Archive now fences the exact session, stops and drains active work before commit, preserves main/global-main/unknown protections and Delete behavior, and keeps patchMany per-target ordering.

* test(gateway): provide archive lifecycle context

* test(ui): expect active sessions to remain archivable

* refactor(gateway): keep archive drains internal

* fix(gateway): keep abort lifecycle contract acyclic

* fix(sessions): fence sharing across archive drains

* test(gateway): type archive lifecycle responses

* fix(sessions): reclaim cloud workers before archive

* fix(sessions): align archive request integration

* test(gateway): omit default deferred type

* docs(sessions): clarify cloud archive retries
2026-08-09 09:03:20 -07:00
Shakker f06e3675a6 docs: clarify browser annotation session scope 2026-08-09 13:56:55 +02:00
Shakker 7874024748 fix: preserve staged browser annotations across remounts 2026-08-09 13:56:55 +02:00
Shakker d0e76dea49 fix: bound browser annotation composer lifecycle 2026-08-09 13:56:55 +02:00
Shakker a3938ef435 fix: couple browser annotations to composer attachments 2026-08-09 13:56:55 +02:00
Peter Steinberger 1273657993 fix(ui): archive eligible sessions from mixed selections (#120835)
Batch Archive now delegates protected-row failures to ordered patchMany outcomes, while single Archive and Delete remain guarded.
2026-08-08 19:49:21 -07:00
Peter Steinberger 909509a5db fix(codex): resume catalog sessions with the catalog's CODEX_HOME; add main-content terminal placement (#120708)
* fix(codex): pin catalog CODEX_HOME onto terminal resume spawns

The Codex session catalog lists threads through the plugin's supervision
app-server connection, which can run on the agent-scoped Codex home
(homeScope: "agent"). The terminal resume plan spawned a bare
'codex resume <threadId>' under the operator login shell, so the CLI
resolved its default ~/.codex and failed with "No saved session found".

Terminal plans now carry the catalog connection's CODEX_HOME (local and
paired-node paths), the gateway merges plan env into the PTY spawn, and
the triplicated home-scope resolution collapses into one shared
resolveCodexAppServerLocalHomeDir.

* feat(ui): add main-content terminal placement

The terminal panel gains a third dock placement, "main", filling the
content region next to the sidebar like the transcript pane. The panel
header gets a bottom/right/main placement switcher (persisted in the
existing openclaw.terminal.panel.v1 store), and opening a Codex/Claude
session from the session catalog selects main mode so resumed sessions
appear as a full window instead of a bottom strip.
2026-08-08 14:33:20 -07:00
Peter Steinberger 4930c9d7de refactor(ui): remove local-only chat message hide feature (#120681)
Remove the localStorage-backed per-browser hide action ("Hide in this browser only") so the transcript mirrors agent context. The action was un-undoable because restore() had no UI path.

Stale openclaw:deleted:* localStorage keys become inert.
2026-08-08 13:57:15 -07:00
Peter Steinberger 13e8e1df4a fix(ui): hide connection form during initial auth (#120372)
* fix(ui): hide connection form during initial auth

Use the authoritative gateway connecting/error state so trusted-proxy, Tailscale, bootstrap, device, and token auth all keep the centered loading screen until the first handshake resolves. Real failures still reveal the login gate, manual retries stay pinned, and established reconnects retain the shell.

* fix(ui): preserve approval document login gate

Scope the neutral unresolved first-connect splash to the normal Control UI document. Standalone approval links continue to expose their authentication gate without losing the deep link, while embedded terminal behavior remains unchanged.
2026-08-07 17:18:02 -07:00
Peter Steinberger dcb125d202 fix: remove retired insecure auth guidance (#120295) 2026-08-07 09:45:48 -07:00
Shakker e16421d5d1 docs: clarify browser-local text size 2026-08-06 21:44:44 +01:00
Shakker 54e2ab545f test: cover read-only preference sync 2026-08-06 21:44:44 +01:00
Shakker 47591e7b11 docs: document control ui owner handoff 2026-08-06 02:21:45 +01:00
Jason (Json) 8df95ccd08 fix: recover Control UI access after device-auth upgrades (#118231)
* fix: recover Control UI pairing from dashboard

* test: prove dashboard credential rotation

* test: complete gateway auth generation fixture

* test: restore QR device token verifier

* fix: preserve headless dashboard recovery
2026-08-02 16:40:53 -06:00
Peter Steinberger ad53d4419e fix: make gateway token recovery usable from macOS onboarding (#118051)
* fix(gateway): add safe token recovery

Co-authored-by: 宇宙熊Yzx <53250620+849261680@users.noreply.github.com>

* chore: move gateway release note to PR

* test(cli): classify gateway token output

---------

Co-authored-by: 宇宙熊Yzx <53250620+849261680@users.noreply.github.com>
2026-08-02 10:06:50 -07:00
Peter Steinberger de0fa7c208 feat(webchat): expand truncated assistant messages inline (#117936)
* feat(webchat): expand truncated assistant messages inline

Replace the per-message Open in canvas button with an inline Show more /
Show less disclosure on truncated assistant messages that fetches full
content via chat.message.get on demand.

* test(webchat): stabilize inline expansion e2e

* fix(ui): satisfy lint and export gates for inline show-more

* test(ui): update shared disclosure selector

---------

Co-authored-by: Peter Steinberger <steipete@mac-studio-sf2.local>
2026-08-02 03:35:07 -07:00
qingminlong 3fc7fb2813 docs: clarify Control UI pairing in private browsing (issue #113000) (#114111) 2026-07-31 16:34:40 -07:00
Vincent Koc 62e83c13c5 docs(voice): document live audio roundtrip smoke 2026-07-31 00:42:04 +08:00
Peter Steinberger 03a2c8208d docs(control-ui): document composer capability menu (#115858)
* docs(control-ui): document composer capability menu

* docs(control-ui): explain tool access discovery states

* docs(map): regenerate docs map
2026-07-29 15:26:56 -04:00
Peter Steinberger c87e545c88 fix(ui): rename the Memory Palace browser to Memory Wiki and document it (#115954)
* fix(ui): rename the Memory Palace browser to Memory Wiki and document it

* refactor(memory-wiki): drop the old memory-palace module files

* docs: refresh generated docs map

* test(ui): align dream-diary hub-tab assertion with the wiki sub-tab id

* docs: describe memory wiki clustering behavior accurately

* docs(memory-wiki): record the wiki.overview rename decision at the registration site

* test(ui): query the Agents channels hub tab by tab role after the hub-tabs refactor
2026-07-29 12:51:37 -04:00
Colin Johnson 306c02af57 feat(ui): preview session workspace images (#95956)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-29 09:22:46 -04:00
Peter Steinberger af70829cdf refactor(ui): move Agent Defaults entry from the sidebar into the Agents page (#115836)
* refactor(ui): move Agent Defaults entry from the sidebar into the Agents page

* fix(ui): keep Agent Defaults searchable
2026-07-29 06:30:40 -04:00
Peter Steinberger 662abec754 feat(gateway): push session PR indicators to subscribed clients (#115643)
* feat(gateway): push session PR indicators to subscribed clients

* test(gateway): fix PR indicator drift

* chore(protocol): allowlist PR-indicator event for native apps (Control UI surface)

* test: align PR indicator lifecycle coverage

* fix(ui): scope session PR store listeners to active watchers
2026-07-29 06:30:01 -04:00
Peter Steinberger f318df7a55 refactor(ui): dissolve the General settings page into Appearance (#115798)
* refactor(ui): dissolve the General settings page into Appearance

* test(ui): drop dissolved config route expectation

* test(ui): cover legacy General model redirect

* style(ui): format legacy redirect test
2026-07-29 05:49:20 -04:00
Peter Steinberger 7441362014 feat(openai): support GPT-Live over backend WebSocket (#115622)
* feat(openai): add GPT-Live websocket bridge

* chore: defer GPT-Live changelog to release

* fix(android): preserve GPT-Live relay readiness gate

* fix(openai): normalize GPT-Live assistant completion
2026-07-29 04:15:03 -04:00
Peter Steinberger 33ca26807a feat(ui): add plugin Discover path URL (#115587) 2026-07-29 01:28:13 -04:00
Peter Steinberger 04eb57d299 feat(ui): add contextual Settings documentation links (#115560)
* feat(config): add contextual settings docs URLs

* feat(ui): add contextual settings guide links

* docs: add settings guide pages

* docs: refresh generated docs map

* docs: polish settings guide pages prose
2026-07-29 01:00:15 -04:00
Peter Steinberger 46dd03ad0a fix(talk): add GPT-Live consult safety parity (#115562) 2026-07-29 00:55:33 -04:00
Peter Steinberger c4ffc972ec docs: document gateway and memory chat wizards (#115487) 2026-07-28 22:26:19 -04:00
Peter Steinberger 7a1aa4eb4f feat(ui): Talk settings page with catalog-driven realtime pickers (#115409)
* feat(talk): emit realtime models and voices in talk.catalog and mirror create-time readiness

* feat(ui): add curated Talk settings page with catalog-driven pickers

* docs(talk): correct stale claims and add one-page GPT-Live setup path

* fix(ui): refresh Talk catalog on config-hash advance and neutralize GPT-Live badge

* fix(ui): provider-aware Talk selection, atomic provider switch, focus refresh

* fix(ui): resolve Talk provider fallbacks via catalog and make Default a true reset

* fix(ui): provider-compatible transports and race-free Talk catalog loads

* fix(ui): never resolve an unknown explicit Talk provider to the active one

* docs(talk): note Android relay readiness caveat for browser-only models

* fix(ui): keep the relay transport when switching Talk provider to Auto

* fix(ui): align section-ownership test and drop unused export after rebase
2026-07-28 17:38:15 -04:00
Peter Steinberger f78ba09120 feat(talk): support GPT-Live realtime voice over ChatGPT OAuth (#115226)
* feat(gateway): share the canonical browser-origin policy with plugins

Export resolveAcceptedBrowserOrigin through openclaw/plugin-sdk/webhook-request-guards
so browser-facing plugin routes reuse the Gateway's real origin contract instead of a
narrow allowedOrigins array check. Private LAN/Tailnet Control UI loads and the
Host-header fallback were previously rejected with 403 by plugin offer routes while the
Control UI itself worked.

Moves the loopback/forwarded-header helpers to net.ts (re-exported from auth.ts) so the
guard can delegate without importing gateway auth, and migrates the Codex realtime
broker onto the shared seam.

* feat(talk): let providers own agent delegation for realtime voice

Adds an optional runAgentConsult callback to the browser-session create request and
injects the existing embedded consult runtime from talk-client, bound to the same agent
and session key the GA tool path uses. Providers whose realtime protocol delegates work
through their own control channel (rather than GA function calls) can now reach the
OpenClaw agent without a client round-trip.

Threads the effective per-session model into browser-session capability resolution so a
request-level model override selects the right capability set, and propagates a caller
abort signal into consultRealtimeVoiceAgent so a superseded delegation stops its run.

* feat(openai): support GPT-Live realtime voice over ChatGPT OAuth

Implements OpenAI's quicksilver/frameless session natively for Talk browser sessions.
The Gateway creates the WebRTC call (multipart sdp+session to https://api.openai.com/v1/live)
and owns the sideband control socket, so the browser never holds upstream credentials;
delegation.created events run through the OpenClaw agent and stream back as speakable
context appends.

Verified end-to-end on 2026-07-28 against a ChatGPT Pro OAuth profile: call create 201
with an rtc_* id and answer SDP, sideband session.started, session.close teardown.
ChatGPT OAuth is preferred over a Platform API key because /v1/live access for platform
keys is waitlist-gated; the legacy chatgpt.com backend route returns 403 for every model
and protocol version and is not used.

Accepted models are gpt-live-1-codex and gpt-live-1-boulder-alpha; the voice allowlist is
the ten values the route actually accepts, since an invalid voice is rejected at call
creation and cannot be repaired afterwards (session.update reports immutable_field_update).

* docs: document GPT-Live Talk support and its route gotchas

Records the working route and auth, the accepted models and voices, the browser-only
scope, and the two traps that cost the most time: the chatgpt.com backend route returns
403 Voice session access denied for every model, and that same 403 is also what an
invalid voice returns, so it must not be read as an account entitlement block.

* fix(openai): resolve GPT-Live CI failures

* refactor(openai): own zod runtime dependency

* fix(openai): satisfy lint and live-shard gates for GPT-Live

Types the retry-delay finish callback as Error so the rejection reason is provably an
Error at the call site; the abort path already normalized a non-Error AbortSignal reason,
but the unknown parameter type hid that from static analysis.

Registers the new GPT-Live live test in the native-live-extensions-openai shard
expectation. The shard selector already picked the file up from the real tree; only the
hardcoded list in the tooling test lagged.

* fix(openai): clean up post-rebase capability resolver

* fix(openai): preserve GPT-Live delegation fragments

* fix(openai): close GPT-Live sideband handoff race

* fix(openai): accept UUID GPT-Live call ids

* style: apply oxfmt to GPT-Live sources and Talk docs

* style: format Talk docs after rebase

* fix(openai): keep GPT-Live transcript context across ignored delegations
2026-07-28 15:05:55 -04:00
Peter Steinberger 330d0fa4c6 docs: cover Ask OpenClaw page context, dockable panel, and hosted skills/search setup (#115182)
* docs: cover Ask OpenClaw page context, dockable panel, and hosted skills/search setup

* docs: regenerate docs map for renamed masked-wizard heading
2026-07-28 08:45:49 -04:00
Peter Steinberger 4b05d83035 fix: generated images do not appear in native chat (#115042)
* fix(chat): render managed images in native clients

Co-authored-by: Francesco Giannicola <francescogiannicola1@gmail.com>

* chore: keep release changelog owned

* refactor(macos): split managed image loading

* test(apple): prove managed image header policy

* test(native): stabilize managed image proof

* test(apple): satisfy strict concurrency checks

---------

Co-authored-by: Francesco Giannicola <francescogiannicola1@gmail.com>
2026-07-28 04:39:53 -04:00
ClawSweeper f67bdbbfe0 feat: add readable managed worktree names (#114488)
Co-authored-by: Peter Steinberger <steipete@gmail.com>
2026-07-27 05:03:43 -07:00
Peter Steinberger cca5b14785 feat(ui): path-based session and dashboard URLs (#113883)
* feat(ui): path-based session and dashboard URLs

* docs(ui): document control UI URLs

* fix(ui): finalize session path routing

* feat(ui): anchor session URLs on stable keys

* docs(ui): clarify stable session URL identity

* fix(ui): resolve session prefixes with full prefix and pagination

Query sessions.list with the full supplied prefix instead of an eight-char
truncation, and paginate up to a bounded page count so longer disambiguation
links resolve instead of being reported ambiguous. Zero strict-prefix matches
now fall through to literal-key resolution rather than rendering an empty
ambiguity view.

Also document the ~dot/~dotdot segment escape: peer ids reach session keys
trimmed and lowercased only (src/routing/session-key.ts), so a literal '.' or
'..' segment is reachable and browsers would normalize it away.

* fix(ui): synchronize committed session routes

* test(ui): split native shell host coverage

* fix(ui): thread configured mainKey through session URL builders

Reserved-set disambiguation needs the operator-configured mainKey at runtime, so
thread it from agentsList through every session path builder and the ClickClack
control URL. Unambiguous non-hex single-segment rests now resolve literally while
short-id-shaped rests still fail closed, which restores ClickClack channel
compatibility detection and control-link reconciliation.

Also bound prefix-resolution retries, preserve catalog thread identity, and keep
draft state on ambiguous candidate links.

* fix(ui): repair session URL CI integration

* perf(ui): lazy-load session route resolution

* perf(ui): isolate session prefix resolution

* perf(ui): defer session path parsing

* perf(ui): defer session navigation startup

* fix(ui): preserve first-run and literal session navigation

* fix(ui): satisfy session routing type and export gates

* fix(clickclack): preserve unscoped control link agent

* style(ui): satisfy chat page line limit

* refactor(ui): move chat page helpers to owning modules

* fix(ui): preserve destination session route identity

* fix(ui): preserve agent identity in session routes

* fix(ui): escape dots in literal session path segments

encodeURIComponent leaves periods intact, so a literal key segment like
channel:release.js produced /chat/main/channel/release.js. In-app navigation is
intercepted by the SPA, but a refresh, an external link, or a ClickClack link
would be served as a static asset request and never reach the app.

pathForWorkboardBoard already escapes dots for this reason; mirror it in both the
session URL contract and the ClickClack encoder, route the agent id through the
same segment encoder, and pin the case in both shared vector tables.

* fix(ui): stop bootstrap after teardown race

* refactor(ui): centralize session navigation targets

* fix(ui): consume bootstrap teardown abort

* fix(ui): canonicalize configured main session routes

* fix(ui): preserve distinct session references

* fix(ui): redirect released session query links

* fix(ui): make bootstrap teardown abort-safe
2026-07-26 12:46:04 -04:00
Peter Steinberger d1aec7d65f fix(control-ui): drop stale Create PR row after merge and surface PR chips mid-turn (#113944)
* fix(control-ui): drop stale Create PR row after merge and surface PR chips mid-turn

* test(gateway): split session-PR branch tests to satisfy max-lines

* test(gateway): drop unused GitContext export from test support
2026-07-25 18:51:07 -07:00
Colin Johnson de9ed64c29 feat(talk): enable GPT Live with Codex OAuth (#113354) 2026-07-25 20:41:27 -04:00
Peter Steinberger 81b7a0a006 feat(gateway): enable the operator terminal by default (#113888) 2026-07-25 16:34:28 -07:00
Peter Steinberger a95486cefc feat: session rail with read-only session companion in Control UI chat (#113698)
* feat(protocol): add session companion schemas

* feat(gateway): add session companion service

* feat(gateway): expose session companion rpc

* fix(gateway): harden companion runtime limits

* test(gateway): fix companion type assertions

* test(gateway): align companion test target

* feat(ui): replace observer HUD and side chat with session rail

* docs: session rail companion for control ui

* test(ui): align session rail client mock

* fix(ui): drop stale chat search import

* fix: satisfy session companion lint contracts

* refactor(gateway): isolate companion state contract

* fix(ui): keep session rail reachable while idle

* fix(agents): clamp derived openai prompt cache keys at boundary

* fix(ai): clamp chatgpt responses session_id affinity header

* fix(ci): align session companion branch gates

* fix(ui): require run id for sessionless terminal chat events

* fix(agents): scope internal run events to transcript

* chore: revert changelog edit (release generation owns changelog)
2026-07-25 08:14:32 -07:00
Peter Steinberger a2acc8a755 fix(ui): keep subagent details in task panel (#113671) 2026-07-25 06:13:06 -07:00
Peter Steinberger dd7f7ada7e feat(sessions): show preambles as live subtitles (#112958)
* feat(sessions): show preambles as live subtitles

* fix(sessions): harden preamble observer ordering

* fix(sessions): suppress duplicate preamble restore

* fix(sessions): preserve preamble observer lifecycle

* fix(ci): satisfy session subtitle checks

* fix(sessions): preserve terminal and preamble dedupe

* fix(sessions): finalize contextless terminal runs

* test(sessions): cover dormant contextless terminals

* fix(sessions): preserve queued preambles across dormancy
2026-07-25 01:26:50 -07:00
scotthuang 2900026b33 fix: stop selected channel sessions from WebChat (#111108)
* fix: stop selected channel sessions from WebChat

* fix: clear channel working state after stop

* fix: cancel queued turns before session abort

* fix: replay pending stops after reconnect

* fix: align stop lifecycle test fixtures

* fix(ui): bind pending aborts to gateway client

* test(ui): keep chat pane specs within line limit

* chore(ios): refresh native i18n inventory

* chore: retrigger PR checks

* fix(system-agent): avoid blocking TUI catalog discovery

* fix: preserve session abort ownership

* test: align abort coverage with current main

* test: assert scoped session abort broadcast

* fix(agent-runs): expose SDK runtime abort state

* fix(ui): clear queued main-session stops by scope

* fix(ui): replay only exact run aborts

* fix(gateway): protect session abort cleanup

* fix(ui): narrow session abort intent

* test(ui): avoid unbound request assertions

---------

Co-authored-by: scotthuang <scotthuang@tencent.com>
Co-authored-by: Patrick Erichsen <patrick.a.erichsen@gmail.com>
2026-07-24 14:36:18 -05:00
Peter Steinberger bb657eec93 refactor(config): retire redundant settings (#113174)
* refactor(config): retire redundant settings

* style: apply current formatter

* chore: update plugin sdk baseline

* fix: keep Codex tool caps context-aware

* chore: remove stale imports

* test: align WhatsApp QA debounce config

* fix(config): clean up retired config checks

* fix(ci): align config cleanup checks
2026-07-23 17:45:02 -07:00
Peter Steinberger 1603781bb0 improve(ui): unify sidebar footer into a full-width identity card (#113156)
* feat(ui): unify sidebar footer into full-width identity card

Footer becomes one card (avatar + name + chevron) mirroring the top agent
card; identity menu gains email header, Settings (with platform shortcut
hint), and Usage; Usage leaves default sidebar pins; settings shortcut now
also binds Ctrl+Shift+Comma; offline state lives in the card subtitle and
menu retry action and the card persists while disconnected.

* test(ui): align persisted-sidebar fallback default with usage removal
2026-07-23 17:40:30 -07:00
Peter Steinberger 54f8f61167 refactor(ui): split agent menu by scope — account items move to the footer identity menu (#113046)
* refactor(ui): split agent menu by scope — account items move to footer identity menu; fix facepile tooltip anchors

* test(ui): match footer identity button by its name-bearing aria label

* refactor(ui): move sidebar menu rendering out of the menus controller

* perf(ui): lazy-load sidebar menu rendering outside the startup chunk

* fix(ui): inherit knownSessionGroups signature from organizer host
2026-07-23 09:36:37 -07:00
Peter Steinberger 09672312c4 feat(gateway): incognito sessions for the web Control UI (#113006)
* feat(gateway): add web-only incognito sessions held in process memory

* feat(ui): add incognito toggle and badges to the web new-session flow

* fix(sessions): classify incognito by key shape, fail closed on stale keys, and gate memory writes

* fix(codex): start harness threads ephemeral for incognito sessions

* fix(sessions): reshape internal-effects incognito keys and add doctor repair for reserved key collisions

* refactor(plugin-sdk): export canonical incognito key classifier and guard the sentinel path

* fix(state): classify incognito DB handles from the recorded open-time set

* fix(gateway): isolate incognito sessions from durable lineage and allocation on read-only misses

* docs(sessions): pin the reserved incognito namespace ownership decision

* feat(gateway): admin-scope incognito visibility and incognito-blind cross-session surfaces

* fix(ci): repair kysely guardrails, dead export, docs map, protocol bindings, and ACP reset rotation

* fix(gateway): remove non-admin observability side channels for incognito sessions

* fix(gateway): enforce admin-scope incognito access and cover all parent-reference creation paths
2026-07-23 09:04:36 -07:00
Peter Steinberger 29d5dcfac6 feat(ui): restructure chat transcript for multi-user sessions (#112938)
* feat(ui): restructure chat transcript for multi-user sessions

Viewer-relative alignment: attributed messages from other participants
(senderId != viewer) render left-aligned as peers with their avatar,
name, and identity tint; only the viewer's own messages stay right-aligned.
System-role transcript entries (e.g. local command output) now render as
centered notice rows instead of a pseudo-participant with a question-mark
avatar. In threads with 2+ attributed senders, assistant replies carry a
'Replying to <name>' attribution chip derived from the preceding attributed
user turn; unattributed turns clear the attribution rather than mislabeling.
Also drops redundant role lowercasing on already-normalized roles.

* docs(web): describe multi-user chat transcript layout

* docs(web): refresh chat transcript docs map
2026-07-23 07:46:34 -07:00