@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.
Files changed (52) hide show
  1. package/README.md +68 -12
  2. package/bin/tmct.mjs +5 -2
  3. package/corpus/sprites/src/sprite-facts.jsonl +18 -0
  4. package/corpus/worlds/manifest.json +5 -5
  5. package/corpus/worlds/shards/ashcombe-hall.jsonl.gz +0 -0
  6. package/corpus/worlds/src/ashcombe-hall.jsonl +27 -0
  7. package/data/sprites/book-icon.toml +12 -0
  8. package/data/sprites/cellar-icon.toml +12 -0
  9. package/data/sprites/drawing-room-icon.toml +13 -0
  10. package/data/sprites/garden-icon.toml +12 -0
  11. package/data/sprites/kitchen-icon.toml +13 -0
  12. package/data/sprites/library-icon.toml +12 -0
  13. package/data/sprites/pan-icon.toml +11 -0
  14. package/data/sprites/study-icon.toml +12 -0
  15. package/package.json +7 -2
  16. package/src/adapters/corpus/wikipedia-live.mjs +182 -26
  17. package/src/adapters/corpus/worlds-pack.mjs +8 -2
  18. package/src/adapters/memory/core.mjs +8 -1
  19. package/src/adapters/toml-config.mjs +6 -0
  20. package/src/domain/cli-verbs.mjs +2 -0
  21. package/src/domain/memory/trust.mjs +32 -2
  22. package/src/domain/sense-split.mjs +203 -0
  23. package/src/domain/worlds-pack.mjs +50 -0
  24. package/src/services/adventure-autoplay.mjs +5 -2
  25. package/src/services/adventure-viz.mjs +301 -33
  26. package/src/services/adventure.mjs +162 -14
  27. package/src/services/chat-page-viz.mjs +341 -197
  28. package/src/services/chat-session.mjs +24 -9
  29. package/src/services/chat.mjs +580 -47
  30. package/src/services/code-explorer-viz.mjs +198 -76
  31. package/src/services/extract-facts.mjs +384 -82
  32. package/src/services/fold.mjs +1 -1
  33. package/src/services/ingest-viz.mjs +637 -0
  34. package/src/services/ledger-viz.mjs +209 -0
  35. package/src/services/memory-panel-viz.mjs +159 -0
  36. package/src/services/research.mjs +266 -0
  37. package/src/services/sentences.mjs +19 -0
  38. package/src/services/session-log-format.mjs +64 -0
  39. package/src/services/sessions.mjs +56 -22
  40. package/src/services/spider-fly-turn.mjs +54 -1
  41. package/src/services/spider-fly-viz.mjs +41 -23
  42. package/src/surfaces/web/adventure-browser-entry.mjs +9 -5
  43. package/src/surfaces/web/chat-browser-entry.mjs +32 -11
  44. package/src/surfaces/web/code-explorer-browser-entry.mjs +27 -11
  45. package/src/surfaces/web/ingest-browser-entry.mjs +208 -0
  46. package/src/surfaces/web/ledger-browser-entry.mjs +24 -5
  47. package/src/surfaces/web/memory-ask-browser.bundle.js +134 -125
  48. package/src/surfaces/web/memory-stats.mjs +53 -0
  49. package/src/tools/definitions.mjs +14 -0
  50. package/src/tools/handlers/index.mjs +2 -0
  51. package/src/tools/handlers/tmct-ingest.mjs +43 -0
  52. package/src/tools/server.mjs +5 -2
@@ -28,6 +28,8 @@ import * as defaultSource from "../adapters/source.mjs";
28
28
  import { resolveExtensions, mergedLexiconExtra } from "./extensions.mjs";
29
29
  import { runTurn, hasSeededVocabulary, vocabExampleHint } from "./chat.mjs";
30
30
  import { resolveGameConfig } from "../domain/game-config.mjs";
31
+ import { resolveResearchConfig } from "./research.mjs";
32
+ import { sessionLogHeaderMarkdown, sessionLogTurnMarkdown, sessionLogEndMarkdown } from "./session-log-format.mjs";
31
33
 
32
34
  /** Where session logs live, relative to the target repo. `.tmct/` is the repo's
33
35
  * one artifact directory (gitignored, machine-local) — flip this single constant
@@ -198,6 +200,11 @@ export async function createSession({
198
200
  // to the shipped defaults for every key.
199
201
  const gameConfig = resolveGameConfig(toml);
200
202
 
203
+ // The research lane's knobs (fan-out cap, depth, the polite interval) —
204
+ // resolved once per session from the same tmct.toml, defaults filling
205
+ // every unset key exactly as resolveGameConfig does above.
206
+ const researchConfig = resolveResearchConfig(toml);
207
+
201
208
  // tmct.toml's corpus tier3 opts the session into the live supplement too —
202
209
  // the flag/env tiers above stay authoritative when set.
203
210
  if (toml?.corpus?.tier === "tier3") liveReferenceOn = true;
@@ -243,7 +250,7 @@ export async function createSession({
243
250
  const sessionsDir = join(repo, SESSIONS_DIR_REL);
244
251
  await mkdir(logDir, { recursive: true });
245
252
  await mkdir(sessionsDir, { recursive: true });
246
- const logFile = join(logDir, `session-${sessionId}.log`);
253
+ const logFile = join(logDir, `session-${sessionId}.md`);
247
254
  const sidecarFile = join(sessionsDir, `session-${sessionId}.jsonl`);
248
255
  const stream = createWriteStream(logFile, { flags: "a" });
249
256
  const sidecar = createWriteStream(sidecarFile, { flags: "a" });
@@ -255,7 +262,7 @@ export async function createSession({
255
262
  const writeSidecar = (obj) => flush(sidecar, JSON.stringify(obj) + "\n");
256
263
 
257
264
  const startIso = new Date().toISOString();
258
- await writeLog(`# tmct chat ${version} session started ${startIso} repo ${repo}\n\n`);
265
+ await writeLog(sessionLogHeaderMarkdown({ version, sessionId, startedAt: startIso, repo }));
259
266
  await writeSidecar({ type: "session", id: sessionId, started: startIso, repo, tmctVersion: version });
260
267
 
261
268
  // Read-time graph upsert (sessions.mjs): after every turn, the session becomes /
@@ -336,6 +343,7 @@ export async function createSession({
336
343
  let focus = null; // the current focus entity ({id,label}) — threaded turn to turn
337
344
  let last = null; // the last dispatched answer ({query,answer,detail}) — why/say-more re-renders it
338
345
  let planState = null; // the in-progress plan (goals/moves/cursor) — cleared by completion or a fresh goal, never by an aside
346
+ let researchState = null; // the in-progress research queue — advanced by "research next", cleared by completion or "research stop"
339
347
  let closed = false;
340
348
 
341
349
  return {
@@ -346,6 +354,7 @@ export async function createSession({
346
354
  get focus() { return focus; },
347
355
  get lastAnswer() { return last; },
348
356
  get planState() { return planState; },
357
+ get researchState() { return researchState; },
349
358
  get turns() { return turns; },
350
359
  get narrate() { return narrateOn; },
351
360
  get liveReference() { return liveReferenceOn; },
@@ -359,27 +368,31 @@ export async function createSession({
359
368
  async turn(line) {
360
369
  let result;
361
370
  try {
362
- result = await runTurn(line, { config, source, graph, focus, last, memoryDir, sessionId, env, lexicon, narrate: narrateOn, liveReference: liveReferenceOn, vocabHint, tel, biasByBundle, planState, gameConfig });
371
+ result = await runTurn(line, { config, source, graph, focus, last, memoryDir, sessionId, env, lexicon, narrate: narrateOn, liveReference: liveReferenceOn, vocabHint, tel, biasByBundle, planState, gameConfig, researchState, researchConfig });
363
372
  } catch (e) {
364
373
  const ts = new Date().toISOString();
365
374
  const message = e instanceof Error ? e.message : String(e);
366
- await writeLog(`${ts}\n> ${line}\nerror: ${message}\n`);
375
+ await writeLog(sessionLogTurnMarkdown({ startedAt: ts, turnNumber: turns + 1, query: line, answer: `error: ${message}` }));
367
376
  const errorRecord = { type: "error", ts, query: line, error: message };
368
377
  await writeSidecar(errorRecord);
369
378
  turnRecords.push(errorRecord);
370
379
  turns += 1;
371
380
  return { answer: `Something went wrong answering that (${message}). Try rephrasing, or /help.`, end: false, prompt: promptFor(focus) };
372
381
  }
373
- const { answer, logLines, record, focus: nextFocus, last: nextLast, end, narrate: nextNarrate, liveReference: nextLiveReference } = result;
382
+ const { answer, record, focus: nextFocus, last: nextLast, end, narrate: nextNarrate, liveReference: nextLiveReference } = result;
374
383
  focus = nextFocus;
375
384
  last = nextLast;
376
385
  if ("planState" in result) planState = result.planState;
386
+ if ("researchState" in result) researchState = result.researchState;
377
387
  // /narrate on|off and /wiki on|off (runCommand) ride the turn RESULT the
378
388
  // same way a focus update does — apply them to this handle's
379
389
  // session-scoped state.
380
390
  if (typeof nextNarrate === "boolean") narrateOn = nextNarrate;
381
- if (typeof nextLiveReference === "boolean") liveReferenceOn = nextLiveReference;
382
- await writeLog(logLines.join("\n") + "\n");
391
+ // four-state: false (off), true (rescue on a miss), "supplement" (also
392
+ // append a cited read-out under every grounded vocabulary answer), or
393
+ // "always" (widen that to every grounded answer).
394
+ if (typeof nextLiveReference === "boolean" || nextLiveReference === "supplement" || nextLiveReference === "always") liveReferenceOn = nextLiveReference;
395
+ await writeLog(sessionLogTurnMarkdown({ startedAt: record.ts, turnNumber: turns + 1, query: line, answer }));
383
396
  await writeSidecar(record);
384
397
  turnRecords.push(record);
385
398
  // One telemetry line per dispatched turn (OFF by default → no-op). query.raw is
@@ -391,7 +404,7 @@ export async function createSession({
391
404
  });
392
405
  await upsertGraph(record.ts);
393
406
  turns += 1;
394
- return { answer, end: Boolean(end), prompt: promptFor(focus), plan: result.plan ?? null, record };
407
+ return { answer, end: Boolean(end), prompt: promptFor(focus), plan: result.plan ?? null, research: result.research, record };
395
408
  },
396
409
 
397
410
  /** End-of-session close: end lines in both artifacts, the final graph upsert
@@ -401,7 +414,9 @@ export async function createSession({
401
414
  if (closed) return;
402
415
  closed = true;
403
416
  const endIso = new Date().toISOString();
404
- await writeLog(`${endIso}\n> /exit\nsession end ${endIso}\n`);
417
+ const closingTurnNumber = turns + 1;
418
+ await writeLog(sessionLogTurnMarkdown({ startedAt: endIso, turnNumber: closingTurnNumber, query: "/exit", answer: "" }));
419
+ await writeLog(sessionLogEndMarkdown({ endedAt: endIso, turnCount: closingTurnNumber }));
405
420
  await writeSidecar({ type: "end", ts: endIso });
406
421
  await upsertGraph(endIso);
407
422
  await new Promise((resolve) => stream.end(resolve));