@hachej/boring-agent 0.1.91 → 0.1.93

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.
@@ -340,6 +340,7 @@ var SAFE_SESSION_NAMESPACE = /^[a-zA-Z0-9_-]+$/;
340
340
  var SESSION_ROOT_ENV = "BORING_AGENT_SESSION_ROOT";
341
341
  var SUMMARY_PREFIX_BYTES = 64 * 1024;
342
342
  var DEFAULT_LEGACY_WORKSPACE_ID = "default";
343
+ var TRUSTED_LOCAL_USER_ID = "local";
343
344
  function sessionDirForNamespace(namespace, explicitRoot) {
344
345
  const safeNamespace = namespace.trim();
345
346
  if (!SAFE_SESSION_NAMESPACE.test(safeNamespace)) {
@@ -358,6 +359,7 @@ var PiSessionStore = class {
358
359
  cwd;
359
360
  sessionDir;
360
361
  allowLegacyUnscopedAccess;
362
+ pathDerivedLegacyAccess;
361
363
  prefixCache = /* @__PURE__ */ new Map();
362
364
  listInFlight = /* @__PURE__ */ new Map();
363
365
  writerTails = /* @__PURE__ */ new Map();
@@ -366,9 +368,11 @@ var PiSessionStore = class {
366
368
  if (typeof options === "string") {
367
369
  this.sessionDir = options;
368
370
  this.allowLegacyUnscopedAccess = true;
371
+ this.pathDerivedLegacyAccess = false;
369
372
  return;
370
373
  }
371
374
  this.allowLegacyUnscopedAccess = true;
375
+ this.pathDerivedLegacyAccess = options?.sessionDir === void 0 && options?.sessionNamespace === void 0;
372
376
  this.sessionDir = options?.sessionDir ?? (options?.sessionNamespace ? sessionDirForNamespace(options.sessionNamespace, options.sessionRoot) : defaultSessionDir(options?.storageCwd ?? cwd, options?.sessionRoot));
373
377
  }
374
378
  getSessionDir() {
@@ -713,6 +717,7 @@ var PiSessionStore = class {
713
717
  }
714
718
  throw new Error(`Session not found: ${sessionId}`);
715
719
  }
720
+ if (ctx) await this.assertFileBelongsToCtx(matchedPath, ctx, sessionId);
716
721
  return this.ensureWrapperForNativeSession(sessionId, matchedPath, ctx);
717
722
  }
718
723
  async assertFileBelongsToCtx(filepath, ctx, sessionId) {
@@ -975,8 +980,16 @@ var PiSessionStore = class {
975
980
  return header ? this.storedCtxBelongsToCtx(readHeaderSessionCtx(header), ctx) : isEmptySessionCtx(ctx);
976
981
  }
977
982
  storedCtxBelongsToCtx(storedCtx, ctx) {
978
- if (storedCtx === null) return this.allowLegacyUnscopedAccess && isLegacyUnscopedCtx(ctx);
979
- return sameSessionCtx(storedCtx, ctx);
983
+ const trustedLocalCtx = !ctx.userId || ctx.userId === TRUSTED_LOCAL_USER_ID;
984
+ if (storedCtx === null) {
985
+ return this.allowLegacyUnscopedAccess && (isLegacyUnscopedCtx(ctx) || this.pathDerivedLegacyAccess && trustedLocalCtx);
986
+ }
987
+ if (sameSessionCtx(storedCtx, ctx)) return true;
988
+ if (!this.pathDerivedLegacyAccess || !trustedLocalCtx) return false;
989
+ if (isEmptySessionCtx(storedCtx)) return true;
990
+ return Boolean(
991
+ storedCtx.workspaceId && storedCtx.workspaceId === ctx.workspaceId && (!storedCtx.userId || !ctx.userId && storedCtx.userId === TRUSTED_LOCAL_USER_ID)
992
+ );
980
993
  }
981
994
  };
982
995
  async function readJsonlPrefix(filepath, maxBytes = SUMMARY_PREFIX_BYTES) {
@@ -6,7 +6,7 @@ import {
6
6
  readConfiguredDefaultModel,
7
7
  registerConfiguredModelProviders,
8
8
  withPiHarnessDefaults
9
- } from "./chunk-IWBC6SF7.js";
9
+ } from "./chunk-2TMS2RU2.js";
10
10
  import {
11
11
  AgentEffectAdmissionError,
12
12
  createAgentRuntimeBridge,
@@ -48,7 +48,7 @@ import {
48
48
  StopPayloadSchema,
49
49
  extractToolUiMetadata,
50
50
  sanitizeToolUiMetadata2 as sanitizeToolUiMetadata
51
- } from "./chunk-PZC76CIA.js";
51
+ } from "./chunk-OFQ7J6SI.js";
52
52
  import {
53
53
  AgentDefinitionErrorCode,
54
54
  AgentDeploymentErrorCode,
@@ -2478,6 +2478,7 @@ var PiChatEventMapper = class {
2478
2478
  activeAssistantMessageId;
2479
2479
  pendingUserStarts = [];
2480
2480
  toolCallMessageIds = /* @__PURE__ */ new Map();
2481
+ toolCallInputs = /* @__PURE__ */ new Map();
2481
2482
  endedMessageIds = /* @__PURE__ */ new Set();
2482
2483
  endedAssistantTurnIds = /* @__PURE__ */ new Set();
2483
2484
  errorEmittedTurnIds = /* @__PURE__ */ new Set();
@@ -2515,6 +2516,7 @@ var PiChatEventMapper = class {
2515
2516
  ];
2516
2517
  this.activeAssistantMessageId = void 0;
2517
2518
  this.toolCallMessageIds.clear();
2519
+ this.toolCallInputs.clear();
2518
2520
  if (status !== "error") this.activeTurnId = void 0;
2519
2521
  return mapped;
2520
2522
  }
@@ -2654,6 +2656,7 @@ var PiChatEventMapper = class {
2654
2656
  const toolCall = assistantEvent.toolCall;
2655
2657
  const toolCallId = optionalString2(toolCall.id) ?? `${messageId}:tool:${partIdFromAssistantEvent(assistantEvent)}`;
2656
2658
  this.toolCallMessageIds.set(toolCallId, messageId);
2659
+ this.toolCallInputs.set(toolCallId, toolCall.arguments);
2657
2660
  return [
2658
2661
  this.event({
2659
2662
  type: "tool-call",
@@ -2747,9 +2750,17 @@ var PiChatEventMapper = class {
2747
2750
  const messageId = this.toolCallMessageIds.get(toolCallId) ?? this.activeAssistantMessageId ?? fallbackMessageId(this.sessionId, "assistant", this.seq + 1);
2748
2751
  const result = event.result;
2749
2752
  const mapped = [];
2753
+ const toolFilesystem = filesystemFromToolInput(this.toolCallInputs.get(toolCallId));
2750
2754
  for (const fileChange of extractFileChanges(isRecord2(result) ? result.details : void 0)) {
2751
- mapped.push(this.event({ type: "file-changed", path: fileChange.path, changeType: fileChange.op }));
2755
+ const filesystem = fileChange.filesystem ?? toolFilesystem;
2756
+ mapped.push(this.event({
2757
+ type: "file-changed",
2758
+ path: fileChange.path,
2759
+ changeType: fileChange.op,
2760
+ ...filesystem ? { filesystem } : {}
2761
+ }));
2752
2762
  }
2763
+ this.toolCallInputs.delete(toolCallId);
2753
2764
  mapped.push(
2754
2765
  this.event({
2755
2766
  type: "tool-result",
@@ -2896,13 +2907,21 @@ function errorMessageFromAssistantError(assistantEvent) {
2896
2907
  if (isRecord2(assistantEvent.error) && typeof assistantEvent.error.errorMessage === "string") return assistantEvent.error.errorMessage;
2897
2908
  return assistantEvent.reason === "aborted" ? "Aborted" : "Unknown error";
2898
2909
  }
2910
+ function filesystemFromToolInput(input) {
2911
+ return isRecord2(input) ? optionalString2(input.filesystem) : void 0;
2912
+ }
2899
2913
  function normalizeFileChangeEntry(value) {
2900
2914
  if (!isRecord2(value)) return null;
2901
2915
  const op = value.op;
2902
2916
  const path = value.path;
2903
2917
  if (typeof op !== "string" || !FILE_CHANGE_OPS.has(op)) return null;
2904
2918
  if (typeof path !== "string" || path.length === 0) return null;
2905
- return { op, path };
2919
+ const filesystem = optionalString2(value.filesystem);
2920
+ return {
2921
+ op,
2922
+ path,
2923
+ ...filesystem ? { filesystem } : {}
2924
+ };
2906
2925
  }
2907
2926
  function extractFileChanges(details) {
2908
2927
  if (!isRecord2(details)) return [];
@@ -4782,7 +4801,7 @@ function createAgentRuntimeBridge2(config, options = {}) {
4782
4801
  });
4783
4802
  }
4784
4803
  async function createRuntime(config, options) {
4785
- const harnessFactory = config.harnessFactory ?? (await import("./createHarness-PMYRKDE4.js")).createPiCodingAgentHarness;
4804
+ const harnessFactory = config.harnessFactory ?? (await import("./createHarness-UCD74XXK.js")).createPiCodingAgentHarness;
4786
4805
  const harnessInput = {
4787
4806
  tools: config.tools ?? [],
4788
4807
  cwd: config.workdir ?? DEFAULT_WORKDIR,
@@ -6938,7 +6957,7 @@ async function buildAgentComposition(input) {
6938
6957
  sessionNamespace: configuredNamespace,
6939
6958
  sessionDir: compatibility?.sessionDir ?? factoryInput.sessionDir
6940
6959
  }) : async (factoryInput) => {
6941
- const { createPiCodingAgentHarness } = await import("./createHarness-PMYRKDE4.js");
6960
+ const { createPiCodingAgentHarness } = await import("./createHarness-UCD74XXK.js");
6942
6961
  return createPiCodingAgentHarness({
6943
6962
  ...factoryInput,
6944
6963
  pi,
@@ -187,7 +187,7 @@ var PiChatEventSchema = z.discriminatedUnion("type", [
187
187
  clientSeq: z.number().int().nonnegative().optional(),
188
188
  messageId: nonEmptyString
189
189
  }),
190
- baseEvent.extend({ type: z.literal("file-changed"), path: nonEmptyString, changeType: nonEmptyString }),
190
+ baseEvent.extend({ type: z.literal("file-changed"), path: nonEmptyString, changeType: nonEmptyString, filesystem: nonEmptyString.optional() }),
191
191
  baseEvent.extend({ type: z.literal("ui-command"), command: ShallowPayloadSchema, displayOnly: z.literal(true) }),
192
192
  baseEvent.extend({ type: z.literal("usage"), usage: ShallowPayloadSchema }),
193
193
  baseEvent.extend({
@@ -1,8 +1,8 @@
1
- import { A as AgentHarness, a as AgentReadiness, b as Agent } from '../harness-Bt_GMNYR.js';
2
- export { c as AGENT_NOT_IMPLEMENTED_UNTIL_T1, d as AgentActor, e as AgentCoreHarness, f as AgentCoreHarnessFactory, g as AgentCorePromptInput, h as AgentCoreSessionAdapter, i as AgentCoreSessionSnapshot, j as AgentEvent, k as AgentMessageContent, l as AgentMessagePart, m as AgentNotImplementedError, n as AgentReadinessStatus, o as AgentResolveInputResponse, p as AgentSendInput, q as AgentStartReceipt, r as AgentStreamOptions } from '../harness-Bt_GMNYR.js';
3
- import { S as SessionStore } from '../piChatEvent-DBO3M5lu.js';
4
- import { A as AgentCoreSessionService, a as AgentEffectAdmission } from '../piChatSessionService-BaaVWke7.js';
5
- export { b as AGENT_EFFECT_METHODS, c as AgentEffectAdmissionError, P as PiChatEventStreamResult, d as PiChatEventStreamSubscription, e as PiChatEventSubscriber, f as PiChatReplayRangeError, g as PiChatSessionService, h as PiSessionCreateInit, i as PiSessionRequestContext, w as withAgentEffectAdmission } from '../piChatSessionService-BaaVWke7.js';
1
+ import { A as AgentHarness, a as AgentReadiness, b as Agent } from '../harness-Cc48o6uS.js';
2
+ export { c as AGENT_NOT_IMPLEMENTED_UNTIL_T1, d as AgentActor, e as AgentCoreHarness, f as AgentCoreHarnessFactory, g as AgentCorePromptInput, h as AgentCoreSessionAdapter, i as AgentCoreSessionSnapshot, j as AgentEvent, k as AgentMessageContent, l as AgentMessagePart, m as AgentNotImplementedError, n as AgentReadinessStatus, o as AgentResolveInputResponse, p as AgentSendInput, q as AgentStartReceipt, r as AgentStreamOptions } from '../harness-Cc48o6uS.js';
3
+ import { S as SessionStore } from '../piChatEvent-BsMp3MSo.js';
4
+ import { A as AgentCoreSessionService, a as AgentEffectAdmission } from '../piChatSessionService-BrPqKrpY.js';
5
+ export { b as AGENT_EFFECT_METHODS, c as AgentEffectAdmissionError, P as PiChatEventStreamResult, d as PiChatEventStreamSubscription, e as PiChatEventSubscriber, f as PiChatReplayRangeError, g as PiChatSessionService, h as PiSessionCreateInit, i as PiSessionRequestContext, w as withAgentEffectAdmission } from '../piChatSessionService-BrPqKrpY.js';
6
6
  import '@mariozechner/pi-coding-agent';
7
7
  import 'zod';
8
8
 
@@ -4,7 +4,7 @@ import {
4
4
  deriveSourcePlugin,
5
5
  mergePiPackageSources,
6
6
  withPiHarnessDefaults
7
- } from "./chunk-IWBC6SF7.js";
7
+ } from "./chunk-2TMS2RU2.js";
8
8
  import "./chunk-AQBXNPMD.js";
9
9
  import "./chunk-2GBHYJVC.js";
10
10
  export {
@@ -1,4 +1,4 @@
1
- import { b as PiChatEvent, o as ChatModelSelection, K as ThinkingLevel, v as ChatAttachmentPayload, Q as QueuedUserMessage, n as PiChatSnapshot } from './piChatEvent-DBO3M5lu.js';
1
+ import { b as PiChatEvent, o as ChatModelSelection, K as ThinkingLevel, v as ChatAttachmentPayload, Q as QueuedUserMessage, n as PiChatSnapshot } from './piChatEvent-BsMp3MSo.js';
2
2
 
3
3
  /** Placement-independent event envelope. `seq` is the only replay cursor. */
4
4
  interface AgentSessionEvent {
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ComponentProps, HTMLAttributes, FormEvent, ReactNode, ComponentType } from 'react';
3
3
  import { FileUIPart, ChatStatus, UIMessage } from 'ai';
4
- import { T as ToolUiMetadata, B as BoringChatPart, a as BoringChatMessage, P as PiChatStatus, Q as QueuedUserMessage, C as ChatError, b as PiChatEvent, c as PromptPayload, d as PromptReceipt, F as FollowUpPayload, e as FollowUpReceipt, f as QueueClearPayload, g as QueueClearReceipt, I as InterruptPayload, h as CommandReceipt, i as StopPayload, j as StopReceipt, k as SessionSummary } from '../piChatEvent-DBO3M5lu.js';
4
+ import { T as ToolUiMetadata, B as BoringChatPart, a as BoringChatMessage, P as PiChatStatus, Q as QueuedUserMessage, C as ChatError, b as PiChatEvent, c as PromptPayload, d as PromptReceipt, F as FollowUpPayload, e as FollowUpReceipt, f as QueueClearPayload, g as QueueClearReceipt, I as InterruptPayload, h as CommandReceipt, i as StopPayload, j as StopReceipt, k as SessionSummary } from '../piChatEvent-BsMp3MSo.js';
5
5
  import { InputGroupAddon, InputGroupButton, InputGroupTextarea, Button, Collapsible, CollapsibleContent, CollapsibleTrigger } from '@hachej/boring-ui-kit';
6
6
  import { Streamdown } from 'streamdown';
7
7
  import { StickToBottom } from 'use-stick-to-bottom';
@@ -154,6 +154,7 @@ type SlashCommandHandlerResult = string | void | {
154
154
  preserveDraft?: boolean;
155
155
  };
156
156
  type SlashCommandHandler = (args: string, ctx: SlashCommandContext) => SlashCommandHandlerResult | Promise<SlashCommandHandlerResult>;
157
+ type SlashCommandClickBehavior = 'execute' | 'insert' | 'disabled';
157
158
  interface SlashCommand {
158
159
  name: string;
159
160
  description: string;
@@ -165,6 +166,8 @@ interface SlashCommand {
165
166
  * is needed.
166
167
  */
167
168
  kind?: 'local' | 'skill';
169
+ /** Explicit opt-in for assistant-message command links. Unset commands remain plain text. */
170
+ clickBehavior?: SlashCommandClickBehavior;
168
171
  /**
169
172
  * Origin of the command, surfaced as a tag in the slash-command picker.
170
173
  * Mirrors Pi's command sources for server commands; `local` for built-in