mastracode 0.33.2-alpha.8 → 0.34.0-alpha.13

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 (35) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/dist/cli.cjs +3 -2
  3. package/dist/cli.cjs.map +1 -1
  4. package/dist/cli.js +3 -2
  5. package/dist/cli.js.map +1 -1
  6. package/dist/tui/command-dispatch.d.ts.map +1 -1
  7. package/dist/tui/commands/index.d.ts +1 -0
  8. package/dist/tui/commands/index.d.ts.map +1 -1
  9. package/dist/tui/commands/knowledge-command.d.ts +3 -0
  10. package/dist/tui/commands/knowledge-command.d.ts.map +1 -0
  11. package/dist/tui/commands/types.d.ts +2 -0
  12. package/dist/tui/commands/types.d.ts.map +1 -1
  13. package/dist/tui/components/help-overlay.d.ts.map +1 -1
  14. package/dist/tui/components/knowledge-browser.d.ts +57 -0
  15. package/dist/tui/components/knowledge-browser.d.ts.map +1 -0
  16. package/dist/tui/components/subconscious-activity.d.ts +25 -0
  17. package/dist/tui/components/subconscious-activity.d.ts.map +1 -0
  18. package/dist/tui/db-message-parts.d.ts +3 -1
  19. package/dist/tui/db-message-parts.d.ts.map +1 -1
  20. package/dist/tui/mastra-tui.d.ts.map +1 -1
  21. package/dist/tui/render-messages.d.ts.map +1 -1
  22. package/dist/tui/setup.d.ts.map +1 -1
  23. package/dist/tui/state.d.ts +3 -0
  24. package/dist/tui/state.d.ts.map +1 -1
  25. package/dist/tui/utils/experimental-features.d.ts +2 -0
  26. package/dist/tui/utils/experimental-features.d.ts.map +1 -0
  27. package/dist/{tui-D-aJNadI.js → tui-BB2N6Mud.js} +599 -4
  28. package/dist/tui-BB2N6Mud.js.map +1 -0
  29. package/dist/{tui-C-5CxtMW.cjs → tui-C6uUdh0u.cjs} +599 -4
  30. package/dist/tui-C6uUdh0u.cjs.map +1 -0
  31. package/dist/tui.cjs +1 -1
  32. package/dist/tui.js +1 -1
  33. package/package.json +11 -11
  34. package/dist/tui-C-5CxtMW.cjs.map +0 -1
  35. package/dist/tui-D-aJNadI.js.map +0 -1
@@ -1456,6 +1456,11 @@ async function startGoal(ctx, objective, judgeModelId, maxTurns, options = {}) {
1456
1456
  }
1457
1457
  }
1458
1458
  //#endregion
1459
+ //#region src/tui/utils/experimental-features.ts
1460
+ function isSubconsciousEnabled() {
1461
+ return process.env.MASTRACODE_EXPERIMENTAL_SUBCONSCIOUS === "1";
1462
+ }
1463
+ //#endregion
1459
1464
  //#region src/tui/components/help-overlay.ts
1460
1465
  function getCommands(modes) {
1461
1466
  const cmds = [
@@ -1515,6 +1520,10 @@ function getCommands(modes) {
1515
1520
  key: "/memory",
1516
1521
  description: "Configure Observational Memory (/om alias)"
1517
1522
  },
1523
+ ...isSubconsciousEnabled() ? [{
1524
+ key: "/knowledge",
1525
+ description: "Browse scoped Subconscious knowledge"
1526
+ }] : [],
1518
1527
  {
1519
1528
  key: "/review",
1520
1529
  description: "Review a GitHub pull request"
@@ -4560,15 +4569,18 @@ function isGoalJudgeEvaluationSignal(message) {
4560
4569
  const reminder = getReminderView(message);
4561
4570
  return reminder.reminderType === "goal-judge" && reminder.goalEvaluation !== void 0;
4562
4571
  }
4563
- /** Fields the state-signal UI needs, sourced from a `state` signal's `metadata.state`. */
4572
+ /** Fields the state-signal UI needs, sourced from a `state` signal's metadata. */
4564
4573
  function getStateSignalView(message) {
4565
4574
  const signal = getSignalView(message);
4566
- const stateMeta = asRecord(asRecord(signal.metadata)?.state) ?? {};
4575
+ const metadata = asRecord(signal.metadata) ?? {};
4576
+ const stateMeta = asRecord(metadata.state) ?? {};
4567
4577
  return {
4568
4578
  stateId: asString(stateMeta.id) ?? asString(signal.tagName) ?? "state",
4569
4579
  mode: stateMeta.mode === "delta" ? "delta" : "snapshot",
4570
4580
  cacheKey: asString(stateMeta.cacheKey),
4571
4581
  version: asNumber(stateMeta.version),
4582
+ ..."value" in metadata ? { value: metadata.value } : {},
4583
+ ..."delta" in metadata ? { delta: metadata.delta } : {},
4572
4584
  message: contentsToText(signal.contents)
4573
4585
  };
4574
4586
  }
@@ -5782,6 +5794,77 @@ function summarizeArgs(args, maxWidth = 40) {
5782
5794
  return parts.join(" ");
5783
5795
  }
5784
5796
  //#endregion
5797
+ //#region src/tui/components/subconscious-activity.ts
5798
+ const MAX_UPDATES = 100;
5799
+ const MAX_HOT = 100;
5800
+ const MAX_ERRORS = 100;
5801
+ const DISPLAY_UPDATES = 4;
5802
+ const DISPLAY_HOT = 4;
5803
+ const DISPLAY_ERRORS = 3;
5804
+ function object(value) {
5805
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : void 0;
5806
+ }
5807
+ function string(value) {
5808
+ return typeof value === "string" && value.length > 0;
5809
+ }
5810
+ function update(value) {
5811
+ const item = object(value);
5812
+ if (!item || !string(item.action) || !["node", "record"].includes(String(item.type)) || !string(item.createdAt) || item.name !== void 0 && typeof item.name !== "string") return;
5813
+ return {
5814
+ action: item.action,
5815
+ type: item.type,
5816
+ ...typeof item.name === "string" ? { name: item.name } : {},
5817
+ createdAt: item.createdAt
5818
+ };
5819
+ }
5820
+ function hotRecord(value) {
5821
+ const item = object(value);
5822
+ if (!item || item.type !== "node" || !string(item.name) || typeof item.updates !== "number" || !Number.isFinite(item.updates) || item.updates < 0) return;
5823
+ return {
5824
+ type: item.type,
5825
+ name: item.name,
5826
+ updates: item.updates
5827
+ };
5828
+ }
5829
+ function parseSubconsciousActivitySnapshot(value) {
5830
+ const snapshot = object(value);
5831
+ if (!snapshot || !Array.isArray(snapshot.updates) || !Array.isArray(snapshot.hot)) return void 0;
5832
+ if (snapshot.updates.length > MAX_UPDATES || snapshot.hot.length > MAX_HOT) return void 0;
5833
+ if (snapshot.errors !== void 0 && (!Array.isArray(snapshot.errors) || snapshot.errors.length > MAX_ERRORS)) return;
5834
+ const updates = snapshot.updates.map(update);
5835
+ const hot = snapshot.hot.map(hotRecord);
5836
+ const errors = snapshot.errors?.map((error) => typeof error === "string" ? error : void 0);
5837
+ if (updates.some((item) => !item) || hot.some((item) => !item) || errors?.some((error) => error === void 0)) return;
5838
+ return {
5839
+ updates,
5840
+ hot,
5841
+ ...errors?.length ? { errors } : {}
5842
+ };
5843
+ }
5844
+ var SubconsciousActivityComponent = class extends Container {
5845
+ constructor(snapshot) {
5846
+ super();
5847
+ const errorCount = snapshot.errors?.length ?? 0;
5848
+ const summary = `${snapshot.updates.length} update${snapshot.updates.length === 1 ? "" : "s"} · ${snapshot.hot.length} hot${errorCount ? ` · ${errorCount} error${errorCount === 1 ? "" : "s"}` : ""}`;
5849
+ this.addChild(new Text(chalk.hex(mastra.blue).bold("Subconscious knowledge"), 0, 0));
5850
+ this.addChild(new Text(theme.fg("dim", summary), 2, 0));
5851
+ for (const item of snapshot.updates.slice(0, DISPLAY_UPDATES)) {
5852
+ const target = item.name ?? `${item.type} (details unavailable)`;
5853
+ this.addChild(new Text(`${item.action}: ${target}`, 2, 0));
5854
+ }
5855
+ if (snapshot.updates.length > DISPLAY_UPDATES) this.addChild(new Text(theme.fg("muted", `+${snapshot.updates.length - DISPLAY_UPDATES} more updates`), 2, 0));
5856
+ if (snapshot.hot.length) {
5857
+ const names = snapshot.hot.slice(0, DISPLAY_HOT).map((item) => `${item.name} (${item.updates})`).join(", ");
5858
+ this.addChild(new Text(theme.fg("dim", `Hot: ${names}`), 2, 0));
5859
+ }
5860
+ for (const error of snapshot.errors?.slice(0, DISPLAY_ERRORS) ?? []) this.addChild(new Text(theme.fg("error", `Error: ${error}`), 2, 0));
5861
+ if (errorCount > DISPLAY_ERRORS) this.addChild(new Text(theme.fg("muted", `+${errorCount - DISPLAY_ERRORS} more errors`), 2, 0));
5862
+ }
5863
+ getChatSpacingKind() {
5864
+ return "system";
5865
+ }
5866
+ };
5867
+ //#endregion
5785
5868
  //#region src/tui/components/system-reminder.ts
5786
5869
  /**
5787
5870
  * SystemReminderComponent - renders system-generated reminder messages
@@ -9401,7 +9484,8 @@ function renderSignalMessage(state, message) {
9401
9484
  if (kind === "state") {
9402
9485
  const stateSignal = getStateSignalView(message);
9403
9486
  if (stateSignal.stateId === TASKS_STATE_ID || stateSignal.stateId === GOAL_STATE_SIGNAL_ID) return true;
9404
- const component = new StateSignalComponent({
9487
+ const subconsciousActivity = stateSignal.stateId === "subconscious-activity" ? parseSubconsciousActivitySnapshot(stateSignal.value) : void 0;
9488
+ const component = subconsciousActivity ? new SubconsciousActivityComponent(subconsciousActivity) : new StateSignalComponent({
9405
9489
  stateId: stateSignal.stateId,
9406
9490
  mode: stateSignal.mode,
9407
9491
  version: stateSignal.version,
@@ -12745,6 +12829,509 @@ async function handleOMCommand(ctx) {
12745
12829
  });
12746
12830
  }
12747
12831
  //#endregion
12832
+ //#region src/tui/components/knowledge-browser.ts
12833
+ const SECTIONS = [
12834
+ "scopes",
12835
+ "nodes",
12836
+ "activity"
12837
+ ];
12838
+ const NODE_SORTS = [
12839
+ "relevant",
12840
+ "recent",
12841
+ "connected"
12842
+ ];
12843
+ const PAGE_SIZE = 12;
12844
+ const MAX_BODY_LINES = 10;
12845
+ const MIN_CONTENT_WIDTH = 20;
12846
+ function middleTruncate(value, width) {
12847
+ if (visibleWidth(value) <= width) return value;
12848
+ if (width <= 1) return "…";
12849
+ const side = Math.max(1, Math.floor((width - 1) / 2));
12850
+ return `${value.slice(0, side)}…${value.slice(-side)}`;
12851
+ }
12852
+ function scopeLabel(record, level) {
12853
+ return `[${record.scope.level === level ? "exact" : "inherited"}:${record.scope.level}]`;
12854
+ }
12855
+ const ROLE_GROUPS = [
12856
+ {
12857
+ role: "bridge",
12858
+ label: "Bridges"
12859
+ },
12860
+ {
12861
+ role: "source",
12862
+ label: "Sources"
12863
+ },
12864
+ {
12865
+ role: "referenced",
12866
+ label: "Referenced only"
12867
+ },
12868
+ {
12869
+ role: "isolated",
12870
+ label: "Isolated"
12871
+ }
12872
+ ];
12873
+ function graphRole(record) {
12874
+ const counts = record.relationshipCounts;
12875
+ if (!counts) return void 0;
12876
+ if (counts.outgoing > 0 && counts.incoming > 0) return "bridge";
12877
+ if (counts.outgoing > 0) return "source";
12878
+ if (counts.incoming > 0) return "referenced";
12879
+ return "isolated";
12880
+ }
12881
+ function roleLabel(role) {
12882
+ switch (role) {
12883
+ case "bridge": return "Bridge";
12884
+ case "source": return "Source";
12885
+ case "referenced": return "Referenced only";
12886
+ case "isolated": return "Isolated";
12887
+ }
12888
+ }
12889
+ function countsBadge(record) {
12890
+ const counts = record.relationshipCounts;
12891
+ if (!counts) return "";
12892
+ return ` · →${counts.outgoing} ←${counts.incoming}${counts.sampled ? "+" : ""}`;
12893
+ }
12894
+ function groupNodeRecords(records) {
12895
+ const grouped = [];
12896
+ for (const group of ROLE_GROUPS) grouped.push(...records.filter((record) => graphRole(record) === group.role));
12897
+ grouped.push(...records.filter((record) => graphRole(record) === void 0));
12898
+ return grouped;
12899
+ }
12900
+ function formatError(error) {
12901
+ return error instanceof Error ? error.message : String(error);
12902
+ }
12903
+ var KnowledgeBrowserComponent = class {
12904
+ tui;
12905
+ inspector;
12906
+ onClose;
12907
+ scopeTree;
12908
+ identityKey;
12909
+ section = "scopes";
12910
+ level = "resource";
12911
+ nodes = [];
12912
+ activity = [];
12913
+ nextCursor;
12914
+ query = "";
12915
+ nodeSort = "relevant";
12916
+ nodeCoverage;
12917
+ selectedIndex = 0;
12918
+ detail;
12919
+ detailHistory = [];
12920
+ detailTargets = [];
12921
+ loading = false;
12922
+ error;
12923
+ requestVersion = 0;
12924
+ _focused = false;
12925
+ constructor(options) {
12926
+ this.tui = options.tui;
12927
+ this.inspector = options.inspector;
12928
+ this.onClose = options.onClose;
12929
+ this.refresh();
12930
+ }
12931
+ get focused() {
12932
+ return this._focused;
12933
+ }
12934
+ set focused(value) {
12935
+ this._focused = value;
12936
+ }
12937
+ async refresh() {
12938
+ const requestVersion = ++this.requestVersion;
12939
+ this.loading = true;
12940
+ this.error = void 0;
12941
+ this.renderNow();
12942
+ try {
12943
+ const tree = await this.inspector.getScopeTree();
12944
+ if (requestVersion !== this.requestVersion) return;
12945
+ const changed = this.identityKey !== void 0 && this.identityKey !== tree.identityKey;
12946
+ this.scopeTree = tree;
12947
+ this.identityKey = tree.identityKey;
12948
+ if (changed) {
12949
+ this.level = tree.defaultLevel;
12950
+ this.section = "scopes";
12951
+ this.detail = void 0;
12952
+ this.detailHistory = [];
12953
+ this.query = "";
12954
+ this.nodes = [];
12955
+ this.activity = [];
12956
+ this.nextCursor = void 0;
12957
+ this.selectedIndex = 0;
12958
+ }
12959
+ } catch (error) {
12960
+ if (requestVersion === this.requestVersion) this.error = formatError(error);
12961
+ } finally {
12962
+ if (requestVersion === this.requestVersion) {
12963
+ this.loading = false;
12964
+ this.renderNow();
12965
+ }
12966
+ }
12967
+ }
12968
+ renderNow() {
12969
+ this.tui.requestRender();
12970
+ }
12971
+ async ensureIdentity() {
12972
+ const previous = this.identityKey;
12973
+ await this.refresh();
12974
+ return previous === void 0 || previous === this.identityKey;
12975
+ }
12976
+ async loadSection(append = false) {
12977
+ const requestVersion = ++this.requestVersion;
12978
+ this.loading = true;
12979
+ this.error = void 0;
12980
+ this.renderNow();
12981
+ try {
12982
+ const tree = await this.inspector.getScopeTree();
12983
+ if (requestVersion !== this.requestVersion) return;
12984
+ if (this.identityKey !== void 0 && tree.identityKey !== this.identityKey) {
12985
+ this.scopeTree = tree;
12986
+ this.identityKey = tree.identityKey;
12987
+ this.level = tree.defaultLevel;
12988
+ this.section = "scopes";
12989
+ this.detail = void 0;
12990
+ this.detailHistory = [];
12991
+ this.nodes = [];
12992
+ this.activity = [];
12993
+ this.nextCursor = void 0;
12994
+ this.selectedIndex = 0;
12995
+ return;
12996
+ }
12997
+ this.scopeTree = tree;
12998
+ this.identityKey = tree.identityKey;
12999
+ const cursor = append ? this.nextCursor : void 0;
13000
+ let result;
13001
+ if (this.section === "nodes") result = await this.inspector.listNodes({
13002
+ level: this.level,
13003
+ namePrefix: this.query || void 0,
13004
+ sort: this.nodeSort,
13005
+ cursor,
13006
+ limit: PAGE_SIZE
13007
+ });
13008
+ else if (this.section === "activity") result = await this.inspector.listActivity({
13009
+ level: this.level,
13010
+ cursor,
13011
+ limit: PAGE_SIZE
13012
+ });
13013
+ else return;
13014
+ if (requestVersion !== this.requestVersion || result.identityKey !== this.identityKey) return;
13015
+ if (this.section === "activity") {
13016
+ const events = result.events;
13017
+ this.activity = append ? [...this.activity, ...events] : events;
13018
+ } else {
13019
+ const recordResult = result;
13020
+ const merged = append ? [...this.nodes, ...recordResult.nodes] : recordResult.nodes;
13021
+ this.nodes = groupNodeRecords(merged);
13022
+ this.nodeCoverage = recordResult.coverage;
13023
+ }
13024
+ this.nextCursor = result.nextCursor;
13025
+ if (!append) this.selectedIndex = 0;
13026
+ } catch (error) {
13027
+ if (requestVersion === this.requestVersion) this.error = formatError(error);
13028
+ } finally {
13029
+ if (requestVersion === this.requestVersion) {
13030
+ this.loading = false;
13031
+ this.renderNow();
13032
+ }
13033
+ }
13034
+ }
13035
+ async openNode(node) {
13036
+ const requestVersion = ++this.requestVersion;
13037
+ this.loading = true;
13038
+ this.error = void 0;
13039
+ this.renderNow();
13040
+ try {
13041
+ const detail = {
13042
+ type: "node",
13043
+ value: await this.inspector.getNode({ handle: node.handle })
13044
+ };
13045
+ if (requestVersion !== this.requestVersion || detail.value.identityKey !== this.identityKey) return;
13046
+ if (this.detail) this.detailHistory.push(this.detail);
13047
+ else this.detailHistory = [];
13048
+ this.detail = detail;
13049
+ this.selectedIndex = 0;
13050
+ } catch (error) {
13051
+ if (requestVersion === this.requestVersion) this.error = formatError(error);
13052
+ } finally {
13053
+ if (requestVersion === this.requestVersion) {
13054
+ this.loading = false;
13055
+ this.renderNow();
13056
+ }
13057
+ }
13058
+ }
13059
+ mergeNodes(current, next) {
13060
+ return [...new Map([...current, ...next].map((node) => [`${node.type}:${node.kind ?? ""}:${node.name}:${node.scope.level}:${node.scope.id}`, node])).values()];
13061
+ }
13062
+ async loadMoreRecords(kind) {
13063
+ if (this.detail?.type !== "node") return;
13064
+ const current = this.detail.value;
13065
+ const cursor = kind === "about" ? current.recordsNextCursor : current.mentioningRecordsNextCursor;
13066
+ if (!cursor) return;
13067
+ const requestVersion = ++this.requestVersion;
13068
+ this.loading = true;
13069
+ this.renderNow();
13070
+ try {
13071
+ const next = await this.inspector.getNode({
13072
+ handle: current.node.handle,
13073
+ recordsCursor: kind === "about" ? cursor : void 0,
13074
+ mentioningRecordsCursor: kind === "mentioning" ? cursor : void 0
13075
+ });
13076
+ if (requestVersion !== this.requestVersion || next.identityKey !== this.identityKey || this.detail?.type !== "node") return;
13077
+ this.detail = {
13078
+ type: "node",
13079
+ value: {
13080
+ ...next,
13081
+ records: kind === "about" ? [...current.records, ...next.records] : current.records,
13082
+ recordsNextCursor: kind === "about" ? next.recordsNextCursor : current.recordsNextCursor,
13083
+ mentioningRecords: kind === "mentioning" ? [...current.mentioningRecords, ...next.mentioningRecords] : current.mentioningRecords,
13084
+ mentioningRecordsNextCursor: kind === "mentioning" ? next.mentioningRecordsNextCursor : current.mentioningRecordsNextCursor,
13085
+ outgoingTargets: {
13086
+ nodes: this.mergeNodes(current.outgoingTargets.nodes, next.outgoingTargets.nodes),
13087
+ partial: kind === "about" ? next.outgoingTargets.partial : current.outgoingTargets.partial
13088
+ },
13089
+ incomingParents: {
13090
+ nodes: this.mergeNodes(current.incomingParents.nodes, next.incomingParents.nodes),
13091
+ partial: kind === "mentioning" ? next.incomingParents.partial : current.incomingParents.partial
13092
+ }
13093
+ }
13094
+ };
13095
+ } catch (error) {
13096
+ if (requestVersion === this.requestVersion) this.error = formatError(error);
13097
+ } finally {
13098
+ if (requestVersion === this.requestVersion) {
13099
+ this.loading = false;
13100
+ this.renderNow();
13101
+ }
13102
+ }
13103
+ }
13104
+ listLength() {
13105
+ if (this.section === "scopes") return this.scopeTree?.roots.length ?? 0;
13106
+ return (this.section === "activity" ? this.activity.length : this.nodes.length) + (this.nextCursor ? 1 : 0);
13107
+ }
13108
+ move(delta) {
13109
+ const length = this.detail ? this.detailTargets.length : this.listLength();
13110
+ if (length === 0) return;
13111
+ this.selectedIndex = (this.selectedIndex + delta + length) % length;
13112
+ this.renderNow();
13113
+ }
13114
+ async selectCurrent() {
13115
+ if (!await this.ensureIdentity()) return;
13116
+ if (this.detail) {
13117
+ const target = this.detailTargets[this.selectedIndex];
13118
+ if (target?.type === "node") await this.openNode(target.node);
13119
+ else if (target?.type === "more-records") await this.loadMoreRecords("about");
13120
+ else if (target?.type === "more-mentioning") await this.loadMoreRecords("mentioning");
13121
+ return;
13122
+ }
13123
+ if (this.section === "scopes") {
13124
+ const root = this.scopeTree?.roots[this.selectedIndex];
13125
+ if (!root?.available) return;
13126
+ this.level = root.level;
13127
+ this.section = "nodes";
13128
+ this.selectedIndex = 0;
13129
+ await this.loadSection();
13130
+ return;
13131
+ }
13132
+ const entries = this.section === "activity" ? this.activity : this.nodes;
13133
+ if (this.selectedIndex === entries.length && this.nextCursor) {
13134
+ await this.loadSection(true);
13135
+ return;
13136
+ }
13137
+ if (this.section === "activity") {
13138
+ const record = this.activity[this.selectedIndex]?.record;
13139
+ if (record) await this.openNode(record);
13140
+ return;
13141
+ }
13142
+ const record = this.nodes[this.selectedIndex];
13143
+ if (record) await this.openNode(record);
13144
+ }
13145
+ async changeSection(delta) {
13146
+ const index = SECTIONS.indexOf(this.section);
13147
+ this.section = SECTIONS[(index + delta + SECTIONS.length) % SECTIONS.length];
13148
+ this.detail = void 0;
13149
+ this.detailHistory = [];
13150
+ this.selectedIndex = 0;
13151
+ this.query = "";
13152
+ this.nodes = [];
13153
+ this.activity = [];
13154
+ this.nextCursor = void 0;
13155
+ if (this.section === "scopes") await this.refresh();
13156
+ else await this.loadSection();
13157
+ }
13158
+ async cycleNodeSort() {
13159
+ const index = NODE_SORTS.indexOf(this.nodeSort);
13160
+ this.nodeSort = NODE_SORTS[(index + 1) % NODE_SORTS.length];
13161
+ this.nodes = [];
13162
+ this.nextCursor = void 0;
13163
+ this.selectedIndex = 0;
13164
+ await this.loadSection();
13165
+ }
13166
+ handleInput(data) {
13167
+ const kb = getKeybindings();
13168
+ if (kb.matches(data, "tui.select.cancel")) this.onClose();
13169
+ else if (matchesKey(data, "shift+tab")) this.changeSection(-1);
13170
+ else if (matchesKey(data, "tab")) this.changeSection(1);
13171
+ else if (!this.detail && this.section === "nodes" && matchesKey(data, "ctrl+s")) this.cycleNodeSort();
13172
+ else if (kb.matches(data, "tui.select.up") || data === "k") this.move(-1);
13173
+ else if (kb.matches(data, "tui.select.down") || data === "j") this.move(1);
13174
+ else if (kb.matches(data, "tui.select.confirm")) this.selectCurrent();
13175
+ else if (data === "" || data === "\b") {
13176
+ if (this.detail) {
13177
+ this.detail = this.detailHistory.pop();
13178
+ this.selectedIndex = 0;
13179
+ this.renderNow();
13180
+ } else if (this.query && this.section === "nodes") {
13181
+ this.query = this.query.slice(0, -1);
13182
+ this.loadSection();
13183
+ } else if (this.section !== "scopes") {
13184
+ this.section = "scopes";
13185
+ this.selectedIndex = 0;
13186
+ this.refresh();
13187
+ }
13188
+ } else if (!this.detail && this.section === "nodes" && /^[\x20-\x7e]$/.test(data)) {
13189
+ this.query += data;
13190
+ this.loadSection();
13191
+ }
13192
+ }
13193
+ invalidate() {}
13194
+ breadcrumb(width) {
13195
+ const scopeId = this.scopeTree?.roots.find((root) => root.level === this.level)?.id ?? "unavailable";
13196
+ const detailName = (detail) => detail.value.node.name;
13197
+ const trail = this.detail ? [...this.detailHistory.map(detailName), detailName(this.detail)] : [];
13198
+ const suffix = ` / ${this.section[0].toUpperCase() + this.section.slice(1)}${trail.map((name) => ` / ${name}`).join("")}`;
13199
+ const prefix = `Knowledge / ${this.level}:`;
13200
+ const idWidth = Math.max(6, width - visibleWidth(prefix + suffix) - 2);
13201
+ return truncateAnsi(`${theme.bold("Knowledge")} / ${this.level}:${middleTruncate(scopeId, idWidth)}${suffix}`, width);
13202
+ }
13203
+ renderTabs(width) {
13204
+ return truncateAnsi(SECTIONS.map((section) => section === this.section ? theme.bold(theme.fg("accent", `[${section}]`)) : theme.fg("muted", section)).join(" "), width);
13205
+ }
13206
+ renderScopes(width) {
13207
+ if (!this.scopeTree) return [];
13208
+ return this.scopeTree.roots.map((root, index) => {
13209
+ const marker = index === this.selectedIndex ? "→" : " ";
13210
+ const availability = root.available ? "" : ` — ${root.reason ?? "unavailable"}`;
13211
+ const id = root.id ?? "unavailable";
13212
+ const prefix = `${marker} ${root.level.padEnd(8)} `;
13213
+ return truncateAnsi(`${prefix}${middleTruncate(id, Math.max(1, width - prefix.length - availability.length))}${availability}`, width);
13214
+ });
13215
+ }
13216
+ renderRecordList(width) {
13217
+ const lines = [];
13218
+ let lastRole = null;
13219
+ this.nodes.forEach((record, index) => {
13220
+ if (this.section === "nodes") {
13221
+ const role = graphRole(record);
13222
+ if (role !== lastRole) {
13223
+ lastRole = role;
13224
+ const group = ROLE_GROUPS.find((entry) => entry.role === role);
13225
+ if (lines.length > 0) lines.push("");
13226
+ lines.push(theme.fg("muted", group ? group.label : "Other"));
13227
+ }
13228
+ }
13229
+ const marker = index === this.selectedIndex ? "→" : " ";
13230
+ const kind = record.kind ? ` (${record.kind})` : "";
13231
+ const badge = scopeLabel(record, this.level);
13232
+ lines.push(truncateAnsi(`${marker} ${record.name}${kind}${countsBadge(record)} ${theme.fg("muted", badge)}`, width));
13233
+ });
13234
+ if (this.nextCursor) lines.push(`${this.selectedIndex === this.nodes.length ? "→" : " "} Load more…`);
13235
+ if (!this.loading && lines.length === 0) lines.push(theme.fg("muted", `No ${this.section} found.`));
13236
+ return lines;
13237
+ }
13238
+ renderActivity(width) {
13239
+ const lines = this.activity.map((event, index) => {
13240
+ const marker = index === this.selectedIndex ? "→" : " ";
13241
+ const target = event.record?.name ?? `${event.recordType} (unavailable)`;
13242
+ const badge = event.record ? scopeLabel(event.record, this.level) : `[${event.scope.level}]`;
13243
+ return truncateAnsi(`${marker} ${event.action}: ${target} ${theme.fg("muted", badge)}`, width);
13244
+ });
13245
+ if (this.nextCursor) lines.push(`${this.selectedIndex === this.activity.length ? "→" : " "} Load more…`);
13246
+ if (!this.loading && lines.length === 0) lines.push(theme.fg("muted", "No knowledge activity found."));
13247
+ return lines;
13248
+ }
13249
+ selectableLine(text, target, width) {
13250
+ return truncateAnsi(`${this.detailTargets.push(target) - 1 === this.selectedIndex ? "→" : " "} ${text}`, width);
13251
+ }
13252
+ renderNodeDetail(detail, width) {
13253
+ this.detailTargets = [];
13254
+ const counts = detail.relationshipCounts;
13255
+ const role = graphRole(detail.node);
13256
+ const roleSummary = `${role ? `${roleLabel(role)} · ` : ""}${counts.records} records · ${counts.outgoing} outgoing · ${counts.incoming} incoming${counts.sampled ? " (sampled)" : ""}`;
13257
+ const lines = [`${theme.bold(detail.node.name)} ${detail.node.kind ?? "node"} ${scopeLabel(detail.node, this.level)} v${detail.node.version}`, theme.fg("muted", roleSummary)];
13258
+ if (detail.content) {
13259
+ lines.push("", theme.bold("Content"));
13260
+ const contentLines = wrapTextWithAnsi(detail.content, Math.max(MIN_CONTENT_WIDTH, width - 2)).slice(0, MAX_BODY_LINES);
13261
+ lines.push(...contentLines.map((line) => truncateAnsi(` ${line}`, width)));
13262
+ if (detail.contentTruncated || contentLines.length === MAX_BODY_LINES) lines.push(theme.fg("muted", " … preview truncated"));
13263
+ }
13264
+ lines.push("", theme.bold(`Knowledge (${detail.records.length})`), ...detail.records.slice(0, 8).map((record) => truncateAnsi(` • ${record.text} [${record.scope.level}]`, width)));
13265
+ if (detail.recordsNextCursor) lines.push(this.selectableLine("Load more knowledge…", { type: "more-records" }, width));
13266
+ lines.push("", theme.bold(`Mentioning knowledge (${detail.mentioningRecords.length})`));
13267
+ lines.push(...detail.mentioningRecords.slice(0, 6).map((record) => truncateAnsi(` • ${record.text} [${record.scope.level}]`, width)));
13268
+ if (detail.mentioningRecordsNextCursor) lines.push(this.selectableLine("Load more mentioning knowledge…", { type: "more-mentioning" }, width));
13269
+ lines.push("", theme.bold(`Outgoing links${detail.outgoingTargets.partial ? " (partial)" : ""}`));
13270
+ for (const related of detail.outgoingTargets.nodes) lines.push(this.selectableLine(`→ ${related.name} ${scopeLabel(related, this.level)}`, {
13271
+ type: "node",
13272
+ node: related
13273
+ }, width));
13274
+ if (detail.outgoingTargets.nodes.length === 0) lines.push(theme.fg("muted", " No outgoing links."));
13275
+ lines.push("", theme.bold(`Referenced by${detail.incomingParents.partial ? " (partial)" : ""}`));
13276
+ for (const parent of detail.incomingParents.nodes) lines.push(this.selectableLine(`← ${parent.name} ${scopeLabel(parent, this.level)}`, {
13277
+ type: "node",
13278
+ node: parent
13279
+ }, width));
13280
+ if (detail.incomingParents.nodes.length === 0) lines.push(theme.fg("muted", " No incoming parents."));
13281
+ return lines;
13282
+ }
13283
+ render(width) {
13284
+ const contentWidth = Math.max(MIN_CONTENT_WIDTH, width - 4);
13285
+ const lines = [
13286
+ this.breadcrumb(contentWidth),
13287
+ this.renderTabs(contentWidth),
13288
+ ""
13289
+ ];
13290
+ if (this.section === "nodes" && !this.detail) {
13291
+ const coverage = this.nodeCoverage === "recent-window" ? " · recent window" : "";
13292
+ const label = this.nodeSort[0].toUpperCase() + this.nodeSort.slice(1);
13293
+ lines.push(theme.fg("muted", `Sort: ${label}${coverage} · Ctrl+S change`), "");
13294
+ }
13295
+ if (this.query && !this.detail) lines.push(truncateAnsi(`Filter: ${this.query}`, contentWidth), "");
13296
+ if (this.error) lines.push(theme.fg("error", truncateAnsi(`Error: ${this.error}`, contentWidth)), "");
13297
+ if (this.detail) lines.push(...this.renderNodeDetail(this.detail.value, contentWidth));
13298
+ else if (this.section === "scopes") lines.push(...this.renderScopes(contentWidth));
13299
+ else if (this.section === "activity") lines.push(...this.renderActivity(contentWidth));
13300
+ else lines.push(...this.renderRecordList(contentWidth));
13301
+ if (this.loading) lines.push("", theme.fg("muted", "Loading…"));
13302
+ lines.push("", theme.fg("dim", "Tab sections · ↑↓/jk select · Enter open · Backspace back · Esc close"));
13303
+ return lines.map((line) => truncateAnsi(line, contentWidth));
13304
+ }
13305
+ };
13306
+ //#endregion
13307
+ //#region src/tui/commands/knowledge-command.ts
13308
+ async function handleKnowledgeCommand(ctx) {
13309
+ if (!isSubconsciousEnabled()) {
13310
+ ctx.showError("Unknown command: /knowledge");
13311
+ return;
13312
+ }
13313
+ if (!ctx.knowledgeInspector) {
13314
+ ctx.showError("Knowledge inspection is unavailable. Enable MastraCode memory with a knowledge-capable store.");
13315
+ return;
13316
+ }
13317
+ return new Promise((resolve) => {
13318
+ const browser = new KnowledgeBrowserComponent({
13319
+ tui: ctx.state.ui,
13320
+ inspector: ctx.knowledgeInspector,
13321
+ onClose: () => {
13322
+ ctx.state.ui.hideOverlay();
13323
+ resolve();
13324
+ }
13325
+ });
13326
+ showModalOverlay(ctx.state.ui, browser, {
13327
+ widthPercent: .9,
13328
+ maxWidth: 140,
13329
+ maxHeight: "85%"
13330
+ });
13331
+ browser.focused = true;
13332
+ });
13333
+ }
13334
+ //#endregion
12748
13335
  //#region src/tui/components/settings.ts
12749
13336
  /**
12750
13337
  * General settings component.
@@ -16081,6 +16668,9 @@ async function dispatchSlashCommand(input, state, buildCtx) {
16081
16668
  case "om":
16082
16669
  await handleOMCommand(ctx);
16083
16670
  return true;
16671
+ case "knowledge":
16672
+ await handleKnowledgeCommand(ctx);
16673
+ return true;
16084
16674
  case "think":
16085
16675
  await handleThinkCommand(ctx, args);
16086
16676
  return true;
@@ -20704,6 +21294,10 @@ function setupAutocomplete(state) {
20704
21294
  name: "om",
20705
21295
  description: "Alias for /memory"
20706
21296
  },
21297
+ ...isSubconsciousEnabled() ? [{
21298
+ name: "knowledge",
21299
+ description: "Browse scoped Subconscious knowledge"
21300
+ }] : [],
20707
21301
  {
20708
21302
  name: "think",
20709
21303
  description: "Session thinking override (off|low|medium|high|xhigh|max|default|status)"
@@ -22119,6 +22713,7 @@ var MastraTUI = class MastraTUI {
22119
22713
  pluginManager: this.state.pluginManager,
22120
22714
  analytics: this.state.analytics,
22121
22715
  authStorage: this.state.authStorage,
22716
+ knowledgeInspector: this.state.options.knowledgeInspector,
22122
22717
  customSlashCommands: this.state.customSlashCommands,
22123
22718
  showInfo: (msg) => showInfo(this.state, msg),
22124
22719
  showError: (msg) => showError(this.state, msg),
@@ -22527,4 +23122,4 @@ var MastraTUI = class MastraTUI {
22527
23122
  //#endregion
22528
23123
  export { mastraBrand as _, OMProgressComponent as a, ToolExecutionComponentEnhanced as c, detectTerminalTheme as d, applyThemeMode as f, mastra as g, getThemeMode as h, LoginDialogComponent as i, AssistantMessageComponent as l, getMarkdownTheme as m, createTUIState as n, formatOMStatus as o, getEditorTheme as p, LoginSelectorComponent as r, UserMessageComponent as s, MastraTUI as t, ModelSelectorComponent as u, restoreTerminalForeground as v, theme as y };
22529
23124
 
22530
- //# sourceMappingURL=tui-D-aJNadI.js.map
23125
+ //# sourceMappingURL=tui-BB2N6Mud.js.map