@robota-sdk/agent-sdk 3.0.0-beta.60 → 3.0.0-beta.61

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.
@@ -45,6 +45,7 @@ __export(index_exports, {
45
45
  COST_COMMAND_DESCRIPTION: () => COST_COMMAND_DESCRIPTION,
46
46
  CommandRegistry: () => CommandRegistry,
47
47
  DEFAULT_AUTO_COMPACT_THRESHOLD: () => DEFAULT_AUTO_COMPACT_THRESHOLD,
48
+ DEFAULT_BACKGROUND_TASK_LOG_PAGE_SIZE: () => import_agent_runtime4.DEFAULT_BACKGROUND_TASK_LOG_PAGE_SIZE,
48
49
  DEFAULT_STATUS_LINE_COMMAND_SETTINGS: () => DEFAULT_STATUS_LINE_COMMAND_SETTINGS,
49
50
  EXIT_COMMAND_DESCRIPTION: () => EXIT_COMMAND_DESCRIPTION,
50
51
  EditCheckpointStore: () => EditCheckpointStore,
@@ -59,12 +60,14 @@ __export(index_exports, {
59
60
  MEMORY_INDEX_MAX_LINES: () => MEMORY_INDEX_MAX_LINES,
60
61
  MODEL_COMMAND_ARGUMENT_HINT: () => MODEL_COMMAND_ARGUMENT_HINT,
61
62
  MODEL_COMMAND_DESCRIPTION: () => MODEL_COMMAND_DESCRIPTION,
63
+ MODEL_COMMAND_TOOL_PREFIX: () => MODEL_COMMAND_TOOL_PREFIX,
62
64
  MarketplaceClient: () => MarketplaceClient,
63
65
  PERMISSIONS_COMMAND_DESCRIPTION: () => PERMISSIONS_COMMAND_DESCRIPTION,
64
66
  PERMISSION_MODE_ARGUMENT_HINT: () => PERMISSION_MODE_ARGUMENT_HINT,
65
67
  PERMISSION_MODE_COMMAND_DESCRIPTION: () => PERMISSION_MODE_COMMAND_DESCRIPTION,
66
68
  PLUGIN_COMMAND_ARGUMENT_HINT: () => PLUGIN_COMMAND_ARGUMENT_HINT,
67
69
  PLUGIN_COMMAND_DESCRIPTION: () => PLUGIN_COMMAND_DESCRIPTION,
70
+ PROVIDER_SAFE_TOOL_NAME_PATTERN: () => PROVIDER_SAFE_TOOL_NAME_PATTERN,
68
71
  PluginCommandSource: () => PluginCommandSource,
69
72
  PluginSettingsStore: () => PluginSettingsStore,
70
73
  ProjectMemoryStore: () => ProjectMemoryStore,
@@ -81,9 +84,11 @@ __export(index_exports, {
81
84
  SkillCommandSource: () => SkillCommandSource,
82
85
  SubagentManager: () => import_agent_runtime7.SubagentManager,
83
86
  SystemCommandExecutor: () => SystemCommandExecutor,
84
- TRUST_TO_MODE: () => import_agent_core8.TRUST_TO_MODE,
87
+ VALIDATE_SESSION_COMMAND_DESCRIPTION: () => VALIDATE_SESSION_COMMAND_DESCRIPTION,
85
88
  VALID_PERMISSION_MODES: () => VALID_PERMISSION_MODES,
86
89
  WorktreeSubagentRunner: () => import_agent_runtime8.WorktreeSubagentRunner,
90
+ addCommandContextReference: () => addCommandContextReference,
91
+ appendPrefixedLogLines: () => import_agent_runtime4.appendPrefixedLogLines,
87
92
  assembleSubagentPrompt: () => assembleSubagentPrompt,
88
93
  buildBackgroundCommandSubcommands: () => buildBackgroundCommandSubcommands,
89
94
  buildLanguageCommandSubcommands: () => buildLanguageCommandSubcommands,
@@ -91,26 +96,35 @@ __export(index_exports, {
91
96
  buildModelCommandSubcommands: () => buildModelCommandSubcommands,
92
97
  buildPermissionModeSubcommands: () => buildPermissionModeSubcommands,
93
98
  buildPluginCommandSubcommands: () => buildPluginCommandSubcommands,
99
+ buildPromptWithFileReferences: () => buildPromptWithFileReferences,
94
100
  buildProviderProfile: () => buildProviderProfile,
95
101
  buildProviderSetupPatch: () => buildProviderSetupPatch,
96
102
  buildRewindCommandSubcommands: () => buildRewindCommandSubcommands,
97
- buildSkillPrompt: () => buildSkillPrompt,
98
103
  buildStatusLineCommandSubcommands: () => buildStatusLineCommandSubcommands,
99
104
  cancelCommandBackgroundTask: () => cancelCommandBackgroundTask,
100
- chatEntryToMessage: () => import_agent_core9.chatEntryToMessage,
105
+ clearCommandContextReferences: () => clearCommandContextReferences,
106
+ clearContextReferences: () => clearContextReferences,
101
107
  clearConversationHistory: () => clearConversationHistory,
102
108
  closeCommandBackgroundTask: () => closeCommandBackgroundTask,
103
109
  compactCommandContext: () => compactCommandContext,
104
110
  createAgentTool: () => createAgentTool,
105
111
  createBackgroundProcessTool: () => createBackgroundProcessTool,
112
+ createBackgroundTaskLogPage: () => import_agent_runtime4.createBackgroundTaskLogPage,
106
113
  createBuiltinCommandModule: () => createBuiltinCommandModule,
107
114
  createCommandExecutionTool: () => createCommandExecutionTool,
108
115
  createCommandMemoryStores: () => createCommandMemoryStores,
109
116
  createCommandPendingMemoryStore: () => createCommandPendingMemoryStore,
110
117
  createCommandProjectMemoryStore: () => createCommandProjectMemoryStore,
118
+ createContextReferenceItem: () => createContextReferenceItem,
111
119
  createDefaultTools: () => createDefaultTools,
120
+ createLimitedOutputCapture: () => import_agent_runtime4.createLimitedOutputCapture,
121
+ createModelCommandToolProjection: () => createModelCommandToolProjection,
112
122
  createPluginRegistryReloadRequestedEffect: () => createPluginRegistryReloadRequestedEffect,
113
123
  createPluginTuiRequestedEffect: () => createPluginTuiRequestedEffect,
124
+ createProjectSessionStore: () => createProjectSessionStore,
125
+ createProjectedCommandExecutionTools: () => createProjectedCommandExecutionTools,
126
+ createPromptFileReferenceHistoryEntry: () => createPromptFileReferenceHistoryEntry,
127
+ createProviderSafeModelCommandToolName: () => createProviderSafeModelCommandToolName,
114
128
  createProviderSetupFlow: () => createProviderSetupFlow,
115
129
  createQuery: () => createQuery,
116
130
  createSessionExitRequestedEffect: () => createSessionExitRequestedEffect,
@@ -120,48 +134,57 @@ __export(index_exports, {
120
134
  createSubagentSession: () => createSubagentSession,
121
135
  createSystemCommands: () => createSystemCommands,
122
136
  createWorktreeSubagentRunner: () => import_agent_runtime8.createWorktreeSubagentRunner,
137
+ deleteProviderProfile: () => deleteProviderProfile,
123
138
  discoverTaskFiles: () => discoverTaskFiles,
124
- evaluatePermission: () => import_agent_core10.evaluatePermission,
125
139
  evaluateReversibleToolSafety: () => evaluateReversibleToolSafety,
126
140
  executeSkill: () => executeSkill,
127
141
  formatCommandBackgroundTask: () => formatCommandBackgroundTask,
128
142
  formatCommandBackgroundTaskList: () => formatCommandBackgroundTaskList,
129
143
  formatCommandHelpMessage: () => formatCommandHelpMessage,
130
144
  formatCommandPermissionsMessage: () => formatCommandPermissionsMessage,
145
+ formatCommandSessionReplayValidationReport: () => formatCommandSessionReplayValidationReport,
131
146
  formatEnvReference: () => formatEnvReference,
132
147
  formatInvalidPermissionModeMessage: () => formatInvalidPermissionModeMessage,
133
148
  formatLanguageUsageMessage: () => formatLanguageUsageMessage,
149
+ formatModelCommandUsageMessage: () => formatModelCommandUsageMessage,
150
+ formatModelCommandUsageMessageAsync: () => formatModelCommandUsageMessageAsync,
151
+ formatProjectedModelCommandToolPromptDescription: () => formatProjectedModelCommandToolPromptDescription,
152
+ formatPromptFileReferenceDiagnostics: () => formatPromptFileReferenceDiagnostics,
134
153
  formatProviderSetupChoiceLabel: () => formatProviderSetupChoiceLabel,
154
+ formatProviderSetupHelpLinks: () => formatProviderSetupHelpLinks,
135
155
  formatProviderSetupPromptLabel: () => formatProviderSetupPromptLabel,
136
156
  formatProviderSetupSelectionPrompt: () => formatProviderSetupSelectionPrompt,
137
157
  formatTaskContext: () => formatTaskContext,
138
158
  getBackgroundTaskTransitions: () => import_agent_runtime4.getBackgroundTaskTransitions,
139
159
  getBuiltInAgent: () => getBuiltInAgent,
140
160
  getForkWorkerSuffix: () => getForkWorkerSuffix,
141
- getMessagesForAPI: () => import_agent_core9.getMessagesForAPI,
142
161
  getProviderSetupStep: () => getProviderSetupStep,
143
162
  getSubagentSuffix: () => getSubagentSuffix,
163
+ hasBlockingPromptFileReferenceDiagnostics: () => hasBlockingPromptFileReferenceDiagnostics,
144
164
  hasSensitiveCommandMemoryContent: () => hasSensitiveCommandMemoryContent,
145
165
  hasUsableSecretReference: () => hasUsableSecretReference,
146
166
  inspectCommandEditCheckpoint: () => inspectCommandEditCheckpoint,
147
- isChatEntry: () => import_agent_core9.isChatEntry,
148
167
  isCommandMemoryType: () => isCommandMemoryType,
149
168
  isEnvReference: () => isEnvReference,
150
169
  isMemoryType: () => isMemoryType,
151
170
  isPermissionMode: () => isPermissionMode,
152
171
  isStatusLineCommandSettingsPatch: () => isStatusLineCommandSettingsPatch,
153
172
  isTerminalBackgroundTaskStatus: () => import_agent_runtime4.isTerminalBackgroundTaskStatus,
173
+ listActiveContextReferences: () => listActiveContextReferences,
154
174
  listCommandBackgroundTasks: () => listCommandBackgroundTasks,
175
+ listCommandContextReferences: () => listCommandContextReferences,
155
176
  listCommandEditCheckpoints: () => listCommandEditCheckpoints,
156
177
  listCommandSessionAllowedTools: () => listCommandSessionAllowedTools,
157
178
  listCommandUsedMemoryReferences: () => listCommandUsedMemoryReferences,
179
+ listResumableSessionSummaries: () => listResumableSessionSummaries,
158
180
  loadTaskContext: () => loadTaskContext,
159
181
  mergeProviderPatch: () => mergeProviderPatch,
160
- messageToHistoryEntry: () => import_agent_core9.messageToHistoryEntry,
182
+ normalizeModelCommandName: () => normalizeModelCommandName,
161
183
  parseCommandBackgroundLogCursor: () => parseCommandBackgroundLogCursor,
162
184
  parseFrontmatter: () => parseFrontmatter,
163
185
  parseLanguageArgument: () => parseLanguageArgument,
164
186
  parsePermissionModeArgument: () => parsePermissionModeArgument,
187
+ parsePromptFileReferences: () => parsePromptFileReferences,
165
188
  parseSessionNameArgument: () => parseSessionNameArgument,
166
189
  parseTaskFile: () => parseTaskFile,
167
190
  planSelfHostingVerification: () => planSelfHostingVerification,
@@ -178,30 +201,43 @@ __export(index_exports, {
178
201
  readCommandSessionInfo: () => readCommandSessionInfo,
179
202
  readCurrentGitBranch: () => readCurrentGitBranch,
180
203
  recordCommandMemoryEvent: () => recordCommandMemoryEvent,
204
+ removeCommandContextReference: () => removeCommandContextReference,
205
+ removeContextReference: () => removeContextReference,
181
206
  resetAutoCompactThresholdSetting: () => resetAutoCompactThresholdSetting,
207
+ resolveActiveProviderModelCatalog: () => resolveActiveProviderModelCatalog,
208
+ resolveActiveProviderModelCatalogState: () => resolveActiveProviderModelCatalogState,
182
209
  resolveEnvReference: () => resolveEnvReference,
210
+ resolveLatestSessionId: () => resolveLatestSessionId,
183
211
  resolvePermissionModeAdapter: () => resolvePermissionModeAdapter,
184
212
  resolvePluginCommandAdapter: () => resolvePluginCommandAdapter,
213
+ resolvePromptFileReferencePaths: () => resolvePromptFileReferencePaths,
214
+ resolvePromptFileReferences: () => resolvePromptFileReferences,
185
215
  resolveProviderSetupSelection: () => resolveProviderSetupSelection,
216
+ resolveSessionIdByIdOrName: () => resolveSessionIdByIdOrName,
186
217
  resolveSubagentLogDir: () => resolveSubagentLogDir,
187
218
  restoreCommandEditCheckpoint: () => restoreCommandEditCheckpoint,
188
219
  retrieveAgentToolDeps: () => retrieveAgentToolDeps,
189
220
  rollbackCommandEditCheckpoint: () => rollbackCommandEditCheckpoint,
190
- runHooks: () => import_agent_core11.runHooks,
191
221
  runProviderSetupPromptFlow: () => runProviderSetupPromptFlow,
222
+ sanitizeProviderProfileName: () => sanitizeProviderProfileName,
192
223
  selectRelevantTasks: () => selectRelevantTasks,
193
224
  setCommandAutoCompactThreshold: () => setCommandAutoCompactThreshold,
194
225
  setCurrentProvider: () => setCurrentProvider,
195
226
  storeAgentToolDeps: () => storeAgentToolDeps,
196
227
  submitProviderSetupValue: () => submitProviderSetupValue,
197
228
  substituteVariables: () => substituteVariables,
229
+ suggestProviderProfileName: () => suggestProviderProfileName,
198
230
  summarizeBackgroundJobGroup: () => summarizeBackgroundJobGroup,
199
231
  testProviderProfileCommand: () => testProviderProfileCommand,
232
+ toContextReferenceRecords: () => toContextReferenceRecords,
233
+ toPromptFileReferenceRecords: () => toPromptFileReferenceRecords,
200
234
  transitionBackgroundTaskStatus: () => import_agent_runtime4.transitionBackgroundTaskStatus,
201
235
  transitionSelfHostingLoop: () => transitionSelfHostingLoop,
202
236
  updateTaskFileStatus: () => updateTaskFileStatus,
237
+ upsertContextReference: () => upsertContextReference,
203
238
  upsertProviderProfile: () => upsertProviderProfile,
204
239
  userPaths: () => userPaths,
240
+ validateCommandSessionReplayLog: () => validateCommandSessionReplayLog,
205
241
  validateProviderProfile: () => validateProviderProfile,
206
242
  validateProviderSetupValue: () => validateProviderSetupValue,
207
243
  wrapEditCheckpointTools: () => wrapEditCheckpointTools,
@@ -212,6 +248,7 @@ __export(index_exports, {
212
248
  module.exports = __toCommonJS(index_exports);
213
249
 
214
250
  // src/interactive/interactive-session.ts
251
+ var import_node_crypto5 = require("crypto");
215
252
  var import_agent_core7 = require("@robota-sdk/agent-core");
216
253
 
217
254
  // src/commands/capability-descriptors.ts
@@ -223,7 +260,7 @@ function inferKind(command) {
223
260
  function commandToCapabilityDescriptor(command) {
224
261
  const skillLike = command.source === "skill" || command.source === "plugin" && Boolean(command.skillContent);
225
262
  return {
226
- name: `/${command.name}`,
263
+ name: command.name,
227
264
  kind: inferKind(command),
228
265
  description: command.description,
229
266
  userInvocable: command.userInvocable !== false,
@@ -316,7 +353,7 @@ var SystemCommandExecutor = class {
316
353
  }
317
354
  listModelInvocableCommands() {
318
355
  return this.listCommands().filter((command) => command.modelInvocable === true).map((command) => ({
319
- name: `/${command.name}`,
356
+ name: command.name,
320
357
  kind: "builtin-command",
321
358
  description: command.description,
322
359
  userInvocable: command.userInvocable !== false,
@@ -425,6 +462,32 @@ function setCurrentProvider(settings, profileName) {
425
462
  currentProvider: profileName
426
463
  };
427
464
  }
465
+ function deleteProviderProfile(settings, profileName, options = {}) {
466
+ if (!settings.providers?.[profileName]) {
467
+ throw new Error(`Provider profile "${profileName}" was not found`);
468
+ }
469
+ const providers = { ...settings.providers };
470
+ delete providers[profileName];
471
+ if (options.replacementCurrentProvider !== void 0 && providers[options.replacementCurrentProvider] === void 0) {
472
+ throw new Error(`Provider profile "${options.replacementCurrentProvider}" was not found`);
473
+ }
474
+ const next = {
475
+ ...settings,
476
+ providers
477
+ };
478
+ if (settings.currentProvider !== profileName) {
479
+ return next;
480
+ }
481
+ if (options.replacementCurrentProvider !== void 0) {
482
+ return {
483
+ ...next,
484
+ currentProvider: options.replacementCurrentProvider
485
+ };
486
+ }
487
+ const withoutCurrentProvider = { ...next };
488
+ delete withoutCurrentProvider.currentProvider;
489
+ return withoutCurrentProvider;
490
+ }
428
491
  function validateProviderProfile(profileName, profile, options = {}) {
429
492
  if (!profile.type) {
430
493
  throw new Error(`Provider profile "${profileName}" is missing type`);
@@ -433,8 +496,11 @@ function validateProviderProfile(profileName, profile, options = {}) {
433
496
  throw new Error(`Provider profile "${profileName}" is missing model`);
434
497
  }
435
498
  const definition = (0, import_agent_core.findProviderDefinition)(options.providerDefinitions ?? [], profile.type);
436
- if (definition?.requiresApiKey === true && !hasUsableSecretReference(profile.apiKey ?? definition.defaults?.apiKey)) {
437
- throw new Error(`Provider profile "${profileName}" is missing apiKey`);
499
+ const credentialRequirement = (0, import_agent_core.getProviderCredentialRequirement)(definition);
500
+ if (credentialRequirement !== void 0 && !hasUsableRequiredProviderCredential(profile, definition?.defaults, credentialRequirement)) {
501
+ throw new Error(
502
+ `Provider profile "${profileName}" is missing ${formatCredentialRequirement(credentialRequirement)}`
503
+ );
438
504
  }
439
505
  }
440
506
  function buildProviderSetupPatch(input, options = {}) {
@@ -454,7 +520,7 @@ function buildProviderProfile(input, options = {}) {
454
520
  return {
455
521
  type: input.type,
456
522
  model: input.model ?? defaults.model,
457
- ...apiKey !== void 0 && { apiKey },
523
+ ...isNonEmptyString(apiKey) && { apiKey },
458
524
  ...baseURL !== void 0 && { baseURL },
459
525
  ...input.timeout !== void 0 && { timeout: input.timeout }
460
526
  };
@@ -470,6 +536,20 @@ function mergeProviderPatch(settings, patch) {
470
536
  function getProviderDefaults(type, providerDefinitions) {
471
537
  return (0, import_agent_core.findProviderDefinition)(providerDefinitions, type)?.defaults ?? {};
472
538
  }
539
+ function hasUsableRequiredProviderCredential(profile, defaults, requirement) {
540
+ return requirement.anyOf.some(
541
+ (field) => hasUsableSecretReference(resolveProviderCredentialValue(field, profile, defaults))
542
+ );
543
+ }
544
+ function resolveProviderCredentialValue(field, profile, defaults) {
545
+ return profile[field] ?? defaults?.[field];
546
+ }
547
+ function formatCredentialRequirement(requirement) {
548
+ return requirement.anyOf.join(" or ");
549
+ }
550
+ function isNonEmptyString(value) {
551
+ return value !== void 0 && value.length > 0;
552
+ }
473
553
 
474
554
  // src/command-api/provider/provider-command-probe.ts
475
555
  async function testProviderProfileCommand(currentProvider, providers, profileArg, options) {
@@ -702,18 +782,64 @@ async function compactCommandContext(context, instructions) {
702
782
  const after = readCommandContextState(context);
703
783
  return { before, after };
704
784
  }
785
+ function listCommandContextReferences(context) {
786
+ return context.listContextReferences?.() ?? [];
787
+ }
788
+ async function addCommandContextReference(context, path) {
789
+ if (!context.addContextReference) {
790
+ return {
791
+ evicted: [],
792
+ diagnostics: ["Command host does not support context reference additions."]
793
+ };
794
+ }
795
+ return context.addContextReference(path);
796
+ }
797
+ function removeCommandContextReference(context, path) {
798
+ return context.removeContextReference?.(path) ?? {};
799
+ }
800
+ function clearCommandContextReferences(context) {
801
+ return context.clearContextReferences?.() ?? { removed: [] };
802
+ }
705
803
  function getSettingsAdapter(context) {
706
804
  return context.getCommandHostAdapters?.().settings;
707
805
  }
708
806
 
807
+ // src/command-api/provider/provider-profile-names.ts
808
+ var FALLBACK_PROFILE_NAME = "provider";
809
+ var FIRST_DUPLICATE_SUFFIX = 2;
810
+ function suggestProviderProfileName(input, options = {}) {
811
+ const baseName = sanitizeProviderProfileName(input.model) ?? sanitizeProviderProfileName(input.type) ?? FALLBACK_PROFILE_NAME;
812
+ const existing = new Set(options.existingProfileNames ?? []);
813
+ if (!existing.has(baseName)) {
814
+ return baseName;
815
+ }
816
+ let suffix = FIRST_DUPLICATE_SUFFIX;
817
+ while (existing.has(`${baseName}-${suffix}`)) {
818
+ suffix += 1;
819
+ }
820
+ return `${baseName}-${suffix}`;
821
+ }
822
+ function sanitizeProviderProfileName(value) {
823
+ const normalized = value?.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
824
+ return normalized !== void 0 && normalized.length > 0 ? normalized : void 0;
825
+ }
826
+
709
827
  // src/command-api/provider/provider-setup-flow.ts
710
828
  var import_agent_core3 = require("@robota-sdk/agent-core");
711
- function createProviderSetupFlow(type, providerDefinitions) {
829
+ function createProviderSetupFlow(type, providerDefinitions, options = {}) {
830
+ const definition = getProviderSetupDefinition(type, providerDefinitions);
712
831
  return {
713
832
  type,
714
- steps: getProviderSetupSteps(type, providerDefinitions),
833
+ steps: applyProviderSetupInitialValues(
834
+ getProviderSetupSteps(definition),
835
+ options.initialValues
836
+ ),
837
+ setupHelpLinks: definition.setupHelpLinks ?? [],
715
838
  stepIndex: 0,
716
- values: {}
839
+ values: {},
840
+ existingProfileNames: options.existingProfileNames ?? [],
841
+ ...options.profileName !== void 0 ? { profileName: options.profileName } : {},
842
+ ...options.setCurrent !== void 0 ? { setCurrent: options.setCurrent } : {}
717
843
  };
718
844
  }
719
845
  function formatProviderSetupSelectionPrompt(providerDefinitions) {
@@ -774,12 +900,15 @@ function submitProviderSetupValue(state, rawValue) {
774
900
  }
775
901
  return { status: "complete", input: buildProviderSetupInput(nextState) };
776
902
  }
777
- async function runProviderSetupPromptFlow(type, promptInput, providerDefinitions) {
778
- let state = createProviderSetupFlow(type, providerDefinitions);
903
+ async function runProviderSetupPromptFlow(type, promptInput, providerDefinitions, options = {}) {
904
+ let state = createProviderSetupFlow(type, providerDefinitions, options);
779
905
  const stepCount = state.steps.length;
780
906
  while (state.stepIndex < stepCount) {
781
907
  const step = getProviderSetupStep(state);
782
- const value = await promptInput(formatProviderSetupPromptLabel(step), step.masked === true);
908
+ const value = await promptInput(
909
+ formatProviderSetupPromptLabel(step, state.setupHelpLinks),
910
+ step.masked === true
911
+ );
783
912
  const result = submitProviderSetupValue(state, value);
784
913
  if (result.status === "complete") {
785
914
  return result.input;
@@ -791,14 +920,25 @@ async function runProviderSetupPromptFlow(type, promptInput, providerDefinitions
791
920
  }
792
921
  throw new Error("Provider setup flow ended without completion");
793
922
  }
794
- function formatProviderSetupPromptLabel(step) {
923
+ function formatProviderSetupPromptLabel(step, setupHelpLinks = []) {
795
924
  const suffix = step.defaultValue !== void 0 ? ` (default: ${step.defaultValue})` : "";
796
- return ` ${step.title}${suffix}: `;
925
+ const setupHelp = formatProviderSetupHelpLinks(setupHelpLinks);
926
+ const prefix = setupHelp.length > 0 ? `${setupHelp}
927
+ ` : "";
928
+ return `${prefix} ${step.title}${suffix}: `;
797
929
  }
798
930
  function formatProviderSetupChoiceLabel(definition) {
799
931
  const label = definition.displayName !== void 0 ? `${definition.displayName} (${definition.type})` : definition.type;
800
932
  return definition.description !== void 0 ? `${label} - ${definition.description}` : label;
801
933
  }
934
+ function formatProviderSetupHelpLinks(setupHelpLinks = []) {
935
+ if (setupHelpLinks.length === 0) {
936
+ return "";
937
+ }
938
+ return setupHelpLinks.map(
939
+ (link) => ` Setup help: ${formatProviderSetupHelpLinkKind(link.kind)}: ${link.label} - ${link.url}`
940
+ ).join("\n");
941
+ }
802
942
  function parseProviderSelectionIndex(value) {
803
943
  if (!/^\d+$/.test(value)) {
804
944
  return void 0;
@@ -811,13 +951,16 @@ function validateProviderSetupValue(step, value) {
811
951
  }
812
952
  return void 0;
813
953
  }
814
- function getProviderSetupSteps(type, providerDefinitions) {
954
+ function getProviderSetupDefinition(type, providerDefinitions) {
815
955
  const definition = (0, import_agent_core3.findProviderDefinition)(providerDefinitions, type);
816
956
  if (definition === void 0) {
817
957
  throw new Error(
818
958
  `Unknown provider: ${type}. Currently supported: ${(0, import_agent_core3.formatSupportedProviderTypes)(providerDefinitions)}`
819
959
  );
820
960
  }
961
+ return definition;
962
+ }
963
+ function getProviderSetupSteps(definition) {
821
964
  if (definition.setupSteps !== void 0) {
822
965
  return [...definition.setupSteps];
823
966
  }
@@ -847,14 +990,44 @@ function getProviderSetupSteps(type, providerDefinitions) {
847
990
  }
848
991
  return steps;
849
992
  }
993
+ function formatProviderSetupHelpLinkKind(kind) {
994
+ if (kind === "api-key") {
995
+ return "API key";
996
+ }
997
+ if (kind === "console") {
998
+ return "Console";
999
+ }
1000
+ return "Official";
1001
+ }
1002
+ function applyProviderSetupInitialValues(steps, initialValues) {
1003
+ if (initialValues === void 0) {
1004
+ return [...steps];
1005
+ }
1006
+ return steps.map((step) => {
1007
+ const initialValue = initialValues[step.key];
1008
+ if (initialValue === void 0) {
1009
+ return step;
1010
+ }
1011
+ return {
1012
+ ...step,
1013
+ defaultValue: initialValue,
1014
+ required: false
1015
+ };
1016
+ });
1017
+ }
850
1018
  function buildProviderSetupInput(state) {
1019
+ const profile = state.profileName ?? suggestProviderProfileName(
1020
+ { type: state.type, model: state.values.model },
1021
+ { existingProfileNames: state.existingProfileNames }
1022
+ );
1023
+ const apiKey = state.values.apiKey;
851
1024
  return {
852
- profile: state.type,
1025
+ profile,
853
1026
  type: state.type,
854
1027
  model: state.values.model,
855
- apiKey: state.values.apiKey,
1028
+ ...apiKey !== void 0 && apiKey.length > 0 && { apiKey },
856
1029
  ...state.values.baseURL !== void 0 && { baseURL: state.values.baseURL },
857
- setCurrent: true
1030
+ setCurrent: state.setCurrent ?? true
858
1031
  };
859
1032
  }
860
1033
 
@@ -943,7 +1116,67 @@ function closeCommandBackgroundTask(context, taskId) {
943
1116
  var import_agent_core4 = require("@robota-sdk/agent-core");
944
1117
  var MODEL_COMMAND_DESCRIPTION = "Change AI model";
945
1118
  var MODEL_COMMAND_ARGUMENT_HINT = "<model-id>";
946
- function buildModelCommandSubcommands(source = "model") {
1119
+ function buildModelCommandSubcommands(sourceOrOptions = "model") {
1120
+ const options = typeof sourceOrOptions === "string" ? { source: sourceOrOptions } : sourceOrOptions;
1121
+ const source = options.source ?? "model";
1122
+ const catalog = resolveActiveProviderModelCatalog(options.settings, options.providerDefinitions);
1123
+ if (catalog !== void 0) {
1124
+ return buildCatalogSubcommands(catalog, source);
1125
+ }
1126
+ if (options.settings !== void 0) {
1127
+ return [];
1128
+ }
1129
+ return buildClaudeModelSubcommands(source);
1130
+ }
1131
+ function formatModelCommandUsageMessage(options = {}) {
1132
+ const snapshot = resolveActiveProviderModelCatalogSnapshot(
1133
+ options.settings,
1134
+ options.providerDefinitions
1135
+ );
1136
+ return formatModelUsageMessage(snapshot === void 0 ? void 0 : toCatalogState(snapshot));
1137
+ }
1138
+ async function formatModelCommandUsageMessageAsync(options = {}) {
1139
+ return formatModelUsageMessage(await resolveActiveProviderModelCatalogState(options));
1140
+ }
1141
+ function resolveActiveProviderModelCatalog(settings, providerDefinitions = []) {
1142
+ return resolveActiveProviderModelCatalogSnapshot(settings, providerDefinitions)?.catalog;
1143
+ }
1144
+ async function resolveActiveProviderModelCatalogState(options) {
1145
+ const snapshot = resolveActiveProviderModelCatalogSnapshot(
1146
+ options.settings,
1147
+ options.providerDefinitions
1148
+ );
1149
+ if (snapshot === void 0) return void 0;
1150
+ if (options.refresh !== true || snapshot.definition?.refreshModelCatalog === void 0) {
1151
+ return toCatalogState(snapshot);
1152
+ }
1153
+ try {
1154
+ const refreshed = await snapshot.definition.refreshModelCatalog({
1155
+ profile: resolveRefreshProfile(snapshot)
1156
+ });
1157
+ if (refreshed.status !== "unavailable") {
1158
+ return {
1159
+ providerType: snapshot.providerType,
1160
+ catalog: refreshed,
1161
+ refreshAttempted: true
1162
+ };
1163
+ }
1164
+ return {
1165
+ providerType: snapshot.providerType,
1166
+ catalog: snapshot.catalog ?? refreshed,
1167
+ refreshAttempted: true,
1168
+ ...refreshed.message !== void 0 ? { refreshMessage: refreshed.message } : {}
1169
+ };
1170
+ } catch (error) {
1171
+ return {
1172
+ providerType: snapshot.providerType,
1173
+ ...snapshot.catalog !== void 0 ? { catalog: snapshot.catalog } : {},
1174
+ refreshAttempted: true,
1175
+ refreshMessage: error instanceof Error ? error.message : String(error)
1176
+ };
1177
+ }
1178
+ }
1179
+ function buildClaudeModelSubcommands(source) {
947
1180
  const seen = /* @__PURE__ */ new Set();
948
1181
  const commands = [];
949
1182
  for (const model of Object.values(import_agent_core4.CLAUDE_MODELS)) {
@@ -957,6 +1190,97 @@ function buildModelCommandSubcommands(source = "model") {
957
1190
  }
958
1191
  return commands;
959
1192
  }
1193
+ function buildCatalogSubcommands(catalog, source) {
1194
+ return (catalog.entries ?? []).filter((entry) => entry.lifecycle !== "unavailable").map((entry) => ({
1195
+ name: entry.id,
1196
+ description: formatCatalogEntryDescription(entry),
1197
+ source
1198
+ }));
1199
+ }
1200
+ function formatCatalogEntryDescription(entry) {
1201
+ if (entry.contextWindow === void 0) {
1202
+ return entry.displayName;
1203
+ }
1204
+ return `${entry.displayName} (${(0, import_agent_core4.formatTokenCount)(entry.contextWindow).toUpperCase()})`;
1205
+ }
1206
+ function resolveActiveProviderModelCatalogSnapshot(settings, providerDefinitions = []) {
1207
+ const profile = resolveActiveProviderProfile(settings);
1208
+ const providerType = profile?.type ?? profile?.name;
1209
+ if (providerType === void 0) {
1210
+ return void 0;
1211
+ }
1212
+ const definition = (0, import_agent_core4.findProviderDefinition)(providerDefinitions, providerType);
1213
+ return {
1214
+ providerType,
1215
+ ...profile !== void 0 ? { profile } : {},
1216
+ ...definition !== void 0 ? { definition } : {},
1217
+ ...definition?.modelCatalog !== void 0 ? { catalog: definition.modelCatalog } : {}
1218
+ };
1219
+ }
1220
+ function resolveActiveProviderProfile(settings) {
1221
+ if (settings?.currentProvider !== void 0) {
1222
+ return settings.providers?.[settings.currentProvider];
1223
+ }
1224
+ return settings?.provider;
1225
+ }
1226
+ function toCatalogState(snapshot) {
1227
+ return {
1228
+ providerType: snapshot.providerType,
1229
+ ...snapshot.catalog !== void 0 ? { catalog: snapshot.catalog } : {},
1230
+ refreshAttempted: false
1231
+ };
1232
+ }
1233
+ function resolveRefreshProfile(snapshot) {
1234
+ const profile = snapshot.profile;
1235
+ const defaults = snapshot.definition?.defaults;
1236
+ const apiKey = resolveOptionalEnvReference(profile?.apiKey ?? defaults?.apiKey);
1237
+ const model = resolveProfileValue(profile?.model, defaults?.model);
1238
+ const baseURL = resolveProfileValue(profile?.baseURL, defaults?.baseURL);
1239
+ const timeout = resolveProfileValue(profile?.timeout, defaults?.timeout);
1240
+ const options = resolveProfileValue(profile?.options, defaults?.options);
1241
+ const refreshProfile = {
1242
+ type: profile?.type ?? snapshot.providerType
1243
+ };
1244
+ if (model !== void 0) refreshProfile.model = model;
1245
+ if (apiKey !== void 0) refreshProfile.apiKey = apiKey;
1246
+ if (baseURL !== void 0) refreshProfile.baseURL = baseURL;
1247
+ if (timeout !== void 0) refreshProfile.timeout = timeout;
1248
+ if (options !== void 0) refreshProfile.options = options;
1249
+ return refreshProfile;
1250
+ }
1251
+ function resolveProfileValue(profileValue, defaultValue) {
1252
+ return profileValue ?? defaultValue;
1253
+ }
1254
+ function resolveOptionalEnvReference(value) {
1255
+ return value === void 0 ? void 0 : resolveEnvReference(value);
1256
+ }
1257
+ function formatModelUsageMessage(active) {
1258
+ const base = active?.providerType !== void 0 && (active.catalog?.entries === void 0 || active.catalog.entries.length === 0) ? `No model catalog available for provider ${active.providerType}. Usage: model <model-id>` : "Usage: model <model-id>";
1259
+ const freshness = formatCatalogFreshness(active);
1260
+ return freshness === void 0 ? base : `${base}
1261
+ ${freshness}`;
1262
+ }
1263
+ function formatCatalogFreshness(active) {
1264
+ const catalog = active?.catalog;
1265
+ if (catalog === void 0) return void 0;
1266
+ const parts = [`Catalog: ${catalog.status}`];
1267
+ if (catalog.entries !== void 0) {
1268
+ parts.push(`${catalog.entries.length} model(s)`);
1269
+ }
1270
+ if (catalog.lastVerifiedAt !== void 0) {
1271
+ parts.push(`verified ${catalog.lastVerifiedAt}`);
1272
+ }
1273
+ if (catalog.sourceUrl !== void 0) {
1274
+ parts.push(`source ${catalog.sourceUrl}`);
1275
+ }
1276
+ const refreshMessage = active?.refreshMessage;
1277
+ if (refreshMessage !== void 0) {
1278
+ parts.push(`refresh ${refreshMessage}`);
1279
+ } else if (catalog.message !== void 0) {
1280
+ parts.push(catalog.message);
1281
+ }
1282
+ return parts.join("; ");
1283
+ }
960
1284
 
961
1285
  // src/command-api/language/language-command-api.ts
962
1286
  var LANGUAGE_COMMAND_DESCRIPTION = "Set response language";
@@ -985,7 +1309,7 @@ function formatLanguageUsageMessage(commandName = "language") {
985
1309
  // src/command-api/permissions/permission-mode-command-api.ts
986
1310
  var PERMISSION_MODE_COMMAND_DESCRIPTION = "Show/change permission mode";
987
1311
  var PERMISSION_MODE_ARGUMENT_HINT = "plan | default | acceptEdits | bypassPermissions";
988
- var PERMISSIONS_COMMAND_DESCRIPTION = "Show permission rules";
1312
+ var PERMISSIONS_COMMAND_DESCRIPTION = "Show/change permission mode and permission rules";
989
1313
  var VALID_PERMISSION_MODES = [
990
1314
  "plan",
991
1315
  "default",
@@ -1100,12 +1424,39 @@ function buildPluginCommandSubcommands() {
1100
1424
  ];
1101
1425
  }
1102
1426
 
1427
+ // src/command-api/session/session-command-api.ts
1428
+ var import_node_path3 = require("path");
1429
+ var import_agent_sessions2 = require("@robota-sdk/agent-sessions");
1430
+
1431
+ // src/paths.ts
1432
+ var import_node_path2 = require("path");
1433
+ var import_node_os2 = require("os");
1434
+ function projectPaths(cwd) {
1435
+ const base = (0, import_node_path2.join)(cwd, ".robota");
1436
+ return {
1437
+ settings: (0, import_node_path2.join)(base, "settings.json"),
1438
+ settingsLocal: (0, import_node_path2.join)(base, "settings.local.json"),
1439
+ logs: (0, import_node_path2.join)(base, "logs"),
1440
+ sessions: (0, import_node_path2.join)(base, "sessions"),
1441
+ memory: (0, import_node_path2.join)(base, "memory"),
1442
+ checkpoints: (0, import_node_path2.join)(base, "checkpoints")
1443
+ };
1444
+ }
1445
+ function userPaths() {
1446
+ const base = (0, import_node_path2.join)((0, import_node_os2.homedir)(), ".robota");
1447
+ return {
1448
+ settings: (0, import_node_path2.join)(base, "settings.json"),
1449
+ sessions: (0, import_node_path2.join)(base, "sessions")
1450
+ };
1451
+ }
1452
+
1103
1453
  // src/command-api/session/session-command-api.ts
1104
1454
  var CLEAR_COMMAND_DESCRIPTION = "Clear conversation history";
1105
1455
  var RENAME_COMMAND_DESCRIPTION = "Rename the current session";
1106
1456
  var RENAME_COMMAND_USAGE = "Usage: rename <name>";
1107
1457
  var RESUME_COMMAND_DESCRIPTION = "Resume a previous session";
1108
1458
  var COST_COMMAND_DESCRIPTION = "Show session info";
1459
+ var VALIDATE_SESSION_COMMAND_DESCRIPTION = "Validate current session replay log";
1109
1460
  var EXIT_COMMAND_DESCRIPTION = "Exit CLI";
1110
1461
  function clearConversationHistory(context) {
1111
1462
  if (context.clearConversationHistory !== void 0) {
@@ -1134,6 +1485,45 @@ function readCommandSessionInfo(context) {
1134
1485
  messageCount: session.getMessageCount()
1135
1486
  };
1136
1487
  }
1488
+ function validateCommandSessionReplayLog(context) {
1489
+ const hostReport = context.validateCurrentSessionReplayLog?.();
1490
+ if (hostReport !== void 0) {
1491
+ return hostReport;
1492
+ }
1493
+ const sessionId = context.getSession().getSessionId();
1494
+ const logFile = (0, import_node_path3.join)(projectPaths(context.getCwd()).logs, `${sessionId}.jsonl`);
1495
+ const entries = (0, import_agent_sessions2.loadSessionLogEntries)(logFile);
1496
+ return {
1497
+ logFile,
1498
+ entryCount: entries.length,
1499
+ validation: (0, import_agent_sessions2.validateSessionReplayLogEntries)(entries)
1500
+ };
1501
+ }
1502
+ function formatCommandSessionReplayValidationReport(report) {
1503
+ const header = report.validation.ok ? "Session replay log is valid." : `Session replay log has ${report.validation.issues.length} issue(s).`;
1504
+ const details = [`Log: ${report.logFile}`, `Entries: ${report.entryCount}`];
1505
+ if (report.validation.ok) {
1506
+ return [header, ...details].join("\n");
1507
+ }
1508
+ const issueLines = report.validation.issues.map((issue, index) => {
1509
+ const location = formatReplayValidationIssueLocation(issue);
1510
+ return `${index + 1}. ${issue.code}${location}: ${issue.message}`;
1511
+ });
1512
+ return [header, ...details, "", ...issueLines].join("\n");
1513
+ }
1514
+ function formatReplayValidationIssueLocation(issue) {
1515
+ const parts = [];
1516
+ if (issue.executionId !== void 0) {
1517
+ parts.push(`execution=${issue.executionId}`);
1518
+ }
1519
+ if (issue.round !== void 0) {
1520
+ parts.push(`round=${issue.round}`);
1521
+ }
1522
+ if (issue.toolCallId !== void 0) {
1523
+ parts.push(`tool=${issue.toolCallId}`);
1524
+ }
1525
+ return parts.length > 0 ? ` (${parts.join(", ")})` : "";
1526
+ }
1137
1527
 
1138
1528
  // src/command-api/checkpoint/rewind-command-api.ts
1139
1529
  var REWIND_COMMAND_DESCRIPTION = "List, inspect, restore, or rollback edit checkpoints.";
@@ -1176,10 +1566,10 @@ function containsSensitiveMemoryContent(text) {
1176
1566
 
1177
1567
  // src/memory/pending-memory-store.ts
1178
1568
  var import_node_fs2 = require("fs");
1179
- var import_node_path2 = require("path");
1569
+ var import_node_path4 = require("path");
1180
1570
  var PENDING_FILENAME = "pending.json";
1181
1571
  function memoryRoot(cwd) {
1182
- return (0, import_node_path2.join)(cwd, ".robota", "memory");
1572
+ return (0, import_node_path4.join)(cwd, ".robota", "memory");
1183
1573
  }
1184
1574
  function emptyDocument() {
1185
1575
  return { version: 1, records: [] };
@@ -1188,7 +1578,7 @@ var PendingMemoryStore = class {
1188
1578
  path;
1189
1579
  now;
1190
1580
  constructor(cwd, now = () => /* @__PURE__ */ new Date()) {
1191
- this.path = (0, import_node_path2.join)(memoryRoot(cwd), PENDING_FILENAME);
1581
+ this.path = (0, import_node_path4.join)(memoryRoot(cwd), PENDING_FILENAME);
1192
1582
  this.now = now;
1193
1583
  }
1194
1584
  getPath() {
@@ -1242,7 +1632,7 @@ var PendingMemoryStore = class {
1242
1632
  }
1243
1633
  }
1244
1634
  write(document) {
1245
- (0, import_node_fs2.mkdirSync)((0, import_node_path2.dirname)(this.path), { recursive: true });
1635
+ (0, import_node_fs2.mkdirSync)((0, import_node_path4.dirname)(this.path), { recursive: true });
1246
1636
  (0, import_node_fs2.writeFileSync)(this.path, JSON.stringify(document, null, 2), "utf8");
1247
1637
  }
1248
1638
  };
@@ -1455,24 +1845,6 @@ async function preprocessShellCommands(content) {
1455
1845
  }
1456
1846
  return result;
1457
1847
  }
1458
- async function buildSkillPrompt(input, registry, context) {
1459
- const parts = input.slice(1).split(/\s+/);
1460
- const cmd = parts[0]?.toLowerCase() ?? "";
1461
- const skillCmd = registry.getCommands().find((c) => c.name === cmd && (c.source === "skill" || c.source === "plugin"));
1462
- if (!skillCmd) return null;
1463
- const args = parts.slice(1).join(" ").trim();
1464
- const userInstruction = args || skillCmd.description;
1465
- if (skillCmd.skillContent) {
1466
- let processed = await preprocessShellCommands(skillCmd.skillContent);
1467
- processed = substituteVariables(processed, args, context);
1468
- return `<skill name="${cmd}">
1469
- ${processed}
1470
- </skill>
1471
-
1472
- Execute the "${cmd}" skill: ${userInstruction}`;
1473
- }
1474
- return `Use the "${cmd}" skill: ${userInstruction}`;
1475
- }
1476
1848
 
1477
1849
  // src/commands/skill-executor.ts
1478
1850
  async function buildProcessedContent(skill, args, context) {
@@ -1495,7 +1867,9 @@ Execute the "${skill.name}" skill: ${userInstruction}`;
1495
1867
  async function executeSkill(skill, args, callbacks, context) {
1496
1868
  if (skill.context === "fork") {
1497
1869
  if (!callbacks.runInFork) {
1498
- throw new Error("Fork execution is not available. Agent tool deps may not be initialized.");
1870
+ throw new Error(
1871
+ "Fork execution is not available. Agent runtime deps may not be initialized."
1872
+ );
1499
1873
  }
1500
1874
  const content = await buildProcessedContent(skill, args, context);
1501
1875
  const prompt2 = content ?? `Use the "${skill.name}" skill: ${args || skill.description}`;
@@ -1509,8 +1883,39 @@ async function executeSkill(skill, args, callbacks, context) {
1509
1883
  return { mode: "inject", prompt };
1510
1884
  }
1511
1885
 
1886
+ // src/commands/skill-activation-events.ts
1887
+ function getSkillActivationSource(skill) {
1888
+ return skill.source === "plugin" ? "plugin" : "skill";
1889
+ }
1890
+ function getSkillActivationMode(skill) {
1891
+ return skill.context === "fork" ? "fork" : "inject";
1892
+ }
1893
+ function createSkillActivationEvent(input) {
1894
+ return {
1895
+ type: "skill-activation",
1896
+ skillName: input.skill.name,
1897
+ source: getSkillActivationSource(input.skill),
1898
+ invocation: input.invocation,
1899
+ mode: getSkillActivationMode(input.skill),
1900
+ status: input.status,
1901
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1902
+ ...input.qualifiedName !== void 0 ? { qualifiedName: input.qualifiedName } : {},
1903
+ ...input.error !== void 0 ? { error: input.error } : {}
1904
+ };
1905
+ }
1906
+ function formatSkillActivationMessage(event) {
1907
+ const sourceLabel = event.source === "plugin" ? "plugin skill" : "skill";
1908
+ if (event.status === "failed") {
1909
+ return `Skill failed: ${event.skillName}${event.error ? ` (${event.error})` : ""}`;
1910
+ }
1911
+ if (event.status === "completed") {
1912
+ return `Skill completed: ${event.skillName}`;
1913
+ }
1914
+ return `Invoking ${sourceLabel}: ${event.skillName}`;
1915
+ }
1916
+
1512
1917
  // src/assembly/create-subagent-session.ts
1513
- var import_agent_sessions2 = require("@robota-sdk/agent-sessions");
1918
+ var import_agent_sessions3 = require("@robota-sdk/agent-sessions");
1514
1919
 
1515
1920
  // src/assembly/subagent-prompts.ts
1516
1921
  function getSubagentSuffix() {
@@ -1541,12 +1946,147 @@ function assembleSubagentPrompt(options) {
1541
1946
  return parts.join("\n\n");
1542
1947
  }
1543
1948
 
1949
+ // src/tools/model-command-tool-projection.ts
1950
+ var import_node_crypto = require("crypto");
1951
+ var import_zod = require("zod");
1952
+ var import_agent_tools = require("@robota-sdk/agent-tools");
1953
+ var MODEL_COMMAND_TOOL_PREFIX = "robota_command_";
1954
+ var PROVIDER_SAFE_TOOL_NAME_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
1955
+ var MAX_PROVIDER_TOOL_NAME_LENGTH = 64;
1956
+ var HASH_LENGTH = 8;
1957
+ var HASH_SEPARATOR_LENGTH = 1;
1958
+ function asZodSchema(schema) {
1959
+ return schema;
1960
+ }
1961
+ function normalizeModelCommandName(command) {
1962
+ return command.trim().replace(/^\/+/, "").split(/\s+/)[0] ?? "";
1963
+ }
1964
+ function createProviderSafeModelCommandToolName(commandName) {
1965
+ const normalizedCommandName = normalizeModelCommandName(commandName);
1966
+ if (!normalizedCommandName) {
1967
+ throw new Error("Model command descriptor name must not be empty.");
1968
+ }
1969
+ const safeBody = normalizedCommandName.replace(/[^A-Za-z0-9_-]/g, "_").replace(/_+/g, "_").replace(/^_+|_+$/g, "");
1970
+ if (!safeBody) {
1971
+ throw new Error(`Model command descriptor name cannot be projected safely: ${commandName}`);
1972
+ }
1973
+ const rawToolName = `${MODEL_COMMAND_TOOL_PREFIX}${safeBody}`;
1974
+ if (PROVIDER_SAFE_TOOL_NAME_PATTERN.test(rawToolName)) {
1975
+ return rawToolName;
1976
+ }
1977
+ const hash = (0, import_node_crypto.createHash)("sha256").update(normalizedCommandName).digest("hex").slice(0, HASH_LENGTH);
1978
+ const maxBodyLength = MAX_PROVIDER_TOOL_NAME_LENGTH - MODEL_COMMAND_TOOL_PREFIX.length - HASH_SEPARATOR_LENGTH - HASH_LENGTH;
1979
+ if (maxBodyLength < 1) {
1980
+ throw new Error("Model command tool prefix leaves no room for command names.");
1981
+ }
1982
+ const truncatedBody = safeBody.slice(0, maxBodyLength).replace(/[_-]+$/g, "") || "command";
1983
+ const toolName = `${MODEL_COMMAND_TOOL_PREFIX}${truncatedBody}_${hash}`;
1984
+ if (!PROVIDER_SAFE_TOOL_NAME_PATTERN.test(toolName)) {
1985
+ throw new Error(`Projected model command tool name is not provider-safe: ${toolName}`);
1986
+ }
1987
+ return toolName;
1988
+ }
1989
+ function createModelCommandToolProjection(commandDescriptors) {
1990
+ const commandNames = /* @__PURE__ */ new Set();
1991
+ const toolNameToCommandName = /* @__PURE__ */ new Map();
1992
+ const commandNameToToolName = /* @__PURE__ */ new Map();
1993
+ const commandTools = [];
1994
+ for (const descriptor of commandDescriptors) {
1995
+ const commandName = normalizeModelCommandName(descriptor.name);
1996
+ if (!commandName) {
1997
+ throw new Error("Model command descriptor name must not be empty.");
1998
+ }
1999
+ if (commandNames.has(commandName)) {
2000
+ throw new Error(`Duplicate model command descriptor: ${commandName}`);
2001
+ }
2002
+ commandNames.add(commandName);
2003
+ const toolName = createProviderSafeModelCommandToolName(commandName);
2004
+ const existingCommandName = toolNameToCommandName.get(toolName);
2005
+ if (existingCommandName !== void 0) {
2006
+ throw new Error(
2007
+ `Model command projection collision: ${existingCommandName} and ${commandName} both map to ${toolName}`
2008
+ );
2009
+ }
2010
+ toolNameToCommandName.set(toolName, commandName);
2011
+ commandNameToToolName.set(commandName, toolName);
2012
+ commandTools.push({
2013
+ commandName,
2014
+ toolName,
2015
+ description: formatProjectedModelCommandToolDescription(commandName, descriptor),
2016
+ descriptor
2017
+ });
2018
+ }
2019
+ return {
2020
+ commandTools,
2021
+ toolNameToCommandName,
2022
+ commandNameToToolName
2023
+ };
2024
+ }
2025
+ function formatProjectedModelCommandToolPromptDescription(projection) {
2026
+ return `${projection.toolName} \u2014 ${projection.descriptor.description}`;
2027
+ }
2028
+ function stringifyModelCommandResult(command, result) {
2029
+ if (!result) {
2030
+ return JSON.stringify({
2031
+ success: false,
2032
+ command,
2033
+ error: `Unknown command: ${command}`
2034
+ });
2035
+ }
2036
+ return JSON.stringify({
2037
+ success: result.success,
2038
+ command,
2039
+ message: result.message,
2040
+ data: result.data
2041
+ });
2042
+ }
2043
+ function createProjectedCommandExecutionTools(deps) {
2044
+ const projection = createModelCommandToolProjection(deps.commandDescriptors);
2045
+ return projection.commandTools.map((projectedTool) => {
2046
+ const schema = createProjectedCommandArgsSchema(projectedTool.descriptor);
2047
+ return (0, import_agent_tools.createZodFunctionTool)(
2048
+ projectedTool.toolName,
2049
+ projectedTool.description,
2050
+ asZodSchema(schema),
2051
+ async (params) => {
2052
+ const parsedParams = schema.parse(params);
2053
+ if (!deps.isModelInvocable(projectedTool.commandName)) {
2054
+ return JSON.stringify({
2055
+ success: false,
2056
+ command: projectedTool.commandName,
2057
+ error: `Command is not model-invocable: ${projectedTool.commandName}`
2058
+ });
2059
+ }
2060
+ return stringifyModelCommandResult(
2061
+ projectedTool.commandName,
2062
+ await deps.execute(projectedTool.commandName, parsedParams.args ?? "")
2063
+ );
2064
+ }
2065
+ );
2066
+ });
2067
+ }
2068
+ function createProjectedCommandArgsSchema(descriptor) {
2069
+ const argsDescription = descriptor.argumentHint ? `Arguments for the command. Expected grammar: ${descriptor.argumentHint}` : "Arguments for the command as a single string.";
2070
+ return import_zod.z.object({
2071
+ args: import_zod.z.string().optional().describe(argsDescription)
2072
+ });
2073
+ }
2074
+ function formatProjectedModelCommandToolDescription(commandName, descriptor) {
2075
+ const lines = [descriptor.description.trim(), `Robota command id: ${commandName}.`];
2076
+ if (descriptor.argumentHint) {
2077
+ lines.push(`Argument grammar: ${descriptor.argumentHint}`);
2078
+ }
2079
+ return lines.filter((line) => line.length > 0).join("\n\n");
2080
+ }
2081
+
1544
2082
  // src/assembly/create-subagent-session.ts
1545
2083
  var MODEL_SHORTCUTS = {
1546
2084
  sonnet: "claude-sonnet-4-6",
1547
2085
  haiku: "claude-haiku-4-5",
1548
2086
  opus: "claude-opus-4-6"
1549
2087
  };
2088
+ var LEGACY_AGENT_TOOL_NAME = "Agent";
2089
+ var PROJECTED_AGENT_COMMAND_TOOL_NAME = createProviderSafeModelCommandToolName("agent");
1550
2090
  function resolveModelId(shortName, _parentModel) {
1551
2091
  return MODEL_SHORTCUTS[shortName] ?? shortName;
1552
2092
  }
@@ -1560,7 +2100,9 @@ function filterTools(parentTools, agentDefinition) {
1560
2100
  const allowSet = new Set(agentDefinition.tools);
1561
2101
  tools = tools.filter((t) => allowSet.has(t.getName()));
1562
2102
  }
1563
- tools = tools.filter((t) => t.getName() !== "Agent");
2103
+ tools = tools.filter(
2104
+ (t) => t.getName() !== LEGACY_AGENT_TOOL_NAME && t.getName() !== PROJECTED_AGENT_COMMAND_TOOL_NAME
2105
+ );
1564
2106
  return tools;
1565
2107
  }
1566
2108
  function createSubagentSession(options) {
@@ -1574,7 +2116,7 @@ function createSubagentSession(options) {
1574
2116
  isForkWorker: options.isForkWorker ?? false
1575
2117
  });
1576
2118
  const provider = options.provider;
1577
- return new import_agent_sessions2.Session({
2119
+ return new import_agent_sessions3.Session({
1578
2120
  tools,
1579
2121
  provider,
1580
2122
  systemMessage,
@@ -1655,8 +2197,8 @@ function getBuiltInAgent(name) {
1655
2197
  }
1656
2198
 
1657
2199
  // src/tools/agent-tool.ts
1658
- var import_zod = require("zod");
1659
- var import_agent_tools = require("@robota-sdk/agent-tools");
2200
+ var import_zod2 = require("zod");
2201
+ var import_agent_tools2 = require("@robota-sdk/agent-tools");
1660
2202
  var import_agent_runtime = require("@robota-sdk/agent-runtime");
1661
2203
 
1662
2204
  // src/subagents/in-process-subagent-runner.ts
@@ -1886,35 +2428,21 @@ var AGENT_TOOL_DESCRIPTION = [
1886
2428
  "After the tool returns, base user-facing claims on returned mode and counts; do not say parallel or multiple jobs started unless the result proves those jobs started.",
1887
2429
  "Execution is represented by a real tool call and runtime background task event."
1888
2430
  ].join(" ");
1889
- function createAgentToolPromptDescription(agentDefinitions = []) {
1890
- const availableAgents = agentDefinitions.length > 0 ? ` Available agent types: ${agentDefinitions.map((agent) => `${agent.name} (${agent.description})`).join(", ")}.` : "";
1891
- return [
1892
- "Agent \u2014 creates isolated subagent jobs.",
1893
- "Without jobs, one Agent tool call corresponds to one subagent job.",
1894
- "For explicit multi-agent or parallel-agent requests, use one Agent tool call with jobs containing one entry per requested role and a stable label for each role.",
1895
- "When the user explicitly asks to create, run, spawn, delegate to, or use agents/subagents, start the requested subagent job immediately.",
1896
- "Do not ask a follow-up question unless execution is impossible or unsafe.",
1897
- "The tool returns terminal result data with mode, requestedJobCount, startedJobCount, failedJobCount, and provenance.",
1898
- "After the tool returns, base user-facing claims on returned mode and counts; do not say parallel or multiple jobs started unless the result proves those jobs started.",
1899
- "Runtime mode is background.",
1900
- availableAgents
1901
- ].join(" ").replace(/\s+/g, " ").trim();
1902
- }
1903
- function asZodSchema(schema) {
2431
+ function asZodSchema2(schema) {
1904
2432
  return schema;
1905
2433
  }
1906
- var AgentSchema = import_zod.z.object({
1907
- prompt: import_zod.z.string().optional().describe("The task for a single subagent to perform. Required when jobs is omitted."),
1908
- subagent_type: import_zod.z.string().optional().describe('Agent type: "general-purpose", "Explore", "Plan", or a custom agent name'),
1909
- model: import_zod.z.string().optional().describe("Optional model override"),
1910
- isolation: import_zod.z.enum(["none", "worktree"]).optional().describe('Optional runtime isolation mode. "worktree" runs in a Git worktree.'),
1911
- jobs: import_zod.z.array(
1912
- import_zod.z.object({
1913
- label: import_zod.z.string().optional().describe("Stable role label for this batch job"),
1914
- prompt: import_zod.z.string().describe("The task for this subagent to perform"),
1915
- subagent_type: import_zod.z.string().optional().describe("Agent type for this job"),
1916
- model: import_zod.z.string().optional().describe("Optional model override for this job"),
1917
- isolation: import_zod.z.enum(["none", "worktree"]).optional().describe("Isolation for this job")
2434
+ var AgentSchema = import_zod2.z.object({
2435
+ prompt: import_zod2.z.string().optional().describe("The task for a single subagent to perform. Required when jobs is omitted."),
2436
+ subagent_type: import_zod2.z.string().optional().describe('Agent type: "general-purpose", "Explore", "Plan", or a custom agent name'),
2437
+ model: import_zod2.z.string().optional().describe("Optional model override"),
2438
+ isolation: import_zod2.z.enum(["none", "worktree"]).optional().describe('Optional runtime isolation mode. "worktree" runs in a Git worktree.'),
2439
+ jobs: import_zod2.z.array(
2440
+ import_zod2.z.object({
2441
+ label: import_zod2.z.string().optional().describe("Stable role label for this batch job"),
2442
+ prompt: import_zod2.z.string().describe("The task for this subagent to perform"),
2443
+ subagent_type: import_zod2.z.string().optional().describe("Agent type for this job"),
2444
+ model: import_zod2.z.string().optional().describe("Optional model override for this job"),
2445
+ isolation: import_zod2.z.enum(["none", "worktree"]).optional().describe("Isolation for this job")
1918
2446
  }).passthrough()
1919
2447
  ).optional().describe("Batch of subagent jobs to start in one Agent tool call")
1920
2448
  }).passthrough();
@@ -2039,10 +2567,10 @@ async function runManagedAgent(args, deps, manager) {
2039
2567
  }
2040
2568
  function createAgentTool(deps) {
2041
2569
  const manager = createSubagentManager(deps);
2042
- return (0, import_agent_tools.createZodFunctionTool)(
2570
+ return (0, import_agent_tools2.createZodFunctionTool)(
2043
2571
  "Agent",
2044
2572
  AGENT_TOOL_DESCRIPTION,
2045
- asZodSchema(AgentSchema),
2573
+ asZodSchema2(AgentSchema),
2046
2574
  async (params) => {
2047
2575
  const args = params;
2048
2576
  if (Array.isArray(args.jobs) && args.jobs.length > 0) {
@@ -2144,8 +2672,8 @@ var BackgroundJobOrchestrator = class {
2144
2672
  createRecord(state) {
2145
2673
  let resolveGroup = () => {
2146
2674
  };
2147
- const completion = new Promise((resolve4) => {
2148
- resolveGroup = resolve4;
2675
+ const completion = new Promise((resolve6) => {
2676
+ resolveGroup = resolve6;
2149
2677
  });
2150
2678
  return { state, completion, resolve: resolveGroup };
2151
2679
  }
@@ -2270,8 +2798,385 @@ function retrieveSessionBackgroundTaskManager(key) {
2270
2798
  }
2271
2799
 
2272
2800
  // src/interactive/interactive-session-execution.ts
2273
- var import_node_crypto = require("crypto");
2801
+ var import_node_crypto3 = require("crypto");
2274
2802
  var import_agent_core5 = require("@robota-sdk/agent-core");
2803
+
2804
+ // src/context/context-reference-inventory.ts
2805
+ var DEFAULT_MAX_ACTIVE_REFERENCES = Number("8");
2806
+ var BYTES_PER_KIB = Number("1024");
2807
+ var DEFAULT_MAX_ACTIVE_BYTES = Number("256") * BYTES_PER_KIB;
2808
+ var DEFAULT_MAX_OBSERVED_REFERENCES = Number("32");
2809
+ function createContextReferenceItem(record, loadType, status, timestamp = (/* @__PURE__ */ new Date()).toISOString()) {
2810
+ return {
2811
+ id: `${loadType}:${record.relativePath}`,
2812
+ sourcePath: record.sourcePath,
2813
+ relativePath: record.relativePath,
2814
+ originalReference: record.originalReference,
2815
+ loadType,
2816
+ status,
2817
+ byteLength: record.byteLength,
2818
+ loadedAt: timestamp,
2819
+ lastUsedAt: timestamp
2820
+ };
2821
+ }
2822
+ function upsertContextReference(references, item, limits) {
2823
+ const existing = references.find((reference) => reference.sourcePath === item.sourcePath);
2824
+ const retained = references.filter((reference) => reference.sourcePath !== item.sourcePath);
2825
+ const nextItem = existing ? mergeContextReference(existing, item) : item;
2826
+ return enforceContextReferenceLimits([...retained, nextItem], limits);
2827
+ }
2828
+ function removeContextReference(references, query) {
2829
+ const normalized = normalizeReferenceQuery(query);
2830
+ const removed = references.find((reference) => matchesContextReference(reference, normalized));
2831
+ if (!removed) return { references: [...references], result: {} };
2832
+ return {
2833
+ references: references.filter((reference) => reference.sourcePath !== removed.sourcePath),
2834
+ result: { removed }
2835
+ };
2836
+ }
2837
+ function clearContextReferences(references) {
2838
+ return { removed: [...references] };
2839
+ }
2840
+ function listActiveContextReferences(references) {
2841
+ return references.filter((reference) => reference.status === "active");
2842
+ }
2843
+ function toContextReferenceRecords(references) {
2844
+ return references.map((reference) => ({
2845
+ originalReference: reference.originalReference,
2846
+ sourcePath: reference.sourcePath,
2847
+ relativePath: reference.relativePath,
2848
+ reason: reference.loadType,
2849
+ depth: 0,
2850
+ byteLength: reference.byteLength
2851
+ }));
2852
+ }
2853
+ function mergeContextReference(existing, incoming) {
2854
+ if (incoming.status === "active") return { ...incoming, loadedAt: existing.loadedAt };
2855
+ return {
2856
+ ...existing,
2857
+ byteLength: incoming.byteLength,
2858
+ originalReference: incoming.originalReference,
2859
+ lastUsedAt: incoming.lastUsedAt
2860
+ };
2861
+ }
2862
+ function enforceContextReferenceLimits(references, limits) {
2863
+ const maxActiveReferences = limits?.maxActiveReferences ?? DEFAULT_MAX_ACTIVE_REFERENCES;
2864
+ const maxActiveBytes = limits?.maxActiveBytes ?? DEFAULT_MAX_ACTIVE_BYTES;
2865
+ const maxObservedReferences = limits?.maxObservedReferences ?? DEFAULT_MAX_OBSERVED_REFERENCES;
2866
+ const evicted = [];
2867
+ let next = [...references];
2868
+ while (countActiveReferences(next) > maxActiveReferences || countActiveBytes(next) > maxActiveBytes) {
2869
+ const candidate = next.find((reference) => reference.status === "active");
2870
+ if (!candidate) break;
2871
+ evicted.push(candidate);
2872
+ next = next.filter((reference) => reference.sourcePath !== candidate.sourcePath);
2873
+ }
2874
+ const observed = next.filter((reference) => reference.status === "observed");
2875
+ if (observed.length > maxObservedReferences) {
2876
+ const overflow = observed.slice(0, observed.length - maxObservedReferences);
2877
+ evicted.push(...overflow);
2878
+ next = next.filter(
2879
+ (reference) => reference.status !== "observed" || !overflow.some((removed) => removed.sourcePath === reference.sourcePath)
2880
+ );
2881
+ }
2882
+ return { references: next, evicted };
2883
+ }
2884
+ function countActiveReferences(references) {
2885
+ return references.filter((reference) => reference.status === "active").length;
2886
+ }
2887
+ function countActiveBytes(references) {
2888
+ return references.reduce(
2889
+ (total, reference) => total + (reference.status === "active" ? reference.byteLength : 0),
2890
+ 0
2891
+ );
2892
+ }
2893
+ function normalizeReferenceQuery(query) {
2894
+ return query.startsWith("@") ? query.slice(1) : query;
2895
+ }
2896
+ function matchesContextReference(reference, query) {
2897
+ return reference.relativePath === query || reference.sourcePath === query || reference.originalReference === query || reference.originalReference === `@${query}`;
2898
+ }
2899
+
2900
+ // src/context/prompt-file-reference-format.ts
2901
+ var import_node_crypto2 = require("crypto");
2902
+ function buildPromptWithFileReferences(input, references) {
2903
+ if (references.length === 0) return input;
2904
+ const blocks = references.map((reference) => {
2905
+ const content = reference.content.replaceAll("</file>", "<\\/file>");
2906
+ return [
2907
+ `<file path="${escapeAttribute(reference.relativePath)}" bytes="${reference.byteLength}" reason="${reference.reason}">`,
2908
+ content,
2909
+ "</file>"
2910
+ ].join("\n");
2911
+ });
2912
+ return [input, "<robota_file_references>", ...blocks, "</robota_file_references>"].join("\n\n");
2913
+ }
2914
+ function hasBlockingPromptFileReferenceDiagnostics(diagnostics) {
2915
+ return diagnostics.some((diagnostic) => diagnostic.severity === "error");
2916
+ }
2917
+ function formatPromptFileReferenceDiagnostics(diagnostics) {
2918
+ if (diagnostics.length === 0) return "";
2919
+ return [
2920
+ "File reference error:",
2921
+ ...diagnostics.map((diagnostic) => `- ${diagnostic.reference}: ${diagnostic.message}`)
2922
+ ].join("\n");
2923
+ }
2924
+ function toPromptFileReferenceRecords(references) {
2925
+ return references.map(({ content: _content, ...record }) => record);
2926
+ }
2927
+ function createPromptFileReferenceHistoryEntry(references) {
2928
+ const records = toPromptFileReferenceRecords(references);
2929
+ return {
2930
+ id: `prompt_file_reference_${(0, import_node_crypto2.randomUUID)()}`,
2931
+ timestamp: /* @__PURE__ */ new Date(),
2932
+ category: "event",
2933
+ type: "prompt-file-reference",
2934
+ data: {
2935
+ message: formatLoadedPromptFileReferencesMessage(records),
2936
+ references: records
2937
+ }
2938
+ };
2939
+ }
2940
+ function escapeAttribute(value) {
2941
+ return value.replaceAll("&", "&amp;").replaceAll('"', "&quot;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
2942
+ }
2943
+ function formatLoadedPromptFileReferencesMessage(references) {
2944
+ const list = references.map((reference) => `${reference.relativePath} (${reference.byteLength} B)`).join(", ");
2945
+ return `Loaded file references: ${list}`;
2946
+ }
2947
+
2948
+ // src/context/prompt-file-reference-parser.ts
2949
+ var REFERENCE_PATTERN = /(^|[\s([{])@([^\s)\]}>,;"'`]+)/g;
2950
+ function parsePromptFileReferences(input) {
2951
+ const references = [];
2952
+ for (const match of input.matchAll(REFERENCE_PATTERN)) {
2953
+ const token = stripTrailingPunctuation(match[2] ?? "");
2954
+ if (!isPathLikeReference(token)) continue;
2955
+ references.push({
2956
+ original: `@${token}`,
2957
+ path: token,
2958
+ index: match.index ?? 0
2959
+ });
2960
+ }
2961
+ return references;
2962
+ }
2963
+ function stripTrailingPunctuation(token) {
2964
+ let end = token.length;
2965
+ while (end > 0 && /[.,:;!?]/.test(token[end - 1] ?? "")) {
2966
+ end -= 1;
2967
+ }
2968
+ return token.slice(0, end);
2969
+ }
2970
+ function isPathLikeReference(referencePath) {
2971
+ if (referencePath.length === 0) return false;
2972
+ if (referencePath.includes("://")) return false;
2973
+ return referencePath.startsWith("./") || referencePath.startsWith("../") || referencePath.startsWith("/") || referencePath.startsWith("~/") || referencePath.startsWith(".") || referencePath.includes(".");
2974
+ }
2975
+
2976
+ // src/context/prompt-file-reference-resolver.ts
2977
+ var import_promises = require("fs/promises");
2978
+ var import_node_path6 = require("path");
2979
+
2980
+ // src/context/prompt-file-reference-paths.ts
2981
+ var import_node_os3 = require("os");
2982
+ var import_node_path5 = require("path");
2983
+ function resolveCandidatePath(referencePath, rootPath) {
2984
+ if (referencePath.startsWith("~/")) {
2985
+ return (0, import_node_path5.resolve)((0, import_node_os3.homedir)(), referencePath.slice("~/".length));
2986
+ }
2987
+ if ((0, import_node_path5.isAbsolute)(referencePath)) {
2988
+ return (0, import_node_path5.resolve)(referencePath);
2989
+ }
2990
+ return (0, import_node_path5.resolve)(rootPath, referencePath);
2991
+ }
2992
+ function isPathWithinRoot(candidatePath, rootPath) {
2993
+ const relativePath = (0, import_node_path5.relative)(rootPath, candidatePath);
2994
+ return relativePath === "" || !relativePath.startsWith("..") && !(0, import_node_path5.isAbsolute)(relativePath);
2995
+ }
2996
+ function normalizeRelativePath(rootPath, sourcePath) {
2997
+ return (0, import_node_path5.relative)(rootPath, sourcePath).split(import_node_path5.sep).join("/");
2998
+ }
2999
+
3000
+ // src/context/prompt-file-reference-resolver.ts
3001
+ var DEFAULT_MAX_DEPTH = Number("2");
3002
+ var DEFAULT_MAX_REFERENCES = Number("8");
3003
+ var BYTES_PER_KIB2 = Number("1024");
3004
+ var DEFAULT_MAX_FILE_BYTES = Number("64") * BYTES_PER_KIB2;
3005
+ var DEFAULT_MAX_TOTAL_BYTES = Number("256") * BYTES_PER_KIB2;
3006
+ async function resolvePromptFileReferences(input, options) {
3007
+ const state = await createResolveState(options);
3008
+ for (const reference of parsePromptFileReferences(input)) {
3009
+ await resolveReference(reference, 0, [], state);
3010
+ }
3011
+ return toResolvedReferences(state);
3012
+ }
3013
+ async function resolvePromptFileReferencePaths(referencePaths, options) {
3014
+ const state = await createResolveState(options);
3015
+ for (const referencePath of referencePaths) {
3016
+ await resolveReference(
3017
+ { original: `@${referencePath}`, path: referencePath, index: 0 },
3018
+ 0,
3019
+ [],
3020
+ state
3021
+ );
3022
+ }
3023
+ return toResolvedReferences(state);
3024
+ }
3025
+ async function createResolveState(options) {
3026
+ return {
3027
+ rootPath: await resolveWorkspaceRoot(options.cwd),
3028
+ limits: resolveLimits(options.limits),
3029
+ reason: options.reason ?? "prompt-reference",
3030
+ references: [],
3031
+ diagnostics: [],
3032
+ loadedPaths: /* @__PURE__ */ new Set(),
3033
+ totalBytes: 0
3034
+ };
3035
+ }
3036
+ function toResolvedReferences(state) {
3037
+ return {
3038
+ references: state.references,
3039
+ diagnostics: state.diagnostics
3040
+ };
3041
+ }
3042
+ function resolveLimits(limits) {
3043
+ return {
3044
+ maxDepth: limits?.maxDepth ?? DEFAULT_MAX_DEPTH,
3045
+ maxReferences: limits?.maxReferences ?? DEFAULT_MAX_REFERENCES,
3046
+ maxFileBytes: limits?.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES,
3047
+ maxTotalBytes: limits?.maxTotalBytes ?? DEFAULT_MAX_TOTAL_BYTES
3048
+ };
3049
+ }
3050
+ async function resolveWorkspaceRoot(cwd) {
3051
+ try {
3052
+ return await (0, import_promises.realpath)(cwd);
3053
+ } catch {
3054
+ return (0, import_node_path6.resolve)(cwd);
3055
+ }
3056
+ }
3057
+ async function resolveReference(reference, depth, activePaths, state) {
3058
+ if (!checkReferenceBudget(reference, depth, state)) return;
3059
+ const sourcePath = await resolveReferencePath(reference, state);
3060
+ if (sourcePath === void 0) return;
3061
+ if (!checkReferenceCycleAndDuplicate(reference, sourcePath, activePaths, state)) return;
3062
+ const fileInfo = await inspectReferenceFile(reference, sourcePath, state);
3063
+ if (fileInfo === void 0) return;
3064
+ const content = await readReferenceFile(reference, sourcePath, state);
3065
+ if (content === void 0) return;
3066
+ state.loadedPaths.add(sourcePath);
3067
+ state.totalBytes += fileInfo.byteLength;
3068
+ state.references.push(buildResolvedReference(reference, fileInfo, depth, content, state));
3069
+ await resolveNestedReferences(content, depth, [...activePaths, sourcePath], state);
3070
+ }
3071
+ function checkReferenceBudget(reference, depth, state) {
3072
+ if (state.references.length >= state.limits.maxReferences) {
3073
+ pushDiagnostic(state, "too-many-references", reference, "Too many file references.");
3074
+ return false;
3075
+ }
3076
+ if (depth > state.limits.maxDepth) {
3077
+ pushDiagnostic(state, "max-depth", reference, "File reference nesting is too deep.");
3078
+ return false;
3079
+ }
3080
+ return true;
3081
+ }
3082
+ async function resolveReferencePath(reference, state) {
3083
+ const candidatePath = resolveCandidatePath(reference.path, state.rootPath);
3084
+ if (!isPathWithinRoot(candidatePath, state.rootPath)) {
3085
+ pushDiagnostic(state, "outside-root", reference, "Referenced path is outside the workspace.");
3086
+ return void 0;
3087
+ }
3088
+ try {
3089
+ const sourcePath = await (0, import_promises.realpath)(candidatePath);
3090
+ if (isPathWithinRoot(sourcePath, state.rootPath)) return sourcePath;
3091
+ pushDiagnostic(
3092
+ state,
3093
+ "outside-root",
3094
+ reference,
3095
+ "Referenced path resolves outside the workspace."
3096
+ );
3097
+ } catch {
3098
+ pushDiagnostic(state, "not-found", reference, "Referenced file was not found.");
3099
+ }
3100
+ return void 0;
3101
+ }
3102
+ function checkReferenceCycleAndDuplicate(reference, sourcePath, activePaths, state) {
3103
+ if (activePaths.includes(sourcePath)) {
3104
+ pushDiagnostic(state, "circular-reference", reference, "Circular file reference detected.");
3105
+ return false;
3106
+ }
3107
+ return !state.loadedPaths.has(sourcePath);
3108
+ }
3109
+ async function inspectReferenceFile(reference, sourcePath, state) {
3110
+ try {
3111
+ const fileStat = await (0, import_promises.stat)(sourcePath);
3112
+ if (fileStat.isDirectory()) {
3113
+ pushDiagnostic(
3114
+ state,
3115
+ "directory-not-supported",
3116
+ reference,
3117
+ "Directory references are not supported."
3118
+ );
3119
+ return void 0;
3120
+ }
3121
+ if (fileStat.size > state.limits.maxFileBytes) {
3122
+ pushDiagnostic(
3123
+ state,
3124
+ "file-too-large",
3125
+ reference,
3126
+ "Referenced file exceeds the per-file size limit."
3127
+ );
3128
+ return void 0;
3129
+ }
3130
+ if (state.totalBytes + fileStat.size > state.limits.maxTotalBytes) {
3131
+ pushDiagnostic(
3132
+ state,
3133
+ "total-too-large",
3134
+ reference,
3135
+ "Referenced files exceed the total size limit."
3136
+ );
3137
+ return void 0;
3138
+ }
3139
+ return { sourcePath, byteLength: fileStat.size };
3140
+ } catch {
3141
+ pushDiagnostic(state, "unreadable", reference, "Referenced file could not be inspected.");
3142
+ return void 0;
3143
+ }
3144
+ }
3145
+ async function readReferenceFile(reference, sourcePath, state) {
3146
+ try {
3147
+ return await (0, import_promises.readFile)(sourcePath, "utf8");
3148
+ } catch {
3149
+ pushDiagnostic(state, "unreadable", reference, "Referenced file could not be read.");
3150
+ return void 0;
3151
+ }
3152
+ }
3153
+ function buildResolvedReference(reference, fileInfo, depth, content, state) {
3154
+ return {
3155
+ originalReference: reference.original,
3156
+ sourcePath: fileInfo.sourcePath,
3157
+ relativePath: normalizeRelativePath(state.rootPath, fileInfo.sourcePath),
3158
+ reason: state.reason,
3159
+ depth,
3160
+ byteLength: fileInfo.byteLength,
3161
+ content
3162
+ };
3163
+ }
3164
+ async function resolveNestedReferences(content, depth, activePaths, state) {
3165
+ for (const nestedReference of parsePromptFileReferences(content)) {
3166
+ await resolveReference(nestedReference, depth + 1, activePaths, state);
3167
+ }
3168
+ }
3169
+ function pushDiagnostic(state, code, reference, message) {
3170
+ state.diagnostics.push({
3171
+ code,
3172
+ severity: "error",
3173
+ reference: reference.original,
3174
+ message,
3175
+ path: reference.path
3176
+ });
3177
+ }
3178
+
3179
+ // src/interactive/interactive-session-execution.ts
2275
3180
  function isAbortError(err) {
2276
3181
  return err instanceof DOMException && err.name === "AbortError" || err instanceof Error && (err.message.includes("aborted") || err.message.includes("abort"));
2277
3182
  }
@@ -2287,7 +3192,7 @@ function extractToolSummaries(history, historyBefore) {
2287
3192
  }
2288
3193
  return summaries;
2289
3194
  }
2290
- function buildResult(response, sessionHistory, interactiveHistory, historyBefore, contextState) {
3195
+ function buildResult(response, sessionHistory, interactiveHistory, historyBefore, contextState, promptFileReferences) {
2291
3196
  const toolSummaries = extractToolSummaries(sessionHistory, historyBefore);
2292
3197
  const usage = extractTurnUsage(sessionHistory, historyBefore, contextState);
2293
3198
  return {
@@ -2295,7 +3200,8 @@ function buildResult(response, sessionHistory, interactiveHistory, historyBefore
2295
3200
  history: interactiveHistory,
2296
3201
  toolSummaries,
2297
3202
  contextState,
2298
- ...usage && { usage }
3203
+ ...usage && { usage },
3204
+ ...promptFileReferences && promptFileReferences.length > 0 ? { promptFileReferences: [...promptFileReferences] } : {}
2299
3205
  };
2300
3206
  }
2301
3207
  function buildInterruptedResult(sessionHistory, interactiveHistory, historyBefore, contextState) {
@@ -2316,13 +3222,50 @@ function buildInterruptedResult(sessionHistory, interactiveHistory, historyBefor
2316
3222
  }
2317
3223
  function createUsageSummaryEntry(usage) {
2318
3224
  return {
2319
- id: `usage_${(0, import_node_crypto.randomUUID)()}`,
3225
+ id: `usage_${(0, import_node_crypto3.randomUUID)()}`,
2320
3226
  timestamp: /* @__PURE__ */ new Date(),
2321
3227
  category: "event",
2322
3228
  type: "usage-summary",
2323
3229
  data: usage
2324
3230
  };
2325
3231
  }
3232
+ async function preparePromptInput(input, cwd, rawInput, contextReferences = []) {
3233
+ const activeReferenceResult = await resolvePromptFileReferencePaths(
3234
+ listActiveContextReferences(contextReferences).map((reference) => reference.sourcePath),
3235
+ { cwd, reason: "manual" }
3236
+ );
3237
+ const promptFileReferenceResult = await resolvePromptFileReferences(input, { cwd });
3238
+ const diagnostics = [
3239
+ ...activeReferenceResult.diagnostics,
3240
+ ...promptFileReferenceResult.diagnostics
3241
+ ];
3242
+ if (hasBlockingPromptFileReferenceDiagnostics(diagnostics)) {
3243
+ throw new Error(formatPromptFileReferenceDiagnostics(diagnostics));
3244
+ }
3245
+ const resolvedReferences = dedupeResolvedReferences([
3246
+ ...activeReferenceResult.references,
3247
+ ...promptFileReferenceResult.references
3248
+ ]);
3249
+ const modelInput = buildPromptWithFileReferences(input, resolvedReferences);
3250
+ const hookInput = rawInput ?? (modelInput === input ? void 0 : input);
3251
+ const activeContextReferenceRecords = toPromptFileReferenceRecords(
3252
+ activeReferenceResult.references
3253
+ );
3254
+ const promptFileReferenceRecords = toPromptFileReferenceRecords(
3255
+ promptFileReferenceResult.references
3256
+ );
3257
+ const promptFileReferenceEntry = promptFileReferenceResult.references.length > 0 ? createPromptFileReferenceHistoryEntry(promptFileReferenceResult.references) : void 0;
3258
+ return {
3259
+ modelInput,
3260
+ ...hookInput !== void 0 ? { hookInput } : {},
3261
+ activeContextReferenceRecords,
3262
+ promptFileReferenceRecords,
3263
+ ...promptFileReferenceEntry !== void 0 ? { promptFileReferenceEntry } : {}
3264
+ };
3265
+ }
3266
+ function dedupeResolvedReferences(references) {
3267
+ return [...new Map(references.map((reference) => [reference.sourcePath, reference])).values()];
3268
+ }
2326
3269
  function extractTurnUsage(sessionHistory, historyBefore, contextState) {
2327
3270
  const turnMessages = sessionHistory.slice(historyBefore);
2328
3271
  let promptTokens = 0;
@@ -2349,34 +3292,6 @@ function extractTurnUsage(sessionHistory, historyBefore, contextState) {
2349
3292
  costStatus: "unknown"
2350
3293
  };
2351
3294
  }
2352
- function persistSession(sessionStore, session, sessionName, cwd, history, backgroundState, memoryState) {
2353
- try {
2354
- const sessionId = session.getSessionId();
2355
- const existing = sessionStore.load(sessionId);
2356
- sessionStore.save({
2357
- id: sessionId,
2358
- name: sessionName ?? existing?.name,
2359
- cwd,
2360
- createdAt: existing?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
2361
- updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
2362
- messages: session.getHistory(),
2363
- history,
2364
- systemPrompt: session.getSystemMessage(),
2365
- toolSchemas: session.getToolSchemas(),
2366
- ...backgroundState ? {
2367
- backgroundTasks: [...backgroundState.tasks],
2368
- backgroundTaskEvents: [...backgroundState.events],
2369
- backgroundJobGroups: [...backgroundState.groups ?? []],
2370
- backgroundJobGroupEvents: [...backgroundState.groupEvents ?? []]
2371
- } : {},
2372
- ...memoryState ? {
2373
- memoryEvents: [...memoryState.events],
2374
- usedMemoryReferences: [...memoryState.usedReferences]
2375
- } : {}
2376
- });
2377
- } catch {
2378
- }
2379
- }
2380
3295
  var NOOP_TERMINAL = {
2381
3296
  write: () => {
2382
3297
  },
@@ -2393,8 +3308,75 @@ var NOOP_TERMINAL = {
2393
3308
  } })
2394
3309
  };
2395
3310
 
3311
+ // src/interactive/interactive-session-persistence.ts
3312
+ function persistSession(sessionStore, session, sessionName, cwd, history, backgroundState, memoryState, skillActivationState, contextReferenceState, sandboxState) {
3313
+ try {
3314
+ const sessionId = session.getSessionId();
3315
+ const existing = sessionStore.load(sessionId);
3316
+ const sandboxSnapshotId = sandboxState?.snapshotId ?? existing?.sandboxSnapshotId;
3317
+ sessionStore.save(
3318
+ buildInteractiveSessionRecord({
3319
+ session,
3320
+ sessionId,
3321
+ sessionName: sessionName ?? existing?.name,
3322
+ cwd,
3323
+ history,
3324
+ createdAt: existing?.createdAt,
3325
+ backgroundState,
3326
+ memoryState,
3327
+ skillActivationState,
3328
+ contextReferenceState,
3329
+ ...sandboxSnapshotId !== void 0 ? { sandboxSnapshotId } : {}
3330
+ })
3331
+ );
3332
+ } catch {
3333
+ }
3334
+ }
3335
+ function buildInteractiveSessionRecord(input) {
3336
+ return {
3337
+ id: input.sessionId,
3338
+ ...input.sessionName !== void 0 ? { name: input.sessionName } : {},
3339
+ cwd: input.cwd,
3340
+ createdAt: input.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
3341
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
3342
+ messages: input.session.getHistory(),
3343
+ history: input.history,
3344
+ systemPrompt: input.session.getSystemMessage(),
3345
+ toolSchemas: input.session.getToolSchemas(),
3346
+ ...input.sandboxSnapshotId !== void 0 ? { sandboxSnapshotId: input.sandboxSnapshotId } : {},
3347
+ ...buildBackgroundRecordFields(input.backgroundState),
3348
+ ...buildMemoryRecordFields(input.memoryState),
3349
+ ...buildSkillActivationRecordFields(input.skillActivationState),
3350
+ ...buildContextReferenceRecordFields(input.contextReferenceState)
3351
+ };
3352
+ }
3353
+ function buildBackgroundRecordFields(state) {
3354
+ if (!state) return {};
3355
+ return {
3356
+ backgroundTasks: [...state.tasks],
3357
+ backgroundTaskEvents: [...state.events],
3358
+ backgroundJobGroups: [...state.groups ?? []],
3359
+ backgroundJobGroupEvents: [...state.groupEvents ?? []]
3360
+ };
3361
+ }
3362
+ function buildMemoryRecordFields(state) {
3363
+ if (!state) return {};
3364
+ return {
3365
+ memoryEvents: [...state.events],
3366
+ usedMemoryReferences: [...state.usedReferences]
3367
+ };
3368
+ }
3369
+ function buildSkillActivationRecordFields(state) {
3370
+ if (!state) return {};
3371
+ return { skillActivationEvents: [...state.events] };
3372
+ }
3373
+ function buildContextReferenceRecordFields(state) {
3374
+ if (!state) return {};
3375
+ return { contextReferences: [...state.references] };
3376
+ }
3377
+
2396
3378
  // src/interactive/interactive-session-streaming.ts
2397
- var import_node_crypto2 = require("crypto");
3379
+ var import_node_crypto4 = require("crypto");
2398
3380
  var import_node_fs3 = require("fs");
2399
3381
  var TOOL_ARG_DISPLAY_MAX = 80;
2400
3382
  var TAIL_KEEP = 30;
@@ -2492,7 +3474,7 @@ function pushToolSummaryToHistory(state) {
2492
3474
  return `${status} ${t.toolName}${t.firstArg ? `(${t.firstArg})` : ""}`;
2493
3475
  }).join("\n");
2494
3476
  state.history.push({
2495
- id: (0, import_node_crypto2.randomUUID)(),
3477
+ id: (0, import_node_crypto4.randomUUID)(),
2496
3478
  timestamp: /* @__PURE__ */ new Date(),
2497
3479
  category: "event",
2498
3480
  type: "tool-summary",
@@ -2528,7 +3510,7 @@ function applyToolStart(state, event) {
2528
3510
  const toolState = { toolName: event.toolName, firstArg, isRunning: true };
2529
3511
  state.activeTools.push(toolState);
2530
3512
  state.history.push({
2531
- id: (0, import_node_crypto2.randomUUID)(),
3513
+ id: (0, import_node_crypto4.randomUUID)(),
2532
3514
  timestamp: /* @__PURE__ */ new Date(),
2533
3515
  category: "event",
2534
3516
  type: "tool-start",
@@ -2550,7 +3532,7 @@ function applyToolEnd(state, event) {
2550
3532
  state.activeTools[idx] = finished;
2551
3533
  state.activeTools = trimCompletedTools(state.activeTools);
2552
3534
  state.history.push({
2553
- id: (0, import_node_crypto2.randomUUID)(),
3535
+ id: (0, import_node_crypto4.randomUUID)(),
2554
3536
  timestamp: /* @__PURE__ */ new Date(),
2555
3537
  category: "event",
2556
3538
  type: "tool-end",
@@ -2570,110 +3552,110 @@ var import_fs2 = require("fs");
2570
3552
  var import_path2 = require("path");
2571
3553
 
2572
3554
  // src/config/config-types.ts
2573
- var import_zod2 = require("zod");
2574
- var UniversalValueSchema = import_zod2.z.lazy(
2575
- () => import_zod2.z.union([
2576
- import_zod2.z.string(),
2577
- import_zod2.z.number(),
2578
- import_zod2.z.boolean(),
2579
- import_zod2.z.null(),
2580
- import_zod2.z.undefined(),
2581
- import_zod2.z.date(),
2582
- import_zod2.z.array(UniversalValueSchema),
2583
- import_zod2.z.record(UniversalValueSchema)
3555
+ var import_zod3 = require("zod");
3556
+ var UniversalValueSchema = import_zod3.z.lazy(
3557
+ () => import_zod3.z.union([
3558
+ import_zod3.z.string(),
3559
+ import_zod3.z.number(),
3560
+ import_zod3.z.boolean(),
3561
+ import_zod3.z.null(),
3562
+ import_zod3.z.undefined(),
3563
+ import_zod3.z.date(),
3564
+ import_zod3.z.array(UniversalValueSchema),
3565
+ import_zod3.z.record(UniversalValueSchema)
2584
3566
  ])
2585
3567
  );
2586
- var ProviderSchema = import_zod2.z.object({
2587
- name: import_zod2.z.string().optional(),
2588
- model: import_zod2.z.string().optional(),
2589
- apiKey: import_zod2.z.string().optional(),
2590
- baseURL: import_zod2.z.string().optional(),
2591
- timeout: import_zod2.z.number().optional(),
2592
- options: import_zod2.z.record(UniversalValueSchema).optional()
3568
+ var ProviderSchema = import_zod3.z.object({
3569
+ name: import_zod3.z.string().optional(),
3570
+ model: import_zod3.z.string().optional(),
3571
+ apiKey: import_zod3.z.string().optional(),
3572
+ baseURL: import_zod3.z.string().optional(),
3573
+ timeout: import_zod3.z.number().optional(),
3574
+ options: import_zod3.z.record(UniversalValueSchema).optional()
2593
3575
  });
2594
- var ProviderProfileSchema = import_zod2.z.object({
2595
- type: import_zod2.z.string().optional(),
2596
- model: import_zod2.z.string().optional(),
2597
- apiKey: import_zod2.z.string().optional(),
2598
- baseURL: import_zod2.z.string().optional(),
2599
- timeout: import_zod2.z.number().optional(),
2600
- options: import_zod2.z.record(UniversalValueSchema).optional()
3576
+ var ProviderProfileSchema = import_zod3.z.object({
3577
+ type: import_zod3.z.string().optional(),
3578
+ model: import_zod3.z.string().optional(),
3579
+ apiKey: import_zod3.z.string().optional(),
3580
+ baseURL: import_zod3.z.string().optional(),
3581
+ timeout: import_zod3.z.number().optional(),
3582
+ options: import_zod3.z.record(UniversalValueSchema).optional()
2601
3583
  });
2602
- var PermissionsSchema = import_zod2.z.object({
3584
+ var PermissionsSchema = import_zod3.z.object({
2603
3585
  /** Patterns that are always approved without prompting */
2604
- allow: import_zod2.z.array(import_zod2.z.string()).optional(),
3586
+ allow: import_zod3.z.array(import_zod3.z.string()).optional(),
2605
3587
  /** Patterns that are always denied */
2606
- deny: import_zod2.z.array(import_zod2.z.string()).optional()
3588
+ deny: import_zod3.z.array(import_zod3.z.string()).optional()
2607
3589
  });
2608
- var EnvSchema = import_zod2.z.record(import_zod2.z.string()).optional();
2609
- var CommandHookDefinitionSchema = import_zod2.z.object({
2610
- type: import_zod2.z.literal("command"),
2611
- command: import_zod2.z.string(),
2612
- timeout: import_zod2.z.number().optional()
3590
+ var EnvSchema = import_zod3.z.record(import_zod3.z.string()).optional();
3591
+ var CommandHookDefinitionSchema = import_zod3.z.object({
3592
+ type: import_zod3.z.literal("command"),
3593
+ command: import_zod3.z.string(),
3594
+ timeout: import_zod3.z.number().optional()
2613
3595
  });
2614
- var HttpHookDefinitionSchema = import_zod2.z.object({
2615
- type: import_zod2.z.literal("http"),
2616
- url: import_zod2.z.string(),
2617
- headers: import_zod2.z.record(import_zod2.z.string()).optional(),
2618
- timeout: import_zod2.z.number().optional()
3596
+ var HttpHookDefinitionSchema = import_zod3.z.object({
3597
+ type: import_zod3.z.literal("http"),
3598
+ url: import_zod3.z.string(),
3599
+ headers: import_zod3.z.record(import_zod3.z.string()).optional(),
3600
+ timeout: import_zod3.z.number().optional()
2619
3601
  });
2620
- var PromptHookDefinitionSchema = import_zod2.z.object({
2621
- type: import_zod2.z.literal("prompt"),
2622
- prompt: import_zod2.z.string(),
2623
- model: import_zod2.z.string().optional()
3602
+ var PromptHookDefinitionSchema = import_zod3.z.object({
3603
+ type: import_zod3.z.literal("prompt"),
3604
+ prompt: import_zod3.z.string(),
3605
+ model: import_zod3.z.string().optional()
2624
3606
  });
2625
- var AgentHookDefinitionSchema = import_zod2.z.object({
2626
- type: import_zod2.z.literal("agent"),
2627
- agent: import_zod2.z.string(),
2628
- maxTurns: import_zod2.z.number().optional(),
2629
- timeout: import_zod2.z.number().optional()
3607
+ var AgentHookDefinitionSchema = import_zod3.z.object({
3608
+ type: import_zod3.z.literal("agent"),
3609
+ agent: import_zod3.z.string(),
3610
+ maxTurns: import_zod3.z.number().optional(),
3611
+ timeout: import_zod3.z.number().optional()
2630
3612
  });
2631
- var HookDefinitionSchema = import_zod2.z.discriminatedUnion("type", [
3613
+ var HookDefinitionSchema = import_zod3.z.discriminatedUnion("type", [
2632
3614
  CommandHookDefinitionSchema,
2633
3615
  HttpHookDefinitionSchema,
2634
3616
  PromptHookDefinitionSchema,
2635
3617
  AgentHookDefinitionSchema
2636
3618
  ]);
2637
- var HookGroupSchema = import_zod2.z.object({
2638
- matcher: import_zod2.z.string(),
2639
- hooks: import_zod2.z.array(HookDefinitionSchema)
3619
+ var HookGroupSchema = import_zod3.z.object({
3620
+ matcher: import_zod3.z.string(),
3621
+ hooks: import_zod3.z.array(HookDefinitionSchema)
2640
3622
  });
2641
- var HooksSchema = import_zod2.z.object({
2642
- PreToolUse: import_zod2.z.array(HookGroupSchema).optional(),
2643
- PostToolUse: import_zod2.z.array(HookGroupSchema).optional(),
2644
- SessionStart: import_zod2.z.array(HookGroupSchema).optional(),
2645
- SessionEnd: import_zod2.z.array(HookGroupSchema).optional(),
2646
- Stop: import_zod2.z.array(HookGroupSchema).optional(),
2647
- StopFailure: import_zod2.z.array(HookGroupSchema).optional(),
2648
- PreCompact: import_zod2.z.array(HookGroupSchema).optional(),
2649
- PostCompact: import_zod2.z.array(HookGroupSchema).optional(),
2650
- UserPromptSubmit: import_zod2.z.array(HookGroupSchema).optional(),
2651
- SubagentStart: import_zod2.z.array(HookGroupSchema).optional(),
2652
- SubagentStop: import_zod2.z.array(HookGroupSchema).optional(),
2653
- WorktreeCreate: import_zod2.z.array(HookGroupSchema).optional(),
2654
- WorktreeRemove: import_zod2.z.array(HookGroupSchema).optional()
3623
+ var HooksSchema = import_zod3.z.object({
3624
+ PreToolUse: import_zod3.z.array(HookGroupSchema).optional(),
3625
+ PostToolUse: import_zod3.z.array(HookGroupSchema).optional(),
3626
+ SessionStart: import_zod3.z.array(HookGroupSchema).optional(),
3627
+ SessionEnd: import_zod3.z.array(HookGroupSchema).optional(),
3628
+ Stop: import_zod3.z.array(HookGroupSchema).optional(),
3629
+ StopFailure: import_zod3.z.array(HookGroupSchema).optional(),
3630
+ PreCompact: import_zod3.z.array(HookGroupSchema).optional(),
3631
+ PostCompact: import_zod3.z.array(HookGroupSchema).optional(),
3632
+ UserPromptSubmit: import_zod3.z.array(HookGroupSchema).optional(),
3633
+ SubagentStart: import_zod3.z.array(HookGroupSchema).optional(),
3634
+ SubagentStop: import_zod3.z.array(HookGroupSchema).optional(),
3635
+ WorktreeCreate: import_zod3.z.array(HookGroupSchema).optional(),
3636
+ WorktreeRemove: import_zod3.z.array(HookGroupSchema).optional()
2655
3637
  }).optional();
2656
- var EnabledPluginsSchema = import_zod2.z.record(import_zod2.z.boolean()).optional();
2657
- var MarketplaceSourceSchema = import_zod2.z.object({
2658
- source: import_zod2.z.object({
2659
- type: import_zod2.z.enum(["github", "git", "local", "url"]),
2660
- repo: import_zod2.z.string().optional(),
2661
- url: import_zod2.z.string().optional(),
2662
- path: import_zod2.z.string().optional(),
2663
- ref: import_zod2.z.string().optional()
3638
+ var EnabledPluginsSchema = import_zod3.z.record(import_zod3.z.boolean()).optional();
3639
+ var MarketplaceSourceSchema = import_zod3.z.object({
3640
+ source: import_zod3.z.object({
3641
+ type: import_zod3.z.enum(["github", "git", "local", "url"]),
3642
+ repo: import_zod3.z.string().optional(),
3643
+ url: import_zod3.z.string().optional(),
3644
+ path: import_zod3.z.string().optional(),
3645
+ ref: import_zod3.z.string().optional()
2664
3646
  })
2665
3647
  });
2666
- var ExtraKnownMarketplacesSchema = import_zod2.z.record(MarketplaceSourceSchema).optional().catch(void 0);
2667
- var AutoCompactThresholdSchema = import_zod2.z.union([import_zod2.z.number().gt(0).lte(1), import_zod2.z.literal(false)]).optional();
2668
- var SettingsSchema = import_zod2.z.object({
3648
+ var ExtraKnownMarketplacesSchema = import_zod3.z.record(MarketplaceSourceSchema).optional().catch(void 0);
3649
+ var AutoCompactThresholdSchema = import_zod3.z.union([import_zod3.z.number().gt(0).lte(1), import_zod3.z.literal(false)]).optional();
3650
+ var SettingsSchema = import_zod3.z.object({
2669
3651
  /** Trust level used when no --permission-mode flag is given */
2670
- defaultTrustLevel: import_zod2.z.enum(["safe", "moderate", "full"]).optional(),
3652
+ defaultTrustLevel: import_zod3.z.enum(["safe", "moderate", "full"]).optional(),
2671
3653
  /** Response language (e.g., "ko", "en", "ja"). Injected into system prompt. */
2672
- language: import_zod2.z.string().optional(),
3654
+ language: import_zod3.z.string().optional(),
2673
3655
  /** Active provider profile key from providers. */
2674
- currentProvider: import_zod2.z.string().optional(),
3656
+ currentProvider: import_zod3.z.string().optional(),
2675
3657
  /** Provider profiles keyed by user-facing profile name. */
2676
- providers: import_zod2.z.record(ProviderProfileSchema).optional(),
3658
+ providers: import_zod3.z.record(ProviderProfileSchema).optional(),
2677
3659
  /** Legacy single-provider settings. Prefer currentProvider + providers for new config. */
2678
3660
  provider: ProviderSchema.optional(),
2679
3661
  permissions: PermissionsSchema.optional(),
@@ -2727,18 +3709,12 @@ function resolveEnvRef(value) {
2727
3709
  return value;
2728
3710
  }
2729
3711
  function resolveEnvRefs(settings) {
2730
- const provider = settings.provider?.apiKey !== void 0 ? {
2731
- ...settings.provider,
2732
- apiKey: resolveEnvRef(settings.provider.apiKey)
2733
- } : settings.provider;
3712
+ const provider = settings.provider?.apiKey !== void 0 ? resolveProviderCredentialEnvRefs(settings.provider) : settings.provider;
2734
3713
  if (settings.providers !== void 0) {
2735
3714
  const providers = Object.fromEntries(
2736
3715
  Object.entries(settings.providers).map(([name, profile]) => [
2737
3716
  name,
2738
- {
2739
- ...profile,
2740
- ...profile.apiKey !== void 0 && { apiKey: resolveEnvRef(profile.apiKey) }
2741
- }
3717
+ resolveProviderCredentialEnvRefs(profile)
2742
3718
  ])
2743
3719
  );
2744
3720
  return {
@@ -2752,6 +3728,12 @@ function resolveEnvRefs(settings) {
2752
3728
  provider
2753
3729
  };
2754
3730
  }
3731
+ function resolveProviderCredentialEnvRefs(provider) {
3732
+ return {
3733
+ ...provider,
3734
+ ...provider.apiKey !== void 0 && { apiKey: resolveEnvRef(provider.apiKey) }
3735
+ };
3736
+ }
2755
3737
  function mergeSettings(layers) {
2756
3738
  return layers.reduce((merged, layer) => {
2757
3739
  return {
@@ -2785,22 +3767,32 @@ function mergeProviders(base, override) {
2785
3767
  }
2786
3768
  function resolveProvider(merged) {
2787
3769
  if (merged.currentProvider !== void 0) {
2788
- const profile = merged.providers?.[merged.currentProvider];
2789
- if (profile === void 0) {
2790
- throw new Error(`currentProvider "${merged.currentProvider}" was not found in providers`);
2791
- }
2792
- if (profile.type === void 0) {
2793
- throw new Error(`Provider profile "${merged.currentProvider}" is missing type`);
2794
- }
2795
- return {
2796
- name: profile.type,
2797
- model: profile.model ?? DEFAULTS.provider.model,
2798
- apiKey: profile.apiKey ?? DEFAULTS.provider.apiKey,
2799
- ...profile.baseURL !== void 0 && { baseURL: profile.baseURL },
2800
- ...profile.timeout !== void 0 && { timeout: profile.timeout },
2801
- ...profile.options !== void 0 && { options: profile.options }
2802
- };
3770
+ return resolveActiveProviderProfile2(merged);
3771
+ }
3772
+ return resolveLegacyProvider(merged);
3773
+ }
3774
+ function resolveActiveProviderProfile2(merged) {
3775
+ const currentProvider = merged.currentProvider;
3776
+ if (currentProvider === void 0) {
3777
+ throw new Error("currentProvider is required");
2803
3778
  }
3779
+ const profile = merged.providers?.[currentProvider];
3780
+ if (profile === void 0) {
3781
+ throw new Error(`currentProvider "${currentProvider}" was not found in providers`);
3782
+ }
3783
+ if (profile.type === void 0) {
3784
+ throw new Error(`Provider profile "${currentProvider}" is missing type`);
3785
+ }
3786
+ return {
3787
+ name: profile.type,
3788
+ model: profile.model ?? DEFAULTS.provider.model,
3789
+ apiKey: profile.apiKey ?? DEFAULTS.provider.apiKey,
3790
+ ...profile.baseURL !== void 0 && { baseURL: profile.baseURL },
3791
+ ...profile.timeout !== void 0 && { timeout: profile.timeout },
3792
+ ...profile.options !== void 0 && { options: profile.options }
3793
+ };
3794
+ }
3795
+ function resolveLegacyProvider(merged) {
2804
3796
  return {
2805
3797
  name: merged.provider?.name ?? DEFAULTS.provider.name,
2806
3798
  model: merged.provider?.model ?? DEFAULTS.provider.model,
@@ -2972,7 +3964,7 @@ Respond with JSON: { "ok": boolean, "reason"?: string }`;
2972
3964
  };
2973
3965
 
2974
3966
  // src/assembly/create-session.ts
2975
- var import_agent_sessions3 = require("@robota-sdk/agent-sessions");
3967
+ var import_agent_sessions4 = require("@robota-sdk/agent-sessions");
2976
3968
 
2977
3969
  // src/context/system-prompt-composer.ts
2978
3970
  function renderSection(section) {
@@ -3077,9 +4069,15 @@ function formatCapability(descriptor) {
3077
4069
  return `- ${descriptor.name}${arg}: ${descriptor.description}`;
3078
4070
  }
3079
4071
  function createCapabilityKindSection(kind, title, priority, source, descriptors) {
3080
- const content = descriptors.filter((descriptor) => descriptor.modelInvocable && descriptor.kind === kind).map(formatCapability).join("\n");
3081
- if (content.trim().length === 0) return void 0;
3082
- return createSection(`capability-${kind}`, title, priority, content, source);
4072
+ const formattedDescriptors = descriptors.filter((descriptor) => descriptor.modelInvocable && descriptor.kind === kind).map(formatCapability);
4073
+ if (formattedDescriptors.length === 0) return void 0;
4074
+ return createSection(
4075
+ `capability-${kind}`,
4076
+ title,
4077
+ priority,
4078
+ formattedDescriptors.join("\n"),
4079
+ source
4080
+ );
3083
4081
  }
3084
4082
  function createCapabilitySections(descriptors) {
3085
4083
  const sections = [];
@@ -3146,7 +4144,7 @@ function buildSystemPrompt(params) {
3146
4144
  }
3147
4145
 
3148
4146
  // src/assembly/create-tools.ts
3149
- var import_agent_tools2 = require("@robota-sdk/agent-tools");
4147
+ var import_agent_tools3 = require("@robota-sdk/agent-tools");
3150
4148
  var DEFAULT_TOOL_DESCRIPTIONS = [
3151
4149
  "Bash \u2014 execute shell commands",
3152
4150
  "Read \u2014 read file contents with line numbers",
@@ -3157,32 +4155,32 @@ var DEFAULT_TOOL_DESCRIPTIONS = [
3157
4155
  "WebFetch \u2014 fetch URL content as text",
3158
4156
  "WebSearch \u2014 search the internet through the configured local tool"
3159
4157
  ];
3160
- function createDefaultTools() {
4158
+ function createDefaultTools(options = {}) {
3161
4159
  return [
3162
- import_agent_tools2.bashTool,
3163
- import_agent_tools2.readTool,
3164
- import_agent_tools2.writeTool,
3165
- import_agent_tools2.editTool,
3166
- import_agent_tools2.globTool,
3167
- import_agent_tools2.grepTool,
3168
- import_agent_tools2.webFetchTool,
3169
- import_agent_tools2.webSearchTool
4160
+ (0, import_agent_tools3.createBashTool)(options),
4161
+ (0, import_agent_tools3.createReadTool)(options),
4162
+ (0, import_agent_tools3.createWriteTool)(options),
4163
+ (0, import_agent_tools3.createEditTool)(options),
4164
+ import_agent_tools3.globTool,
4165
+ import_agent_tools3.grepTool,
4166
+ import_agent_tools3.webFetchTool,
4167
+ import_agent_tools3.webSearchTool
3170
4168
  ];
3171
4169
  }
3172
4170
 
3173
4171
  // src/tools/background-process-tool.ts
3174
- var import_zod3 = require("zod");
3175
- var import_agent_tools3 = require("@robota-sdk/agent-tools");
4172
+ var import_zod4 = require("zod");
4173
+ var import_agent_tools4 = require("@robota-sdk/agent-tools");
3176
4174
  var DEFAULT_PROCESS_TIMEOUT_MS = 12e4;
3177
- function asZodSchema2(schema) {
4175
+ function asZodSchema3(schema) {
3178
4176
  return schema;
3179
4177
  }
3180
- var BackgroundProcessSchema = import_zod3.z.object({
3181
- command: import_zod3.z.string().describe("The shell command to start in the background"),
3182
- timeout: import_zod3.z.number().optional().describe("Optional timeout in milliseconds. Default is 120000."),
3183
- workingDirectory: import_zod3.z.string().optional().describe("Working directory for the command. Defaults to the current project directory."),
3184
- stdin: import_zod3.z.string().optional().describe("Optional stdin to write after the process starts."),
3185
- outputLimitBytes: import_zod3.z.number().optional().describe("Maximum captured output bytes kept in the task result.")
4178
+ var BackgroundProcessSchema = import_zod4.z.object({
4179
+ command: import_zod4.z.string().describe("The shell command to start in the background"),
4180
+ timeout: import_zod4.z.number().optional().describe("Optional timeout in milliseconds. Default is 120000."),
4181
+ workingDirectory: import_zod4.z.string().optional().describe("Working directory for the command. Defaults to the current project directory."),
4182
+ stdin: import_zod4.z.string().optional().describe("Optional stdin to write after the process starts."),
4183
+ outputLimitBytes: import_zod4.z.number().optional().describe("Maximum captured output bytes kept in the task result.")
3186
4184
  });
3187
4185
  function stringifyStarted(taskId, status, command) {
3188
4186
  return JSON.stringify({
@@ -3222,59 +4220,11 @@ async function startBackgroundProcess(args, deps) {
3222
4220
  }
3223
4221
  }
3224
4222
  function createBackgroundProcessTool(deps) {
3225
- return (0, import_agent_tools3.createZodFunctionTool)(
3226
- "BackgroundProcess",
3227
- "Start a shell command as a managed background task. Use this for long-running commands that should not block the current conversation. Use /background list, /background read <taskId>, /background cancel <taskId>, or /background close <taskId> to inspect or control it.",
3228
- asZodSchema2(BackgroundProcessSchema),
3229
- async (params) => startBackgroundProcess(params, deps)
3230
- );
3231
- }
3232
-
3233
- // src/tools/command-execution-tool.ts
3234
- var import_zod4 = require("zod");
3235
- var import_agent_tools4 = require("@robota-sdk/agent-tools");
3236
- var CommandExecutionSchema = import_zod4.z.object({
3237
- command: import_zod4.z.string().describe("Command name to execute, with or without a leading slash"),
3238
- args: import_zod4.z.string().optional().describe("Arguments to pass to the command")
3239
- });
3240
- function asZodSchema3(schema) {
3241
- return schema;
3242
- }
3243
- function normalizeCommand(command) {
3244
- return command.trim().replace(/^\/+/, "").split(/\s+/)[0] ?? "";
3245
- }
3246
- function stringifyCommandResult(command, result) {
3247
- if (!result) {
3248
- return JSON.stringify({
3249
- success: false,
3250
- command,
3251
- error: `Unknown command: ${command}`
3252
- });
3253
- }
3254
- return JSON.stringify({
3255
- success: result.success,
3256
- command,
3257
- message: result.message,
3258
- data: result.data
3259
- });
3260
- }
3261
- function createCommandExecutionTool(deps) {
3262
4223
  return (0, import_agent_tools4.createZodFunctionTool)(
3263
- "ExecuteCommand",
3264
- "Executes a registered model-invocable Robota command through the command registry. Accepted command names and argument grammar come from registered command descriptors.",
3265
- asZodSchema3(CommandExecutionSchema),
3266
- async (params) => {
3267
- const args = CommandExecutionSchema.parse(params);
3268
- const command = normalizeCommand(args.command);
3269
- if (!deps.isModelInvocable(command)) {
3270
- return JSON.stringify({
3271
- success: false,
3272
- command,
3273
- error: `Command is not model-invocable: ${command}`
3274
- });
3275
- }
3276
- return stringifyCommandResult(command, await deps.execute(command, args.args ?? ""));
3277
- }
4224
+ "BackgroundProcess",
4225
+ "Start a shell command as a managed background task. Use this for long-running commands that should not block the current conversation. Use /background list, /background read <taskId>, /background cancel <taskId>, or /background close <taskId> to inspect or control it.",
4226
+ asZodSchema3(BackgroundProcessSchema),
4227
+ async (params) => startBackgroundProcess(params, deps)
3278
4228
  );
3279
4229
  }
3280
4230
 
@@ -3338,6 +4288,9 @@ function evaluateReversibleToolSafety(input) {
3338
4288
  };
3339
4289
  }
3340
4290
  if (FILE_MUTATION_TOOLS.has(toolName)) {
4291
+ if (input.context.isolation === "worktree" || input.context.isolation === "provider-sandbox") {
4292
+ return evaluateIsolatedSideEffect(toolName, "file-mutation", input.context);
4293
+ }
3341
4294
  if (input.context.checkpointAvailable) {
3342
4295
  return {
3343
4296
  toolName,
@@ -3520,8 +4473,8 @@ var import_agent_runtime6 = require("@robota-sdk/agent-runtime");
3520
4473
 
3521
4474
  // src/agents/agent-definition-loader.ts
3522
4475
  var import_node_fs4 = require("fs");
3523
- var import_node_path3 = require("path");
3524
- var import_node_os2 = require("os");
4476
+ var import_node_path7 = require("path");
4477
+ var import_node_os4 = require("os");
3525
4478
  var LIST_KEYS2 = /* @__PURE__ */ new Set(["tools", "disallowedTools"]);
3526
4479
  var NUMBER_KEYS = /* @__PURE__ */ new Set(["maxTurns"]);
3527
4480
  function parseListValue2(rawValue) {
@@ -3575,10 +4528,10 @@ function scanAgentsDir(dir) {
3575
4528
  }
3576
4529
  for (const entry of entries) {
3577
4530
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
3578
- const filePath = (0, import_node_path3.join)(dir, entry.name);
4531
+ const filePath = (0, import_node_path7.join)(dir, entry.name);
3579
4532
  const content = (0, import_node_fs4.readFileSync)(filePath, "utf-8");
3580
4533
  const { frontmatter, body } = parseFrontmatter2(content);
3581
- const fallbackName = (0, import_node_path3.basename)(entry.name, ".md");
4534
+ const fallbackName = (0, import_node_path7.basename)(entry.name, ".md");
3582
4535
  const agent = {
3583
4536
  name: frontmatter?.name ?? fallbackName,
3584
4537
  description: frontmatter?.description ?? "",
@@ -3598,16 +4551,16 @@ var AgentDefinitionLoader = class {
3598
4551
  home;
3599
4552
  constructor(cwd, home) {
3600
4553
  this.cwd = cwd;
3601
- this.home = home ?? (0, import_node_os2.homedir)();
4554
+ this.home = home ?? (0, import_node_os4.homedir)();
3602
4555
  }
3603
4556
  /** Load all agent definitions, merged with built-in agents. Custom overrides built-in on name collision. */
3604
4557
  loadAll() {
3605
4558
  const sources = [
3606
- scanAgentsDir((0, import_node_path3.join)(this.cwd, ".robota", "agents")),
3607
- scanAgentsDir((0, import_node_path3.join)(this.cwd, ".agents", "agents")),
3608
- scanAgentsDir((0, import_node_path3.join)(this.cwd, ".claude", "agents")),
3609
- scanAgentsDir((0, import_node_path3.join)(this.home, ".robota", "agents")),
3610
- scanAgentsDir((0, import_node_path3.join)(this.home, ".claude", "agents"))
4559
+ scanAgentsDir((0, import_node_path7.join)(this.cwd, ".robota", "agents")),
4560
+ scanAgentsDir((0, import_node_path7.join)(this.cwd, ".agents", "agents")),
4561
+ scanAgentsDir((0, import_node_path7.join)(this.cwd, ".claude", "agents")),
4562
+ scanAgentsDir((0, import_node_path7.join)(this.home, ".robota", "agents")),
4563
+ scanAgentsDir((0, import_node_path7.join)(this.home, ".claude", "agents"))
3611
4564
  ];
3612
4565
  const seen = /* @__PURE__ */ new Set();
3613
4566
  const customAgents = [];
@@ -3676,6 +4629,17 @@ function fireSubagentLifecycleHook(event, cwd, hooks, hookTypeExecutors) {
3676
4629
  var ID_RADIX = 36;
3677
4630
  var ID_RANDOM_LENGTH = 9;
3678
4631
  var DEFAULT_PROVIDER_IDLE_TIMEOUT_MS = 12e4;
4632
+ function getModelInvocableCommandDescriptors(descriptors) {
4633
+ return (descriptors ?? []).filter(
4634
+ (descriptor) => descriptor.modelInvocable && descriptor.kind === "builtin-command"
4635
+ );
4636
+ }
4637
+ function normalizeCommandDescriptorName(name) {
4638
+ return name.trim().replace(/^\/+/, "").split(/\s+/)[0] ?? "";
4639
+ }
4640
+ function hasModelInvocableCommandDescriptor(descriptors, name) {
4641
+ return descriptors.some((descriptor) => normalizeCommandDescriptorName(descriptor.name) === name);
4642
+ }
3679
4643
  function createSession(options) {
3680
4644
  if (!options.provider) {
3681
4645
  throw new Error(
@@ -3685,17 +4649,34 @@ function createSession(options) {
3685
4649
  const provider = options.provider;
3686
4650
  const cwd = options.cwd ?? process.cwd();
3687
4651
  const sessionId = options.sessionId ?? createSessionId();
3688
- const defaultTools = options.editCheckpointRecorder ? wrapEditCheckpointTools(createDefaultTools(), options.editCheckpointRecorder) : createDefaultTools();
4652
+ const skillCommandSource = new SkillCommandSource(cwd);
4653
+ const modelInvocableCommandDescriptors = getModelInvocableCommandDescriptors(
4654
+ options.commandDescriptors
4655
+ );
4656
+ const modelCommandToolsEnabled = modelInvocableCommandDescriptors.length > 0 && options.modelCommandExecutor !== void 0 && options.isModelCommandInvocable !== void 0;
4657
+ const modelCommandToolProjection = modelCommandToolsEnabled ? createModelCommandToolProjection(modelInvocableCommandDescriptors) : void 0;
4658
+ const modelVisibleSkills = hasModelInvocableCommandDescriptor(
4659
+ modelInvocableCommandDescriptors,
4660
+ "skills"
4661
+ ) ? skillCommandSource.getModelInvocableSkills() : [];
4662
+ const baseDefaultTools = createDefaultTools({ sandboxClient: options.sandboxClient });
4663
+ const shouldWrapHostEditCheckpoints = options.editCheckpointRecorder !== void 0 && options.sandboxClient === void 0;
4664
+ const defaultTools = shouldWrapHostEditCheckpoints && options.editCheckpointRecorder ? wrapEditCheckpointTools(baseDefaultTools, options.editCheckpointRecorder) : baseDefaultTools;
3689
4665
  const assembledTools = [...defaultTools, ...options.additionalTools ?? []];
3690
- const tools = options.reversibleExecution ? wrapReversibleExecutionTools(assembledTools, {
4666
+ const reversibleExecution = options.reversibleExecution ? {
3691
4667
  ...options.reversibleExecution,
3692
- checkpointAvailable: options.editCheckpointRecorder !== void 0
4668
+ isolation: options.reversibleExecution.isolation ?? (options.sandboxClient ? "provider-sandbox" : void 0)
4669
+ } : void 0;
4670
+ const tools = reversibleExecution ? wrapReversibleExecutionTools(assembledTools, {
4671
+ ...reversibleExecution,
4672
+ checkpointAvailable: shouldWrapHostEditCheckpoints
3693
4673
  }) : assembledTools;
3694
- if (options.modelCommandExecutor && options.isModelCommandInvocable) {
4674
+ if (modelCommandToolsEnabled && options.modelCommandExecutor !== void 0 && options.isModelCommandInvocable !== void 0) {
3695
4675
  tools.push(
3696
- createCommandExecutionTool({
4676
+ ...createProjectedCommandExecutionTools({
3697
4677
  execute: options.modelCommandExecutor,
3698
- isModelInvocable: options.isModelCommandInvocable
4678
+ isModelInvocable: options.isModelCommandInvocable,
4679
+ commandDescriptors: modelInvocableCommandDescriptors
3699
4680
  })
3700
4681
  );
3701
4682
  }
@@ -3778,14 +4759,12 @@ function createSession(options) {
3778
4759
  };
3779
4760
  tools.push(createBackgroundProcessTool(backgroundProcessToolDeps));
3780
4761
  }
3781
- if (agentToolDeps) {
3782
- tools.push(createAgentTool(agentToolDeps));
3783
- }
3784
4762
  const buildPrompt = options.systemPromptBuilder ?? buildSystemPrompt;
3785
4763
  const defaultToolDescriptions = [
3786
4764
  ...DEFAULT_TOOL_DESCRIPTIONS,
3787
- ...agentToolDeps ? [createAgentToolPromptDescription(agentDefinitions)] : [],
3788
- ...options.modelCommandExecutor ? ["ExecuteCommand \u2014 execute model-invocable Robota commands"] : []
4765
+ ...modelCommandToolProjection ? modelCommandToolProjection.commandTools.map(
4766
+ formatProjectedModelCommandToolPromptDescription
4767
+ ) : []
3789
4768
  ];
3790
4769
  const systemMessage = buildPrompt({
3791
4770
  agentsMd: options.context.agentsMd,
@@ -3800,7 +4779,7 @@ function createSession(options) {
3800
4779
  projectInfo: options.projectInfo ?? { type: "unknown", language: "unknown" },
3801
4780
  cwd,
3802
4781
  language: options.config.language,
3803
- skills: new SkillCommandSource(cwd).getModelInvocableSkills().map((skill) => ({
4782
+ skills: modelVisibleSkills.map((skill) => ({
3804
4783
  name: skill.name,
3805
4784
  description: skill.description,
3806
4785
  disableModelInvocation: skill.disableModelInvocation
@@ -3829,7 +4808,7 @@ ${options.appendSystemPrompt}` : systemMessage;
3829
4808
  allow: [...defaultAllow, ...options.config.permissions.allow ?? [], ...allowedToolPatterns],
3830
4809
  deny: options.config.permissions.deny ?? []
3831
4810
  };
3832
- const SessionWithAutoCompact = import_agent_sessions3.Session;
4811
+ const SessionWithAutoCompact = import_agent_sessions4.Session;
3833
4812
  const session = new SessionWithAutoCompact({
3834
4813
  tools,
3835
4814
  provider,
@@ -3874,41 +4853,19 @@ function logBackgroundTaskEvent(logger, sessionId, event) {
3874
4853
 
3875
4854
  // src/assembly/subagent-logger.ts
3876
4855
  var import_node_fs5 = require("fs");
3877
- var import_node_path4 = require("path");
3878
- var import_agent_sessions4 = require("@robota-sdk/agent-sessions");
4856
+ var import_node_path8 = require("path");
4857
+ var import_agent_sessions5 = require("@robota-sdk/agent-sessions");
3879
4858
  function createSubagentLogger(parentSessionId, _agentId, baseLogsDir) {
3880
- const subagentDir = (0, import_node_path4.join)(baseLogsDir, parentSessionId, "subagents");
4859
+ const subagentDir = (0, import_node_path8.join)(baseLogsDir, parentSessionId, "subagents");
3881
4860
  (0, import_node_fs5.mkdirSync)(subagentDir, { recursive: true });
3882
- return new import_agent_sessions4.FileSessionLogger(subagentDir);
4861
+ return new import_agent_sessions5.FileSessionLogger(subagentDir);
3883
4862
  }
3884
4863
  function resolveSubagentLogDir(parentSessionId, baseLogsDir) {
3885
- return (0, import_node_path4.join)(baseLogsDir, parentSessionId, "subagents");
4864
+ return (0, import_node_path8.join)(baseLogsDir, parentSessionId, "subagents");
3886
4865
  }
3887
4866
 
3888
4867
  // src/interactive/interactive-session-init.ts
3889
- var import_agent_sessions5 = require("@robota-sdk/agent-sessions");
3890
-
3891
- // src/paths.ts
3892
- var import_node_path5 = require("path");
3893
- var import_node_os3 = require("os");
3894
- function projectPaths(cwd) {
3895
- const base = (0, import_node_path5.join)(cwd, ".robota");
3896
- return {
3897
- settings: (0, import_node_path5.join)(base, "settings.json"),
3898
- settingsLocal: (0, import_node_path5.join)(base, "settings.local.json"),
3899
- logs: (0, import_node_path5.join)(base, "logs"),
3900
- sessions: (0, import_node_path5.join)(base, "sessions"),
3901
- memory: (0, import_node_path5.join)(base, "memory"),
3902
- checkpoints: (0, import_node_path5.join)(base, "checkpoints")
3903
- };
3904
- }
3905
- function userPaths() {
3906
- const base = (0, import_node_path5.join)((0, import_node_os3.homedir)(), ".robota");
3907
- return {
3908
- settings: (0, import_node_path5.join)(base, "settings.json"),
3909
- sessions: (0, import_node_path5.join)(base, "sessions")
3910
- };
3911
- }
4868
+ var import_agent_sessions6 = require("@robota-sdk/agent-sessions");
3912
4869
 
3913
4870
  // src/context/context-loader.ts
3914
4871
  var import_fs3 = require("fs");
@@ -3916,8 +4873,8 @@ var import_path3 = require("path");
3916
4873
 
3917
4874
  // src/context/task-context.ts
3918
4875
  var import_node_fs6 = require("fs");
3919
- var import_node_path6 = require("path");
3920
- var TASKS_DIR = (0, import_node_path6.join)(".agents", "tasks");
4876
+ var import_node_path9 = require("path");
4877
+ var TASKS_DIR = (0, import_node_path9.join)(".agents", "tasks");
3921
4878
  var README_FILENAME = "README.md";
3922
4879
  var MARKDOWN_EXTENSION = ".md";
3923
4880
  var DEFAULT_MAX_TASKS = Number("3");
@@ -3937,7 +4894,7 @@ function normalizeStatus(value) {
3937
4894
  }
3938
4895
  function extractTitle(content, taskPath) {
3939
4896
  const heading = content.split(/\r?\n/).find((line) => /^#\s+/.test(line));
3940
- return heading?.replace(/^#\s+/, "").trim() || (0, import_node_path6.basename)(taskPath, MARKDOWN_EXTENSION);
4897
+ return heading?.replace(/^#\s+/, "").trim() || (0, import_node_path9.basename)(taskPath, MARKDOWN_EXTENSION);
3941
4898
  }
3942
4899
  function extractMetadata(content, key) {
3943
4900
  const matcher = new RegExp(`^- \\*\\*${key}\\*\\*:\\s*(.+)$`, "im");
@@ -4017,18 +4974,18 @@ function appendProgressEntry(content, now, progressMessage) {
4017
4974
  return lines.join("\n");
4018
4975
  }
4019
4976
  function resolveGitDirectory(cwd) {
4020
- let current = (0, import_node_path6.resolve)(cwd);
4977
+ let current = (0, import_node_path9.resolve)(cwd);
4021
4978
  let reachedRoot = false;
4022
4979
  while (!reachedRoot) {
4023
- const gitPath = (0, import_node_path6.join)(current, ".git");
4980
+ const gitPath = (0, import_node_path9.join)(current, ".git");
4024
4981
  if ((0, import_node_fs6.existsSync)(gitPath)) {
4025
4982
  const stats = (0, import_node_fs6.statSync)(gitPath);
4026
4983
  if (stats.isDirectory()) return gitPath;
4027
4984
  const content = (0, import_node_fs6.readFileSync)(gitPath, "utf8").trim();
4028
4985
  const gitdir = content.match(/^gitdir:\s*(.+)$/)?.[1];
4029
- if (gitdir) return (0, import_node_path6.isAbsolute)(gitdir) ? gitdir : (0, import_node_path6.resolve)(current, gitdir);
4986
+ if (gitdir) return (0, import_node_path9.isAbsolute)(gitdir) ? gitdir : (0, import_node_path9.resolve)(current, gitdir);
4030
4987
  }
4031
- const parent = (0, import_node_path6.dirname)(current);
4988
+ const parent = (0, import_node_path9.dirname)(current);
4032
4989
  reachedRoot = parent === current;
4033
4990
  current = parent;
4034
4991
  }
@@ -4037,24 +4994,24 @@ function resolveGitDirectory(cwd) {
4037
4994
  function readCurrentGitBranch(cwd) {
4038
4995
  const gitDir = resolveGitDirectory(cwd);
4039
4996
  if (!gitDir) return void 0;
4040
- const headPath = (0, import_node_path6.join)(gitDir, "HEAD");
4997
+ const headPath = (0, import_node_path9.join)(gitDir, "HEAD");
4041
4998
  if (!(0, import_node_fs6.existsSync)(headPath)) return void 0;
4042
4999
  const head = (0, import_node_fs6.readFileSync)(headPath, "utf8").trim();
4043
5000
  const branch = head.match(/^ref:\s+refs\/heads\/(.+)$/)?.[1];
4044
5001
  return branch?.trim();
4045
5002
  }
4046
5003
  function discoverTaskFiles(cwd) {
4047
- const tasksDir = (0, import_node_path6.join)(cwd, TASKS_DIR);
5004
+ const tasksDir = (0, import_node_path9.join)(cwd, TASKS_DIR);
4048
5005
  if (!(0, import_node_fs6.existsSync)(tasksDir)) {
4049
5006
  return [];
4050
5007
  }
4051
- return (0, import_node_fs6.readdirSync)(tasksDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).filter((name) => name !== README_FILENAME && name.endsWith(MARKDOWN_EXTENSION)).sort((a, b) => a.localeCompare(b)).map((name) => (0, import_node_path6.join)(tasksDir, name));
5008
+ return (0, import_node_fs6.readdirSync)(tasksDir, { withFileTypes: true }).filter((entry) => entry.isFile()).map((entry) => entry.name).filter((name) => name !== README_FILENAME && name.endsWith(MARKDOWN_EXTENSION)).sort((a, b) => a.localeCompare(b)).map((name) => (0, import_node_path9.join)(tasksDir, name));
4052
5009
  }
4053
5010
  function parseTaskFile(taskPath, cwd) {
4054
5011
  const content = (0, import_node_fs6.readFileSync)(taskPath, "utf8");
4055
5012
  return {
4056
5013
  path: taskPath,
4057
- relativePath: (0, import_node_path6.relative)(cwd, taskPath),
5014
+ relativePath: (0, import_node_path9.relative)(cwd, taskPath),
4058
5015
  title: extractTitle(content, taskPath),
4059
5016
  status: normalizeStatus(extractMetadata(content, "Status")),
4060
5017
  branch: extractMetadata(content, "Branch"),
@@ -4209,7 +5166,7 @@ async function detectProject(cwd) {
4209
5166
 
4210
5167
  // src/plugins/plugin-settings-store.ts
4211
5168
  var import_node_fs7 = require("fs");
4212
- var import_node_path7 = require("path");
5169
+ var import_node_path10 = require("path");
4213
5170
  var PluginSettingsStore = class {
4214
5171
  settingsPath;
4215
5172
  constructor(settingsPath) {
@@ -4233,7 +5190,7 @@ var PluginSettingsStore = class {
4233
5190
  }
4234
5191
  /** Write the full settings file to disk. */
4235
5192
  writeAll(settings) {
4236
- const dir = (0, import_node_path7.dirname)(this.settingsPath);
5193
+ const dir = (0, import_node_path10.dirname)(this.settingsPath);
4237
5194
  if (!(0, import_node_fs7.existsSync)(dir)) {
4238
5195
  (0, import_node_fs7.mkdirSync)(dir, { recursive: true });
4239
5196
  }
@@ -4310,7 +5267,7 @@ var PluginSettingsStore = class {
4310
5267
 
4311
5268
  // src/plugins/bundle-plugin-loader.ts
4312
5269
  var import_node_fs9 = require("fs");
4313
- var import_node_path8 = require("path");
5270
+ var import_node_path11 = require("path");
4314
5271
 
4315
5272
  // src/plugins/bundle-plugin-utils.ts
4316
5273
  var import_node_fs8 = require("fs");
@@ -4394,22 +5351,22 @@ var BundlePluginLoader = class {
4394
5351
  * For each marketplace/plugin pair, the latest version (lexicographically last) is loaded.
4395
5352
  */
4396
5353
  discoverAndLoad() {
4397
- const cacheDir = (0, import_node_path8.join)(this.pluginsDir, "cache");
5354
+ const cacheDir = (0, import_node_path11.join)(this.pluginsDir, "cache");
4398
5355
  if (!(0, import_node_fs9.existsSync)(cacheDir)) {
4399
5356
  return [];
4400
5357
  }
4401
5358
  const results = [];
4402
5359
  const marketplaces = getSortedSubdirs(cacheDir);
4403
5360
  for (const marketplace of marketplaces) {
4404
- const marketplaceDir = (0, import_node_path8.join)(cacheDir, marketplace);
5361
+ const marketplaceDir = (0, import_node_path11.join)(cacheDir, marketplace);
4405
5362
  const plugins = getSortedSubdirs(marketplaceDir);
4406
5363
  for (const pluginName of plugins) {
4407
- const pluginDir = (0, import_node_path8.join)(marketplaceDir, pluginName);
5364
+ const pluginDir = (0, import_node_path11.join)(marketplaceDir, pluginName);
4408
5365
  const versions = getSortedSubdirs(pluginDir);
4409
5366
  if (versions.length === 0) continue;
4410
5367
  const latestVersion = versions[versions.length - 1];
4411
- const versionDir = (0, import_node_path8.join)(pluginDir, latestVersion);
4412
- const manifestPath = (0, import_node_path8.join)(versionDir, ".claude-plugin", "plugin.json");
5368
+ const versionDir = (0, import_node_path11.join)(pluginDir, latestVersion);
5369
+ const manifestPath = (0, import_node_path11.join)(versionDir, ".claude-plugin", "plugin.json");
4413
5370
  if (!(0, import_node_fs9.existsSync)(manifestPath)) continue;
4414
5371
  const manifest = this.readManifest(manifestPath);
4415
5372
  if (!manifest) continue;
@@ -4459,13 +5416,13 @@ var BundlePluginLoader = class {
4459
5416
  }
4460
5417
  /** Load skills from the plugin's skills/ directory. */
4461
5418
  loadSkills(pluginDir, pluginName) {
4462
- const skillsDir = (0, import_node_path8.join)(pluginDir, "skills");
5419
+ const skillsDir = (0, import_node_path11.join)(pluginDir, "skills");
4463
5420
  if (!(0, import_node_fs9.existsSync)(skillsDir)) return [];
4464
5421
  const entries = (0, import_node_fs9.readdirSync)(skillsDir, { withFileTypes: true });
4465
5422
  const skills = [];
4466
5423
  for (const entry of entries) {
4467
5424
  if (!entry.isDirectory()) continue;
4468
- const skillFile = (0, import_node_path8.join)(skillsDir, entry.name, "SKILL.md");
5425
+ const skillFile = (0, import_node_path11.join)(skillsDir, entry.name, "SKILL.md");
4469
5426
  if (!(0, import_node_fs9.existsSync)(skillFile)) continue;
4470
5427
  const raw = (0, import_node_fs9.readFileSync)(skillFile, "utf-8");
4471
5428
  const { metadata, content } = parseSkillFrontmatter(raw);
@@ -4482,13 +5439,13 @@ var BundlePluginLoader = class {
4482
5439
  }
4483
5440
  /** Load commands from the plugin's commands/ directory (flat .md files). */
4484
5441
  loadCommands(pluginDir, pluginName) {
4485
- const commandsDir = (0, import_node_path8.join)(pluginDir, "commands");
5442
+ const commandsDir = (0, import_node_path11.join)(pluginDir, "commands");
4486
5443
  if (!(0, import_node_fs9.existsSync)(commandsDir)) return [];
4487
5444
  const entries = (0, import_node_fs9.readdirSync)(commandsDir, { withFileTypes: true });
4488
5445
  const commands = [];
4489
5446
  for (const entry of entries) {
4490
5447
  if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
4491
- const raw = (0, import_node_fs9.readFileSync)((0, import_node_path8.join)(commandsDir, entry.name), "utf-8");
5448
+ const raw = (0, import_node_fs9.readFileSync)((0, import_node_path11.join)(commandsDir, entry.name), "utf-8");
4492
5449
  const { metadata, content } = parseSkillFrontmatter(raw);
4493
5450
  const name = typeof metadata.name === "string" ? metadata.name : entry.name.replace(/\.md$/, "");
4494
5451
  const description = typeof metadata.description === "string" ? metadata.description : "";
@@ -4503,7 +5460,7 @@ var BundlePluginLoader = class {
4503
5460
  }
4504
5461
  /** Load hooks from hooks/hooks.json if present. */
4505
5462
  loadHooks(pluginDir) {
4506
- const hooksPath = (0, import_node_path8.join)(pluginDir, "hooks", "hooks.json");
5463
+ const hooksPath = (0, import_node_path11.join)(pluginDir, "hooks", "hooks.json");
4507
5464
  if (!(0, import_node_fs9.existsSync)(hooksPath)) return {};
4508
5465
  try {
4509
5466
  const raw = (0, import_node_fs9.readFileSync)(hooksPath, "utf-8");
@@ -4518,8 +5475,8 @@ var BundlePluginLoader = class {
4518
5475
  }
4519
5476
  /** Load MCP server configuration if present. Checks `.mcp.json` at plugin root first. */
4520
5477
  loadMcpConfig(pluginDir) {
4521
- const primaryPath = (0, import_node_path8.join)(pluginDir, ".mcp.json");
4522
- const fallbackPath = (0, import_node_path8.join)(pluginDir, ".claude-plugin", "mcp.json");
5478
+ const primaryPath = (0, import_node_path11.join)(pluginDir, ".mcp.json");
5479
+ const fallbackPath = (0, import_node_path11.join)(pluginDir, ".claude-plugin", "mcp.json");
4523
5480
  const mcpPath = (0, import_node_fs9.existsSync)(primaryPath) ? primaryPath : fallbackPath;
4524
5481
  if (!(0, import_node_fs9.existsSync)(mcpPath)) return void 0;
4525
5482
  try {
@@ -4531,7 +5488,7 @@ var BundlePluginLoader = class {
4531
5488
  }
4532
5489
  /** Load agent definitions from agents/ directory if present. */
4533
5490
  loadAgents(pluginDir) {
4534
- const agentsDir = (0, import_node_path8.join)(pluginDir, "agents");
5491
+ const agentsDir = (0, import_node_path11.join)(pluginDir, "agents");
4535
5492
  if (!(0, import_node_fs9.existsSync)(agentsDir)) return [];
4536
5493
  try {
4537
5494
  const entries = (0, import_node_fs9.readdirSync)(agentsDir, { withFileTypes: true });
@@ -4545,7 +5502,7 @@ var BundlePluginLoader = class {
4545
5502
  // src/plugins/bundle-plugin-installer.ts
4546
5503
  var import_node_child_process2 = require("child_process");
4547
5504
  var import_node_fs10 = require("fs");
4548
- var import_node_path9 = require("path");
5505
+ var import_node_path12 = require("path");
4549
5506
  var GIT_CLONE_TIMEOUT_MS = 6e4;
4550
5507
  var BundlePluginInstaller = class {
4551
5508
  pluginsDir;
@@ -4556,8 +5513,8 @@ var BundlePluginInstaller = class {
4556
5513
  exec;
4557
5514
  constructor(options) {
4558
5515
  this.pluginsDir = options.pluginsDir;
4559
- this.cacheDir = (0, import_node_path9.join)(this.pluginsDir, "cache");
4560
- this.registryPath = (0, import_node_path9.join)(this.pluginsDir, "installed_plugins.json");
5516
+ this.cacheDir = (0, import_node_path12.join)(this.pluginsDir, "cache");
5517
+ this.registryPath = (0, import_node_path12.join)(this.pluginsDir, "installed_plugins.json");
4561
5518
  this.settingsStore = options.settingsStore;
4562
5519
  this.marketplaceClient = options.marketplaceClient;
4563
5520
  this.exec = options.exec ?? this.defaultExec;
@@ -4577,7 +5534,7 @@ var BundlePluginInstaller = class {
4577
5534
  throw new Error(`Plugin "${pluginName}" not found in marketplace "${marketplaceName}"`);
4578
5535
  }
4579
5536
  const version = this.resolveVersion(entry, marketplaceName);
4580
- const targetDir = (0, import_node_path9.join)(this.cacheDir, marketplaceName, pluginName, version);
5537
+ const targetDir = (0, import_node_path12.join)(this.cacheDir, marketplaceName, pluginName, version);
4581
5538
  if ((0, import_node_fs10.existsSync)(targetDir)) {
4582
5539
  throw new Error(
4583
5540
  `Plugin "${pluginName}" version "${version}" is already installed from "${marketplaceName}"`
@@ -4657,7 +5614,7 @@ var BundlePluginInstaller = class {
4657
5614
  try {
4658
5615
  if (typeof source === "string") {
4659
5616
  const marketplaceDir = this.marketplaceClient.getMarketplaceDir(marketplaceName);
4660
- const sourcePath = (0, import_node_path9.join)(marketplaceDir, source);
5617
+ const sourcePath = (0, import_node_path12.join)(marketplaceDir, source);
4661
5618
  if (!(0, import_node_fs10.existsSync)(sourcePath)) {
4662
5619
  throw new Error(
4663
5620
  `Plugin source path "${source}" not found in marketplace "${marketplaceName}"`
@@ -4710,7 +5667,7 @@ var BundlePluginInstaller = class {
4710
5667
  }
4711
5668
  /** Write the installed_plugins.json registry. */
4712
5669
  writeRegistry(registry) {
4713
- const dir = (0, import_node_path9.dirname)(this.registryPath);
5670
+ const dir = (0, import_node_path12.dirname)(this.registryPath);
4714
5671
  if (!(0, import_node_fs10.existsSync)(dir)) {
4715
5672
  (0, import_node_fs10.mkdirSync)(dir, { recursive: true });
4716
5673
  }
@@ -4725,11 +5682,11 @@ var BundlePluginInstaller = class {
4725
5682
  // src/plugins/marketplace-client.ts
4726
5683
  var import_node_child_process3 = require("child_process");
4727
5684
  var import_node_fs12 = require("fs");
4728
- var import_node_path11 = require("path");
5685
+ var import_node_path14 = require("path");
4729
5686
 
4730
5687
  // src/plugins/marketplace-registry.ts
4731
5688
  var import_node_fs11 = require("fs");
4732
- var import_node_path10 = require("path");
5689
+ var import_node_path13 = require("path");
4733
5690
  function readRegistry(registryPath) {
4734
5691
  if (!(0, import_node_fs11.existsSync)(registryPath)) {
4735
5692
  return {};
@@ -4746,14 +5703,14 @@ function readRegistry(registryPath) {
4746
5703
  }
4747
5704
  }
4748
5705
  function writeRegistry(registryPath, registry) {
4749
- const dir = (0, import_node_path10.dirname)(registryPath);
5706
+ const dir = (0, import_node_path13.dirname)(registryPath);
4750
5707
  if (!(0, import_node_fs11.existsSync)(dir)) {
4751
5708
  (0, import_node_fs11.mkdirSync)(dir, { recursive: true });
4752
5709
  }
4753
5710
  (0, import_node_fs11.writeFileSync)(registryPath, JSON.stringify(registry, null, 2), "utf-8");
4754
5711
  }
4755
5712
  function removeInstalledPluginsForMarketplace(pluginsDir, marketplaceName) {
4756
- const installedPath = (0, import_node_path10.join)(pluginsDir, "installed_plugins.json");
5713
+ const installedPath = (0, import_node_path13.join)(pluginsDir, "installed_plugins.json");
4757
5714
  if (!(0, import_node_fs11.existsSync)(installedPath)) return;
4758
5715
  let registry;
4759
5716
  try {
@@ -4775,7 +5732,7 @@ function removeInstalledPluginsForMarketplace(pluginsDir, marketplaceName) {
4775
5732
  }
4776
5733
  }
4777
5734
  if (changed) {
4778
- const dir = (0, import_node_path10.dirname)(installedPath);
5735
+ const dir = (0, import_node_path13.dirname)(installedPath);
4779
5736
  if (!(0, import_node_fs11.existsSync)(dir)) {
4780
5737
  (0, import_node_fs11.mkdirSync)(dir, { recursive: true });
4781
5738
  }
@@ -4793,8 +5750,8 @@ var MarketplaceClient = class {
4793
5750
  constructor(options) {
4794
5751
  this.pluginsDir = options.pluginsDir;
4795
5752
  this.exec = options.exec ?? this.defaultExec;
4796
- this.marketplacesDir = (0, import_node_path11.join)(this.pluginsDir, "marketplaces");
4797
- this.registryPath = (0, import_node_path11.join)(this.pluginsDir, "known_marketplaces.json");
5753
+ this.marketplacesDir = (0, import_node_path14.join)(this.pluginsDir, "marketplaces");
5754
+ this.registryPath = (0, import_node_path14.join)(this.pluginsDir, "known_marketplaces.json");
4798
5755
  }
4799
5756
  /**
4800
5757
  * Add a marketplace by cloning its repository.
@@ -4807,7 +5764,7 @@ var MarketplaceClient = class {
4807
5764
  */
4808
5765
  addMarketplace(source) {
4809
5766
  const tempName = "temp-" + Date.now().toString(36);
4810
- const tempDir = (0, import_node_path11.join)(this.marketplacesDir, tempName);
5767
+ const tempDir = (0, import_node_path14.join)(this.marketplacesDir, tempName);
4811
5768
  (0, import_node_fs12.mkdirSync)(this.marketplacesDir, { recursive: true });
4812
5769
  if (source.type === "local") {
4813
5770
  if (!(0, import_node_fs12.existsSync)(source.path)) {
@@ -4824,7 +5781,7 @@ var MarketplaceClient = class {
4824
5781
  throw new Error(`Failed to clone marketplace: ${message}`);
4825
5782
  }
4826
5783
  }
4827
- const manifestPath = (0, import_node_path11.join)(tempDir, ".claude-plugin", "marketplace.json");
5784
+ const manifestPath = (0, import_node_path14.join)(tempDir, ".claude-plugin", "marketplace.json");
4828
5785
  if (!(0, import_node_fs12.existsSync)(manifestPath)) {
4829
5786
  (0, import_node_fs12.rmSync)(tempDir, { recursive: true, force: true });
4830
5787
  throw new Error(
@@ -4842,7 +5799,7 @@ var MarketplaceClient = class {
4842
5799
  (0, import_node_fs12.rmSync)(tempDir, { recursive: true, force: true });
4843
5800
  throw new Error(`Marketplace "${name}" already exists`);
4844
5801
  }
4845
- const finalDir = (0, import_node_path11.join)(this.marketplacesDir, name);
5802
+ const finalDir = (0, import_node_path14.join)(this.marketplacesDir, name);
4846
5803
  (0, import_node_fs12.renameSync)(tempDir, finalDir);
4847
5804
  registry[name] = {
4848
5805
  source,
@@ -4919,7 +5876,7 @@ var MarketplaceClient = class {
4919
5876
  if (!entry) {
4920
5877
  throw new Error(`Marketplace "${marketplaceName}" not found`);
4921
5878
  }
4922
- const manifestPath = (0, import_node_path11.join)(entry.installLocation, ".claude-plugin", "marketplace.json");
5879
+ const manifestPath = (0, import_node_path14.join)(entry.installLocation, ".claude-plugin", "marketplace.json");
4923
5880
  if (!(0, import_node_fs12.existsSync)(manifestPath)) {
4924
5881
  throw new Error(
4925
5882
  `Marketplace "${marketplaceName}" does not contain .claude-plugin/marketplace.json`
@@ -5001,9 +5958,9 @@ var MarketplaceClient = class {
5001
5958
  };
5002
5959
 
5003
5960
  // src/plugins/plugin-hooks-merger.ts
5004
- var import_node_path12 = require("path");
5961
+ var import_node_path15 = require("path");
5005
5962
  function buildPluginEnv(plugin) {
5006
- const dataDir = (0, import_node_path12.join)((0, import_node_path12.dirname)((0, import_node_path12.dirname)(plugin.pluginDir)), "data", plugin.manifest.name);
5963
+ const dataDir = (0, import_node_path15.join)((0, import_node_path15.dirname)((0, import_node_path15.dirname)(plugin.pluginDir)), "data", plugin.manifest.name);
5007
5964
  return {
5008
5965
  CLAUDE_PLUGIN_ROOT: plugin.pluginDir,
5009
5966
  CLAUDE_PLUGIN_PATH: plugin.pluginDir,
@@ -5065,8 +6022,9 @@ function mergeHooksIntoConfig(configHooks, pluginHooks) {
5065
6022
  }
5066
6023
 
5067
6024
  // src/interactive/interactive-session-init.ts
5068
- var import_node_os4 = require("os");
5069
- var import_node_path13 = require("path");
6025
+ var import_node_os5 = require("os");
6026
+ var import_node_path16 = require("path");
6027
+ var import_agent_tools5 = require("@robota-sdk/agent-tools");
5070
6028
  async function createInteractiveSession(options) {
5071
6029
  const cwd = options.cwd;
5072
6030
  const [config, context, projectInfo] = await Promise.all([
@@ -5074,7 +6032,7 @@ async function createInteractiveSession(options) {
5074
6032
  options.bare ? Promise.resolve({ agentsMd: "", claudeMd: "" }) : loadContext(cwd),
5075
6033
  options.bare ? Promise.resolve({ type: "unknown", language: "unknown" }) : detectProject(cwd)
5076
6034
  ]);
5077
- const pluginsDir = (0, import_node_path13.join)((0, import_node_os4.homedir)(), ".robota", "plugins");
6035
+ const pluginsDir = (0, import_node_path16.join)((0, import_node_os5.homedir)(), ".robota", "plugins");
5078
6036
  const pluginLoader = new BundlePluginLoader(pluginsDir);
5079
6037
  let mergedConfig = config;
5080
6038
  if (!options.bare) {
@@ -5094,6 +6052,10 @@ async function createInteractiveSession(options) {
5094
6052
  }
5095
6053
  }
5096
6054
  const paths = projectPaths(cwd);
6055
+ const sandboxRestored = await restoreInteractiveSandboxSnapshot(options);
6056
+ if (!sandboxRestored) {
6057
+ await applyInteractiveWorkspaceManifest(options, cwd);
6058
+ }
5097
6059
  const sessionId = options.resumeSessionId && !options.forkSession ? options.resumeSessionId : void 0;
5098
6060
  return createSession({
5099
6061
  config: mergedConfig,
@@ -5103,7 +6065,7 @@ async function createInteractiveSession(options) {
5103
6065
  permissionMode: options.permissionMode,
5104
6066
  maxTurns: options.maxTurns,
5105
6067
  terminal: NOOP_TERMINAL,
5106
- sessionLogger: new import_agent_sessions5.FileSessionLogger(paths.logs),
6068
+ sessionLogger: new import_agent_sessions6.FileSessionLogger(paths.logs),
5107
6069
  permissionHandler: options.permissionHandler,
5108
6070
  provider: options.provider,
5109
6071
  onTextDelta: options.onTextDelta,
@@ -5127,20 +6089,37 @@ async function createInteractiveSession(options) {
5127
6089
  modelCommandExecutor: options.modelCommandExecutor,
5128
6090
  isModelCommandInvocable: options.isModelCommandInvocable,
5129
6091
  editCheckpointRecorder: options.editCheckpointRecorder,
5130
- reversibleExecution: options.reversibleExecution
6092
+ reversibleExecution: options.reversibleExecution,
6093
+ sandboxClient: options.sandboxClient
5131
6094
  });
5132
6095
  }
6096
+ async function applyInteractiveWorkspaceManifest(options, cwd) {
6097
+ if (!options.workspaceManifest) return;
6098
+ if (!options.sandboxClient) {
6099
+ throw new Error("workspaceManifest requires sandboxClient.");
6100
+ }
6101
+ await (0, import_agent_tools5.applyWorkspaceManifest)(options.sandboxClient, options.workspaceManifest, {
6102
+ hostRoot: cwd,
6103
+ ...options.sandboxWorkspaceRoot ? { targetRoot: options.sandboxWorkspaceRoot } : {}
6104
+ });
6105
+ }
6106
+ async function restoreInteractiveSandboxSnapshot(options) {
6107
+ if (!options.sandboxSnapshotId) return false;
6108
+ if (!options.sandboxClient?.restore) {
6109
+ throw new Error("sandboxSnapshotId requires sandboxClient with restore().");
6110
+ }
6111
+ await options.sandboxClient.restore(options.sandboxSnapshotId);
6112
+ return true;
6113
+ }
5133
6114
  function injectSavedMessage(session, msg) {
5134
- if (!msg || typeof msg !== "object") return;
5135
- const m = msg;
5136
- if (!m.role || !m.content) return;
5137
- const role = m.role;
5138
- if (role === "tool") {
5139
- const toolCallId = m.toolCallId ?? "";
5140
- const name = m.name ?? void 0;
5141
- session.injectMessage("tool", m.content, { toolCallId, name });
5142
- } else if (role === "user" || role === "assistant" || role === "system") {
5143
- session.injectMessage(role, m.content);
6115
+ if (typeof msg.content !== "string") return;
6116
+ if (msg.role === "tool") {
6117
+ session.injectMessage("tool", msg.content, {
6118
+ toolCallId: msg.toolCallId,
6119
+ ...msg.name !== void 0 ? { name: msg.name } : {}
6120
+ });
6121
+ } else {
6122
+ session.injectMessage(msg.role, msg.content);
5144
6123
  }
5145
6124
  }
5146
6125
  function loadSessionRecord(sessionStore, resumeSessionId, forkSession, existingSession) {
@@ -5154,8 +6133,11 @@ function loadSessionRecord(sessionStore, resumeSessionId, forkSession, existingS
5154
6133
  backgroundTaskEvents: [],
5155
6134
  backgroundJobGroups: [],
5156
6135
  backgroundJobGroupEvents: [],
6136
+ skillActivationEvents: [],
5157
6137
  memoryEvents: [],
5158
- usedMemoryReferences: []
6138
+ usedMemoryReferences: [],
6139
+ contextReferences: [],
6140
+ sandboxSnapshotId: void 0
5159
6141
  };
5160
6142
  }
5161
6143
  const history = record.history ?? [];
@@ -5163,8 +6145,11 @@ function loadSessionRecord(sessionStore, resumeSessionId, forkSession, existingS
5163
6145
  const restoredBackgroundTaskEvents = record.backgroundTaskEvents ?? [];
5164
6146
  const backgroundJobGroups = record.backgroundJobGroups ?? [];
5165
6147
  const backgroundJobGroupEvents = record.backgroundJobGroupEvents ?? [];
6148
+ const skillActivationEvents = record.skillActivationEvents ?? [];
5166
6149
  const memoryEvents = record.memoryEvents ?? [];
5167
6150
  const usedMemoryReferences = record.usedMemoryReferences ?? [];
6151
+ const contextReferences = record.contextReferences ?? [];
6152
+ const sandboxSnapshotId = record.sandboxSnapshotId;
5168
6153
  const { backgroundTasks, backgroundTaskEvents } = reconcileRestoredBackgroundTasks(
5169
6154
  restoredBackgroundTasks,
5170
6155
  restoredBackgroundTaskEvents
@@ -5188,8 +6173,11 @@ function loadSessionRecord(sessionStore, resumeSessionId, forkSession, existingS
5188
6173
  backgroundTaskEvents,
5189
6174
  backgroundJobGroups,
5190
6175
  backgroundJobGroupEvents,
6176
+ skillActivationEvents,
5191
6177
  memoryEvents,
5192
- usedMemoryReferences
6178
+ usedMemoryReferences,
6179
+ contextReferences,
6180
+ sandboxSnapshotId
5193
6181
  };
5194
6182
  }
5195
6183
  function reconcileRestoredBackgroundTasks(tasks, events) {
@@ -5222,14 +6210,62 @@ function isRestoredTerminalStatus(status) {
5222
6210
  return status === "completed" || status === "failed" || status === "cancelled";
5223
6211
  }
5224
6212
 
6213
+ // src/interactive/interactive-session-context-references.ts
6214
+ async function addInteractiveContextReference(references, path, cwd) {
6215
+ const result = await resolvePromptFileReferencePaths([path], {
6216
+ cwd,
6217
+ reason: "manual"
6218
+ });
6219
+ if (hasBlockingPromptFileReferenceDiagnostics(result.diagnostics)) {
6220
+ return {
6221
+ references: [...references],
6222
+ result: {
6223
+ evicted: [],
6224
+ diagnostics: [formatPromptFileReferenceDiagnostics(result.diagnostics)]
6225
+ }
6226
+ };
6227
+ }
6228
+ const reference = result.references[0];
6229
+ if (!reference) {
6230
+ return {
6231
+ references: [...references],
6232
+ result: { evicted: [], diagnostics: ["No context reference was resolved."] }
6233
+ };
6234
+ }
6235
+ const item = createContextReferenceItem(
6236
+ toPromptFileReferenceRecords([reference])[0],
6237
+ "manual",
6238
+ "active"
6239
+ );
6240
+ const upserted = upsertContextReference(references, item);
6241
+ return {
6242
+ references: upserted.references,
6243
+ result: {
6244
+ reference: item,
6245
+ evicted: upserted.evicted,
6246
+ diagnostics: []
6247
+ }
6248
+ };
6249
+ }
6250
+ function recordInteractiveContextReferences(references, records, options) {
6251
+ if (records.length === 0) return [...references];
6252
+ const now = (/* @__PURE__ */ new Date()).toISOString();
6253
+ let next = [...references];
6254
+ for (const record of records) {
6255
+ const item = createContextReferenceItem(record, options.loadType, options.status, now);
6256
+ next = upsertContextReference(next, item).references;
6257
+ }
6258
+ return next;
6259
+ }
6260
+
5225
6261
  // src/checkpoints/edit-checkpoint-store.ts
5226
- var import_promises = require("fs/promises");
6262
+ var import_promises2 = require("fs/promises");
5227
6263
  var import_node_fs14 = require("fs");
5228
- var import_node_path15 = require("path");
6264
+ var import_node_path18 = require("path");
5229
6265
 
5230
6266
  // src/checkpoints/edit-checkpoint-inspection.ts
5231
6267
  var import_node_fs13 = require("fs");
5232
- var import_node_path14 = require("path");
6268
+ var import_node_path17 = require("path");
5233
6269
  function buildEditCheckpointInspection(input) {
5234
6270
  const later = input.manifests.filter((manifest) => manifest.sequence > input.target.sequence);
5235
6271
  const rollbackRange = input.manifests.filter(
@@ -5238,11 +6274,11 @@ function buildEditCheckpointInspection(input) {
5238
6274
  return {
5239
6275
  target: toSummary(input.target),
5240
6276
  capturedFiles: input.target.files.map((file) => {
5241
- const snapshotPath = file.snapshotFile ? (0, import_node_path14.join)(input.checkpointDir(input.sessionId, input.target.id), file.snapshotFile) : void 0;
6277
+ const snapshotPath = file.snapshotFile ? (0, import_node_path17.join)(input.checkpointDir(input.sessionId, input.target.id), file.snapshotFile) : void 0;
5242
6278
  const snapshotStats = snapshotPath ? statSafe(snapshotPath) : void 0;
5243
6279
  return {
5244
6280
  originalPath: file.originalPath,
5245
- relativePath: (0, import_node_path14.relative)(input.cwd, file.originalPath),
6281
+ relativePath: (0, import_node_path17.relative)(input.cwd, file.originalPath),
5246
6282
  existed: file.existed,
5247
6283
  restoreAction: file.existed ? "restore-preimage" : "delete-created-file",
5248
6284
  snapshotAvailable: file.existed ? snapshotStats !== void 0 : false,
@@ -5288,7 +6324,7 @@ var EditCheckpointStore = class {
5288
6324
  now;
5289
6325
  activeTurn = null;
5290
6326
  constructor(options) {
5291
- this.cwd = (0, import_node_path15.resolve)(options.cwd);
6327
+ this.cwd = (0, import_node_path18.resolve)(options.cwd);
5292
6328
  this.rootDir = projectPaths(this.cwd).checkpoints;
5293
6329
  this.now = options.now ?? (() => /* @__PURE__ */ new Date());
5294
6330
  }
@@ -5298,8 +6334,8 @@ var EditCheckpointStore = class {
5298
6334
  }
5299
6335
  const nextSequence = this.nextSequence(input.sessionId);
5300
6336
  const id = `turn-${String(nextSequence).padStart(ID_PAD, "0")}`;
5301
- const dir = (0, import_node_path15.join)(this.sessionDir(input.sessionId), id);
5302
- await (0, import_promises.mkdir)((0, import_node_path15.join)(dir, SNAPSHOT_DIR), { recursive: true });
6337
+ const dir = (0, import_node_path18.join)(this.sessionDir(input.sessionId), id);
6338
+ await (0, import_promises2.mkdir)((0, import_node_path18.join)(dir, SNAPSHOT_DIR), { recursive: true });
5303
6339
  const manifest = {
5304
6340
  version: 1,
5305
6341
  id,
@@ -5319,7 +6355,7 @@ var EditCheckpointStore = class {
5319
6355
  }
5320
6356
  async captureFile(filePath) {
5321
6357
  if (!this.activeTurn) return;
5322
- const originalPath = (0, import_node_path15.resolve)(this.cwd, filePath);
6358
+ const originalPath = (0, import_node_path18.resolve)(this.cwd, filePath);
5323
6359
  if (this.activeTurn.capturedPaths.has(originalPath)) return;
5324
6360
  if (isInside(this.rootDir, originalPath)) return;
5325
6361
  const record = await this.createFileRecord(originalPath, this.activeTurn);
@@ -5366,7 +6402,7 @@ var EditCheckpointStore = class {
5366
6402
  }
5367
6403
  }
5368
6404
  for (const manifest of later) {
5369
- await (0, import_promises.rm)(this.checkpointDir(sessionId, manifest.id), { recursive: true, force: true });
6405
+ await (0, import_promises2.rm)(this.checkpointDir(sessionId, manifest.id), { recursive: true, force: true });
5370
6406
  }
5371
6407
  return {
5372
6408
  target: toSummary2(target),
@@ -5390,7 +6426,7 @@ var EditCheckpointStore = class {
5390
6426
  }
5391
6427
  }
5392
6428
  for (const manifest of rollbackRange) {
5393
- await (0, import_promises.rm)(this.checkpointDir(sessionId, manifest.id), { recursive: true, force: true });
6429
+ await (0, import_promises2.rm)(this.checkpointDir(sessionId, manifest.id), { recursive: true, force: true });
5394
6430
  }
5395
6431
  return {
5396
6432
  target: toSummary2(target),
@@ -5407,11 +6443,11 @@ var EditCheckpointStore = class {
5407
6443
  existed: false
5408
6444
  };
5409
6445
  }
5410
- const snapshotFile = (0, import_node_path15.join)(
6446
+ const snapshotFile = (0, import_node_path18.join)(
5411
6447
  SNAPSHOT_DIR,
5412
6448
  `${String(active.manifest.files.length + 1).padStart(SNAPSHOT_PAD, "0")}.content`
5413
6449
  );
5414
- await (0, import_promises.copyFile)(originalPath, (0, import_node_path15.join)(active.dir, snapshotFile));
6450
+ await (0, import_promises2.copyFile)(originalPath, (0, import_node_path18.join)(active.dir, snapshotFile));
5415
6451
  return {
5416
6452
  originalPath,
5417
6453
  existed: true,
@@ -5420,38 +6456,38 @@ var EditCheckpointStore = class {
5420
6456
  }
5421
6457
  async restoreFile(sessionId, checkpointId, record) {
5422
6458
  if (!record.existed) {
5423
- await (0, import_promises.rm)(record.originalPath, { force: true });
6459
+ await (0, import_promises2.rm)(record.originalPath, { force: true });
5424
6460
  return;
5425
6461
  }
5426
6462
  if (!record.snapshotFile) {
5427
6463
  throw new Error(`Checkpoint file record is missing a snapshot: ${record.originalPath}`);
5428
6464
  }
5429
- await (0, import_promises.mkdir)((0, import_node_path15.dirname)(record.originalPath), { recursive: true });
5430
- await (0, import_promises.copyFile)(
5431
- (0, import_node_path15.join)(this.checkpointDir(sessionId, checkpointId), record.snapshotFile),
6465
+ await (0, import_promises2.mkdir)((0, import_node_path18.dirname)(record.originalPath), { recursive: true });
6466
+ await (0, import_promises2.copyFile)(
6467
+ (0, import_node_path18.join)(this.checkpointDir(sessionId, checkpointId), record.snapshotFile),
5432
6468
  record.originalPath
5433
6469
  );
5434
6470
  }
5435
6471
  loadManifests(sessionId) {
5436
6472
  const dir = this.sessionDir(sessionId);
5437
- return readDirSyncSafe(dir).map((entry) => (0, import_node_path15.join)(dir, entry, MANIFEST_FILE)).map((manifestPath) => readJsonManifest(manifestPath)).filter((manifest) => manifest !== void 0).sort((a, b) => a.sequence - b.sequence);
6473
+ return readDirSyncSafe(dir).map((entry) => (0, import_node_path18.join)(dir, entry, MANIFEST_FILE)).map((manifestPath) => readJsonManifest(manifestPath)).filter((manifest) => manifest !== void 0).sort((a, b) => a.sequence - b.sequence);
5438
6474
  }
5439
6475
  nextSequence(sessionId) {
5440
6476
  const last = this.list(sessionId).at(-1);
5441
6477
  return (last?.sequence ?? 0) + 1;
5442
6478
  }
5443
6479
  async writeManifest(dir, manifest) {
5444
- await (0, import_promises.mkdir)(dir, { recursive: true });
5445
- const path = (0, import_node_path15.join)(dir, MANIFEST_FILE);
6480
+ await (0, import_promises2.mkdir)(dir, { recursive: true });
6481
+ const path = (0, import_node_path18.join)(dir, MANIFEST_FILE);
5446
6482
  const tmp = `${path}.tmp`;
5447
- await (0, import_promises.writeFile)(tmp, JSON.stringify(manifest, null, 2), "utf8");
5448
- await (0, import_promises.rename)(tmp, path);
6483
+ await (0, import_promises2.writeFile)(tmp, JSON.stringify(manifest, null, 2), "utf8");
6484
+ await (0, import_promises2.rename)(tmp, path);
5449
6485
  }
5450
6486
  sessionDir(sessionId) {
5451
- return (0, import_node_path15.join)(this.rootDir, safePathSegment(sessionId));
6487
+ return (0, import_node_path18.join)(this.rootDir, safePathSegment(sessionId));
5452
6488
  }
5453
6489
  checkpointDir(sessionId, checkpointId) {
5454
- return (0, import_node_path15.join)(this.sessionDir(sessionId), safePathSegment(checkpointId));
6490
+ return (0, import_node_path18.join)(this.sessionDir(sessionId), safePathSegment(checkpointId));
5455
6491
  }
5456
6492
  };
5457
6493
  function toSummary2(manifest) {
@@ -5468,12 +6504,12 @@ function safePathSegment(value) {
5468
6504
  return value.replace(/[^a-zA-Z0-9._-]/g, "_");
5469
6505
  }
5470
6506
  function isInside(parent, child) {
5471
- const rel = (0, import_node_path15.relative)(parent, child);
6507
+ const rel = (0, import_node_path18.relative)(parent, child);
5472
6508
  return rel.length === 0 || !rel.startsWith("..") && !rel.startsWith("/");
5473
6509
  }
5474
6510
  async function pathExists(path) {
5475
6511
  try {
5476
- await (0, import_promises.access)(path, import_node_fs14.constants.F_OK);
6512
+ await (0, import_promises2.access)(path, import_node_fs14.constants.F_OK);
5477
6513
  return true;
5478
6514
  } catch {
5479
6515
  return false;
@@ -5496,6 +6532,21 @@ function readJsonManifest(path) {
5496
6532
  }
5497
6533
 
5498
6534
  // src/interactive/interactive-session.ts
6535
+ function normalizeSkillName(name) {
6536
+ return name.trim().replace(/^\/+/, "").split(/\s+/)[0] ?? "";
6537
+ }
6538
+ function normalizeCommandName(name) {
6539
+ return name.trim().replace(/^\/+/, "").split(/\s+/)[0] ?? "";
6540
+ }
6541
+ function formatSkillCommandArgs(skillName, args) {
6542
+ const trimmedArgs = args.trim();
6543
+ return trimmedArgs.length > 0 ? `${skillName} ${trimmedArgs}` : skillName;
6544
+ }
6545
+ function getQualifiedSkillName(rawInput) {
6546
+ if (!rawInput?.startsWith("/")) return void 0;
6547
+ const firstToken = rawInput.slice(1).trim().split(/\s+/)[0];
6548
+ return firstToken && firstToken.length > 0 ? firstToken : void 0;
6549
+ }
5499
6550
  var InteractiveSession = class {
5500
6551
  session = null;
5501
6552
  commandExecutor;
@@ -5520,6 +6571,7 @@ var InteractiveSession = class {
5520
6571
  backgroundJobGroupEvents = [];
5521
6572
  memoryEvents = [];
5522
6573
  usedMemoryReferences = [];
6574
+ contextReferences = [];
5523
6575
  editCheckpointStore = null;
5524
6576
  resumeSessionId;
5525
6577
  forkSession;
@@ -5528,15 +6580,16 @@ var InteractiveSession = class {
5528
6580
  backgroundJobOrchestrator = null;
5529
6581
  commandModules;
5530
6582
  commandHostAdapters;
6583
+ skillCommandSource;
6584
+ skillActivationEvents = [];
5531
6585
  autoCompactThresholdSource = "default";
5532
6586
  shuttingDown = false;
5533
6587
  shutdownPromise = null;
6588
+ sandboxClient;
6589
+ sandboxSnapshotId;
6590
+ commandInvocationSource = "user";
5534
6591
  constructor(options) {
5535
- const sdkBuiltinModule = createBuiltinCommandModule();
5536
- this.commandModules = [
5537
- sdkBuiltinModule,
5538
- ..."commandModules" in options ? options.commandModules ?? [] : []
5539
- ];
6592
+ this.commandModules = [..."commandModules" in options ? options.commandModules ?? [] : []];
5540
6593
  this.commandExecutor = new SystemCommandExecutor(
5541
6594
  this.commandModules.flatMap((module2) => module2.systemCommands ?? [])
5542
6595
  );
@@ -5549,34 +6602,48 @@ var InteractiveSession = class {
5549
6602
  this.resumeSessionId = options.resumeSessionId;
5550
6603
  this.forkSession = options.forkSession ?? false;
5551
6604
  this.commandHostAdapters = "commandHostAdapters" in options ? options.commandHostAdapters : void 0;
5552
- if ("session" in options && options.session) {
5553
- this.session = options.session;
5554
- this.autoCompactThresholdSource = "session";
5555
- this.initialized = true;
5556
- } else {
5557
- const stdOpts = options;
5558
- this.initPromise = this.initializeAsync(stdOpts);
5559
- }
5560
- if (options.resumeSessionId && this.sessionStore) {
5561
- const restored = loadSessionRecord(
5562
- this.sessionStore,
5563
- options.resumeSessionId,
5564
- this.forkSession,
5565
- this.session
5566
- );
5567
- if (restored.history.length > 0) this.history = restored.history;
5568
- if (restored.sessionName) this.sessionName = restored.sessionName;
5569
- this.backgroundTasks = restored.backgroundTasks;
5570
- this.backgroundTaskEvents = restored.backgroundTaskEvents;
5571
- this.backgroundJobGroups = restored.backgroundJobGroups;
5572
- this.backgroundJobGroupEvents = restored.backgroundJobGroupEvents;
5573
- this.memoryEvents = restored.memoryEvents;
5574
- this.usedMemoryReferences = restored.usedMemoryReferences;
5575
- this.pendingRestoreMessages = restored.pendingRestoreMessages;
5576
- }
6605
+ this.sandboxClient = "sandboxClient" in options ? options.sandboxClient : void 0;
6606
+ this.sandboxSnapshotId = "sandboxSnapshotId" in options ? options.sandboxSnapshotId : void 0;
6607
+ this.skillCommandSource = new SkillCommandSource(this.cwd || process.cwd());
6608
+ const hasInjectedSession = this.configureInjectedSession(options);
6609
+ this.restoreSessionRecordIfNeeded(options);
6610
+ this.startAsyncInitializationIfNeeded(options, hasInjectedSession);
5577
6611
  if (this.initialized) this.subscribeBackgroundTaskEvents();
5578
6612
  if (this.initialized) this.persistCurrentSession();
5579
6613
  }
6614
+ configureInjectedSession(options) {
6615
+ if (!("session" in options && options.session)) return false;
6616
+ this.session = options.session;
6617
+ this.autoCompactThresholdSource = "session";
6618
+ this.initialized = true;
6619
+ return true;
6620
+ }
6621
+ restoreSessionRecordIfNeeded(options) {
6622
+ if (!options.resumeSessionId || !this.sessionStore) return;
6623
+ const restored = loadSessionRecord(
6624
+ this.sessionStore,
6625
+ options.resumeSessionId,
6626
+ this.forkSession,
6627
+ this.session
6628
+ );
6629
+ if (restored.history.length > 0) this.history = restored.history;
6630
+ if (restored.sessionName) this.sessionName = restored.sessionName;
6631
+ this.backgroundTasks = restored.backgroundTasks;
6632
+ this.backgroundTaskEvents = restored.backgroundTaskEvents;
6633
+ this.backgroundJobGroups = restored.backgroundJobGroups;
6634
+ this.backgroundJobGroupEvents = restored.backgroundJobGroupEvents;
6635
+ this.skillActivationEvents = restored.skillActivationEvents;
6636
+ this.memoryEvents = restored.memoryEvents;
6637
+ this.usedMemoryReferences = restored.usedMemoryReferences;
6638
+ this.contextReferences = restored.contextReferences;
6639
+ this.pendingRestoreMessages = restored.pendingRestoreMessages;
6640
+ this.sandboxSnapshotId = this.forkSession ? void 0 : restored.sandboxSnapshotId;
6641
+ }
6642
+ startAsyncInitializationIfNeeded(options, hasInjectedSession) {
6643
+ if (hasInjectedSession) return;
6644
+ const stdOpts = options;
6645
+ this.initPromise = this.initializeAsync(stdOpts);
6646
+ }
5580
6647
  async initializeAsync(options) {
5581
6648
  const config = options.config ?? await loadConfig(options.cwd);
5582
6649
  this.autoCompactThresholdSource = config.autoCompactThreshold === void 0 ? "default" : "settings";
@@ -5602,6 +6669,10 @@ var InteractiveSession = class {
5602
6669
  ...options.commandModules ? { commandModules: options.commandModules } : {},
5603
6670
  editCheckpointRecorder: this.editCheckpointStore,
5604
6671
  ...options.reversibleExecution ? { reversibleExecution: options.reversibleExecution } : {},
6672
+ ...options.sandboxClient ? { sandboxClient: options.sandboxClient } : {},
6673
+ ...options.workspaceManifest ? { workspaceManifest: options.workspaceManifest } : {},
6674
+ ...options.sandboxWorkspaceRoot ? { sandboxWorkspaceRoot: options.sandboxWorkspaceRoot } : {},
6675
+ ...this.sandboxSnapshotId ? { sandboxSnapshotId: this.sandboxSnapshotId } : {},
5605
6676
  commandDescriptors: this.commandExecutor.listModelInvocableCommands(),
5606
6677
  ...this.commandExecutor.listModelInvocableCommands().length > 0 ? {
5607
6678
  modelCommandExecutor: (command, args) => this.executeModelCommand(command, args),
@@ -5648,36 +6719,102 @@ var InteractiveSession = class {
5648
6719
  }
5649
6720
  async executeCommand(name, args) {
5650
6721
  await this.ensureInitialized();
5651
- const command = this.commandExecutor.getCommand(name);
5652
- if (!command) return null;
6722
+ const normalizedName = normalizeCommandName(name);
6723
+ const command = this.commandExecutor.getCommand(normalizedName);
6724
+ const commandArgs = args.trim();
6725
+ if (!command) {
6726
+ const skill = this.findSkillCommand(normalizedName);
6727
+ const skillsCommand = this.commandExecutor.getCommand("skills");
6728
+ if (!skill || !skillsCommand) return null;
6729
+ return this.executeCommandWithInvocationSource(
6730
+ "user",
6731
+ skillsCommand,
6732
+ formatSkillCommandArgs(skill.name, commandArgs)
6733
+ );
6734
+ }
6735
+ return this.executeCommandWithInvocationSource("user", command, commandArgs);
6736
+ }
6737
+ async executeCommandWithInvocationSource(source, command, args) {
5653
6738
  if (this.executing) {
5654
6739
  return {
5655
6740
  success: false,
5656
6741
  message: "Another prompt or command is already running. Wait for it to finish."
5657
6742
  };
5658
6743
  }
5659
- if (command.lifecycle === "blocking") {
5660
- return this.executeForegroundCommand(command, args);
6744
+ const previousSource = this.commandInvocationSource;
6745
+ this.commandInvocationSource = source;
6746
+ try {
6747
+ if (command.lifecycle === "blocking") {
6748
+ return this.executeForegroundCommand(command, args);
6749
+ }
6750
+ return await this.commandExecutor.executeCommand(command, this, args);
6751
+ } finally {
6752
+ this.commandInvocationSource = previousSource;
5661
6753
  }
5662
- return this.commandExecutor.executeCommand(command, this, args);
5663
6754
  }
5664
6755
  async executeModelCommand(name, args) {
5665
6756
  await this.ensureInitialized();
5666
- return this.commandExecutor.executeModelInvocable(name, this, args);
6757
+ const previousSource = this.commandInvocationSource;
6758
+ this.commandInvocationSource = "model";
6759
+ try {
6760
+ return await this.commandExecutor.executeModelInvocable(name, this, args);
6761
+ } finally {
6762
+ this.commandInvocationSource = previousSource;
6763
+ }
5667
6764
  }
5668
- async executeSkillCommand(skill, args, displayInput, rawInput) {
6765
+ getCommandInvocationSource() {
6766
+ return this.commandInvocationSource;
6767
+ }
6768
+ async executeSkillCommandByName(name, args, request) {
5669
6769
  await this.ensureInitialized();
5670
- if (skill.context === "fork") {
5671
- return this.executeForkSkillCommand(skill, args, displayInput);
6770
+ const skill = this.findSkillCommand(name);
6771
+ if (!skill) return null;
6772
+ if (request.invocationSource === "model") {
6773
+ if (skill.disableModelInvocation === true) {
6774
+ return {
6775
+ success: false,
6776
+ message: `Skill is not model-invocable: ${skill.name}`
6777
+ };
6778
+ }
6779
+ const result = await this.executeSkillWithActivation(skill, args, "model-tool");
6780
+ return {
6781
+ success: true,
6782
+ message: `Skill activated: ${skill.name}`,
6783
+ data: {
6784
+ skill: skill.name,
6785
+ mode: result.mode,
6786
+ ...result.prompt !== void 0 ? { prompt: result.prompt } : {},
6787
+ ...result.result !== void 0 ? { result: result.result } : {}
6788
+ }
6789
+ };
5672
6790
  }
5673
- const result = await executeSkill(
6791
+ await this.executeUserResolvedSkillCommand(
5674
6792
  skill,
5675
6793
  args,
5676
- {
5677
- runInFork: (content, options) => this.runSkillInFork(content, options)
5678
- },
5679
- { sessionId: this.getSessionOrThrow().getSessionId() }
6794
+ request.displayInput,
6795
+ request.rawInput,
6796
+ "user-slash"
5680
6797
  );
6798
+ return {
6799
+ success: true,
6800
+ message: "",
6801
+ data: {
6802
+ skill: skill.name,
6803
+ sessionExecution: true
6804
+ },
6805
+ effects: [{ type: "session-execution-started" }]
6806
+ };
6807
+ }
6808
+ async executeUserResolvedSkillCommand(skill, args, displayInput, rawInput, invocation) {
6809
+ await this.ensureInitialized();
6810
+ if (skill.userInvocable === false) {
6811
+ throw new Error(`Skill is not user-invocable: ${skill.name}`);
6812
+ }
6813
+ const qualifiedName = getQualifiedSkillName(rawInput);
6814
+ if (skill.context === "fork") {
6815
+ return this.executeForkSkillCommand(skill, args, displayInput, qualifiedName, invocation);
6816
+ }
6817
+ const result = await this.executeSkillWithActivation(skill, args, invocation, qualifiedName);
5681
6818
  if (result.mode === "inject") {
5682
6819
  if (result.prompt) {
5683
6820
  await this.submit(result.prompt, displayInput, rawInput);
@@ -5693,12 +6830,31 @@ var InteractiveSession = class {
5693
6830
  description: cmd.description
5694
6831
  }));
5695
6832
  }
6833
+ listSkills() {
6834
+ return this.skillCommandSource.getCommands().map((skill) => ({
6835
+ name: skill.name,
6836
+ description: skill.description,
6837
+ source: skill.source,
6838
+ modelInvocable: skill.disableModelInvocation !== true,
6839
+ userInvocable: skill.userInvocable !== false,
6840
+ ...skill.argumentHint !== void 0 ? { argumentHint: skill.argumentHint } : {},
6841
+ ...skill.context !== void 0 ? { context: skill.context } : {},
6842
+ ...skill.agent !== void 0 ? { agent: skill.agent } : {}
6843
+ }));
6844
+ }
5696
6845
  listModelInvocableCommands() {
5697
6846
  return this.commandExecutor.listModelInvocableCommands().map((cmd) => ({
5698
6847
  name: cmd.name,
5699
6848
  description: cmd.description
5700
6849
  }));
5701
6850
  }
6851
+ getSkillActivationEvents() {
6852
+ return [...this.skillActivationEvents];
6853
+ }
6854
+ findSkillCommand(name) {
6855
+ const normalizedName = normalizeSkillName(name);
6856
+ return this.skillCommandSource.getCommands().find((skill) => skill.name.toLowerCase() === normalizedName.toLowerCase());
6857
+ }
5702
6858
  abort() {
5703
6859
  this.clearPendingQueue();
5704
6860
  this.session?.abort();
@@ -5718,6 +6874,7 @@ var InteractiveSession = class {
5718
6874
  this.backgroundJobUnsubscribe = null;
5719
6875
  this.backgroundJobOrchestrator?.dispose();
5720
6876
  this.backgroundJobOrchestrator = null;
6877
+ await this.captureSandboxSnapshot();
5721
6878
  this.persistCurrentSession();
5722
6879
  await session?.shutdown({ reason: options.reason ?? "other" });
5723
6880
  })();
@@ -5830,6 +6987,31 @@ var InteractiveSession = class {
5830
6987
  this.memoryEvents.push(event);
5831
6988
  this.persistCurrentSession();
5832
6989
  }
6990
+ listContextReferences() {
6991
+ return [...this.contextReferences];
6992
+ }
6993
+ async addContextReference(path) {
6994
+ const { references, result } = await addInteractiveContextReference(
6995
+ this.contextReferences,
6996
+ path,
6997
+ this.getCwd()
6998
+ );
6999
+ this.contextReferences = references;
7000
+ this.persistCurrentSession();
7001
+ return result;
7002
+ }
7003
+ removeContextReference(path) {
7004
+ const result = removeContextReference(this.contextReferences, path);
7005
+ this.contextReferences = result.references;
7006
+ this.persistCurrentSession();
7007
+ return result.result;
7008
+ }
7009
+ clearContextReferences() {
7010
+ const result = clearContextReferences(this.contextReferences);
7011
+ this.contextReferences = [];
7012
+ this.persistCurrentSession();
7013
+ return result;
7014
+ }
5833
7015
  listBackgroundTasks(filter) {
5834
7016
  return this.getBackgroundTaskManagerOrThrow().list(filter);
5835
7017
  }
@@ -5931,18 +7113,63 @@ var InteractiveSession = class {
5931
7113
  attachTransport(transport) {
5932
7114
  transport.attach(this);
5933
7115
  }
5934
- async executeForkSkillCommand(skill, args, displayInput) {
5935
- if (this.executing) {
5936
- throw new Error("Cannot execute fork skill while another prompt is running.");
5937
- }
5938
- this.startForkSkillExecution(displayInput ?? `/${skill.name}`);
7116
+ async executeSkillWithActivation(skill, args, invocation, qualifiedName) {
7117
+ this.recordSkillActivation(skill, invocation, "started", qualifiedName);
5939
7118
  try {
5940
7119
  const result = await executeSkill(
5941
7120
  skill,
5942
7121
  args,
5943
- { runInFork: (content, options) => this.runSkillInFork(content, options) },
7122
+ {
7123
+ runInFork: (content, options) => this.runSkillInFork(content, options)
7124
+ },
5944
7125
  { sessionId: this.getSessionOrThrow().getSessionId() }
5945
7126
  );
7127
+ this.recordSkillActivation(skill, invocation, "completed", qualifiedName, {
7128
+ appendHistory: false
7129
+ });
7130
+ return result;
7131
+ } catch (err) {
7132
+ const error = err instanceof Error ? err : new Error(String(err));
7133
+ this.recordSkillActivation(skill, invocation, "failed", qualifiedName, {
7134
+ error: error.message
7135
+ });
7136
+ throw error;
7137
+ }
7138
+ }
7139
+ recordSkillActivation(skill, invocation, status, qualifiedName, options = {}) {
7140
+ const event = createSkillActivationEvent({
7141
+ skill,
7142
+ invocation,
7143
+ status,
7144
+ ...qualifiedName !== void 0 ? { qualifiedName } : {},
7145
+ ...options.error !== void 0 ? { error: options.error } : {}
7146
+ });
7147
+ this.recordSkillActivationEvent(event, options.appendHistory ?? status !== "completed");
7148
+ }
7149
+ recordSkillActivationEvent(event, appendHistory) {
7150
+ this.skillActivationEvents.push(event);
7151
+ if (appendHistory) {
7152
+ this.history.push({
7153
+ id: (0, import_node_crypto5.randomUUID)(),
7154
+ timestamp: new Date(event.timestamp),
7155
+ category: "event",
7156
+ type: "skill-activation",
7157
+ data: {
7158
+ ...event,
7159
+ message: formatSkillActivationMessage(event)
7160
+ }
7161
+ });
7162
+ }
7163
+ this.emit("skill_activation", event);
7164
+ this.persistCurrentSession();
7165
+ }
7166
+ async executeForkSkillCommand(skill, args, displayInput, qualifiedName, invocation = "user-slash") {
7167
+ if (this.executing) {
7168
+ throw new Error("Cannot execute fork skill while another prompt is running.");
7169
+ }
7170
+ this.startForkSkillExecution(displayInput ?? `/${skill.name}`);
7171
+ try {
7172
+ const result = await this.executeSkillWithActivation(skill, args, invocation, qualifiedName);
5946
7173
  await this.applyForkSkillResult(result.result ?? "(empty response)");
5947
7174
  return result;
5948
7175
  } catch (err) {
@@ -6056,9 +7283,30 @@ var InteractiveSession = class {
6056
7283
  {
6057
7284
  events: this.memoryEvents,
6058
7285
  usedReferences: this.usedMemoryReferences
7286
+ },
7287
+ {
7288
+ events: this.skillActivationEvents
7289
+ },
7290
+ {
7291
+ references: this.contextReferences
7292
+ },
7293
+ {
7294
+ snapshotId: this.sandboxSnapshotId
6059
7295
  }
6060
7296
  );
6061
7297
  }
7298
+ async captureSandboxSnapshot() {
7299
+ if (!this.sandboxClient?.snapshot) return;
7300
+ try {
7301
+ this.sandboxSnapshotId = await this.sandboxClient.snapshot();
7302
+ } catch (error) {
7303
+ const err = error instanceof Error ? error : new Error(String(error));
7304
+ this.history.push(
7305
+ (0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createSystemMessage)(`Sandbox snapshot error: ${err.message}`))
7306
+ );
7307
+ this.emit("error", err);
7308
+ }
7309
+ }
6062
7310
  startForkSkillExecution(displayInput) {
6063
7311
  this.executing = true;
6064
7312
  this.clearStreaming();
@@ -6074,7 +7322,7 @@ var InteractiveSession = class {
6074
7322
  const queuedDisplay = this.pendingDisplayInput;
6075
7323
  const queuedRaw = this.pendingRawInput;
6076
7324
  this.clearPendingQueue();
6077
- setTimeout(() => this.executePrompt(queued, queuedDisplay, queuedRaw), 0);
7325
+ setTimeout(() => void this.submit(queued, queuedDisplay, queuedRaw), 0);
6078
7326
  }
6079
7327
  }
6080
7328
  recordForkSkillError(err) {
@@ -6096,7 +7344,9 @@ var InteractiveSession = class {
6096
7344
  const parentSession = this.getSessionOrThrow();
6097
7345
  const deps = retrieveAgentToolDeps(parentSession);
6098
7346
  if (!deps) {
6099
- throw new Error("Fork execution is not available. Agent tool deps may not be initialized.");
7347
+ throw new Error(
7348
+ "Fork execution is not available. Agent runtime deps may not be initialized."
7349
+ );
6100
7350
  }
6101
7351
  const agentType = options.agent ?? "general-purpose";
6102
7352
  const agentDefinition = this.resolveForkAgentDefinition(agentType, options);
@@ -6154,7 +7404,7 @@ var InteractiveSession = class {
6154
7404
  const queuedDisplay = this.pendingDisplayInput;
6155
7405
  const queuedRaw = this.pendingRawInput;
6156
7406
  this.clearPendingQueue();
6157
- setTimeout(() => this.executePrompt(queued, queuedDisplay, queuedRaw), 0);
7407
+ setTimeout(() => void this.submit(queued, queuedDisplay, queuedRaw), 0);
6158
7408
  }
6159
7409
  }
6160
7410
  }
@@ -6166,8 +7416,22 @@ var InteractiveSession = class {
6166
7416
  const historyBefore = this.getSessionOrThrow().getHistory().length;
6167
7417
  this.usedMemoryReferences = [];
6168
7418
  try {
7419
+ const preparedPrompt = await preparePromptInput(
7420
+ input,
7421
+ this.getCwd(),
7422
+ rawInput,
7423
+ this.contextReferences
7424
+ );
7425
+ if (preparedPrompt.promptFileReferenceEntry) {
7426
+ this.history.push(preparedPrompt.promptFileReferenceEntry);
7427
+ }
7428
+ this.recordContextReferenceUsage(preparedPrompt.activeContextReferenceRecords);
7429
+ this.recordPromptContextReferences(preparedPrompt.promptFileReferenceRecords);
6169
7430
  await this.beginEditCheckpointTurn(displayInput ?? input);
6170
- const response = await this.getSessionOrThrow().run(input, rawInput);
7431
+ const response = await this.getSessionOrThrow().run(
7432
+ preparedPrompt.modelInput,
7433
+ preparedPrompt.hookInput
7434
+ );
6171
7435
  this.flushStreaming();
6172
7436
  pushToolSummaryToHistory({ activeTools: this.activeTools, history: this.history });
6173
7437
  this.clearStreaming();
@@ -6176,7 +7440,8 @@ var InteractiveSession = class {
6176
7440
  this.getSessionOrThrow().getHistory(),
6177
7441
  this.history,
6178
7442
  historyBefore,
6179
- this.getContextState()
7443
+ this.getContextState(),
7444
+ preparedPrompt.promptFileReferenceRecords
6180
7445
  );
6181
7446
  this.history.push((0, import_agent_core7.messageToHistoryEntry)((0, import_agent_core7.createAssistantMessage)(result.response)));
6182
7447
  if (result.usage) this.history.push(createUsageSummaryEntry(result.usage));
@@ -6215,10 +7480,24 @@ var InteractiveSession = class {
6215
7480
  const queuedDisplay = this.pendingDisplayInput;
6216
7481
  const queuedRaw = this.pendingRawInput;
6217
7482
  this.clearPendingQueue();
6218
- setTimeout(() => this.executePrompt(queued, queuedDisplay, queuedRaw), 0);
7483
+ setTimeout(() => void this.submit(queued, queuedDisplay, queuedRaw), 0);
6219
7484
  }
6220
7485
  }
6221
7486
  }
7487
+ recordContextReferenceUsage(records) {
7488
+ this.contextReferences = recordInteractiveContextReferences(this.contextReferences, records, {
7489
+ loadType: "manual",
7490
+ status: "active"
7491
+ });
7492
+ this.persistCurrentSession();
7493
+ }
7494
+ recordPromptContextReferences(records) {
7495
+ this.contextReferences = recordInteractiveContextReferences(this.contextReferences, records, {
7496
+ loadType: "prompt-reference",
7497
+ status: "observed"
7498
+ });
7499
+ this.persistCurrentSession();
7500
+ }
6222
7501
  getEditCheckpointStore() {
6223
7502
  if (!this.editCheckpointStore) {
6224
7503
  this.editCheckpointStore = new EditCheckpointStore({ cwd: this.getCwd() });
@@ -6294,6 +7573,159 @@ var InteractiveSession = class {
6294
7573
  }
6295
7574
  };
6296
7575
 
7576
+ // src/interactive/session-persistence.ts
7577
+ var import_agent_sessions7 = require("@robota-sdk/agent-sessions");
7578
+ var import_node_fs15 = require("fs");
7579
+ var import_node_path19 = require("path");
7580
+ function createProjectSessionStore(cwd) {
7581
+ const paths = projectPaths(cwd);
7582
+ return new ProjectSessionStoreFacade(paths.sessions, paths.logs);
7583
+ }
7584
+ function listResumableSessionSummaries(sessionStore, cwd) {
7585
+ return (sessionStore?.list() ?? []).filter((session) => session.cwd === cwd).sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()).map((session) => ({
7586
+ id: session.id,
7587
+ ...session.name !== void 0 ? { name: session.name } : {},
7588
+ cwd: session.cwd,
7589
+ updatedAt: session.updatedAt,
7590
+ messageCount: session.messages.length,
7591
+ preview: getLastAssistantPreview(session.messages)
7592
+ }));
7593
+ }
7594
+ function resolveLatestSessionId(sessionStore, cwd) {
7595
+ return listResumableSessionSummaries(sessionStore, cwd)[0]?.id;
7596
+ }
7597
+ function resolveSessionIdByIdOrName(sessionStore, idOrName) {
7598
+ const match = (sessionStore?.list() ?? []).find(
7599
+ (session) => session.id === idOrName || session.name === idOrName
7600
+ );
7601
+ return match?.id;
7602
+ }
7603
+ var ProjectSessionStoreFacade = class {
7604
+ store;
7605
+ logsDir;
7606
+ constructor(baseDir, logsDir) {
7607
+ this.store = new import_agent_sessions7.SessionStore(baseDir);
7608
+ this.logsDir = logsDir;
7609
+ }
7610
+ save(session) {
7611
+ this.store.save(toSessionRecord(session));
7612
+ }
7613
+ load(id) {
7614
+ const session = this.store.load(id);
7615
+ if (session !== void 0) {
7616
+ return fromSessionRecord(session);
7617
+ }
7618
+ return this.loadFromReplayLog(id);
7619
+ }
7620
+ list() {
7621
+ const records = this.store.list().map(fromSessionRecord);
7622
+ const seen = new Set(records.map((record) => record.id));
7623
+ for (const replayRecord of this.listReplayLogRecords()) {
7624
+ if (!seen.has(replayRecord.id)) {
7625
+ records.push(replayRecord);
7626
+ }
7627
+ }
7628
+ return records.sort(
7629
+ (a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime()
7630
+ );
7631
+ }
7632
+ delete(id) {
7633
+ this.store.delete(id);
7634
+ }
7635
+ loadFromReplayLog(id) {
7636
+ if (!this.logsDir) return void 0;
7637
+ const replay = (0, import_agent_sessions7.replaySessionLogEntries)(
7638
+ (0, import_agent_sessions7.loadSessionLogEntries)((0, import_node_path19.join)(this.logsDir, `${id}.jsonl`))
7639
+ );
7640
+ if (!replay.sessionId || replay.messages.length === 0) {
7641
+ return void 0;
7642
+ }
7643
+ const backgroundTaskEvents = replay.backgroundTaskEvents;
7644
+ const backgroundJobGroupEvents = replay.backgroundJobGroupEvents;
7645
+ return {
7646
+ id: replay.sessionId,
7647
+ cwd: replay.cwd ?? "",
7648
+ createdAt: replay.createdAt ?? replay.updatedAt ?? (/* @__PURE__ */ new Date(0)).toISOString(),
7649
+ updatedAt: replay.updatedAt ?? replay.createdAt ?? (/* @__PURE__ */ new Date(0)).toISOString(),
7650
+ messages: replay.messages,
7651
+ history: replay.history,
7652
+ backgroundTasks: deriveBackgroundTasks(backgroundTaskEvents),
7653
+ backgroundTaskEvents,
7654
+ backgroundJobGroups: deriveBackgroundJobGroups(backgroundJobGroupEvents),
7655
+ backgroundJobGroupEvents,
7656
+ skillActivationEvents: [],
7657
+ memoryEvents: replay.memoryEvents
7658
+ };
7659
+ }
7660
+ listReplayLogRecords() {
7661
+ if (!this.logsDir || !(0, import_node_fs15.existsSync)(this.logsDir)) {
7662
+ return [];
7663
+ }
7664
+ return (0, import_node_fs15.readdirSync)(this.logsDir).filter((file) => file.endsWith(".jsonl")).map((file) => this.loadFromReplayLog(file.slice(0, -".jsonl".length))).filter((record) => record !== void 0);
7665
+ }
7666
+ };
7667
+ function getLastAssistantPreview(messages) {
7668
+ for (const message of [...messages].reverse()) {
7669
+ if (message.role !== "assistant") continue;
7670
+ if (typeof message.content !== "string") continue;
7671
+ return message.content.replace(/[\n\r]+/g, " ").trim();
7672
+ }
7673
+ return "";
7674
+ }
7675
+ function toSessionRecord(session) {
7676
+ return { ...session };
7677
+ }
7678
+ function fromSessionRecord(session) {
7679
+ return {
7680
+ id: session.id,
7681
+ ...session.name !== void 0 ? { name: session.name } : {},
7682
+ cwd: session.cwd,
7683
+ createdAt: session.createdAt,
7684
+ updatedAt: session.updatedAt,
7685
+ messages: session.messages,
7686
+ ...session.history !== void 0 ? { history: session.history } : {},
7687
+ ...session.systemPrompt !== void 0 ? { systemPrompt: session.systemPrompt } : {},
7688
+ ...session.toolSchemas !== void 0 ? { toolSchemas: session.toolSchemas } : {},
7689
+ ...session.backgroundTasks !== void 0 ? { backgroundTasks: session.backgroundTasks } : {},
7690
+ ...session.backgroundTaskEvents !== void 0 ? { backgroundTaskEvents: session.backgroundTaskEvents } : {},
7691
+ ...session.backgroundJobGroups !== void 0 ? { backgroundJobGroups: session.backgroundJobGroups } : {},
7692
+ ...session.backgroundJobGroupEvents !== void 0 ? { backgroundJobGroupEvents: session.backgroundJobGroupEvents } : {},
7693
+ ...session.skillActivationEvents !== void 0 ? { skillActivationEvents: session.skillActivationEvents } : {},
7694
+ ...session.memoryEvents !== void 0 ? { memoryEvents: session.memoryEvents } : {},
7695
+ ...session.usedMemoryReferences !== void 0 ? { usedMemoryReferences: session.usedMemoryReferences } : {},
7696
+ ...session.contextReferences !== void 0 ? { contextReferences: session.contextReferences } : {},
7697
+ ...session.sandboxSnapshotId !== void 0 ? { sandboxSnapshotId: session.sandboxSnapshotId } : {}
7698
+ };
7699
+ }
7700
+ function deriveBackgroundTasks(events) {
7701
+ const tasks = /* @__PURE__ */ new Map();
7702
+ for (const event of events) {
7703
+ const task = getBackgroundTaskSnapshot(event);
7704
+ if (task) tasks.set(task.id, task);
7705
+ }
7706
+ return [...tasks.values()];
7707
+ }
7708
+ function getBackgroundTaskSnapshot(event) {
7709
+ switch (event.type) {
7710
+ case "background_task_created":
7711
+ case "background_task_started":
7712
+ case "background_task_updated":
7713
+ case "background_task_completed":
7714
+ case "background_task_failed":
7715
+ case "background_task_cancelled":
7716
+ return event.task;
7717
+ default:
7718
+ return void 0;
7719
+ }
7720
+ }
7721
+ function deriveBackgroundJobGroups(events) {
7722
+ const groups = /* @__PURE__ */ new Map();
7723
+ for (const event of events) {
7724
+ groups.set(event.group.id, event.group);
7725
+ }
7726
+ return [...groups.values()];
7727
+ }
7728
+
6297
7729
  // src/query.ts
6298
7730
  function createQuery(options) {
6299
7731
  const session = new InteractiveSession({
@@ -6307,14 +7739,14 @@ function createQuery(options) {
6307
7739
  session.on("text_delta", options.onTextDelta);
6308
7740
  }
6309
7741
  return async (prompt) => {
6310
- return new Promise((resolve4, reject) => {
7742
+ return new Promise((resolve6, reject) => {
6311
7743
  const onComplete = (result) => {
6312
7744
  cleanup();
6313
- resolve4(result.response);
7745
+ resolve6(result.response);
6314
7746
  };
6315
7747
  const onInterrupted = (result) => {
6316
7748
  cleanup();
6317
- resolve4(result.response);
7749
+ resolve6(result.response);
6318
7750
  };
6319
7751
  const onError = (error) => {
6320
7752
  cleanup();
@@ -6336,12 +7768,6 @@ function createQuery(options) {
6336
7768
  };
6337
7769
  }
6338
7770
 
6339
- // src/types.ts
6340
- var import_agent_core8 = require("@robota-sdk/agent-core");
6341
-
6342
- // src/index.ts
6343
- var import_agent_core9 = require("@robota-sdk/agent-core");
6344
-
6345
7771
  // src/self-hosting/self-hosting-verification.ts
6346
7772
  var DEFAULT_BASE_REF = "origin/develop";
6347
7773
  var PACKAGE_VERIFY_COMMANDS = ["test", "typecheck", "build"];
@@ -6457,13 +7883,72 @@ function transitionSelfHostingLoop(state, event) {
6457
7883
  return nextState;
6458
7884
  }
6459
7885
 
7886
+ // src/tools/command-execution-tool.ts
7887
+ var import_zod5 = require("zod");
7888
+ var import_agent_tools6 = require("@robota-sdk/agent-tools");
7889
+ function asZodSchema4(schema) {
7890
+ return schema;
7891
+ }
7892
+ function toNonEmptyCommandNames(commandNames) {
7893
+ if (!commandNames || commandNames.length === 0) return void 0;
7894
+ const [first, ...rest] = commandNames;
7895
+ if (first === void 0) return void 0;
7896
+ return [first, ...rest];
7897
+ }
7898
+ function createCommandExecutionSchema(commandNames) {
7899
+ const validCommandNames = toNonEmptyCommandNames(commandNames);
7900
+ const commandSchema = validCommandNames !== void 0 ? import_zod5.z.enum(validCommandNames).describe("Registered model-invocable command name to execute") : import_zod5.z.string().describe("Registered model-invocable command name to execute");
7901
+ return import_zod5.z.object({
7902
+ command: commandSchema,
7903
+ args: import_zod5.z.string().optional().describe("Arguments to pass to the command")
7904
+ });
7905
+ }
7906
+ function getCommandNames(deps) {
7907
+ if (deps.commandNames !== void 0) return deps.commandNames;
7908
+ if (deps.commandDescriptors === void 0) return void 0;
7909
+ return deps.commandDescriptors.map((descriptor) => normalizeModelCommandName(descriptor.name));
7910
+ }
7911
+ function formatCommandDescriptor(descriptor) {
7912
+ const commandName = normalizeModelCommandName(descriptor.name);
7913
+ const argumentHint = descriptor.argumentHint ? ` ${descriptor.argumentHint}` : "";
7914
+ return `- ${commandName}${argumentHint}: ${descriptor.description}`;
7915
+ }
7916
+ function createToolDescription(commandDescriptors) {
7917
+ const base = "Executes a registered model-invocable Robota command through the command registry. Accepted command names and argument grammar come from registered command descriptors.";
7918
+ if (commandDescriptors === void 0 || commandDescriptors.length === 0) return base;
7919
+ return [
7920
+ base,
7921
+ "Use the registered command descriptors below as the authority for when to call this tool.",
7922
+ "",
7923
+ "Registered model-invocable commands:",
7924
+ ...commandDescriptors.map(formatCommandDescriptor)
7925
+ ].join("\n");
7926
+ }
7927
+ function createCommandExecutionTool(deps) {
7928
+ const commandExecutionSchema = createCommandExecutionSchema(getCommandNames(deps));
7929
+ return (0, import_agent_tools6.createZodFunctionTool)(
7930
+ "ExecuteCommand",
7931
+ createToolDescription(deps.commandDescriptors),
7932
+ asZodSchema4(commandExecutionSchema),
7933
+ async (params) => {
7934
+ const args = commandExecutionSchema.parse(params);
7935
+ const command = normalizeModelCommandName(args.command);
7936
+ if (!deps.isModelInvocable(command)) {
7937
+ return JSON.stringify({
7938
+ success: false,
7939
+ command,
7940
+ error: `Command is not model-invocable: ${command}`
7941
+ });
7942
+ }
7943
+ return stringifyModelCommandResult(command, await deps.execute(command, args.args ?? ""));
7944
+ }
7945
+ );
7946
+ }
7947
+
6460
7948
  // src/subagents/index.ts
6461
7949
  var import_agent_runtime7 = require("@robota-sdk/agent-runtime");
6462
7950
  var import_agent_runtime8 = require("@robota-sdk/agent-runtime");
6463
7951
 
6464
- // src/index.ts
6465
- var import_agent_core10 = require("@robota-sdk/agent-core");
6466
-
6467
7952
  // src/permissions/permission-prompt.ts
6468
7953
  var import_chalk = __toESM(require("chalk"), 1);
6469
7954
  var PERMISSION_OPTIONS = ["Allow", "Deny"];
@@ -6483,9 +7968,6 @@ async function promptForApproval(terminal, toolName, toolArgs) {
6483
7968
  const selected = await terminal.select(PERMISSION_OPTIONS, ALLOW_INDEX);
6484
7969
  return selected === ALLOW_INDEX;
6485
7970
  }
6486
-
6487
- // src/index.ts
6488
- var import_agent_core11 = require("@robota-sdk/agent-core");
6489
7971
  // Annotate the CommonJS export names for ESM import in node:
6490
7972
  0 && (module.exports = {
6491
7973
  AUTO_COMPACT_THRESHOLD_SETTINGS_KEY,
@@ -6503,6 +7985,7 @@ var import_agent_core11 = require("@robota-sdk/agent-core");
6503
7985
  COST_COMMAND_DESCRIPTION,
6504
7986
  CommandRegistry,
6505
7987
  DEFAULT_AUTO_COMPACT_THRESHOLD,
7988
+ DEFAULT_BACKGROUND_TASK_LOG_PAGE_SIZE,
6506
7989
  DEFAULT_STATUS_LINE_COMMAND_SETTINGS,
6507
7990
  EXIT_COMMAND_DESCRIPTION,
6508
7991
  EditCheckpointStore,
@@ -6517,12 +8000,14 @@ var import_agent_core11 = require("@robota-sdk/agent-core");
6517
8000
  MEMORY_INDEX_MAX_LINES,
6518
8001
  MODEL_COMMAND_ARGUMENT_HINT,
6519
8002
  MODEL_COMMAND_DESCRIPTION,
8003
+ MODEL_COMMAND_TOOL_PREFIX,
6520
8004
  MarketplaceClient,
6521
8005
  PERMISSIONS_COMMAND_DESCRIPTION,
6522
8006
  PERMISSION_MODE_ARGUMENT_HINT,
6523
8007
  PERMISSION_MODE_COMMAND_DESCRIPTION,
6524
8008
  PLUGIN_COMMAND_ARGUMENT_HINT,
6525
8009
  PLUGIN_COMMAND_DESCRIPTION,
8010
+ PROVIDER_SAFE_TOOL_NAME_PATTERN,
6526
8011
  PluginCommandSource,
6527
8012
  PluginSettingsStore,
6528
8013
  ProjectMemoryStore,
@@ -6539,9 +8024,11 @@ var import_agent_core11 = require("@robota-sdk/agent-core");
6539
8024
  SkillCommandSource,
6540
8025
  SubagentManager,
6541
8026
  SystemCommandExecutor,
6542
- TRUST_TO_MODE,
8027
+ VALIDATE_SESSION_COMMAND_DESCRIPTION,
6543
8028
  VALID_PERMISSION_MODES,
6544
8029
  WorktreeSubagentRunner,
8030
+ addCommandContextReference,
8031
+ appendPrefixedLogLines,
6545
8032
  assembleSubagentPrompt,
6546
8033
  buildBackgroundCommandSubcommands,
6547
8034
  buildLanguageCommandSubcommands,
@@ -6549,26 +8036,35 @@ var import_agent_core11 = require("@robota-sdk/agent-core");
6549
8036
  buildModelCommandSubcommands,
6550
8037
  buildPermissionModeSubcommands,
6551
8038
  buildPluginCommandSubcommands,
8039
+ buildPromptWithFileReferences,
6552
8040
  buildProviderProfile,
6553
8041
  buildProviderSetupPatch,
6554
8042
  buildRewindCommandSubcommands,
6555
- buildSkillPrompt,
6556
8043
  buildStatusLineCommandSubcommands,
6557
8044
  cancelCommandBackgroundTask,
6558
- chatEntryToMessage,
8045
+ clearCommandContextReferences,
8046
+ clearContextReferences,
6559
8047
  clearConversationHistory,
6560
8048
  closeCommandBackgroundTask,
6561
8049
  compactCommandContext,
6562
8050
  createAgentTool,
6563
8051
  createBackgroundProcessTool,
8052
+ createBackgroundTaskLogPage,
6564
8053
  createBuiltinCommandModule,
6565
8054
  createCommandExecutionTool,
6566
8055
  createCommandMemoryStores,
6567
8056
  createCommandPendingMemoryStore,
6568
8057
  createCommandProjectMemoryStore,
8058
+ createContextReferenceItem,
6569
8059
  createDefaultTools,
8060
+ createLimitedOutputCapture,
8061
+ createModelCommandToolProjection,
6570
8062
  createPluginRegistryReloadRequestedEffect,
6571
8063
  createPluginTuiRequestedEffect,
8064
+ createProjectSessionStore,
8065
+ createProjectedCommandExecutionTools,
8066
+ createPromptFileReferenceHistoryEntry,
8067
+ createProviderSafeModelCommandToolName,
6572
8068
  createProviderSetupFlow,
6573
8069
  createQuery,
6574
8070
  createSessionExitRequestedEffect,
@@ -6578,48 +8074,57 @@ var import_agent_core11 = require("@robota-sdk/agent-core");
6578
8074
  createSubagentSession,
6579
8075
  createSystemCommands,
6580
8076
  createWorktreeSubagentRunner,
8077
+ deleteProviderProfile,
6581
8078
  discoverTaskFiles,
6582
- evaluatePermission,
6583
8079
  evaluateReversibleToolSafety,
6584
8080
  executeSkill,
6585
8081
  formatCommandBackgroundTask,
6586
8082
  formatCommandBackgroundTaskList,
6587
8083
  formatCommandHelpMessage,
6588
8084
  formatCommandPermissionsMessage,
8085
+ formatCommandSessionReplayValidationReport,
6589
8086
  formatEnvReference,
6590
8087
  formatInvalidPermissionModeMessage,
6591
8088
  formatLanguageUsageMessage,
8089
+ formatModelCommandUsageMessage,
8090
+ formatModelCommandUsageMessageAsync,
8091
+ formatProjectedModelCommandToolPromptDescription,
8092
+ formatPromptFileReferenceDiagnostics,
6592
8093
  formatProviderSetupChoiceLabel,
8094
+ formatProviderSetupHelpLinks,
6593
8095
  formatProviderSetupPromptLabel,
6594
8096
  formatProviderSetupSelectionPrompt,
6595
8097
  formatTaskContext,
6596
8098
  getBackgroundTaskTransitions,
6597
8099
  getBuiltInAgent,
6598
8100
  getForkWorkerSuffix,
6599
- getMessagesForAPI,
6600
8101
  getProviderSetupStep,
6601
8102
  getSubagentSuffix,
8103
+ hasBlockingPromptFileReferenceDiagnostics,
6602
8104
  hasSensitiveCommandMemoryContent,
6603
8105
  hasUsableSecretReference,
6604
8106
  inspectCommandEditCheckpoint,
6605
- isChatEntry,
6606
8107
  isCommandMemoryType,
6607
8108
  isEnvReference,
6608
8109
  isMemoryType,
6609
8110
  isPermissionMode,
6610
8111
  isStatusLineCommandSettingsPatch,
6611
8112
  isTerminalBackgroundTaskStatus,
8113
+ listActiveContextReferences,
6612
8114
  listCommandBackgroundTasks,
8115
+ listCommandContextReferences,
6613
8116
  listCommandEditCheckpoints,
6614
8117
  listCommandSessionAllowedTools,
6615
8118
  listCommandUsedMemoryReferences,
8119
+ listResumableSessionSummaries,
6616
8120
  loadTaskContext,
6617
8121
  mergeProviderPatch,
6618
- messageToHistoryEntry,
8122
+ normalizeModelCommandName,
6619
8123
  parseCommandBackgroundLogCursor,
6620
8124
  parseFrontmatter,
6621
8125
  parseLanguageArgument,
6622
8126
  parsePermissionModeArgument,
8127
+ parsePromptFileReferences,
6623
8128
  parseSessionNameArgument,
6624
8129
  parseTaskFile,
6625
8130
  planSelfHostingVerification,
@@ -6636,30 +8141,43 @@ var import_agent_core11 = require("@robota-sdk/agent-core");
6636
8141
  readCommandSessionInfo,
6637
8142
  readCurrentGitBranch,
6638
8143
  recordCommandMemoryEvent,
8144
+ removeCommandContextReference,
8145
+ removeContextReference,
6639
8146
  resetAutoCompactThresholdSetting,
8147
+ resolveActiveProviderModelCatalog,
8148
+ resolveActiveProviderModelCatalogState,
6640
8149
  resolveEnvReference,
8150
+ resolveLatestSessionId,
6641
8151
  resolvePermissionModeAdapter,
6642
8152
  resolvePluginCommandAdapter,
8153
+ resolvePromptFileReferencePaths,
8154
+ resolvePromptFileReferences,
6643
8155
  resolveProviderSetupSelection,
8156
+ resolveSessionIdByIdOrName,
6644
8157
  resolveSubagentLogDir,
6645
8158
  restoreCommandEditCheckpoint,
6646
8159
  retrieveAgentToolDeps,
6647
8160
  rollbackCommandEditCheckpoint,
6648
- runHooks,
6649
8161
  runProviderSetupPromptFlow,
8162
+ sanitizeProviderProfileName,
6650
8163
  selectRelevantTasks,
6651
8164
  setCommandAutoCompactThreshold,
6652
8165
  setCurrentProvider,
6653
8166
  storeAgentToolDeps,
6654
8167
  submitProviderSetupValue,
6655
8168
  substituteVariables,
8169
+ suggestProviderProfileName,
6656
8170
  summarizeBackgroundJobGroup,
6657
8171
  testProviderProfileCommand,
8172
+ toContextReferenceRecords,
8173
+ toPromptFileReferenceRecords,
6658
8174
  transitionBackgroundTaskStatus,
6659
8175
  transitionSelfHostingLoop,
6660
8176
  updateTaskFileStatus,
8177
+ upsertContextReference,
6661
8178
  upsertProviderProfile,
6662
8179
  userPaths,
8180
+ validateCommandSessionReplayLog,
6663
8181
  validateProviderProfile,
6664
8182
  validateProviderSetupValue,
6665
8183
  wrapEditCheckpointTools,