@norman-else/dsh-claude 0.1.48 → 0.1.50

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/lib/index.mjs CHANGED
@@ -1,10 +1,10 @@
1
1
  import { A as CLAUDE_REPOSITORY_FILE_PATH, C as CLAUDE_PROMPTS_PATH, D as CLAUDE_RENDER_MODES, E as CLAUDE_PROSE_MODES, F as CLAUDE_UPDATE_CHECK_PATH, H as isClaudeAlertMode, I as CLAUDE_UPDATE_PATH, L as CLAUDE_USAGE_PATH, M as CLAUDE_REPOSITORY_STATUS_PATH, N as CLAUDE_REVIEW_COMMENT_PATH, O as CLAUDE_REPOSITORY_ACTION_PATH, P as CLAUDE_REWIND_PATH, R as DEFAULT_CLAUDE_PROSE_MODE, S as CLAUDE_PROJECTION_PATH, T as CLAUDE_PROMPT_REFINE_PATH, U as isClaudeProseMode, V as TASK_TOOL_NAMES, W as isClaudeRenderMode, _ as CLAUDE_CODE_PROVIDER_IDS, a as latestClaudeTasks, b as CLAUDE_JIRA_PATH, c as normalizeTasksEvent, d as CLAUDE_ACTIVITY_EVENT, f as CLAUDE_ALERT_MODES, g as CLAUDE_CODE_PROVIDER, h as CLAUDE_CODE_PRESET_ID, i as latestClaudeSessionBinding, j as CLAUDE_REPOSITORY_SETUP_PATH, k as CLAUDE_REPOSITORY_FEEDBACK_PATH, l as redactText, m as CLAUDE_CLIENT_DIAGNOSTICS_PATH, n as currentClaudeActivityCursor, o as normalizeActivity, p as CLAUDE_ASK_PATH, r as latestClaudeContextUsage, s as normalizeContextUsage, t as boundText, u as safeDetail, v as CLAUDE_DOCTOR_PATH, w as CLAUDE_PROMPT_NAME_PATH, x as CLAUDE_PLAN_FEEDBACK_PATH, y as CLAUDE_GLOBAL_SETTINGS_PATH, z as DEFAULT_CLAUDE_RENDER_MODE } from "./events-B498uofA.mjs";
2
2
  import { a as projectClaudeCommands, i as CLAUDE_COMMANDS_SERVICE, r as dynamicPresenterDefinition, t as CLAUDE_PRESENTER_NAMES } from "./presenters-CRFcjLSC.mjs";
3
- import { a as resolveClaudeExecutable, n as ensureManagedPreset, o as runClaudeDoctor, t as ManagedPresetConflictError } from "./preset-installer-C4TTNV9L.mjs";
3
+ import { a as resolveClaudeExecutable, n as ensureManagedPreset, o as runClaudeDoctor, t as ManagedPresetConflictError } from "./preset-installer-Cj637ucf.mjs";
4
+ import { basename, dirname, extname, isAbsolute, join, resolve, sep } from "node:path";
4
5
  import z from "@deepseek-ai/schemastery";
5
6
  import { createHash, randomUUID } from "node:crypto";
6
7
  import { chmod, mkdir, opendir, readFile, readdir, realpath, rename, rm, stat, writeFile } from "node:fs/promises";
7
- import { basename, dirname, extname, isAbsolute, join, resolve, sep } from "node:path";
8
8
  import { dshHomePath, resolveDshHome } from "@deepseek-ai/dsh-home-paths";
9
9
  import { homedir, tmpdir } from "node:os";
10
10
  import { query } from "@anthropic-ai/claude-agent-sdk";
@@ -8662,7 +8662,7 @@ const WRITE_CONTEXTS = [
8662
8662
  * hundred git probes. */
8663
8663
  const MAX_PATHS_PER_COMMAND = 50;
8664
8664
  const PULL_REQUEST_URL = /https:\/\/github\.com\/([\w.-]+\/[\w.-]+)\/pull\/(\d{1,9})(?![\d])/gu;
8665
- const MAX_PULL_REQUESTS = 8;
8665
+ const MAX_PULL_REQUESTS = 12;
8666
8666
  function unescaped(escaped) {
8667
8667
  try {
8668
8668
  return JSON.parse(`"${escaped}"`);
@@ -8701,23 +8701,40 @@ function touchedFilePaths(activities) {
8701
8701
  return [...paths];
8702
8702
  }
8703
8703
  const PR_CREATE = /\bgh\s+pr\s+create\b/u;
8704
+ /** A file a command writes (redirect, tee): where a script lands. */
8705
+ const WRITTEN_FILE = new RegExp(String.raw`(?:>{1,2}\s*|\btee\s+(?:-\S+\s+)*)(${PATH_TOKEN}|[\w.@+~-]+(?:\/[\w.@+~-]+)*)`, "gu");
8706
+ function escapeRegExp(value) {
8707
+ return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
8708
+ }
8704
8709
  /** The pull requests the session opened: the URL `gh pr create` printed,
8705
8710
  * read off that call's own result. Other than the session repository's,
8706
8711
  * once each in first-seen order. A URL merely read, quoted or mentioned
8707
8712
  * (a fixture, a summary, a `gh pr view`) is not one the session made.
8713
+ * A script the session wrote with `gh pr create` inside and then ran by
8714
+ * name -- once per repository, the way a fan-out gets done -- counts the
8715
+ * same: the URLs come out of the runs, not of the write.
8708
8716
  * A checkout that has since moved back to its base branch no longer knows
8709
8717
  * about its pull request; the log still does. */
8710
8718
  function touchedPullRequests(activities, ownRepository) {
8711
8719
  const found = /* @__PURE__ */ new Map();
8712
8720
  const own = ownRepository?.toLowerCase();
8713
8721
  const creating = /* @__PURE__ */ new Set();
8722
+ /** Basenames of scripts written with `gh pr create` inside, as patterns. */
8723
+ const scripts = [];
8714
8724
  for (const activity of activities) {
8715
8725
  if (activity.toolUseId === void 0) continue;
8716
8726
  if (activity.kind === "tool-call" || activity.kind === "subagent" && activity.toolName !== void 0) {
8717
8727
  if (activity.toolName !== "Bash" || activity.detail === void 0) continue;
8718
8728
  const escaped = COMMAND_KEY.exec(activity.detail)?.[1];
8719
8729
  const command = escaped === void 0 ? void 0 : unescaped(escaped);
8720
- if (command !== void 0 && PR_CREATE.test(command)) creating.add(activity.toolUseId);
8730
+ if (command === void 0) continue;
8731
+ if (PR_CREATE.test(command)) {
8732
+ creating.add(activity.toolUseId);
8733
+ for (const match of command.matchAll(WRITTEN_FILE)) {
8734
+ const name = match[1]?.split("/").at(-1);
8735
+ if (name !== void 0 && name.length > 0) scripts.push(new RegExp(String.raw`(?:^|[\s/])${escapeRegExp(name)}(?=$|\s)`, "mu"));
8736
+ }
8737
+ } else if (scripts.some((script) => script.test(command))) creating.add(activity.toolUseId);
8721
8738
  continue;
8722
8739
  }
8723
8740
  if (activity.detail === void 0 || !creating.has(activity.toolUseId)) continue;
@@ -9562,8 +9579,9 @@ const CLAUDE_SCOPE_UNAVAILABLE_MESSAGE = "agent command scope unavailable (prese
9562
9579
  const CATALOG_RETRY_MS = 5e3;
9563
9580
  const SCOPE_RETRY_MS = 500;
9564
9581
  const MAX_CATALOG_RETRIES = 3;
9565
- /** Bounded: each extra checkout costs a git chain and a `gh pr view` per sweep. */
9566
- const MAX_EXTRA_REPOSITORIES = 8;
9582
+ /** Bounded: each extra checkout costs a git chain and a `gh pr view` per sweep.
9583
+ * A fan-out over every backend service is the largest real case. */
9584
+ const MAX_EXTRA_REPOSITORIES = 12;
9567
9585
  const MAX_SCOPE_RETRIES = 24;
9568
9586
  function mountClaudeMetadata(ctx, supervisor, agent, model, sidecar, publishCommands = () => {}, resolveCommands = () => ctx.agentPresets.serviceFor(agent, CLAUDE_COMMANDS_SERVICE)) {
9569
9587
  if (ctx.agentPresets.composedPreset(agent.ctx) !== "claude") return void 0;
@@ -9829,7 +9847,7 @@ async function apply(ctx, config) {
9829
9847
  /** Checkouts besides its own a session's routes may act on: every root a
9830
9848
  * projection sweep has ever vouched for, so a transient probe failure in
9831
9849
  * one sweep does not un-authorise a linked bar the client still shows. */
9832
- const extraRoots = new SessionRootLedger(32);
9850
+ const extraRoots = new SessionRootLedger(48);
9833
9851
  const cwdForClaudeSession = (sessionId, root) => {
9834
9852
  const agent = webCtx.agents.get(sessionId);
9835
9853
  if (agent === void 0 || webCtx.agentPresets.composedPreset(agent.ctx) !== "claude") return void 0;
@@ -9845,17 +9863,29 @@ async function apply(ctx, config) {
9845
9863
  const checkouts = probed.filter(linkedRepositoryShown);
9846
9864
  const covered = new Set(checkouts.map((status) => `${status.remote?.toLowerCase()}#${status.pullRequest?.number}`));
9847
9865
  const pullRequests = touchedPullRequests(activities, ownStatus.remote).filter((item) => !covered.has(`${item.repository}#${item.number}`)).slice(0, Math.max(0, MAX_EXTRA_REPOSITORIES - checkouts.length));
9866
+ const parents = [...new Set([own ?? cwd, ...probed.flatMap((status) => status.root === void 0 ? [] : [status.root])].map((root) => dirname(root)))];
9867
+ const cloneFor = async (item) => {
9868
+ const named = probed.find((status) => status.status === "ready" && status.remote?.toLowerCase() === item.repository && status.root !== void 0);
9869
+ if (named?.root !== void 0) return named.root;
9870
+ const name = item.repository.split("/").at(-1) ?? "";
9871
+ for (const parent of parents) {
9872
+ const root = await repositoryStatus.rootOf(join(parent, name));
9873
+ if (root === void 0) continue;
9874
+ const status = await repositoryStatus.inspect(root);
9875
+ if (status.status === "ready" && status.remote?.toLowerCase() === item.repository) return root;
9876
+ }
9877
+ };
9848
9878
  const detached = (await Promise.all(pullRequests.map(async (item) => {
9849
- const clone = probed.find((status) => status.status === "ready" && status.remote?.toLowerCase() === item.repository && status.root !== void 0);
9850
- const status = await repositoryStatus.inspectPullRequest(clone?.root ?? cwd, item.repository, item.number);
9851
- if (clone?.root === void 0 || status.status !== "ready") return status;
9852
- if (status.branch !== void 0 && cleanedLinked.has(`${clone.root}\0${status.branch}`)) return {
9879
+ const cloneRoot = await cloneFor(item);
9880
+ const status = await repositoryStatus.inspectPullRequest(cloneRoot ?? cwd, item.repository, item.number);
9881
+ if (cloneRoot === void 0 || status.status !== "ready") return status;
9882
+ if (status.branch !== void 0 && cleanedLinked.has(`${cloneRoot}\0${status.branch}`)) return {
9853
9883
  status: "unavailable",
9854
9884
  cwd
9855
9885
  };
9856
9886
  return {
9857
9887
  ...status,
9858
- root: clone.root
9888
+ root: cloneRoot
9859
9889
  };
9860
9890
  }))).filter(linkedRepositoryShown);
9861
9891
  const linked = [...checkouts, ...detached];