docorbit 0.1.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/LICENSE +21 -0
- package/README.md +660 -0
- package/apps/cli/bin/docorbit.js +8 -0
- package/apps/cli/src/commands/add.ts +44 -0
- package/apps/cli/src/commands/api.ts +38 -0
- package/apps/cli/src/commands/context.ts +47 -0
- package/apps/cli/src/commands/dashboard.ts +55 -0
- package/apps/cli/src/commands/diff.ts +30 -0
- package/apps/cli/src/commands/evaluate.ts +133 -0
- package/apps/cli/src/commands/examples.ts +39 -0
- package/apps/cli/src/commands/export.ts +89 -0
- package/apps/cli/src/commands/impact.ts +31 -0
- package/apps/cli/src/commands/init.ts +69 -0
- package/apps/cli/src/commands/inspect.ts +30 -0
- package/apps/cli/src/commands/mcp.ts +72 -0
- package/apps/cli/src/commands/pitfalls.ts +38 -0
- package/apps/cli/src/commands/recipes.ts +35 -0
- package/apps/cli/src/commands/search.ts +48 -0
- package/apps/cli/src/commands/update.ts +73 -0
- package/apps/cli/src/commands/verify.ts +48 -0
- package/apps/cli/src/formatters/colors.ts +23 -0
- package/apps/cli/src/formatters/inspection.ts +102 -0
- package/apps/cli/src/formatters/knowledge.ts +272 -0
- package/apps/cli/src/formatters/retrieval.ts +74 -0
- package/apps/cli/src/formatters/terminal.ts +6 -0
- package/apps/cli/src/formatters/verification.ts +126 -0
- package/apps/cli/src/index.ts +409 -0
- package/bin/docorbit.js +8 -0
- package/package.json +46 -0
- package/packages/core/src/dashboard/server.ts +314 -0
- package/packages/core/src/dashboard/ui.ts +586 -0
- package/packages/core/src/implementation-service.ts +451 -0
- package/packages/core/src/index.ts +7 -0
- package/packages/core/src/inspector.ts +71 -0
- package/packages/core/src/pipeline.ts +331 -0
- package/packages/crawler/src/config.ts +12 -0
- package/packages/crawler/src/fetcher.ts +185 -0
- package/packages/crawler/src/index.ts +2 -0
- package/packages/discovery/src/index.ts +31 -0
- package/packages/discovery/src/provider.ts +47 -0
- package/packages/discovery/src/providers/generic.ts +98 -0
- package/packages/discovery/src/providers/github.ts +61 -0
- package/packages/discovery/src/providers/llms-txt.ts +73 -0
- package/packages/discovery/src/providers/markdown.ts +48 -0
- package/packages/discovery/src/providers/openapi.ts +91 -0
- package/packages/discovery/src/providers/sitemap.ts +62 -0
- package/packages/discovery/src/providers/skill.ts +54 -0
- package/packages/discovery/src/ranker.ts +123 -0
- package/packages/evaluation/src/dataset.ts +963 -0
- package/packages/evaluation/src/index.ts +8 -0
- package/packages/evaluation/src/runner.ts +241 -0
- package/packages/evaluation/src/strategies/context7-runner.ts +269 -0
- package/packages/evaluation/src/strategies/docorbit-runner.ts +228 -0
- package/packages/evaluation/src/strategies/firecrawl-runner.ts +172 -0
- package/packages/evaluation/src/strategies/web-search-runner.ts +194 -0
- package/packages/evaluation/src/types.ts +34 -0
- package/packages/evaluation/src/version-matcher.ts +73 -0
- package/packages/export/src/agents-md.ts +200 -0
- package/packages/export/src/claude-md.ts +141 -0
- package/packages/export/src/docs-map.ts +150 -0
- package/packages/export/src/index.ts +6 -0
- package/packages/export/src/llms-txt.ts +96 -0
- package/packages/export/src/service.ts +250 -0
- package/packages/export/src/skill-md.ts +128 -0
- package/packages/mcp/src/index.ts +46 -0
- package/packages/mcp/src/resources/index.ts +189 -0
- package/packages/mcp/src/server.ts +278 -0
- package/packages/mcp/src/tools/analyze-impact.ts +74 -0
- package/packages/mcp/src/tools/check-api.ts +86 -0
- package/packages/mcp/src/tools/diff-docs.ts +68 -0
- package/packages/mcp/src/tools/export-context.ts +73 -0
- package/packages/mcp/src/tools/find-api.ts +99 -0
- package/packages/mcp/src/tools/find-example.ts +100 -0
- package/packages/mcp/src/tools/find-pitfall.ts +94 -0
- package/packages/mcp/src/tools/find-recipe.ts +98 -0
- package/packages/mcp/src/tools/get-doc.ts +130 -0
- package/packages/mcp/src/tools/get-docs-map.ts +64 -0
- package/packages/mcp/src/tools/get-version.ts +118 -0
- package/packages/mcp/src/tools/implementation-context.ts +88 -0
- package/packages/mcp/src/tools/index.ts +59 -0
- package/packages/mcp/src/tools/list-sources.ts +85 -0
- package/packages/mcp/src/tools/search-docs.ts +123 -0
- package/packages/mcp/src/tools/types.ts +28 -0
- package/packages/mcp/src/transports/http.ts +256 -0
- package/packages/mcp/src/transports/stdio.ts +105 -0
- package/packages/mcp/src/transports/types.ts +6 -0
- package/packages/mcp/src/types.ts +102 -0
- package/packages/normalizer/src/example-indexer.ts +240 -0
- package/packages/normalizer/src/html.ts +253 -0
- package/packages/normalizer/src/index.ts +8 -0
- package/packages/normalizer/src/llms.ts +83 -0
- package/packages/normalizer/src/openapi/endpoint-parser.ts +406 -0
- package/packages/normalizer/src/openapi/schema-resolver.ts +111 -0
- package/packages/normalizer/src/openapi.ts +2 -0
- package/packages/normalizer/src/page.ts +184 -0
- package/packages/normalizer/src/pitfall-extractor.ts +190 -0
- package/packages/normalizer/src/slicer.ts +455 -0
- package/packages/retrieval/src/engine.ts +120 -0
- package/packages/retrieval/src/index.ts +7 -0
- package/packages/retrieval/src/intent.ts +43 -0
- package/packages/retrieval/src/packer.ts +145 -0
- package/packages/retrieval/src/recipe-engine.ts +313 -0
- package/packages/retrieval/src/scorer.ts +139 -0
- package/packages/retrieval/src/weights.ts +31 -0
- package/packages/security/src/annotations.ts +112 -0
- package/packages/security/src/index.ts +2 -0
- package/packages/security/src/ssrf.ts +153 -0
- package/packages/shared/src/errors.ts +53 -0
- package/packages/shared/src/hashing.ts +23 -0
- package/packages/shared/src/index.ts +3 -0
- package/packages/shared/src/types.ts +881 -0
- package/packages/storage/src/db.ts +72 -0
- package/packages/storage/src/index.ts +11 -0
- package/packages/storage/src/interfaces.ts +115 -0
- package/packages/storage/src/repositories/api-repository.ts +219 -0
- package/packages/storage/src/repositories/chunk-repository.ts +316 -0
- package/packages/storage/src/repositories/example-repository.ts +206 -0
- package/packages/storage/src/repositories/page-repository.ts +205 -0
- package/packages/storage/src/repositories/pitfall-repository.ts +188 -0
- package/packages/storage/src/repositories/source-repository.ts +205 -0
- package/packages/storage/src/repository.ts +256 -0
- package/packages/storage/src/schema.ts +269 -0
- package/packages/storage/src/search-tokens.ts +28 -0
- package/packages/verification/src/diff-engine.ts +258 -0
- package/packages/verification/src/extractor.ts +339 -0
- package/packages/verification/src/impact-scanner.ts +203 -0
- package/packages/verification/src/index.ts +5 -0
- package/packages/verification/src/services.ts +238 -0
- package/packages/verification/src/verifier.ts +375 -0
- package/packages/workspace/src/detector.ts +143 -0
- package/packages/workspace/src/ecosystems/cargo.ts +84 -0
- package/packages/workspace/src/ecosystems/composer.ts +42 -0
- package/packages/workspace/src/ecosystems/go.ts +54 -0
- package/packages/workspace/src/ecosystems/index.ts +34 -0
- package/packages/workspace/src/ecosystems/maven.ts +34 -0
- package/packages/workspace/src/ecosystems/npm.ts +83 -0
- package/packages/workspace/src/ecosystems/pub.ts +40 -0
- package/packages/workspace/src/ecosystems/pypi.ts +100 -0
- package/packages/workspace/src/ecosystems/rubygems.ts +30 -0
- package/packages/workspace/src/ecosystems/types.ts +18 -0
- package/packages/workspace/src/index.ts +5 -0
- package/packages/workspace/src/lockfile.ts +194 -0
- package/packages/workspace/src/resolver.ts +234 -0
- package/packages/workspace/src/semver.ts +259 -0
|
@@ -0,0 +1,586 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Embedded HTML/CSS/JS dashboard UI for DocOrbit.
|
|
3
|
+
* Lightweight, zero external dependencies, zero CDN requests, fully offline capable.
|
|
4
|
+
*/
|
|
5
|
+
export function renderDashboardHtml(): string {
|
|
6
|
+
return `<!DOCTYPE html>
|
|
7
|
+
<html lang="en">
|
|
8
|
+
<head>
|
|
9
|
+
<meta charset="UTF-8">
|
|
10
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
11
|
+
<title>DocOrbit — Documentation Intelligence Dashboard</title>
|
|
12
|
+
<style>
|
|
13
|
+
:root {
|
|
14
|
+
--bg: #0f172a;
|
|
15
|
+
--surface: #1e293b;
|
|
16
|
+
--surface-hover: #334155;
|
|
17
|
+
--border: #334155;
|
|
18
|
+
--text: #f8fafc;
|
|
19
|
+
--text-muted: #94a3b8;
|
|
20
|
+
--primary: #6366f1;
|
|
21
|
+
--primary-hover: #4f46e5;
|
|
22
|
+
--accent: #06b6d4;
|
|
23
|
+
--success: #10b981;
|
|
24
|
+
--warning: #f59e0b;
|
|
25
|
+
--danger: #ef4444;
|
|
26
|
+
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
27
|
+
--font-sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
28
|
+
}
|
|
29
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
30
|
+
body {
|
|
31
|
+
background-color: var(--bg);
|
|
32
|
+
color: var(--text);
|
|
33
|
+
font-family: var(--font-sans);
|
|
34
|
+
line-height: 1.5;
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-direction: column;
|
|
37
|
+
height: 100vh;
|
|
38
|
+
overflow: hidden;
|
|
39
|
+
}
|
|
40
|
+
header {
|
|
41
|
+
background: var(--surface);
|
|
42
|
+
border-bottom: 1px solid var(--border);
|
|
43
|
+
padding: 0.75rem 1.5rem;
|
|
44
|
+
display: flex;
|
|
45
|
+
align-items: center;
|
|
46
|
+
justify-content: space-between;
|
|
47
|
+
}
|
|
48
|
+
.brand {
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
gap: 0.75rem;
|
|
52
|
+
}
|
|
53
|
+
.brand-icon {
|
|
54
|
+
width: 2rem;
|
|
55
|
+
height: 2rem;
|
|
56
|
+
background: linear-gradient(135deg, var(--primary), var(--accent));
|
|
57
|
+
border-radius: 6px;
|
|
58
|
+
display: flex;
|
|
59
|
+
align-items: center;
|
|
60
|
+
justify-content: center;
|
|
61
|
+
font-weight: 800;
|
|
62
|
+
color: #fff;
|
|
63
|
+
}
|
|
64
|
+
.brand-title {
|
|
65
|
+
font-size: 1.15rem;
|
|
66
|
+
font-weight: 700;
|
|
67
|
+
letter-spacing: -0.02em;
|
|
68
|
+
}
|
|
69
|
+
.badge {
|
|
70
|
+
font-size: 0.75rem;
|
|
71
|
+
padding: 0.2rem 0.5rem;
|
|
72
|
+
border-radius: 4px;
|
|
73
|
+
font-weight: 600;
|
|
74
|
+
text-transform: uppercase;
|
|
75
|
+
letter-spacing: 0.05em;
|
|
76
|
+
}
|
|
77
|
+
.badge-primary { background: rgba(99, 102, 241, 0.2); color: var(--primary); border: 1px solid var(--primary); }
|
|
78
|
+
.badge-success { background: rgba(16, 185, 129, 0.2); color: var(--success); border: 1px solid var(--success); }
|
|
79
|
+
.badge-warning { background: rgba(245, 158, 11, 0.2); color: var(--warning); border: 1px solid var(--warning); }
|
|
80
|
+
.badge-danger { background: rgba(239, 68, 68, 0.2); color: var(--danger); border: 1px solid var(--danger); }
|
|
81
|
+
.badge-untrusted { background: rgba(245, 158, 11, 0.15); color: #fbbf24; border: 1px solid #d97706; }
|
|
82
|
+
|
|
83
|
+
nav.tabs {
|
|
84
|
+
background: var(--surface);
|
|
85
|
+
border-bottom: 1px solid var(--border);
|
|
86
|
+
display: flex;
|
|
87
|
+
padding: 0 1.5rem;
|
|
88
|
+
gap: 0.5rem;
|
|
89
|
+
}
|
|
90
|
+
.tab-btn {
|
|
91
|
+
background: none;
|
|
92
|
+
border: none;
|
|
93
|
+
color: var(--text-muted);
|
|
94
|
+
padding: 0.75rem 1rem;
|
|
95
|
+
font-size: 0.9rem;
|
|
96
|
+
font-weight: 500;
|
|
97
|
+
cursor: pointer;
|
|
98
|
+
border-bottom: 2px solid transparent;
|
|
99
|
+
transition: all 0.15s ease;
|
|
100
|
+
}
|
|
101
|
+
.tab-btn:hover { color: var(--text); }
|
|
102
|
+
.tab-btn.active {
|
|
103
|
+
color: var(--accent);
|
|
104
|
+
border-bottom-color: var(--accent);
|
|
105
|
+
font-weight: 600;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
main {
|
|
109
|
+
flex: 1;
|
|
110
|
+
overflow-y: auto;
|
|
111
|
+
padding: 1.5rem;
|
|
112
|
+
max-width: 1400px;
|
|
113
|
+
margin: 0 auto;
|
|
114
|
+
width: 100%;
|
|
115
|
+
}
|
|
116
|
+
.tab-content { display: none; }
|
|
117
|
+
.tab-content.active { display: block; }
|
|
118
|
+
|
|
119
|
+
.grid-stats {
|
|
120
|
+
display: grid;
|
|
121
|
+
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
|
122
|
+
gap: 1rem;
|
|
123
|
+
margin-bottom: 1.5rem;
|
|
124
|
+
}
|
|
125
|
+
.card {
|
|
126
|
+
background: var(--surface);
|
|
127
|
+
border: 1px solid var(--border);
|
|
128
|
+
border-radius: 8px;
|
|
129
|
+
padding: 1.25rem;
|
|
130
|
+
}
|
|
131
|
+
.stat-label { font-size: 0.8rem; color: var(--text-muted); text-transform: uppercase; font-weight: 600; }
|
|
132
|
+
.stat-val { font-size: 1.75rem; font-weight: 700; color: var(--text); margin-top: 0.25rem; }
|
|
133
|
+
|
|
134
|
+
.search-bar {
|
|
135
|
+
display: flex;
|
|
136
|
+
gap: 0.75rem;
|
|
137
|
+
margin-bottom: 1rem;
|
|
138
|
+
}
|
|
139
|
+
input, select, textarea {
|
|
140
|
+
background: var(--bg);
|
|
141
|
+
border: 1px solid var(--border);
|
|
142
|
+
color: var(--text);
|
|
143
|
+
padding: 0.5rem 0.75rem;
|
|
144
|
+
border-radius: 6px;
|
|
145
|
+
font-family: inherit;
|
|
146
|
+
font-size: 0.9rem;
|
|
147
|
+
}
|
|
148
|
+
input:focus, select:focus, textarea:focus {
|
|
149
|
+
outline: none;
|
|
150
|
+
border-color: var(--accent);
|
|
151
|
+
}
|
|
152
|
+
.btn {
|
|
153
|
+
background: var(--primary);
|
|
154
|
+
color: #fff;
|
|
155
|
+
border: none;
|
|
156
|
+
padding: 0.5rem 1rem;
|
|
157
|
+
border-radius: 6px;
|
|
158
|
+
cursor: pointer;
|
|
159
|
+
font-weight: 600;
|
|
160
|
+
transition: background 0.15s;
|
|
161
|
+
}
|
|
162
|
+
.btn:hover { background: var(--primary-hover); }
|
|
163
|
+
.btn-secondary {
|
|
164
|
+
background: var(--surface-hover);
|
|
165
|
+
color: var(--text);
|
|
166
|
+
}
|
|
167
|
+
.btn-secondary:hover { background: var(--border); }
|
|
168
|
+
|
|
169
|
+
table {
|
|
170
|
+
width: 100%;
|
|
171
|
+
border-collapse: collapse;
|
|
172
|
+
margin-top: 1rem;
|
|
173
|
+
}
|
|
174
|
+
th, td {
|
|
175
|
+
text-align: left;
|
|
176
|
+
padding: 0.75rem 1rem;
|
|
177
|
+
border-bottom: 1px solid var(--border);
|
|
178
|
+
}
|
|
179
|
+
th { font-size: 0.8rem; color: var(--text-muted); text-transform: uppercase; font-weight: 600; background: rgba(0,0,0,0.1); }
|
|
180
|
+
tr:hover { background: var(--surface-hover); }
|
|
181
|
+
code, pre { font-family: var(--font-mono); }
|
|
182
|
+
pre {
|
|
183
|
+
background: var(--bg);
|
|
184
|
+
border: 1px solid var(--border);
|
|
185
|
+
border-radius: 6px;
|
|
186
|
+
padding: 1rem;
|
|
187
|
+
overflow-x: auto;
|
|
188
|
+
font-size: 0.85rem;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.method-pill {
|
|
192
|
+
font-family: var(--font-mono);
|
|
193
|
+
font-size: 0.75rem;
|
|
194
|
+
font-weight: 700;
|
|
195
|
+
padding: 0.2rem 0.4rem;
|
|
196
|
+
border-radius: 4px;
|
|
197
|
+
text-transform: uppercase;
|
|
198
|
+
display: inline-block;
|
|
199
|
+
}
|
|
200
|
+
.method-get { background: rgba(16, 185, 129, 0.2); color: #34d399; }
|
|
201
|
+
.method-post { background: rgba(99, 102, 241, 0.2); color: #818cf8; }
|
|
202
|
+
.method-put { background: rgba(245, 158, 11, 0.2); color: #fbbf24; }
|
|
203
|
+
.method-delete { background: rgba(239, 68, 68, 0.2); color: #f87171; }
|
|
204
|
+
.method-patch { background: rgba(236, 72, 153, 0.2); color: #f472b6; }
|
|
205
|
+
|
|
206
|
+
.untrusted-banner {
|
|
207
|
+
background: rgba(245, 158, 11, 0.1);
|
|
208
|
+
border-left: 4px solid var(--warning);
|
|
209
|
+
padding: 0.75rem 1rem;
|
|
210
|
+
border-radius: 4px;
|
|
211
|
+
font-size: 0.85rem;
|
|
212
|
+
color: #fde68a;
|
|
213
|
+
margin-bottom: 1.5rem;
|
|
214
|
+
}
|
|
215
|
+
</style>
|
|
216
|
+
</head>
|
|
217
|
+
<body>
|
|
218
|
+
<header>
|
|
219
|
+
<div class="brand">
|
|
220
|
+
<div class="brand-icon">DO</div>
|
|
221
|
+
<div>
|
|
222
|
+
<div class="brand-title">DocOrbit Dashboard</div>
|
|
223
|
+
<div style="font-size: 0.75rem; color: var(--text-muted);">Documentation Intelligence & Verification Layer</div>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
<div style="display: flex; gap: 0.5rem; align-items: center;">
|
|
227
|
+
<span class="badge badge-untrusted">Untrusted Docs Boundary</span>
|
|
228
|
+
<span id="conn-badge" class="badge badge-success">Connected</span>
|
|
229
|
+
</div>
|
|
230
|
+
</header>
|
|
231
|
+
|
|
232
|
+
<nav class="tabs">
|
|
233
|
+
<button class="tab-btn active" onclick="switchTab('overview')">Overview</button>
|
|
234
|
+
<button class="tab-btn" onclick="switchTab('apis')">API Explorer</button>
|
|
235
|
+
<button class="tab-btn" onclick="switchTab('pitfalls')">Pitfalls & Caveats</button>
|
|
236
|
+
<button class="tab-btn" onclick="switchTab('examples')">Code Examples</button>
|
|
237
|
+
<button class="tab-btn" onclick="switchTab('docsmap')">Docs Map</button>
|
|
238
|
+
<button class="tab-btn" onclick="switchTab('verifier')">Live Verifier</button>
|
|
239
|
+
<button class="tab-btn" onclick="switchTab('export')">Export Center</button>
|
|
240
|
+
</nav>
|
|
241
|
+
|
|
242
|
+
<main>
|
|
243
|
+
<div class="untrusted-banner">
|
|
244
|
+
<strong>Notice:</strong> All indexed external documentation is treated strictly as untrusted input (<code>untrusted: true</code>).
|
|
245
|
+
Extracted API schemas, caveats, and recipes are deterministically verified without autonomous code execution.
|
|
246
|
+
</div>
|
|
247
|
+
|
|
248
|
+
<!-- OVERVIEW TAB -->
|
|
249
|
+
<section id="tab-overview" class="tab-content active">
|
|
250
|
+
<div class="grid-stats">
|
|
251
|
+
<div class="card"><div class="stat-label">Sources</div><div id="stat-sources" class="stat-val">0</div></div>
|
|
252
|
+
<div class="card"><div class="stat-label">Pages</div><div id="stat-pages" class="stat-val">0</div></div>
|
|
253
|
+
<div class="card"><div class="stat-label">Chunks</div><div id="stat-chunks" class="stat-val">0</div></div>
|
|
254
|
+
<div class="card"><div class="stat-label">APIs Indexed</div><div id="stat-apis" class="stat-val">0</div></div>
|
|
255
|
+
<div class="card"><div class="stat-label">Pitfalls</div><div id="stat-pitfalls" class="stat-val">0</div></div>
|
|
256
|
+
<div class="card"><div class="stat-label">Examples</div><div id="stat-examples" class="stat-val">0</div></div>
|
|
257
|
+
</div>
|
|
258
|
+
|
|
259
|
+
<div class="card" style="margin-bottom: 1.5rem;">
|
|
260
|
+
<h3 style="margin-bottom: 0.75rem;">Indexed Sources & Snapshots</h3>
|
|
261
|
+
<div id="sources-list" style="font-size: 0.9rem; color: var(--text-muted);">Loading sources...</div>
|
|
262
|
+
</div>
|
|
263
|
+
|
|
264
|
+
<div class="card">
|
|
265
|
+
<h3 style="margin-bottom: 0.75rem;">Active Documentation Versions</h3>
|
|
266
|
+
<div id="versions-list" style="display: flex; gap: 0.5rem; flex-wrap: wrap;">Loading versions...</div>
|
|
267
|
+
</div>
|
|
268
|
+
</section>
|
|
269
|
+
|
|
270
|
+
<!-- APIS TAB -->
|
|
271
|
+
<section id="tab-apis" class="tab-content">
|
|
272
|
+
<div class="search-bar">
|
|
273
|
+
<input type="text" id="api-search" placeholder="Search API path, summary, or parameter..." style="flex: 1;" oninput="loadApis()">
|
|
274
|
+
<select id="api-method" onchange="loadApis()">
|
|
275
|
+
<option value="">All Methods</option>
|
|
276
|
+
<option value="get">GET</option>
|
|
277
|
+
<option value="post">POST</option>
|
|
278
|
+
<option value="put">PUT</option>
|
|
279
|
+
<option value="delete">DELETE</option>
|
|
280
|
+
<option value="patch">PATCH</option>
|
|
281
|
+
</select>
|
|
282
|
+
<input type="text" id="api-version" placeholder="Version (e.g. v14)" style="width: 140px;" oninput="loadApis()">
|
|
283
|
+
</div>
|
|
284
|
+
<div class="card">
|
|
285
|
+
<table id="apis-table">
|
|
286
|
+
<thead>
|
|
287
|
+
<tr><th>Method</th><th>Path</th><th>Summary</th><th>Required Parameters</th><th>Version</th></tr>
|
|
288
|
+
</thead>
|
|
289
|
+
<tbody id="apis-body"><tr><td colspan="5" style="text-align:center;">Loading APIs...</td></tr></tbody>
|
|
290
|
+
</table>
|
|
291
|
+
</div>
|
|
292
|
+
</section>
|
|
293
|
+
|
|
294
|
+
<!-- PITFALLS TAB -->
|
|
295
|
+
<section id="tab-pitfalls" class="tab-content">
|
|
296
|
+
<div class="search-bar">
|
|
297
|
+
<input type="text" id="pitfall-search" placeholder="Search warnings, caveats, breaking changes..." style="flex: 1;" oninput="loadPitfalls()">
|
|
298
|
+
<select id="pitfall-kind" onchange="loadPitfalls()">
|
|
299
|
+
<option value="">All Kinds</option>
|
|
300
|
+
<option value="deprecated">Deprecated</option>
|
|
301
|
+
<option value="removed">Removed</option>
|
|
302
|
+
<option value="breaking_change">Breaking Change</option>
|
|
303
|
+
<option value="server_only">Server Only</option>
|
|
304
|
+
<option value="rate_limit">Rate Limit</option>
|
|
305
|
+
<option value="security">Security</option>
|
|
306
|
+
</select>
|
|
307
|
+
</div>
|
|
308
|
+
<div id="pitfalls-list" style="display: flex; flex-direction: column; gap: 1rem;">Loading pitfalls...</div>
|
|
309
|
+
</section>
|
|
310
|
+
|
|
311
|
+
<!-- EXAMPLES TAB -->
|
|
312
|
+
<section id="tab-examples" class="tab-content">
|
|
313
|
+
<div class="search-bar">
|
|
314
|
+
<input type="text" id="example-search" placeholder="Search code examples..." style="flex: 1;" oninput="loadExamples()">
|
|
315
|
+
<input type="text" id="example-framework" placeholder="Framework (e.g. next, express)" oninput="loadExamples()">
|
|
316
|
+
</div>
|
|
317
|
+
<div id="examples-list" style="display: flex; flex-direction: column; gap: 1rem;">Loading code examples...</div>
|
|
318
|
+
</section>
|
|
319
|
+
|
|
320
|
+
<!-- DOCS MAP TAB -->
|
|
321
|
+
<section id="tab-docsmap" class="tab-content">
|
|
322
|
+
<div class="card">
|
|
323
|
+
<h3 style="margin-bottom: 0.5rem;">Documentation Hierarchy & Token Footprint</h3>
|
|
324
|
+
<p style="font-size: 0.85rem; color: var(--text-muted); margin-bottom: 1rem;">
|
|
325
|
+
Shows the full tree of indexed pages, chunk density, headings, and token allocation estimates.
|
|
326
|
+
</p>
|
|
327
|
+
<pre id="docsmap-content">Loading documentation map...</pre>
|
|
328
|
+
</div>
|
|
329
|
+
</section>
|
|
330
|
+
|
|
331
|
+
<!-- LIVE VERIFIER TAB -->
|
|
332
|
+
<section id="tab-verifier" class="tab-content">
|
|
333
|
+
<div class="card" style="margin-bottom: 1.5rem;">
|
|
334
|
+
<h3 style="margin-bottom: 0.5rem;">Interactive API Verification</h3>
|
|
335
|
+
<p style="font-size: 0.85rem; color: var(--text-muted); margin-bottom: 1rem;">
|
|
336
|
+
Test code against indexed OpenAPI schemas, parameters, and version caveats.
|
|
337
|
+
</p>
|
|
338
|
+
<div style="display: flex; gap: 1rem; margin-bottom: 1rem;">
|
|
339
|
+
<input type="text" id="verify-version" placeholder="Doc Version (e.g. v14, v15)" style="width: 200px;">
|
|
340
|
+
<button class="btn" onclick="runVerify()">Check Code</button>
|
|
341
|
+
</div>
|
|
342
|
+
<textarea id="verify-code" rows="8" style="width: 100%; font-family: var(--font-mono); font-size: 0.85rem;" placeholder="// Paste JavaScript, TypeScript, Python, or cURL code to verify fetch('/v1/webhook_endpoints', { method: 'POST', body: JSON.stringify({ url: 'https://example.com' }) });"></textarea>
|
|
343
|
+
</div>
|
|
344
|
+
|
|
345
|
+
<div id="verify-results" class="card" style="display: none;">
|
|
346
|
+
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
|
|
347
|
+
<h3>Verification Findings</h3>
|
|
348
|
+
<span id="verify-verdict" class="badge">UNKNOWN</span>
|
|
349
|
+
</div>
|
|
350
|
+
<div id="verify-summary" style="margin-bottom: 1rem; font-size: 0.9rem;"></div>
|
|
351
|
+
<table id="verify-findings-table">
|
|
352
|
+
<thead>
|
|
353
|
+
<tr><th>Severity</th><th>Rule</th><th>Line</th><th>Message</th><th>Expected</th></tr>
|
|
354
|
+
</thead>
|
|
355
|
+
<tbody id="verify-findings-body"></tbody>
|
|
356
|
+
</table>
|
|
357
|
+
</div>
|
|
358
|
+
</section>
|
|
359
|
+
|
|
360
|
+
<!-- EXPORT CENTER TAB -->
|
|
361
|
+
<section id="tab-export" class="tab-content">
|
|
362
|
+
<div class="card" style="margin-bottom: 1.5rem;">
|
|
363
|
+
<h3 style="margin-bottom: 0.5rem;">Deterministic Agent File Exports</h3>
|
|
364
|
+
<p style="font-size: 0.85rem; color: var(--text-muted); margin-bottom: 1rem;">
|
|
365
|
+
Generate reproducible, version-aware agent configuration and guidance files.
|
|
366
|
+
</p>
|
|
367
|
+
<div style="display: flex; gap: 0.5rem; flex-wrap: wrap; margin-bottom: 1rem;">
|
|
368
|
+
<button class="btn btn-secondary" onclick="loadExport('agents.md')">Preview AGENTS.md</button>
|
|
369
|
+
<button class="btn btn-secondary" onclick="loadExport('claude.md')">Preview CLAUDE.md</button>
|
|
370
|
+
<button class="btn btn-secondary" onclick="loadExport('skill.md')">Preview skill.md</button>
|
|
371
|
+
<button class="btn btn-secondary" onclick="loadExport('llms.txt')">Preview llms.txt</button>
|
|
372
|
+
<button class="btn btn-secondary" onclick="loadExport('docs-map.md')">Preview docs-map.md</button>
|
|
373
|
+
</div>
|
|
374
|
+
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem;">
|
|
375
|
+
<strong id="export-filename">AGENTS.md</strong>
|
|
376
|
+
<button class="btn" style="padding: 0.3rem 0.75rem; font-size: 0.8rem;" onclick="copyExportContent()">Copy to Clipboard</button>
|
|
377
|
+
</div>
|
|
378
|
+
<pre id="export-preview" style="max-height: 500px;">Click a button above to generate export preview...</pre>
|
|
379
|
+
</div>
|
|
380
|
+
</section>
|
|
381
|
+
</main>
|
|
382
|
+
|
|
383
|
+
<script>
|
|
384
|
+
function switchTab(tabId) {
|
|
385
|
+
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
|
|
386
|
+
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
|
|
387
|
+
event.target.classList.add('active');
|
|
388
|
+
const target = document.getElementById('tab-' + tabId);
|
|
389
|
+
if (target) target.classList.add('active');
|
|
390
|
+
|
|
391
|
+
if (tabId === 'overview') loadStats();
|
|
392
|
+
if (tabId === 'apis') loadApis();
|
|
393
|
+
if (tabId === 'pitfalls') loadPitfalls();
|
|
394
|
+
if (tabId === 'examples') loadExamples();
|
|
395
|
+
if (tabId === 'docsmap') loadDocsMap();
|
|
396
|
+
if (tabId === 'export') loadExport('agents.md');
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
async function loadStats() {
|
|
400
|
+
try {
|
|
401
|
+
const res = await fetch('/api/stats');
|
|
402
|
+
const data = await res.json();
|
|
403
|
+
document.getElementById('stat-sources').textContent = data.totalSources || 0;
|
|
404
|
+
document.getElementById('stat-pages').textContent = data.totalPages || 0;
|
|
405
|
+
document.getElementById('stat-chunks').textContent = data.totalChunks || 0;
|
|
406
|
+
document.getElementById('stat-apis').textContent = data.totalApis || 0;
|
|
407
|
+
document.getElementById('stat-pitfalls').textContent = data.totalPitfalls || 0;
|
|
408
|
+
document.getElementById('stat-examples').textContent = data.totalExamples || 0;
|
|
409
|
+
|
|
410
|
+
const vList = document.getElementById('versions-list');
|
|
411
|
+
if (data.activeVersions && data.activeVersions.length > 0) {
|
|
412
|
+
vList.innerHTML = data.activeVersions.map(v => '<span class="badge badge-primary">' + v + '</span>').join('');
|
|
413
|
+
} else {
|
|
414
|
+
vList.innerHTML = '<em>No explicit version tags indexed.</em>';
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
const sRes = await fetch('/api/sources');
|
|
418
|
+
const sources = await sRes.json();
|
|
419
|
+
const sList = document.getElementById('sources-list');
|
|
420
|
+
if (sources && sources.length > 0) {
|
|
421
|
+
sList.innerHTML = '<ul>' + sources.map(s => '<li><strong>' + s.url + '</strong> (' + s.authority + ')</li>').join('') + '</ul>';
|
|
422
|
+
} else {
|
|
423
|
+
sList.innerHTML = '<em>No sources indexed. Run <code>docorbit add <url></code> to index documentation.</em>';
|
|
424
|
+
}
|
|
425
|
+
} catch (err) {
|
|
426
|
+
document.getElementById('conn-badge').textContent = 'Disconnected';
|
|
427
|
+
document.getElementById('conn-badge').className = 'badge badge-danger';
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
async function loadApis() {
|
|
432
|
+
const q = document.getElementById('api-search').value;
|
|
433
|
+
const method = document.getElementById('api-method').value;
|
|
434
|
+
const docVersion = document.getElementById('api-version').value;
|
|
435
|
+
const url = new URL('/api/apis', window.location.origin);
|
|
436
|
+
if (q) url.searchParams.set('q', q);
|
|
437
|
+
if (method) url.searchParams.set('method', method);
|
|
438
|
+
if (docVersion) url.searchParams.set('docVersion', docVersion);
|
|
439
|
+
|
|
440
|
+
const res = await fetch(url);
|
|
441
|
+
const apis = await res.json();
|
|
442
|
+
const body = document.getElementById('apis-body');
|
|
443
|
+
if (!apis || apis.length === 0) {
|
|
444
|
+
body.innerHTML = '<tr><td colspan="5" style="text-align:center;">No matching APIs found.</td></tr>';
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
body.innerHTML = apis.map(ep => {
|
|
449
|
+
const mClass = 'method-' + ep.method.toLowerCase();
|
|
450
|
+
const req = (ep.parameters || []).filter(p => p.required).map(p => '<code>' + p.name + '</code>').join(', ') || 'none';
|
|
451
|
+
const dep = ep.deprecated ? ' <span class="badge badge-danger">deprecated</span>' : '';
|
|
452
|
+
return '<tr>' +
|
|
453
|
+
'<td><span class="method-pill ' + mClass + '">' + ep.method + '</span>' + dep + '</td>' +
|
|
454
|
+
'<td><code>' + ep.path + '</code></td>' +
|
|
455
|
+
'<td>' + (ep.summary || '') + '</td>' +
|
|
456
|
+
'<td>' + req + '</td>' +
|
|
457
|
+
'<td>' + (ep.docVersion || '-') + '</td>' +
|
|
458
|
+
'</tr>';
|
|
459
|
+
}).join('');
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
async function loadPitfalls() {
|
|
463
|
+
const q = document.getElementById('pitfall-search').value;
|
|
464
|
+
const kind = document.getElementById('pitfall-kind').value;
|
|
465
|
+
const url = new URL('/api/pitfalls', window.location.origin);
|
|
466
|
+
if (q) url.searchParams.set('q', q);
|
|
467
|
+
if (kind) url.searchParams.set('kind', kind);
|
|
468
|
+
|
|
469
|
+
const res = await fetch(url);
|
|
470
|
+
const pitfalls = await res.json();
|
|
471
|
+
const container = document.getElementById('pitfalls-list');
|
|
472
|
+
if (!pitfalls || pitfalls.length === 0) {
|
|
473
|
+
container.innerHTML = '<div class="card">No pitfalls found.</div>';
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
container.innerHTML = pitfalls.map(pf => {
|
|
478
|
+
const sevClass = pf.severity === 'error' ? 'badge-danger' : (pf.severity === 'info' ? 'badge-primary' : 'badge-warning');
|
|
479
|
+
return '<div class="card">' +
|
|
480
|
+
'<div style="display:flex; justify-content:space-between; margin-bottom:0.5rem;">' +
|
|
481
|
+
'<h4>' + pf.title + '</h4>' +
|
|
482
|
+
'<div><span class="badge ' + sevClass + '">' + (pf.severity || 'warning') + '</span> <span class="badge badge-primary">' + pf.kind + '</span></div>' +
|
|
483
|
+
'</div>' +
|
|
484
|
+
'<p style="font-size:0.9rem; margin-bottom:0.5rem;">' + pf.message + '</p>' +
|
|
485
|
+
(pf.mitigation ? '<p style="font-size:0.85rem; color:var(--accent);"><strong>Fix:</strong> ' + pf.mitigation + '</p>' : '') +
|
|
486
|
+
'</div>';
|
|
487
|
+
}).join('');
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
async function loadExamples() {
|
|
491
|
+
const q = document.getElementById('example-search').value;
|
|
492
|
+
const fw = document.getElementById('example-framework').value;
|
|
493
|
+
const url = new URL('/api/examples', window.location.origin);
|
|
494
|
+
if (q) url.searchParams.set('q', q);
|
|
495
|
+
if (fw) url.searchParams.set('framework', fw);
|
|
496
|
+
|
|
497
|
+
const res = await fetch(url);
|
|
498
|
+
const examples = await res.json();
|
|
499
|
+
const container = document.getElementById('examples-list');
|
|
500
|
+
if (!examples || examples.length === 0) {
|
|
501
|
+
container.innerHTML = '<div class="card">No code examples found.</div>';
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
container.innerHTML = examples.map(ex => {
|
|
506
|
+
return '<div class="card">' +
|
|
507
|
+
'<div style="display:flex; justify-content:space-between; margin-bottom:0.5rem;">' +
|
|
508
|
+
'<h4>' + (ex.task || ex.title || 'Example') + '</h4>' +
|
|
509
|
+
'<span class="badge badge-primary">' + (ex.framework || ex.language || 'code') + '</span>' +
|
|
510
|
+
'</div>' +
|
|
511
|
+
'<pre><code>' + (ex.code || ex.rawSnippet || '').trim() + '</code></pre>' +
|
|
512
|
+
'</div>';
|
|
513
|
+
}).join('');
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
async function loadDocsMap() {
|
|
517
|
+
const res = await fetch('/api/docs-map');
|
|
518
|
+
const data = await res.json();
|
|
519
|
+
document.getElementById('docsmap-content').textContent = data.markdownTree || 'No map available.';
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
async function runVerify() {
|
|
523
|
+
const code = document.getElementById('verify-code').value;
|
|
524
|
+
const docVersion = document.getElementById('verify-version').value;
|
|
525
|
+
if (!code.trim()) return;
|
|
526
|
+
|
|
527
|
+
const res = await fetch('/api/verify', {
|
|
528
|
+
method: 'POST',
|
|
529
|
+
headers: { 'Content-Type': 'application/json' },
|
|
530
|
+
body: JSON.stringify({ code, version: docVersion || undefined })
|
|
531
|
+
});
|
|
532
|
+
const data = await res.json();
|
|
533
|
+
const result = data.result || data;
|
|
534
|
+
|
|
535
|
+
const resultsDiv = document.getElementById('verify-results');
|
|
536
|
+
resultsDiv.style.display = 'block';
|
|
537
|
+
|
|
538
|
+
const vBadge = document.getElementById('verify-verdict');
|
|
539
|
+
vBadge.textContent = result.verdict ? result.verdict.toUpperCase() : 'UNKNOWN';
|
|
540
|
+
vBadge.className = 'badge ' + (
|
|
541
|
+
result.verdict === 'verified' ? 'badge-success' :
|
|
542
|
+
result.verdict === 'warning' ? 'badge-warning' :
|
|
543
|
+
result.verdict === 'mismatch' ? 'badge-danger' : 'badge-primary'
|
|
544
|
+
);
|
|
545
|
+
|
|
546
|
+
document.getElementById('verify-summary').textContent = result.summary || '';
|
|
547
|
+
|
|
548
|
+
const tbody = document.getElementById('verify-findings-body');
|
|
549
|
+
if (!result.findings || result.findings.length === 0) {
|
|
550
|
+
tbody.innerHTML = '<tr><td colspan="5" style="text-align:center;">No issues detected. Code is verified against indexed schemas.</td></tr>';
|
|
551
|
+
} else {
|
|
552
|
+
tbody.innerHTML = result.findings.map(f => {
|
|
553
|
+
const sevClass = f.severity === 'error' ? 'badge-danger' : (f.severity === 'info' ? 'badge-primary' : 'badge-warning');
|
|
554
|
+
return '<tr>' +
|
|
555
|
+
'<td><span class="badge ' + sevClass + '">' + f.severity + '</span></td>' +
|
|
556
|
+
'<td>' + f.rule + '</td>' +
|
|
557
|
+
'<td>' + (f.location?.line || '-') + '</td>' +
|
|
558
|
+
'<td>' + f.message + '</td>' +
|
|
559
|
+
'<td>' + (f.expected || '-') + '</td>' +
|
|
560
|
+
'</tr>';
|
|
561
|
+
}).join('');
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
async function loadExport(format) {
|
|
566
|
+
document.getElementById('export-filename').textContent = format;
|
|
567
|
+
const preview = document.getElementById('export-preview');
|
|
568
|
+
preview.textContent = 'Generating export...';
|
|
569
|
+
|
|
570
|
+
const res = await fetch('/api/export?format=' + encodeURIComponent(format));
|
|
571
|
+
const data = await res.json();
|
|
572
|
+
preview.textContent = data.content || '';
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
function copyExportContent() {
|
|
576
|
+
const text = document.getElementById('export-preview').textContent;
|
|
577
|
+
navigator.clipboard.writeText(text);
|
|
578
|
+
alert('Copied ' + document.getElementById('export-filename').textContent + ' to clipboard!');
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
// Initial load
|
|
582
|
+
loadStats();
|
|
583
|
+
</script>
|
|
584
|
+
</body>
|
|
585
|
+
</html>`;
|
|
586
|
+
}
|