@bunshin-cc/bunshin 0.10.4 → 0.10.5

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.
package/dist/bin.js CHANGED
@@ -1827,9 +1827,11 @@ function globToRegExp(glob) {
1827
1827
  globCache.set(glob, out);
1828
1828
  return out;
1829
1829
  }
1830
+ function normalPath(path29) {
1831
+ return path29.replace(/\\/g, "/").split("/").filter((s) => s !== "" && s !== ".").join("/");
1832
+ }
1830
1833
  function matchesGlob(path29, glob) {
1831
- const p = path29.replace(/^\.\//, "").replace(/\\/g, "/");
1832
- return globToRegExp(glob.replace(/^\.\//, "")).test(p);
1834
+ return globToRegExp(glob.replace(/^\.\//, "")).test(normalPath(path29));
1833
1835
  }
1834
1836
  var DEFAULT_EMBEDDERS, globCache;
1835
1837
  var init_text_index = __esm({
@@ -5617,7 +5619,7 @@ function applyLocally(v2, view, s) {
5617
5619
  const section = s.target.sectionId ? view.byId.get(s.target.sectionId) : void 0;
5618
5620
  if (!section) return { applied: false, target: s.target.sectionId ?? "?", reason: "target section not in the local view" };
5619
5621
  if (section.storage.type === "repo") {
5620
- const file = containedPath(view.root, section.storage.path);
5622
+ const file = isDoc(section.storage.path) ? containedPath(view.root, section.storage.path) : null;
5621
5623
  const ours = !view.repo || section.storage.repo === view.repo;
5622
5624
  if (ours && file && fs11.existsSync(file)) {
5623
5625
  const before = fs11.readFileSync(file, "utf8");
@@ -5727,6 +5729,7 @@ var init_apply = __esm({
5727
5729
  "use strict";
5728
5730
  init_v22();
5729
5731
  init_util();
5732
+ init_repo();
5730
5733
  init_view();
5731
5734
  STATUS_FOR = {
5732
5735
  "drop-overlay": "accepted",
@@ -6656,6 +6659,7 @@ async function askRouter(store, v2, sessionId, model) {
6656
6659
  if (!session?.lastPrompt) return { picks: { error: "no prompt in the session file" } };
6657
6660
  if (!canCall(config)) return { picks: { error: "offline: the router's index comes from the server" } };
6658
6661
  const index = await routerIndex(store, v2, session.source ?? "");
6662
+ if (!/^[\w-]{1,64}$/.test(index.hash)) return { picks: { error: "the router index came back with a malformed hash" } };
6659
6663
  indexHash = index.hash;
6660
6664
  const systemFile = path11.join(dir(v2), `system-${index.hash}.txt`);
6661
6665
  if (!fs16.existsSync(systemFile)) fs16.writeFileSync(systemFile, index.system);
@@ -8777,7 +8781,8 @@ async function connectionProfile(apiUrl, apiKey) {
8777
8781
  if (!profile || ![profile.orgId, profile.userId, profile.role].every((value) => typeof value === "string" && value.length > 0) || typeof profile.orgUnit !== "string" || !["public", "org", "department", "team", "leadership", "csuite", "private"].includes(profile.clearance) || !Array.isArray(profile.responsibilities) || !profile.responsibilities.every((value) => typeof value === "string")) {
8778
8782
  throw new Error("Bunshin returned an incomplete profile. No connection settings were changed.");
8779
8783
  }
8780
- return profile;
8784
+ const { orgId, userId, role, orgUnit, clearance, responsibilities } = profile;
8785
+ return { orgId, userId, role, orgUnit, clearance, responsibilities: [...responsibilities] };
8781
8786
  }
8782
8787
  async function readKey() {
8783
8788
  if (!process.stdin.isTTY) throw new Error("Run setup in a terminal to paste your key, or supply it through BUNSHIN_API_KEY or --key-stdin.");
@@ -61,11 +61,15 @@ export function register(on) {
61
61
  return result;
62
62
  });
63
63
 
64
- // After each Bunshin hook has run (the settings hooks are below us in the chain), read the feed.
65
- on("classic.SessionStart", after);
66
- on("classic.UserPromptSubmit", after);
67
- on("classic.PreToolUse", after);
68
- on("classic.Stop", after);
64
+ // After each Bunshin settings hook has run, read the feed. Not on classic.*: the bundled
65
+ // cc-plugin-sec-default (seated outermost for Team and Enterprise organizations and on machines
66
+ // with managed settings) sends every classic.* event past the plugins a person installs, so
67
+ // those hooks never run there. These events carry the same settings hooks inside their next():
68
+ // prompt.submit runs UserPromptSubmit's, tool.call PreToolUse's; turn.complete ends the turn
69
+ // Stop closes; SessionStart is session.start's first refresh above. The poll catches the rest.
70
+ on("prompt.submit", after);
71
+ on("tool.call", after);
72
+ on("turn.complete", ($, e, next) => (e.agentId === undefined ? after($, e, next) : next(e)));
69
73
 
70
74
  // /clear and /resume change the session.
71
75
  on("command.run", { command: ["clear", "resume"] }, async ($, e, next) => {
@@ -113,7 +117,7 @@ export function register(on) {
113
117
  });
114
118
  }
115
119
 
116
- /** After one of Bunshin's settings hooks ran (they sit below the mods in the chain): read the feed. */
120
+ /** Once the event beneath (and the Bunshin settings hooks it runs) has settled: read the feed. */
117
121
  async function after($, e, next) {
118
122
  const result = await next(e);
119
123
  void refresh($).catch(() => undefined);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunshin-cc/bunshin",
3
- "version": "0.10.4",
3
+ "version": "0.10.5",
4
4
  "description": "Shared memory for company AI agents. Connect Codex, Claude Code, or Pi to Bunshin.",
5
5
  "type": "module",
6
6
  "bin": {