@polycode-projects/the-mechanical-code-talker 2.10.3 → 2.11.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/README.md +68 -12
- package/bin/tmct.mjs +5 -2
- package/corpus/sprites/src/sprite-facts.jsonl +18 -0
- package/corpus/worlds/manifest.json +5 -5
- package/corpus/worlds/shards/ashcombe-hall.jsonl.gz +0 -0
- package/corpus/worlds/src/ashcombe-hall.jsonl +27 -0
- package/data/sprites/book-icon.toml +12 -0
- package/data/sprites/cellar-icon.toml +12 -0
- package/data/sprites/drawing-room-icon.toml +13 -0
- package/data/sprites/garden-icon.toml +12 -0
- package/data/sprites/kitchen-icon.toml +13 -0
- package/data/sprites/library-icon.toml +12 -0
- package/data/sprites/pan-icon.toml +11 -0
- package/data/sprites/study-icon.toml +12 -0
- package/package.json +7 -2
- package/src/adapters/corpus/wikipedia-live.mjs +182 -26
- package/src/adapters/corpus/worlds-pack.mjs +8 -2
- package/src/adapters/memory/core.mjs +8 -1
- package/src/adapters/toml-config.mjs +6 -0
- package/src/domain/cli-verbs.mjs +2 -0
- package/src/domain/memory/trust.mjs +32 -2
- package/src/domain/sense-split.mjs +203 -0
- package/src/domain/worlds-pack.mjs +50 -0
- package/src/services/adventure-autoplay.mjs +5 -2
- package/src/services/adventure-viz.mjs +301 -33
- package/src/services/adventure.mjs +162 -14
- package/src/services/chat-page-viz.mjs +341 -197
- package/src/services/chat-session.mjs +24 -9
- package/src/services/chat.mjs +580 -47
- package/src/services/code-explorer-viz.mjs +198 -76
- package/src/services/extract-facts.mjs +384 -82
- package/src/services/fold.mjs +1 -1
- package/src/services/ingest-viz.mjs +637 -0
- package/src/services/ledger-viz.mjs +209 -0
- package/src/services/memory-panel-viz.mjs +159 -0
- package/src/services/research.mjs +266 -0
- package/src/services/sentences.mjs +19 -0
- package/src/services/session-log-format.mjs +64 -0
- package/src/services/sessions.mjs +56 -22
- package/src/services/spider-fly-turn.mjs +54 -1
- package/src/services/spider-fly-viz.mjs +41 -23
- package/src/surfaces/web/adventure-browser-entry.mjs +9 -5
- package/src/surfaces/web/chat-browser-entry.mjs +32 -11
- package/src/surfaces/web/code-explorer-browser-entry.mjs +27 -11
- package/src/surfaces/web/ingest-browser-entry.mjs +208 -0
- package/src/surfaces/web/ledger-browser-entry.mjs +24 -5
- package/src/surfaces/web/memory-ask-browser.bundle.js +134 -125
- package/src/surfaces/web/memory-stats.mjs +53 -0
- package/src/tools/definitions.mjs +14 -0
- package/src/tools/handlers/index.mjs +2 -0
- package/src/tools/handlers/tmct-ingest.mjs +43 -0
- package/src/tools/server.mjs +5 -2
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
// code-explorer-viz.mjs — the code
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
1
|
+
// code-explorer-viz.mjs — the code explorer as a full-viewport IDE shell:
|
|
2
|
+
// a title bar (graph source, Open graph…/Open repo…), an explorer sidebar
|
|
3
|
+
// reading each import/call/contains edge back as a plain sentence, a chat
|
|
4
|
+
// centre over the same graph with a rail of suggested questions, and a status
|
|
5
|
+
// bar carrying the graph's own counts. The chat session seeds BOTH the loaded
|
|
6
|
+
// code graph and chat.html's general-knowledge bands (./chat-seed.json,
|
|
7
|
+
// fetched lazily at runtime), so one conversation answers "what is a queue"
|
|
8
|
+
// and "what imports src/core/model.mjs" alike — and degrades to graph-only
|
|
9
|
+
// when the seed asset is unavailable.
|
|
7
10
|
//
|
|
8
|
-
// The
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
+
// The derivations are pure so the shell, the packaging scripts, and the unit
|
|
12
|
+
// tests all share one code path; renderCodeExplorerHtml builds one
|
|
13
|
+
// self-contained document that both packagers ship unchanged — the site build
|
|
14
|
+
// (scripts/build-demo-site.mjs) and the Electron desktop shell
|
|
15
|
+
// (scripts/build-electron-app.mjs). Panels are plain sections inside the
|
|
16
|
+
// sidebar/centre grid, so a later panel is one more <section class="panel">,
|
|
17
|
+
// not a re-architecture.
|
|
11
18
|
|
|
12
19
|
import { THEME_TOKENS_CSS, SERIF_STACK, MONO_STACK, escapeHtml, embedJson, embedScriptText } from "./viz-theme.mjs";
|
|
13
20
|
import { generateCodeHints } from "../domain/code-explorer-hints.mjs";
|
|
@@ -31,6 +38,17 @@ export function edgePhrase(kind) {
|
|
|
31
38
|
return EDGE_PHRASE.get(String(kind || "")) || String(kind || "").replace(/([a-z0-9])([A-Z])/g, "$1 $2").toLowerCase();
|
|
32
39
|
}
|
|
33
40
|
|
|
41
|
+
// Both packagers (build-electron-app.mjs, build-demo-site.mjs) place
|
|
42
|
+
// vendor/wink.js one level below the page they render, so the same loader
|
|
43
|
+
// script inlines into renderCodeExplorerHtml's `winkLoaderInline` slot for
|
|
44
|
+
// either channel.
|
|
45
|
+
export const VENDOR_WINK_LOADER_JS = `window.__WINK_LOADER__ = async function () {
|
|
46
|
+
var m = await import("./vendor/wink.js");
|
|
47
|
+
return { winkNLP: m.winkNLP, model: m.model };
|
|
48
|
+
};`;
|
|
49
|
+
|
|
50
|
+
export const DESKTOP_APP_URL = "https://gitlab.com/polycode-projects/the-mechanical-code-talker#the-code-explorer-desktop";
|
|
51
|
+
|
|
34
52
|
const LEDGER_ROW_LIMIT_DEFAULT = 4000;
|
|
35
53
|
|
|
36
54
|
/** Pure derivation over an entities payload (individuals + objectProperties).
|
|
@@ -110,6 +128,7 @@ const CLIENT_JS = String.raw`
|
|
|
110
128
|
input: document.getElementById("chat-input"),
|
|
111
129
|
dockNote: document.getElementById("dock-note"),
|
|
112
130
|
source: document.getElementById("source-name"),
|
|
131
|
+
seedStatus: document.getElementById("seed-status"),
|
|
113
132
|
};
|
|
114
133
|
var session = null;
|
|
115
134
|
|
|
@@ -163,7 +182,7 @@ const CLIENT_JS = String.raw`
|
|
|
163
182
|
renderHints(data);
|
|
164
183
|
}
|
|
165
184
|
|
|
166
|
-
function
|
|
185
|
+
function appendTurn(role, text) {
|
|
167
186
|
var div = document.createElement("div");
|
|
168
187
|
div.className = "turn turn-" + role;
|
|
169
188
|
div.innerHTML = '<span class="who">' + (role === "you" ? "you" : "tmct") + '</span><span class="said">' + esc(text) + '</span>';
|
|
@@ -171,23 +190,93 @@ const CLIENT_JS = String.raw`
|
|
|
171
190
|
els.log.scrollTop = els.log.scrollHeight;
|
|
172
191
|
}
|
|
173
192
|
|
|
193
|
+
function appendNote(text) {
|
|
194
|
+
var div = document.createElement("div");
|
|
195
|
+
div.className = "turn turn-note";
|
|
196
|
+
div.textContent = text;
|
|
197
|
+
els.log.appendChild(div);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ---- the general-knowledge seed --------------------------------------
|
|
201
|
+
// The same chat-seed.json chat.html boots from, loaded lazily so the shell
|
|
202
|
+
// paints instantly: same-origin fetch on the site, the preload bridge's
|
|
203
|
+
// readSeed under the desktop shell (a file:// page cannot fetch). The
|
|
204
|
+
// status bar narrates the load; a missing or failing seed leaves the chat
|
|
205
|
+
// graph-only and says so, never broken.
|
|
206
|
+
var seedState = { status: api ? "loading" : "absent", payload: null, facts: 0 };
|
|
207
|
+
function seedNote(text) { if (els.seedStatus) els.seedStatus.textContent = text; }
|
|
208
|
+
function mbText(n) { return (n / 1048576).toFixed(1); }
|
|
209
|
+
|
|
210
|
+
async function fetchTextWithProgress(url, onProgress) {
|
|
211
|
+
var res = await fetch(url);
|
|
212
|
+
if (!res.ok) throw new Error("HTTP " + res.status);
|
|
213
|
+
var total = Number(res.headers.get("content-length")) || 0;
|
|
214
|
+
if (!res.body || !res.body.getReader) return res.text();
|
|
215
|
+
var reader = res.body.getReader();
|
|
216
|
+
var chunks = [];
|
|
217
|
+
var loaded = 0;
|
|
218
|
+
for (;;) {
|
|
219
|
+
var step = await reader.read();
|
|
220
|
+
if (step.done) break;
|
|
221
|
+
chunks.push(step.value);
|
|
222
|
+
loaded += step.value.byteLength;
|
|
223
|
+
onProgress(loaded, total);
|
|
224
|
+
}
|
|
225
|
+
return new Blob(chunks).text();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async function loadSeed() {
|
|
229
|
+
try {
|
|
230
|
+
var text = null;
|
|
231
|
+
if (window.tmctDesktop && typeof window.tmctDesktop.readSeed === "function") {
|
|
232
|
+
seedNote("loading general knowledge…");
|
|
233
|
+
text = await window.tmctDesktop.readSeed();
|
|
234
|
+
} else {
|
|
235
|
+
text = await fetchTextWithProgress("./chat-seed.json", function (loaded, total) {
|
|
236
|
+
seedNote("loading general knowledge… " + mbText(loaded) + (total ? " of " + mbText(total) : "") + " MB");
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
if (text) {
|
|
240
|
+
seedState.payload = JSON.parse(text);
|
|
241
|
+
seedState.facts = (seedState.payload.individuals || []).filter(function (i) { return i.class === "Fact"; }).length;
|
|
242
|
+
seedState.status = "ready";
|
|
243
|
+
seedNote("general knowledge: " + seedState.facts + " facts");
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
} catch (e) {
|
|
247
|
+
console.warn("tmct code explorer: chat-seed unavailable, continuing graph-only", e);
|
|
248
|
+
}
|
|
249
|
+
seedState.status = "absent";
|
|
250
|
+
seedNote("graph-only — general knowledge unavailable");
|
|
251
|
+
}
|
|
252
|
+
var seedPromise = api ? loadSeed() : Promise.resolve();
|
|
253
|
+
|
|
254
|
+
function cloneSeed() {
|
|
255
|
+
if (!seedState.payload) return null;
|
|
256
|
+
try { return structuredClone(seedState.payload); } catch (e) { return JSON.parse(JSON.stringify(seedState.payload)); }
|
|
257
|
+
}
|
|
258
|
+
|
|
174
259
|
async function ensureSession() {
|
|
175
260
|
if (session || !api || !api.createCodeExplorerSession) return session;
|
|
176
|
-
var winkLoaded = true;
|
|
177
261
|
if (api.registerWinkModel && window.__WINK_LOADER__) {
|
|
178
262
|
try { var mod = await window.__WINK_LOADER__(); api.registerWinkModel(function () { return mod; }); }
|
|
179
|
-
catch (e) {
|
|
263
|
+
catch (e) { /* the lemma/POS tier is optional */ }
|
|
180
264
|
}
|
|
181
|
-
|
|
265
|
+
await seedPromise;
|
|
266
|
+
session = api.createCodeExplorerSession({
|
|
267
|
+
graphPayload: DATA.payload,
|
|
268
|
+
seedPayload: cloneSeed(),
|
|
269
|
+
vocabSeeded: seedState.status === "ready",
|
|
270
|
+
});
|
|
182
271
|
return session;
|
|
183
272
|
}
|
|
184
273
|
|
|
185
274
|
async function ask(q) {
|
|
186
|
-
|
|
275
|
+
appendTurn("you", q);
|
|
187
276
|
var s = await ensureSession();
|
|
188
|
-
if (!s) {
|
|
277
|
+
if (!s) { appendTurn("tmct", "the live chat is not loaded on this page."); return; }
|
|
189
278
|
var res = await s.turn(q);
|
|
190
|
-
|
|
279
|
+
appendTurn("tmct", res.answer);
|
|
191
280
|
}
|
|
192
281
|
|
|
193
282
|
// Delegate term + hint clicks.
|
|
@@ -208,7 +297,8 @@ const CLIENT_JS = String.raw`
|
|
|
208
297
|
});
|
|
209
298
|
}
|
|
210
299
|
|
|
211
|
-
// Desktop pickers, present only under the Electron shell.
|
|
300
|
+
// Desktop pickers, present only under the Electron shell. A swapped graph
|
|
301
|
+
// starts a fresh session; the general-knowledge seed carries over.
|
|
212
302
|
function wirePicker(id, method, updateSource) {
|
|
213
303
|
var btn = document.getElementById(id);
|
|
214
304
|
if (!btn) return;
|
|
@@ -234,8 +324,11 @@ const CLIENT_JS = String.raw`
|
|
|
234
324
|
wirePicker("open-repo", "openRepo", true);
|
|
235
325
|
|
|
236
326
|
if (!api) {
|
|
237
|
-
if (els.dockNote) els.dockNote.textContent = "static view — the live chat
|
|
327
|
+
if (els.dockNote) els.dockNote.textContent = "static view — the live chat is unavailable on this page.";
|
|
238
328
|
if (els.input) els.input.disabled = true;
|
|
329
|
+
seedNote("static view");
|
|
330
|
+
} else {
|
|
331
|
+
appendNote("Ask about this code graph — or anything its general knowledge covers, like “what is a queue”.");
|
|
239
332
|
}
|
|
240
333
|
|
|
241
334
|
mountView(DATA);
|
|
@@ -243,16 +336,17 @@ const CLIENT_JS = String.raw`
|
|
|
243
336
|
`;
|
|
244
337
|
|
|
245
338
|
/**
|
|
246
|
-
* One self-contained HTML document
|
|
247
|
-
* computeCodeExplorerData's output. `bundleInline` inlines the
|
|
339
|
+
* One self-contained HTML document: the full-viewport IDE shell over
|
|
340
|
+
* computeCodeExplorerData's output. `bundleInline` inlines the chat engine
|
|
248
341
|
* (for a single-file page / a data: URL); otherwise `bundleAvailable` links
|
|
249
342
|
* `./code-explorer.bundle.js`. `winkLoaderInline` optionally inlines a wink
|
|
250
|
-
* model loader as `window.__WINK_LOADER__`.
|
|
343
|
+
* model loader as `window.__WINK_LOADER__`. `showDesktopLink` adds a line
|
|
344
|
+
* pointing at the desktop app's README section — the desktop shell itself
|
|
345
|
+
* renders this page too and passes `false`, since it has nothing to point at.
|
|
251
346
|
*/
|
|
252
|
-
export function renderCodeExplorerHtml(data, { bundleInline = "", bundleAvailable = false, winkLoaderInline = "", sourceName = "demo code graph" } = {}) {
|
|
347
|
+
export function renderCodeExplorerHtml(data, { bundleInline = "", bundleAvailable = false, winkLoaderInline = "", sourceName = "demo code graph", showDesktopLink = false } = {}) {
|
|
253
348
|
const payloadJson = embedJson(data.payload);
|
|
254
349
|
const dataJson = embedJson({ ledger: data.ledger, hints: data.hints, focus: data.focus, meta: data.meta });
|
|
255
|
-
const title = escapeHtml(data.meta?.title || "code explorer");
|
|
256
350
|
|
|
257
351
|
return `<!doctype html>
|
|
258
352
|
<html lang="en">
|
|
@@ -263,74 +357,102 @@ export function renderCodeExplorerHtml(data, { bundleInline = "", bundleAvailabl
|
|
|
263
357
|
<style>
|
|
264
358
|
${THEME_TOKENS_CSS}
|
|
265
359
|
* { box-sizing: border-box; }
|
|
266
|
-
body {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
360
|
+
html, body { height: 100%; }
|
|
361
|
+
body { margin: 0; overflow: hidden; background: var(--bg); color: var(--ink); font-family: ${SERIF_STACK}; }
|
|
362
|
+
.shell { height: 100%; display: grid; grid-template-rows: auto minmax(0, 1fr) auto; }
|
|
363
|
+
|
|
364
|
+
.titlebar { display: flex; align-items: center; gap: 0.7rem; flex-wrap: wrap; padding: 0.5rem 0.9rem; background: var(--card); border-bottom: 1px solid var(--line); box-shadow: inset 0 -2px 0 var(--entail-soft); }
|
|
365
|
+
.titlebar .mark { width: 15px; height: 15px; color: var(--entail); flex: none; }
|
|
366
|
+
.titlebar h1 { font-size: 0.95rem; margin: 0; font-weight: 600; letter-spacing: 0.02em; }
|
|
367
|
+
.titlebar .sub { color: var(--muted); font-size: 0.76rem; font-family: ${MONO_STACK}; }
|
|
368
|
+
.titlebar .sub a { color: var(--corpus); }
|
|
369
|
+
.titlebar .pickers { margin-left: auto; display: flex; gap: 0.45rem; }
|
|
271
370
|
button { font: inherit; cursor: pointer; }
|
|
272
371
|
button:disabled { cursor: default; opacity: 0.5; }
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
.
|
|
278
|
-
.
|
|
279
|
-
|
|
372
|
+
button:focus-visible, input:focus-visible { outline: 2px solid var(--entail); outline-offset: 1px; }
|
|
373
|
+
.pickers button { background: var(--bg); color: var(--ink); border: 1px solid var(--line); border-radius: 4px; padding: 0.3rem 0.65rem; font-size: 0.8rem; }
|
|
374
|
+
.pickers button:hover { border-color: var(--entail); }
|
|
375
|
+
|
|
376
|
+
.workbench { display: grid; grid-template-columns: minmax(230px, 320px) minmax(0, 1fr); min-height: 0; }
|
|
377
|
+
.sidebar { display: flex; flex-direction: column; min-height: 0; border-right: 1px solid var(--line); }
|
|
378
|
+
.panel { display: flex; flex-direction: column; min-height: 0; flex: 1; }
|
|
379
|
+
.panel-head { margin: 0; padding: 0.45rem 0.9rem; flex: none; display: flex; align-items: baseline; gap: 0.45rem; font-family: ${MONO_STACK}; font-size: 0.66rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.09em; color: var(--muted); border-bottom: 1px solid var(--line); }
|
|
380
|
+
.panel-body { flex: 1; min-height: 0; overflow-y: auto; padding: 0.5rem 0.9rem 1rem; }
|
|
381
|
+
.focus-line { font-family: ${MONO_STACK}; font-size: 0.72rem; color: var(--corpus); text-transform: none; letter-spacing: 0; overflow-wrap: anywhere; }
|
|
280
382
|
ul.rows { list-style: none; margin: 0; padding: 0; }
|
|
281
|
-
.row { padding: 0.
|
|
383
|
+
.row { padding: 0.26rem 0.35rem; border-radius: 4px; font-size: 0.88rem; line-height: 1.45; }
|
|
282
384
|
.row-focus { background: var(--corpus-soft); }
|
|
283
385
|
.row.muted, .muted { color: var(--muted); }
|
|
284
|
-
.term { background: none; border: none; padding: 0; color: var(--corpus); font-family: ${MONO_STACK}; font-size: 0.
|
|
386
|
+
.term { background: none; border: none; padding: 0; color: var(--corpus); font-family: ${MONO_STACK}; font-size: 0.8rem; text-align: left; text-decoration: underline; text-decoration-color: var(--line); overflow-wrap: anywhere; }
|
|
285
387
|
.term:hover { text-decoration-color: var(--corpus); }
|
|
286
388
|
.verb { color: var(--muted); }
|
|
287
|
-
|
|
288
|
-
.
|
|
289
|
-
.
|
|
290
|
-
.
|
|
291
|
-
|
|
292
|
-
.turn { font-
|
|
293
|
-
.turn
|
|
294
|
-
.turn-
|
|
295
|
-
.turn-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
.
|
|
389
|
+
|
|
390
|
+
.editor { display: flex; flex-direction: column; min-height: 0; background: var(--card); }
|
|
391
|
+
#chat-log { flex: 1; min-height: 0; overflow-y: auto; padding: 0.9rem 1.1rem; display: flex; flex-direction: column; gap: 0.7rem; }
|
|
392
|
+
.turn { max-width: 46rem; font-size: 0.95rem; line-height: 1.5; }
|
|
393
|
+
.turn .who { display: block; font-family: ${MONO_STACK}; font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.07em; color: var(--muted); margin-bottom: 0.15rem; }
|
|
394
|
+
.turn-you .said { font-family: ${MONO_STACK}; font-size: 0.84rem; }
|
|
395
|
+
.turn-tmct { border-left: 2px solid var(--entail); padding-left: 0.7rem; }
|
|
396
|
+
.turn-tmct .said { white-space: pre-wrap; }
|
|
397
|
+
.turn-note { color: var(--muted); font-style: italic; font-size: 0.85rem; }
|
|
398
|
+
.suggest { flex: none; border-top: 1px solid var(--line); padding: 0.45rem 1.1rem 0.1rem; }
|
|
399
|
+
.suggest-label { font-family: ${MONO_STACK}; font-size: 0.66rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.09em; color: var(--muted); }
|
|
400
|
+
.hints { display: flex; flex-wrap: wrap; gap: 0.35rem; max-height: 5.6rem; overflow-y: auto; padding: 0.35rem 0 0.45rem; }
|
|
401
|
+
.hint { background: var(--bg); border: 1px solid var(--line); border-radius: 999px; padding: 0.24rem 0.7rem; font-size: 0.8rem; color: var(--ink); text-align: left; }
|
|
402
|
+
.hint:hover { border-color: var(--entail); }
|
|
403
|
+
#chat-form { flex: none; display: flex; gap: 0.5rem; padding: 0.55rem 1.1rem 0.8rem; border-top: 1px solid var(--line); }
|
|
404
|
+
#chat-input { flex: 1; min-width: 0; font: inherit; font-size: 0.92rem; padding: 0.5rem 0.65rem; border: 1px solid var(--line); border-radius: 4px; background: var(--bg); color: var(--ink); }
|
|
405
|
+
#chat-form button { background: var(--entail); color: var(--card); font-weight: 600; border: none; border-radius: 4px; padding: 0.5rem 1rem; font-size: 0.9rem; }
|
|
406
|
+
|
|
407
|
+
.statusbar { display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap; padding: 0.32rem 0.9rem; font-family: ${MONO_STACK}; font-size: 0.7rem; color: var(--muted); background: var(--entail-soft); border-top: 1px solid var(--entail); }
|
|
408
|
+
#seed-status { margin-left: auto; text-align: right; }
|
|
409
|
+
|
|
410
|
+
@media (max-width: 760px) {
|
|
411
|
+
.workbench { grid-template-columns: 1fr; grid-template-rows: minmax(0, 34%) minmax(0, 1fr); }
|
|
412
|
+
.sidebar { border-right: none; border-bottom: 1px solid var(--line); }
|
|
413
|
+
}
|
|
301
414
|
</style>
|
|
302
415
|
</head>
|
|
303
416
|
<body>
|
|
304
|
-
<
|
|
305
|
-
<
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
<
|
|
309
|
-
<
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
<
|
|
313
|
-
<main>
|
|
314
|
-
<section class="ledger-pane">
|
|
315
|
-
<h2>Facts around <span class="focus-line" id="focus-name">—</span></h2>
|
|
316
|
-
<ul class="rows" id="ledger"></ul>
|
|
317
|
-
</section>
|
|
318
|
-
<aside class="rail">
|
|
319
|
-
<div>
|
|
320
|
-
<h2>Try asking</h2>
|
|
321
|
-
<div class="hints" id="hints"></div>
|
|
417
|
+
<div class="shell">
|
|
418
|
+
<header class="titlebar">
|
|
419
|
+
<svg class="mark" viewBox="0 0 16 16" aria-hidden="true"><path fill="currentColor" d="M8 0l1 2.3a5.8 5.8 0 0 1 1.9.8L13.3 2l.7.7-1.1 2.4c.4.6.6 1.2.8 1.9L16 8l-2.3 1a5.8 5.8 0 0 1-.8 1.9l1.1 2.4-.7.7-2.4-1.1a5.8 5.8 0 0 1-1.9.8L8 16l-1-2.3a5.8 5.8 0 0 1-1.9-.8L2.7 14l-.7-.7 1.1-2.4a5.8 5.8 0 0 1-.8-1.9L0 8l2.3-1c.2-.7.4-1.3.8-1.9L2 2.7l.7-.7 2.4 1.1A5.8 5.8 0 0 1 7 2.3L8 0zm0 5.2A2.8 2.8 0 1 0 8 10.8 2.8 2.8 0 0 0 8 5.2z"/></svg>
|
|
420
|
+
<h1>tmct code explorer</h1>
|
|
421
|
+
<span class="sub">source: <span id="source-name">${escapeHtml(sourceName)}</span></span>
|
|
422
|
+
${showDesktopLink ? `<span class="sub">Also available as a <a href="${DESKTOP_APP_URL}">desktop app</a>.</span>` : ""}
|
|
423
|
+
<div class="pickers">
|
|
424
|
+
<button id="open-graph">Open graph…</button>
|
|
425
|
+
<button id="open-repo">Open repo…</button>
|
|
322
426
|
</div>
|
|
323
|
-
|
|
324
|
-
|
|
427
|
+
</header>
|
|
428
|
+
<div class="workbench">
|
|
429
|
+
<aside class="sidebar">
|
|
430
|
+
<section class="panel" data-panel="explorer">
|
|
431
|
+
<h2 class="panel-head">Facts around <span class="focus-line" id="focus-name">—</span></h2>
|
|
432
|
+
<div class="panel-body">
|
|
433
|
+
<ul class="rows" id="ledger"></ul>
|
|
434
|
+
</div>
|
|
435
|
+
</section>
|
|
436
|
+
</aside>
|
|
437
|
+
<section class="editor" data-panel="conversation">
|
|
438
|
+
<h2 class="panel-head">Conversation</h2>
|
|
325
439
|
<div id="chat-log"></div>
|
|
440
|
+
<div class="suggest">
|
|
441
|
+
<span class="suggest-label">Try asking</span>
|
|
442
|
+
<div class="hints" id="hints"></div>
|
|
443
|
+
</div>
|
|
326
444
|
<form id="chat-form">
|
|
327
|
-
<input id="chat-input" type="text" autocomplete="off" placeholder="ask about this graph…">
|
|
445
|
+
<input id="chat-input" type="text" autocomplete="off" placeholder="ask about this graph, or anything it knows…">
|
|
328
446
|
<button type="submit">Ask</button>
|
|
329
447
|
</form>
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
448
|
+
</section>
|
|
449
|
+
</div>
|
|
450
|
+
<footer class="statusbar">
|
|
451
|
+
<span id="stats"></span>
|
|
452
|
+
<span id="dock-note"></span>
|
|
453
|
+
<span id="seed-status"></span>
|
|
454
|
+
</footer>
|
|
455
|
+
</div>
|
|
334
456
|
<script>window.__CODE_EXPLORER__ = Object.assign({ payload: ${payloadJson} }, ${dataJson});</script>
|
|
335
457
|
${winkLoaderInline ? `<script>\n${embedScriptText(winkLoaderInline)}\n</script>` : ""}
|
|
336
458
|
${bundleInline ? `<script>\n${embedScriptText(bundleInline)}\n</script>` : ""}
|