@byfriends/agent-core 0.2.5 → 0.3.0

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.
@@ -1154,7 +1154,7 @@ interface BackgroundTaskInfo$1 {
1154
1154
  readonly command: string;
1155
1155
  readonly description: string;
1156
1156
  readonly status: BackgroundTaskStatus;
1157
- readonly pid: number;
1157
+ readonly pid: number | null;
1158
1158
  readonly exitCode: number | null;
1159
1159
  readonly startedAt: number;
1160
1160
  readonly endedAt: number | null;
@@ -1437,7 +1437,7 @@ declare class BackgroundProcessManager {
1437
1437
  /** Drop a persisted task from disk and ghost map. */
1438
1438
  forgetTask(taskId: string): Promise<void>;
1439
1439
  /**
1440
- * Persist the current state of a live ManagedProcess. Called from
1440
+ * Persist the current state of a live TaskEntry. Called from
1441
1441
  * `register()` and the lifecycle finally block. No-op unless attached.
1442
1442
  */
1443
1443
  private persistLive;
@@ -1907,6 +1907,13 @@ interface RecordRestoreHandler {
1907
1907
  restoreRecord(record: AgentRecord): void;
1908
1908
  }
1909
1909
  //#endregion
1910
+ //#region src/agent/context/projector.d.ts
1911
+ interface EphemeralInjection {
1912
+ kind: 'memory_recall' | 'system_reminder' | 'pending_notification';
1913
+ content: string | Record<string, unknown>;
1914
+ position?: 'before_user' | 'after_system';
1915
+ }
1916
+ //#endregion
1910
1917
  //#region src/agent/context/scratch-manager.d.ts
1911
1918
  interface ScratchManagerConfig {
1912
1919
  /** 每个 session 的最大 scratch 大小 (bytes),默认 50MB */
@@ -1950,6 +1957,12 @@ declare class ContextMemory implements RecordRestoreHandler {
1950
1957
  get tokenCountWithPending(): number;
1951
1958
  get history(): readonly ContextMessage$1[];
1952
1959
  get messages(): Message[];
1960
+ /**
1961
+ * Project history into provider-ready messages, optionally with
1962
+ * ephemeral injections (e.g. timestamp, permission mode) appended
1963
+ * at the `'before_user'` position.
1964
+ */
1965
+ getMessages(ephemeral?: readonly EphemeralInjection[]): Message[];
1953
1966
  applyObservationMasking(config?: MaskingConfig): MaskingResult;
1954
1967
  applyPruning(config?: {
1955
1968
  effectiveCapacityRatio?: number;
@@ -2488,6 +2501,13 @@ interface AgentMeta {
2488
2501
  readonly homedir: string;
2489
2502
  readonly type: AgentType$1;
2490
2503
  readonly parentAgentId: string | null;
2504
+ /**
2505
+ * The parent agent's tool-call id that spawned this agent. Absent for the
2506
+ * main agent and for sessions persisted before this field existed. The TUI
2507
+ * uses it on resume to map a main-agent `Agent` tool-call back to its child
2508
+ * agent's activity (the child's own replay/usage/text).
2509
+ */
2510
+ readonly parentToolCallId?: string | undefined;
2491
2511
  }
2492
2512
  interface SessionMeta$1 {
2493
2513
  createdAt: string;
@@ -2520,7 +2540,7 @@ declare class Session {
2520
2540
  }>;
2521
2541
  close(): Promise<void>;
2522
2542
  private stopBackgroundTasksOnExit;
2523
- createAgent(config: Partial<AgentConfig>, profile?: ResolvedAgentProfile, parentAgentId?: string | undefined): Promise<{
2543
+ createAgent(config: Partial<AgentConfig>, profile?: ResolvedAgentProfile, parentAgentId?: string | undefined, parentToolCallId?: string | undefined): Promise<{
2524
2544
  readonly id: string;
2525
2545
  readonly agent: Agent;
2526
2546
  }>;
@@ -2686,6 +2706,7 @@ declare class InjectionManager {
2686
2706
  private readonly injectors;
2687
2707
  constructor(agent: Agent);
2688
2708
  inject(): Promise<void>;
2709
+ getEphemeralInjections(): readonly EphemeralInjection[];
2689
2710
  onContextClear(): void;
2690
2711
  onContextCompacted(compactedCount: number): void;
2691
2712
  }
@@ -3416,6 +3437,13 @@ interface ResumedAgentState {
3416
3437
  readonly tools: readonly ToolInfo[];
3417
3438
  readonly toolStore?: Readonly<Record<string, unknown>>;
3418
3439
  readonly background: readonly BackgroundTaskInfo[];
3440
+ /**
3441
+ * For sub-agents: the parent agent's tool-call id that spawned this agent.
3442
+ * Absent for the main agent and for sessions persisted before this field
3443
+ * existed. The TUI uses it to attach a resumed main-agent `Agent` tool-call
3444
+ * to this child's activity (replay/usage/text).
3445
+ */
3446
+ readonly parentToolCallId?: string | undefined;
3419
3447
  }
3420
3448
  interface ResumeSessionResult extends SessionSummary {
3421
3449
  readonly sessionMetadata: SessionMeta;
package/dist/index.d.mts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { t as AGENT_WIRE_PROTOCOL_VERSION } from "./index-DitEeLHK.mjs";
2
- import { $ as CoreInfo, $n as SessionSkillConfig, $r as resolveByfHome, $t as BackgroundTaskUpdatedEvent, A as QuestionAnswers, Ai as ProviderType, An as TurnStepInterruptedEvent, Ar as LoopStepEndEvent, At as SetModelResult, B as SDKSessionAPI, Bi as LogEntry, Bn as ByfError, Br as BackgroundTaskStatus, Bt as Unsubscribe, C as SDKRPCClient, Ci as PermissionConfigSchema, Cn as ToolProgressEvent, Cr as PromptOrigin, Ct as ResumeSessionPayload, D as ApprovalResponse, Di as PermissionRuleScopeSchema, Dn as TurnEndedEvent, Dr as LoopContentPartEvent, Dt as SetActiveToolsPayload, E as ApprovalRequest, Ei as PermissionRuleSchema, En as TurnEndReason, Er as ToolStoreUpdate, Et as SessionSummary, F as QuestionResult, Fi as ThinkingConfigSchema, Fn as ByfErrorPayload, Fr as ExecutableToolSuccessResult, Ft as SkillSummary, G as AgentAPI, Gi as RootLogger, Gn as ErrorCodes, Gr as parseConfigString, Gt as AgentReplayRecord, H as ToolCallRequest, Hi as LogPayload, Hn as BYF_ERROR_INFO, Hr as OAuthTokenProviderResolver, Ht as WithAgentId, I as SDKAPI, Ii as formatConfigValidationError, In as fromByfErrorPayload, Ir as ToolInputDisplay, It as SteerPayload, J as ByfConfigPatch, Jn as SubagentHandle, Jr as writeConfigFile, Jt as AgentEvent, K as BeginCompactionPayload, Ki as SessionAttachInput, Kn as RuntimeConfig, Kr as readConfigFile, Kt as ResumeSessionResult, L as SDKAgentAPI, Li as getDefaultConfig, Ln as isByfError, Lr as BackgroundLifecycleEvent, Lt as StopBackgroundPayload, M as QuestionOption, Mi as ServicesConfig, Mn as TurnStepStartedEvent, Mr as LoopToolResultEvent, Mt as SetThinkingPayload, N as QuestionRequest, Ni as ServicesConfigSchema, Nn as UsageStatus, Nr as ExecutableToolErrorResult, Nt as ShellExecPayload, O as ApprovalScope, Oi as ProviderConfig, On as TurnStartedEvent, Or as LoopRecordedEvent, Ot as SetByfConfigPayload, P as QuestionResponse, Pi as ThinkingConfig, Pn as WarningEvent, Pr as ExecutableToolResult, Pt as ShellExecResult, Q as CoreAPI, Qn as SessionMeta, Qr as ensureByfHome, Qt as BackgroundTaskTerminatedEvent, R as SDKAgentRPC, Ri as validateConfig, Rn as makeErrorPayload, Rr as BackgroundTaskInfo, Rt as TextPromptPart, S as RPCMethods, Si as PermissionConfig, Sn as ToolListUpdatedReason, Sr as ContextMessage, St as RenameSessionPayload, T as ApprovalDecision, Ti as PermissionRuleDecisionSchema, Tn as ToolUpdate, Tr as UserPromptOrigin, Tt as SessionMetadataPatch, U as ToolCallResponse, Ui as Logger, Un as ByfErrorCode, Ur as configToTomlData, Ut as WithSessionId, V as SDKSessionRPC, Vi as LogLevel, Vn as ByfErrorOptions, Vr as BearerTokenProvider, Vt as UpdateSessionMetadataPayload, W as ActivateSkillPayload, Wi as LoggingConfig, Wn as ByfErrorInfo, Wr as ensureConfigFile, Wt as proxyWithExtraPayload, X as CancelPlanPayload, Xn as Session, Xr as parseBooleanEnv, Xt as AssistantDeltaEvent, Y as CancelPayload, Yn as AgentMeta, Yr as ResolveConfigValueInput, Yt as AgentStatusUpdatedEvent, Z as CloseSessionPayload, Zn as SessionConfig, Zr as resolveConfigValue, Zt as BackgroundTaskStartedEvent, _ as ByfCoreOptions, _i as McpServerStdioConfigSchema, _n as SubagentSpawnedEvent, _r as PermissionMode, _t as PromptPart, a as collectFilesRecursive, ai as ByfConfigSchema, an as Event, ar as redact, at as ForkSessionPayload, b as RPCCallOptions, bi as OAuthRef, bn as ToolCallStartedEvent, br as CompactionResult, bt as RegisterToolPayload, c as WIRE_PROTOCOL_VERSION, ci as HookDefConfig, cn as McpOAuthAuthorizationUrlUpdateData, cr as ToolInfo, ct as GetBackgroundPayload, d as normalizeTimestampMs, di as LoopControlSchema, dn as ObservationMaskingAppliedEvent, dr as AgentRecord, dt as JsonValue, ei as resolveConfigPath, en as CompactionBlockedEvent, er as TelemetryClient, et as CreateSessionPayload, f as scanSessionWire, fi as McpServerConfig, fn as PruningAppliedEvent, fr as AgentRecordEvents, ft as ListSessionsPayload, g as ByfCore, gi as McpServerStdioConfig, gn as SubagentFailedEvent, gr as PermissionApprovalResultRecord, gt as PromptInput, h as AgentType, hi as McpServerHttpConfigSchema, hn as SubagentCompletedEvent, hr as UsageRecordScope, ht as PlanData, i as ExtraZipEntry, ii as ByfConfigPatchSchema, in as ErrorEvent, ir as log, it as ExportSessionResult, j as QuestionItem, ji as ProviderTypeSchema, jn as TurnStepRetryingEvent, jr as LoopToolCallEvent, jt as SetPermissionPayload, k as QuestionAnswerMethod, ki as ProviderConfigSchema, kn as TurnStepCompletedEvent, kr as LoopStepBeginEvent, kt as SetModelPayload, l as buildExportManifest, li as HookDefSchema, ln as McpServerStatusEvent, lr as ToolSource, lt as JsonObject, m as AgentConfig, mi as McpServerHttpConfig, mn as SkillActivatedEvent, mr as AgentRecordPersistence, mt as McpStartupMetrics, n as ResolveLoggingInput, ni as BackgroundConfig, nn as CompactionCompletedEvent, nr as flushDiagnosticLogs, nt as ExportSessionManifest, o as writeExportZip, oi as ByfServiceConfig, on as HookResultEvent, or as resolveGlobalLogPath, ot as GetBackgroundOutputPathPayload, p as Agent, pi as McpServerConfigSchema, pn as SessionMetaUpdatedEvent, pr as AgentRecordOf, pt as McpServerInfo, q as ByfConfig, qi as SessionLogHandle, qn as SessionSubagentHost, qr as transformTomlData, qt as ResumedAgentState, r as resolveLoggingConfig, ri as BackgroundConfigSchema, rn as CompactionStartedEvent, rr as getRootLogger, rt as ExportSessionPayload, s as exportSessionDirectory, si as ByfServiceConfigSchema, sn as MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE, sr as BuiltinTool, st as GetBackgroundOutputPayload, t as buildPromptPlan, ti as mergeConfigPatch, tn as CompactionCancelledEvent, tr as TelemetryProperties, tt as EmptyPayload, u as SessionWireScan, ui as LoopControl, un as McpServerStatusPayload, ur as UserToolRegistration, ut as JsonPrimitive, v as CoreRPC, vi as ModelAlias, vn as ThinkingDeltaEvent, vr as AgentConfigUpdateData, vt as PromptPayload, w as createRPC, wi as PermissionModeSchema, wn as ToolResultEvent, wr as USER_PROMPT_ORIGIN, wt as SessionAPI, x as RPCClient, xi as OAuthRefSchema, xn as ToolListUpdatedEvent, xr as AgentContextData, xt as RemoveByfProviderPayload, y as CoreRPCClient, yi as ModelAliasSchema, yn as ToolCallDeltaEvent, yr as CompactionBeginData, yt as ReconnectMcpServerPayload, z as SDKRPC, zi as LogContext, zn as toByfErrorPayload, zr as BackgroundTaskKind, zt as UnregisterToolPayload } from "./index-Bi8MjEPf.mjs";
2
+ import { $ as CoreInfo, $n as SessionSkillConfig, $r as resolveByfHome, $t as BackgroundTaskUpdatedEvent, A as QuestionAnswers, Ai as ProviderType, An as TurnStepInterruptedEvent, Ar as LoopStepEndEvent, At as SetModelResult, B as SDKSessionAPI, Bi as LogEntry, Bn as ByfError, Br as BackgroundTaskStatus, Bt as Unsubscribe, C as SDKRPCClient, Ci as PermissionConfigSchema, Cn as ToolProgressEvent, Cr as PromptOrigin, Ct as ResumeSessionPayload, D as ApprovalResponse, Di as PermissionRuleScopeSchema, Dn as TurnEndedEvent, Dr as LoopContentPartEvent, Dt as SetActiveToolsPayload, E as ApprovalRequest, Ei as PermissionRuleSchema, En as TurnEndReason, Er as ToolStoreUpdate, Et as SessionSummary, F as QuestionResult, Fi as ThinkingConfigSchema, Fn as ByfErrorPayload, Fr as ExecutableToolSuccessResult, Ft as SkillSummary, G as AgentAPI, Gi as RootLogger, Gn as ErrorCodes, Gr as parseConfigString, Gt as AgentReplayRecord, H as ToolCallRequest, Hi as LogPayload, Hn as BYF_ERROR_INFO, Hr as OAuthTokenProviderResolver, Ht as WithAgentId, I as SDKAPI, Ii as formatConfigValidationError, In as fromByfErrorPayload, Ir as ToolInputDisplay, It as SteerPayload, J as ByfConfigPatch, Jn as SubagentHandle, Jr as writeConfigFile, Jt as AgentEvent, K as BeginCompactionPayload, Ki as SessionAttachInput, Kn as RuntimeConfig, Kr as readConfigFile, Kt as ResumeSessionResult, L as SDKAgentAPI, Li as getDefaultConfig, Ln as isByfError, Lr as BackgroundLifecycleEvent, Lt as StopBackgroundPayload, M as QuestionOption, Mi as ServicesConfig, Mn as TurnStepStartedEvent, Mr as LoopToolResultEvent, Mt as SetThinkingPayload, N as QuestionRequest, Ni as ServicesConfigSchema, Nn as UsageStatus, Nr as ExecutableToolErrorResult, Nt as ShellExecPayload, O as ApprovalScope, Oi as ProviderConfig, On as TurnStartedEvent, Or as LoopRecordedEvent, Ot as SetByfConfigPayload, P as QuestionResponse, Pi as ThinkingConfig, Pn as WarningEvent, Pr as ExecutableToolResult, Pt as ShellExecResult, Q as CoreAPI, Qn as SessionMeta, Qr as ensureByfHome, Qt as BackgroundTaskTerminatedEvent, R as SDKAgentRPC, Ri as validateConfig, Rn as makeErrorPayload, Rr as BackgroundTaskInfo, Rt as TextPromptPart, S as RPCMethods, Si as PermissionConfig, Sn as ToolListUpdatedReason, Sr as ContextMessage, St as RenameSessionPayload, T as ApprovalDecision, Ti as PermissionRuleDecisionSchema, Tn as ToolUpdate, Tr as UserPromptOrigin, Tt as SessionMetadataPatch, U as ToolCallResponse, Ui as Logger, Un as ByfErrorCode, Ur as configToTomlData, Ut as WithSessionId, V as SDKSessionRPC, Vi as LogLevel, Vn as ByfErrorOptions, Vr as BearerTokenProvider, Vt as UpdateSessionMetadataPayload, W as ActivateSkillPayload, Wi as LoggingConfig, Wn as ByfErrorInfo, Wr as ensureConfigFile, Wt as proxyWithExtraPayload, X as CancelPlanPayload, Xn as Session, Xr as parseBooleanEnv, Xt as AssistantDeltaEvent, Y as CancelPayload, Yn as AgentMeta, Yr as ResolveConfigValueInput, Yt as AgentStatusUpdatedEvent, Z as CloseSessionPayload, Zn as SessionConfig, Zr as resolveConfigValue, Zt as BackgroundTaskStartedEvent, _ as ByfCoreOptions, _i as McpServerStdioConfigSchema, _n as SubagentSpawnedEvent, _r as PermissionMode, _t as PromptPart, a as collectFilesRecursive, ai as ByfConfigSchema, an as Event, ar as redact, at as ForkSessionPayload, b as RPCCallOptions, bi as OAuthRef, bn as ToolCallStartedEvent, br as CompactionResult, bt as RegisterToolPayload, c as WIRE_PROTOCOL_VERSION, ci as HookDefConfig, cn as McpOAuthAuthorizationUrlUpdateData, cr as ToolInfo, ct as GetBackgroundPayload, d as normalizeTimestampMs, di as LoopControlSchema, dn as ObservationMaskingAppliedEvent, dr as AgentRecord, dt as JsonValue, ei as resolveConfigPath, en as CompactionBlockedEvent, er as TelemetryClient, et as CreateSessionPayload, f as scanSessionWire, fi as McpServerConfig, fn as PruningAppliedEvent, fr as AgentRecordEvents, ft as ListSessionsPayload, g as ByfCore, gi as McpServerStdioConfig, gn as SubagentFailedEvent, gr as PermissionApprovalResultRecord, gt as PromptInput, h as AgentType, hi as McpServerHttpConfigSchema, hn as SubagentCompletedEvent, hr as UsageRecordScope, ht as PlanData, i as ExtraZipEntry, ii as ByfConfigPatchSchema, in as ErrorEvent, ir as log, it as ExportSessionResult, j as QuestionItem, ji as ProviderTypeSchema, jn as TurnStepRetryingEvent, jr as LoopToolCallEvent, jt as SetPermissionPayload, k as QuestionAnswerMethod, ki as ProviderConfigSchema, kn as TurnStepCompletedEvent, kr as LoopStepBeginEvent, kt as SetModelPayload, l as buildExportManifest, li as HookDefSchema, ln as McpServerStatusEvent, lr as ToolSource, lt as JsonObject, m as AgentConfig, mi as McpServerHttpConfig, mn as SkillActivatedEvent, mr as AgentRecordPersistence, mt as McpStartupMetrics, n as ResolveLoggingInput, ni as BackgroundConfig, nn as CompactionCompletedEvent, nr as flushDiagnosticLogs, nt as ExportSessionManifest, o as writeExportZip, oi as ByfServiceConfig, on as HookResultEvent, or as resolveGlobalLogPath, ot as GetBackgroundOutputPathPayload, p as Agent, pi as McpServerConfigSchema, pn as SessionMetaUpdatedEvent, pr as AgentRecordOf, pt as McpServerInfo, q as ByfConfig, qi as SessionLogHandle, qn as SessionSubagentHost, qr as transformTomlData, qt as ResumedAgentState, r as resolveLoggingConfig, ri as BackgroundConfigSchema, rn as CompactionStartedEvent, rr as getRootLogger, rt as ExportSessionPayload, s as exportSessionDirectory, si as ByfServiceConfigSchema, sn as MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE, sr as BuiltinTool, st as GetBackgroundOutputPayload, t as buildPromptPlan, ti as mergeConfigPatch, tn as CompactionCancelledEvent, tr as TelemetryProperties, tt as EmptyPayload, u as SessionWireScan, ui as LoopControl, un as McpServerStatusPayload, ur as UserToolRegistration, ut as JsonPrimitive, v as CoreRPC, vi as ModelAlias, vn as ThinkingDeltaEvent, vr as AgentConfigUpdateData, vt as PromptPayload, w as createRPC, wi as PermissionModeSchema, wn as ToolResultEvent, wr as USER_PROMPT_ORIGIN, wt as SessionAPI, x as RPCClient, xi as OAuthRefSchema, xn as ToolListUpdatedEvent, xr as AgentContextData, xt as RemoveByfProviderPayload, y as CoreRPCClient, yi as ModelAliasSchema, yn as ToolCallDeltaEvent, yr as CompactionBeginData, yt as ReconnectMcpServerPayload, z as SDKRPC, zi as LogContext, zn as toByfErrorPayload, zr as BackgroundTaskKind, zt as UnregisterToolPayload } from "./index-BfZezIU5.mjs";
3
3
  export { AGENT_WIRE_PROTOCOL_VERSION, ActivateSkillPayload, Agent, AgentAPI, AgentConfig, type AgentConfigUpdateData, type AgentContextData, AgentEvent, AgentMeta, type AgentRecord, type AgentRecordEvents, type AgentRecordOf, type AgentRecordPersistence, AgentReplayRecord, AgentStatusUpdatedEvent, AgentType, ApprovalDecision, ApprovalRequest, ApprovalResponse, ApprovalScope, AssistantDeltaEvent, BYF_ERROR_INFO, BackgroundConfig, BackgroundConfigSchema, type BackgroundLifecycleEvent, type BackgroundTaskInfo, type BackgroundTaskKind, BackgroundTaskStartedEvent, type BackgroundTaskStatus, BackgroundTaskTerminatedEvent, BackgroundTaskUpdatedEvent, type BearerTokenProvider, BeginCompactionPayload, type BuiltinTool, ByfConfigPatchSchema, ByfConfigSchema, ByfCore, ByfCoreOptions, ByfError, type ByfErrorCode, type ByfErrorInfo, type ByfErrorOptions, type ByfErrorPayload, ByfServiceConfig, ByfServiceConfigSchema, CancelPayload, CancelPlanPayload, CloseSessionPayload, type CompactionBeginData, CompactionBlockedEvent, CompactionCancelledEvent, CompactionCompletedEvent, CompactionResult, CompactionStartedEvent, type ContextMessage, CoreAPI, CoreInfo, CoreRPC, CoreRPCClient, CreateSessionPayload, EmptyPayload, ErrorCodes, ErrorEvent, Event, type ExecutableToolErrorResult, type ExecutableToolResult, type ExecutableToolSuccessResult, ExportSessionManifest, ExportSessionPayload, ExportSessionResult, ExtraZipEntry, ForkSessionPayload, GetBackgroundOutputPathPayload, GetBackgroundOutputPayload, GetBackgroundPayload, HookDefConfig, HookDefSchema, HookResultEvent, JsonObject, JsonPrimitive, JsonValue, ListSessionsPayload, type LogContext, type LogEntry, type LogLevel, type LogPayload, type Logger, type LoggingConfig, type LoopContentPartEvent, LoopControl, LoopControlSchema, type LoopRecordedEvent, type LoopStepBeginEvent, type LoopStepEndEvent, type LoopToolCallEvent, type LoopToolResultEvent, MCP_OAUTH_AUTHORIZATION_URL_TOOL_UPDATE, McpOAuthAuthorizationUrlUpdateData, McpServerConfig, McpServerConfigSchema, McpServerHttpConfig, McpServerHttpConfigSchema, McpServerInfo, McpServerStatusEvent, McpServerStatusPayload, McpServerStdioConfig, McpServerStdioConfigSchema, McpStartupMetrics, ModelAlias, ModelAliasSchema, OAuthRef, OAuthRefSchema, type OAuthTokenProviderResolver, ObservationMaskingAppliedEvent, type PermissionApprovalResultRecord, PermissionConfig, PermissionConfigSchema, type PermissionMode, PermissionModeSchema, PermissionRuleDecisionSchema, PermissionRuleSchema, PermissionRuleScopeSchema, PlanData, PromptInput, type PromptOrigin, PromptPart, PromptPayload, ProviderConfig, ProviderConfigSchema, ProviderType, ProviderTypeSchema, PruningAppliedEvent, QuestionAnswerMethod, QuestionAnswers, QuestionItem, QuestionOption, QuestionRequest, QuestionResponse, QuestionResult, RPCCallOptions, RPCClient, RPCMethods, ReconnectMcpServerPayload, RegisterToolPayload, RemoveByfProviderPayload, RenameSessionPayload, ResolveConfigValueInput, type ResolveLoggingInput, ResumeSessionPayload, ResumeSessionResult, ResumedAgentState, type RootLogger, type RuntimeConfig, SDKAPI, SDKAgentAPI, SDKAgentRPC, SDKRPC, SDKRPCClient, SDKSessionAPI, SDKSessionRPC, ServicesConfig, ServicesConfigSchema, Session, SessionAPI, type SessionAttachInput, SessionConfig, type SessionLogHandle, SessionMeta, SessionMetaUpdatedEvent, SessionMetadataPatch, SessionSkillConfig, SessionSubagentHost, SessionSummary, SessionWireScan, SetActiveToolsPayload, SetByfConfigPayload, SetModelPayload, SetModelResult, SetPermissionPayload, SetThinkingPayload, ShellExecPayload, ShellExecResult, SkillActivatedEvent, SkillSummary, SteerPayload, StopBackgroundPayload, SubagentCompletedEvent, SubagentFailedEvent, SubagentHandle, SubagentSpawnedEvent, type TelemetryClient, type TelemetryProperties, TextPromptPart, ThinkingConfig, ThinkingConfigSchema, ThinkingDeltaEvent, ToolCallDeltaEvent, ToolCallRequest, ToolCallResponse, ToolCallStartedEvent, type ToolInfo, type ToolInputDisplay, ToolListUpdatedEvent, ToolListUpdatedReason, ToolProgressEvent, ToolResultEvent, type ToolSource, type ToolStoreUpdate, ToolUpdate, TurnEndReason, TurnEndedEvent, TurnStartedEvent, TurnStepCompletedEvent, TurnStepInterruptedEvent, TurnStepRetryingEvent, TurnStepStartedEvent, USER_PROMPT_ORIGIN, UnregisterToolPayload, Unsubscribe, UpdateSessionMetadataPayload, type UsageRecordScope, UsageStatus, type UserPromptOrigin, type UserToolRegistration, WIRE_PROTOCOL_VERSION, WarningEvent, WithAgentId, WithSessionId, buildExportManifest, buildPromptPlan, collectFilesRecursive, configToTomlData, createRPC, ensureByfHome, ensureConfigFile, exportSessionDirectory, flushDiagnosticLogs, formatConfigValidationError, fromByfErrorPayload, getDefaultConfig, getRootLogger, isByfError, log, makeErrorPayload, mergeConfigPatch, normalizeTimestampMs, parseBooleanEnv, parseConfigString, proxyWithExtraPayload, readConfigFile, redact, resolveByfHome, resolveConfigPath, resolveConfigValue, resolveGlobalLogPath, resolveLoggingConfig, scanSessionWire, toByfErrorPayload, transformTomlData, validateConfig, writeConfigFile, writeExportZip };
package/dist/index.mjs CHANGED
@@ -843,17 +843,17 @@ async function loadAgentsMd(kaos, workDir) {
843
843
  return true;
844
844
  };
845
845
  const home = kaos.gethome();
846
- await collect(joinPath$2(kaos, home, ".byf", "AGENTS.md"));
847
- const genericFiles = [joinPath$2(kaos, home, ".agents")].flatMap((dir) => ["AGENTS.md", "agents.md"].map((name) => joinPath$2(kaos, dir, name)));
846
+ await collect(joinPath$1(kaos, home, ".byf", "AGENTS.md"));
847
+ const genericFiles = [joinPath$1(kaos, home, ".agents")].flatMap((dir) => ["AGENTS.md", "agents.md"].map((name) => joinPath$1(kaos, dir, name)));
848
848
  for (const file of genericFiles) if (await collect(file)) break;
849
849
  for (const dir of dirs) {
850
- await collect(joinPath$2(kaos, dir, ".byf", "AGENTS.md"));
851
- for (const fileName of ["AGENTS.md", "agents.md"]) if (await collect(joinPath$2(kaos, dir, fileName))) break;
850
+ await collect(joinPath$1(kaos, dir, ".byf", "AGENTS.md"));
851
+ for (const fileName of ["AGENTS.md", "agents.md"]) if (await collect(joinPath$1(kaos, dir, fileName))) break;
852
852
  }
853
853
  return renderAgentFiles(discovered);
854
854
  }
855
855
  async function findProjectRoot$1(kaos, workDir) {
856
- const path = pathMod$6(kaos);
856
+ const path = pathMod$5(kaos);
857
857
  const initial = kaos.normpath(workDir);
858
858
  let current = initial;
859
859
  while (true) {
@@ -864,7 +864,7 @@ async function findProjectRoot$1(kaos, workDir) {
864
864
  }
865
865
  }
866
866
  function dirsRootToLeaf(kaos, workDir, projectRoot) {
867
- const path = pathMod$6(kaos);
867
+ const path = pathMod$5(kaos);
868
868
  const dirs = [];
869
869
  let current = kaos.normpath(workDir);
870
870
  while (true) {
@@ -939,10 +939,10 @@ function byteLength(text) {
939
939
  function annotationFor(path) {
940
940
  return `<!-- From: ${path} -->\n`;
941
941
  }
942
- function joinPath$2(kaos, ...parts) {
943
- return pathMod$6(kaos).join(...parts);
942
+ function joinPath$1(kaos, ...parts) {
943
+ return pathMod$5(kaos).join(...parts);
944
944
  }
945
- function pathMod$6(kaos) {
945
+ function pathMod$5(kaos) {
946
946
  return kaos.pathClass() === "win32" ? win32Path : posixPath;
947
947
  }
948
948
  //#endregion
@@ -1195,7 +1195,7 @@ const PROFILE_SOURCES = {
1195
1195
  "profile/default/agent.yaml": agent_default$1,
1196
1196
  "profile/default/coder.yaml": coder_default,
1197
1197
  "profile/default/explore.yaml": explore_default,
1198
- "profile/default/system.md": "You are BYF, an AI agent running on the user's computer. Your job is to help\nusers accomplish tasks by taking action — read, write, search, and execute to\nmake real changes on the user's system. Answer questions when asked; otherwise,\nact.\n\nWhen responding, use the same language as the user unless explicitly instructed\notherwise.\n\n{{ ROLE_ADDITIONAL }}\n\n# First Principles\n\nThink from first principles. Strip away assumptions and conventions; every\naction must be traceable to a verifiable fact — the actual file contents,\ncommand output, data, or the user's explicit words. When in doubt, read\nbefore guessing, ask before assuming, verify before claiming.\n\n# Tool Use\n\nUse tools only when the task requires them. If the request can be answered\nwithout reading files, running commands, or searching the web, reply in text\ndirectly. When a request is ambiguous, prefer action — the user can see your\noutput and correct course.\n\nCode that only appears in your text response is NOT saved to the file system\nand will not take effect. To create or modify files, use `Write` or `Edit`.\nTo run commands, use `Bash`.\n\n# Protocol\n\n<system> tags in user or tool messages provide supplementary context. Treat\nthem as background information.\n\n<system-reminder> tags are authoritative directives that override default\nbehavior. They are unrelated to the messages they appear in. Always comply.\n\n# Safety\n\nThe environment is not a sandbox — your actions immediately affect the user's\nsystem.\n\n- Stay within the working directory unless explicitly instructed otherwise.\n- Git operations are destructive and may affect remote repositories. Never\n execute git mutations unless explicitly asked; confirm each time.\n- Avoid installing or deleting anything outside the working directory. If\n necessary, ask for confirmation first.\n\n# Working Environment\n\n## Operating System\n\nYou are running on **{{ BYF_OS }}**. The Bash tool executes commands using **{{ BYF_SHELL }}**.\n{% if BYF_OS == \"Windows\" %}\n\nIMPORTANT: You are on Windows. The Bash tool runs through Git Bash, so use Unix shell syntax inside Bash commands — `/dev/null` not `NUL`, and forward slashes in paths. For file operations, always prefer the built-in tools (Read, Write, Edit, Glob, Grep) over Bash commands — they work reliably across all platforms.\n{% endif %}\n\n## Working Directory\n\nThe current working directory is `{{ BYF_WORK_DIR }}`. This should be considered as the project root if you are instructed to perform tasks on the project. Every file system operation will be relative to the working directory if you do not explicitly specify the absolute path. Tools may require absolute paths for some parameters, IF SO, YOU MUST use absolute paths for these parameters.\n{% if BYF_ADDITIONAL_DIRS_INFO %}\n\n## Additional Directories\n\nThe following directories have been added to the workspace. You can read, write, search, and glob files in these directories as part of your workspace scope.\n\n{{ BYF_ADDITIONAL_DIRS_INFO }}\n{% endif %}\n\n# Project Information\n\n`AGENTS.md` files contain project-specific context, styles, and conventions for agents. They may exist at different locations in the project — each file governs its directory and all subdirectories beneath it. Deeper files take precedence over parent files.\n\nIf instructions conflict:\n- `<system-reminder>` directives override all other instructions, including user messages.\n- Safety rules are hard constraints and must never be violated, even if a user message or AGENTS.md says otherwise.\n- Beyond those two, user messages > AGENTS.md > default system instructions.\n\n{% if BYF_AGENTS_MD_TOO_LONG %}\n> ⚠️ The merged AGENTS.md content exceeds 4,000 tokens. Consider compressing project instructions to reduce context usage.\n{% endif %}\n\nThe `AGENTS.md` instructions (merged from all applicable directories):\n\n`````````\n{{ BYF_AGENTS_MD }}\n`````````\n\nIf you modified anything mentioned in `AGENTS.md` files, update the corresponding files to keep them up-to-date.\n\n# Skills\n\nSkills are reusable capabilities. When a skill from the listing matches the user's request, you MUST call the `Skill` tool (not free-form text).\n\n{{ BYF_SKILLS }}\n"
1198
+ "profile/default/system.md": "You are BYF, an AI agent running on the user's computer. Your job is to help\nusers accomplish tasks by taking action — read, write, search, and execute to\nmake real changes on the user's system. Answer questions when asked; otherwise,\nact.\n\nWhen responding, use the same language as the user unless explicitly instructed\notherwise.\n\n{{ ROLE_ADDITIONAL }}\n\n# First Principles\n\nThink from first principles. Strip away assumptions and conventions; every\naction must be traceable to a verifiable fact — the actual file contents,\ncommand output, data, or the user's explicit words. When in doubt, read\nbefore guessing, ask before assuming, verify before claiming.\n\n# Tool Use\n\nUse tools only when the task requires them. If the request can be answered\nwithout reading files, running commands, or searching the web, reply in text\ndirectly. When a request is ambiguous, prefer action — the user can see your\noutput and correct course.\n\nCode that only appears in your text response is NOT saved to the file system\nand will not take effect. To create or modify files, use `Write` or `Edit`.\nTo run commands, use `Bash`.\n\n# Protocol\n\n<system> tags in user or tool messages provide supplementary context. Treat\nthem as background information.\n\n<system-reminder> tags are authoritative directives that override default\nbehavior. They are unrelated to the messages they appear in. Always comply.\n\n# Safety\n\nThe environment is not a sandbox — your actions immediately affect the user's\nsystem.\n\n- Stay within the working directory unless explicitly instructed otherwise.\n- Git operations are destructive and may affect remote repositories. Never\n execute git mutations unless explicitly asked; confirm each time.\n- Avoid installing or deleting anything outside the working directory. If\n necessary, ask for confirmation first.\n\n# Project Information\n\n`AGENTS.md` files contain project-specific context, styles, and conventions for agents. They may exist at different locations in the project — each file governs its directory and all subdirectories beneath it. Deeper files take precedence over parent files.\n\nIf instructions conflict:\n- `<system-reminder>` directives override all other instructions, including user messages.\n- Safety rules are hard constraints and must never be violated, even if a user message or AGENTS.md says otherwise.\n- Beyond those two, user messages > AGENTS.md > default system instructions.\n\n{% if BYF_AGENTS_MD_TOO_LONG %}\n> ⚠️ The merged AGENTS.md content exceeds 4,000 tokens. Consider compressing project instructions to reduce context usage.\n{% endif %}\n\nThe `AGENTS.md` instructions (merged from all applicable directories):\n\n`````````\n{{ BYF_AGENTS_MD }}\n`````````\n\nIf you modified anything mentioned in `AGENTS.md` files, update the corresponding files to keep them up-to-date.\n\n# Working Environment\n\n## Operating System\n\nYou are running on **{{ BYF_OS }}**. The Bash tool executes commands using **{{ BYF_SHELL }}**.\n{% if BYF_OS == \"Windows\" %}\n\nIMPORTANT: You are on Windows. The Bash tool runs through Git Bash, so use Unix shell syntax inside Bash commands — `/dev/null` not `NUL`, and forward slashes in paths. For file operations, always prefer the built-in tools (Read, Write, Edit, Glob, Grep) over Bash commands — they work reliably across all platforms.\n{% endif %}\n\n## Working Directory\n\nThe current working directory is `{{ BYF_WORK_DIR }}`. This should be considered as the project root if you are instructed to perform tasks on the project. Every file system operation will be relative to the working directory if you do not explicitly specify the absolute path. Tools may require absolute paths for some parameters, IF SO, YOU MUST use absolute paths for these parameters.\n{% if BYF_ADDITIONAL_DIRS_INFO %}\n\n## Additional Directories\n\nThe following directories have been added to the workspace. You can read, write, search, and glob files in these directories as part of your workspace scope.\n\n{{ BYF_ADDITIONAL_DIRS_INFO }}\n{% endif %}\n\n# Skills\n\nSkills are reusable capabilities. When a skill from the listing matches the user's request, you MUST call the `Skill` tool (not free-form text).\n\n{{ BYF_SKILLS }}\n"
1199
1199
  };
1200
1200
  const DEFAULT_INIT_PROMPT = init_default;
1201
1201
  const DEFAULT_AGENT_PROFILES = loadAgentProfilesFromSources([
@@ -1621,6 +1621,7 @@ var BackgroundProcessManager = class {
1621
1621
  const kind = opts?.kind;
1622
1622
  const taskId = generateTaskId(kind ?? "bash");
1623
1623
  const entry = {
1624
+ kind: "process",
1624
1625
  taskId,
1625
1626
  command,
1626
1627
  description,
@@ -1820,9 +1821,10 @@ var BackgroundProcessManager = class {
1820
1821
  entry.approvalReason = void 0;
1821
1822
  entry.stopRequested = true;
1822
1823
  entry.stopReason = stopReason;
1823
- try {
1824
+ if (entry.kind === "process") try {
1824
1825
  await entry.proc.kill("SIGTERM");
1825
1826
  } catch {}
1827
+ else entry.abort();
1826
1828
  let graceTimer;
1827
1829
  const graceful = await Promise.race([entry.lifecyclePromise.then(() => true, () => true), new Promise((resolve) => {
1828
1830
  graceTimer = setTimeout(() => {
@@ -1834,9 +1836,11 @@ var BackgroundProcessManager = class {
1834
1836
  await entry.persistWriteQueue;
1835
1837
  return this.toInfo(entry);
1836
1838
  }
1837
- if (!graceful && entry.proc.exitCode === null) try {
1838
- await entry.proc.kill("SIGKILL");
1839
- } catch {}
1839
+ if (!graceful) if (entry.kind === "process") {
1840
+ if (entry.proc.exitCode === null) try {
1841
+ await entry.proc.kill("SIGKILL");
1842
+ } catch {}
1843
+ } else entry.abort();
1840
1844
  if (TERMINAL_STATUSES.has(entry.status)) {
1841
1845
  await entry.persistWriteQueue;
1842
1846
  return this.toInfo(entry);
@@ -1894,32 +1898,15 @@ var BackgroundProcessManager = class {
1894
1898
  else this.assertCanRegister();
1895
1899
  const taskId = generateTaskId("agent");
1896
1900
  const entry = {
1901
+ kind: "promise",
1897
1902
  taskId,
1898
1903
  command: `[agent] ${description}`,
1899
1904
  description,
1900
1905
  timeoutMs: opts.timeoutMs,
1906
+ completion,
1907
+ abort: () => opts.abort?.(),
1901
1908
  agentId: opts.agentId ?? taskId,
1902
1909
  subagentType: opts.subagentType ?? "agent",
1903
- proc: {
1904
- stdin: {
1905
- write: () => false,
1906
- end: () => {}
1907
- },
1908
- stdout: {
1909
- setEncoding: () => {},
1910
- on: () => {}
1911
- },
1912
- stderr: {
1913
- setEncoding: () => {},
1914
- on: () => {}
1915
- },
1916
- pid: 0,
1917
- exitCode: null,
1918
- wait: () => completion.then(() => 0),
1919
- kill: async () => {
1920
- opts.abort?.();
1921
- }
1922
- },
1923
1910
  outputChunks: [],
1924
1911
  outputSizeBytes: 0,
1925
1912
  status: "running",
@@ -2095,7 +2082,7 @@ var BackgroundProcessManager = class {
2095
2082
  if (this.sessionDir !== void 0) await removeTask(this.sessionDir, taskId);
2096
2083
  }
2097
2084
  /**
2098
- * Persist the current state of a live ManagedProcess. Called from
2085
+ * Persist the current state of a live TaskEntry. Called from
2099
2086
  * `register()` and the lifecycle finally block. No-op unless attached.
2100
2087
  */
2101
2088
  persistLive(entry) {
@@ -2105,7 +2092,7 @@ var BackgroundProcessManager = class {
2105
2092
  task_id: entry.taskId,
2106
2093
  command: entry.command,
2107
2094
  description: entry.description,
2108
- pid: entry.proc.pid,
2095
+ pid: entry.kind === "process" ? entry.proc.pid : 0,
2109
2096
  started_at: entry.startedAt,
2110
2097
  ended_at: entry.endedAt,
2111
2098
  exit_code: entry.exitCode,
@@ -2151,7 +2138,7 @@ var BackgroundProcessManager = class {
2151
2138
  }
2152
2139
  observedExitCompletions() {
2153
2140
  const completions = [];
2154
- for (const entry of this.processes.values()) if (!TERMINAL_STATUSES.has(entry.status) && entry.proc.exitCode !== null) completions.push(entry.lifecyclePromise);
2141
+ for (const entry of this.processes.values()) if (entry.kind === "process" && !TERMINAL_STATUSES.has(entry.status) && entry.proc.exitCode !== null) completions.push(entry.lifecyclePromise);
2155
2142
  return completions;
2156
2143
  }
2157
2144
  toInfo(entry) {
@@ -2160,7 +2147,7 @@ var BackgroundProcessManager = class {
2160
2147
  command: entry.command,
2161
2148
  description: entry.description,
2162
2149
  status: entry.status,
2163
- pid: entry.proc.pid,
2150
+ pid: entry.kind === "process" ? entry.proc.pid : null,
2164
2151
  exitCode: entry.exitCode,
2165
2152
  startedAt: entry.startedAt,
2166
2153
  endedAt: entry.endedAt,
@@ -2208,7 +2195,7 @@ function infoToPersisted(info) {
2208
2195
  task_id: info.taskId,
2209
2196
  command: info.command,
2210
2197
  description: info.description,
2211
- pid: info.pid,
2198
+ pid: info.pid ?? 0,
2212
2199
  started_at: info.startedAt,
2213
2200
  ended_at: info.endedAt,
2214
2201
  exit_code: info.exitCode,
@@ -3605,14 +3592,14 @@ const SENSITIVE_DOT_VARIANT_SUFFIXES = [
3605
3592
  ];
3606
3593
  const SENSITIVE_DOT_VARIANT_SUFFIX_SET = new Set(SENSITIVE_DOT_VARIANT_SUFFIXES);
3607
3594
  const DEFAULT_PATH_CLASS$1 = nativePath.sep === "\\" ? "win32" : "posix";
3608
- function pathMod$5(pathClass) {
3595
+ function pathMod$4(pathClass) {
3609
3596
  return pathClass === "win32" ? win32Path : posixPath;
3610
3597
  }
3611
3598
  function comparable(path, pathClass) {
3612
3599
  return pathClass === "win32" ? path.toLowerCase() : path;
3613
3600
  }
3614
3601
  function isSensitiveFile(path, pathClass = DEFAULT_PATH_CLASS$1) {
3615
- const mod = pathMod$5(pathClass);
3602
+ const mod = pathMod$4(pathClass);
3616
3603
  const comparableName = comparable(mod.basename(path), pathClass);
3617
3604
  const comparablePath = comparable(path, pathClass);
3618
3605
  if (ENV_EXEMPTIONS.has(comparableName)) return false;
@@ -3666,7 +3653,7 @@ var PathSecurityError = class extends Error {
3666
3653
  }
3667
3654
  };
3668
3655
  const DEFAULT_PATH_CLASS = nativePath.sep === "\\" ? "win32" : "posix";
3669
- function pathMod$4(pathClass) {
3656
+ function pathMod$3(pathClass) {
3670
3657
  return pathClass === "win32" ? win32Path : posixPath;
3671
3658
  }
3672
3659
  function comparablePath(path, pathClass) {
@@ -3696,7 +3683,7 @@ function normalizeUserPath(path, pathClass = DEFAULT_PATH_CLASS) {
3696
3683
  function expandUserPath$1(path, homeDir, pathClass) {
3697
3684
  if (homeDir === void 0) return path;
3698
3685
  if (path === "~") return homeDir;
3699
- if (path.startsWith("~/") || pathClass === "win32" && path.startsWith("~\\")) return pathMod$4(pathClass).join(homeDir, path.slice(2));
3686
+ if (path.startsWith("~/") || pathClass === "win32" && path.startsWith("~\\")) return pathMod$3(pathClass).join(homeDir, path.slice(2));
3700
3687
  return path;
3701
3688
  }
3702
3689
  /**
@@ -3705,7 +3692,7 @@ function expandUserPath$1(path, homeDir, pathClass) {
3705
3692
  */
3706
3693
  function canonicalizePath(path, cwd, pathClass = DEFAULT_PATH_CLASS) {
3707
3694
  if (path === "") throw new PathSecurityError("PATH_INVALID", path, path, "Path cannot be empty");
3708
- const mod = pathMod$4(pathClass);
3695
+ const mod = pathMod$3(pathClass);
3709
3696
  const normalizedPath = normalizeUserPath(path, pathClass);
3710
3697
  if (pathClass === "win32" && isWin32DriveRelative(normalizedPath)) throw new PathSecurityError("PATH_INVALID", path, normalizedPath, `"${path}" is a drive-relative Windows path. Use an absolute path like C:\\path or a path relative to the working directory.`);
3711
3698
  if (!mod.isAbsolute(normalizedPath) && !mod.isAbsolute(cwd)) throw new PathSecurityError("PATH_INVALID", path, normalizedPath, `Cannot resolve "${path}" against non-absolute cwd "${cwd}".`);
@@ -3717,7 +3704,7 @@ function canonicalizePath(path, cwd, pathClass = DEFAULT_PATH_CLASS) {
3717
3704
  * on path-component boundaries. Both arguments must already be canonical.
3718
3705
  */
3719
3706
  function isWithinDirectory(candidate, base, pathClass = DEFAULT_PATH_CLASS) {
3720
- const mod = pathMod$4(pathClass);
3707
+ const mod = pathMod$3(pathClass);
3721
3708
  const comparableCandidate = comparablePath(candidate, pathClass);
3722
3709
  const comparableBase = comparablePath(base, pathClass);
3723
3710
  if (comparableCandidate === comparableBase) return true;
@@ -3743,7 +3730,7 @@ function relativeOutsideMessage(path, operation) {
3743
3730
  }
3744
3731
  function resolvePathAccess(path, cwd, config, options) {
3745
3732
  const pathClass = options.pathClass ?? DEFAULT_PATH_CLASS;
3746
- const mod = pathMod$4(pathClass);
3733
+ const mod = pathMod$3(pathClass);
3747
3734
  const expandedPath = expandUserPath$1(normalizeUserPath(path, pathClass), options.homeDir, pathClass);
3748
3735
  const rawIsAbsolute = mod.isAbsolute(expandedPath);
3749
3736
  const canonical = canonicalizePath(expandedPath, cwd, pathClass);
@@ -3898,11 +3885,11 @@ var EditTool = class {
3898
3885
  }
3899
3886
  }
3900
3887
  };
3901
- async function collectEntries$1(kaos, dirPath, maxWidth, pathClass) {
3888
+ async function collectEntries(kaos, dirPath, maxWidth, pathClass) {
3902
3889
  const all = [];
3903
3890
  try {
3904
3891
  for await (const fullPath of kaos.iterdir(dirPath)) {
3905
- const name = basename$2(fullPath, pathClass);
3892
+ const name = basename$1(fullPath, pathClass);
3906
3893
  let isDir = false;
3907
3894
  try {
3908
3895
  isDir = ((await kaos.stat(fullPath)).stMode & 61440) === 16384;
@@ -3929,11 +3916,11 @@ async function collectEntries$1(kaos, dirPath, maxWidth, pathClass) {
3929
3916
  readable: true
3930
3917
  };
3931
3918
  }
3932
- function pathMod$3(pathClass) {
3919
+ function pathMod$2(pathClass) {
3933
3920
  return pathClass === "win32" ? win32Path : posixPath;
3934
3921
  }
3935
- function basename$2(p, pathClass) {
3936
- return pathMod$3(pathClass).basename(p);
3922
+ function basename$1(p, pathClass) {
3923
+ return pathMod$2(pathClass).basename(p);
3937
3924
  }
3938
3925
  /**
3939
3926
  * Return a 2-level tree listing of `workDir` suitable for inclusion in a
@@ -3943,7 +3930,7 @@ function basename$2(p, pathClass) {
3943
3930
  async function listDirectory(kaos, workDir) {
3944
3931
  const lines = [];
3945
3932
  const pathClass = kaos.pathClass();
3946
- const { entries, total, readable } = await collectEntries$1(kaos, workDir, 30, pathClass);
3933
+ const { entries, total, readable } = await collectEntries(kaos, workDir, 30, pathClass);
3947
3934
  if (!readable) return "[not readable]";
3948
3935
  const remaining = total - entries.length;
3949
3936
  for (let i = 0; i < entries.length; i++) {
@@ -3955,7 +3942,7 @@ async function listDirectory(kaos, workDir) {
3955
3942
  if (isDir) {
3956
3943
  lines.push(`${connector}${name}/`);
3957
3944
  const childPrefix = isLast ? " " : "│ ";
3958
- const child = await collectEntries$1(kaos, joinPath$1(workDir, name, pathClass), 10, pathClass);
3945
+ const child = await collectEntries(kaos, joinPath(workDir, name, pathClass), 10, pathClass);
3959
3946
  if (!child.readable) {
3960
3947
  lines.push(`${childPrefix}└── [not readable]`);
3961
3948
  continue;
@@ -3974,8 +3961,8 @@ async function listDirectory(kaos, workDir) {
3974
3961
  if (remaining > 0) lines.push(`└── ... and ${String(remaining)} more entries`);
3975
3962
  return lines.length > 0 ? lines.join("\n") : "(empty directory)";
3976
3963
  }
3977
- function joinPath$1(parent, child, pathClass) {
3978
- return pathMod$3(pathClass).join(parent, child);
3964
+ function joinPath(parent, child, pathClass) {
3965
+ return pathMod$2(pathClass).join(parent, child);
3979
3966
  }
3980
3967
  //#endregion
3981
3968
  //#region src/tools/builtin/file/glob.md
@@ -5955,7 +5942,7 @@ var write_default = "Overwrite or append to a file with content exactly as provi
5955
5942
  const S_IFMT$2 = 61440;
5956
5943
  /** File-type bits of a directory. */
5957
5944
  const S_IFDIR$1 = 16384;
5958
- function pathMod$2(pathClass) {
5945
+ function pathMod$1(pathClass) {
5959
5946
  return pathClass === "win32" ? win32Path : posixPath;
5960
5947
  }
5961
5948
  const WriteInputSchema = z.object({
@@ -6022,7 +6009,7 @@ var WriteTool = class {
6022
6009
  * skipped and the write proceeds, surfacing the real I/O error if any.
6023
6010
  */
6024
6011
  async checkParentDirectory(safePath) {
6025
- const parent = pathMod$2(this.kaos.pathClass()).dirname(safePath);
6012
+ const parent = pathMod$1(this.kaos.pathClass()).dirname(safePath);
6026
6013
  let stat;
6027
6014
  try {
6028
6015
  stat = await this.kaos.stat(parent);
@@ -6935,8 +6922,14 @@ function project(history, ephemeralInjections) {
6935
6922
  if (isBlockedUserPrompt(message)) return false;
6936
6923
  return !isTranscriptOnlyHookResult(message) && message.partial !== true && !(message.role === "assistant" && message.content.length === 0 && message.toolCalls.length === 0);
6937
6924
  }));
6938
- const injectionMessages = ephemeralInjections?.map((injection) => renderInjection(injection));
6939
- return injectionMessages ? [...injectionMessages, ...merged] : merged;
6925
+ if (!ephemeralInjections?.length) return merged;
6926
+ const afterSystemMsgs = ephemeralInjections.filter((injection) => !injection.position || injection.position === "after_system").map((injection) => renderInjection(injection));
6927
+ const beforeUserMsgs = ephemeralInjections.filter((injection) => injection.position === "before_user").map((injection) => renderInjection(injection));
6928
+ return [
6929
+ ...afterSystemMsgs,
6930
+ ...merged,
6931
+ ...beforeUserMsgs
6932
+ ];
6940
6933
  }
6941
6934
  function isTranscriptOnlyHookResult(message) {
6942
6935
  return message.origin?.kind === "hook_result" && TRANSCRIPT_ONLY_HOOK_RESULT_EVENTS.has(message.origin.event ?? "");
@@ -7926,7 +7919,15 @@ var ContextMemory = class {
7926
7919
  return this._history;
7927
7920
  }
7928
7921
  get messages() {
7929
- return project(this.history);
7922
+ return this.getMessages();
7923
+ }
7924
+ /**
7925
+ * Project history into provider-ready messages, optionally with
7926
+ * ephemeral injections (e.g. timestamp, permission mode) appended
7927
+ * at the `'before_user'` position.
7928
+ */
7929
+ getMessages(ephemeral) {
7930
+ return project(this.history, ephemeral);
7930
7931
  }
7931
7932
  applyObservationMasking(config) {
7932
7933
  const effectiveConfig = config ?? DEFAULT_MASKING_CONFIG;
@@ -8587,146 +8588,55 @@ var DynamicInjector = class {
8587
8588
  }
8588
8589
  };
8589
8590
  //#endregion
8590
- //#region src/agent/injection/directory-tree.ts
8591
- const EXCLUDED_DIRS = new Set([
8592
- "node_modules",
8593
- ".git",
8594
- "dist",
8595
- "build",
8596
- ".next",
8597
- ".nuxt",
8598
- ".vite",
8599
- "target",
8600
- ".turbo",
8601
- "coverage",
8602
- ".cache",
8603
- ".DS_Store",
8604
- ".idea",
8605
- ".vscode",
8606
- "venv",
8607
- ".venv"
8608
- ]);
8609
- const HIDDEN_DIR_WHITELIST = new Set([
8610
- ".github",
8611
- ".byf",
8612
- ".agents",
8613
- ".changeset",
8614
- ".husky"
8615
- ]);
8616
- var DirectoryTreeInjector = class extends DynamicInjector {
8617
- injectionVariant = "directory_tree";
8618
- lastTree;
8619
- hasInjected = false;
8620
- capturedTimestamp;
8621
- async getInjection() {
8622
- const kaos = this.agent.runtime.kaos;
8623
- const workDir = this.agent.config.cwd || kaos.getcwd();
8624
- const tree = await buildTree(kaos, workDir);
8625
- if (this.hasInjected && tree === this.lastTree) return;
8626
- this.lastTree = tree;
8627
- this.hasInjected = true;
8628
- if (this.capturedTimestamp === void 0) this.capturedTimestamp = (/* @__PURE__ */ new Date()).toISOString();
8629
- return `Current working directory structure (${workDir}):\n${tree}\n\nThe current date and time in ISO format is \`${this.capturedTimestamp}\`. This is only a reference for you when searching the web or checking file modification time, etc. If you need the exact time, use Bash tool with proper command.`;
8630
- }
8631
- };
8632
- async function buildTree(kaos, workDir) {
8633
- const lines = [];
8634
- const pathClass = kaos.pathClass();
8635
- const { entries, total, readable } = await collectEntries(kaos, workDir, 30, pathClass);
8636
- if (!readable) return "[not readable]";
8637
- const remaining = total - entries.length;
8638
- for (let i = 0; i < entries.length; i++) {
8639
- const entry = entries[i];
8640
- if (entry === void 0) continue;
8641
- const { name, isDir } = entry;
8642
- const isLast = i === entries.length - 1 && remaining === 0;
8643
- const connector = isLast ? "└── " : "├── ";
8644
- if (isDir) {
8645
- lines.push(`${connector}${name}/`);
8646
- const childPrefix = isLast ? " " : "│ ";
8647
- const child = await collectEntries(kaos, joinPath(workDir, name, pathClass), 10, pathClass);
8648
- if (!child.readable) {
8649
- lines.push(`${childPrefix}└── [not readable]`);
8650
- continue;
8651
- }
8652
- const childRemaining = child.total - child.entries.length;
8653
- for (let j = 0; j < child.entries.length; j++) {
8654
- const ce = child.entries[j];
8655
- if (ce === void 0) continue;
8656
- const cConnector = j === child.entries.length - 1 && childRemaining === 0 ? "└── " : "├── ";
8657
- const suffix = ce.isDir ? "/" : "";
8658
- lines.push(`${childPrefix}${cConnector}${ce.name}${suffix}`);
8659
- }
8660
- if (childRemaining > 0) lines.push(`${childPrefix}└── ... and ${String(childRemaining)} more`);
8661
- } else lines.push(`${connector}${name}`);
8662
- }
8663
- if (remaining > 0) lines.push(`└── ... and ${String(remaining)} more entries`);
8664
- return lines.length > 0 ? lines.join("\n") : "(empty directory)";
8665
- }
8666
- async function collectEntries(kaos, dirPath, maxWidth, pathClass) {
8667
- const all = [];
8668
- try {
8669
- for await (const fullPath of kaos.iterdir(dirPath)) {
8670
- const name = basename$1(fullPath, pathClass);
8671
- if (shouldExclude(name)) continue;
8672
- let isDir = false;
8673
- try {
8674
- isDir = ((await kaos.stat(fullPath)).stMode & 61440) === 16384;
8675
- } catch {}
8676
- all.push({
8677
- name,
8678
- isDir
8679
- });
8680
- }
8681
- } catch {
8682
- return {
8683
- entries: [],
8684
- total: 0,
8685
- readable: false
8686
- };
8687
- }
8688
- all.sort((a, b) => {
8689
- if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;
8690
- return a.name.localeCompare(b.name);
8691
- });
8692
- return {
8693
- entries: all.slice(0, maxWidth),
8694
- total: all.length,
8695
- readable: true
8696
- };
8697
- }
8698
- function shouldExclude(name) {
8699
- if (EXCLUDED_DIRS.has(name)) return true;
8700
- if (name.startsWith(".") && !HIDDEN_DIR_WHITELIST.has(name)) return true;
8701
- return false;
8702
- }
8703
- function pathMod$1(pathClass) {
8704
- return pathClass === "win32" ? win32Path : posixPath;
8705
- }
8706
- function basename$1(p, pathClass) {
8707
- return pathMod$1(pathClass).basename(p);
8708
- }
8709
- function joinPath(parent, child, pathClass) {
8710
- return pathMod$1(pathClass).join(parent, child);
8711
- }
8712
- //#endregion
8713
8591
  //#region src/agent/injection/permission-mode.ts
8714
- const AUTO_MODE_ENTER_REMINDER = [
8592
+ const AUTO_MODE_REMINDER = [
8715
8593
  "Auto permission mode is active. Tool approvals will be handled automatically while this mode remains enabled.",
8716
8594
  " - Continue normally without pausing for approval prompts.",
8717
8595
  " - Do NOT call AskUserQuestion while auto mode is active. Make a reasonable decision and continue without asking the user."
8718
8596
  ].join("\n");
8719
- const AUTO_MODE_EXIT_REMINDER = ["Auto permission mode is no longer active. Tool approvals and permission checks are back to the current mode.", " - Continue normally, but expect approval prompts or denials when a tool requires them."].join("\n");
8597
+ /**
8598
+ * Ephemeral injector for permission mode state.
8599
+ *
8600
+ * Emits the current permission mode as an ephemeral injection placed at
8601
+ * the `'before_user'` position. Unlike the previous persistent approach
8602
+ * (which recorded transition events into history), the ephemeral approach
8603
+ * always reflects the current state — surviving compaction and avoiding
8604
+ * history pollution.
8605
+ *
8606
+ * Only auto mode produces an injection; in all other modes the absence
8607
+ * of a reminder signals that normal approval prompts apply.
8608
+ */
8720
8609
  var PermissionModeInjector = class extends DynamicInjector {
8721
8610
  injectionVariant = "permission_mode";
8722
- lastMode;
8723
- getInjection() {
8724
- const mode = this.agent.permission.mode;
8725
- const previousMode = this.lastMode;
8726
- if (mode === previousMode) return void 0;
8727
- this.lastMode = mode;
8728
- if (mode === "auto") return AUTO_MODE_ENTER_REMINDER;
8729
- if (previousMode === "auto") return AUTO_MODE_EXIT_REMINDER;
8611
+ getInjection() {}
8612
+ getEphemeral() {
8613
+ if (this.agent.permission.mode !== "auto") return [];
8614
+ return [{
8615
+ kind: "system_reminder",
8616
+ content: AUTO_MODE_REMINDER,
8617
+ position: "before_user"
8618
+ }];
8619
+ }
8620
+ };
8621
+ //#endregion
8622
+ //#region src/agent/injection/timestamp.ts
8623
+ /**
8624
+ * Ephemeral injector that provides the current timestamp at request time.
8625
+ *
8626
+ * The timestamp is rendered fresh on every step (not frozen) and placed
8627
+ * at the `'before_user'` position so it never breaks the cached prefix.
8628
+ * This aligns with the prompt-cache best practice of keeping per-request
8629
+ * dynamic content out of the cacheable system-prompt blocks.
8630
+ */
8631
+ var TimestampInjector = class extends DynamicInjector {
8632
+ injectionVariant = "timestamp";
8633
+ getInjection() {}
8634
+ getEphemeral() {
8635
+ return [{
8636
+ kind: "system_reminder",
8637
+ content: `The current date and time in ISO format is \`${(/* @__PURE__ */ new Date()).toISOString()}\`. This is only a reference for you when searching the web or checking file modification time, etc. If you need the exact time, use Bash tool with proper command.`,
8638
+ position: "before_user"
8639
+ }];
8730
8640
  }
8731
8641
  };
8732
8642
  //#endregion
@@ -8736,11 +8646,20 @@ var InjectionManager = class {
8736
8646
  injectors;
8737
8647
  constructor(agent) {
8738
8648
  this.agent = agent;
8739
- this.injectors = [new PermissionModeInjector(agent), new DirectoryTreeInjector(agent)];
8649
+ this.injectors = [new PermissionModeInjector(agent), new TimestampInjector(agent)];
8740
8650
  }
8741
8651
  async inject() {
8742
8652
  for (const injector of this.injectors) await injector.inject();
8743
8653
  }
8654
+ getEphemeralInjections() {
8655
+ return this.injectors.flatMap((injector) => {
8656
+ try {
8657
+ return injector.getEphemeral?.() ?? [];
8658
+ } catch {
8659
+ return [];
8660
+ }
8661
+ });
8662
+ }
8744
8663
  onContextClear() {
8745
8664
  for (const injector of this.injectors) injector.onContextClear();
8746
8665
  }
@@ -13718,20 +13637,25 @@ const CACHE_BOUNDARY_MARKER = "__CACHE_BOUNDARY__";
13718
13637
  *
13719
13638
  * These headers mark natural breaks in the system prompt where cache boundaries should be placed:
13720
13639
  * - "# Project Information" marks the start of project-specific content
13640
+ * - "# Working Environment" marks the start of session-specific environment (OS, working directory)
13721
13641
  * - "# Skills" marks the start of session-specific skills listing
13722
13642
  */
13723
- const IMPLICIT_BOUNDARY_HEADERS = ["# Project Information", "# Skills"];
13643
+ const IMPLICIT_BOUNDARY_HEADERS = [
13644
+ "# Project Information",
13645
+ "# Working Environment",
13646
+ "# Skills"
13647
+ ];
13724
13648
  /**
13725
13649
  * Block names by position.
13726
13650
  *
13727
13651
  * - First block (before first marker): 'base'
13728
13652
  * - Last block (after last marker): 'sessionContext'
13729
- * - Intermediate blocks: Sequential names from 'projectInstructions', 'skillsListing', etc.
13653
+ * - Intermediate blocks: Sequential names from 'projectInstructions', 'workingEnvironment', etc.
13730
13654
  */
13731
13655
  const BLOCK_NAMES = [
13732
13656
  "base",
13733
13657
  "projectInstructions",
13734
- "skillsListing",
13658
+ "workingEnvironment",
13735
13659
  "sessionContext"
13736
13660
  ];
13737
13661
  /**
@@ -14555,8 +14479,8 @@ var TurnFlow = class {
14555
14479
  completionBudgetConfig
14556
14480
  }),
14557
14481
  buildMessages: () => {
14558
- const messages = this.agent.context.messages;
14559
- return applyCacheStaking(messages, { previousTurnMessageCount: this._previousTurnMessageCount });
14482
+ const ephemeral = this.agent.injection.getEphemeralInjections();
14483
+ return applyCacheStaking(this.agent.context.getMessages(ephemeral), { previousTurnMessageCount: this._previousTurnMessageCount });
14560
14484
  },
14561
14485
  dispatchEvent: this.buildDispatchEvent(turnId),
14562
14486
  tools: this.agent.tools.loopTools,
@@ -16868,7 +16792,7 @@ var SessionSubagentHost = class {
16868
16792
  const { id, agent } = await this.session.createAgent({
16869
16793
  type: "sub",
16870
16794
  generate: parent.rawGenerate
16871
- }, void 0, this.ownerAgentId);
16795
+ }, void 0, this.ownerAgentId, options.parentToolCallId);
16872
16796
  const controller = new AbortController();
16873
16797
  const unlinkAbortSignal = linkAbortSignal(options.signal, controller);
16874
16798
  this.activeChildren.set(id, {
@@ -17167,7 +17091,7 @@ var Session = class {
17167
17091
  })) return;
17168
17092
  await Promise.all(Array.from(this.agents.values(), (agent) => agent.background.stopAll("Session closed")));
17169
17093
  }
17170
- async createAgent(config, profile, parentAgentId) {
17094
+ async createAgent(config, profile, parentAgentId, parentToolCallId) {
17171
17095
  await this.skillsReady;
17172
17096
  const type = config.type ?? "main";
17173
17097
  const id = type === "main" ? "main" : this.nextGeneratedAgentId();
@@ -17179,7 +17103,8 @@ var Session = class {
17179
17103
  this.metadata.agents[id] = {
17180
17104
  homedir,
17181
17105
  type,
17182
- parentAgentId: parentAgentId ?? null
17106
+ parentAgentId: parentAgentId ?? null,
17107
+ parentToolCallId
17183
17108
  };
17184
17109
  this.writeMetadata();
17185
17110
  return {
@@ -20124,7 +20049,8 @@ async function resumeSessionResult(summary, session, warning) {
20124
20049
  usage,
20125
20050
  tools: await api.getTools({ agentId }),
20126
20051
  toolStore: agent.tools.storeData(),
20127
- background: agent.background.list(false)
20052
+ background: agent.background.list(false),
20053
+ parentToolCallId: session.metadata.agents[agentId]?.parentToolCallId
20128
20054
  };
20129
20055
  }
20130
20056
  return {
@@ -1,4 +1,4 @@
1
- import { Et as SessionSummary, ft as ListSessionsPayload, lt as JsonObject } from "../../index-Bi8MjEPf.mjs";
1
+ import { Et as SessionSummary, ft as ListSessionsPayload, lt as JsonObject } from "../../index-BfZezIU5.mjs";
2
2
 
3
3
  //#region src/session/store/session-store.d.ts
4
4
  interface CreateSessionRecordInput {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byfriends/agent-core",
3
- "version": "0.2.5",
3
+ "version": "0.3.0",
4
4
  "description": "Unified agent engine for BYF",
5
5
  "license": "Proprietary",
6
6
  "author": "ByronFinn",
@@ -70,7 +70,7 @@
70
70
  "yauzl": "^3.3.0",
71
71
  "zod": "^4.3.6",
72
72
  "@byfriends/kaos": "^0.2.2",
73
- "@byfriends/kosong": "^0.2.2"
73
+ "@byfriends/kosong": "^0.2.3"
74
74
  },
75
75
  "devDependencies": {
76
76
  "@types/js-yaml": "^4.0.9",