@runfusion/fusion 0.14.1 → 0.14.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.
Files changed (38) hide show
  1. package/dist/bin.js +195 -99
  2. package/dist/client/assets/{AgentDetailView-B3KAsP2O.js → AgentDetailView-C2Iik3Qf.js} +1 -1
  3. package/dist/client/assets/{AgentsView-DoXb_amw.js → AgentsView-DkX0tzrN.js} +3 -3
  4. package/dist/client/assets/ChatView-CEm2Hw6m.js +1 -0
  5. package/dist/client/assets/{DevServerView-DbgM4tlT.js → DevServerView-Bumvo_ge.js} +1 -1
  6. package/dist/client/assets/{DirectoryPicker-DfmtfMiu.js → DirectoryPicker-CXN11cBp.js} +1 -1
  7. package/dist/client/assets/{DocumentsView-_-Efkx_W.js → DocumentsView-B71IqAxA.js} +1 -1
  8. package/dist/client/assets/{InsightsView-DUjcfW53.js → InsightsView-Bs4Rldu6.js} +1 -1
  9. package/dist/client/assets/{MemoryView-DxMPBb0q.js → MemoryView-Bs7b_L2Q.js} +1 -1
  10. package/dist/client/assets/{NodesView-BEBTI15s.js → NodesView-BvAGTXbO.js} +1 -1
  11. package/dist/client/assets/{PiExtensionsManager-BpMYhHH_.js → PiExtensionsManager-3Kcc4uhA.js} +2 -2
  12. package/dist/client/assets/{PluginManager-CPv7yQd3.js → PluginManager-Ch-Xynlm.js} +1 -1
  13. package/dist/client/assets/{ResearchView-BrFvdyXT.js → ResearchView-Bj6Saqf6.js} +1 -1
  14. package/dist/client/assets/{RoadmapsView-BDjLrtcj.js → RoadmapsView-9qT8Vwd0.js} +1 -1
  15. package/dist/client/assets/{SettingsModal-CxDxiTRy.js → SettingsModal-D4ERGQNQ.js} +1 -1
  16. package/dist/client/assets/SettingsModal-Zo5qDGOq.js +31 -0
  17. package/dist/client/assets/{SetupWizardModal-DFUA4X3z.js → SetupWizardModal-Dv0rX2_o.js} +1 -1
  18. package/dist/client/assets/{SkillMultiselect-BUWe5ujb.js → SkillMultiselect-CSkXQzdv.js} +1 -1
  19. package/dist/client/assets/{SkillsView-RAkqGX3y.js → SkillsView-2srXMOzj.js} +1 -1
  20. package/dist/client/assets/{TodoView-Ceb0wrg1.js → TodoView-CxPPIvw2.js} +1 -1
  21. package/dist/client/assets/{folder-open-DcM-Vd6r.js → folder-open-FA1PwpXV.js} +1 -1
  22. package/dist/client/assets/{index-DH3aprf6.js → index-CEavim6l.js} +150 -149
  23. package/dist/client/assets/index-D1gTSlYB.css +1 -0
  24. package/dist/client/assets/{list-checks-ByGHVQpZ.js → list-checks-6EktkUso.js} +1 -1
  25. package/dist/client/assets/{star-DlEYI8GL.js → star-B6Th07jw.js} +1 -1
  26. package/dist/client/assets/{upload-DKshabz-.js → upload-BJwuErhV.js} +1 -1
  27. package/dist/client/assets/{users-X6tYPPBV.js → users-BrnPTF8H.js} +1 -1
  28. package/dist/client/index.html +2 -2
  29. package/dist/client/version.json +1 -1
  30. package/dist/extension.js +191 -95
  31. package/dist/pi-claude-cli/package.json +1 -1
  32. package/dist/pi-claude-cli/src/__tests__/event-bridge.test.ts +107 -0
  33. package/dist/pi-claude-cli/src/event-bridge.ts +48 -4
  34. package/package.json +1 -1
  35. package/skill/fusion/references/engine-tools.md +0 -1
  36. package/dist/client/assets/ChatView-BJ2c7wvd.js +0 -1
  37. package/dist/client/assets/SettingsModal-Cd-QGB0C.js +0 -31
  38. package/dist/client/assets/index-C1prPuSl.css +0 -1
@@ -1,4 +1,4 @@
1
- import{c}from"./index-DH3aprf6.js";/**
1
+ import{c}from"./index-CEavim6l.js";/**
2
2
  * @license lucide-react v1.7.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-DH3aprf6.js";/**
1
+ import{c as a}from"./index-CEavim6l.js";/**
2
2
  * @license lucide-react v1.7.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as a}from"./index-DH3aprf6.js";/**
1
+ import{c as a}from"./index-CEavim6l.js";/**
2
2
  * @license lucide-react v1.7.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as e}from"./index-DH3aprf6.js";/**
1
+ import{c as e}from"./index-CEavim6l.js";/**
2
2
  * @license lucide-react v1.7.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -92,11 +92,11 @@
92
92
  }
93
93
  })();
94
94
  </script>
95
- <script type="module" crossorigin src="/assets/index-DH3aprf6.js"></script>
95
+ <script type="module" crossorigin src="/assets/index-CEavim6l.js"></script>
96
96
  <link rel="modulepreload" crossorigin href="/assets/vendor-react-K0fH_qHe.js">
97
97
  <link rel="modulepreload" crossorigin href="/assets/vendor-xterm-DzcZoU0P.js">
98
98
  <link rel="stylesheet" crossorigin href="/assets/vendor-xterm-LZoznX6r.css">
99
- <link rel="stylesheet" crossorigin href="/assets/index-C1prPuSl.css">
99
+ <link rel="stylesheet" crossorigin href="/assets/index-D1gTSlYB.css">
100
100
  </head>
101
101
  <body>
102
102
  <div id="root"></div>
@@ -1 +1 @@
1
- {"version":"monkm5qv-26aba899"}
1
+ {"version":"monmfp1r-d0470197"}
package/dist/extension.js CHANGED
@@ -37491,6 +37491,60 @@ var init_plugin_loader = __esm({
37491
37491
  }
37492
37492
  return runtimes;
37493
37493
  }
37494
+ /**
37495
+ * Get all skill contributions from loaded plugins.
37496
+ */
37497
+ getPluginSkills() {
37498
+ const skills = [];
37499
+ for (const [pluginId, plugin4] of this.plugins) {
37500
+ if (plugin4.skills) {
37501
+ for (const skill of plugin4.skills) {
37502
+ skills.push({ pluginId, skill });
37503
+ }
37504
+ }
37505
+ }
37506
+ return skills;
37507
+ }
37508
+ /**
37509
+ * Get all workflow step contributions from loaded plugins.
37510
+ */
37511
+ getPluginWorkflowSteps() {
37512
+ const steps = [];
37513
+ for (const [pluginId, plugin4] of this.plugins) {
37514
+ if (plugin4.workflowSteps) {
37515
+ for (const step of plugin4.workflowSteps) {
37516
+ steps.push({ pluginId, step });
37517
+ }
37518
+ }
37519
+ }
37520
+ return steps;
37521
+ }
37522
+ /**
37523
+ * Get all prompt contributions from loaded plugins.
37524
+ */
37525
+ getPluginPromptContributions() {
37526
+ const contributions = [];
37527
+ for (const [pluginId, plugin4] of this.plugins) {
37528
+ if (plugin4.promptContributions) {
37529
+ for (const contribution of plugin4.promptContributions.contributions) {
37530
+ contributions.push({ pluginId, contribution, config: plugin4.promptContributions });
37531
+ }
37532
+ }
37533
+ }
37534
+ return contributions;
37535
+ }
37536
+ /**
37537
+ * Get all setup metadata and hooks from loaded plugins.
37538
+ */
37539
+ getPluginSetupInfo() {
37540
+ const setups = [];
37541
+ for (const [pluginId, plugin4] of this.plugins) {
37542
+ if (plugin4.setup) {
37543
+ setups.push({ pluginId, manifest: plugin4.setup.manifest, hooks: plugin4.setup.hooks });
37544
+ }
37545
+ }
37546
+ return setups;
37547
+ }
37494
37548
  /**
37495
37549
  * Get all loaded plugin instances.
37496
37550
  */
@@ -55419,65 +55473,6 @@ ${lines.join("\n")}`
55419
55473
  }
55420
55474
  };
55421
55475
  }
55422
- function createIdentityTool({ agent, resolvedInstructions }) {
55423
- const identityParams = Type.Object({});
55424
- return {
55425
- name: "fn_identity",
55426
- label: "Identity Check",
55427
- description: "Return a structured summary of which soul, instructions, and memory are loaded for this heartbeat tick. Call this FIRST before any other tool.",
55428
- parameters: identityParams,
55429
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
55430
- execute: async (_id, _params, _signal, _onUpdate, _ctx) => {
55431
- const PREVIEW_CHARS = 500;
55432
- const INSTRUCTIONS_PREVIEW_CHARS = 1e3;
55433
- const MEMORY_PREVIEW_CHARS = 1e3;
55434
- const soulPresent = typeof agent.soul === "string" && agent.soul.trim().length > 0;
55435
- const instructionsPresent = resolvedInstructions.trim().length > 0;
55436
- const memoryPresent = typeof agent.memory === "string" && agent.memory.trim().length > 0;
55437
- const soulPreview = soulPresent ? agent.soul.slice(0, PREVIEW_CHARS) : "";
55438
- const instructionsPreview = instructionsPresent ? resolvedInstructions.slice(0, INSTRUCTIONS_PREVIEW_CHARS) : "";
55439
- const memoryPreview = memoryPresent ? agent.memory.slice(0, MEMORY_PREVIEW_CHARS) : "";
55440
- const result = {
55441
- agentId: agent.id,
55442
- name: agent.name,
55443
- role: agent.role,
55444
- soulPresent,
55445
- instructionsPresent,
55446
- memoryPresent,
55447
- soulPreview,
55448
- instructionsPreview,
55449
- memoryPreview
55450
- };
55451
- const lines = [
55452
- `agentId: ${result.agentId}`,
55453
- `name: ${result.name}`,
55454
- `role: ${result.role}`,
55455
- `soul: ${result.soulPresent ? "loaded" : "absent"}`,
55456
- `instructions: ${result.instructionsPresent ? "loaded" : "absent"}`,
55457
- `memory: ${result.memoryPresent ? "loaded" : "absent"}`
55458
- ];
55459
- if (result.soulPresent && result.soulPreview) {
55460
- lines.push(`
55461
- Soul preview (first ${PREVIEW_CHARS} chars):
55462
- ${result.soulPreview}`);
55463
- }
55464
- if (result.instructionsPresent && result.instructionsPreview) {
55465
- lines.push(`
55466
- Instructions preview (first ${INSTRUCTIONS_PREVIEW_CHARS} chars):
55467
- ${result.instructionsPreview}`);
55468
- }
55469
- if (result.memoryPresent && result.memoryPreview) {
55470
- lines.push(`
55471
- Memory preview (first ${MEMORY_PREVIEW_CHARS} chars):
55472
- ${result.memoryPreview}`);
55473
- }
55474
- return {
55475
- content: [{ type: "text", text: lines.join("\n") }],
55476
- details: result
55477
- };
55478
- }
55479
- };
55480
- }
55481
55476
  var taskCreateParams, taskLogParams, taskDocumentWriteParams, taskDocumentReadParams, reflectOnPerformanceParams, listAgentsParams, delegateTaskParams, sendMessageParams, readMessagesParams, memorySearchParams, memoryGetParams, researchRunParams, researchListParams, researchGetParams, researchCancelParams, memoryAppendParams, log10, AGENT_MEMORY_ROOT2, AGENT_MEMORY_FILENAME2, AGENT_DREAMS_FILENAME2, agentQmdRefreshState, AGENT_QMD_REFRESH_INTERVAL_MS, DAILY_AGENT_MEMORY_RE2;
55482
55477
  var init_agent_tools = __esm({
55483
55478
  "../engine/src/agent-tools.ts"() {
@@ -71983,6 +71978,7 @@ Rules:
71983
71978
 
71984
71979
  // ../engine/src/agent-heartbeat.ts
71985
71980
  import { Type as Type6 } from "@mariozechner/pi-ai";
71981
+ import { createHash as createHash5 } from "node:crypto";
71986
71982
  function isBlockedStateDuplicate(current, previous) {
71987
71983
  return current.blockedBy === previous.blockedBy && current.contextHash === previous.contextHash;
71988
71984
  }
@@ -71992,39 +71988,30 @@ function truncatePrompt(text, maxChars) {
71992
71988
 
71993
71989
  ... (truncated, ${text.length} chars)`;
71994
71990
  }
71991
+ function shortContentHash(value) {
71992
+ return createHash5("sha256").update(value).digest("hex").slice(0, 8);
71993
+ }
71995
71994
  function buildIdentitySnapshot(args) {
71996
71995
  const { agent, resolvedInstructions } = args;
71997
- const SOUL_PREVIEW = 500;
71998
- const INSTR_PREVIEW = 1e3;
71999
- const MEM_PREVIEW = 1e3;
72000
- const soulPresent = typeof agent.soul === "string" && agent.soul.trim().length > 0;
72001
- const instrPresent = resolvedInstructions.trim().length > 0;
72002
- const memPresent = typeof agent.memory === "string" && agent.memory.trim().length > 0;
72003
- const lines = [
71996
+ const soulTrimmed = typeof agent.soul === "string" ? agent.soul.trim() : "";
71997
+ const instrTrimmed = resolvedInstructions.trim();
71998
+ const memTrimmed = typeof agent.memory === "string" ? agent.memory.trim() : "";
71999
+ const formatField = (trimmed) => {
72000
+ if (!trimmed) return "absent";
72001
+ return `loaded (${trimmed.length} chars, sha256:${shortContentHash(trimmed)})`;
72002
+ };
72003
+ return [
72004
72004
  "## Identity Snapshot",
72005
72005
  "",
72006
- "Verify these match what you expect. Surface any anomalies in your first text output before acting.",
72006
+ "Full content is in the Custom Instructions section of your system prompt. Surface anomalies in your first text output before acting.",
72007
72007
  "",
72008
72008
  `- agentId: ${agent.id}`,
72009
72009
  `- name: ${agent.name}`,
72010
72010
  `- role: ${agent.role}`,
72011
- `- soul: ${soulPresent ? "loaded" : "absent"}`,
72012
- `- instructions: ${instrPresent ? "loaded" : "absent"}`,
72013
- `- memory: ${memPresent ? "loaded" : "absent"}`
72014
- ];
72015
- if (soulPresent) {
72016
- const preview = agent.soul.trim().slice(0, SOUL_PREVIEW);
72017
- lines.push("", `### Soul (first ${SOUL_PREVIEW} chars)`, preview);
72018
- }
72019
- if (instrPresent) {
72020
- const preview = resolvedInstructions.trim().slice(0, INSTR_PREVIEW);
72021
- lines.push("", `### Instructions (first ${INSTR_PREVIEW} chars)`, preview);
72022
- }
72023
- if (memPresent) {
72024
- const preview = agent.memory.trim().slice(0, MEM_PREVIEW);
72025
- lines.push("", `### Memory (first ${MEM_PREVIEW} chars)`, preview);
72026
- }
72027
- return lines.join("\n");
72011
+ `- soul: ${formatField(soulTrimmed)}`,
72012
+ `- instructions: ${formatField(instrTrimmed)}`,
72013
+ `- memory: ${formatField(memTrimmed)}`
72014
+ ].join("\n");
72028
72015
  }
72029
72016
  async function getHeartbeatMemorySettings(taskStore) {
72030
72017
  const maybeGetSettings = taskStore.getSettings;
@@ -72206,9 +72193,8 @@ When sending messages:
72206
72193
  1. **Identity & context** \u2014 review the **Identity Snapshot** at the top of
72207
72194
  this prompt. Confirm your role, soul, instructions, and memory match what
72208
72195
  you expect, and surface any anomalies in your first text output before
72209
- doing anything else. (If fn_identity is available in your runtime you may
72210
- also call it for full structured detail; the snapshot above is the
72211
- authoritative source.)
72196
+ doing anything else. The full content is in the Custom Instructions
72197
+ section of your system prompt.
72212
72198
  2. **Inbox** \u2014 when fn_read_messages is available, call it. Process any pending
72213
72199
  messages first; reply with reply_to_message_id when answering.
72214
72200
  3. **Wake delta** \u2014 read the Wake Delta block above. The wake reason is the
@@ -72234,9 +72220,8 @@ a bug. Do not loop on the same plan across heartbeats without recording why.`;
72234
72220
  1. **Identity & context** \u2014 review the **Identity Snapshot** at the top of
72235
72221
  this prompt. Confirm your role, soul, instructions, and memory match what
72236
72222
  you expect, and surface any anomalies in your first text output before
72237
- doing anything else. (If fn_identity is available in your runtime you may
72238
- also call it for full structured detail; the snapshot above is the
72239
- authoritative source.)
72223
+ doing anything else. The full content is in the Custom Instructions
72224
+ section of your system prompt.
72240
72225
  2. **Inbox** \u2014 when fn_read_messages is available, call it. Process any pending
72241
72226
  messages first; reply with reply_to_message_id when answering.
72242
72227
  3. **Wake delta** \u2014 read the Wake Delta block above. The wake reason is the
@@ -73038,7 +73023,6 @@ not loop on the same plan across heartbeats without recording why.`;
73038
73023
  baseHeartbeatSystemPrompt,
73039
73024
  [resolvedInstructionsForIdentity, memoryInstructions].filter((part) => part.trim()).join("\n\n")
73040
73025
  );
73041
- heartbeatTools.push(createIdentityTool({ agent, resolvedInstructions: resolvedInstructionsForIdentity }));
73042
73026
  heartbeatTools.push(heartbeatDoneTool);
73043
73027
  if (isNoTaskRun) {
73044
73028
  agentLogger = new AgentLogger({
@@ -77892,10 +77876,18 @@ var init_plugin_runner = __esm({
77892
77876
  cachedRoutes = null;
77893
77877
  cachedUiSlots = null;
77894
77878
  cachedRuntimes = null;
77879
+ cachedSkills = null;
77880
+ cachedWorkflowSteps = null;
77881
+ cachedPromptContributions = null;
77882
+ cachedSetupInfo = null;
77895
77883
  toolsCacheVersion = 0;
77896
77884
  routesCacheVersion = 0;
77897
77885
  uiSlotsCacheVersion = 0;
77898
77886
  runtimesCacheVersion = 0;
77887
+ skillsCacheVersion = 0;
77888
+ workflowStepsCacheVersion = 0;
77889
+ promptContributionsCacheVersion = 0;
77890
+ setupCacheVersion = 0;
77899
77891
  hookTimeoutMs;
77900
77892
  // Event handler references for cleanup
77901
77893
  handlePluginEnabled;
@@ -77927,6 +77919,10 @@ var init_plugin_runner = __esm({
77927
77919
  this.invalidateRoutesCache();
77928
77920
  this.invalidateUiSlotsCache();
77929
77921
  this.invalidateRuntimesCache();
77922
+ this.invalidateSkillsCache();
77923
+ this.invalidateWorkflowStepsCache();
77924
+ this.invalidatePromptContributionsCache();
77925
+ this.invalidateSetupCache();
77930
77926
  }
77931
77927
  /**
77932
77928
  * Shutdown the plugin runner.
@@ -78007,6 +78003,54 @@ var init_plugin_runner = __esm({
78007
78003
  }
78008
78004
  return this.cachedRuntimes.runtimes;
78009
78005
  }
78006
+ getPluginSkills() {
78007
+ if (!this.cachedSkills || this.cachedSkills.version !== this.skillsCacheVersion) {
78008
+ this.cachedSkills = {
78009
+ skills: this.options.pluginLoader.getPluginSkills(),
78010
+ version: this.skillsCacheVersion
78011
+ };
78012
+ }
78013
+ return this.cachedSkills.skills;
78014
+ }
78015
+ getPluginWorkflowSteps() {
78016
+ if (!this.cachedWorkflowSteps || this.cachedWorkflowSteps.version !== this.workflowStepsCacheVersion) {
78017
+ this.cachedWorkflowSteps = {
78018
+ steps: this.options.pluginLoader.getPluginWorkflowSteps(),
78019
+ version: this.workflowStepsCacheVersion
78020
+ };
78021
+ }
78022
+ return this.cachedWorkflowSteps.steps;
78023
+ }
78024
+ getPluginPromptContributions() {
78025
+ if (!this.cachedPromptContributions || this.cachedPromptContributions.version !== this.promptContributionsCacheVersion) {
78026
+ this.cachedPromptContributions = {
78027
+ contributions: this.options.pluginLoader.getPluginPromptContributions(),
78028
+ version: this.promptContributionsCacheVersion
78029
+ };
78030
+ }
78031
+ return this.cachedPromptContributions.contributions;
78032
+ }
78033
+ getPluginSetupInfo() {
78034
+ if (!this.cachedSetupInfo || this.cachedSetupInfo.version !== this.setupCacheVersion) {
78035
+ this.cachedSetupInfo = {
78036
+ setups: this.options.pluginLoader.getPluginSetupInfo(),
78037
+ version: this.setupCacheVersion
78038
+ };
78039
+ }
78040
+ return this.cachedSetupInfo.setups;
78041
+ }
78042
+ getPromptContributionsForSurface(surface) {
78043
+ return this.getPluginPromptContributions().filter(({ pluginId, contribution, config }) => {
78044
+ const plugin4 = this.options.pluginLoader.getPlugin(pluginId);
78045
+ if (!plugin4 || plugin4.state !== "started") {
78046
+ return false;
78047
+ }
78048
+ if (contribution.surface !== surface) {
78049
+ return false;
78050
+ }
78051
+ return config.enabledByDefault !== false;
78052
+ });
78053
+ }
78010
78054
  /**
78011
78055
  * Get a specific runtime registration by its runtimeId.
78012
78056
  *
@@ -78040,6 +78084,10 @@ var init_plugin_runner = __esm({
78040
78084
  this.invalidateRoutesCache();
78041
78085
  this.invalidateUiSlotsCache();
78042
78086
  this.invalidateRuntimesCache();
78087
+ this.invalidateSkillsCache();
78088
+ this.invalidateWorkflowStepsCache();
78089
+ this.invalidatePromptContributionsCache();
78090
+ this.invalidateSetupCache();
78043
78091
  executorLog.log(`Plugin ${pluginId} reloaded`);
78044
78092
  }
78045
78093
  // ── Event Handlers for Hot-Load/Unload ─────────────────────────
@@ -78051,6 +78099,10 @@ var init_plugin_runner = __esm({
78051
78099
  this.invalidateRoutesCache();
78052
78100
  this.invalidateUiSlotsCache();
78053
78101
  this.invalidateRuntimesCache();
78102
+ this.invalidateSkillsCache();
78103
+ this.invalidateWorkflowStepsCache();
78104
+ this.invalidatePromptContributionsCache();
78105
+ this.invalidateSetupCache();
78054
78106
  try {
78055
78107
  executorLog.log(`Auto-loading enabled plugin: ${plugin4.id}`);
78056
78108
  await this.options.pluginLoader.loadPlugin(plugin4.id);
@@ -78066,6 +78118,10 @@ var init_plugin_runner = __esm({
78066
78118
  this.invalidateRoutesCache();
78067
78119
  this.invalidateUiSlotsCache();
78068
78120
  this.invalidateRuntimesCache();
78121
+ this.invalidateSkillsCache();
78122
+ this.invalidateWorkflowStepsCache();
78123
+ this.invalidatePromptContributionsCache();
78124
+ this.invalidateSetupCache();
78069
78125
  try {
78070
78126
  executorLog.log(`Auto-stopping disabled plugin: ${plugin4.id}`);
78071
78127
  await this.options.pluginLoader.stopPlugin(plugin4.id);
@@ -78081,6 +78137,10 @@ var init_plugin_runner = __esm({
78081
78137
  this.invalidateRoutesCache();
78082
78138
  this.invalidateUiSlotsCache();
78083
78139
  this.invalidateRuntimesCache();
78140
+ this.invalidateSkillsCache();
78141
+ this.invalidateWorkflowStepsCache();
78142
+ this.invalidatePromptContributionsCache();
78143
+ this.invalidateSetupCache();
78084
78144
  try {
78085
78145
  executorLog.log(`Stopping unregistered plugin: ${plugin4.id}`);
78086
78146
  await this.options.pluginLoader.stopPlugin(plugin4.id);
@@ -78097,6 +78157,10 @@ var init_plugin_runner = __esm({
78097
78157
  this.invalidateRoutesCache();
78098
78158
  this.invalidateUiSlotsCache();
78099
78159
  this.invalidateRuntimesCache();
78160
+ this.invalidateSkillsCache();
78161
+ this.invalidateWorkflowStepsCache();
78162
+ this.invalidatePromptContributionsCache();
78163
+ this.invalidateSetupCache();
78100
78164
  }
78101
78165
  /**
78102
78166
  * Handle plugin updates - invalidate caches.
@@ -78106,6 +78170,10 @@ var init_plugin_runner = __esm({
78106
78170
  this.invalidateRoutesCache();
78107
78171
  this.invalidateUiSlotsCache();
78108
78172
  this.invalidateRuntimesCache();
78173
+ this.invalidateSkillsCache();
78174
+ this.invalidateWorkflowStepsCache();
78175
+ this.invalidatePromptContributionsCache();
78176
+ this.invalidateSetupCache();
78109
78177
  }
78110
78178
  /**
78111
78179
  * Handle plugin:loaded event from loader - invalidate caches.
@@ -78115,6 +78183,10 @@ var init_plugin_runner = __esm({
78115
78183
  this.invalidateRoutesCache();
78116
78184
  this.invalidateUiSlotsCache();
78117
78185
  this.invalidateRuntimesCache();
78186
+ this.invalidateSkillsCache();
78187
+ this.invalidateWorkflowStepsCache();
78188
+ this.invalidatePromptContributionsCache();
78189
+ this.invalidateSetupCache();
78118
78190
  }
78119
78191
  /**
78120
78192
  * Handle plugin:unloaded event from loader - invalidate caches.
@@ -78124,6 +78196,10 @@ var init_plugin_runner = __esm({
78124
78196
  this.invalidateRoutesCache();
78125
78197
  this.invalidateUiSlotsCache();
78126
78198
  this.invalidateRuntimesCache();
78199
+ this.invalidateSkillsCache();
78200
+ this.invalidateWorkflowStepsCache();
78201
+ this.invalidatePromptContributionsCache();
78202
+ this.invalidateSetupCache();
78127
78203
  }
78128
78204
  /**
78129
78205
  * Handle plugin:reloaded event from loader - invalidate caches.
@@ -78133,6 +78209,10 @@ var init_plugin_runner = __esm({
78133
78209
  this.invalidateRoutesCache();
78134
78210
  this.invalidateUiSlotsCache();
78135
78211
  this.invalidateRuntimesCache();
78212
+ this.invalidateSkillsCache();
78213
+ this.invalidateWorkflowStepsCache();
78214
+ this.invalidatePromptContributionsCache();
78215
+ this.invalidateSetupCache();
78136
78216
  }
78137
78217
  // ── Tool Conversion ───────────────────────────────────────────────
78138
78218
  /**
@@ -78304,6 +78384,22 @@ var init_plugin_runner = __esm({
78304
78384
  this.runtimesCacheVersion++;
78305
78385
  this.log.log(`Runtimes cache invalidated (version: ${this.runtimesCacheVersion})`);
78306
78386
  }
78387
+ invalidateSkillsCache() {
78388
+ this.skillsCacheVersion++;
78389
+ this.log.log(`Skills cache invalidated (version: ${this.skillsCacheVersion})`);
78390
+ }
78391
+ invalidateWorkflowStepsCache() {
78392
+ this.workflowStepsCacheVersion++;
78393
+ this.log.log(`Workflow steps cache invalidated (version: ${this.workflowStepsCacheVersion})`);
78394
+ }
78395
+ invalidatePromptContributionsCache() {
78396
+ this.promptContributionsCacheVersion++;
78397
+ this.log.log(`Prompt contributions cache invalidated (version: ${this.promptContributionsCacheVersion})`);
78398
+ }
78399
+ invalidateSetupCache() {
78400
+ this.setupCacheVersion++;
78401
+ this.log.log(`Setup cache invalidated (version: ${this.setupCacheVersion})`);
78402
+ }
78307
78403
  // ── Store Event Subscriptions ────────────────────────────────────
78308
78404
  /**
78309
78405
  * Subscribe to TaskStore events for task lifecycle hooks.
@@ -96746,7 +96842,7 @@ var require_websocket = __commonJS({
96746
96842
  var http = __require("http");
96747
96843
  var net = __require("net");
96748
96844
  var tls = __require("tls");
96749
- var { randomBytes: randomBytes3, createHash: createHash5 } = __require("crypto");
96845
+ var { randomBytes: randomBytes3, createHash: createHash6 } = __require("crypto");
96750
96846
  var { Duplex, Readable } = __require("stream");
96751
96847
  var { URL: URL2 } = __require("url");
96752
96848
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -97406,7 +97502,7 @@ var require_websocket = __commonJS({
97406
97502
  abortHandshake(websocket, socket, "Invalid Upgrade header");
97407
97503
  return;
97408
97504
  }
97409
- const digest = createHash5("sha1").update(key + GUID).digest("base64");
97505
+ const digest = createHash6("sha1").update(key + GUID).digest("base64");
97410
97506
  if (res.headers["sec-websocket-accept"] !== digest) {
97411
97507
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
97412
97508
  return;
@@ -97773,7 +97869,7 @@ var require_websocket_server = __commonJS({
97773
97869
  var EventEmitter31 = __require("events");
97774
97870
  var http = __require("http");
97775
97871
  var { Duplex } = __require("stream");
97776
- var { createHash: createHash5 } = __require("crypto");
97872
+ var { createHash: createHash6 } = __require("crypto");
97777
97873
  var extension2 = require_extension();
97778
97874
  var PerMessageDeflate2 = require_permessage_deflate();
97779
97875
  var subprotocol2 = require_subprotocol();
@@ -98074,7 +98170,7 @@ var require_websocket_server = __commonJS({
98074
98170
  );
98075
98171
  }
98076
98172
  if (this._state > RUNNING) return abortHandshake(socket, 503);
98077
- const digest = createHash5("sha1").update(key + GUID).digest("base64");
98173
+ const digest = createHash6("sha1").update(key + GUID).digest("base64");
98078
98174
  const headers = [
98079
98175
  "HTTP/1.1 101 Switching Protocols",
98080
98176
  "Upgrade: websocket",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fusion/pi-claude-cli",
3
- "version": "0.14.1",
3
+ "version": "0.14.2",
4
4
  "description": "Fusion vendored fork: pi coding-agent extension that routes LLM calls through the Claude Code CLI. Forked from rchern/pi-claude-cli (MIT). See UPSTREAM.md.",
5
5
  "license": "MIT",
6
6
  "private": true,
@@ -178,6 +178,89 @@ describe("createEventBridge", () => {
178
178
  expect(textEnd1.contentIndex).toBe(1);
179
179
  expect(textEnd1.content).toBe("Second");
180
180
  });
181
+
182
+ it("repairs a missing sentence boundary between consecutive text blocks", () => {
183
+ const bridge = createBridgeWithStart();
184
+
185
+ bridge.handleEvent({
186
+ type: "content_block_start",
187
+ index: 0,
188
+ content_block: { type: "text", text: "" },
189
+ });
190
+ bridge.handleEvent({
191
+ type: "content_block_delta",
192
+ index: 0,
193
+ delta: { type: "text_delta", text: "compare them." },
194
+ });
195
+ bridge.handleEvent({
196
+ type: "content_block_stop",
197
+ index: 0,
198
+ });
199
+
200
+ bridge.handleEvent({
201
+ type: "content_block_start",
202
+ index: 1,
203
+ content_block: { type: "text", text: "" },
204
+ });
205
+ bridge.handleEvent({
206
+ type: "content_block_delta",
207
+ index: 1,
208
+ delta: { type: "text_delta", text: "Good overview." },
209
+ });
210
+
211
+ const output = bridge.getOutput();
212
+ const combinedText = output.content
213
+ .filter((content): content is any => content.type === "text")
214
+ .map((content: any) => content.text)
215
+ .join("");
216
+
217
+ expect(combinedText).toBe("compare them. Good overview.");
218
+ expect(stream.events[4]).toEqual(
219
+ expect.objectContaining({
220
+ type: "text_delta",
221
+ contentIndex: 1,
222
+ delta: " Good overview.",
223
+ }),
224
+ );
225
+ });
226
+
227
+ it("does not insert spaces into lowercase continuations like property access", () => {
228
+ const bridge = createBridgeWithStart();
229
+
230
+ bridge.handleEvent({
231
+ type: "content_block_start",
232
+ index: 0,
233
+ content_block: { type: "text", text: "" },
234
+ });
235
+ bridge.handleEvent({
236
+ type: "content_block_delta",
237
+ index: 0,
238
+ delta: { type: "text_delta", text: "console." },
239
+ });
240
+ bridge.handleEvent({
241
+ type: "content_block_stop",
242
+ index: 0,
243
+ });
244
+
245
+ bridge.handleEvent({
246
+ type: "content_block_start",
247
+ index: 1,
248
+ content_block: { type: "text", text: "" },
249
+ });
250
+ bridge.handleEvent({
251
+ type: "content_block_delta",
252
+ index: 1,
253
+ delta: { type: "text_delta", text: "log('hi')" },
254
+ });
255
+
256
+ const output = bridge.getOutput();
257
+ const combinedText = output.content
258
+ .filter((content): content is any => content.type === "text")
259
+ .map((content: any) => content.text)
260
+ .join("");
261
+
262
+ expect(combinedText).toBe("console.log('hi')");
263
+ });
181
264
  });
182
265
 
183
266
  describe("message_start usage tracking", () => {
@@ -795,6 +878,30 @@ describe("createEventBridge", () => {
795
878
  expect(thinkingBlock.thinking).toBe("First thought. Second thought.");
796
879
  });
797
880
 
881
+ it("repairs a missing sentence boundary between thinking deltas", () => {
882
+ const bridge = createBridgeWithStart();
883
+
884
+ bridge.handleEvent({
885
+ type: "content_block_start",
886
+ index: 0,
887
+ content_block: { type: "thinking" },
888
+ });
889
+ bridge.handleEvent({
890
+ type: "content_block_delta",
891
+ index: 0,
892
+ delta: { type: "thinking_delta", thinking: "I will inspect the hook." },
893
+ });
894
+ bridge.handleEvent({
895
+ type: "content_block_delta",
896
+ index: 0,
897
+ delta: { type: "thinking_delta", thinking: "Good, now the component." },
898
+ });
899
+
900
+ const output = bridge.getOutput();
901
+ const thinkingBlock = output.content[0] as any;
902
+ expect(thinkingBlock.thinking).toBe("I will inspect the hook. Good, now the component.");
903
+ });
904
+
798
905
  it("emits thinking_end for thinking block stop", () => {
799
906
  const bridge = createBridgeWithStart();
800
907