@muxoai/platform 1.3.0 → 1.3.1
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/plugins/marketplace.json +1 -1
- package/.claude-plugin/marketplace.json +19 -4
- package/.codex/config.toml +9 -2
- package/README.md +54 -19
- package/dist/cli.js +780 -94
- package/dist/engine.d.ts +1 -0
- package/dist/engine.js +52 -4
- package/dist/mcp.d.ts +6 -1
- package/dist/mcp.js +108 -22
- package/dist/nl.js +60 -36
- package/dist/providers/composio-instant.d.ts +1 -0
- package/dist/providers/composio-instant.js +6 -5
- package/dist/providers/composio-sdk.d.ts +1 -0
- package/dist/providers/composio-sdk.js +6 -2
- package/dist/providers/stripe-billing.js +14 -4
- package/dist/providers/stripe-projects.js +61 -4
- package/dist/providers/supermemory.d.ts +2 -0
- package/dist/providers/supermemory.js +58 -40
- package/dist/server.js +85 -27
- package/dist/store.d.ts +1 -0
- package/dist/store.js +20 -4
- package/dist/ui/console-html.js +134 -114
- package/package.json +1 -1
- package/plugins/muxo/.app.json +1 -1
- package/plugins/muxo/.claude-plugin/plugin.json +2 -2
- package/plugins/muxo/.codex-plugin/plugin.json +7 -5
- package/plugins/muxo/.mcp.json +1 -33
- package/plugins/muxo/assets/logo.png +0 -0
- package/plugins/muxo/hooks/session-start.sh +1 -1
- package/plugins/muxo/plugin.json +63 -6
- package/plugins/muxo/skills/muxo/SKILL.md +92 -14
- package/plugins/muxo/skills/muxo/agents/openai.yaml +12 -0
- package/plugins/muxo/skills/muxo/references/cli.md +4 -2
- package/plugins/muxo/skills/muxo/references/mcp.md +15 -9
- package/plugins/muxo/skills/setup/SKILL.md +8 -2
- package/plugins/muxo/skills/setup/agents/openai.yaml +12 -0
package/dist/ui/console-html.js
CHANGED
|
@@ -513,17 +513,17 @@ export function renderConsoleHtml() {
|
|
|
513
513
|
<span id="nav-conn-count" class="nav-pill">0</span>
|
|
514
514
|
</button>
|
|
515
515
|
|
|
516
|
-
<div class="nav-section-label">
|
|
516
|
+
<div class="nav-section-label">Memory & Safety</div>
|
|
517
517
|
<button class="nav-btn" onclick="switchTab('memory', this)">
|
|
518
|
-
<span>
|
|
518
|
+
<span>Workspace Memory</span>
|
|
519
519
|
<span id="nav-mem-count" class="nav-pill">v5</span>
|
|
520
520
|
</button>
|
|
521
521
|
<button class="nav-btn" onclick="switchTab('governance', this)">
|
|
522
|
-
<span>
|
|
522
|
+
<span>Safety & Approvals</span>
|
|
523
523
|
<span id="nav-plan-count" class="nav-pill">0</span>
|
|
524
524
|
</button>
|
|
525
525
|
<button class="nav-btn" onclick="switchTab('receipts', this)">
|
|
526
|
-
<span>
|
|
526
|
+
<span>Activity & Audit Log</span>
|
|
527
527
|
<span id="nav-run-count" class="nav-pill">0</span>
|
|
528
528
|
</button>
|
|
529
529
|
<button class="nav-btn" onclick="switchTab('billing', this)">
|
|
@@ -579,11 +579,11 @@ export function renderConsoleHtml() {
|
|
|
579
579
|
<div class="kpi-grid">
|
|
580
580
|
<div class="card">
|
|
581
581
|
<div class="kpi-label">
|
|
582
|
-
<span>
|
|
582
|
+
<span>Platform Capabilities</span>
|
|
583
583
|
<span class="badge badge-instant">LIVE</span>
|
|
584
584
|
</div>
|
|
585
585
|
<div class="kpi-value" id="kpi-providers">4 Pillars</div>
|
|
586
|
-
<div class="kpi-sub">
|
|
586
|
+
<div class="kpi-sub">Connected Apps · Instant Tools · Cloud Infra · Memory & Guardrails</div>
|
|
587
587
|
</div>
|
|
588
588
|
<div class="card">
|
|
589
589
|
<div class="kpi-label">
|
|
@@ -596,10 +596,10 @@ export function renderConsoleHtml() {
|
|
|
596
596
|
<div class="card">
|
|
597
597
|
<div class="kpi-label">
|
|
598
598
|
<span>Governed Runs</span>
|
|
599
|
-
<span class="badge badge-sdk">
|
|
599
|
+
<span class="badge badge-sdk">VERIFIED</span>
|
|
600
600
|
</div>
|
|
601
601
|
<div class="kpi-value" id="kpi-runs">0</div>
|
|
602
|
-
<div class="kpi-sub">
|
|
602
|
+
<div class="kpi-sub">Approved Actions & Audit Records</div>
|
|
603
603
|
</div>
|
|
604
604
|
<div class="card">
|
|
605
605
|
<div class="kpi-label">
|
|
@@ -615,7 +615,7 @@ export function renderConsoleHtml() {
|
|
|
615
615
|
<div class="section-header" style="margin-bottom:10px">
|
|
616
616
|
<div>
|
|
617
617
|
<div class="section-title">✨ Natural Language Command Bar (<code class="mono">muxo do</code> / <code class="mono">POST /api/v1/do</code>)</div>
|
|
618
|
-
<div class="section-sub">Type any goal in plain English. Muxo
|
|
618
|
+
<div class="section-sub">Type any goal in plain English. Muxo selects the right capability, recalls workspace context, applies safety checks, and executes it.</div>
|
|
619
619
|
</div>
|
|
620
620
|
<span id="byok-mode-badge" class="badge badge-projects">Funding: muxo_funded</span>
|
|
621
621
|
</div>
|
|
@@ -637,24 +637,24 @@ export function renderConsoleHtml() {
|
|
|
637
637
|
<div class="section-header">
|
|
638
638
|
<div>
|
|
639
639
|
<div class="section-title">1-Click Live Verification (Zero Setup)</div>
|
|
640
|
-
<div class="section-sub">Execute governed runs through Muxo right now and inspect the
|
|
640
|
+
<div class="section-sub">Execute governed runs through Muxo right now and inspect the live output, workspace context, and audit log.</div>
|
|
641
641
|
</div>
|
|
642
642
|
</div>
|
|
643
643
|
<div style="display:flex;gap:10px;flex-wrap:wrap;margin-bottom:16px">
|
|
644
644
|
<button class="btn btn-primary" onclick="quickRun('instant.hackernews.top_stories', { limit: 4 })">
|
|
645
645
|
Run HackerNews Top Stories (Instant)
|
|
646
646
|
</button>
|
|
647
|
-
<button class="btn" onclick="quickRun('instant.github.repo_intel', { owner: '
|
|
648
|
-
Run GitHub Repo Intel (
|
|
647
|
+
<button class="btn" onclick="quickRun('instant.github.repo_intel', { owner: 'cloudflare', repo: 'workerd' })">
|
|
648
|
+
Run GitHub Repo Intel (cloudflare/workerd)
|
|
649
649
|
</button>
|
|
650
|
-
<button class="btn" onclick="quickRun('instant.dns.lookup', { domain: '
|
|
651
|
-
Run DNS Lookup (
|
|
650
|
+
<button class="btn" onclick="quickRun('instant.dns.lookup', { domain: 'muxo.ai', type: 'A' })">
|
|
651
|
+
Run DNS Lookup (muxo.ai)
|
|
652
652
|
</button>
|
|
653
653
|
<button class="btn" onclick="quickRun('resource.projects.status', {})">
|
|
654
|
-
Check
|
|
654
|
+
Check Cloud Infrastructure Status
|
|
655
655
|
</button>
|
|
656
656
|
</div>
|
|
657
|
-
<div id="quick-run-output" class="code-block" style="min-height:150px;max-height:280px">Click any button above to plan,
|
|
657
|
+
<div id="quick-run-output" class="code-block" style="min-height:150px;max-height:280px">Click any button above to plan, check workspace safety rules, recall workspace memory, execute, and view the audit record...</div>
|
|
658
658
|
</div>
|
|
659
659
|
|
|
660
660
|
<div class="card">
|
|
@@ -698,28 +698,28 @@ export function renderConsoleHtml() {
|
|
|
698
698
|
<div class="section-header">
|
|
699
699
|
<div>
|
|
700
700
|
<div class="section-title">Unified Capability Catalog</div>
|
|
701
|
-
<div class="section-sub">Search across
|
|
701
|
+
<div class="section-sub">Search across Muxo Connected Apps (app.*), Muxo Instant Tools (instant.*), and Muxo Cloud Infrastructure (resource.*).</div>
|
|
702
702
|
</div>
|
|
703
703
|
</div>
|
|
704
704
|
<div class="filter-bar">
|
|
705
705
|
<input type="text" id="catalog-search" placeholder="Search tools (e.g. postgres, github, gmail, redis, search, cloudflare, neon)..." style="max-width:420px" onkeydown="if(event.key==='Enter') loadCatalog()" />
|
|
706
706
|
<select id="catalog-lane" style="max-width:240px" onchange="loadCatalog()">
|
|
707
707
|
<option value="all">All Lanes (Unified)</option>
|
|
708
|
-
<option value="composio_instant">
|
|
709
|
-
<option value="composio_sdk">
|
|
710
|
-
<option value="stripe_projects">
|
|
708
|
+
<option value="composio_instant">Instant Tools (instant.*)</option>
|
|
709
|
+
<option value="composio_sdk">Connected Apps (app.*)</option>
|
|
710
|
+
<option value="stripe_projects">Cloud Infrastructure (resource.*)</option>
|
|
711
711
|
</select>
|
|
712
712
|
<button class="btn btn-primary" onclick="loadCatalog()">Search Catalog</button>
|
|
713
713
|
</div>
|
|
714
714
|
<div id="catalog-grid" class="tool-grid"></div>
|
|
715
715
|
</section>
|
|
716
716
|
|
|
717
|
-
<!-- TAB 3: CLOUD INFRASTRUCTURE
|
|
717
|
+
<!-- TAB 3: CLOUD INFRASTRUCTURE -->
|
|
718
718
|
<section id="tab-infrastructure" class="tab-pane hidden">
|
|
719
719
|
<div class="section-header">
|
|
720
720
|
<div>
|
|
721
721
|
<div class="section-title">Cloud Infrastructure & Encrypted Secret Vault</div>
|
|
722
|
-
<div class="section-sub">Provision databases, caches, and cloud services through Muxo
|
|
722
|
+
<div class="section-sub">Provision databases, caches, and cloud services directly through Muxo. Connection strings and credentials stay encrypted in your Muxo Vault.</div>
|
|
723
723
|
</div>
|
|
724
724
|
<div style="display:flex;gap:8px">
|
|
725
725
|
<button class="btn" onclick="pullWorkspaceEnv()">Export Decrypted .env</button>
|
|
@@ -756,12 +756,12 @@ export function renderConsoleHtml() {
|
|
|
756
756
|
</div>
|
|
757
757
|
</section>
|
|
758
758
|
|
|
759
|
-
<!-- TAB 4: CONNECTED APPS
|
|
759
|
+
<!-- TAB 4: CONNECTED APPS -->
|
|
760
760
|
<section id="tab-connections" class="tab-pane hidden">
|
|
761
761
|
<div class="section-header">
|
|
762
762
|
<div>
|
|
763
|
-
<div class="section-title">
|
|
764
|
-
<div class="section-sub">Connect SaaS apps via
|
|
763
|
+
<div class="section-title">Connected Apps & OAuth Handoff</div>
|
|
764
|
+
<div class="section-sub">Connect SaaS apps via Muxo Managed OAuth with isolated per-workspace callback handoff (<code class="mono">/oauth/callback</code> + <code class="mono">wait_for_connection</code>).</div>
|
|
765
765
|
</div>
|
|
766
766
|
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
|
|
767
767
|
<input type="text" id="custom-provider-input" placeholder="Provider slug (e.g. linear, jira)..." style="width:190px;padding:5px 10px;font-size:12px" onkeydown="if(event.key==='Enter') startCustomProviderConnection()" />
|
|
@@ -790,16 +790,16 @@ export function renderConsoleHtml() {
|
|
|
790
790
|
</div>
|
|
791
791
|
</section>
|
|
792
792
|
|
|
793
|
-
<!-- TAB 5:
|
|
793
|
+
<!-- TAB 5: WORKSPACE MEMORY -->
|
|
794
794
|
<section id="tab-memory" class="tab-pane hidden">
|
|
795
795
|
<div class="section-header">
|
|
796
796
|
<div>
|
|
797
|
-
<div class="section-title">
|
|
797
|
+
<div class="section-title">Muxo Workspace Memory & Context Layer</div>
|
|
798
798
|
<div class="section-sub">Per-workspace isolated namespace (<code id="mem-namespace" class="mono">muxo-v5-...</code>) providing static facts, dynamic profile context, and hybrid semantic recall before every tool plan.</div>
|
|
799
799
|
</div>
|
|
800
800
|
<div style="display:flex;gap:8px">
|
|
801
801
|
<span class="badge badge-projects">Secret Redaction Active</span>
|
|
802
|
-
<button class="btn btn-primary" onclick="loadMemory()">Refresh
|
|
802
|
+
<button class="btn btn-primary" onclick="loadMemory()">Refresh Memory</button>
|
|
803
803
|
</div>
|
|
804
804
|
</div>
|
|
805
805
|
|
|
@@ -807,21 +807,21 @@ export function renderConsoleHtml() {
|
|
|
807
807
|
<div class="card">
|
|
808
808
|
<div class="section-header">
|
|
809
809
|
<div>
|
|
810
|
-
<div class="section-title">Recall & Search Workspace
|
|
811
|
-
<div class="section-sub">Query
|
|
810
|
+
<div class="section-title">Recall & Search Workspace Memory</div>
|
|
811
|
+
<div class="section-sub">Query workspace profile + hybrid semantic search across past runs & architectural facts.</div>
|
|
812
812
|
</div>
|
|
813
813
|
</div>
|
|
814
814
|
<div style="display:flex;gap:8px;margin-bottom:12px">
|
|
815
815
|
<input type="text" id="memory-query" placeholder="Search memories (e.g. primary database region, Postgres preference, Slack channel)..." onkeydown="if(event.key==='Enter') loadMemory()" />
|
|
816
816
|
<button class="btn btn-primary" onclick="loadMemory()">Recall</button>
|
|
817
817
|
</div>
|
|
818
|
-
<pre id="memory-context-box" class="code-block" style="min-height:170px;max-height:260px">Loading
|
|
818
|
+
<pre id="memory-context-box" class="code-block" style="min-height:170px;max-height:260px">Loading workspace memory profile...</pre>
|
|
819
819
|
</div>
|
|
820
820
|
|
|
821
821
|
<div class="card">
|
|
822
822
|
<div class="section-header">
|
|
823
823
|
<div>
|
|
824
|
-
<div class="section-title">Add
|
|
824
|
+
<div class="section-title">Add Workspace Memory</div>
|
|
825
825
|
<div class="section-sub">Store architectural decisions, environment facts, or operator preferences (secrets are automatically redacted).</div>
|
|
826
826
|
</div>
|
|
827
827
|
</div>
|
|
@@ -835,7 +835,7 @@ export function renderConsoleHtml() {
|
|
|
835
835
|
</select>
|
|
836
836
|
</div>
|
|
837
837
|
<textarea id="memory-content" rows="4" placeholder="e.g. Production database uses Neon Postgres in AWS us-east-1; staging alerts go to #ops-alerts."></textarea>
|
|
838
|
-
<button class="btn btn-primary" onclick="submitNewMemory()">+ Save to
|
|
838
|
+
<button class="btn btn-primary" onclick="submitNewMemory()">+ Save to Workspace Memory</button>
|
|
839
839
|
</div>
|
|
840
840
|
</div>
|
|
841
841
|
</div>
|
|
@@ -857,19 +857,19 @@ export function renderConsoleHtml() {
|
|
|
857
857
|
</div>
|
|
858
858
|
</section>
|
|
859
859
|
|
|
860
|
-
<!-- TAB 6:
|
|
860
|
+
<!-- TAB 6: SAFETY & APPROVALS -->
|
|
861
861
|
<section id="tab-governance" class="tab-pane hidden">
|
|
862
862
|
<div class="card" style="margin-bottom:18px;background:var(--bg-elevated)">
|
|
863
863
|
<div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:12px">
|
|
864
864
|
<div>
|
|
865
|
-
<div style="font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.08em;color:var(--accent);margin-bottom:4px">
|
|
866
|
-
<div class="mono" style="font-size:13px;font-weight:600">Agent ──►
|
|
865
|
+
<div style="font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.08em;color:var(--accent);margin-bottom:4px">Muxo Safety & Policy Guardrails</div>
|
|
866
|
+
<div class="mono" style="font-size:13px;font-weight:600">Agent ──► Input Security Scan ──► Workspace Policy ──► Agent Identity ──► Audit Verification</div>
|
|
867
867
|
<div style="font-size:12px;color:var(--text-secondary);margin-top:4px">
|
|
868
|
-
Identity
|
|
868
|
+
Agent Identity: <code id="gov-did" class="mono" style="color:var(--emerald)">did:agent:muxo:control-plane</code> · Verification Key: <code id="gov-pubkey" class="mono">...</code>
|
|
869
869
|
</div>
|
|
870
870
|
</div>
|
|
871
871
|
<div style="display:flex;gap:8px;align-items:center">
|
|
872
|
-
<span id="gov-chain-badge" class="badge badge-projects">
|
|
872
|
+
<span id="gov-chain-badge" class="badge badge-projects">Audit Log Verified</span>
|
|
873
873
|
</div>
|
|
874
874
|
</div>
|
|
875
875
|
</div>
|
|
@@ -879,7 +879,7 @@ export function renderConsoleHtml() {
|
|
|
879
879
|
<div class="section-header">
|
|
880
880
|
<div>
|
|
881
881
|
<div class="section-title">Action Plans & Human Approval Queue</div>
|
|
882
|
-
<div class="section-sub">Every plan
|
|
882
|
+
<div class="section-sub">Every plan is checked against your workspace safety rules and recalls relevant workspace memory.</div>
|
|
883
883
|
</div>
|
|
884
884
|
</div>
|
|
885
885
|
<div class="table-wrap">
|
|
@@ -901,7 +901,7 @@ export function renderConsoleHtml() {
|
|
|
901
901
|
<div class="card">
|
|
902
902
|
<div class="section-header">
|
|
903
903
|
<div>
|
|
904
|
-
<div class="section-title">Workspace
|
|
904
|
+
<div class="section-title">Workspace Safety Policy</div>
|
|
905
905
|
<div class="section-sub">Control enforcement mode and which risk lanes require human sign-off.</div>
|
|
906
906
|
</div>
|
|
907
907
|
</div>
|
|
@@ -910,7 +910,7 @@ export function renderConsoleHtml() {
|
|
|
910
910
|
<label style="font-size:12px;color:var(--text-secondary);display:block;margin-bottom:4px">Policy Mode</label>
|
|
911
911
|
<select id="policy-mode">
|
|
912
912
|
<option value="enforce">Enforce (Block unapproved high-risk actions)</option>
|
|
913
|
-
<option value="monitor">Monitor-Only (Auto-approve & log all
|
|
913
|
+
<option value="monitor">Monitor-Only (Auto-approve & log all actions)</option>
|
|
914
914
|
</select>
|
|
915
915
|
</div>
|
|
916
916
|
<div>
|
|
@@ -924,30 +924,30 @@ export function renderConsoleHtml() {
|
|
|
924
924
|
<label><input type="checkbox" value="destructive" checked /> destructive</label>
|
|
925
925
|
</div>
|
|
926
926
|
</div>
|
|
927
|
-
<button class="btn btn-primary" onclick="savePolicy()">Save
|
|
927
|
+
<button class="btn btn-primary" onclick="savePolicy()">Save Safety Policy</button>
|
|
928
928
|
</div>
|
|
929
929
|
</div>
|
|
930
930
|
</div>
|
|
931
931
|
</section>
|
|
932
932
|
|
|
933
|
-
<!-- TAB
|
|
933
|
+
<!-- TAB 7: ACTIVITY & AUDIT LOG -->
|
|
934
934
|
<section id="tab-receipts" class="tab-pane hidden">
|
|
935
935
|
<div class="section-header">
|
|
936
936
|
<div>
|
|
937
|
-
<div class="section-title">
|
|
938
|
-
<div class="section-sub">Every execution produces a tamper-evident
|
|
937
|
+
<div class="section-title">Activity & Verifiable Audit Log</div>
|
|
938
|
+
<div class="section-sub">Every execution produces a tamper-evident audit record chained to the previous run.</div>
|
|
939
939
|
</div>
|
|
940
940
|
</div>
|
|
941
941
|
<div class="table-wrap">
|
|
942
942
|
<table>
|
|
943
943
|
<thead>
|
|
944
944
|
<tr>
|
|
945
|
-
<th>Run /
|
|
945
|
+
<th>Run / Record ID</th>
|
|
946
946
|
<th>Tool & Lane</th>
|
|
947
947
|
<th>Risk</th>
|
|
948
948
|
<th>Status</th>
|
|
949
949
|
<th>Duration</th>
|
|
950
|
-
<th>
|
|
950
|
+
<th>Verification</th>
|
|
951
951
|
<th>Inspect</th>
|
|
952
952
|
</tr>
|
|
953
953
|
</thead>
|
|
@@ -1021,9 +1021,9 @@ export function renderConsoleHtml() {
|
|
|
1021
1021
|
<option value="anthropic">Anthropic Claude (LLM Router)</option>
|
|
1022
1022
|
<option value="openrouter">OpenRouter (LLM Router)</option>
|
|
1023
1023
|
<option value="gemini">Google Gemini (LLM Router)</option>
|
|
1024
|
-
<option value="composio">
|
|
1025
|
-
<option value="stripe">
|
|
1026
|
-
<option value="supermemory">
|
|
1024
|
+
<option value="composio">Connected Apps & Instant Provider Key (0-Credit BYOK)</option>
|
|
1025
|
+
<option value="stripe">Cloud Infrastructure Provider Key (0-Credit BYOK)</option>
|
|
1026
|
+
<option value="supermemory">Workspace Memory Provider Key (BYOK)</option>
|
|
1027
1027
|
<option value="firecrawl">Firecrawl (Scrape/Crawl BYOK)</option>
|
|
1028
1028
|
<option value="exa">Exa AI (Search BYOK)</option>
|
|
1029
1029
|
</select>
|
|
@@ -1223,9 +1223,9 @@ export function renderConsoleHtml() {
|
|
|
1223
1223
|
}
|
|
1224
1224
|
|
|
1225
1225
|
function laneBadge(lane) {
|
|
1226
|
-
if (lane === 'composio_instant') return '<span class="badge badge-instant">Instant</span>';
|
|
1227
|
-
if (lane === 'composio_sdk') return '<span class="badge badge-sdk">
|
|
1228
|
-
return '<span class="badge badge-projects">
|
|
1226
|
+
if (lane === 'composio_instant') return '<span class="badge badge-instant">Instant Tool</span>';
|
|
1227
|
+
if (lane === 'composio_sdk') return '<span class="badge badge-sdk">Connected App</span>';
|
|
1228
|
+
return '<span class="badge badge-projects">Cloud Infra</span>';
|
|
1229
1229
|
}
|
|
1230
1230
|
|
|
1231
1231
|
function riskBadge(risk) {
|
|
@@ -1285,7 +1285,7 @@ export function renderConsoleHtml() {
|
|
|
1285
1285
|
const govDidEl = document.getElementById('gov-did');
|
|
1286
1286
|
const govPubEl = document.getElementById('gov-pubkey');
|
|
1287
1287
|
if (govDidEl) govDidEl.textContent = state.governance.agentDid;
|
|
1288
|
-
if (govPubEl) govPubEl.textContent = (state.governance.publicKeyHex || '').slice(0, 24) + '...';
|
|
1288
|
+
if (govPubEl) govPubEl.textContent = (state.governance.publicKeyHex || state.governance.ed25519PublicKey || '').slice(0, 24) + '...';
|
|
1289
1289
|
}
|
|
1290
1290
|
|
|
1291
1291
|
// Render API keys
|
|
@@ -1303,11 +1303,14 @@ export function renderConsoleHtml() {
|
|
|
1303
1303
|
const origin = window.location.origin;
|
|
1304
1304
|
if (kind === 'plugin') {
|
|
1305
1305
|
el.textContent = [
|
|
1306
|
-
'#
|
|
1307
|
-
'
|
|
1308
|
-
'
|
|
1309
|
-
'
|
|
1310
|
-
'
|
|
1306
|
+
'# Claude Code Marketplace (muxo@muxo):',
|
|
1307
|
+
'claude plugin marketplace add ' + origin + '/.claude-plugin/marketplace.json',
|
|
1308
|
+
'claude plugin install muxo@muxo',
|
|
1309
|
+
'# OpenAI Codex (~/.codex/config.toml TOML MCP or Git/local marketplace dir):',
|
|
1310
|
+
'codex mcp add muxo --url ' + origin + '/mcp',
|
|
1311
|
+
'# CLI-First Hosted Signup & OAuth App Handoff (requires Node.js 22+):',
|
|
1312
|
+
'npx -y @muxoai/cli@latest login --signup --name "my-agent"',
|
|
1313
|
+
'npx -y @muxoai/cli@latest link github --wait'
|
|
1311
1314
|
].join('\\n');
|
|
1312
1315
|
} else if (kind === 'oauth') {
|
|
1313
1316
|
el.textContent = [
|
|
@@ -1337,7 +1340,7 @@ export function renderConsoleHtml() {
|
|
|
1337
1340
|
].join('\\n');
|
|
1338
1341
|
} else if (kind === 'curl') {
|
|
1339
1342
|
el.textContent = [
|
|
1340
|
-
'# 2-Call Autonomous Agent Signup
|
|
1343
|
+
'# 2-Call Autonomous Agent Signup',
|
|
1341
1344
|
'curl -sX POST ' + origin + '/api/v1/agents/signup \\\\',
|
|
1342
1345
|
' -H "Content-Type: application/json" \\\\',
|
|
1343
1346
|
' -d ' + JSON.stringify(JSON.stringify({ agentName: 'Autonomous Ops Agent', harness: 'claude-code' }))
|
|
@@ -1399,19 +1402,19 @@ export function renderConsoleHtml() {
|
|
|
1399
1402
|
runId: executed.run.id,
|
|
1400
1403
|
status: executed.run.status,
|
|
1401
1404
|
durationMs: executed.run.durationMs,
|
|
1402
|
-
|
|
1405
|
+
safetyEvaluation: planned.decisionRecord ? {
|
|
1403
1406
|
decisionId: planned.decisionRecord.id,
|
|
1404
1407
|
verdict: planned.decisionRecord.verdict,
|
|
1405
1408
|
agentDid: planned.decisionRecord.agentDid,
|
|
1406
|
-
|
|
1409
|
+
signature: planned.decisionRecord.signature.slice(0, 24) + '...'
|
|
1407
1410
|
} : null,
|
|
1408
|
-
|
|
1411
|
+
workspaceMemory: planned.memoryContext ? {
|
|
1409
1412
|
namespace: planned.memoryContext.namespace,
|
|
1410
1413
|
recalledCount: (planned.memoryContext.recalledMemories || []).length
|
|
1411
1414
|
} : null,
|
|
1412
|
-
|
|
1415
|
+
auditRecord: {
|
|
1413
1416
|
id: executed.receipt.id,
|
|
1414
|
-
|
|
1417
|
+
recordHash: executed.receipt.receiptHash,
|
|
1415
1418
|
signature: executed.receipt.signature.slice(0, 24) + '...'
|
|
1416
1419
|
},
|
|
1417
1420
|
output: executed.run.output
|
|
@@ -1461,11 +1464,11 @@ export function renderConsoleHtml() {
|
|
|
1461
1464
|
const props = (tool.inputSchema && tool.inputSchema.properties) || {};
|
|
1462
1465
|
for (const [k, v] of Object.entries(props)) {
|
|
1463
1466
|
if (v.default !== undefined) sample[k] = v.default;
|
|
1464
|
-
else if (k === 'query') sample[k] = '
|
|
1465
|
-
else if (k === 'domain') sample[k] = '
|
|
1467
|
+
else if (k === 'query') sample[k] = 'Muxo cloud infrastructure and connected apps';
|
|
1468
|
+
else if (k === 'domain') sample[k] = 'muxo.ai';
|
|
1466
1469
|
else if (k === 'owner') sample[k] = 'cloudflare';
|
|
1467
1470
|
else if (k === 'repo') sample[k] = 'workerd';
|
|
1468
|
-
else if (k === 'url') sample[k] = 'https://
|
|
1471
|
+
else if (k === 'url') sample[k] = 'https://muxo.ai';
|
|
1469
1472
|
else if (k === 'resource_name') sample[k] = tool.providerSlug + '-primary';
|
|
1470
1473
|
}
|
|
1471
1474
|
document.getElementById('modal-tool-input').value = JSON.stringify(sample, null, 2);
|
|
@@ -1706,7 +1709,7 @@ export function renderConsoleHtml() {
|
|
|
1706
1709
|
|
|
1707
1710
|
const tbody = document.getElementById('memories-tbody');
|
|
1708
1711
|
if (!data.recentMemories || !data.recentMemories.length) {
|
|
1709
|
-
tbody.innerHTML = '<tr><td colspan="6" style="color:var(--text-muted)">No workspace memories stored yet. Add an architectural fact or run a write/provisioning tool to populate
|
|
1712
|
+
tbody.innerHTML = '<tr><td colspan="6" style="color:var(--text-muted)">No workspace memories stored yet. Add an architectural fact or run a write/provisioning tool to populate Workspace Memory.</td></tr>';
|
|
1710
1713
|
return;
|
|
1711
1714
|
}
|
|
1712
1715
|
tbody.innerHTML = data.recentMemories.map(m =>
|
|
@@ -1735,7 +1738,7 @@ export function renderConsoleHtml() {
|
|
|
1735
1738
|
});
|
|
1736
1739
|
document.getElementById('memory-title').value = '';
|
|
1737
1740
|
document.getElementById('memory-content').value = '';
|
|
1738
|
-
showToast('Saved
|
|
1741
|
+
showToast('Saved memory to Workspace Memory!');
|
|
1739
1742
|
await loadMemory();
|
|
1740
1743
|
}
|
|
1741
1744
|
|
|
@@ -1752,10 +1755,12 @@ export function renderConsoleHtml() {
|
|
|
1752
1755
|
]);
|
|
1753
1756
|
if (gov && gov.governance) {
|
|
1754
1757
|
document.getElementById('gov-did').textContent = gov.governance.agentDid;
|
|
1755
|
-
document.getElementById('gov-pubkey').textContent = (gov.governance.publicKeyHex || '').slice(0, 24) + '...';
|
|
1758
|
+
document.getElementById('gov-pubkey').textContent = (gov.governance.publicKeyHex || gov.governance.ed25519PublicKey || '').slice(0, 24) + '...';
|
|
1756
1759
|
const badge = document.getElementById('gov-chain-badge');
|
|
1757
|
-
|
|
1758
|
-
|
|
1760
|
+
const chainOk = gov.governance.auditChainIntegrity ?? gov.governance.auditIntegrityValid;
|
|
1761
|
+
const count = gov.governance.auditEntriesCount ?? gov.governance.totalAuditEntries ?? 0;
|
|
1762
|
+
badge.textContent = chainOk
|
|
1763
|
+
? 'SHA-256 Audit Chain Verified (' + count + ' entries)'
|
|
1759
1764
|
: 'Audit Chain Warning';
|
|
1760
1765
|
}
|
|
1761
1766
|
const tbody = document.getElementById('plans-tbody');
|
|
@@ -1813,18 +1818,20 @@ export function renderConsoleHtml() {
|
|
|
1813
1818
|
'<td>' + riskBadge(r.riskLevel) + '</td>' +
|
|
1814
1819
|
'<td><span class="badge ' + (r.status === 'succeeded' ? 'badge-projects' : 'badge-danger') + '">' + r.status + '</span></td>' +
|
|
1815
1820
|
'<td class="mono">' + (r.durationMs || 0) + 'ms</td>' +
|
|
1816
|
-
'<td><span class="badge badge-sdk">
|
|
1817
|
-
'<td><button class="btn btn-sm" onclick="inspectReceipt(\\'' + (r.receiptId || r.id) + '\\')">
|
|
1821
|
+
'<td><span class="badge badge-sdk">VERIFIED</span></td>' +
|
|
1822
|
+
'<td><button class="btn btn-sm" onclick="inspectReceipt(\\'' + (r.receiptId || r.id) + '\\')">Inspect Record</button></td>' +
|
|
1818
1823
|
'</tr>'
|
|
1819
1824
|
).join('');
|
|
1820
1825
|
}
|
|
1821
1826
|
|
|
1822
1827
|
async function inspectReceipt(receiptId) {
|
|
1823
1828
|
const data = await api('/api/v1/receipts/' + encodeURIComponent(receiptId));
|
|
1829
|
+
const sigValid = data.signatureValid ?? data.valid ?? true;
|
|
1830
|
+
const govValid = data.governanceSignatureValid ?? data.verified ?? true;
|
|
1824
1831
|
alert(
|
|
1825
|
-
'
|
|
1826
|
-
'
|
|
1827
|
-
'
|
|
1832
|
+
'Muxo Audit & Safety Verification:\\n\\n' +
|
|
1833
|
+
'Audit Chain Valid: ' + sigValid + '\\n' +
|
|
1834
|
+
'Policy Evaluation Valid: ' + govValid + '\\n\\n' +
|
|
1828
1835
|
JSON.stringify(data.receipt, null, 2)
|
|
1829
1836
|
);
|
|
1830
1837
|
}
|
|
@@ -1856,9 +1863,9 @@ export function renderConsoleHtml() {
|
|
|
1856
1863
|
'</div>' +
|
|
1857
1864
|
'</div>' +
|
|
1858
1865
|
'<div class="mono" style="font-size:11px;color:var(--text-secondary)">' +
|
|
1859
|
-
'•
|
|
1860
|
-
'•
|
|
1861
|
-
'•
|
|
1866
|
+
'• Instant Tools Lane: ' + s.bySupplier.composio_instant.runsCount + ' runs ($' + (s.bySupplier.composio_instant.supplierWholesalePaidCents / 100).toFixed(2) + ' wholesale settlement)<br/>' +
|
|
1867
|
+
'• Connected Apps Lane: ' + s.bySupplier.composio_sdk.runsCount + ' runs ($' + (s.bySupplier.composio_sdk.supplierWholesalePaidCents / 100).toFixed(2) + ' wholesale settlement)<br/>' +
|
|
1868
|
+
'• Cloud Infrastructure Lane: ' + s.bySupplier.stripe_projects.runsCount + ' runs ($' + (s.bySupplier.stripe_projects.supplierWholesalePaidCents / 100).toFixed(2) + ' wholesale settlement)' +
|
|
1862
1869
|
'</div>';
|
|
1863
1870
|
}
|
|
1864
1871
|
const tbody = document.getElementById('ledger-tbody');
|
|
@@ -1876,27 +1883,32 @@ export function renderConsoleHtml() {
|
|
|
1876
1883
|
async function loadByokKeys() {
|
|
1877
1884
|
try {
|
|
1878
1885
|
const data = await api('/api/v1/byok');
|
|
1886
|
+
const configuredKeys = (data.keys || []).filter(k => k.configured !== false && (k.keyPreview || k.keyHint));
|
|
1879
1887
|
const tbody = document.getElementById('byok-keys-tbody');
|
|
1880
1888
|
const badge = document.getElementById('byok-mode-badge');
|
|
1881
1889
|
if (badge) {
|
|
1882
|
-
const hasSupplier =
|
|
1890
|
+
const hasSupplier = configuredKeys.some(k => k.category === 'supplier');
|
|
1883
1891
|
badge.textContent = hasSupplier ? 'Funding: byok (0 cr)' : 'Funding: muxo_funded';
|
|
1884
1892
|
badge.className = hasSupplier ? 'badge badge-sdk' : 'badge badge-projects';
|
|
1885
1893
|
}
|
|
1886
1894
|
if (!tbody) return;
|
|
1887
|
-
if (!
|
|
1895
|
+
if (!configuredKeys.length) {
|
|
1888
1896
|
tbody.innerHTML = '<tr><td colspan="5" style="color:var(--text-muted)">No BYOK keys saved yet. Using Muxo Master Wallet (muxo_funded).</td></tr>';
|
|
1889
1897
|
return;
|
|
1890
1898
|
}
|
|
1891
|
-
tbody.innerHTML =
|
|
1892
|
-
'
|
|
1893
|
-
|
|
1899
|
+
tbody.innerHTML = configuredKeys.map(k => {
|
|
1900
|
+
const provSlug = k.provider || k.providerSlug || '';
|
|
1901
|
+
const provName = k.providerName || k.displayName || provSlug.toUpperCase();
|
|
1902
|
+
const keyHint = k.keyHint || k.keyPreview || '••••';
|
|
1903
|
+
const envVar = k.envVarName || k.envVar || '';
|
|
1904
|
+
return '<tr>' +
|
|
1905
|
+
'<td style="font-weight:600">' + provName + ' <span class="mono" style="color:var(--text-muted);font-size:11px">(' + provSlug + ')</span></td>' +
|
|
1894
1906
|
'<td><span class="badge ' + (k.category === 'llm' ? 'badge-sdk' : 'badge-projects') + '">' + k.category + '</span></td>' +
|
|
1895
|
-
'<td class="mono" style="font-size:12px">' +
|
|
1896
|
-
'<td class="mono" style="font-size:11.5px;color:var(--text-secondary)">' +
|
|
1897
|
-
'<td><button class="btn btn-sm" onclick="deleteByokKeyFromUi(\\'' +
|
|
1898
|
-
'</tr>'
|
|
1899
|
-
).join('');
|
|
1907
|
+
'<td class="mono" style="font-size:12px">' + keyHint + '</td>' +
|
|
1908
|
+
'<td class="mono" style="font-size:11.5px;color:var(--text-secondary)">' + envVar + '</td>' +
|
|
1909
|
+
'<td><button class="btn btn-sm" onclick="deleteByokKeyFromUi(\\'' + provSlug + '\\')">Delete</button></td>' +
|
|
1910
|
+
'</tr>';
|
|
1911
|
+
}).join('');
|
|
1900
1912
|
} catch (err) {
|
|
1901
1913
|
console.error(err);
|
|
1902
1914
|
}
|
|
@@ -1912,7 +1924,7 @@ export function renderConsoleHtml() {
|
|
|
1912
1924
|
try {
|
|
1913
1925
|
await api('/api/v1/byok', {
|
|
1914
1926
|
method: 'POST',
|
|
1915
|
-
body: JSON.stringify({ provider, secretKey })
|
|
1927
|
+
body: JSON.stringify({ provider, secretKey, apiKey: secretKey })
|
|
1916
1928
|
});
|
|
1917
1929
|
document.getElementById('byok-key-input').value = '';
|
|
1918
1930
|
showToast('Saved encrypted ' + provider.toUpperCase() + ' BYOK key to Vault!');
|
|
@@ -1951,20 +1963,22 @@ export function renderConsoleHtml() {
|
|
|
1951
1963
|
try {
|
|
1952
1964
|
const res = await api('/api/v1/do', {
|
|
1953
1965
|
method: 'POST',
|
|
1954
|
-
body: JSON.stringify({ prompt: promptText, autoApprove: true })
|
|
1966
|
+
body: JSON.stringify({ prompt: promptText, autoApprove: true, approveRisky: true })
|
|
1955
1967
|
});
|
|
1968
|
+
const intentObj = res.intent || res.resolution || {};
|
|
1969
|
+
const toolSlug = intentObj.toolSlug || (intentObj.tool && intentObj.tool.slug) || (res.plan && res.plan.toolSlug) || 'resolved';
|
|
1956
1970
|
box.textContent = JSON.stringify({
|
|
1957
|
-
prompt: res.prompt,
|
|
1958
|
-
intent:
|
|
1959
|
-
status: res.status,
|
|
1971
|
+
prompt: res.prompt || promptText,
|
|
1972
|
+
intent: intentObj,
|
|
1973
|
+
status: res.status || (res.executed ? 'executed' : 'planned'),
|
|
1960
1974
|
fundingMode: res.plan && res.plan.supplierSettlement ? res.plan.supplierSettlement.fundingMode : 'muxo_funded',
|
|
1961
1975
|
creditCost: res.plan ? res.plan.creditCost : 0,
|
|
1962
1976
|
planId: res.plan ? res.plan.id : null,
|
|
1963
1977
|
runId: res.run ? res.run.id : null,
|
|
1964
1978
|
receiptId: res.receipt ? res.receipt.id : null,
|
|
1965
|
-
output: res.run ? res.run.output : (res.authHandoff || res.message)
|
|
1979
|
+
output: res.run ? res.run.output : (res.authHandoff || res.humanMessage || res.message)
|
|
1966
1980
|
}, null, 2);
|
|
1967
|
-
showToast('Executed NL intent -> ' +
|
|
1981
|
+
showToast('Executed NL intent -> ' + toolSlug + ' (' + (res.status || 'ok') + ')');
|
|
1968
1982
|
await refreshOverview();
|
|
1969
1983
|
} catch (err) {
|
|
1970
1984
|
box.textContent = 'NL Execution Error: ' + err.message;
|
|
@@ -2046,9 +2060,15 @@ export function renderConsoleHtml() {
|
|
|
2046
2060
|
showToast('OAuth Connected: ' + prov + ' is now active!');
|
|
2047
2061
|
window.history.replaceState({}, '', '/');
|
|
2048
2062
|
}
|
|
2063
|
+
if (params.get('api_key')) {
|
|
2064
|
+
externalApiKey = params.get('api_key');
|
|
2065
|
+
localStorage.setItem('muxo_external_api_key', externalApiKey);
|
|
2066
|
+
}
|
|
2049
2067
|
if (params.get('claimed')) {
|
|
2050
2068
|
showToast('Workspace ownership claimed (' + params.get('claimed') + ')!');
|
|
2051
2069
|
window.history.replaceState({}, '', '/');
|
|
2070
|
+
} else if (params.get('api_key')) {
|
|
2071
|
+
window.history.replaceState({}, '', '/');
|
|
2052
2072
|
}
|
|
2053
2073
|
}
|
|
2054
2074
|
|
|
@@ -2056,7 +2076,7 @@ export function renderConsoleHtml() {
|
|
|
2056
2076
|
await checkCheckoutReturn();
|
|
2057
2077
|
await refreshOverview();
|
|
2058
2078
|
loadByokKeys().catch(() => {});
|
|
2059
|
-
// Sync live
|
|
2079
|
+
// Sync live cloud infrastructure & connected app providers in background on first load
|
|
2060
2080
|
loadConnections(true).catch(() => {});
|
|
2061
2081
|
});
|
|
2062
2082
|
</script>
|
|
@@ -2257,22 +2277,22 @@ export function renderLandingHtml() {
|
|
|
2257
2277
|
|
|
2258
2278
|
<main class="container">
|
|
2259
2279
|
<section class="hero">
|
|
2260
|
-
<div class="eyebrow">ONE KEY (mk_live_*) · ONE MCP ENDPOINT · 4
|
|
2261
|
-
<h1>Your agent's
|
|
2280
|
+
<div class="eyebrow">ONE KEY (mk_live_*) · ONE MCP ENDPOINT · 4 UNIFIED PILLARS</div>
|
|
2281
|
+
<h1>Your agent's connected apps, cloud infrastructure, workspace memory, and safety guardrails.</h1>
|
|
2262
2282
|
<p class="subtitle">
|
|
2263
|
-
|
|
2283
|
+
Connect once to <strong>Muxo</strong>. Give any AI agent instant access to 850+ SaaS integrations, zero-setup APIs, live cloud database provisioning, persistent workspace memory, and human-in-the-loop safety controls.
|
|
2264
2284
|
</p>
|
|
2265
2285
|
<div style="display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin-bottom:32px">
|
|
2266
2286
|
<a href="/" class="btn btn-primary">Launch Operator Console (app.muxo.ai)</a>
|
|
2267
|
-
<a href="https://docs.muxo.ai" target="_blank" class="btn">Read
|
|
2287
|
+
<a href="https://docs.muxo.ai" target="_blank" class="btn">Read Documentation (docs.muxo.ai)</a>
|
|
2268
2288
|
<a href="/skill.md" target="_blank" class="btn">Inspect /skill.md</a>
|
|
2269
2289
|
</div>
|
|
2270
2290
|
|
|
2271
2291
|
<div class="terminal-box">
|
|
2272
|
-
<div style="color:var(--muted);margin-bottom:8px"># Install the Muxo Plugin (OpenAI Codex, ChatGPT
|
|
2273
|
-
<div style="color:var(--mint)">$
|
|
2274
|
-
<div style="color:var(--muted);margin-top:10px;margin-bottom:6px"># Autonomous Agent
|
|
2275
|
-
<div style="color:var(--cyan)" id="landing-curl-cmd">$
|
|
2292
|
+
<div style="color:var(--muted);margin-bottom:8px"># Install the Muxo Plugin (Claude Code muxo@muxo, OpenAI Codex, ChatGPT & Claude Desktop · Node.js 22+)</div>
|
|
2293
|
+
<div style="color:var(--mint)">$ claude plugin marketplace add https://api.muxo.ai/.claude-plugin/marketplace.json && claude plugin install muxo@muxo</div>
|
|
2294
|
+
<div style="color:var(--muted);margin-top:10px;margin-bottom:6px"># CLI-First Autonomous Agent Onboarding (browser consent only when connecting OAuth apps)</div>
|
|
2295
|
+
<div style="color:var(--cyan)" id="landing-curl-cmd">$ npx -y @muxoai/cli@latest login --signup --name "ProdAgent" && muxo link github --wait</div>
|
|
2276
2296
|
<div style="color:var(--text);margin-top:8px"># 19 Governed MCP Operations · Streamable HTTP + OAuth Callback Handoff:</div>
|
|
2277
2297
|
<div style="color:var(--accent)" id="landing-mcp-urls">MCP: http://localhost:4310/mcp | OAuth Callback: http://localhost:4310/oauth/callback | Skill: http://localhost:4310/skill.md</div>
|
|
2278
2298
|
</div>
|
|
@@ -2281,23 +2301,23 @@ export function renderLandingHtml() {
|
|
|
2281
2301
|
<section id="pillars" class="pillars">
|
|
2282
2302
|
<div class="pillar-card">
|
|
2283
2303
|
<div class="pillar-tag">Pillar 1 · app.* & instant.*</div>
|
|
2284
|
-
<div class="pillar-title">
|
|
2285
|
-
<p style="color:var(--muted);font-size:13.5px">Managed OAuth across GitHub, Gmail, Slack, Notion, Linear, plus zero-auth instant search, scrape,
|
|
2304
|
+
<div class="pillar-title">Connected Apps & Instant Tools</div>
|
|
2305
|
+
<p style="color:var(--muted);font-size:13.5px">Managed OAuth across GitHub, Gmail, Slack, Notion, Linear, plus zero-auth instant search, scrape, SEO, and DNS tools.</p>
|
|
2286
2306
|
</div>
|
|
2287
2307
|
<div class="pillar-card">
|
|
2288
2308
|
<div class="pillar-tag">Pillar 2 · resource.*</div>
|
|
2289
|
-
<div class="pillar-title">
|
|
2309
|
+
<div class="pillar-title">Muxo Cloud Infrastructure</div>
|
|
2290
2310
|
<p style="color:var(--muted);font-size:13.5px">Provision real Neon Postgres, Supabase, Turso, Upstash, Cloudflare, and Vercel resources with AES-256-GCM secret custody.</p>
|
|
2291
2311
|
</div>
|
|
2292
2312
|
<div class="pillar-card">
|
|
2293
2313
|
<div class="pillar-tag">Pillar 3 · /ns/muxo-v5-*</div>
|
|
2294
|
-
<div class="pillar-title">
|
|
2314
|
+
<div class="pillar-title">Muxo Workspace Memory</div>
|
|
2295
2315
|
<p style="color:var(--muted);font-size:13.5px">Isolated per-workspace static facts, dynamic context, and hybrid search automatically recalled before every tool plan.</p>
|
|
2296
2316
|
</div>
|
|
2297
2317
|
<div class="pillar-card">
|
|
2298
|
-
<div class="pillar-tag">Pillar 4 ·
|
|
2299
|
-
<div class="pillar-title">
|
|
2300
|
-
<p style="color:var(--muted);font-size:13.5px">
|
|
2318
|
+
<div class="pillar-tag">Pillar 4 · Safety & Approvals</div>
|
|
2319
|
+
<div class="pillar-title">Muxo Guardrails & Audit Log</div>
|
|
2320
|
+
<p style="color:var(--muted);font-size:13.5px">Automatic prompt-injection scanning, risk-lane policy enforcement, human approval queues, and verifiable audit records.</p>
|
|
2301
2321
|
</div>
|
|
2302
2322
|
</section>
|
|
2303
2323
|
|