@polycode-projects/the-mechanical-code-talker 3.0.10 → 3.1.2

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.
@@ -26,8 +26,10 @@ export function resolveOrThrow(svc, symbol, what) {
26
26
  return { match, candidates };
27
27
  }
28
28
 
29
- /** The shape most cold tools share: one required `symbol`, resolved, then rendered. */
30
- export const symbolHandler = (render) => (args, { graph, svc }) => {
29
+ /** The shape most cold tools share: one required `symbol`, resolved, then rendered.
30
+ * `config.toolNamePrefix` (default "tmct_", set by e.g. seonix's own tool naming)
31
+ * threads through so a render's own follow-up hints stay accurate outside tmct. */
32
+ export const symbolHandler = (render) => (args, { graph, svc, config }) => {
31
33
  const { match } = resolveOrThrow(svc, requiredArg(args, "symbol"), "symbol");
32
- return render(graph, match);
34
+ return render(graph, match, { toolNamePrefix: config?.toolNamePrefix });
33
35
  };
@@ -36,6 +36,7 @@ export async function buildContextBundle(args, { config, source = defaultSource,
36
36
  // bodies) with top-up, and it OVERRIDES trim so even secondary modules get the full bundle. Used
37
37
  // by the tmct-max arm to test whether more injection re-bloats.
38
38
  const max = Boolean(args?.max);
39
+ const toolNamePrefix = config?.toolNamePrefix || "tmct_";
39
40
  const graph = await loadGraph(config, source);
40
41
  // repo root = the dir containing .tmct/ (graphFile = <repo>/.tmct/graph.json) — computed
41
42
  // before createGraphService so the RI service can be constructed source-capable: this
@@ -123,7 +124,7 @@ export async function buildContextBundle(args, { config, source = defaultSource,
123
124
  out.push(` ${s.class} ${s.label}${s.site ? ` :${s.site.start}` : ""} ${dec}${sig}${r}`);
124
125
  }
125
126
  if (plan.siblings.length > plan.siblingCap) {
126
- out.push(` …+${plan.siblings.length - plan.siblingCap} more (use tmct_search kind=function or tmct_snippet <name> for any of them)`);
127
+ out.push(` …+${plan.siblings.length - plan.siblingCap} more (use ${toolNamePrefix}search kind=function or ${toolNamePrefix}snippet <name> for any of them)`);
127
128
  }
128
129
  }
129
130
  if (mask.allExports && plan.allExports) {
@@ -148,7 +149,7 @@ export async function buildContextBundle(args, { config, source = defaultSource,
148
149
  out.push(`\nYou now have the snippet, the sibling style, the registration anchor and the tests. ` +
149
150
  `Write the new code with Edit/Write — do NOT Read ${plan.moduleLabel}.`);
150
151
  if (tier !== "FULL") {
151
- out.push(`(bundle tier ${tier}; for any omitted sections run tmct_context_more {"symbol":"${symbol}"}, or tmct_context with depth="full".)`);
152
+ out.push(`(bundle tier ${tier}; for any omitted sections run ${toolNamePrefix}context_more {"symbol":"${symbol}"}, or ${toolNamePrefix}context with depth="full".)`);
152
153
  }
153
154
  return { text: out.join("\n"), tier, topup };
154
155
  }
@@ -10,13 +10,19 @@ import { serializeFactsJsonl } from "../../adapters/memory/export-jsonl.mjs";
10
10
  import { dirname } from "node:path";
11
11
  import { loadMemory, openConfiguredMemoryBackend } from "../../adapters/memory/core.mjs";
12
12
 
13
- export async function tmct_export(_args, { config }) {
14
- const { dir, close } = await openConfiguredMemoryBackend(dirname(dirname(config.graphFile)));
13
+ export async function tmct_export(_args, { config, memoryBackend = null }) {
14
+ // Prefer a caller-supplied backend handle (e.g. an already-open session's
15
+ // memory store) over re-deriving one from config/tmct.toml — re-deriving
16
+ // can silently land on a different backend than the one the caller is
17
+ // actually using. A caller-supplied handle is caller-owned, so it is never
18
+ // closed here; only a backend this call opened itself gets closed.
19
+ const opened = memoryBackend ? null : await openConfiguredMemoryBackend(dirname(dirname(config.graphFile)));
20
+ const dir = memoryBackend || opened.dir;
15
21
  try {
16
22
  const jsonl = serializeFactsJsonl(await loadMemory(dir));
17
23
  return jsonl || "(the memory store holds no facts to export)";
18
24
  } finally {
19
- await close();
25
+ if (opened) await opened.close();
20
26
  }
21
27
  }
22
28
 
@@ -9,7 +9,7 @@ import { requiredArg, resolveOrThrow } from "./kit.mjs";
9
9
  export async function tmct_members(args, { graph, svc, config }) {
10
10
  const symbol = requiredArg(args, "class");
11
11
  const { match } = resolveSymbol(svc.graph, symbol);
12
- if (match) return renderMembers(graph, match); // code-map wins when present
12
+ if (match) return renderMembers(graph, match, { toolNamePrefix: config?.toolNamePrefix }); // code-map wins when present
13
13
  const fallback = renderMemorySubclasses(await memoryFactRows(config), symbol);
14
14
  if (fallback) return fallback;
15
15
  resolveOrThrow(svc, symbol, "class"); // the honest miss
@@ -13,6 +13,7 @@ export async function tmct_search(args, { graph, config }) {
13
13
  kind,
14
14
  decorator: String(args?.decorator || "").trim(),
15
15
  name: String(args?.name || "").trim(),
16
+ toolNamePrefix: config?.toolNamePrefix,
16
17
  });
17
18
  if (!kind && /^no module matches/.test(out)) {
18
19
  const fallback = renderMemoryDefinition(await memoryFactRows(config), query);
@@ -44,7 +44,7 @@ export const TOOLS = HOT_TOOLS.map(({ name, agentDescription, inputSchema }) =>
44
44
  inputSchema,
45
45
  }));
46
46
 
47
- export async function dispatchTool(name, args, { config, source = defaultSource, tel = null, ingest = null } = {}) {
47
+ export async function dispatchTool(name, args, { config, source = defaultSource, tel = null, ingest = null, memoryBackend = null } = {}) {
48
48
  // Reject an unknown tool BEFORE touching the graph — an unknown name never
49
49
  // triggers a load. hasOwn, so an inherited name ("constructor", "toString")
50
50
  // is unknown rather than a callable found on the prototype chain.
@@ -52,13 +52,18 @@ export async function dispatchTool(name, args, { config, source = defaultSource,
52
52
  const handle = HANDLERS[name];
53
53
  // `ingest` is the recognizer seam a caller in the service layer injects (the
54
54
  // tool layer sits UNDER services and must not import one, so a tool that needs
55
- // the chat recognizer receives it here rather than importing it).
56
- if (handle.ownsGraphLoad) return handle(args, { config, source, tel, ingest });
55
+ // the chat recognizer receives it here rather than importing it). `memoryBackend`
56
+ // is the same kind of seam for a caller that already holds an open memory-store
57
+ // handle (e.g. a session's own `memoryDir`) — a handler that reads the
58
+ // conversational memory store (tmct_export) prefers it over re-deriving a
59
+ // backend from config when one is supplied; every other caller leaves it null
60
+ // and gets today's re-derive-from-config behaviour unchanged.
61
+ if (handle.ownsGraphLoad) return handle(args, { config, source, tel, ingest, memoryBackend });
57
62
  const graph = await loadGraph(config, source);
58
63
  // repo root = the dir containing .tmct/ (graphFile = <repo>/.tmct/graph.json). Passed to
59
64
  // createGraphService so svc.snippet()/svc.context() are usable directly, and on to the
60
65
  // handlers that do their own safe source reads.
61
66
  const repoRoot = dirname(dirname(config.graphFile));
62
67
  const svc = createGraphService(graph, { sourceAccess: true, repoRoot, readFile, tel, ask });
63
- return handle(args, { graph, svc, config, repoRoot });
68
+ return handle(args, { graph, svc, config, repoRoot, memoryBackend });
64
69
  }