@muxoai/platform 0.0.0-stage → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +111 -0
- package/README.md +53 -2
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +527 -0
- package/dist/config.d.ts +20 -0
- package/dist/config.js +89 -0
- package/dist/engine.d.ts +128 -0
- package/dist/engine.js +709 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +7 -0
- package/dist/mcp.d.ts +9 -0
- package/dist/mcp.js +401 -0
- package/dist/providers/composio-instant.d.ts +14 -0
- package/dist/providers/composio-instant.js +372 -0
- package/dist/providers/composio-sdk.d.ts +41 -0
- package/dist/providers/composio-sdk.js +514 -0
- package/dist/providers/microsoft-governance.d.ts +66 -0
- package/dist/providers/microsoft-governance.js +415 -0
- package/dist/providers/stripe-billing.d.ts +31 -0
- package/dist/providers/stripe-billing.js +168 -0
- package/dist/providers/stripe-projects.d.ts +53 -0
- package/dist/providers/stripe-projects.js +607 -0
- package/dist/providers/supermemory.d.ts +64 -0
- package/dist/providers/supermemory.js +224 -0
- package/dist/sdk.d.ts +115 -0
- package/dist/sdk.js +117 -0
- package/dist/server.d.ts +10 -0
- package/dist/server.js +816 -0
- package/dist/store.d.ts +200 -0
- package/dist/store.js +1260 -0
- package/dist/types.d.ts +273 -0
- package/dist/types.js +1 -0
- package/dist/ui/console-html.d.ts +2 -0
- package/dist/ui/console-html.js +2153 -0
- package/package.json +74 -4
- package/plugins/muxo/.app.json +8 -0
- package/plugins/muxo/.claude-plugin/plugin.json +16 -0
- package/plugins/muxo/.codex-plugin/plugin.json +51 -0
- package/plugins/muxo/.mcp.json +8 -0
- package/plugins/muxo/assets/logo.png +0 -0
- package/plugins/muxo/assets/logo.svg +6 -0
- package/plugins/muxo/hooks/hooks.json +27 -0
- package/plugins/muxo/hooks/session-start.sh +85 -0
- package/plugins/muxo/hooks/user-prompt-submit.sh +45 -0
- package/plugins/muxo/skills/muxo/SKILL.md +25 -0
- package/plugins/muxo/skills/muxo/references/cli.md +57 -0
- package/plugins/muxo/skills/muxo/references/mcp.md +25 -0
- package/src/catalogues/stripe-projects-catalog.json +9832 -0
- package/vendor/microsoft-governance/README.md +363 -0
- package/vendor/microsoft-governance/dist/audit.d.ts +26 -0
- package/vendor/microsoft-governance/dist/audit.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/audit.js +107 -0
- package/vendor/microsoft-governance/dist/audit.js.map +1 -0
- package/vendor/microsoft-governance/dist/cascade-containment.d.ts +84 -0
- package/vendor/microsoft-governance/dist/cascade-containment.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/cascade-containment.js +387 -0
- package/vendor/microsoft-governance/dist/cascade-containment.js.map +1 -0
- package/vendor/microsoft-governance/dist/client.d.ts +34 -0
- package/vendor/microsoft-governance/dist/client.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/client.js +112 -0
- package/vendor/microsoft-governance/dist/client.js.map +1 -0
- package/vendor/microsoft-governance/dist/context-poisoning.d.ts +58 -0
- package/vendor/microsoft-governance/dist/context-poisoning.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/context-poisoning.js +410 -0
- package/vendor/microsoft-governance/dist/context-poisoning.js.map +1 -0
- package/vendor/microsoft-governance/dist/credential-vault.d.ts +213 -0
- package/vendor/microsoft-governance/dist/credential-vault.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/credential-vault.js +567 -0
- package/vendor/microsoft-governance/dist/credential-vault.js.map +1 -0
- package/vendor/microsoft-governance/dist/discovery.d.ts +80 -0
- package/vendor/microsoft-governance/dist/discovery.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/discovery.js +404 -0
- package/vendor/microsoft-governance/dist/discovery.js.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/channel.d.ts +29 -0
- package/vendor/microsoft-governance/dist/encryption/channel.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/channel.js +78 -0
- package/vendor/microsoft-governance/dist/encryption/channel.js.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/index.d.ts +9 -0
- package/vendor/microsoft-governance/dist/encryption/index.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/index.js +23 -0
- package/vendor/microsoft-governance/dist/encryption/index.js.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/mesh-client.d.ts +267 -0
- package/vendor/microsoft-governance/dist/encryption/mesh-client.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/mesh-client.js +1001 -0
- package/vendor/microsoft-governance/dist/encryption/mesh-client.js.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/ratchet.d.ts +38 -0
- package/vendor/microsoft-governance/dist/encryption/ratchet.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/ratchet.js +223 -0
- package/vendor/microsoft-governance/dist/encryption/ratchet.js.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/registry-client.d.ts +136 -0
- package/vendor/microsoft-governance/dist/encryption/registry-client.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/registry-client.js +369 -0
- package/vendor/microsoft-governance/dist/encryption/registry-client.js.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/x3dh.d.ts +80 -0
- package/vendor/microsoft-governance/dist/encryption/x3dh.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/encryption/x3dh.js +238 -0
- package/vendor/microsoft-governance/dist/encryption/x3dh.js.map +1 -0
- package/vendor/microsoft-governance/dist/framework-adapter.d.ts +63 -0
- package/vendor/microsoft-governance/dist/framework-adapter.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/framework-adapter.js +253 -0
- package/vendor/microsoft-governance/dist/framework-adapter.js.map +1 -0
- package/vendor/microsoft-governance/dist/identity.d.ts +124 -0
- package/vendor/microsoft-governance/dist/identity.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/identity.js +446 -0
- package/vendor/microsoft-governance/dist/identity.js.map +1 -0
- package/vendor/microsoft-governance/dist/index.d.ts +39 -0
- package/vendor/microsoft-governance/dist/index.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/index.js +95 -0
- package/vendor/microsoft-governance/dist/index.js.map +1 -0
- package/vendor/microsoft-governance/dist/kill-switch.d.ts +22 -0
- package/vendor/microsoft-governance/dist/kill-switch.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/kill-switch.js +60 -0
- package/vendor/microsoft-governance/dist/kill-switch.js.map +1 -0
- package/vendor/microsoft-governance/dist/lifecycle.d.ts +50 -0
- package/vendor/microsoft-governance/dist/lifecycle.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/lifecycle.js +113 -0
- package/vendor/microsoft-governance/dist/lifecycle.js.map +1 -0
- package/vendor/microsoft-governance/dist/mcp.d.ts +41 -0
- package/vendor/microsoft-governance/dist/mcp.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/mcp.js +233 -0
- package/vendor/microsoft-governance/dist/mcp.js.map +1 -0
- package/vendor/microsoft-governance/dist/metrics.d.ts +123 -0
- package/vendor/microsoft-governance/dist/metrics.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/metrics.js +289 -0
- package/vendor/microsoft-governance/dist/metrics.js.map +1 -0
- package/vendor/microsoft-governance/dist/oci-manifest.d.ts +49 -0
- package/vendor/microsoft-governance/dist/oci-manifest.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/oci-manifest.js +182 -0
- package/vendor/microsoft-governance/dist/oci-manifest.js.map +1 -0
- package/vendor/microsoft-governance/dist/policy-backends/cedar.d.ts +15 -0
- package/vendor/microsoft-governance/dist/policy-backends/cedar.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/policy-backends/cedar.js +88 -0
- package/vendor/microsoft-governance/dist/policy-backends/cedar.js.map +1 -0
- package/vendor/microsoft-governance/dist/policy-backends/opa.d.ts +17 -0
- package/vendor/microsoft-governance/dist/policy-backends/opa.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/policy-backends/opa.js +74 -0
- package/vendor/microsoft-governance/dist/policy-backends/opa.js.map +1 -0
- package/vendor/microsoft-governance/dist/policy.d.ts +77 -0
- package/vendor/microsoft-governance/dist/policy.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/policy.js +760 -0
- package/vendor/microsoft-governance/dist/policy.js.map +1 -0
- package/vendor/microsoft-governance/dist/prompt-defense.d.ts +37 -0
- package/vendor/microsoft-governance/dist/prompt-defense.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/prompt-defense.js +229 -0
- package/vendor/microsoft-governance/dist/prompt-defense.js.map +1 -0
- package/vendor/microsoft-governance/dist/protocol-facets.d.ts +87 -0
- package/vendor/microsoft-governance/dist/protocol-facets.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/protocol-facets.js +728 -0
- package/vendor/microsoft-governance/dist/protocol-facets.js.map +1 -0
- package/vendor/microsoft-governance/dist/rings.d.ts +17 -0
- package/vendor/microsoft-governance/dist/rings.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/rings.js +61 -0
- package/vendor/microsoft-governance/dist/rings.js.map +1 -0
- package/vendor/microsoft-governance/dist/sandbox.d.ts +61 -0
- package/vendor/microsoft-governance/dist/sandbox.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/sandbox.js +199 -0
- package/vendor/microsoft-governance/dist/sandbox.js.map +1 -0
- package/vendor/microsoft-governance/dist/surface-parity.d.ts +45 -0
- package/vendor/microsoft-governance/dist/surface-parity.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/surface-parity.js +216 -0
- package/vendor/microsoft-governance/dist/surface-parity.js.map +1 -0
- package/vendor/microsoft-governance/dist/trust.d.ts +28 -0
- package/vendor/microsoft-governance/dist/trust.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/trust.js +209 -0
- package/vendor/microsoft-governance/dist/trust.js.map +1 -0
- package/vendor/microsoft-governance/dist/types.d.ts +422 -0
- package/vendor/microsoft-governance/dist/types.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/types.js +29 -0
- package/vendor/microsoft-governance/dist/types.js.map +1 -0
- package/vendor/microsoft-governance/dist/verify.d.ts +135 -0
- package/vendor/microsoft-governance/dist/verify.d.ts.map +1 -0
- package/vendor/microsoft-governance/dist/verify.js +356 -0
- package/vendor/microsoft-governance/dist/verify.js.map +1 -0
|
@@ -0,0 +1,2153 @@
|
|
|
1
|
+
export function renderConsoleHtml() {
|
|
2
|
+
return `<!DOCTYPE html>
|
|
3
|
+
<html lang="en" data-theme="dark">
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>Muxo — Unified Agent Execution & Infrastructure Platform</title>
|
|
8
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
9
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
10
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Space+Grotesk:wght@600;700&display=swap" rel="stylesheet">
|
|
11
|
+
<style>
|
|
12
|
+
:root {
|
|
13
|
+
--bg-canvas: #050507;
|
|
14
|
+
--bg-surface: #0D0F14;
|
|
15
|
+
--bg-elevated: #141720;
|
|
16
|
+
--bg-hover: #1C202C;
|
|
17
|
+
--border: #232736;
|
|
18
|
+
--border-strong: #343B52;
|
|
19
|
+
--text-primary: #F5F2EB;
|
|
20
|
+
--text-secondary: #A0A6BA;
|
|
21
|
+
--text-muted: #687089;
|
|
22
|
+
--accent: #FF5A1F;
|
|
23
|
+
--accent-hover: #E04812;
|
|
24
|
+
--accent-soft: rgba(255, 90, 31, 0.15);
|
|
25
|
+
--emerald: #2DD4BF;
|
|
26
|
+
--emerald-soft: rgba(45, 212, 191, 0.14);
|
|
27
|
+
--amber: #F59E0B;
|
|
28
|
+
--amber-soft: rgba(245, 158, 11, 0.14);
|
|
29
|
+
--rose: #F43F5E;
|
|
30
|
+
--rose-soft: rgba(244, 63, 94, 0.14);
|
|
31
|
+
--cyan: #38BDF8;
|
|
32
|
+
--cyan-soft: rgba(56, 189, 248, 0.14);
|
|
33
|
+
--radius: 8px;
|
|
34
|
+
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
|
35
|
+
--font-display: 'Space Grotesk', 'Inter', sans-serif;
|
|
36
|
+
--font-mono: 'JetBrains Mono', monospace;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
[data-theme="light"] {
|
|
40
|
+
--bg-canvas: #F8FAFC;
|
|
41
|
+
--bg-surface: #FFFFFF;
|
|
42
|
+
--bg-elevated: #F1F5F9;
|
|
43
|
+
--bg-hover: #E2E8F0;
|
|
44
|
+
--border: #E2E8F0;
|
|
45
|
+
--border-strong: #CBD5E1;
|
|
46
|
+
--text-primary: #0F172A;
|
|
47
|
+
--text-secondary: #475569;
|
|
48
|
+
--text-muted: #64748B;
|
|
49
|
+
--accent: #4F46E5;
|
|
50
|
+
--accent-hover: #4338CA;
|
|
51
|
+
--accent-soft: rgba(79, 70, 229, 0.1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
55
|
+
body {
|
|
56
|
+
font-family: var(--font-sans);
|
|
57
|
+
background: var(--bg-canvas);
|
|
58
|
+
color: var(--text-primary);
|
|
59
|
+
font-size: 14px;
|
|
60
|
+
line-height: 1.5;
|
|
61
|
+
-webkit-font-smoothing: antialiased;
|
|
62
|
+
}
|
|
63
|
+
code, pre, .mono {
|
|
64
|
+
font-family: var(--font-mono);
|
|
65
|
+
font-variant-numeric: tabular-nums;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Layout Shell */
|
|
69
|
+
.shell {
|
|
70
|
+
display: grid;
|
|
71
|
+
grid-template-columns: 248px 1fr;
|
|
72
|
+
min-height: 100vh;
|
|
73
|
+
}
|
|
74
|
+
.sidebar {
|
|
75
|
+
background: var(--bg-surface);
|
|
76
|
+
border-right: 1px solid var(--border);
|
|
77
|
+
display: flex;
|
|
78
|
+
flex-direction: column;
|
|
79
|
+
padding: 18px 14px;
|
|
80
|
+
position: sticky;
|
|
81
|
+
top: 0;
|
|
82
|
+
height: 100vh;
|
|
83
|
+
}
|
|
84
|
+
.brand {
|
|
85
|
+
display: flex;
|
|
86
|
+
align-items: center;
|
|
87
|
+
justify-content: space-between;
|
|
88
|
+
padding: 4px 8px 18px;
|
|
89
|
+
border-bottom: 1px solid var(--border);
|
|
90
|
+
margin-bottom: 16px;
|
|
91
|
+
}
|
|
92
|
+
.brand-logo {
|
|
93
|
+
display: flex;
|
|
94
|
+
align-items: center;
|
|
95
|
+
gap: 10px;
|
|
96
|
+
font-weight: 700;
|
|
97
|
+
font-size: 16px;
|
|
98
|
+
letter-spacing: -0.02em;
|
|
99
|
+
}
|
|
100
|
+
.brand-mark {
|
|
101
|
+
width: 28px;
|
|
102
|
+
height: 28px;
|
|
103
|
+
border-radius: 6px;
|
|
104
|
+
background: linear-gradient(135deg, #6366F1 0%, #06B6D4 100%);
|
|
105
|
+
display: grid;
|
|
106
|
+
place-items: center;
|
|
107
|
+
color: #fff;
|
|
108
|
+
font-weight: 700;
|
|
109
|
+
font-size: 14px;
|
|
110
|
+
font-family: var(--font-mono);
|
|
111
|
+
}
|
|
112
|
+
.tier-badge {
|
|
113
|
+
font-size: 11px;
|
|
114
|
+
font-weight: 600;
|
|
115
|
+
text-transform: uppercase;
|
|
116
|
+
padding: 2px 7px;
|
|
117
|
+
border-radius: 99px;
|
|
118
|
+
background: var(--accent-soft);
|
|
119
|
+
color: var(--accent);
|
|
120
|
+
border: 1px solid rgba(99, 102, 241, 0.3);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.nav-section-label {
|
|
124
|
+
font-size: 11px;
|
|
125
|
+
font-weight: 600;
|
|
126
|
+
text-transform: uppercase;
|
|
127
|
+
letter-spacing: 0.06em;
|
|
128
|
+
color: var(--text-muted);
|
|
129
|
+
padding: 10px 10px 6px;
|
|
130
|
+
}
|
|
131
|
+
.nav-btn {
|
|
132
|
+
display: flex;
|
|
133
|
+
align-items: center;
|
|
134
|
+
justify-content: space-between;
|
|
135
|
+
width: 100%;
|
|
136
|
+
text-align: left;
|
|
137
|
+
padding: 9px 10px;
|
|
138
|
+
border-radius: 6px;
|
|
139
|
+
border: none;
|
|
140
|
+
background: transparent;
|
|
141
|
+
color: var(--text-secondary);
|
|
142
|
+
font-size: 13.5px;
|
|
143
|
+
font-weight: 500;
|
|
144
|
+
cursor: pointer;
|
|
145
|
+
transition: all 0.12s ease;
|
|
146
|
+
margin-bottom: 2px;
|
|
147
|
+
}
|
|
148
|
+
.nav-btn:hover {
|
|
149
|
+
background: var(--bg-hover);
|
|
150
|
+
color: var(--text-primary);
|
|
151
|
+
}
|
|
152
|
+
.nav-btn.active {
|
|
153
|
+
background: var(--accent-soft);
|
|
154
|
+
color: var(--accent);
|
|
155
|
+
font-weight: 600;
|
|
156
|
+
}
|
|
157
|
+
.nav-pill {
|
|
158
|
+
font-family: var(--font-mono);
|
|
159
|
+
font-size: 11px;
|
|
160
|
+
padding: 1px 6px;
|
|
161
|
+
border-radius: 99px;
|
|
162
|
+
background: var(--bg-elevated);
|
|
163
|
+
color: var(--text-secondary);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.sidebar-footer {
|
|
167
|
+
margin-top: auto;
|
|
168
|
+
padding-top: 14px;
|
|
169
|
+
border-top: 1px solid var(--border);
|
|
170
|
+
display: flex;
|
|
171
|
+
flex-direction: column;
|
|
172
|
+
gap: 10px;
|
|
173
|
+
}
|
|
174
|
+
.meter-box {
|
|
175
|
+
background: var(--bg-elevated);
|
|
176
|
+
border: 1px solid var(--border);
|
|
177
|
+
border-radius: var(--radius);
|
|
178
|
+
padding: 10px 12px;
|
|
179
|
+
font-size: 12px;
|
|
180
|
+
}
|
|
181
|
+
.meter-row {
|
|
182
|
+
display: flex;
|
|
183
|
+
justify-content: space-between;
|
|
184
|
+
margin-bottom: 5px;
|
|
185
|
+
}
|
|
186
|
+
.progress-track {
|
|
187
|
+
height: 5px;
|
|
188
|
+
background: var(--border);
|
|
189
|
+
border-radius: 99px;
|
|
190
|
+
overflow: hidden;
|
|
191
|
+
margin-bottom: 8px;
|
|
192
|
+
}
|
|
193
|
+
.progress-fill {
|
|
194
|
+
height: 100%;
|
|
195
|
+
background: var(--accent);
|
|
196
|
+
border-radius: 99px;
|
|
197
|
+
transition: width 0.25s ease;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/* Main Content */
|
|
201
|
+
.main {
|
|
202
|
+
display: flex;
|
|
203
|
+
flex-direction: column;
|
|
204
|
+
min-width: 0;
|
|
205
|
+
}
|
|
206
|
+
.topbar {
|
|
207
|
+
height: 58px;
|
|
208
|
+
border-bottom: 1px solid var(--border);
|
|
209
|
+
background: var(--bg-surface);
|
|
210
|
+
padding: 0 28px;
|
|
211
|
+
display: flex;
|
|
212
|
+
align-items: center;
|
|
213
|
+
justify-content: space-between;
|
|
214
|
+
position: sticky;
|
|
215
|
+
top: 0;
|
|
216
|
+
z-index: 10;
|
|
217
|
+
}
|
|
218
|
+
.topbar-title {
|
|
219
|
+
font-size: 15px;
|
|
220
|
+
font-weight: 600;
|
|
221
|
+
display: flex;
|
|
222
|
+
align-items: center;
|
|
223
|
+
gap: 10px;
|
|
224
|
+
}
|
|
225
|
+
.topbar-actions {
|
|
226
|
+
display: flex;
|
|
227
|
+
align-items: center;
|
|
228
|
+
gap: 10px;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.content {
|
|
232
|
+
padding: 28px;
|
|
233
|
+
max-width: 1320px;
|
|
234
|
+
width: 100%;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/* Cards & Grids */
|
|
238
|
+
.kpi-grid {
|
|
239
|
+
display: grid;
|
|
240
|
+
grid-template-columns: repeat(4, 1fr);
|
|
241
|
+
gap: 14px;
|
|
242
|
+
margin-bottom: 24px;
|
|
243
|
+
}
|
|
244
|
+
.card {
|
|
245
|
+
background: var(--bg-surface);
|
|
246
|
+
border: 1px solid var(--border);
|
|
247
|
+
border-radius: var(--radius);
|
|
248
|
+
padding: 18px;
|
|
249
|
+
}
|
|
250
|
+
.kpi-label {
|
|
251
|
+
font-size: 12px;
|
|
252
|
+
color: var(--text-secondary);
|
|
253
|
+
margin-bottom: 6px;
|
|
254
|
+
display: flex;
|
|
255
|
+
justify-content: space-between;
|
|
256
|
+
align-items: center;
|
|
257
|
+
}
|
|
258
|
+
.kpi-value {
|
|
259
|
+
font-size: 24px;
|
|
260
|
+
font-weight: 700;
|
|
261
|
+
font-family: var(--font-mono);
|
|
262
|
+
letter-spacing: -0.02em;
|
|
263
|
+
}
|
|
264
|
+
.kpi-sub {
|
|
265
|
+
font-size: 12px;
|
|
266
|
+
color: var(--text-muted);
|
|
267
|
+
margin-top: 4px;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.grid-2 {
|
|
271
|
+
display: grid;
|
|
272
|
+
grid-template-columns: 1.2fr 0.8fr;
|
|
273
|
+
gap: 18px;
|
|
274
|
+
margin-bottom: 24px;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.section-header {
|
|
278
|
+
display: flex;
|
|
279
|
+
align-items: center;
|
|
280
|
+
justify-content: space-between;
|
|
281
|
+
margin-bottom: 14px;
|
|
282
|
+
gap: 12px;
|
|
283
|
+
}
|
|
284
|
+
.section-title {
|
|
285
|
+
font-size: 15px;
|
|
286
|
+
font-weight: 600;
|
|
287
|
+
}
|
|
288
|
+
.section-sub {
|
|
289
|
+
font-size: 12.5px;
|
|
290
|
+
color: var(--text-secondary);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/* Buttons & Inputs */
|
|
294
|
+
.btn {
|
|
295
|
+
display: inline-flex;
|
|
296
|
+
align-items: center;
|
|
297
|
+
gap: 7px;
|
|
298
|
+
padding: 7px 13px;
|
|
299
|
+
border-radius: 6px;
|
|
300
|
+
font-size: 13px;
|
|
301
|
+
font-weight: 500;
|
|
302
|
+
border: 1px solid var(--border-strong);
|
|
303
|
+
background: var(--bg-elevated);
|
|
304
|
+
color: var(--text-primary);
|
|
305
|
+
cursor: pointer;
|
|
306
|
+
transition: all 0.12s ease;
|
|
307
|
+
text-decoration: none;
|
|
308
|
+
}
|
|
309
|
+
.btn:hover { background: var(--bg-hover); }
|
|
310
|
+
.btn-primary {
|
|
311
|
+
background: var(--accent);
|
|
312
|
+
border-color: var(--accent);
|
|
313
|
+
color: #fff;
|
|
314
|
+
}
|
|
315
|
+
.btn-primary:hover { background: var(--accent-hover); }
|
|
316
|
+
.btn-emerald {
|
|
317
|
+
background: var(--emerald);
|
|
318
|
+
border-color: var(--emerald);
|
|
319
|
+
color: #fff;
|
|
320
|
+
}
|
|
321
|
+
.btn-danger {
|
|
322
|
+
background: var(--rose-soft);
|
|
323
|
+
border-color: rgba(244, 63, 94, 0.35);
|
|
324
|
+
color: var(--rose);
|
|
325
|
+
}
|
|
326
|
+
.btn-sm {
|
|
327
|
+
padding: 4px 9px;
|
|
328
|
+
font-size: 12px;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
input[type="text"], input[type="email"], input[type="password"], select, textarea {
|
|
332
|
+
background: var(--bg-elevated);
|
|
333
|
+
border: 1px solid var(--border-strong);
|
|
334
|
+
color: var(--text-primary);
|
|
335
|
+
border-radius: 6px;
|
|
336
|
+
padding: 8px 12px;
|
|
337
|
+
font-size: 13px;
|
|
338
|
+
font-family: inherit;
|
|
339
|
+
width: 100%;
|
|
340
|
+
}
|
|
341
|
+
input:focus, select:focus, textarea:focus {
|
|
342
|
+
outline: none;
|
|
343
|
+
border-color: var(--accent);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/* Badges */
|
|
347
|
+
.badge {
|
|
348
|
+
display: inline-flex;
|
|
349
|
+
align-items: center;
|
|
350
|
+
gap: 5px;
|
|
351
|
+
padding: 2px 8px;
|
|
352
|
+
border-radius: 99px;
|
|
353
|
+
font-size: 11px;
|
|
354
|
+
font-weight: 600;
|
|
355
|
+
font-family: var(--font-mono);
|
|
356
|
+
}
|
|
357
|
+
.badge-instant { background: var(--cyan-soft); color: var(--cyan); }
|
|
358
|
+
.badge-sdk { background: var(--accent-soft); color: var(--accent); }
|
|
359
|
+
.badge-projects { background: var(--emerald-soft); color: var(--emerald); }
|
|
360
|
+
.badge-warn { background: var(--amber-soft); color: var(--amber); }
|
|
361
|
+
.badge-danger { background: var(--rose-soft); color: var(--rose); }
|
|
362
|
+
|
|
363
|
+
/* Tables & Tool Rows */
|
|
364
|
+
.table-wrap {
|
|
365
|
+
overflow-x: auto;
|
|
366
|
+
border: 1px solid var(--border);
|
|
367
|
+
border-radius: var(--radius);
|
|
368
|
+
background: var(--bg-surface);
|
|
369
|
+
}
|
|
370
|
+
table {
|
|
371
|
+
width: 100%;
|
|
372
|
+
border-collapse: collapse;
|
|
373
|
+
text-align: left;
|
|
374
|
+
}
|
|
375
|
+
th {
|
|
376
|
+
font-size: 11px;
|
|
377
|
+
font-weight: 600;
|
|
378
|
+
text-transform: uppercase;
|
|
379
|
+
letter-spacing: 0.05em;
|
|
380
|
+
color: var(--text-muted);
|
|
381
|
+
padding: 10px 14px;
|
|
382
|
+
border-bottom: 1px solid var(--border);
|
|
383
|
+
background: var(--bg-elevated);
|
|
384
|
+
}
|
|
385
|
+
td {
|
|
386
|
+
padding: 12px 14px;
|
|
387
|
+
border-bottom: 1px solid var(--border);
|
|
388
|
+
font-size: 13px;
|
|
389
|
+
vertical-align: middle;
|
|
390
|
+
}
|
|
391
|
+
tr:last-child td { border-bottom: none; }
|
|
392
|
+
tr:hover td { background: rgba(255, 255, 255, 0.015); }
|
|
393
|
+
|
|
394
|
+
.tool-grid {
|
|
395
|
+
display: grid;
|
|
396
|
+
grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));
|
|
397
|
+
gap: 14px;
|
|
398
|
+
}
|
|
399
|
+
.tool-card {
|
|
400
|
+
background: var(--bg-surface);
|
|
401
|
+
border: 1px solid var(--border);
|
|
402
|
+
border-radius: var(--radius);
|
|
403
|
+
padding: 16px;
|
|
404
|
+
display: flex;
|
|
405
|
+
flex-direction: column;
|
|
406
|
+
justify-content: space-between;
|
|
407
|
+
gap: 12px;
|
|
408
|
+
transition: border-color 0.15s ease;
|
|
409
|
+
}
|
|
410
|
+
.tool-card:hover {
|
|
411
|
+
border-color: var(--border-strong);
|
|
412
|
+
}
|
|
413
|
+
.tool-slug {
|
|
414
|
+
font-family: var(--font-mono);
|
|
415
|
+
font-size: 12px;
|
|
416
|
+
color: var(--accent);
|
|
417
|
+
word-break: break-all;
|
|
418
|
+
}
|
|
419
|
+
.tool-desc {
|
|
420
|
+
font-size: 12.5px;
|
|
421
|
+
color: var(--text-secondary);
|
|
422
|
+
display: -webkit-box;
|
|
423
|
+
-webkit-line-clamp: 2;
|
|
424
|
+
-webkit-box-orient: vertical;
|
|
425
|
+
overflow: hidden;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
.code-block {
|
|
429
|
+
background: #07080C;
|
|
430
|
+
border: 1px solid var(--border);
|
|
431
|
+
border-radius: 6px;
|
|
432
|
+
padding: 12px 14px;
|
|
433
|
+
font-family: var(--font-mono);
|
|
434
|
+
font-size: 12px;
|
|
435
|
+
color: #E2E8F0;
|
|
436
|
+
overflow-x: auto;
|
|
437
|
+
white-space: pre-wrap;
|
|
438
|
+
word-break: break-word;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/* Modal */
|
|
442
|
+
.modal-backdrop {
|
|
443
|
+
position: fixed;
|
|
444
|
+
inset: 0;
|
|
445
|
+
background: rgba(0, 0, 0, 0.68);
|
|
446
|
+
backdrop-filter: blur(3px);
|
|
447
|
+
display: none;
|
|
448
|
+
place-items: center;
|
|
449
|
+
z-index: 100;
|
|
450
|
+
padding: 20px;
|
|
451
|
+
}
|
|
452
|
+
.modal-backdrop.open { display: grid; }
|
|
453
|
+
.modal {
|
|
454
|
+
background: var(--bg-surface);
|
|
455
|
+
border: 1px solid var(--border-strong);
|
|
456
|
+
border-radius: 10px;
|
|
457
|
+
width: 100%;
|
|
458
|
+
max-width: 640px;
|
|
459
|
+
max-height: 88vh;
|
|
460
|
+
overflow-y: auto;
|
|
461
|
+
padding: 22px;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
.toast {
|
|
465
|
+
position: fixed;
|
|
466
|
+
bottom: 22px;
|
|
467
|
+
right: 22px;
|
|
468
|
+
background: var(--bg-elevated);
|
|
469
|
+
border: 1px solid var(--accent);
|
|
470
|
+
color: var(--text-primary);
|
|
471
|
+
padding: 12px 16px;
|
|
472
|
+
border-radius: 8px;
|
|
473
|
+
font-size: 13px;
|
|
474
|
+
z-index: 200;
|
|
475
|
+
display: none;
|
|
476
|
+
box-shadow: 0 10px 30px rgba(0,0,0,0.4);
|
|
477
|
+
}
|
|
478
|
+
.toast.show { display: block; }
|
|
479
|
+
.hidden { display: none !important; }
|
|
480
|
+
.filter-bar {
|
|
481
|
+
display: flex;
|
|
482
|
+
gap: 10px;
|
|
483
|
+
margin-bottom: 16px;
|
|
484
|
+
flex-wrap: wrap;
|
|
485
|
+
}
|
|
486
|
+
</style>
|
|
487
|
+
</head>
|
|
488
|
+
<body>
|
|
489
|
+
<div class="shell">
|
|
490
|
+
<aside class="sidebar">
|
|
491
|
+
<div class="brand">
|
|
492
|
+
<div class="brand-logo">
|
|
493
|
+
<div class="brand-mark">M</div>
|
|
494
|
+
<span>Muxo</span>
|
|
495
|
+
</div>
|
|
496
|
+
<span id="sidebar-tier" class="tier-badge">FREE</span>
|
|
497
|
+
</div>
|
|
498
|
+
|
|
499
|
+
<div class="nav-section-label">Control Plane</div>
|
|
500
|
+
<button class="nav-btn active" onclick="switchTab('overview', this)">
|
|
501
|
+
<span>Overview & Quickstart</span>
|
|
502
|
+
</button>
|
|
503
|
+
<button class="nav-btn" onclick="switchTab('catalog', this)">
|
|
504
|
+
<span>Unified Catalog</span>
|
|
505
|
+
<span id="nav-catalog-count" class="nav-pill">140+</span>
|
|
506
|
+
</button>
|
|
507
|
+
<button class="nav-btn" onclick="switchTab('infrastructure', this)">
|
|
508
|
+
<span>Cloud Infrastructure</span>
|
|
509
|
+
<span id="nav-res-count" class="nav-pill">0</span>
|
|
510
|
+
</button>
|
|
511
|
+
<button class="nav-btn" onclick="switchTab('connections', this)">
|
|
512
|
+
<span>Connected Apps</span>
|
|
513
|
+
<span id="nav-conn-count" class="nav-pill">0</span>
|
|
514
|
+
</button>
|
|
515
|
+
|
|
516
|
+
<div class="nav-section-label">Brain & Governance</div>
|
|
517
|
+
<button class="nav-btn" onclick="switchTab('memory', this)">
|
|
518
|
+
<span>Supermemory Brain</span>
|
|
519
|
+
<span id="nav-mem-count" class="nav-pill">v5</span>
|
|
520
|
+
</button>
|
|
521
|
+
<button class="nav-btn" onclick="switchTab('governance', this)">
|
|
522
|
+
<span>Microsoft Governance</span>
|
|
523
|
+
<span id="nav-plan-count" class="nav-pill">0</span>
|
|
524
|
+
</button>
|
|
525
|
+
<button class="nav-btn" onclick="switchTab('receipts', this)">
|
|
526
|
+
<span>Runs & Signed Receipts</span>
|
|
527
|
+
<span id="nav-run-count" class="nav-pill">0</span>
|
|
528
|
+
</button>
|
|
529
|
+
<button class="nav-btn" onclick="switchTab('billing', this)">
|
|
530
|
+
<span>Billing & Credits</span>
|
|
531
|
+
</button>
|
|
532
|
+
|
|
533
|
+
<div class="sidebar-footer">
|
|
534
|
+
<div class="meter-box">
|
|
535
|
+
<div class="meter-row">
|
|
536
|
+
<span style="color:var(--text-secondary)">Monthly Actions</span>
|
|
537
|
+
<span id="meter-actions-text" class="mono">0 / 1,000</span>
|
|
538
|
+
</div>
|
|
539
|
+
<div class="progress-track">
|
|
540
|
+
<div id="meter-actions-bar" class="progress-fill" style="width: 2%"></div>
|
|
541
|
+
</div>
|
|
542
|
+
<div class="meter-row" style="margin-bottom:0">
|
|
543
|
+
<span style="color:var(--text-secondary)">Instant Credits</span>
|
|
544
|
+
<span id="meter-credits-text" class="mono" style="color:var(--emerald);font-weight:600">250</span>
|
|
545
|
+
</div>
|
|
546
|
+
</div>
|
|
547
|
+
<button class="btn" style="width:100%;justify-content:center" onclick="toggleTheme()">
|
|
548
|
+
Toggle Dark / Light Theme
|
|
549
|
+
</button>
|
|
550
|
+
</div>
|
|
551
|
+
</aside>
|
|
552
|
+
|
|
553
|
+
<div class="main">
|
|
554
|
+
<header class="topbar">
|
|
555
|
+
<div class="topbar-title">
|
|
556
|
+
<span id="workspace-name">Muxo Default Workspace</span>
|
|
557
|
+
<span id="workspace-slug" class="mono" style="font-size:12px;color:var(--text-muted)"></span>
|
|
558
|
+
<span id="workspace-auth-badge" class="badge badge-projects" style="font-size:10.5px">Default Session</span>
|
|
559
|
+
</div>
|
|
560
|
+
<div class="topbar-actions">
|
|
561
|
+
<button class="btn btn-sm" onclick="switchExternalWorkspacePrompt()" title="Switch Console to an external mk_live_* workspace or create a new external user workspace">
|
|
562
|
+
🔑 External User / Key
|
|
563
|
+
</button>
|
|
564
|
+
<button id="reset-workspace-btn" class="btn btn-sm hidden" onclick="clearExternalWorkspaceKey()">
|
|
565
|
+
Reset to Default
|
|
566
|
+
</button>
|
|
567
|
+
<a href="/landing" class="btn btn-sm">muxo.ai Landing</a>
|
|
568
|
+
<a href="https://docs.muxo.ai" target="_blank" class="btn btn-sm">docs.muxo.ai</a>
|
|
569
|
+
<a href="/skill.md" target="_blank" class="btn btn-sm">Agent Skill (/skill.md)</a>
|
|
570
|
+
<button class="btn btn-sm btn-primary" onclick="openExecuteModal('instant.hackernews.top_stories')">
|
|
571
|
+
+ Run Instant Tool
|
|
572
|
+
</button>
|
|
573
|
+
</div>
|
|
574
|
+
</header>
|
|
575
|
+
|
|
576
|
+
<main class="content">
|
|
577
|
+
<!-- TAB 1: OVERVIEW -->
|
|
578
|
+
<section id="tab-overview" class="tab-pane">
|
|
579
|
+
<div class="kpi-grid">
|
|
580
|
+
<div class="card">
|
|
581
|
+
<div class="kpi-label">
|
|
582
|
+
<span>4-Pillar Boundary</span>
|
|
583
|
+
<span class="badge badge-instant">LIVE</span>
|
|
584
|
+
</div>
|
|
585
|
+
<div class="kpi-value" id="kpi-providers">4 Pillars</div>
|
|
586
|
+
<div class="kpi-sub">Composio + Stripe Projects + MS Governance + Supermemory</div>
|
|
587
|
+
</div>
|
|
588
|
+
<div class="card">
|
|
589
|
+
<div class="kpi-label">
|
|
590
|
+
<span>Linked Providers</span>
|
|
591
|
+
<span class="badge badge-projects">READY</span>
|
|
592
|
+
</div>
|
|
593
|
+
<div class="kpi-value" id="kpi-connections">0</div>
|
|
594
|
+
<div class="kpi-sub">OAuth Apps & Cloud Infrastructure</div>
|
|
595
|
+
</div>
|
|
596
|
+
<div class="card">
|
|
597
|
+
<div class="kpi-label">
|
|
598
|
+
<span>Governed Runs</span>
|
|
599
|
+
<span class="badge badge-sdk">Ed25519 + SHA256</span>
|
|
600
|
+
</div>
|
|
601
|
+
<div class="kpi-value" id="kpi-runs">0</div>
|
|
602
|
+
<div class="kpi-sub">Signed DecisionRecords & Receipts</div>
|
|
603
|
+
</div>
|
|
604
|
+
<div class="card">
|
|
605
|
+
<div class="kpi-label">
|
|
606
|
+
<span>Workspace Credits</span>
|
|
607
|
+
<span id="kpi-tier-badge" class="badge badge-warn">FREE PLAN</span>
|
|
608
|
+
</div>
|
|
609
|
+
<div class="kpi-value" id="kpi-credits">250</div>
|
|
610
|
+
<div class="kpi-sub">Available for Instant & Provisioning</div>
|
|
611
|
+
</div>
|
|
612
|
+
</div>
|
|
613
|
+
|
|
614
|
+
<div class="grid-2">
|
|
615
|
+
<div class="card">
|
|
616
|
+
<div class="section-header">
|
|
617
|
+
<div>
|
|
618
|
+
<div class="section-title">1-Click Live Verification (Zero Setup)</div>
|
|
619
|
+
<div class="section-sub">Execute governed runs through Muxo right now and inspect the Ed25519 DecisionRecord & Supermemory context.</div>
|
|
620
|
+
</div>
|
|
621
|
+
</div>
|
|
622
|
+
<div style="display:flex;gap:10px;flex-wrap:wrap;margin-bottom:16px">
|
|
623
|
+
<button class="btn btn-primary" onclick="quickRun('instant.hackernews.top_stories', { limit: 4 })">
|
|
624
|
+
Run HackerNews Top Stories (Instant)
|
|
625
|
+
</button>
|
|
626
|
+
<button class="btn" onclick="quickRun('instant.github.repo_intel', { owner: 'Stripe', repo: 'stripe-cli' })">
|
|
627
|
+
Run GitHub Repo Intel (stripe/stripe-cli)
|
|
628
|
+
</button>
|
|
629
|
+
<button class="btn" onclick="quickRun('instant.dns.lookup', { domain: 'composio.dev', type: 'A' })">
|
|
630
|
+
Run DNS Lookup (composio.dev)
|
|
631
|
+
</button>
|
|
632
|
+
<button class="btn" onclick="quickRun('resource.projects.status', {})">
|
|
633
|
+
Check Stripe Projects Live Status
|
|
634
|
+
</button>
|
|
635
|
+
</div>
|
|
636
|
+
<div id="quick-run-output" class="code-block" style="min-height:150px;max-height:280px">Click any button above to plan, evaluate Microsoft Agent Governance, recall Supermemory v5 context, execute, and verify the signed receipt...</div>
|
|
637
|
+
</div>
|
|
638
|
+
|
|
639
|
+
<div class="card">
|
|
640
|
+
<div class="section-header">
|
|
641
|
+
<div>
|
|
642
|
+
<div class="section-title">Connect Your Agent (MCP, Harnesses & Autonomous Signup)</div>
|
|
643
|
+
<div class="section-sub">Configure Claude Code, Cursor, Droid, Mastra, Pi, or spawn an autonomous agent workspace.</div>
|
|
644
|
+
</div>
|
|
645
|
+
<div style="display:flex;gap:6px">
|
|
646
|
+
<button class="btn btn-sm" onclick="spawnAutonomousAgent()">⚡ Agent Auto-Signup</button>
|
|
647
|
+
<button class="btn btn-sm btn-primary" onclick="generateApiKey()">+ New API Key</button>
|
|
648
|
+
</div>
|
|
649
|
+
</div>
|
|
650
|
+
<div id="new-key-banner" class="hidden" style="margin-bottom:12px;padding:10px;border-radius:6px;background:var(--emerald-soft);border:1px solid var(--emerald)">
|
|
651
|
+
<div style="display:flex;justify-content:space-between;align-items:center;gap:8px;margin-bottom:4px">
|
|
652
|
+
<div style="font-size:11px;font-weight:600;color:var(--emerald)">NEW PROJECT API KEY / AGENT SIGNUP (COPY NOW):</div>
|
|
653
|
+
<div style="display:flex;gap:6px">
|
|
654
|
+
<button id="use-spawned-key-btn" class="btn btn-sm btn-emerald hidden" onclick="useLatestSpawnedKey()">Switch Console to This Workspace</button>
|
|
655
|
+
<button class="btn btn-sm" onclick="createClaimLinkPrompt()">Generate Owner Claim Link</button>
|
|
656
|
+
</div>
|
|
657
|
+
</div>
|
|
658
|
+
<code id="new-key-value" style="font-size:12px;word-break:break-all"></code>
|
|
659
|
+
</div>
|
|
660
|
+
<div style="display:flex;gap:6px;margin-bottom:8px;flex-wrap:wrap">
|
|
661
|
+
<button class="btn btn-sm" onclick="setHarnessSnippet('plugin')">Muxo Plugin (Codex / Claude / Droid)</button>
|
|
662
|
+
<button class="btn btn-sm" onclick="setHarnessSnippet('oauth')">CLI Login & OAuth Handoff</button>
|
|
663
|
+
<button class="btn btn-sm" onclick="setHarnessSnippet('mcp')">MCP Config (JSON)</button>
|
|
664
|
+
<button class="btn btn-sm" onclick="setHarnessSnippet('mastra')">Mastra (@mastra/mcp)</button>
|
|
665
|
+
<button class="btn btn-sm" onclick="setHarnessSnippet('pi')">Pi Coding Agent</button>
|
|
666
|
+
<button class="btn btn-sm" onclick="setHarnessSnippet('curl')">Autonomous Signup (cURL)</button>
|
|
667
|
+
</div>
|
|
668
|
+
<pre id="mcp-config-snippet" class="code-block" style="margin-bottom:12px;max-height:160px"></pre>
|
|
669
|
+
<div style="font-size:12px;color:var(--text-secondary);margin-bottom:6px">Active Workspace API Keys:</div>
|
|
670
|
+
<div id="api-keys-list"></div>
|
|
671
|
+
</div>
|
|
672
|
+
</div>
|
|
673
|
+
</section>
|
|
674
|
+
|
|
675
|
+
<!-- TAB 2: UNIFIED CATALOG -->
|
|
676
|
+
<section id="tab-catalog" class="tab-pane hidden">
|
|
677
|
+
<div class="section-header">
|
|
678
|
+
<div>
|
|
679
|
+
<div class="section-title">Unified Capability Catalog</div>
|
|
680
|
+
<div class="section-sub">Search across Composio Connected Apps (app.*), Composio Instant (instant.*), and Stripe Projects Infrastructure (resource.*).</div>
|
|
681
|
+
</div>
|
|
682
|
+
</div>
|
|
683
|
+
<div class="filter-bar">
|
|
684
|
+
<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()" />
|
|
685
|
+
<select id="catalog-lane" style="max-width:240px" onchange="loadCatalog()">
|
|
686
|
+
<option value="all">All Lanes (Unified)</option>
|
|
687
|
+
<option value="composio_instant">Composio Instant (instant.*)</option>
|
|
688
|
+
<option value="composio_sdk">Composio Connected Apps (app.*)</option>
|
|
689
|
+
<option value="stripe_projects">Stripe Projects Infrastructure (resource.*)</option>
|
|
690
|
+
</select>
|
|
691
|
+
<button class="btn btn-primary" onclick="loadCatalog()">Search Catalog</button>
|
|
692
|
+
</div>
|
|
693
|
+
<div id="catalog-grid" class="tool-grid"></div>
|
|
694
|
+
</section>
|
|
695
|
+
|
|
696
|
+
<!-- TAB 3: CLOUD INFRASTRUCTURE (STRIPE PROJECTS) -->
|
|
697
|
+
<section id="tab-infrastructure" class="tab-pane hidden">
|
|
698
|
+
<div class="section-header">
|
|
699
|
+
<div>
|
|
700
|
+
<div class="section-title">Cloud Infrastructure & Encrypted Secret Vault</div>
|
|
701
|
+
<div class="section-sub">Provision databases, caches, and cloud services through Muxo (powered by Stripe Projects). Credentials stay encrypted in Muxo Vault.</div>
|
|
702
|
+
</div>
|
|
703
|
+
<div style="display:flex;gap:8px">
|
|
704
|
+
<button class="btn" onclick="pullWorkspaceEnv()">Export Decrypted .env</button>
|
|
705
|
+
<button class="btn btn-primary" onclick="switchTab('catalog', document.querySelectorAll('.nav-btn')[1]); document.getElementById('catalog-lane').value='stripe_projects'; loadCatalog();">
|
|
706
|
+
+ Provision Service
|
|
707
|
+
</button>
|
|
708
|
+
</div>
|
|
709
|
+
</div>
|
|
710
|
+
|
|
711
|
+
<div id="env-export-box" class="card hidden" style="margin-bottom:18px">
|
|
712
|
+
<div class="section-header">
|
|
713
|
+
<div class="section-title">Decrypted Workspace .env (AES-256-GCM Vault)</div>
|
|
714
|
+
<button class="btn btn-sm" onclick="document.getElementById('env-export-box').classList.add('hidden')">Close</button>
|
|
715
|
+
</div>
|
|
716
|
+
<pre id="env-export-content" class="code-block"></pre>
|
|
717
|
+
</div>
|
|
718
|
+
|
|
719
|
+
<div class="table-wrap" style="margin-bottom:24px">
|
|
720
|
+
<table>
|
|
721
|
+
<thead>
|
|
722
|
+
<tr>
|
|
723
|
+
<th>Resource Name</th>
|
|
724
|
+
<th>Provider</th>
|
|
725
|
+
<th>Service / Tier</th>
|
|
726
|
+
<th>Status</th>
|
|
727
|
+
<th>Vault Env Vars (Redacted)</th>
|
|
728
|
+
<th>Actions</th>
|
|
729
|
+
</tr>
|
|
730
|
+
</thead>
|
|
731
|
+
<tbody id="resources-tbody">
|
|
732
|
+
<tr><td colspan="6" style="color:var(--text-muted)">No resources provisioned yet. Provision Postgres, Redis, Turso, or Storage from the catalog.</td></tr>
|
|
733
|
+
</tbody>
|
|
734
|
+
</table>
|
|
735
|
+
</div>
|
|
736
|
+
</section>
|
|
737
|
+
|
|
738
|
+
<!-- TAB 4: CONNECTED APPS (COMPOSIO) -->
|
|
739
|
+
<section id="tab-connections" class="tab-pane hidden">
|
|
740
|
+
<div class="section-header">
|
|
741
|
+
<div>
|
|
742
|
+
<div class="section-title">Managed App & Provider Connections (OAuth Handoff)</div>
|
|
743
|
+
<div class="section-sub">Connect SaaS apps via Composio Managed OAuth with isolated per-workspace callback handoff (<code class="mono">/oauth/callback</code> + <code class="mono">wait_for_connection</code>).</div>
|
|
744
|
+
</div>
|
|
745
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center">
|
|
746
|
+
<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()" />
|
|
747
|
+
<button class="btn btn-sm" onclick="startCustomProviderConnection()">+ Connect Toolkit</button>
|
|
748
|
+
<button class="btn btn-sm" onclick="startAppConnection('github')">+ GitHub</button>
|
|
749
|
+
<button class="btn btn-sm" onclick="startAppConnection('gmail')">+ Gmail</button>
|
|
750
|
+
<button class="btn btn-sm" onclick="startAppConnection('slack')">+ Slack</button>
|
|
751
|
+
<button class="btn btn-sm" onclick="startAppConnection('notion')">+ Notion</button>
|
|
752
|
+
<button class="btn btn-sm btn-primary" onclick="loadConnections(true)">Sync Live Status</button>
|
|
753
|
+
</div>
|
|
754
|
+
</div>
|
|
755
|
+
|
|
756
|
+
<div class="table-wrap">
|
|
757
|
+
<table>
|
|
758
|
+
<thead>
|
|
759
|
+
<tr>
|
|
760
|
+
<th>Provider</th>
|
|
761
|
+
<th>Execution Lane</th>
|
|
762
|
+
<th>Status</th>
|
|
763
|
+
<th>External Account / Provider ID</th>
|
|
764
|
+
<th>Action</th>
|
|
765
|
+
</tr>
|
|
766
|
+
</thead>
|
|
767
|
+
<tbody id="connections-tbody"></tbody>
|
|
768
|
+
</table>
|
|
769
|
+
</div>
|
|
770
|
+
</section>
|
|
771
|
+
|
|
772
|
+
<!-- TAB 5: SUPERMEMORY BRAIN -->
|
|
773
|
+
<section id="tab-memory" class="tab-pane hidden">
|
|
774
|
+
<div class="section-header">
|
|
775
|
+
<div>
|
|
776
|
+
<div class="section-title">Supermemory v5 Contextual Brain & Context-Aware Tool Layer</div>
|
|
777
|
+
<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>
|
|
778
|
+
</div>
|
|
779
|
+
<div style="display:flex;gap:8px">
|
|
780
|
+
<span class="badge badge-projects">Secret Redaction Active</span>
|
|
781
|
+
<button class="btn btn-primary" onclick="loadMemory()">Refresh Brain</button>
|
|
782
|
+
</div>
|
|
783
|
+
</div>
|
|
784
|
+
|
|
785
|
+
<div class="grid-2" style="margin-bottom:20px">
|
|
786
|
+
<div class="card">
|
|
787
|
+
<div class="section-header">
|
|
788
|
+
<div>
|
|
789
|
+
<div class="section-title">Recall & Search Workspace Brain</div>
|
|
790
|
+
<div class="section-sub">Query Supermemory v5 profile + hybrid semantic search across past runs & architectural facts.</div>
|
|
791
|
+
</div>
|
|
792
|
+
</div>
|
|
793
|
+
<div style="display:flex;gap:8px;margin-bottom:12px">
|
|
794
|
+
<input type="text" id="memory-query" placeholder="Search memories (e.g. primary database region, Postgres preference, Slack channel)..." onkeydown="if(event.key==='Enter') loadMemory()" />
|
|
795
|
+
<button class="btn btn-primary" onclick="loadMemory()">Recall</button>
|
|
796
|
+
</div>
|
|
797
|
+
<pre id="memory-context-box" class="code-block" style="min-height:170px;max-height:260px">Loading Supermemory v5 profile...</pre>
|
|
798
|
+
</div>
|
|
799
|
+
|
|
800
|
+
<div class="card">
|
|
801
|
+
<div class="section-header">
|
|
802
|
+
<div>
|
|
803
|
+
<div class="section-title">Add Governed Workspace Memory</div>
|
|
804
|
+
<div class="section-sub">Store architectural decisions, environment facts, or operator preferences (secrets are automatically redacted).</div>
|
|
805
|
+
</div>
|
|
806
|
+
</div>
|
|
807
|
+
<div style="display:flex;flex-direction:column;gap:10px">
|
|
808
|
+
<div style="display:grid;grid-template-columns:2fr 1fr;gap:8px">
|
|
809
|
+
<input type="text" id="memory-title" placeholder="Memory title (e.g. Primary Postgres Region)" />
|
|
810
|
+
<select id="memory-kind">
|
|
811
|
+
<option value="fact">Architectural Fact</option>
|
|
812
|
+
<option value="preference">Operator Preference</option>
|
|
813
|
+
<option value="resource_note">Resource Note</option>
|
|
814
|
+
</select>
|
|
815
|
+
</div>
|
|
816
|
+
<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>
|
|
817
|
+
<button class="btn btn-primary" onclick="submitNewMemory()">+ Save to Supermemory v5</button>
|
|
818
|
+
</div>
|
|
819
|
+
</div>
|
|
820
|
+
</div>
|
|
821
|
+
|
|
822
|
+
<div class="table-wrap">
|
|
823
|
+
<table>
|
|
824
|
+
<thead>
|
|
825
|
+
<tr>
|
|
826
|
+
<th>Document ID</th>
|
|
827
|
+
<th>Kind</th>
|
|
828
|
+
<th>Title</th>
|
|
829
|
+
<th>Sanitized Content</th>
|
|
830
|
+
<th>Created</th>
|
|
831
|
+
<th>Action</th>
|
|
832
|
+
</tr>
|
|
833
|
+
</thead>
|
|
834
|
+
<tbody id="memories-tbody"></tbody>
|
|
835
|
+
</table>
|
|
836
|
+
</div>
|
|
837
|
+
</section>
|
|
838
|
+
|
|
839
|
+
<!-- TAB 6: MICROSOFT AGENT GOVERNANCE & APPROVALS -->
|
|
840
|
+
<section id="tab-governance" class="tab-pane hidden">
|
|
841
|
+
<div class="card" style="margin-bottom:18px;background:var(--bg-elevated)">
|
|
842
|
+
<div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:12px">
|
|
843
|
+
<div>
|
|
844
|
+
<div style="font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:0.08em;color:var(--accent);margin-bottom:4px">Microsoft Agent Governance Toolkit (@microsoft/agent-governance-sdk v5.0.0)</div>
|
|
845
|
+
<div class="mono" style="font-size:13px;font-weight:600">Agent ──► McpSecurityScanner ──► PolicyEngine ──► AgentIdentity (Ed25519 DID) ──► AuditLogger ──► DecisionRecord</div>
|
|
846
|
+
<div style="font-size:12px;color:var(--text-secondary);margin-top:4px">
|
|
847
|
+
Identity DID: <code id="gov-did" class="mono" style="color:var(--emerald)">did:agent:muxo:control-plane</code> · Public Key: <code id="gov-pubkey" class="mono">...</code>
|
|
848
|
+
</div>
|
|
849
|
+
</div>
|
|
850
|
+
<div style="display:flex;gap:8px;align-items:center">
|
|
851
|
+
<span id="gov-chain-badge" class="badge badge-projects">SHA-256 Audit Chain Verified</span>
|
|
852
|
+
</div>
|
|
853
|
+
</div>
|
|
854
|
+
</div>
|
|
855
|
+
|
|
856
|
+
<div class="grid-2">
|
|
857
|
+
<div class="card">
|
|
858
|
+
<div class="section-header">
|
|
859
|
+
<div>
|
|
860
|
+
<div class="section-title">Action Plans & Human Approval Queue</div>
|
|
861
|
+
<div class="section-sub">Every plan carries an Ed25519-signed DecisionRecord and recalled Supermemory context.</div>
|
|
862
|
+
</div>
|
|
863
|
+
</div>
|
|
864
|
+
<div class="table-wrap">
|
|
865
|
+
<table>
|
|
866
|
+
<thead>
|
|
867
|
+
<tr>
|
|
868
|
+
<th>Plan ID</th>
|
|
869
|
+
<th>Tool</th>
|
|
870
|
+
<th>Risk / Verdict</th>
|
|
871
|
+
<th>Status</th>
|
|
872
|
+
<th>Actions</th>
|
|
873
|
+
</tr>
|
|
874
|
+
</thead>
|
|
875
|
+
<tbody id="plans-tbody"></tbody>
|
|
876
|
+
</table>
|
|
877
|
+
</div>
|
|
878
|
+
</div>
|
|
879
|
+
|
|
880
|
+
<div class="card">
|
|
881
|
+
<div class="section-header">
|
|
882
|
+
<div>
|
|
883
|
+
<div class="section-title">Workspace Governance Policy</div>
|
|
884
|
+
<div class="section-sub">Control enforcement mode and which risk lanes require human sign-off.</div>
|
|
885
|
+
</div>
|
|
886
|
+
</div>
|
|
887
|
+
<div style="display:flex;flex-direction:column;gap:12px">
|
|
888
|
+
<div>
|
|
889
|
+
<label style="font-size:12px;color:var(--text-secondary);display:block;margin-bottom:4px">Policy Mode</label>
|
|
890
|
+
<select id="policy-mode">
|
|
891
|
+
<option value="enforce">Enforce (Block unapproved high-risk actions)</option>
|
|
892
|
+
<option value="monitor">Monitor-Only (Auto-approve & log all receipts)</option>
|
|
893
|
+
</select>
|
|
894
|
+
</div>
|
|
895
|
+
<div>
|
|
896
|
+
<label style="font-size:12px;color:var(--text-secondary);display:block;margin-bottom:6px">Require Human Owner Approval For:</label>
|
|
897
|
+
<div id="policy-risks" style="display:grid;grid-template-columns:1fr 1fr;gap:8px;font-size:13px">
|
|
898
|
+
<label><input type="checkbox" value="read" /> read</label>
|
|
899
|
+
<label><input type="checkbox" value="write" /> write</label>
|
|
900
|
+
<label><input type="checkbox" value="admin" checked /> admin</label>
|
|
901
|
+
<label><input type="checkbox" value="financial" checked /> financial</label>
|
|
902
|
+
<label><input type="checkbox" value="provisioning" checked /> provisioning</label>
|
|
903
|
+
<label><input type="checkbox" value="destructive" checked /> destructive</label>
|
|
904
|
+
</div>
|
|
905
|
+
</div>
|
|
906
|
+
<button class="btn btn-primary" onclick="savePolicy()">Save Governance Policy</button>
|
|
907
|
+
</div>
|
|
908
|
+
</div>
|
|
909
|
+
</div>
|
|
910
|
+
</section>
|
|
911
|
+
|
|
912
|
+
<!-- TAB 6: RUNS & CRYPTOGRAPHIC RECEIPTS -->
|
|
913
|
+
<section id="tab-receipts" class="tab-pane hidden">
|
|
914
|
+
<div class="section-header">
|
|
915
|
+
<div>
|
|
916
|
+
<div class="section-title">Execution Runs & Chained HMAC-SHA256 Receipts</div>
|
|
917
|
+
<div class="section-sub">Every execution produces a tamper-evident cryptographic receipt chained to the previous run.</div>
|
|
918
|
+
</div>
|
|
919
|
+
</div>
|
|
920
|
+
<div class="table-wrap">
|
|
921
|
+
<table>
|
|
922
|
+
<thead>
|
|
923
|
+
<tr>
|
|
924
|
+
<th>Run / Receipt ID</th>
|
|
925
|
+
<th>Tool & Lane</th>
|
|
926
|
+
<th>Risk</th>
|
|
927
|
+
<th>Status</th>
|
|
928
|
+
<th>Duration</th>
|
|
929
|
+
<th>Signature Verification</th>
|
|
930
|
+
<th>Inspect</th>
|
|
931
|
+
</tr>
|
|
932
|
+
</thead>
|
|
933
|
+
<tbody id="runs-tbody"></tbody>
|
|
934
|
+
</table>
|
|
935
|
+
</div>
|
|
936
|
+
</section>
|
|
937
|
+
|
|
938
|
+
<!-- TAB 7: BILLING & CREDITS -->
|
|
939
|
+
<section id="tab-billing" class="tab-pane hidden">
|
|
940
|
+
<div class="grid-2">
|
|
941
|
+
<div class="card">
|
|
942
|
+
<div class="section-header">
|
|
943
|
+
<div>
|
|
944
|
+
<div class="section-title">Subscription & Credit Top-Ups (User Pays Muxo -> Muxo Pays Suppliers)</div>
|
|
945
|
+
<div class="section-sub">Users buy Muxo Credits ($0.01/credit); Muxo settles upstream costs with Composio & Stripe Projects from Muxo's master accounts.</div>
|
|
946
|
+
</div>
|
|
947
|
+
</div>
|
|
948
|
+
<div style="display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-bottom:16px">
|
|
949
|
+
<div style="border:1px solid var(--border-strong);border-radius:8px;padding:16px;background:var(--bg-elevated)">
|
|
950
|
+
<div style="font-weight:600;font-size:15px;margin-bottom:4px">Starter Plan — $29/mo</div>
|
|
951
|
+
<div style="font-size:12.5px;color:var(--text-secondary);margin-bottom:14px">
|
|
952
|
+
5,000 governed actions/month + 1,000 Instant & Provisioning credits included.
|
|
953
|
+
</div>
|
|
954
|
+
<button class="btn btn-primary" style="width:100%;justify-content:center" onclick="startCheckout('starter_subscription')">
|
|
955
|
+
Upgrade via Stripe Checkout ($29/mo)
|
|
956
|
+
</button>
|
|
957
|
+
</div>
|
|
958
|
+
<div style="border:1px solid var(--border-strong);border-radius:8px;padding:16px;background:var(--bg-elevated)">
|
|
959
|
+
<div style="font-weight:600;font-size:15px;margin-bottom:4px">+1,000 Credit Pack — $10</div>
|
|
960
|
+
<div style="font-size:12.5px;color:var(--text-secondary);margin-bottom:14px">
|
|
961
|
+
Top up workspace credits for Instant tools, OAuth connectors & cloud provisioning.
|
|
962
|
+
</div>
|
|
963
|
+
<div style="display:flex;gap:8px;flex-direction:column">
|
|
964
|
+
<button class="btn btn-emerald" style="width:100%;justify-content:center" onclick="startCheckout('credit_topup')">
|
|
965
|
+
Stripe Checkout (+1,000 Credits / $10)
|
|
966
|
+
</button>
|
|
967
|
+
<button class="btn btn-sm" style="width:100%;justify-content:center" onclick="instantTopup(1000)">
|
|
968
|
+
⚡ Instant Wallet Top-Up (+1,000 Credits)
|
|
969
|
+
</button>
|
|
970
|
+
</div>
|
|
971
|
+
</div>
|
|
972
|
+
</div>
|
|
973
|
+
|
|
974
|
+
<div style="border:1px solid var(--border-strong);border-radius:8px;padding:14px;background:rgba(16,185,129,0.05)">
|
|
975
|
+
<div style="font-weight:600;font-size:13px;margin-bottom:8px;color:var(--emerald)">
|
|
976
|
+
💸 Merchant-of-Record Settlement Ledger (muxo_funded)
|
|
977
|
+
</div>
|
|
978
|
+
<div id="settlement-summary-box" style="font-size:12px;color:var(--text-secondary);line-height:1.6">
|
|
979
|
+
Loading supplier settlement metrics...
|
|
980
|
+
</div>
|
|
981
|
+
</div>
|
|
982
|
+
</div>
|
|
983
|
+
|
|
984
|
+
<div class="card">
|
|
985
|
+
<div class="section-header">
|
|
986
|
+
<div>
|
|
987
|
+
<div class="section-title">Audit Credit & Supplier Settlement Ledger</div>
|
|
988
|
+
<div class="section-sub">Immutable record of user credit purchases, run deductions, and upstream supplier payouts.</div>
|
|
989
|
+
</div>
|
|
990
|
+
</div>
|
|
991
|
+
<div class="table-wrap">
|
|
992
|
+
<table>
|
|
993
|
+
<thead>
|
|
994
|
+
<tr>
|
|
995
|
+
<th>Time</th>
|
|
996
|
+
<th>Event & Supplier Settlement</th>
|
|
997
|
+
<th>Credits Delta</th>
|
|
998
|
+
<th>Balance</th>
|
|
999
|
+
</tr>
|
|
1000
|
+
</thead>
|
|
1001
|
+
<tbody id="ledger-tbody"></tbody>
|
|
1002
|
+
</table>
|
|
1003
|
+
</div>
|
|
1004
|
+
</div>
|
|
1005
|
+
</div>
|
|
1006
|
+
</section>
|
|
1007
|
+
</main>
|
|
1008
|
+
</div>
|
|
1009
|
+
</div>
|
|
1010
|
+
|
|
1011
|
+
<!-- Plan & Execute Modal -->
|
|
1012
|
+
<div id="exec-modal" class="modal-backdrop">
|
|
1013
|
+
<div class="modal">
|
|
1014
|
+
<div class="section-header">
|
|
1015
|
+
<div>
|
|
1016
|
+
<div class="section-title" id="modal-tool-name">Plan & Execute Tool</div>
|
|
1017
|
+
<div class="tool-slug" id="modal-tool-slug"></div>
|
|
1018
|
+
</div>
|
|
1019
|
+
<button class="btn btn-sm" onclick="closeExecuteModal()">Close</button>
|
|
1020
|
+
</div>
|
|
1021
|
+
<p id="modal-tool-desc" style="font-size:13px;color:var(--text-secondary);margin-bottom:14px"></p>
|
|
1022
|
+
<div style="margin-bottom:12px">
|
|
1023
|
+
<label style="font-size:12px;color:var(--text-secondary);display:block;margin-bottom:4px">Input Arguments (JSON)</label>
|
|
1024
|
+
<textarea id="modal-tool-input" rows="6" class="mono">{}</textarea>
|
|
1025
|
+
</div>
|
|
1026
|
+
<div style="margin-bottom:14px">
|
|
1027
|
+
<label style="font-size:12px;color:var(--text-secondary);display:block;margin-bottom:4px">Audit Reason</label>
|
|
1028
|
+
<input type="text" id="modal-tool-reason" value="Interactive execution from Muxo Console" />
|
|
1029
|
+
</div>
|
|
1030
|
+
<div style="display:flex;gap:10px;justify-content:flex-end;margin-bottom:14px">
|
|
1031
|
+
<button class="btn" onclick="submitPlanOnly()">1. Create Governed Plan</button>
|
|
1032
|
+
<button class="btn btn-primary" onclick="submitPlanAndExecute()">Plan & Execute Now</button>
|
|
1033
|
+
</div>
|
|
1034
|
+
<div id="modal-oauth-box" class="hidden" style="margin-bottom:14px;padding:12px;border-radius:8px;background:var(--amber-soft);border:1px solid rgba(245,158,11,0.4)">
|
|
1035
|
+
<div style="font-size:12px;font-weight:700;color:var(--amber);margin-bottom:6px" id="modal-oauth-title">OAUTH HANDOFF REQUIRED BEFORE EXECUTION</div>
|
|
1036
|
+
<div style="font-size:12.5px;color:var(--text-secondary);margin-bottom:10px" id="modal-oauth-msg"></div>
|
|
1037
|
+
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
|
1038
|
+
<a id="modal-oauth-link" href="#" target="_blank" class="btn btn-sm btn-primary">1. Authorize OAuth in Browser ↗</a>
|
|
1039
|
+
<button class="btn btn-sm btn-emerald" onclick="waitAndResumeModalPlan()">2. Poll wait_for_connection & Resume</button>
|
|
1040
|
+
<button class="btn btn-sm" onclick="completeCallbackAndResumeModalPlan()">Simulate Callback Handoff & Resume</button>
|
|
1041
|
+
</div>
|
|
1042
|
+
</div>
|
|
1043
|
+
<pre id="modal-result" class="code-block hidden"></pre>
|
|
1044
|
+
</div>
|
|
1045
|
+
</div>
|
|
1046
|
+
|
|
1047
|
+
<div id="toast" class="toast"></div>
|
|
1048
|
+
|
|
1049
|
+
<script>
|
|
1050
|
+
let currentTool = null;
|
|
1051
|
+
let activeKeyHint = 'mk_live_...';
|
|
1052
|
+
let externalApiKey = localStorage.getItem('muxo_external_api_key') || '';
|
|
1053
|
+
let latestSpawnedKey = '';
|
|
1054
|
+
let currentWorkspaceId = '';
|
|
1055
|
+
let pendingModalPlan = null;
|
|
1056
|
+
let pendingModalHandoff = null;
|
|
1057
|
+
|
|
1058
|
+
function showToast(msg) {
|
|
1059
|
+
const t = document.getElementById('toast');
|
|
1060
|
+
t.textContent = msg;
|
|
1061
|
+
t.classList.add('show');
|
|
1062
|
+
setTimeout(() => t.classList.remove('show'), 4000);
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
function toggleTheme() {
|
|
1066
|
+
const html = document.documentElement;
|
|
1067
|
+
html.dataset.theme = html.dataset.theme === 'dark' ? 'light' : 'dark';
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
function switchTab(tabId, btn) {
|
|
1071
|
+
document.querySelectorAll('.tab-pane').forEach(el => el.classList.add('hidden'));
|
|
1072
|
+
document.getElementById('tab-' + tabId).classList.remove('hidden');
|
|
1073
|
+
if (btn) {
|
|
1074
|
+
document.querySelectorAll('.nav-btn').forEach(b => b.classList.remove('active'));
|
|
1075
|
+
btn.classList.add('active');
|
|
1076
|
+
}
|
|
1077
|
+
if (tabId === 'catalog') loadCatalog();
|
|
1078
|
+
if (tabId === 'infrastructure') loadResources();
|
|
1079
|
+
if (tabId === 'connections') loadConnections(false);
|
|
1080
|
+
if (tabId === 'memory') loadMemory();
|
|
1081
|
+
if (tabId === 'governance') loadPlans();
|
|
1082
|
+
if (tabId === 'receipts') loadRuns();
|
|
1083
|
+
if (tabId === 'billing') loadLedger();
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
async function api(path, opts = {}) {
|
|
1087
|
+
const headers = { 'Content-Type': 'application/json', ...(opts.headers || {}) };
|
|
1088
|
+
if (externalApiKey) {
|
|
1089
|
+
headers['Authorization'] = 'Bearer ' + externalApiKey;
|
|
1090
|
+
}
|
|
1091
|
+
const res = await fetch(path, {
|
|
1092
|
+
...opts,
|
|
1093
|
+
headers
|
|
1094
|
+
});
|
|
1095
|
+
const data = await res.json();
|
|
1096
|
+
if (!res.ok || data.ok === false) {
|
|
1097
|
+
throw new Error(data.error || ('HTTP ' + res.status));
|
|
1098
|
+
}
|
|
1099
|
+
return data;
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
async function switchExternalWorkspacePrompt() {
|
|
1103
|
+
const val = prompt(
|
|
1104
|
+
'Enter an external workspace API key (mk_live_...), or type "new" to auto-provision a brand new external user workspace:',
|
|
1105
|
+
externalApiKey || 'new'
|
|
1106
|
+
);
|
|
1107
|
+
if (!val) return;
|
|
1108
|
+
if (val.trim().toLowerCase() === 'new') {
|
|
1109
|
+
const res = await fetch('/api/v1/agents/signup', {
|
|
1110
|
+
method: 'POST',
|
|
1111
|
+
headers: { 'Content-Type': 'application/json' },
|
|
1112
|
+
body: JSON.stringify({ agentName: 'External Browser User', harness: 'console-ui' })
|
|
1113
|
+
}).then(r => r.json());
|
|
1114
|
+
if (res.apiKey) {
|
|
1115
|
+
setExternalWorkspaceKey(res.apiKey, 'Switched to new external workspace: ' + res.workspace.slug);
|
|
1116
|
+
}
|
|
1117
|
+
return;
|
|
1118
|
+
}
|
|
1119
|
+
setExternalWorkspaceKey(val.trim(), 'Switched Console to external API key');
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
async function setExternalWorkspaceKey(key, toastMsg) {
|
|
1123
|
+
externalApiKey = key;
|
|
1124
|
+
localStorage.setItem('muxo_external_api_key', key);
|
|
1125
|
+
if (toastMsg) showToast(toastMsg);
|
|
1126
|
+
await refreshOverview();
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
async function clearExternalWorkspaceKey() {
|
|
1130
|
+
externalApiKey = '';
|
|
1131
|
+
localStorage.removeItem('muxo_external_api_key');
|
|
1132
|
+
showToast('Returned to default workspace session');
|
|
1133
|
+
await refreshOverview();
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
async function useLatestSpawnedKey() {
|
|
1137
|
+
if (!latestSpawnedKey) return;
|
|
1138
|
+
return await setExternalWorkspaceKey(latestSpawnedKey, 'Switched Console to spawned workspace!');
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
async function createClaimLinkPrompt() {
|
|
1142
|
+
const email = prompt('Enter human owner email to bind this workspace to:', 'founder@muxo.ai');
|
|
1143
|
+
if (!email) return;
|
|
1144
|
+
try {
|
|
1145
|
+
const res = await api('/api/v1/agents/claim', {
|
|
1146
|
+
method: 'POST',
|
|
1147
|
+
body: JSON.stringify({ email: email.trim() })
|
|
1148
|
+
});
|
|
1149
|
+
document.getElementById('new-key-banner').classList.remove('hidden');
|
|
1150
|
+
document.getElementById('new-key-value').innerHTML =
|
|
1151
|
+
'Owner Claim Link for <strong>' + email + '</strong>: <a href="' + res.claimUrl + '" target="_blank" style="color:var(--emerald);text-decoration:underline">' + res.claimUrl + '</a>';
|
|
1152
|
+
showToast('Generated owner claim link!');
|
|
1153
|
+
} catch (err) {
|
|
1154
|
+
showToast('Claim Error: ' + err.message);
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
function laneBadge(lane) {
|
|
1159
|
+
if (lane === 'composio_instant') return '<span class="badge badge-instant">Instant</span>';
|
|
1160
|
+
if (lane === 'composio_sdk') return '<span class="badge badge-sdk">Composio App</span>';
|
|
1161
|
+
return '<span class="badge badge-projects">Stripe Projects</span>';
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
function riskBadge(risk) {
|
|
1165
|
+
if (risk === 'read') return '<span class="badge badge-instant">read</span>';
|
|
1166
|
+
if (risk === 'write') return '<span class="badge badge-sdk">write</span>';
|
|
1167
|
+
if (risk === 'provisioning') return '<span class="badge badge-projects">provisioning</span>';
|
|
1168
|
+
if (risk === 'destructive') return '<span class="badge badge-danger">' + risk + '</span>';
|
|
1169
|
+
return '<span class="badge badge-warn">' + risk + '</span>';
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
async function refreshOverview() {
|
|
1173
|
+
const state = await api('/api/v1/bootstrap');
|
|
1174
|
+
const org = state.organization;
|
|
1175
|
+
currentWorkspaceId = org.id;
|
|
1176
|
+
document.getElementById('workspace-name').textContent = org.name;
|
|
1177
|
+
document.getElementById('workspace-slug').textContent = '(' + org.id + ')';
|
|
1178
|
+
const authBadge = document.getElementById('workspace-auth-badge');
|
|
1179
|
+
const resetBtn = document.getElementById('reset-workspace-btn');
|
|
1180
|
+
if (externalApiKey) {
|
|
1181
|
+
authBadge.textContent = 'External Key (' + externalApiKey.slice(0, 14) + '...)';
|
|
1182
|
+
authBadge.className = 'badge badge-sdk';
|
|
1183
|
+
resetBtn.classList.remove('hidden');
|
|
1184
|
+
} else {
|
|
1185
|
+
authBadge.textContent = 'Default Session';
|
|
1186
|
+
authBadge.className = 'badge badge-projects';
|
|
1187
|
+
resetBtn.classList.add('hidden');
|
|
1188
|
+
}
|
|
1189
|
+
document.getElementById('sidebar-tier').textContent = org.tier.toUpperCase();
|
|
1190
|
+
document.getElementById('kpi-tier-badge').textContent = org.tier.toUpperCase() + ' PLAN';
|
|
1191
|
+
document.getElementById('kpi-connections').textContent = state.connections.filter(c => c.status === 'active').length;
|
|
1192
|
+
document.getElementById('kpi-runs').textContent = state.runs.length;
|
|
1193
|
+
document.getElementById('kpi-credits').textContent = org.usage.creditsBalance.toLocaleString();
|
|
1194
|
+
|
|
1195
|
+
document.getElementById('meter-actions-text').textContent =
|
|
1196
|
+
org.usage.monthlyActionsUsed + ' / ' + org.usage.monthlyActionsLimit.toLocaleString();
|
|
1197
|
+
const pct = Math.min(100, Math.max(2, Math.round((org.usage.monthlyActionsUsed / org.usage.monthlyActionsLimit) * 100)));
|
|
1198
|
+
document.getElementById('meter-actions-bar').style.width = pct + '%';
|
|
1199
|
+
document.getElementById('meter-credits-text').textContent = org.usage.creditsBalance.toLocaleString();
|
|
1200
|
+
|
|
1201
|
+
document.getElementById('nav-res-count').textContent = state.resources.filter(r => r.status === 'active').length;
|
|
1202
|
+
document.getElementById('nav-conn-count').textContent = state.connections.filter(c => c.status === 'active').length;
|
|
1203
|
+
document.getElementById('nav-plan-count').textContent = state.plans.filter(p => p.approvalStatus === 'pending_approval').length;
|
|
1204
|
+
document.getElementById('nav-run-count').textContent = state.runs.length;
|
|
1205
|
+
|
|
1206
|
+
// Policy sync
|
|
1207
|
+
document.getElementById('policy-mode').value = org.policy.mode;
|
|
1208
|
+
const reqSet = new Set(org.policy.requireApprovalFor || []);
|
|
1209
|
+
document.querySelectorAll('#policy-risks input[type=checkbox]').forEach(cb => {
|
|
1210
|
+
cb.checked = reqSet.has(cb.value);
|
|
1211
|
+
});
|
|
1212
|
+
|
|
1213
|
+
// MCP snippet
|
|
1214
|
+
activeKeyHint = externalApiKey || state.defaultApiKey || (state.apiKeys[0] ? state.apiKeys[0].keyPrefix : 'mk_live_...');
|
|
1215
|
+
setHarnessSnippet('plugin');
|
|
1216
|
+
|
|
1217
|
+
if (state.governance) {
|
|
1218
|
+
const govDidEl = document.getElementById('gov-did');
|
|
1219
|
+
const govPubEl = document.getElementById('gov-pubkey');
|
|
1220
|
+
if (govDidEl) govDidEl.textContent = state.governance.agentDid;
|
|
1221
|
+
if (govPubEl) govPubEl.textContent = (state.governance.publicKeyHex || '').slice(0, 24) + '...';
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
// Render API keys
|
|
1225
|
+
const keysEl = document.getElementById('api-keys-list');
|
|
1226
|
+
keysEl.innerHTML = state.apiKeys.map(k =>
|
|
1227
|
+
'<div style="display:flex;justify-content:space-between;align-items:center;padding:6px 0;border-bottom:1px solid var(--border);font-size:12.5px">' +
|
|
1228
|
+
'<div><strong>' + k.name + '</strong> <code style="color:var(--text-secondary)">' + k.keyPrefix + '</code></div>' +
|
|
1229
|
+
'<span class="badge badge-projects">' + k.environment + '</span>' +
|
|
1230
|
+
'</div>'
|
|
1231
|
+
).join('');
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
function setHarnessSnippet(kind) {
|
|
1235
|
+
const el = document.getElementById('mcp-config-snippet');
|
|
1236
|
+
const origin = window.location.origin;
|
|
1237
|
+
if (kind === 'plugin') {
|
|
1238
|
+
el.textContent = [
|
|
1239
|
+
'# Install Muxo Plugin (OpenAI Codex / ChatGPT / Claude Code / Factory Droid)',
|
|
1240
|
+
'codex plugin add muxo@muxo',
|
|
1241
|
+
'# Or authenticate via CLI & link OAuth apps with polling recovery:',
|
|
1242
|
+
'muxo login --signup --name "my-agent"',
|
|
1243
|
+
'muxo link github --wait'
|
|
1244
|
+
].join('\\n');
|
|
1245
|
+
} else if (kind === 'oauth') {
|
|
1246
|
+
el.textContent = [
|
|
1247
|
+
'# External User CLI Login + Isolated OAuth Handoff',
|
|
1248
|
+
'muxo login --signup --name "external-agent" --url ' + origin,
|
|
1249
|
+
'muxo whoami',
|
|
1250
|
+
'muxo link github --wait',
|
|
1251
|
+
'# MCP tools: start_connection -> /oauth/callback -> wait_for_connection'
|
|
1252
|
+
].join('\\n');
|
|
1253
|
+
} else if (kind === 'mastra') {
|
|
1254
|
+
el.textContent = [
|
|
1255
|
+
'import { MCPClient } from "@mastra/mcp";',
|
|
1256
|
+
'export const muxoMcp = new MCPClient({',
|
|
1257
|
+
' servers: {',
|
|
1258
|
+
' muxo: {',
|
|
1259
|
+
' url: new URL("' + origin + '/mcp"),',
|
|
1260
|
+
' requestInit: { headers: { Authorization: "Bearer ' + activeKeyHint + '" } }',
|
|
1261
|
+
' }',
|
|
1262
|
+
' }',
|
|
1263
|
+
'});'
|
|
1264
|
+
].join('\\n');
|
|
1265
|
+
} else if (kind === 'pi') {
|
|
1266
|
+
el.textContent = [
|
|
1267
|
+
'# Pi Coding Agent (@mariozechner/pi-coding-agent)',
|
|
1268
|
+
'curl -sL ' + origin + '/skill.md > ~/.pi/skills/muxo.md',
|
|
1269
|
+
'export MUXO_API_KEY="' + activeKeyHint + '"'
|
|
1270
|
+
].join('\\n');
|
|
1271
|
+
} else if (kind === 'curl') {
|
|
1272
|
+
el.textContent = [
|
|
1273
|
+
'# 2-Call Autonomous Agent Signup (agents.composio.dev pattern)',
|
|
1274
|
+
'curl -sX POST ' + origin + '/api/v1/agents/signup \\\\',
|
|
1275
|
+
' -H "Content-Type: application/json" \\\\',
|
|
1276
|
+
' -d ' + JSON.stringify(JSON.stringify({ agentName: 'Autonomous Ops Agent', harness: 'claude-code' }))
|
|
1277
|
+
].join('\\n');
|
|
1278
|
+
} else {
|
|
1279
|
+
el.textContent = JSON.stringify({
|
|
1280
|
+
mcpServers: {
|
|
1281
|
+
muxo: {
|
|
1282
|
+
url: origin + "/mcp",
|
|
1283
|
+
headers: {
|
|
1284
|
+
Authorization: "Bearer " + activeKeyHint
|
|
1285
|
+
}
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
}, null, 2);
|
|
1289
|
+
}
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
async function spawnAutonomousAgent() {
|
|
1293
|
+
const res = await api('/api/v1/agents/signup', {
|
|
1294
|
+
method: 'POST',
|
|
1295
|
+
body: JSON.stringify({ agentName: 'Autonomous Agent', harness: 'mcp' })
|
|
1296
|
+
});
|
|
1297
|
+
latestSpawnedKey = res.apiKey;
|
|
1298
|
+
document.getElementById('new-key-banner').classList.remove('hidden');
|
|
1299
|
+
document.getElementById('use-spawned-key-btn').classList.remove('hidden');
|
|
1300
|
+
document.getElementById('new-key-value').textContent =
|
|
1301
|
+
res.apiKey + ' (Workspace: ' + res.workspace.slug + ')';
|
|
1302
|
+
showToast('Spawned autonomous agent workspace: ' + res.workspace.slug);
|
|
1303
|
+
}
|
|
1304
|
+
|
|
1305
|
+
async function generateApiKey() {
|
|
1306
|
+
const name = prompt('API Key Name:', 'Agent Key') || 'Agent Key';
|
|
1307
|
+
const res = await api('/api/v1/api-keys', {
|
|
1308
|
+
method: 'POST',
|
|
1309
|
+
body: JSON.stringify({ name, environment: 'live' })
|
|
1310
|
+
});
|
|
1311
|
+
document.getElementById('new-key-banner').classList.remove('hidden');
|
|
1312
|
+
document.getElementById('new-key-value').textContent = res.secretKey;
|
|
1313
|
+
showToast('Created new API key!');
|
|
1314
|
+
await refreshOverview();
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
async function quickRun(toolSlug, input) {
|
|
1318
|
+
const box = document.getElementById('quick-run-output');
|
|
1319
|
+
box.textContent = 'Planning & executing ' + toolSlug + '...';
|
|
1320
|
+
try {
|
|
1321
|
+
const planned = await api('/api/v1/plans', {
|
|
1322
|
+
method: 'POST',
|
|
1323
|
+
body: JSON.stringify({ toolSlug, input, reason: '1-Click Quickstart Verification' })
|
|
1324
|
+
});
|
|
1325
|
+
if (planned.plan.approvalStatus === 'pending_approval') {
|
|
1326
|
+
await api('/api/v1/plans/' + planned.plan.id + '/approve', { method: 'POST' });
|
|
1327
|
+
}
|
|
1328
|
+
const executed = await api('/api/v1/plans/' + planned.plan.id + '/execute', {
|
|
1329
|
+
method: 'POST'
|
|
1330
|
+
});
|
|
1331
|
+
box.textContent = JSON.stringify({
|
|
1332
|
+
runId: executed.run.id,
|
|
1333
|
+
status: executed.run.status,
|
|
1334
|
+
durationMs: executed.run.durationMs,
|
|
1335
|
+
microsoftGovernance: planned.decisionRecord ? {
|
|
1336
|
+
decisionId: planned.decisionRecord.id,
|
|
1337
|
+
verdict: planned.decisionRecord.verdict,
|
|
1338
|
+
agentDid: planned.decisionRecord.agentDid,
|
|
1339
|
+
ed25519Signature: planned.decisionRecord.signature.slice(0, 24) + '...'
|
|
1340
|
+
} : null,
|
|
1341
|
+
supermemoryBrain: planned.memoryContext ? {
|
|
1342
|
+
namespace: planned.memoryContext.namespace,
|
|
1343
|
+
recalledCount: (planned.memoryContext.recalledMemories || []).length
|
|
1344
|
+
} : null,
|
|
1345
|
+
receipt: {
|
|
1346
|
+
id: executed.receipt.id,
|
|
1347
|
+
receiptHash: executed.receipt.receiptHash,
|
|
1348
|
+
signature: executed.receipt.signature.slice(0, 24) + '...'
|
|
1349
|
+
},
|
|
1350
|
+
output: executed.run.output
|
|
1351
|
+
}, null, 2);
|
|
1352
|
+
showToast('Executed ' + toolSlug + ' (' + executed.run.durationMs + 'ms)');
|
|
1353
|
+
await refreshOverview();
|
|
1354
|
+
} catch (err) {
|
|
1355
|
+
box.textContent = 'Error: ' + err.message;
|
|
1356
|
+
}
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1359
|
+
async function loadCatalog() {
|
|
1360
|
+
const query = document.getElementById('catalog-search').value;
|
|
1361
|
+
const lane = document.getElementById('catalog-lane').value;
|
|
1362
|
+
const grid = document.getElementById('catalog-grid');
|
|
1363
|
+
grid.innerHTML = '<div style="color:var(--text-secondary)">Loading unified catalog...</div>';
|
|
1364
|
+
const data = await api('/api/v1/tools?query=' + encodeURIComponent(query) + '&lane=' + encodeURIComponent(lane) + '&limit=48');
|
|
1365
|
+
document.getElementById('nav-catalog-count').textContent = data.total;
|
|
1366
|
+
grid.innerHTML = data.tools.map(t =>
|
|
1367
|
+
'<div class="tool-card">' +
|
|
1368
|
+
'<div>' +
|
|
1369
|
+
'<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;gap:6px">' +
|
|
1370
|
+
laneBadge(t.lane) +
|
|
1371
|
+
riskBadge(t.riskLevel) +
|
|
1372
|
+
'</div>' +
|
|
1373
|
+
'<div style="font-weight:600;font-size:14px;margin-bottom:3px">' + t.name + '</div>' +
|
|
1374
|
+
'<div class="tool-slug" style="margin-bottom:8px">' + t.slug + '</div>' +
|
|
1375
|
+
'<div class="tool-desc">' + t.description + '</div>' +
|
|
1376
|
+
'</div>' +
|
|
1377
|
+
'<div style="display:flex;justify-content:space-between;align-items:center;padding-top:10px;border-top:1px solid var(--border)">' +
|
|
1378
|
+
'<span class="mono" style="font-size:11.5px;color:var(--text-muted)">Cost: ' + t.creditCost + ' cr</span>' +
|
|
1379
|
+
'<button class="btn btn-sm btn-primary" onclick="openExecuteModal(\\'' + t.slug + '\\')">Plan & Run</button>' +
|
|
1380
|
+
'</div>' +
|
|
1381
|
+
'</div>'
|
|
1382
|
+
).join('');
|
|
1383
|
+
}
|
|
1384
|
+
|
|
1385
|
+
async function openExecuteModal(slug) {
|
|
1386
|
+
const tool = await api('/api/v1/tools/' + encodeURIComponent(slug));
|
|
1387
|
+
currentTool = tool;
|
|
1388
|
+
document.getElementById('modal-tool-name').textContent = tool.name;
|
|
1389
|
+
document.getElementById('modal-tool-slug').textContent = tool.slug + ' → ' + tool.upstreamSlug;
|
|
1390
|
+
document.getElementById('modal-tool-desc').textContent = tool.description;
|
|
1391
|
+
|
|
1392
|
+
// Default sample input based on schema
|
|
1393
|
+
const sample = {};
|
|
1394
|
+
const props = (tool.inputSchema && tool.inputSchema.properties) || {};
|
|
1395
|
+
for (const [k, v] of Object.entries(props)) {
|
|
1396
|
+
if (v.default !== undefined) sample[k] = v.default;
|
|
1397
|
+
else if (k === 'query') sample[k] = 'Stripe Projects AI infrastructure';
|
|
1398
|
+
else if (k === 'domain') sample[k] = 'stripe.com';
|
|
1399
|
+
else if (k === 'owner') sample[k] = 'cloudflare';
|
|
1400
|
+
else if (k === 'repo') sample[k] = 'workerd';
|
|
1401
|
+
else if (k === 'url') sample[k] = 'https://example.com';
|
|
1402
|
+
else if (k === 'resource_name') sample[k] = tool.providerSlug + '-primary';
|
|
1403
|
+
}
|
|
1404
|
+
document.getElementById('modal-tool-input').value = JSON.stringify(sample, null, 2);
|
|
1405
|
+
document.getElementById('modal-oauth-box').classList.add('hidden');
|
|
1406
|
+
document.getElementById('modal-result').classList.add('hidden');
|
|
1407
|
+
pendingModalPlan = null;
|
|
1408
|
+
pendingModalHandoff = null;
|
|
1409
|
+
document.getElementById('exec-modal').classList.add('open');
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
function closeExecuteModal() {
|
|
1413
|
+
document.getElementById('exec-modal').classList.remove('open');
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
function renderModalOAuthHandoff(planned) {
|
|
1417
|
+
const box = document.getElementById('modal-oauth-box');
|
|
1418
|
+
if (planned && planned.authHandoff && planned.authHandoff.required) {
|
|
1419
|
+
pendingModalPlan = planned.plan;
|
|
1420
|
+
pendingModalHandoff = planned.authHandoff;
|
|
1421
|
+
document.getElementById('modal-oauth-title').textContent =
|
|
1422
|
+
'OAUTH HANDOFF REQUIRED FOR ' + (planned.authHandoff.provider || '').toUpperCase();
|
|
1423
|
+
document.getElementById('modal-oauth-msg').textContent =
|
|
1424
|
+
planned.authHandoff.instructions || 'Authorize OAuth in your browser, then poll wait_for_connection to resume execution.';
|
|
1425
|
+
const link = document.getElementById('modal-oauth-link');
|
|
1426
|
+
link.href = planned.authHandoff.redirectUrl || '#';
|
|
1427
|
+
box.classList.remove('hidden');
|
|
1428
|
+
return true;
|
|
1429
|
+
}
|
|
1430
|
+
box.classList.add('hidden');
|
|
1431
|
+
return false;
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
async function waitAndResumeModalPlan() {
|
|
1435
|
+
if (!pendingModalHandoff || !pendingModalPlan) return;
|
|
1436
|
+
const resEl = document.getElementById('modal-result');
|
|
1437
|
+
resEl.classList.remove('hidden');
|
|
1438
|
+
resEl.textContent = 'Polling wait_for_connection for ' + pendingModalHandoff.provider + '...';
|
|
1439
|
+
try {
|
|
1440
|
+
const waited = await api('/api/v1/connections/wait', {
|
|
1441
|
+
method: 'POST',
|
|
1442
|
+
body: JSON.stringify({
|
|
1443
|
+
provider: pendingModalHandoff.provider,
|
|
1444
|
+
externalAccountId: pendingModalHandoff.externalAccountId,
|
|
1445
|
+
timeoutMs: 12000,
|
|
1446
|
+
pollIntervalMs: 1500
|
|
1447
|
+
})
|
|
1448
|
+
});
|
|
1449
|
+
if (!waited.connected) {
|
|
1450
|
+
resEl.textContent = JSON.stringify(waited, null, 2);
|
|
1451
|
+
showToast('Connection still pending: ' + waited.status);
|
|
1452
|
+
return;
|
|
1453
|
+
}
|
|
1454
|
+
document.getElementById('modal-oauth-box').classList.add('hidden');
|
|
1455
|
+
if (pendingModalPlan.approvalStatus === 'pending_approval') {
|
|
1456
|
+
await api('/api/v1/plans/' + pendingModalPlan.id + '/approve', { method: 'POST' });
|
|
1457
|
+
}
|
|
1458
|
+
const executed = await api('/api/v1/plans/' + pendingModalPlan.id + '/execute', { method: 'POST' });
|
|
1459
|
+
resEl.textContent = JSON.stringify({ oauthHandoff: waited, execution: executed }, null, 2);
|
|
1460
|
+
showToast('OAuth verified & plan executed!');
|
|
1461
|
+
await refreshOverview();
|
|
1462
|
+
} catch (err) {
|
|
1463
|
+
resEl.textContent = 'Error: ' + err.message;
|
|
1464
|
+
}
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
async function completeCallbackAndResumeModalPlan() {
|
|
1468
|
+
if (!pendingModalHandoff || !pendingModalPlan) return;
|
|
1469
|
+
const cbUrl =
|
|
1470
|
+
'/oauth/callback?format=json&workspace_id=' + encodeURIComponent(currentWorkspaceId) +
|
|
1471
|
+
'&provider=' + encodeURIComponent(pendingModalHandoff.provider) +
|
|
1472
|
+
'&connected_account_id=' + encodeURIComponent(pendingModalHandoff.externalAccountId || ('ca_' + Date.now())) +
|
|
1473
|
+
'&status=success';
|
|
1474
|
+
await fetch(cbUrl);
|
|
1475
|
+
showToast('Completed /oauth/callback handoff for ' + pendingModalHandoff.provider);
|
|
1476
|
+
await waitAndResumeModalPlan();
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
async function submitPlanOnly() {
|
|
1480
|
+
const resEl = document.getElementById('modal-result');
|
|
1481
|
+
resEl.classList.remove('hidden');
|
|
1482
|
+
try {
|
|
1483
|
+
const input = JSON.parse(document.getElementById('modal-tool-input').value || '{}');
|
|
1484
|
+
const reason = document.getElementById('modal-tool-reason').value;
|
|
1485
|
+
const planned = await api('/api/v1/plans', {
|
|
1486
|
+
method: 'POST',
|
|
1487
|
+
body: JSON.stringify({ toolSlug: currentTool.slug, input, reason })
|
|
1488
|
+
});
|
|
1489
|
+
renderModalOAuthHandoff(planned);
|
|
1490
|
+
resEl.textContent = JSON.stringify(planned, null, 2);
|
|
1491
|
+
showToast('Created plan ' + planned.plan.id);
|
|
1492
|
+
await refreshOverview();
|
|
1493
|
+
} catch (err) {
|
|
1494
|
+
resEl.textContent = 'Error: ' + err.message;
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
async function submitPlanAndExecute() {
|
|
1499
|
+
const resEl = document.getElementById('modal-result');
|
|
1500
|
+
resEl.classList.remove('hidden');
|
|
1501
|
+
resEl.textContent = 'Planning & executing ' + currentTool.slug + '...';
|
|
1502
|
+
try {
|
|
1503
|
+
const input = JSON.parse(document.getElementById('modal-tool-input').value || '{}');
|
|
1504
|
+
const reason = document.getElementById('modal-tool-reason').value;
|
|
1505
|
+
const planned = await api('/api/v1/plans', {
|
|
1506
|
+
method: 'POST',
|
|
1507
|
+
body: JSON.stringify({ toolSlug: currentTool.slug, input, reason })
|
|
1508
|
+
});
|
|
1509
|
+
if (renderModalOAuthHandoff(planned)) {
|
|
1510
|
+
resEl.textContent = JSON.stringify(planned, null, 2);
|
|
1511
|
+
showToast('OAuth handoff required for ' + planned.authHandoff.provider + ' before executing');
|
|
1512
|
+
await refreshOverview();
|
|
1513
|
+
return;
|
|
1514
|
+
}
|
|
1515
|
+
if (planned.plan.approvalStatus === 'pending_approval') {
|
|
1516
|
+
await api('/api/v1/plans/' + planned.plan.id + '/approve', { method: 'POST' });
|
|
1517
|
+
}
|
|
1518
|
+
const executed = await api('/api/v1/plans/' + planned.plan.id + '/execute', {
|
|
1519
|
+
method: 'POST'
|
|
1520
|
+
});
|
|
1521
|
+
resEl.textContent = JSON.stringify(executed, null, 2);
|
|
1522
|
+
showToast('Execution ' + executed.run.status + '!');
|
|
1523
|
+
await refreshOverview();
|
|
1524
|
+
} catch (err) {
|
|
1525
|
+
resEl.textContent = 'Error: ' + err.message;
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
|
|
1529
|
+
async function loadResources() {
|
|
1530
|
+
const data = await api('/api/v1/resources');
|
|
1531
|
+
const tbody = document.getElementById('resources-tbody');
|
|
1532
|
+
if (!data.resources.length) {
|
|
1533
|
+
tbody.innerHTML = '<tr><td colspan="6" style="color:var(--text-muted)">No resources provisioned yet. Click "+ Provision Service" to provision Neon, Turso, Supabase, Cloudflare, etc.</td></tr>';
|
|
1534
|
+
return;
|
|
1535
|
+
}
|
|
1536
|
+
tbody.innerHTML = data.resources.map(r =>
|
|
1537
|
+
'<tr>' +
|
|
1538
|
+
'<td class="mono" style="font-weight:600">' + r.resourceName + '</td>' +
|
|
1539
|
+
'<td>' + r.providerName + '</td>' +
|
|
1540
|
+
'<td class="mono">' + r.serviceSlug + '</td>' +
|
|
1541
|
+
'<td><span class="badge badge-projects">' + r.status + '</span></td>' +
|
|
1542
|
+
'<td class="mono" style="font-size:12px">' + (r.envVarKeys.length ? r.envVarKeys.join(', ') : 'Managed') + '</td>' +
|
|
1543
|
+
'<td>' +
|
|
1544
|
+
'<button class="btn btn-sm" onclick="quickRun(\\'resource.projects.rotate_credentials\\', { resource_name: \\'' + r.resourceName + '\\' })">Rotate Keys</button>' +
|
|
1545
|
+
'</td>' +
|
|
1546
|
+
'</tr>'
|
|
1547
|
+
).join('');
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
async function pullWorkspaceEnv() {
|
|
1551
|
+
const data = await api('/api/v1/resources/env');
|
|
1552
|
+
const box = document.getElementById('env-export-box');
|
|
1553
|
+
const pre = document.getElementById('env-export-content');
|
|
1554
|
+
box.classList.remove('hidden');
|
|
1555
|
+
pre.textContent = data.dotenv || '# No environment secrets stored in vault yet.';
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
async function loadConnections(syncLive) {
|
|
1559
|
+
const tbody = document.getElementById('connections-tbody');
|
|
1560
|
+
tbody.innerHTML = '<tr><td colspan="5" style="color:var(--text-secondary)">Syncing provider connections...</td></tr>';
|
|
1561
|
+
const data = await api('/api/v1/connections?sync=' + (syncLive ? 'true' : 'false'));
|
|
1562
|
+
tbody.innerHTML = data.connections.map(c =>
|
|
1563
|
+
'<tr>' +
|
|
1564
|
+
'<td style="font-weight:600">' + c.providerName + ' <span class="mono" style="color:var(--text-muted);font-size:12px">(' + c.providerSlug + ')</span></td>' +
|
|
1565
|
+
'<td>' + laneBadge(c.lane) + '</td>' +
|
|
1566
|
+
'<td><span class="badge ' + (c.status === 'active' ? 'badge-projects' : 'badge-warn') + '">' + c.status + '</span></td>' +
|
|
1567
|
+
'<td class="mono" style="font-size:12px;color:var(--text-secondary)">' + (c.externalAccountId || '—') + '</td>' +
|
|
1568
|
+
'<td style="display:flex;gap:6px;flex-wrap:wrap;align-items:center">' +
|
|
1569
|
+
(c.status === 'active'
|
|
1570
|
+
? '<span style="color:var(--emerald);font-size:12px;font-weight:600">✓ Connected</span>'
|
|
1571
|
+
: (c.redirectUrl ? '<a href="' + c.redirectUrl + '" target="_blank" class="btn btn-sm btn-primary">Authorize OAuth ↗</a>' : '') +
|
|
1572
|
+
'<button class="btn btn-sm" onclick="waitConnectionInUi(\\'' + c.providerSlug + '\\', \\'' + (c.externalAccountId || '') + '\\')">Wait / Poll</button>' +
|
|
1573
|
+
'<button class="btn btn-sm" onclick="completeCallbackInUi(\\'' + c.providerSlug + '\\', \\'' + (c.externalAccountId || '') + '\\')">Complete Handoff</button>') +
|
|
1574
|
+
'</td>' +
|
|
1575
|
+
'</tr>'
|
|
1576
|
+
).join('');
|
|
1577
|
+
await refreshOverview();
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1580
|
+
function startCustomProviderConnection() {
|
|
1581
|
+
const input = document.getElementById('custom-provider-input');
|
|
1582
|
+
const val = (input.value || '').trim().toLowerCase();
|
|
1583
|
+
if (!val) {
|
|
1584
|
+
showToast('Enter a provider slug (e.g. linear, jira, hubspot)');
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
input.value = '';
|
|
1588
|
+
startAppConnection(val);
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
async function waitConnectionInUi(provider, externalAccountId) {
|
|
1592
|
+
showToast('Polling wait_for_connection for ' + provider + '...');
|
|
1593
|
+
const waited = await api('/api/v1/connections/wait', {
|
|
1594
|
+
method: 'POST',
|
|
1595
|
+
body: JSON.stringify({ provider, externalAccountId: externalAccountId || undefined, timeoutMs: 8000, pollIntervalMs: 1500 })
|
|
1596
|
+
});
|
|
1597
|
+
showToast(waited.message || ('Status: ' + waited.status));
|
|
1598
|
+
await loadConnections(false);
|
|
1599
|
+
}
|
|
1600
|
+
|
|
1601
|
+
async function completeCallbackInUi(provider, externalAccountId) {
|
|
1602
|
+
const cbUrl =
|
|
1603
|
+
'/oauth/callback?format=json&workspace_id=' + encodeURIComponent(currentWorkspaceId) +
|
|
1604
|
+
'&provider=' + encodeURIComponent(provider) +
|
|
1605
|
+
'&connected_account_id=' + encodeURIComponent(externalAccountId || ('ca_' + Date.now())) +
|
|
1606
|
+
'&status=success';
|
|
1607
|
+
await fetch(cbUrl);
|
|
1608
|
+
showToast('OAuth callback handoff confirmed for ' + provider + '!');
|
|
1609
|
+
await loadConnections(false);
|
|
1610
|
+
}
|
|
1611
|
+
|
|
1612
|
+
async function startAppConnection(provider) {
|
|
1613
|
+
try {
|
|
1614
|
+
showToast('Starting OAuth connection for ' + provider + '...');
|
|
1615
|
+
const res = await api('/api/v1/connections', {
|
|
1616
|
+
method: 'POST',
|
|
1617
|
+
body: JSON.stringify({ provider, lane: 'composio_sdk' })
|
|
1618
|
+
});
|
|
1619
|
+
showToast(res.connection.message || 'Connection initiated');
|
|
1620
|
+
await loadConnections(false);
|
|
1621
|
+
} catch (err) {
|
|
1622
|
+
showToast('Error: ' + err.message);
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
async function loadMemory() {
|
|
1627
|
+
const q = (document.getElementById('memory-query') || {}).value || '';
|
|
1628
|
+
const data = await api('/api/v1/memory?query=' + encodeURIComponent(q));
|
|
1629
|
+
document.getElementById('mem-namespace').textContent = data.context.namespace;
|
|
1630
|
+
document.getElementById('nav-mem-count').textContent = (data.recentMemories || []).length || 'v5';
|
|
1631
|
+
document.getElementById('memory-context-box').textContent = JSON.stringify({
|
|
1632
|
+
enabled: data.context.enabled,
|
|
1633
|
+
namespace: data.context.namespace,
|
|
1634
|
+
staticFacts: data.context.staticFacts,
|
|
1635
|
+
dynamicContext: data.context.dynamicContext,
|
|
1636
|
+
recalledMemories: data.context.recalledMemories,
|
|
1637
|
+
formattedPromptContext: data.context.formattedPromptContext
|
|
1638
|
+
}, null, 2);
|
|
1639
|
+
|
|
1640
|
+
const tbody = document.getElementById('memories-tbody');
|
|
1641
|
+
if (!data.recentMemories || !data.recentMemories.length) {
|
|
1642
|
+
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 Supermemory v5.</td></tr>';
|
|
1643
|
+
return;
|
|
1644
|
+
}
|
|
1645
|
+
tbody.innerHTML = data.recentMemories.map(m =>
|
|
1646
|
+
'<tr>' +
|
|
1647
|
+
'<td class="mono" style="font-size:12px">' + m.documentId + '</td>' +
|
|
1648
|
+
'<td><span class="badge badge-sdk">' + m.kind + '</span></td>' +
|
|
1649
|
+
'<td style="font-weight:600">' + m.title + '</td>' +
|
|
1650
|
+
'<td style="font-size:12.5px;color:var(--text-secondary)">' + m.content + '</td>' +
|
|
1651
|
+
'<td class="mono" style="font-size:11.5px;color:var(--text-muted)">' + new Date(m.createdAt).toLocaleTimeString() + '</td>' +
|
|
1652
|
+
'<td><button class="btn btn-sm" onclick="deleteMemoryItem(\\'' + m.id + '\\')">Delete</button></td>' +
|
|
1653
|
+
'</tr>'
|
|
1654
|
+
).join('');
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
async function submitNewMemory() {
|
|
1658
|
+
const title = document.getElementById('memory-title').value.trim() || 'Workspace Fact';
|
|
1659
|
+
const kind = document.getElementById('memory-kind').value;
|
|
1660
|
+
const content = document.getElementById('memory-content').value.trim();
|
|
1661
|
+
if (!content) {
|
|
1662
|
+
showToast('Enter memory content first');
|
|
1663
|
+
return;
|
|
1664
|
+
}
|
|
1665
|
+
await api('/api/v1/memory', {
|
|
1666
|
+
method: 'POST',
|
|
1667
|
+
body: JSON.stringify({ title, kind, content })
|
|
1668
|
+
});
|
|
1669
|
+
document.getElementById('memory-title').value = '';
|
|
1670
|
+
document.getElementById('memory-content').value = '';
|
|
1671
|
+
showToast('Saved governed memory to Supermemory v5!');
|
|
1672
|
+
await loadMemory();
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
async function deleteMemoryItem(id) {
|
|
1676
|
+
await api('/api/v1/memory/' + encodeURIComponent(id), { method: 'DELETE' });
|
|
1677
|
+
showToast('Deleted memory from workspace brain');
|
|
1678
|
+
await loadMemory();
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
async function loadPlans() {
|
|
1682
|
+
const [data, gov] = await Promise.all([
|
|
1683
|
+
api('/api/v1/plans'),
|
|
1684
|
+
api('/api/v1/governance').catch(() => null)
|
|
1685
|
+
]);
|
|
1686
|
+
if (gov && gov.governance) {
|
|
1687
|
+
document.getElementById('gov-did').textContent = gov.governance.agentDid;
|
|
1688
|
+
document.getElementById('gov-pubkey').textContent = (gov.governance.publicKeyHex || '').slice(0, 24) + '...';
|
|
1689
|
+
const badge = document.getElementById('gov-chain-badge');
|
|
1690
|
+
badge.textContent = gov.governance.auditChainIntegrity
|
|
1691
|
+
? 'SHA-256 Audit Chain Verified (' + gov.governance.auditEntriesCount + ' entries)'
|
|
1692
|
+
: 'Audit Chain Warning';
|
|
1693
|
+
}
|
|
1694
|
+
const tbody = document.getElementById('plans-tbody');
|
|
1695
|
+
tbody.innerHTML = data.plans.map(p => {
|
|
1696
|
+
const verdict = p.decisionRecord ? p.decisionRecord.verdict : 'allow';
|
|
1697
|
+
return '<tr>' +
|
|
1698
|
+
'<td class="mono" style="font-size:12px">' + p.id + '</td>' +
|
|
1699
|
+
'<td class="mono" style="font-size:12px">' + p.toolSlug + '</td>' +
|
|
1700
|
+
'<td>' + riskBadge(p.riskLevel) + ' <span class="badge badge-sdk">' + verdict + '</span></td>' +
|
|
1701
|
+
'<td><span class="badge ' + (p.approvalStatus === 'pending_approval' ? 'badge-warn' : 'badge-projects') + '">' + p.approvalStatus + '</span></td>' +
|
|
1702
|
+
'<td style="display:flex;gap:6px">' +
|
|
1703
|
+
(p.approvalStatus === 'pending_approval'
|
|
1704
|
+
? '<button class="btn btn-sm btn-emerald" onclick="approveAndRun(\\'' + p.id + '\\')">Approve & Execute</button>'
|
|
1705
|
+
: p.approvalStatus === 'approved' || p.approvalStatus === 'auto_approved'
|
|
1706
|
+
? '<button class="btn btn-sm btn-primary" onclick="executeExistingPlan(\\'' + p.id + '\\')">Execute</button>'
|
|
1707
|
+
: '<span class="mono" style="font-size:11px;color:var(--text-muted)">' + (p.runId || 'Done') + '</span>') +
|
|
1708
|
+
'</td>' +
|
|
1709
|
+
'</tr>';
|
|
1710
|
+
}).join('');
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
async function approveAndRun(planId) {
|
|
1714
|
+
await api('/api/v1/plans/' + planId + '/approve', { method: 'POST' });
|
|
1715
|
+
await executeExistingPlan(planId);
|
|
1716
|
+
}
|
|
1717
|
+
|
|
1718
|
+
async function executeExistingPlan(planId) {
|
|
1719
|
+
const res = await api('/api/v1/plans/' + planId + '/execute', { method: 'POST' });
|
|
1720
|
+
showToast('Executed plan ' + planId + ' -> ' + res.run.status);
|
|
1721
|
+
await loadPlans();
|
|
1722
|
+
await refreshOverview();
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
async function savePolicy() {
|
|
1726
|
+
const mode = document.getElementById('policy-mode').value;
|
|
1727
|
+
const requireApprovalFor = [];
|
|
1728
|
+
document.querySelectorAll('#policy-risks input[type=checkbox]:checked').forEach(cb => {
|
|
1729
|
+
requireApprovalFor.push(cb.value);
|
|
1730
|
+
});
|
|
1731
|
+
await api('/api/v1/policy', {
|
|
1732
|
+
method: 'POST',
|
|
1733
|
+
body: JSON.stringify({ mode, requireApprovalFor })
|
|
1734
|
+
});
|
|
1735
|
+
showToast('Workspace governance policy updated!');
|
|
1736
|
+
await refreshOverview();
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
async function loadRuns() {
|
|
1740
|
+
const data = await api('/api/v1/runs');
|
|
1741
|
+
const tbody = document.getElementById('runs-tbody');
|
|
1742
|
+
tbody.innerHTML = data.runs.map(r =>
|
|
1743
|
+
'<tr>' +
|
|
1744
|
+
'<td class="mono" style="font-size:12px"><div>' + r.id + '</div><div style="color:var(--text-muted)">' + (r.receiptId || '') + '</div></td>' +
|
|
1745
|
+
'<td><div class="mono" style="font-size:12px">' + r.toolSlug + '</div>' + laneBadge(r.lane) + '</td>' +
|
|
1746
|
+
'<td>' + riskBadge(r.riskLevel) + '</td>' +
|
|
1747
|
+
'<td><span class="badge ' + (r.status === 'succeeded' ? 'badge-projects' : 'badge-danger') + '">' + r.status + '</span></td>' +
|
|
1748
|
+
'<td class="mono">' + (r.durationMs || 0) + 'ms</td>' +
|
|
1749
|
+
'<td><span class="badge badge-sdk">HMAC-SHA256 VERIFIED</span></td>' +
|
|
1750
|
+
'<td><button class="btn btn-sm" onclick="inspectReceipt(\\'' + (r.receiptId || r.id) + '\\')">Verify Receipt</button></td>' +
|
|
1751
|
+
'</tr>'
|
|
1752
|
+
).join('');
|
|
1753
|
+
}
|
|
1754
|
+
|
|
1755
|
+
async function inspectReceipt(receiptId) {
|
|
1756
|
+
const data = await api('/api/v1/receipts/' + encodeURIComponent(receiptId));
|
|
1757
|
+
alert(
|
|
1758
|
+
'Cryptographic Receipt & Microsoft Agent Governance Verification:\\n\\n' +
|
|
1759
|
+
'HMAC-SHA256 Receipt Chain Valid: ' + data.signatureValid + '\\n' +
|
|
1760
|
+
'Ed25519 DecisionRecord Valid: ' + data.governanceSignatureValid + '\\n\\n' +
|
|
1761
|
+
JSON.stringify(data.receipt, null, 2)
|
|
1762
|
+
);
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
async function loadLedger() {
|
|
1766
|
+
const data = await api('/api/v1/billing/ledger');
|
|
1767
|
+
const s = data.settlementSummary;
|
|
1768
|
+
const summaryBox = document.getElementById('settlement-summary-box');
|
|
1769
|
+
if (summaryBox && s) {
|
|
1770
|
+
const retailUsd = (s.totalUserRetailSpendCents / 100).toFixed(2);
|
|
1771
|
+
const wholesaleUsd = (s.totalSupplierWholesalePaidCents / 100).toFixed(2);
|
|
1772
|
+
const marginUsd = (s.totalMuxoNetMarginCents / 100).toFixed(2);
|
|
1773
|
+
summaryBox.innerHTML =
|
|
1774
|
+
'<div style="display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin-bottom:10px">' +
|
|
1775
|
+
'<div style="padding:8px;border:1px solid var(--border);border-radius:6px;background:var(--bg-elevated)">' +
|
|
1776
|
+
'<div style="font-size:10.5px;color:var(--text-muted)">USER PAID MUXO (RETAIL)</div>' +
|
|
1777
|
+
'<div class="mono" style="font-size:15px;font-weight:700;color:var(--text-primary)">$' + retailUsd + '</div>' +
|
|
1778
|
+
'<div style="font-size:10.5px;color:var(--text-secondary)">' + s.totalCreditsConsumed + ' credits metered</div>' +
|
|
1779
|
+
'</div>' +
|
|
1780
|
+
'<div style="padding:8px;border:1px solid var(--border);border-radius:6px;background:var(--bg-elevated)">' +
|
|
1781
|
+
'<div style="font-size:10.5px;color:var(--text-muted)">MUXO PAID SUPPLIERS</div>' +
|
|
1782
|
+
'<div class="mono" style="font-size:15px;font-weight:700;color:var(--amber)">$' + wholesaleUsd + '</div>' +
|
|
1783
|
+
'<div style="font-size:10.5px;color:var(--text-secondary)">60% wholesale payout</div>' +
|
|
1784
|
+
'</div>' +
|
|
1785
|
+
'<div style="padding:8px;border:1px solid var(--border);border-radius:6px;background:var(--bg-elevated)">' +
|
|
1786
|
+
'<div style="font-size:10.5px;color:var(--text-muted)">MUXO NET MARGIN</div>' +
|
|
1787
|
+
'<div class="mono" style="font-size:15px;font-weight:700;color:var(--emerald)">$' + marginUsd + '</div>' +
|
|
1788
|
+
'<div style="font-size:10.5px;color:var(--text-secondary)">40% platform margin</div>' +
|
|
1789
|
+
'</div>' +
|
|
1790
|
+
'</div>' +
|
|
1791
|
+
'<div class="mono" style="font-size:11px;color:var(--text-secondary)">' +
|
|
1792
|
+
'• Composio Instant Wallet: ' + s.bySupplier.composio_instant.runsCount + ' runs ($' + (s.bySupplier.composio_instant.supplierWholesalePaidCents / 100).toFixed(2) + ' paid to supplier)<br/>' +
|
|
1793
|
+
'• Composio Managed OAuth: ' + s.bySupplier.composio_sdk.runsCount + ' runs ($' + (s.bySupplier.composio_sdk.supplierWholesalePaidCents / 100).toFixed(2) + ' paid to supplier)<br/>' +
|
|
1794
|
+
'• Stripe Projects Infra: ' + s.bySupplier.stripe_projects.runsCount + ' runs ($' + (s.bySupplier.stripe_projects.supplierWholesalePaidCents / 100).toFixed(2) + ' paid to supplier)' +
|
|
1795
|
+
'</div>';
|
|
1796
|
+
}
|
|
1797
|
+
const tbody = document.getElementById('ledger-tbody');
|
|
1798
|
+
tbody.innerHTML = data.entries.map(e =>
|
|
1799
|
+
'<tr>' +
|
|
1800
|
+
'<td class="mono" style="font-size:11.5px;color:var(--text-secondary)">' + new Date(e.createdAt).toLocaleString() + '</td>' +
|
|
1801
|
+
'<td>' + e.description + '</td>' +
|
|
1802
|
+
'<td class="mono" style="color:' + (e.creditsDelta >= 0 ? 'var(--emerald)' : 'var(--amber)') + '">' + (e.creditsDelta >= 0 ? '+' : '') + e.creditsDelta + '</td>' +
|
|
1803
|
+
'<td class="mono">' + e.balanceAfter + '</td>' +
|
|
1804
|
+
'</tr>'
|
|
1805
|
+
).join('');
|
|
1806
|
+
}
|
|
1807
|
+
|
|
1808
|
+
async function instantTopup(credits) {
|
|
1809
|
+
try {
|
|
1810
|
+
const res = await api('/api/v1/billing/topup', {
|
|
1811
|
+
method: 'POST',
|
|
1812
|
+
body: JSON.stringify({ credits: credits || 1000 })
|
|
1813
|
+
});
|
|
1814
|
+
showToast('Purchased +' + res.creditsAdded + ' Muxo Credits ($' + res.usdPaid.toFixed(2) + ' USD)!');
|
|
1815
|
+
await refreshOverview();
|
|
1816
|
+
await loadLedger();
|
|
1817
|
+
} catch (err) {
|
|
1818
|
+
showToast('Top-up Error: ' + err.message);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
async function startCheckout(kind) {
|
|
1823
|
+
try {
|
|
1824
|
+
showToast('Creating live Stripe Checkout session...');
|
|
1825
|
+
const res = await api('/api/v1/billing/checkout', {
|
|
1826
|
+
method: 'POST',
|
|
1827
|
+
body: JSON.stringify({ kind })
|
|
1828
|
+
});
|
|
1829
|
+
if (res.url) {
|
|
1830
|
+
window.location.href = res.url;
|
|
1831
|
+
}
|
|
1832
|
+
} catch (err) {
|
|
1833
|
+
showToast('Stripe Error: ' + err.message);
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
// Check if returning from Stripe Checkout or OAuth Callback or Owner Claim
|
|
1838
|
+
async function checkCheckoutReturn() {
|
|
1839
|
+
const params = new URLSearchParams(window.location.search);
|
|
1840
|
+
const sessionId = params.get('session_id');
|
|
1841
|
+
if (params.get('checkout') === 'success' && sessionId) {
|
|
1842
|
+
try {
|
|
1843
|
+
const res = await api('/api/v1/billing/verify-session', {
|
|
1844
|
+
method: 'POST',
|
|
1845
|
+
body: JSON.stringify({ sessionId })
|
|
1846
|
+
});
|
|
1847
|
+
if (res.fulfilled) {
|
|
1848
|
+
showToast('Stripe payment verified! Workspace upgraded / credited.');
|
|
1849
|
+
}
|
|
1850
|
+
window.history.replaceState({}, '', '/');
|
|
1851
|
+
} catch (err) {
|
|
1852
|
+
console.error(err);
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
if (params.get('connected')) {
|
|
1856
|
+
const prov = params.get('connected');
|
|
1857
|
+
showToast('OAuth Connected: ' + prov + ' is now active!');
|
|
1858
|
+
window.history.replaceState({}, '', '/');
|
|
1859
|
+
}
|
|
1860
|
+
if (params.get('claimed')) {
|
|
1861
|
+
showToast('Workspace ownership claimed (' + params.get('claimed') + ')!');
|
|
1862
|
+
window.history.replaceState({}, '', '/');
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
window.addEventListener('DOMContentLoaded', async () => {
|
|
1867
|
+
await checkCheckoutReturn();
|
|
1868
|
+
await refreshOverview();
|
|
1869
|
+
// Sync live Stripe Projects & Composio providers in background on first load
|
|
1870
|
+
loadConnections(true).catch(() => {});
|
|
1871
|
+
});
|
|
1872
|
+
</script>
|
|
1873
|
+
</body>
|
|
1874
|
+
</html>`;
|
|
1875
|
+
}
|
|
1876
|
+
export function renderLandingHtml() {
|
|
1877
|
+
return `<!DOCTYPE html>
|
|
1878
|
+
<html lang="en">
|
|
1879
|
+
<head>
|
|
1880
|
+
<meta charset="UTF-8" />
|
|
1881
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
1882
|
+
<title>Muxo (muxo.ai) — The Unified Execution, Infrastructure, Memory & Governance Boundary for AI Agents</title>
|
|
1883
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
1884
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
1885
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Space+Grotesk:wght@600;700&display=swap" rel="stylesheet">
|
|
1886
|
+
<style>
|
|
1887
|
+
:root {
|
|
1888
|
+
--bg: #050507;
|
|
1889
|
+
--surface: #0D0F14;
|
|
1890
|
+
--elevated: #141720;
|
|
1891
|
+
--border: #232736;
|
|
1892
|
+
--text: #F5F2EB;
|
|
1893
|
+
--muted: #A0A6BA;
|
|
1894
|
+
--accent: #FF5A1F;
|
|
1895
|
+
--mint: #2DD4BF;
|
|
1896
|
+
--cyan: #38BDF8;
|
|
1897
|
+
--violet: #A855F7;
|
|
1898
|
+
}
|
|
1899
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
1900
|
+
body {
|
|
1901
|
+
background: var(--bg);
|
|
1902
|
+
color: var(--text);
|
|
1903
|
+
font-family: 'Inter', sans-serif;
|
|
1904
|
+
line-height: 1.55;
|
|
1905
|
+
-webkit-font-smoothing: antialiased;
|
|
1906
|
+
}
|
|
1907
|
+
.container { max-width: 1180px; margin: 0 auto; padding: 0 24px; }
|
|
1908
|
+
header {
|
|
1909
|
+
border-bottom: 1px solid var(--border);
|
|
1910
|
+
background: rgba(5, 5, 7, 0.85);
|
|
1911
|
+
backdrop-filter: blur(12px);
|
|
1912
|
+
position: sticky;
|
|
1913
|
+
top: 0;
|
|
1914
|
+
z-index: 50;
|
|
1915
|
+
}
|
|
1916
|
+
.nav {
|
|
1917
|
+
display: flex;
|
|
1918
|
+
justify-content: space-between;
|
|
1919
|
+
align-items: center;
|
|
1920
|
+
height: 68px;
|
|
1921
|
+
}
|
|
1922
|
+
.logo {
|
|
1923
|
+
font-family: 'Space Grotesk', sans-serif;
|
|
1924
|
+
font-size: 20px;
|
|
1925
|
+
font-weight: 700;
|
|
1926
|
+
display: flex;
|
|
1927
|
+
align-items: center;
|
|
1928
|
+
gap: 10px;
|
|
1929
|
+
text-decoration: none;
|
|
1930
|
+
color: var(--text);
|
|
1931
|
+
}
|
|
1932
|
+
.logo-mark {
|
|
1933
|
+
width: 30px;
|
|
1934
|
+
height: 30px;
|
|
1935
|
+
border-radius: 7px;
|
|
1936
|
+
background: linear-gradient(135deg, var(--accent), var(--mint));
|
|
1937
|
+
display: grid;
|
|
1938
|
+
place-items: center;
|
|
1939
|
+
color: #050507;
|
|
1940
|
+
font-family: 'JetBrains Mono', monospace;
|
|
1941
|
+
font-weight: 800;
|
|
1942
|
+
}
|
|
1943
|
+
.nav-links { display: flex; gap: 18px; align-items: center; }
|
|
1944
|
+
.nav-links a {
|
|
1945
|
+
color: var(--muted);
|
|
1946
|
+
text-decoration: none;
|
|
1947
|
+
font-size: 14px;
|
|
1948
|
+
font-weight: 500;
|
|
1949
|
+
}
|
|
1950
|
+
.nav-links a:hover { color: var(--text); }
|
|
1951
|
+
.btn {
|
|
1952
|
+
display: inline-flex;
|
|
1953
|
+
align-items: center;
|
|
1954
|
+
gap: 8px;
|
|
1955
|
+
padding: 9px 16px;
|
|
1956
|
+
border-radius: 7px;
|
|
1957
|
+
font-size: 13.5px;
|
|
1958
|
+
font-weight: 600;
|
|
1959
|
+
text-decoration: none;
|
|
1960
|
+
border: 1px solid var(--border);
|
|
1961
|
+
background: var(--elevated);
|
|
1962
|
+
color: var(--text);
|
|
1963
|
+
cursor: pointer;
|
|
1964
|
+
}
|
|
1965
|
+
.btn-primary {
|
|
1966
|
+
background: var(--accent);
|
|
1967
|
+
border-color: var(--accent);
|
|
1968
|
+
color: #fff;
|
|
1969
|
+
}
|
|
1970
|
+
.hero {
|
|
1971
|
+
padding: 72px 0 48px;
|
|
1972
|
+
text-align: center;
|
|
1973
|
+
}
|
|
1974
|
+
.eyebrow {
|
|
1975
|
+
display: inline-flex;
|
|
1976
|
+
align-items: center;
|
|
1977
|
+
gap: 8px;
|
|
1978
|
+
font-family: 'JetBrains Mono', monospace;
|
|
1979
|
+
font-size: 12px;
|
|
1980
|
+
padding: 5px 12px;
|
|
1981
|
+
border-radius: 99px;
|
|
1982
|
+
background: rgba(255, 90, 31, 0.14);
|
|
1983
|
+
color: var(--accent);
|
|
1984
|
+
border: 1px solid rgba(255, 90, 31, 0.35);
|
|
1985
|
+
margin-bottom: 20px;
|
|
1986
|
+
}
|
|
1987
|
+
h1 {
|
|
1988
|
+
font-family: 'Space Grotesk', sans-serif;
|
|
1989
|
+
font-size: clamp(36px, 5vw, 58px);
|
|
1990
|
+
line-height: 1.08;
|
|
1991
|
+
letter-spacing: -0.03em;
|
|
1992
|
+
max-width: 900px;
|
|
1993
|
+
margin: 0 auto 18px;
|
|
1994
|
+
}
|
|
1995
|
+
.subtitle {
|
|
1996
|
+
color: var(--muted);
|
|
1997
|
+
font-size: 18px;
|
|
1998
|
+
max-width: 740px;
|
|
1999
|
+
margin: 0 auto 30px;
|
|
2000
|
+
}
|
|
2001
|
+
.pillars {
|
|
2002
|
+
display: grid;
|
|
2003
|
+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
|
2004
|
+
gap: 16px;
|
|
2005
|
+
margin: 40px 0;
|
|
2006
|
+
}
|
|
2007
|
+
.pillar-card {
|
|
2008
|
+
background: var(--surface);
|
|
2009
|
+
border: 1px solid var(--border);
|
|
2010
|
+
border-radius: 10px;
|
|
2011
|
+
padding: 20px;
|
|
2012
|
+
text-align: left;
|
|
2013
|
+
}
|
|
2014
|
+
.pillar-tag {
|
|
2015
|
+
font-family: 'JetBrains Mono', monospace;
|
|
2016
|
+
font-size: 11px;
|
|
2017
|
+
text-transform: uppercase;
|
|
2018
|
+
color: var(--mint);
|
|
2019
|
+
margin-bottom: 6px;
|
|
2020
|
+
}
|
|
2021
|
+
.pillar-title {
|
|
2022
|
+
font-family: 'Space Grotesk', sans-serif;
|
|
2023
|
+
font-size: 18px;
|
|
2024
|
+
margin-bottom: 8px;
|
|
2025
|
+
}
|
|
2026
|
+
.terminal-box {
|
|
2027
|
+
background: var(--surface);
|
|
2028
|
+
border: 1px solid var(--border);
|
|
2029
|
+
border-radius: 10px;
|
|
2030
|
+
padding: 20px;
|
|
2031
|
+
max-width: 820px;
|
|
2032
|
+
margin: 0 auto 48px;
|
|
2033
|
+
text-align: left;
|
|
2034
|
+
font-family: 'JetBrains Mono', monospace;
|
|
2035
|
+
font-size: 13px;
|
|
2036
|
+
}
|
|
2037
|
+
.canvas-grid {
|
|
2038
|
+
display: grid;
|
|
2039
|
+
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
|
|
2040
|
+
gap: 14px;
|
|
2041
|
+
margin-bottom: 64px;
|
|
2042
|
+
}
|
|
2043
|
+
.provider-card {
|
|
2044
|
+
background: var(--surface);
|
|
2045
|
+
border: 1px solid var(--border);
|
|
2046
|
+
border-radius: 8px;
|
|
2047
|
+
padding: 16px;
|
|
2048
|
+
}
|
|
2049
|
+
</style>
|
|
2050
|
+
</head>
|
|
2051
|
+
<body>
|
|
2052
|
+
<header>
|
|
2053
|
+
<div class="container nav">
|
|
2054
|
+
<a href="/landing" class="logo">
|
|
2055
|
+
<span class="logo-mark">M</span>
|
|
2056
|
+
<span>muxo.ai</span>
|
|
2057
|
+
</a>
|
|
2058
|
+
<div class="nav-links">
|
|
2059
|
+
<a href="#pillars">4-Pillar Architecture</a>
|
|
2060
|
+
<a href="#canvas">Live Provider Canvas</a>
|
|
2061
|
+
<a href="https://docs.muxo.ai" target="_blank">Documentation (docs.muxo.ai)</a>
|
|
2062
|
+
<a href="/skill.md" target="_blank">Agent Skill (/skill.md)</a>
|
|
2063
|
+
<a href="/" class="btn btn-primary">Open Console (app.muxo.ai) →</a>
|
|
2064
|
+
</div>
|
|
2065
|
+
</div>
|
|
2066
|
+
</header>
|
|
2067
|
+
|
|
2068
|
+
<main class="container">
|
|
2069
|
+
<section class="hero">
|
|
2070
|
+
<div class="eyebrow">ONE KEY (mk_live_*) · ONE MCP ENDPOINT · 4 GOVERNED PILLARS</div>
|
|
2071
|
+
<h1>Your agent's hands, cloud infrastructure, memory brain, and cryptographic governance.</h1>
|
|
2072
|
+
<p class="subtitle">
|
|
2073
|
+
Customers and AI agents only ever connect to <strong>Muxo</strong>. Underneath, Muxo unifies Composio SDK & Instant, Stripe Projects Cloud Provisioning, Supermemory v5, and the Microsoft Agent Governance Toolkit.
|
|
2074
|
+
</p>
|
|
2075
|
+
<div style="display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin-bottom:32px">
|
|
2076
|
+
<a href="/" class="btn btn-primary">Launch Operator Console (app.muxo.ai)</a>
|
|
2077
|
+
<a href="https://docs.muxo.ai" target="_blank" class="btn">Read Mintlify Docs (docs.muxo.ai)</a>
|
|
2078
|
+
<a href="/skill.md" target="_blank" class="btn">Inspect /skill.md</a>
|
|
2079
|
+
</div>
|
|
2080
|
+
|
|
2081
|
+
<div class="terminal-box">
|
|
2082
|
+
<div style="color:var(--muted);margin-bottom:8px"># Install the Muxo Plugin (OpenAI Codex, ChatGPT, Claude Code & Factory Droid)</div>
|
|
2083
|
+
<div style="color:var(--mint)">$ codex plugin add muxo@muxo && muxo login --signup --name "ProdAgent" && muxo link github --wait</div>
|
|
2084
|
+
<div style="color:var(--muted);margin-top:10px;margin-bottom:6px"># Autonomous Agent 2-Call Onboarding (Zero Browser Required)</div>
|
|
2085
|
+
<div style="color:var(--cyan)" id="landing-curl-cmd">$ curl -sX POST http://localhost:4310/api/v1/agents/signup -H "Content-Type: application/json" -d '{"agentName":"ProdAgent"}'</div>
|
|
2086
|
+
<div style="color:var(--text);margin-top:8px"># 19 Governed MCP Operations · Streamable HTTP + OAuth Callback Handoff:</div>
|
|
2087
|
+
<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>
|
|
2088
|
+
</div>
|
|
2089
|
+
</section>
|
|
2090
|
+
|
|
2091
|
+
<section id="pillars" class="pillars">
|
|
2092
|
+
<div class="pillar-card">
|
|
2093
|
+
<div class="pillar-tag">Pillar 1 · app.* & instant.*</div>
|
|
2094
|
+
<div class="pillar-title">Composio SDK + Instant</div>
|
|
2095
|
+
<p style="color:var(--muted);font-size:13.5px">Managed OAuth across GitHub, Gmail, Slack, Notion, Linear, plus zero-auth instant search, scrape, HN, and DNS tools.</p>
|
|
2096
|
+
</div>
|
|
2097
|
+
<div class="pillar-card">
|
|
2098
|
+
<div class="pillar-tag">Pillar 2 · resource.*</div>
|
|
2099
|
+
<div class="pillar-title">Stripe Projects Cloud</div>
|
|
2100
|
+
<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>
|
|
2101
|
+
</div>
|
|
2102
|
+
<div class="pillar-card">
|
|
2103
|
+
<div class="pillar-tag">Pillar 3 · /ns/muxo-v5-*</div>
|
|
2104
|
+
<div class="pillar-title">Supermemory v5 Brain</div>
|
|
2105
|
+
<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>
|
|
2106
|
+
</div>
|
|
2107
|
+
<div class="pillar-card">
|
|
2108
|
+
<div class="pillar-tag">Pillar 4 · Ed25519 + SHA-256</div>
|
|
2109
|
+
<div class="pillar-title">Microsoft Agent Governance</div>
|
|
2110
|
+
<p style="color:var(--muted);font-size:13.5px">McpSecurityScanner ──► PolicyEngine ──► AgentIdentity (DID) ──► AuditLogger ──► Ed25519 signed DecisionRecord.</p>
|
|
2111
|
+
</div>
|
|
2112
|
+
</section>
|
|
2113
|
+
|
|
2114
|
+
<section id="canvas">
|
|
2115
|
+
<div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:16px;flex-wrap:wrap;gap:12px">
|
|
2116
|
+
<div>
|
|
2117
|
+
<h2 style="font-family:'Space Grotesk',sans-serif;font-size:24px">Interactive Unified Capability Canvas</h2>
|
|
2118
|
+
<p style="color:var(--muted);font-size:14px">Live query against the Muxo catalog across all lanes.</p>
|
|
2119
|
+
</div>
|
|
2120
|
+
<input id="landing-search" type="text" placeholder="Filter live tools (e.g. neon, github, search)..." style="background:var(--surface);border:1px solid var(--border);color:var(--text);padding:9px 14px;border-radius:7px;min-width:280px" oninput="filterLandingCatalog()" />
|
|
2121
|
+
</div>
|
|
2122
|
+
<div id="landing-grid" class="canvas-grid"></div>
|
|
2123
|
+
</section>
|
|
2124
|
+
</main>
|
|
2125
|
+
|
|
2126
|
+
<script>
|
|
2127
|
+
async function filterLandingCatalog() {
|
|
2128
|
+
const q = document.getElementById('landing-search').value || '';
|
|
2129
|
+
const res = await fetch('/api/v1/tools?query=' + encodeURIComponent(q) + '&limit=18');
|
|
2130
|
+
const data = await res.json();
|
|
2131
|
+
const grid = document.getElementById('landing-grid');
|
|
2132
|
+
grid.innerHTML = (data.tools || []).map(t =>
|
|
2133
|
+
'<div class="provider-card">' +
|
|
2134
|
+
'<div style="font-family:JetBrains Mono,monospace;font-size:11px;color:var(--accent);margin-bottom:4px">' + t.lane + ' · ' + t.riskLevel + '</div>' +
|
|
2135
|
+
'<div style="font-weight:600;margin-bottom:4px">' + t.name + '</div>' +
|
|
2136
|
+
'<div style="font-family:JetBrains Mono,monospace;font-size:12px;color:var(--mint);margin-bottom:8px">' + t.slug + '</div>' +
|
|
2137
|
+
'<div style="font-size:13px;color:var(--muted);margin-bottom:12px">' + t.description + '</div>' +
|
|
2138
|
+
'<a href="/" class="btn" style="font-size:12px;padding:6px 10px">Run in Console →</a>' +
|
|
2139
|
+
'</div>'
|
|
2140
|
+
).join('');
|
|
2141
|
+
}
|
|
2142
|
+
filterLandingCatalog();
|
|
2143
|
+
(function updateOriginUrls() {
|
|
2144
|
+
const origin = window.location.origin;
|
|
2145
|
+
const curlEl = document.getElementById('landing-curl-cmd');
|
|
2146
|
+
const mcpEl = document.getElementById('landing-mcp-urls');
|
|
2147
|
+
if (curlEl) curlEl.textContent = '$ curl -sX POST ' + origin + '/api/v1/agents/signup -H "Content-Type: application/json" -d ' + JSON.stringify(JSON.stringify({ agentName: 'ProdAgent' }));
|
|
2148
|
+
if (mcpEl) mcpEl.textContent = 'MCP: ' + origin + '/mcp | OAuth Callback: ' + origin + '/oauth/callback | Skill: ' + origin + '/skill.md';
|
|
2149
|
+
})();
|
|
2150
|
+
</script>
|
|
2151
|
+
</body>
|
|
2152
|
+
</html>`;
|
|
2153
|
+
}
|