@robota-sdk/agent-sdk 3.0.0-beta.33 → 3.0.0-beta.35

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.
@@ -32,16 +32,21 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  AgentExecutor: () => AgentExecutor,
34
34
  BUILT_IN_AGENTS: () => BUILT_IN_AGENTS,
35
+ BuiltinCommandSource: () => BuiltinCommandSource,
35
36
  BundlePluginInstaller: () => BundlePluginInstaller,
36
37
  BundlePluginLoader: () => BundlePluginLoader,
38
+ CommandRegistry: () => CommandRegistry,
37
39
  DEFAULT_TOOL_DESCRIPTIONS: () => DEFAULT_TOOL_DESCRIPTIONS,
38
- FileSessionLogger: () => import_agent_sessions5.FileSessionLogger,
40
+ FileSessionLogger: () => import_agent_sessions6.FileSessionLogger,
41
+ InteractiveSession: () => InteractiveSession,
39
42
  MarketplaceClient: () => MarketplaceClient,
40
43
  PluginSettingsStore: () => PluginSettingsStore,
41
44
  PromptExecutor: () => PromptExecutor,
42
- Session: () => import_agent_sessions4.Session,
43
- SessionStore: () => import_agent_sessions6.SessionStore,
44
- SilentSessionLogger: () => import_agent_sessions5.SilentSessionLogger,
45
+ Session: () => import_agent_sessions5.Session,
46
+ SessionStore: () => import_agent_sessions7.SessionStore,
47
+ SilentSessionLogger: () => import_agent_sessions6.SilentSessionLogger,
48
+ SkillCommandSource: () => SkillCommandSource,
49
+ SystemCommandExecutor: () => SystemCommandExecutor,
45
50
  TRUST_TO_MODE: () => import_agent_core.TRUST_TO_MODE,
46
51
  assembleSubagentPrompt: () => assembleSubagentPrompt,
47
52
  bashTool: () => import_agent_tools3.bashTool,
@@ -52,9 +57,10 @@ __export(index_exports, {
52
57
  createSession: () => createSession,
53
58
  createSubagentLogger: () => createSubagentLogger,
54
59
  createSubagentSession: () => createSubagentSession,
60
+ createSystemCommands: () => createSystemCommands,
55
61
  detectProject: () => detectProject,
56
62
  editTool: () => import_agent_tools6.editTool,
57
- evaluatePermission: () => import_agent_core2.evaluatePermission,
63
+ evaluatePermission: () => import_agent_core4.evaluatePermission,
58
64
  getBuiltInAgent: () => getBuiltInAgent,
59
65
  getForkWorkerSuffix: () => getForkWorkerSuffix,
60
66
  getSubagentSuffix: () => getSubagentSuffix,
@@ -62,13 +68,14 @@ __export(index_exports, {
62
68
  grepTool: () => import_agent_tools8.grepTool,
63
69
  loadConfig: () => loadConfig,
64
70
  loadContext: () => loadContext,
71
+ parseFrontmatter: () => parseFrontmatter2,
65
72
  projectPaths: () => projectPaths,
66
73
  promptForApproval: () => promptForApproval,
67
74
  query: () => query,
68
75
  readTool: () => import_agent_tools4.readTool,
69
76
  resolveSubagentLogDir: () => resolveSubagentLogDir,
70
77
  retrieveAgentToolDeps: () => retrieveAgentToolDeps,
71
- runHooks: () => import_agent_core3.runHooks,
78
+ runHooks: () => import_agent_core5.runHooks,
72
79
  storeAgentToolDeps: () => storeAgentToolDeps,
73
80
  userPaths: () => userPaths,
74
81
  writeTool: () => import_agent_tools5.writeTool
@@ -753,9 +760,9 @@ function resolveSubagentLogDir(parentSessionId, baseLogsDir) {
753
760
  }
754
761
 
755
762
  // src/index.ts
756
- var import_agent_sessions4 = require("@robota-sdk/agent-sessions");
757
763
  var import_agent_sessions5 = require("@robota-sdk/agent-sessions");
758
764
  var import_agent_sessions6 = require("@robota-sdk/agent-sessions");
765
+ var import_agent_sessions7 = require("@robota-sdk/agent-sessions");
759
766
 
760
767
  // src/config/config-loader.ts
761
768
  var import_fs = require("fs");
@@ -1150,8 +1157,8 @@ async function query(prompt, options) {
1150
1157
  }
1151
1158
 
1152
1159
  // src/index.ts
1153
- var import_agent_core2 = require("@robota-sdk/agent-core");
1154
- var import_agent_core3 = require("@robota-sdk/agent-core");
1160
+ var import_agent_core4 = require("@robota-sdk/agent-core");
1161
+ var import_agent_core5 = require("@robota-sdk/agent-core");
1155
1162
 
1156
1163
  // src/paths.ts
1157
1164
  var import_node_path3 = require("path");
@@ -1968,6 +1975,710 @@ var MarketplaceClient = class {
1968
1975
  }
1969
1976
  };
1970
1977
 
1978
+ // src/commands/command-registry.ts
1979
+ var CommandRegistry = class {
1980
+ sources = [];
1981
+ addSource(source) {
1982
+ this.sources.push(source);
1983
+ }
1984
+ /** Get all commands, optionally filtered by prefix */
1985
+ getCommands(filter) {
1986
+ const all = [];
1987
+ for (const source of this.sources) {
1988
+ all.push(...source.getCommands());
1989
+ }
1990
+ if (!filter) return all;
1991
+ const lower = filter.toLowerCase();
1992
+ return all.filter((cmd) => cmd.name.toLowerCase().startsWith(lower));
1993
+ }
1994
+ /** Resolve a short name to its fully qualified plugin:name form */
1995
+ resolveQualifiedName(shortName) {
1996
+ const matches = this.getCommands().filter(
1997
+ (c) => c.source === "plugin" && c.name.includes(":") && c.name.endsWith(`:${shortName}`)
1998
+ );
1999
+ if (matches.length !== 1) return null;
2000
+ return matches[0].name;
2001
+ }
2002
+ /** Get subcommands for a specific command */
2003
+ getSubcommands(commandName) {
2004
+ const lower = commandName.toLowerCase();
2005
+ for (const source of this.sources) {
2006
+ for (const cmd of source.getCommands()) {
2007
+ if (cmd.name.toLowerCase() === lower && cmd.subcommands) {
2008
+ return cmd.subcommands;
2009
+ }
2010
+ }
2011
+ }
2012
+ return [];
2013
+ }
2014
+ };
2015
+
2016
+ // src/commands/builtin-source.ts
2017
+ var import_agent_core2 = require("@robota-sdk/agent-core");
2018
+ function buildModelSubcommands() {
2019
+ const seen = /* @__PURE__ */ new Set();
2020
+ const commands = [];
2021
+ for (const model of Object.values(import_agent_core2.CLAUDE_MODELS)) {
2022
+ if (seen.has(model.name)) continue;
2023
+ seen.add(model.name);
2024
+ commands.push({
2025
+ name: model.id,
2026
+ description: `${model.name} (${(0, import_agent_core2.formatTokenCount)(model.contextWindow).toUpperCase()})`,
2027
+ source: "builtin"
2028
+ });
2029
+ }
2030
+ return commands;
2031
+ }
2032
+ function createBuiltinCommands() {
2033
+ return [
2034
+ { name: "help", description: "Show available commands", source: "builtin" },
2035
+ { name: "clear", description: "Clear conversation history", source: "builtin" },
2036
+ {
2037
+ name: "mode",
2038
+ description: "Permission mode",
2039
+ source: "builtin",
2040
+ subcommands: [
2041
+ { name: "plan", description: "Plan only, no execution", source: "builtin" },
2042
+ { name: "default", description: "Ask before risky actions", source: "builtin" },
2043
+ { name: "acceptEdits", description: "Auto-approve file edits", source: "builtin" },
2044
+ { name: "bypassPermissions", description: "Skip all permission checks", source: "builtin" }
2045
+ ]
2046
+ },
2047
+ {
2048
+ name: "model",
2049
+ description: "Select AI model",
2050
+ source: "builtin",
2051
+ subcommands: buildModelSubcommands()
2052
+ },
2053
+ {
2054
+ name: "language",
2055
+ description: "Set response language",
2056
+ source: "builtin",
2057
+ subcommands: [
2058
+ { name: "ko", description: "Korean", source: "builtin" },
2059
+ { name: "en", description: "English", source: "builtin" },
2060
+ { name: "ja", description: "Japanese", source: "builtin" },
2061
+ { name: "zh", description: "Chinese", source: "builtin" }
2062
+ ]
2063
+ },
2064
+ { name: "compact", description: "Compress context window", source: "builtin" },
2065
+ { name: "cost", description: "Show session info", source: "builtin" },
2066
+ { name: "context", description: "Context window info", source: "builtin" },
2067
+ { name: "permissions", description: "Permission rules", source: "builtin" },
2068
+ { name: "plugin", description: "Manage plugins", source: "builtin" },
2069
+ { name: "reload-plugins", description: "Reload all plugin resources", source: "builtin" },
2070
+ { name: "reset", description: "Delete settings and exit", source: "builtin" },
2071
+ { name: "exit", description: "Exit CLI", source: "builtin" }
2072
+ ];
2073
+ }
2074
+ var BuiltinCommandSource = class {
2075
+ name = "builtin";
2076
+ commands;
2077
+ constructor() {
2078
+ this.commands = createBuiltinCommands();
2079
+ }
2080
+ getCommands() {
2081
+ return this.commands;
2082
+ }
2083
+ };
2084
+
2085
+ // src/commands/skill-source.ts
2086
+ var import_node_fs7 = require("fs");
2087
+ var import_node_path8 = require("path");
2088
+ var import_node_os3 = require("os");
2089
+ var BOOLEAN_KEYS = /* @__PURE__ */ new Set(["disable-model-invocation", "user-invocable"]);
2090
+ var LIST_KEYS2 = /* @__PURE__ */ new Set(["allowed-tools"]);
2091
+ function kebabToCamel(key) {
2092
+ return key.replace(/-([a-z])/g, (_match, letter) => letter.toUpperCase());
2093
+ }
2094
+ function parseFrontmatter2(content) {
2095
+ const lines = content.split("\n");
2096
+ if (lines[0]?.trim() !== "---") return null;
2097
+ const result = {};
2098
+ for (let i = 1; i < lines.length; i++) {
2099
+ const line = lines[i];
2100
+ if (line.trim() === "---") break;
2101
+ const match = line.match(/^([a-z][a-z0-9-]*):\s*(.+)/);
2102
+ if (!match) continue;
2103
+ const key = match[1];
2104
+ const rawValue = match[2].trim();
2105
+ const camelKey = kebabToCamel(key);
2106
+ if (BOOLEAN_KEYS.has(key)) {
2107
+ result[camelKey] = rawValue === "true";
2108
+ } else if (LIST_KEYS2.has(key)) {
2109
+ result[camelKey] = rawValue.split(",").map((s) => s.trim());
2110
+ } else {
2111
+ result[camelKey] = rawValue;
2112
+ }
2113
+ }
2114
+ return Object.keys(result).length > 0 ? result : null;
2115
+ }
2116
+ function buildCommand(frontmatter, content, fallbackName) {
2117
+ const cmd = {
2118
+ name: frontmatter?.name ?? fallbackName,
2119
+ description: frontmatter?.description ?? `Skill: ${fallbackName}`,
2120
+ source: "skill",
2121
+ skillContent: content
2122
+ };
2123
+ if (frontmatter?.argumentHint !== void 0) cmd.argumentHint = frontmatter.argumentHint;
2124
+ if (frontmatter?.disableModelInvocation !== void 0)
2125
+ cmd.disableModelInvocation = frontmatter.disableModelInvocation;
2126
+ if (frontmatter?.userInvocable !== void 0) cmd.userInvocable = frontmatter.userInvocable;
2127
+ if (frontmatter?.allowedTools !== void 0) cmd.allowedTools = frontmatter.allowedTools;
2128
+ if (frontmatter?.model !== void 0) cmd.model = frontmatter.model;
2129
+ if (frontmatter?.effort !== void 0) cmd.effort = frontmatter.effort;
2130
+ if (frontmatter?.context !== void 0) cmd.context = frontmatter.context;
2131
+ if (frontmatter?.agent !== void 0) cmd.agent = frontmatter.agent;
2132
+ return cmd;
2133
+ }
2134
+ function scanSkillsDir(skillsDir) {
2135
+ if (!(0, import_node_fs7.existsSync)(skillsDir)) return [];
2136
+ const commands = [];
2137
+ const entries = (0, import_node_fs7.readdirSync)(skillsDir, { withFileTypes: true });
2138
+ for (const entry of entries) {
2139
+ if (!entry.isDirectory()) continue;
2140
+ const skillFile = (0, import_node_path8.join)(skillsDir, entry.name, "SKILL.md");
2141
+ if (!(0, import_node_fs7.existsSync)(skillFile)) continue;
2142
+ const content = (0, import_node_fs7.readFileSync)(skillFile, "utf-8");
2143
+ const frontmatter = parseFrontmatter2(content);
2144
+ commands.push(buildCommand(frontmatter, content, entry.name));
2145
+ }
2146
+ return commands;
2147
+ }
2148
+ function scanCommandsDir(commandsDir) {
2149
+ if (!(0, import_node_fs7.existsSync)(commandsDir)) return [];
2150
+ const commands = [];
2151
+ const entries = (0, import_node_fs7.readdirSync)(commandsDir, { withFileTypes: true });
2152
+ for (const entry of entries) {
2153
+ if (!entry.isFile() || !entry.name.endsWith(".md")) continue;
2154
+ const filePath = (0, import_node_path8.join)(commandsDir, entry.name);
2155
+ const content = (0, import_node_fs7.readFileSync)(filePath, "utf-8");
2156
+ const frontmatter = parseFrontmatter2(content);
2157
+ const fallbackName = (0, import_node_path8.basename)(entry.name, ".md");
2158
+ commands.push(buildCommand(frontmatter, content, fallbackName));
2159
+ }
2160
+ return commands;
2161
+ }
2162
+ var SkillCommandSource = class {
2163
+ name = "skill";
2164
+ cwd;
2165
+ home;
2166
+ cachedCommands = null;
2167
+ constructor(cwd, home) {
2168
+ this.cwd = cwd;
2169
+ this.home = home ?? (0, import_node_os3.homedir)();
2170
+ }
2171
+ getCommands() {
2172
+ if (this.cachedCommands) return this.cachedCommands;
2173
+ const sources = [
2174
+ scanSkillsDir((0, import_node_path8.join)(this.cwd, ".claude", "skills")),
2175
+ scanCommandsDir((0, import_node_path8.join)(this.cwd, ".claude", "commands")),
2176
+ scanSkillsDir((0, import_node_path8.join)(this.home, ".robota", "skills")),
2177
+ scanSkillsDir((0, import_node_path8.join)(this.cwd, ".agents", "skills"))
2178
+ ];
2179
+ const seen = /* @__PURE__ */ new Set();
2180
+ const merged = [];
2181
+ for (const commands of sources) {
2182
+ for (const cmd of commands) {
2183
+ if (!seen.has(cmd.name)) {
2184
+ seen.add(cmd.name);
2185
+ merged.push(cmd);
2186
+ }
2187
+ }
2188
+ }
2189
+ this.cachedCommands = merged;
2190
+ return this.cachedCommands;
2191
+ }
2192
+ getModelInvocableSkills() {
2193
+ return this.getCommands().filter((cmd) => cmd.disableModelInvocation !== true);
2194
+ }
2195
+ getUserInvocableSkills() {
2196
+ return this.getCommands().filter((cmd) => cmd.userInvocable !== false);
2197
+ }
2198
+ };
2199
+
2200
+ // src/commands/system-command.ts
2201
+ var VALID_MODES = ["plan", "default", "acceptEdits", "bypassPermissions"];
2202
+ function createSystemCommands() {
2203
+ return [
2204
+ {
2205
+ name: "help",
2206
+ description: "Show available commands",
2207
+ execute: (_session, _args) => ({
2208
+ message: [
2209
+ "Available commands:",
2210
+ " help \u2014 Show this help",
2211
+ " clear \u2014 Clear conversation",
2212
+ " compact [instr] \u2014 Compact context (optional focus instructions)",
2213
+ " mode [m] \u2014 Show/change permission mode",
2214
+ " model <id> \u2014 Change AI model",
2215
+ " language <code> \u2014 Set response language (ko, en, ja, zh)",
2216
+ " cost \u2014 Show session info",
2217
+ " context \u2014 Context window info",
2218
+ " permissions \u2014 Permission rules",
2219
+ " reset \u2014 Delete settings and exit"
2220
+ ].join("\n"),
2221
+ success: true
2222
+ })
2223
+ },
2224
+ {
2225
+ name: "clear",
2226
+ description: "Clear conversation history",
2227
+ execute: (session, _args) => {
2228
+ const underlying = session.getSession();
2229
+ underlying.clearHistory();
2230
+ return { message: "Conversation cleared.", success: true };
2231
+ }
2232
+ },
2233
+ {
2234
+ name: "compact",
2235
+ description: "Compress context window",
2236
+ execute: async (session, args) => {
2237
+ const underlying = session.getSession();
2238
+ const instructions = args.trim() || void 0;
2239
+ const before = underlying.getContextState().usedPercentage;
2240
+ await underlying.compact(instructions);
2241
+ const after = underlying.getContextState().usedPercentage;
2242
+ return {
2243
+ message: `Context compacted: ${Math.round(before)}% -> ${Math.round(after)}%`,
2244
+ success: true,
2245
+ data: { before, after }
2246
+ };
2247
+ }
2248
+ },
2249
+ {
2250
+ name: "mode",
2251
+ description: "Show/change permission mode",
2252
+ execute: (session, args) => {
2253
+ const underlying = session.getSession();
2254
+ const arg = args.trim().split(/\s+/)[0];
2255
+ if (!arg) {
2256
+ return {
2257
+ message: `Current mode: ${underlying.getPermissionMode()}`,
2258
+ success: true,
2259
+ data: { mode: underlying.getPermissionMode() }
2260
+ };
2261
+ }
2262
+ if (VALID_MODES.includes(arg)) {
2263
+ underlying.setPermissionMode(arg);
2264
+ return {
2265
+ message: `Permission mode set to: ${arg}`,
2266
+ success: true,
2267
+ data: { mode: arg }
2268
+ };
2269
+ }
2270
+ return {
2271
+ message: `Invalid mode. Valid: ${VALID_MODES.join(" | ")}`,
2272
+ success: false
2273
+ };
2274
+ }
2275
+ },
2276
+ {
2277
+ name: "model",
2278
+ description: "Change AI model",
2279
+ execute: (_session, args) => {
2280
+ const modelId = args.trim().split(/\s+/)[0];
2281
+ if (!modelId) {
2282
+ return { message: "Usage: model <model-id>", success: false };
2283
+ }
2284
+ return {
2285
+ message: `Model change requested: ${modelId}`,
2286
+ success: true,
2287
+ data: { modelId }
2288
+ };
2289
+ }
2290
+ },
2291
+ {
2292
+ name: "language",
2293
+ description: "Set response language",
2294
+ execute: (_session, args) => {
2295
+ const lang = args.trim().split(/\s+/)[0];
2296
+ if (!lang) {
2297
+ return { message: "Usage: language <code> (e.g., ko, en, ja, zh)", success: false };
2298
+ }
2299
+ return {
2300
+ message: `Language set to "${lang}".`,
2301
+ success: true,
2302
+ data: { language: lang }
2303
+ };
2304
+ }
2305
+ },
2306
+ {
2307
+ name: "cost",
2308
+ description: "Show session info",
2309
+ execute: (session, _args) => {
2310
+ const underlying = session.getSession();
2311
+ const sessionId = underlying.getSessionId();
2312
+ const messageCount = underlying.getMessageCount();
2313
+ return {
2314
+ message: `Session: ${sessionId}
2315
+ Messages: ${messageCount}`,
2316
+ success: true,
2317
+ data: { sessionId, messageCount }
2318
+ };
2319
+ }
2320
+ },
2321
+ {
2322
+ name: "context",
2323
+ description: "Context window info",
2324
+ execute: (session, _args) => {
2325
+ const ctx = session.getContextState();
2326
+ return {
2327
+ message: `Context: ${ctx.usedTokens.toLocaleString()} / ${ctx.maxTokens.toLocaleString()} tokens (${Math.round(ctx.usedPercentage)}%)`,
2328
+ success: true,
2329
+ data: {
2330
+ usedTokens: ctx.usedTokens,
2331
+ maxTokens: ctx.maxTokens,
2332
+ percentage: ctx.usedPercentage
2333
+ }
2334
+ };
2335
+ }
2336
+ },
2337
+ {
2338
+ name: "permissions",
2339
+ description: "Show permission rules",
2340
+ execute: (session, _args) => {
2341
+ const underlying = session.getSession();
2342
+ const mode = underlying.getPermissionMode();
2343
+ const sessionAllowed = underlying.getSessionAllowedTools();
2344
+ const lines = [`Permission mode: ${mode}`];
2345
+ if (sessionAllowed.length > 0) {
2346
+ lines.push(`Session-approved tools: ${sessionAllowed.join(", ")}`);
2347
+ } else {
2348
+ lines.push("No session-approved tools.");
2349
+ }
2350
+ return {
2351
+ message: lines.join("\n"),
2352
+ success: true,
2353
+ data: { mode, sessionAllowed }
2354
+ };
2355
+ }
2356
+ },
2357
+ {
2358
+ name: "reset",
2359
+ description: "Delete settings",
2360
+ execute: (_session, _args) => {
2361
+ return {
2362
+ message: "Reset requested.",
2363
+ success: true,
2364
+ data: { resetRequested: true }
2365
+ };
2366
+ }
2367
+ }
2368
+ ];
2369
+ }
2370
+ var SystemCommandExecutor = class {
2371
+ commands;
2372
+ constructor(commands) {
2373
+ this.commands = /* @__PURE__ */ new Map();
2374
+ for (const cmd of commands ?? createSystemCommands()) {
2375
+ this.commands.set(cmd.name, cmd);
2376
+ }
2377
+ }
2378
+ /** Register an additional command. */
2379
+ register(command) {
2380
+ this.commands.set(command.name, command);
2381
+ }
2382
+ /** Execute a command by name. Returns null if command not found. */
2383
+ async execute(name, session, args) {
2384
+ const cmd = this.commands.get(name);
2385
+ if (!cmd) return null;
2386
+ return await cmd.execute(session, args);
2387
+ }
2388
+ /** List all registered commands. */
2389
+ listCommands() {
2390
+ return [...this.commands.values()];
2391
+ }
2392
+ /** Check if a command exists. */
2393
+ hasCommand(name) {
2394
+ return this.commands.has(name);
2395
+ }
2396
+ };
2397
+
2398
+ // src/interactive/interactive-session.ts
2399
+ var import_agent_sessions4 = require("@robota-sdk/agent-sessions");
2400
+ var import_agent_core3 = require("@robota-sdk/agent-core");
2401
+ var import_node_crypto = require("crypto");
2402
+ var TOOL_ARG_DISPLAY_MAX = 80;
2403
+ var TAIL_KEEP = 30;
2404
+ var MAX_COMPLETED_TOOLS = 50;
2405
+ var STREAMING_FLUSH_INTERVAL_MS = 16;
2406
+ var InteractiveSession = class {
2407
+ session;
2408
+ listeners = /* @__PURE__ */ new Map();
2409
+ // Streaming state
2410
+ streamingText = "";
2411
+ flushTimer = null;
2412
+ // Tool state
2413
+ activeTools = [];
2414
+ // Execution state
2415
+ executing = false;
2416
+ pendingPrompt = null;
2417
+ // Display messages (what clients render — not the raw session history)
2418
+ messages = [];
2419
+ constructor(options) {
2420
+ if (options.session) {
2421
+ this.session = options.session;
2422
+ } else {
2423
+ const cwd = options.cwd ?? process.cwd();
2424
+ const paths = projectPaths(cwd);
2425
+ this.session = createSession({
2426
+ config: options.config,
2427
+ context: options.context,
2428
+ projectInfo: options.projectInfo,
2429
+ sessionStore: options.sessionStore,
2430
+ permissionMode: options.permissionMode,
2431
+ maxTurns: options.maxTurns,
2432
+ terminal: NOOP_TERMINAL,
2433
+ sessionLogger: new import_agent_sessions4.FileSessionLogger(paths.logs),
2434
+ permissionHandler: options.permissionHandler,
2435
+ onTextDelta: (delta) => this.handleTextDelta(delta),
2436
+ onToolExecution: (event) => this.handleToolExecution(event)
2437
+ });
2438
+ }
2439
+ }
2440
+ // ── Event system ──────────────────────────────────────────────
2441
+ on(event, handler) {
2442
+ if (!this.listeners.has(event)) {
2443
+ this.listeners.set(event, /* @__PURE__ */ new Set());
2444
+ }
2445
+ this.listeners.get(event).add(handler);
2446
+ }
2447
+ off(event, handler) {
2448
+ this.listeners.get(event)?.delete(handler);
2449
+ }
2450
+ emit(event, ...args) {
2451
+ const handlers = this.listeners.get(event);
2452
+ if (handlers) {
2453
+ for (const handler of handlers) {
2454
+ handler(...args);
2455
+ }
2456
+ }
2457
+ }
2458
+ // ── Public API ────────────────────────────────────────────────
2459
+ /** Submit a prompt. Queues if already executing (max 1 queued). */
2460
+ async submit(input) {
2461
+ if (this.executing) {
2462
+ this.pendingPrompt = input;
2463
+ return;
2464
+ }
2465
+ await this.executePrompt(input);
2466
+ }
2467
+ /** Abort current execution and clear queue. */
2468
+ abort() {
2469
+ this.pendingPrompt = null;
2470
+ this.session.abort();
2471
+ }
2472
+ /** Cancel queued prompt without aborting current execution. */
2473
+ cancelQueue() {
2474
+ this.pendingPrompt = null;
2475
+ }
2476
+ isExecuting() {
2477
+ return this.executing;
2478
+ }
2479
+ getPendingPrompt() {
2480
+ return this.pendingPrompt;
2481
+ }
2482
+ getMessages() {
2483
+ return this.messages;
2484
+ }
2485
+ getStreamingText() {
2486
+ return this.streamingText;
2487
+ }
2488
+ getActiveTools() {
2489
+ return this.activeTools;
2490
+ }
2491
+ getContextState() {
2492
+ return this.session.getContextState();
2493
+ }
2494
+ getSession() {
2495
+ return this.session;
2496
+ }
2497
+ // ── Execution ─────────────────────────────────────────────────
2498
+ async executePrompt(input) {
2499
+ this.executing = true;
2500
+ this.clearStreaming();
2501
+ this.emit("thinking", true);
2502
+ this.messages.push((0, import_agent_core3.createUserMessage)(input));
2503
+ const historyBefore = this.session.getHistory().length;
2504
+ try {
2505
+ const response = await this.session.run(input);
2506
+ this.flushStreaming();
2507
+ this.clearStreaming();
2508
+ const result = this.buildResult(response || "(empty response)", historyBefore);
2509
+ this.messages.push((0, import_agent_core3.createAssistantMessage)(result.response));
2510
+ this.emit("complete", result);
2511
+ this.emit("context_update", this.getContextState());
2512
+ } catch (err) {
2513
+ this.flushStreaming();
2514
+ this.clearStreaming();
2515
+ if (isAbortError(err)) {
2516
+ const result = this.buildInterruptedResult(historyBefore);
2517
+ if (result.response) {
2518
+ this.messages.push((0, import_agent_core3.createAssistantMessage)(result.response));
2519
+ }
2520
+ this.messages.push((0, import_agent_core3.createSystemMessage)("Interrupted by user."));
2521
+ this.emit("interrupted", result);
2522
+ } else {
2523
+ const errMsg = err instanceof Error ? err.message : String(err);
2524
+ this.messages.push((0, import_agent_core3.createSystemMessage)(`Error: ${errMsg}`));
2525
+ this.emit("error", err instanceof Error ? err : new Error(errMsg));
2526
+ }
2527
+ } finally {
2528
+ this.executing = false;
2529
+ this.emit("thinking", false);
2530
+ if (this.pendingPrompt) {
2531
+ const queued = this.pendingPrompt;
2532
+ this.pendingPrompt = null;
2533
+ setTimeout(() => this.executePrompt(queued), 0);
2534
+ }
2535
+ }
2536
+ }
2537
+ // ── Streaming callbacks ───────────────────────────────────────
2538
+ handleTextDelta(delta) {
2539
+ this.streamingText += delta;
2540
+ this.emit("text_delta", delta);
2541
+ if (!this.flushTimer) {
2542
+ this.flushTimer = setTimeout(() => {
2543
+ this.flushTimer = null;
2544
+ }, STREAMING_FLUSH_INTERVAL_MS);
2545
+ }
2546
+ }
2547
+ handleToolExecution(event) {
2548
+ if (event.type === "start") {
2549
+ const firstArg = extractFirstArg(event.toolArgs);
2550
+ const state = {
2551
+ toolName: event.toolName,
2552
+ firstArg,
2553
+ isRunning: true
2554
+ };
2555
+ this.activeTools.push(state);
2556
+ this.emit("tool_start", state);
2557
+ } else {
2558
+ const result = event.denied ? "denied" : event.success === false ? "error" : "success";
2559
+ const idx = this.activeTools.findIndex((t) => t.toolName === event.toolName && t.isRunning);
2560
+ if (idx !== -1) {
2561
+ const finished = {
2562
+ ...this.activeTools[idx],
2563
+ isRunning: false,
2564
+ result
2565
+ };
2566
+ this.activeTools[idx] = finished;
2567
+ this.trimCompletedTools();
2568
+ this.emit("tool_end", finished);
2569
+ }
2570
+ }
2571
+ }
2572
+ // ── Helpers ───────────────────────────────────────────────────
2573
+ clearStreaming() {
2574
+ this.streamingText = "";
2575
+ this.activeTools = [];
2576
+ if (this.flushTimer) {
2577
+ clearTimeout(this.flushTimer);
2578
+ this.flushTimer = null;
2579
+ }
2580
+ }
2581
+ flushStreaming() {
2582
+ if (this.flushTimer) {
2583
+ clearTimeout(this.flushTimer);
2584
+ this.flushTimer = null;
2585
+ }
2586
+ }
2587
+ buildResult(response, historyBefore) {
2588
+ const toolSummaries = this.extractToolSummaries(historyBefore);
2589
+ if (toolSummaries.length > 0) {
2590
+ this.messages.push(
2591
+ (0, import_agent_core3.createToolMessage)(JSON.stringify(toolSummaries), {
2592
+ toolCallId: (0, import_node_crypto.randomUUID)(),
2593
+ name: `${toolSummaries.length} tools`
2594
+ })
2595
+ );
2596
+ }
2597
+ return {
2598
+ response,
2599
+ messages: this.messages,
2600
+ toolSummaries,
2601
+ contextState: this.getContextState()
2602
+ };
2603
+ }
2604
+ buildInterruptedResult(historyBefore) {
2605
+ const history = this.session.getHistory();
2606
+ const toolSummaries = this.extractToolSummaries(historyBefore);
2607
+ if (toolSummaries.length > 0) {
2608
+ this.messages.push(
2609
+ (0, import_agent_core3.createToolMessage)(JSON.stringify(toolSummaries), {
2610
+ toolCallId: (0, import_node_crypto.randomUUID)(),
2611
+ name: `${toolSummaries.length} tools`
2612
+ })
2613
+ );
2614
+ }
2615
+ const parts = [];
2616
+ for (let i = historyBefore; i < history.length; i++) {
2617
+ const msg = history[i];
2618
+ if (msg?.role === "assistant" && msg.content) {
2619
+ parts.push(msg.content);
2620
+ }
2621
+ }
2622
+ return {
2623
+ response: parts.join("\n\n"),
2624
+ messages: this.messages,
2625
+ toolSummaries,
2626
+ contextState: this.getContextState()
2627
+ };
2628
+ }
2629
+ extractToolSummaries(historyBefore) {
2630
+ const history = this.session.getHistory();
2631
+ const summaries = [];
2632
+ for (let i = historyBefore; i < history.length; i++) {
2633
+ const msg = history[i];
2634
+ if (msg?.role === "assistant" && msg.toolCalls) {
2635
+ for (const tc of msg.toolCalls) {
2636
+ summaries.push({ name: tc.function.name, args: tc.function.arguments });
2637
+ }
2638
+ }
2639
+ }
2640
+ return summaries;
2641
+ }
2642
+ trimCompletedTools() {
2643
+ const completed = this.activeTools.filter((t) => !t.isRunning);
2644
+ if (completed.length > MAX_COMPLETED_TOOLS) {
2645
+ const excess = completed.length - MAX_COMPLETED_TOOLS;
2646
+ let removed = 0;
2647
+ this.activeTools = this.activeTools.filter((t) => {
2648
+ if (!t.isRunning && removed < excess) {
2649
+ removed++;
2650
+ return false;
2651
+ }
2652
+ return true;
2653
+ });
2654
+ }
2655
+ }
2656
+ };
2657
+ function isAbortError(err) {
2658
+ return err instanceof DOMException && err.name === "AbortError" || err instanceof Error && (err.message.includes("aborted") || err.message.includes("abort"));
2659
+ }
2660
+ function extractFirstArg(toolArgs) {
2661
+ if (!toolArgs) return "";
2662
+ const firstVal = Object.values(toolArgs)[0];
2663
+ const raw = typeof firstVal === "string" ? firstVal : JSON.stringify(firstVal ?? "");
2664
+ return raw.length > TOOL_ARG_DISPLAY_MAX ? raw.slice(0, TOOL_ARG_DISPLAY_MAX - TAIL_KEEP - 3) + "..." + raw.slice(-TAIL_KEEP) : raw;
2665
+ }
2666
+ var NOOP_TERMINAL = {
2667
+ write: () => {
2668
+ },
2669
+ writeLine: () => {
2670
+ },
2671
+ writeMarkdown: () => {
2672
+ },
2673
+ writeError: () => {
2674
+ },
2675
+ prompt: () => Promise.resolve(""),
2676
+ select: () => Promise.resolve(0),
2677
+ spinner: () => ({ stop: () => {
2678
+ }, update: () => {
2679
+ } })
2680
+ };
2681
+
1971
2682
  // src/index.ts
1972
2683
  var import_agent_tools3 = require("@robota-sdk/agent-tools");
1973
2684
  var import_agent_tools4 = require("@robota-sdk/agent-tools");
@@ -1979,16 +2690,21 @@ var import_agent_tools8 = require("@robota-sdk/agent-tools");
1979
2690
  0 && (module.exports = {
1980
2691
  AgentExecutor,
1981
2692
  BUILT_IN_AGENTS,
2693
+ BuiltinCommandSource,
1982
2694
  BundlePluginInstaller,
1983
2695
  BundlePluginLoader,
2696
+ CommandRegistry,
1984
2697
  DEFAULT_TOOL_DESCRIPTIONS,
1985
2698
  FileSessionLogger,
2699
+ InteractiveSession,
1986
2700
  MarketplaceClient,
1987
2701
  PluginSettingsStore,
1988
2702
  PromptExecutor,
1989
2703
  Session,
1990
2704
  SessionStore,
1991
2705
  SilentSessionLogger,
2706
+ SkillCommandSource,
2707
+ SystemCommandExecutor,
1992
2708
  TRUST_TO_MODE,
1993
2709
  assembleSubagentPrompt,
1994
2710
  bashTool,
@@ -1999,6 +2715,7 @@ var import_agent_tools8 = require("@robota-sdk/agent-tools");
1999
2715
  createSession,
2000
2716
  createSubagentLogger,
2001
2717
  createSubagentSession,
2718
+ createSystemCommands,
2002
2719
  detectProject,
2003
2720
  editTool,
2004
2721
  evaluatePermission,
@@ -2009,6 +2726,7 @@ var import_agent_tools8 = require("@robota-sdk/agent-tools");
2009
2726
  grepTool,
2010
2727
  loadConfig,
2011
2728
  loadContext,
2729
+ parseFrontmatter,
2012
2730
  projectPaths,
2013
2731
  promptForApproval,
2014
2732
  query,