@trops/dash-core 0.1.646 → 0.1.647

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.
@@ -993,6 +993,8 @@ const BOTS_DISMISS_LEAD_INTRO$1 = "bots-dismiss-lead-intro";
993
993
  const BOTS_GET_SETTINGS$1 = "bots-get-settings";
994
994
  const BOTS_SET_SETTINGS$1 = "bots-set-settings";
995
995
  const BOTS_ASK_LEAD$1 = "bots-ask-lead";
996
+ // Bots view (TEAM-011): a bot run history.
997
+ const BOTS_GET_RUNS$1 = "bots-get-runs";
996
998
 
997
999
  // --- Main → Renderer (send) ---
998
1000
  const BOT_STREAM$2 = "bot-stream"; // { botId, event: BotEvent }
@@ -1029,6 +1031,7 @@ var botEvents$2 = {
1029
1031
  BOTS_GET_SETTINGS: BOTS_GET_SETTINGS$1,
1030
1032
  BOTS_SET_SETTINGS: BOTS_SET_SETTINGS$1,
1031
1033
  BOTS_ASK_LEAD: BOTS_ASK_LEAD$1,
1034
+ BOTS_GET_RUNS: BOTS_GET_RUNS$1,
1032
1035
  BOT_STREAM: BOT_STREAM$2,
1033
1036
  BOT_APPROVAL_PENDING: BOT_APPROVAL_PENDING$2,
1034
1037
  BOT_BUDGET_ALERT: BOT_BUDGET_ALERT$2,
@@ -74489,6 +74492,9 @@ const { botRef } = botEvents;
74489
74492
  // bound (full history migrates to SQLite in a later phase).
74490
74493
  const MAX_RUNS_PER_BOT = 100;
74491
74494
 
74495
+ // Run fields that can hold sensitive text — sealed at rest via secretBox.
74496
+ const SEALED_RUN_FIELDS = ["output", "prompt"];
74497
+
74492
74498
  let BotStore$1 = class BotStore {
74493
74499
  /**
74494
74500
  * @param {{ persistence: {read: () => object, write: (o: object) => void},
@@ -74663,11 +74669,16 @@ let BotStore$1 = class BotStore {
74663
74669
  const data = this._load();
74664
74670
  if (!data.bots[id]) throw new Error(`BotStore.appendRun: no bot "${id}"`);
74665
74671
  const entry = { ...run, at: (run && run.at) || this._now() };
74666
- // The run's answer can hold sensitive text (emails…) — sealed at rest.
74667
- const stored =
74668
- this._box && typeof entry.output === "string"
74669
- ? { ...entry, output: this._box.seal(entry.output) }
74670
- : entry;
74672
+ // The run's answer and prompt can hold sensitive text (emails, what the
74673
+ // user asked) — sealed at rest. Tool summaries (names only) stay plain.
74674
+ const stored = { ...entry };
74675
+ if (this._box) {
74676
+ for (const field of SEALED_RUN_FIELDS) {
74677
+ if (typeof stored[field] === "string") {
74678
+ stored[field] = this._box.seal(stored[field]);
74679
+ }
74680
+ }
74681
+ }
74671
74682
  const runs = data.runs[id] || [];
74672
74683
  runs.push(stored);
74673
74684
  data.runs[id] = runs.slice(-MAX_RUNS_PER_BOT);
@@ -74676,20 +74687,25 @@ let BotStore$1 = class BotStore {
74676
74687
  }
74677
74688
 
74678
74689
  /**
74679
- * @returns {object[]} run records for a bot, oldest first. Answers that
74680
- * can't be decrypted (keychain reset, another app identity) come back as
74681
- * `output: null, outputUnavailable: true`.
74690
+ * @returns {object[]} run records for a bot, oldest first. Sealed fields
74691
+ * that can't be decrypted (keychain reset, another app identity) come back
74692
+ * as null, with `outputUnavailable: true` when the answer is affected.
74682
74693
  */
74683
74694
  getRuns(id) {
74684
74695
  const { runs } = this._load();
74685
74696
  const list = runs[id] || [];
74686
74697
  if (!this._box) return list;
74687
74698
  return list.map((r) => {
74688
- if (!r || typeof r.output !== "string") return r;
74689
- const output = this._box.open(r.output);
74690
- return output === null
74691
- ? { ...r, output: null, outputUnavailable: true }
74692
- : { ...r, output };
74699
+ if (!r) return r;
74700
+ const out = { ...r };
74701
+ for (const field of SEALED_RUN_FIELDS) {
74702
+ if (typeof out[field] !== "string") continue;
74703
+ out[field] = this._box.open(out[field]);
74704
+ if (out[field] === null && field === "output") {
74705
+ out.outputUnavailable = true;
74706
+ }
74707
+ }
74708
+ return out;
74693
74709
  });
74694
74710
  }
74695
74711
 
@@ -76125,6 +76141,11 @@ let BotRunner$1 = class BotRunner {
76125
76141
  // The run's answer (its text), kept on the run record — what a team lead
76126
76142
  // reads back. Capped to the last 8 KB; the store seals it at rest.
76127
76143
  const answer = [];
76144
+ // Tool-call summary for the conversation view: tool, provider, ok —
76145
+ // never arguments or results (they can hold email content).
76146
+ const toolCalls = [];
76147
+ const callIndex = new Map();
76148
+ let providerOf = () => null;
76128
76149
 
76129
76150
  try {
76130
76151
  const profile = await this._resolveRunProfile(bot);
@@ -76135,6 +76156,13 @@ let BotRunner$1 = class BotRunner {
76135
76156
  }
76136
76157
 
76137
76158
  const { tools, resolveServer } = await this._resolveTools(bot);
76159
+ providerOf = (name) => {
76160
+ try {
76161
+ return resolveServer(name) || null;
76162
+ } catch (_e) {
76163
+ return null;
76164
+ }
76165
+ };
76138
76166
 
76139
76167
  const requestPermission = this._makeRequestPermission({
76140
76168
  botId,
@@ -76201,6 +76229,17 @@ let BotRunner$1 = class BotRunner {
76201
76229
  for await (const event of engine.run(ctx)) {
76202
76230
  emit(event);
76203
76231
  if (event.type === "text" && event.text) answer.push(event.text);
76232
+ if (event.type === "tool_call" && event.name) {
76233
+ // Bridged tools arrive as "mcp__bot-mcp__<tool>" on the agent engine.
76234
+ const tool = String(event.name).replace(
76235
+ /^mcp__[^_]+(?:-[^_]+)*__/,
76236
+ "",
76237
+ );
76238
+ callIndex.set(event.id, toolCalls.length);
76239
+ toolCalls.push({ tool, provider: providerOf(tool), ok: null });
76240
+ } else if (event.type === "tool_result" && callIndex.has(event.id)) {
76241
+ toolCalls[callIndex.get(event.id)].ok = !event.isError;
76242
+ }
76204
76243
  if (event.type === "session") {
76205
76244
  this._store.saveSession(botId, engine.id, event.session);
76206
76245
  } else if (event.type === "done") {
@@ -76230,6 +76269,11 @@ let BotRunner$1 = class BotRunner {
76230
76269
  usage,
76231
76270
  error: errorMessage,
76232
76271
  output: truncateText(answer.join("")),
76272
+ // The conversation turn (Bots view, TEAM-011). The store seals the
76273
+ // prompt at rest like the answer.
76274
+ prompt: truncateText(opts.prompt || ""),
76275
+ continued: !!opts.continueSession,
76276
+ toolCalls,
76233
76277
  };
76234
76278
  this._store.appendRun(botId, runRecord);
76235
76279
 
@@ -77905,8 +77949,27 @@ const botController$1 = {
77905
77949
  return this._store.delete(botId);
77906
77950
  },
77907
77951
 
77908
- run(botId, prompt) {
77909
- return this._run(botId, { prompt, trigger: "manual" });
77952
+ /**
77953
+ * Run a bot. `continueConversation` resumes its last session — a reply in
77954
+ * the Bots view (TEAM-011) — logged with trigger "reply".
77955
+ */
77956
+ run(botId, prompt, { continueConversation = false } = {}) {
77957
+ return this._run(botId, {
77958
+ prompt,
77959
+ trigger: continueConversation ? "reply" : "manual",
77960
+ continueSession: !!continueConversation,
77961
+ });
77962
+ },
77963
+
77964
+ /**
77965
+ * A bot's latest runs, oldest first — prompt, answer (decrypted by the
77966
+ * store), tool-call summary, status. Feeds the Bots view's conversation
77967
+ * and Activity tab.
77968
+ */
77969
+ getRuns(botId, { limit = 50 } = {}) {
77970
+ const runs = this._store.getRuns(botId) || [];
77971
+ const n = Math.max(1, Math.min(100, Number(limit) || 50));
77972
+ return runs.slice(-n);
77910
77973
  },
77911
77974
 
77912
77975
  // ---- Team leads (bot-teams TEAM-002 / TEAM-003) --------------------------
@@ -82317,6 +82380,7 @@ const {
82317
82380
  BOTS_GET_SETTINGS,
82318
82381
  BOTS_SET_SETTINGS,
82319
82382
  BOTS_ASK_LEAD,
82383
+ BOTS_GET_RUNS,
82320
82384
  BOT_STREAM,
82321
82385
  BOT_APPROVAL_PENDING,
82322
82386
  BOT_BUDGET_ALERT,
@@ -82341,7 +82405,12 @@ const botApi$1 = {
82341
82405
  delete: (botId) => ipcRenderer$3.invoke(BOTS_DELETE, { botId }),
82342
82406
 
82343
82407
  /** Start a run. Stream events arrive via onStream(). */
82344
- run: (botId, prompt) => ipcRenderer$3.invoke(BOTS_RUN, { botId, prompt }),
82408
+ /** Start a run; `continueConversation` replies within its last session. */
82409
+ run: (botId, prompt, continueConversation = false) =>
82410
+ ipcRenderer$3.invoke(BOTS_RUN, { botId, prompt, continueConversation }),
82411
+ /** The bot's latest runs (oldest first), answers decrypted. */
82412
+ getRuns: (botId, limit) =>
82413
+ ipcRenderer$3.invoke(BOTS_GET_RUNS, { botId, limit }),
82345
82414
  stop: (botId) => ipcRenderer$3.invoke(BOTS_STOP, { botId }),
82346
82415
 
82347
82416
  /** Resolve a pending approval. decision: { allow, reason? } */