@elizaos/plugin-shell 2.0.0-alpha.5 → 2.0.0-alpha.7

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.
Files changed (36) hide show
  1. package/dist/actions/clearHistory.d.ts.map +1 -1
  2. package/dist/actions/index.d.ts +0 -2
  3. package/dist/actions/index.d.ts.map +1 -1
  4. package/dist/approvals/allowlist.d.ts.map +1 -1
  5. package/dist/approvals/analysis.d.ts.map +1 -1
  6. package/dist/approvals/index.d.ts.map +1 -1
  7. package/dist/approvals/service.d.ts.map +1 -1
  8. package/dist/approvals/types.d.ts.map +1 -1
  9. package/dist/generated/specs/spec-helpers.d.ts.map +1 -1
  10. package/dist/generated/specs/specs.d.ts +0 -10
  11. package/dist/generated/specs/specs.d.ts.map +1 -1
  12. package/dist/index.browser.d.ts.map +1 -1
  13. package/dist/index.d.ts +1 -2
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +205 -501
  16. package/dist/index.js.map +19 -21
  17. package/dist/providers/shellHistoryProvider.d.ts.map +1 -1
  18. package/dist/providers/terminalUsage.d.ts +3 -0
  19. package/dist/providers/terminalUsage.d.ts.map +1 -0
  20. package/dist/services/index.d.ts.map +1 -1
  21. package/dist/services/processRegistry.d.ts.map +1 -1
  22. package/dist/services/shellService.d.ts.map +1 -1
  23. package/dist/types/index.d.ts.map +1 -1
  24. package/dist/utils/config.d.ts.map +1 -1
  25. package/dist/utils/index.d.ts.map +1 -1
  26. package/dist/utils/pathUtils.d.ts.map +1 -1
  27. package/dist/utils/processQueue.d.ts.map +1 -1
  28. package/dist/utils/ptyKeys.d.ts.map +1 -1
  29. package/dist/utils/shellUtils.d.ts.map +1 -1
  30. package/dist/vitest.config.d.ts +3 -0
  31. package/dist/vitest.config.d.ts.map +1 -0
  32. package/package.json +124 -124
  33. package/dist/actions/executeCommand.d.ts +0 -6
  34. package/dist/actions/executeCommand.d.ts.map +0 -1
  35. package/dist/actions/processAction.d.ts +0 -7
  36. package/dist/actions/processAction.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ var __toESM = (mod, isNodeMode, target) => {
18
18
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
19
19
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
20
20
 
21
- // node_modules/@lydell/node-pty/eventEmitter2.js
21
+ // ../../../node_modules/.pnpm/@lydell+node-pty@1.1.0/node_modules/@lydell/node-pty/eventEmitter2.js
22
22
  var require_eventEmitter2 = __commonJS((exports) => {
23
23
  Object.defineProperty(exports, "__esModule", { value: true });
24
24
  var EventEmitter2 = function() {
@@ -63,7 +63,7 @@ var require_eventEmitter2 = __commonJS((exports) => {
63
63
  exports.EventEmitter2 = EventEmitter2;
64
64
  });
65
65
 
66
- // node_modules/@lydell/node-pty/terminal.js
66
+ // ../../../node_modules/.pnpm/@lydell+node-pty@1.1.0/node_modules/@lydell/node-pty/terminal.js
67
67
  var require_terminal = __commonJS((exports) => {
68
68
  Object.defineProperty(exports, "__esModule", { value: true });
69
69
  var events_1 = __require("events");
@@ -251,7 +251,7 @@ var require_terminal = __commonJS((exports) => {
251
251
  exports.Terminal = Terminal;
252
252
  });
253
253
 
254
- // node_modules/@lydell/node-pty/shared/conout.js
254
+ // ../../../node_modules/.pnpm/@lydell+node-pty@1.1.0/node_modules/@lydell/node-pty/shared/conout.js
255
255
  var require_conout = __commonJS((exports) => {
256
256
  Object.defineProperty(exports, "__esModule", { value: true });
257
257
  function getWorkerPipeName(conoutPipeName) {
@@ -260,9 +260,9 @@ var require_conout = __commonJS((exports) => {
260
260
  exports.getWorkerPipeName = getWorkerPipeName;
261
261
  });
262
262
 
263
- // node_modules/@lydell/node-pty/windowsConoutConnection.js
263
+ // ../../../node_modules/.pnpm/@lydell+node-pty@1.1.0/node_modules/@lydell/node-pty/windowsConoutConnection.js
264
264
  var require_windowsConoutConnection = __commonJS((exports) => {
265
- var __dirname = "/Users/shawwalters/eliza-workspace/plugins/plugin-shell/typescript/node_modules/@lydell/node-pty";
265
+ var __dirname = "/Users/shawwalters/eliza-workspace/milady/node_modules/.pnpm/@lydell+node-pty@1.1.0/node_modules/@lydell/node-pty";
266
266
  var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
267
267
  function adopt(value) {
268
268
  return value instanceof P ? value : new P(function(resolve) {
@@ -435,7 +435,7 @@ var require_windowsConoutConnection = __commonJS((exports) => {
435
435
  exports.ConoutConnection = ConoutConnection;
436
436
  });
437
437
 
438
- // node_modules/@lydell/node-pty/package.json
438
+ // ../../../node_modules/.pnpm/@lydell+node-pty@1.1.0/node_modules/@lydell/node-pty/package.json
439
439
  var require_package = __commonJS((exports, module) => {
440
440
  module.exports = {
441
441
  name: "@lydell/node-pty",
@@ -470,7 +470,7 @@ var require_package = __commonJS((exports, module) => {
470
470
  };
471
471
  });
472
472
 
473
- // node_modules/@lydell/node-pty/requireBinary.js
473
+ // ../../../node_modules/.pnpm/@lydell+node-pty@1.1.0/node_modules/@lydell/node-pty/requireBinary.js
474
474
  var require_requireBinary = __commonJS((exports) => {
475
475
  Object.defineProperty(exports, "__esModule", { value: true });
476
476
  var PACKAGE_NAME = "@lydell/node-pty-" + process.platform + "-" + process.arch;
@@ -511,9 +511,9 @@ Your platform (` + process.platform + "-" + process.arch + ") might not be suppo
511
511
  }
512
512
  });
513
513
 
514
- // node_modules/@lydell/node-pty/windowsPtyAgent.js
514
+ // ../../../node_modules/.pnpm/@lydell+node-pty@1.1.0/node_modules/@lydell/node-pty/windowsPtyAgent.js
515
515
  var require_windowsPtyAgent = __commonJS((exports) => {
516
- var __dirname = "/Users/shawwalters/eliza-workspace/plugins/plugin-shell/typescript/node_modules/@lydell/node-pty";
516
+ var __dirname = "/Users/shawwalters/eliza-workspace/milady/node_modules/.pnpm/@lydell+node-pty@1.1.0/node_modules/@lydell/node-pty";
517
517
  Object.defineProperty(exports, "__esModule", { value: true });
518
518
  var fs5 = __require("fs");
519
519
  var path6 = __require("path");
@@ -729,7 +729,7 @@ var require_windowsPtyAgent = __commonJS((exports) => {
729
729
  }
730
730
  });
731
731
 
732
- // node_modules/@lydell/node-pty/utils.js
732
+ // ../../../node_modules/.pnpm/@lydell+node-pty@1.1.0/node_modules/@lydell/node-pty/utils.js
733
733
  var require_utils = __commonJS((exports) => {
734
734
  Object.defineProperty(exports, "__esModule", { value: true });
735
735
  function assign(target) {
@@ -747,7 +747,7 @@ var require_utils = __commonJS((exports) => {
747
747
  exports.assign = assign;
748
748
  });
749
749
 
750
- // node_modules/@lydell/node-pty/windowsTerminal.js
750
+ // ../../../node_modules/.pnpm/@lydell+node-pty@1.1.0/node_modules/@lydell/node-pty/windowsTerminal.js
751
751
  var require_windowsTerminal = __commonJS((exports) => {
752
752
  var __extends = exports && exports.__extends || function() {
753
753
  var extendStatics = function(d, b) {
@@ -925,7 +925,7 @@ var require_windowsTerminal = __commonJS((exports) => {
925
925
  exports.WindowsTerminal = WindowsTerminal;
926
926
  });
927
927
 
928
- // node_modules/@lydell/node-pty/unixTerminal.js
928
+ // ../../../node_modules/.pnpm/@lydell+node-pty@1.1.0/node_modules/@lydell/node-pty/unixTerminal.js
929
929
  var require_unixTerminal = __commonJS((exports) => {
930
930
  var __extends = exports && exports.__extends || function() {
931
931
  var extendStatics = function(d, b) {
@@ -1171,7 +1171,7 @@ var require_unixTerminal = __commonJS((exports) => {
1171
1171
  exports.UnixTerminal = UnixTerminal;
1172
1172
  });
1173
1173
 
1174
- // node_modules/@lydell/node-pty/index.js
1174
+ // ../../../node_modules/.pnpm/@lydell+node-pty@1.1.0/node_modules/@lydell/node-pty/index.js
1175
1175
  var require_node_pty = __commonJS((exports) => {
1176
1176
  Object.defineProperty(exports, "__esModule", { value: true });
1177
1177
  var terminalCtor;
@@ -1210,26 +1210,11 @@ var coreActionsSpec = {
1210
1210
  {
1211
1211
  name: "CLEAR_SHELL_HISTORY",
1212
1212
  description: "Clears the recorded history of shell commands for the current conversation",
1213
- similes: ["RESET_SHELL", "CLEAR_TERMINAL", "CLEAR_HISTORY", "RESET_HISTORY"],
1214
- parameters: []
1215
- },
1216
- {
1217
- name: "EXECUTE_COMMAND",
1218
- description: "Execute shell commands including brew install, npm install, apt-get, system commands, file operations, directory navigation, and scripts.",
1219
1213
  similes: [
1220
- "RUN_COMMAND",
1221
- "SHELL_COMMAND",
1222
- "TERMINAL_COMMAND",
1223
- "EXEC",
1224
- "RUN",
1225
- "EXECUTE",
1226
- "CREATE_FILE",
1227
- "WRITE_FILE",
1228
- "MAKE_FILE",
1229
- "INSTALL",
1230
- "BREW_INSTALL",
1231
- "NPM_INSTALL",
1232
- "APT_INSTALL"
1214
+ "RESET_SHELL",
1215
+ "CLEAR_TERMINAL",
1216
+ "CLEAR_HISTORY",
1217
+ "RESET_HISTORY"
1233
1218
  ],
1234
1219
  parameters: []
1235
1220
  }
@@ -1241,26 +1226,11 @@ var allActionsSpec = {
1241
1226
  {
1242
1227
  name: "CLEAR_SHELL_HISTORY",
1243
1228
  description: "Clears the recorded history of shell commands for the current conversation",
1244
- similes: ["RESET_SHELL", "CLEAR_TERMINAL", "CLEAR_HISTORY", "RESET_HISTORY"],
1245
- parameters: []
1246
- },
1247
- {
1248
- name: "EXECUTE_COMMAND",
1249
- description: "Execute shell commands including brew install, npm install, apt-get, system commands, file operations, directory navigation, and scripts.",
1250
1229
  similes: [
1251
- "RUN_COMMAND",
1252
- "SHELL_COMMAND",
1253
- "TERMINAL_COMMAND",
1254
- "EXEC",
1255
- "RUN",
1256
- "EXECUTE",
1257
- "CREATE_FILE",
1258
- "WRITE_FILE",
1259
- "MAKE_FILE",
1260
- "INSTALL",
1261
- "BREW_INSTALL",
1262
- "NPM_INSTALL",
1263
- "APT_INSTALL"
1230
+ "RESET_SHELL",
1231
+ "CLEAR_TERMINAL",
1232
+ "CLEAR_HISTORY",
1233
+ "RESET_HISTORY"
1264
1234
  ],
1265
1235
  parameters: []
1266
1236
  }
@@ -1335,17 +1305,38 @@ var clearHistory = {
1335
1305
  name: spec.name,
1336
1306
  similes: spec.similes ? [...spec.similes] : [],
1337
1307
  description: spec.description,
1338
- validate: async (runtime, message, _state) => {
1339
- const shellService = runtime.getService("shell");
1340
- if (!shellService) {
1308
+ validate: async (runtime, message, state, options) => {
1309
+ const __avTextRaw = typeof message?.content?.text === "string" ? message.content.text : "";
1310
+ const __avText = __avTextRaw.toLowerCase();
1311
+ const __avKeywords = ["clear", "shell", "history"];
1312
+ const __avKeywordOk = __avKeywords.length > 0 && __avKeywords.some((kw) => kw.length > 0 && __avText.includes(kw));
1313
+ const __avRegex = new RegExp("\\b(?:clear|shell|history)\\b", "i");
1314
+ const __avRegexOk = __avRegex.test(__avText);
1315
+ const __avSource = String(message?.content?.source ?? message?.source ?? "");
1316
+ const __avExpectedSource = "";
1317
+ const __avSourceOk = __avExpectedSource ? __avSource === __avExpectedSource : Boolean(__avSource || state || runtime?.agentId || runtime?.getService);
1318
+ const __avOptions = options && typeof options === "object" ? options : {};
1319
+ const __avInputOk = __avText.trim().length > 0 || Object.keys(__avOptions).length > 0 || Boolean(message?.content && typeof message.content === "object");
1320
+ if (!(__avKeywordOk && __avRegexOk && __avSourceOk && __avInputOk)) {
1321
+ return false;
1322
+ }
1323
+ const __avLegacyValidate = async (runtime2, message2, _state) => {
1324
+ const shellService = runtime2.getService("shell");
1325
+ if (!shellService) {
1326
+ return false;
1327
+ }
1328
+ const text = message2.content.text?.toLowerCase() || "";
1329
+ const clearKeywords = ["clear", "reset", "delete", "remove", "clean"];
1330
+ const historyKeywords = ["history", "terminal", "shell", "command"];
1331
+ const hasClearKeyword = clearKeywords.some((keyword) => text.includes(keyword));
1332
+ const hasHistoryKeyword = historyKeywords.some((keyword) => text.includes(keyword));
1333
+ return hasClearKeyword && hasHistoryKeyword;
1334
+ };
1335
+ try {
1336
+ return Boolean(await __avLegacyValidate(runtime, message, state, options));
1337
+ } catch {
1341
1338
  return false;
1342
1339
  }
1343
- const text = message.content.text?.toLowerCase() || "";
1344
- const clearKeywords = ["clear", "reset", "delete", "remove", "clean"];
1345
- const historyKeywords = ["history", "terminal", "shell", "command"];
1346
- const hasClearKeyword = clearKeywords.some((keyword) => text.includes(keyword));
1347
- const hasHistoryKeyword = historyKeywords.some((keyword) => text.includes(keyword));
1348
- return hasClearKeyword && hasHistoryKeyword;
1349
1340
  },
1350
1341
  handler: async (runtime, message, _state, _options, callback) => {
1351
1342
  const shellService = runtime.getService("shell");
@@ -1382,389 +1373,12 @@ var clearHistory = {
1382
1373
  },
1383
1374
  examples: spec.examples ?? []
1384
1375
  };
1385
- // actions/executeCommand.ts
1386
- import {
1387
- composePromptFromState,
1388
- logger as logger2,
1389
- ModelType,
1390
- parseJSONObjectFromText
1391
- } from "@elizaos/core";
1392
-
1393
- // generated/prompts/typescript/prompts.ts
1394
- var commandExtractionTemplate = `# Extracting shell command from request
1395
- {{recentMessages}}
1396
-
1397
- # Instructions: {{senderName}} wants to execute a shell command. Extract the COMPLETE shell command they want to run.
1398
-
1399
- IMPORTANT:
1400
- 1. Always return the FULL executable shell command, not just the content or partial command.
1401
- 2. If the user mentions installing something, create the appropriate brew/npm/apt command.
1402
- 3. If the user directly provides a command (like "brew install X"), use it exactly as provided.
1403
- 4. ALWAYS extract a command if the user is asking for ANY kind of system operation.
1404
-
1405
- Common patterns:
1406
- - "run ls -la" -> command: "ls -la"
1407
- - "execute npm test" -> command: "npm test"
1408
- - "show me the files" or "list files" -> command: "ls -la"
1409
- - "what's in this directory" -> command: "ls -la"
1410
- - "check git status" -> command: "git status"
1411
- - "navigate to src folder" -> command: "cd src"
1412
- - "create a file called test.txt" -> command: "touch test.txt"
1413
- - "write hello world to a file" -> command: "echo 'hello world' > file.txt"
1414
- - "create hello.js with javascript code" -> command: "echo 'console.log(\\"Hello, World!\\");' > hello.js"
1415
- - "create hello_world.py and write a python hello world script inside" -> command: "echo 'print(\\"Hello, World!\\")' > hello_world.py"
1416
- - "make a new directory" -> command: "mkdir newdir"
1417
- - "list files inside your filesystem" -> command: "ls -la"
1418
- - "install orbstack" or "brew install orbstack" -> command: "brew install orbstack"
1419
- - "install mullvad vpn" -> command: "brew install --cask mullvad-vpn"
1420
- - "get system info" -> command: "system_profiler SPHardwareDataType"
1421
- - "check memory usage" -> command: "vm_stat"
1422
- - "install package" -> command: "brew install <package>"
1423
-
1424
- Special cases:
1425
- - "Run it in your shell" or "execute it" -> Extract the command from previous context
1426
- - "Install these" -> Look for package names in previous messages
1427
- - Direct commands should be used exactly as provided
1428
-
1429
- Key rules:
1430
- 1. For file creation with content, use: echo 'content' > filename
1431
- 2. For listing files, use: ls -la (not just ls)
1432
- 3. Always include the echo command when writing to files
1433
- 4. Include all flags and arguments
1434
- 5. When user says "run it", "execute it", or similar, they want you to run the command
1435
-
1436
- Your response must be formatted as a JSON block:
1437
- \`\`\`json
1438
- {
1439
- "command": "<complete shell command to execute>"
1440
- }
1441
- \`\`\``;
1442
-
1443
- // actions/executeCommand.ts
1444
- var extractCommand = async (runtime, _message, state) => {
1445
- const prompt = composePromptFromState({
1446
- state,
1447
- template: commandExtractionTemplate
1448
- });
1449
- for (let i = 0;i < 3; i++) {
1450
- const response = await runtime.useModel(ModelType.TEXT_SMALL, {
1451
- prompt
1452
- });
1453
- const parsedResponse = parseJSONObjectFromText(response);
1454
- if (parsedResponse?.command) {
1455
- return { command: parsedResponse.command };
1456
- }
1457
- }
1458
- return null;
1459
- };
1460
- var spec2 = requireActionSpec("EXECUTE_COMMAND");
1461
- var executeCommand = {
1462
- name: spec2.name,
1463
- similes: spec2.similes ? [...spec2.similes] : [],
1464
- description: spec2.description,
1465
- validate: async (runtime, message, _state) => {
1466
- const shellService = runtime.getService("shell");
1467
- if (!shellService) {
1468
- return false;
1469
- }
1470
- const text = message.content.text?.toLowerCase() || "";
1471
- const commandKeywords = [
1472
- "run",
1473
- "execute",
1474
- "command",
1475
- "shell",
1476
- "install",
1477
- "brew",
1478
- "npm",
1479
- "create",
1480
- "file",
1481
- "directory",
1482
- "folder",
1483
- "list",
1484
- "show",
1485
- "system",
1486
- "info",
1487
- "check",
1488
- "status",
1489
- "cd",
1490
- "ls",
1491
- "mkdir",
1492
- "echo",
1493
- "cat",
1494
- "touch",
1495
- "git",
1496
- "build",
1497
- "test"
1498
- ];
1499
- const hasCommandKeyword = commandKeywords.some((keyword) => text.includes(keyword));
1500
- const hasDirectCommand = /^(brew|npm|apt|git|ls|cd|echo|cat|touch|mkdir|rm|mv|cp)\s/i.test(message.content.text || "");
1501
- return hasCommandKeyword || hasDirectCommand;
1502
- },
1503
- handler: async (runtime, message, state, _options, callback) => {
1504
- const shellService = runtime.getService("shell");
1505
- if (!shellService) {
1506
- if (callback) {
1507
- await callback({
1508
- text: "Shell service is not available.",
1509
- source: message.content.source
1510
- });
1511
- }
1512
- return { success: false, error: "Shell service is not available." };
1513
- }
1514
- const commandInfo = await extractCommand(runtime, message, state);
1515
- if (!commandInfo?.command) {
1516
- logger2.error("Failed to extract command from message:", message.content.text);
1517
- if (callback) {
1518
- await callback({
1519
- text: "Could not determine which command to execute. Please specify a shell command.",
1520
- source: message.content.source
1521
- });
1522
- }
1523
- return { success: false, error: "Could not extract command." };
1524
- }
1525
- logger2.info(`Extracted command: "${commandInfo.command}"`);
1526
- try {
1527
- const conversationId = message.roomId || message.agentId;
1528
- const result = await shellService.executeCommand(commandInfo.command, conversationId);
1529
- let responseText = "";
1530
- if (result.success) {
1531
- responseText = `Command executed successfully in ${result.executedIn}
1532
-
1533
- `;
1534
- if (result.stdout) {
1535
- responseText += `Output:
1536
- \`\`\`
1537
- ${result.stdout}
1538
- \`\`\``;
1539
- } else {
1540
- responseText += "Command completed with no output.";
1541
- }
1542
- } else {
1543
- responseText = `Command failed with exit code ${result.exitCode} in ${result.executedIn}
1544
-
1545
- `;
1546
- if (result.error) {
1547
- responseText += `Error: ${result.error}
1548
- `;
1549
- }
1550
- if (result.stderr) {
1551
- responseText += `
1552
- Error output:
1553
- \`\`\`
1554
- ${result.stderr}
1555
- \`\`\``;
1556
- }
1557
- }
1558
- const response = {
1559
- text: responseText,
1560
- source: message.content.source
1561
- };
1562
- if (callback) {
1563
- await callback(response);
1564
- }
1565
- return { success: result.success, text: responseText };
1566
- } catch (error) {
1567
- logger2.error("Error executing command:", error);
1568
- const errorMessage = error instanceof Error ? error.message : String(error);
1569
- if (callback) {
1570
- await callback({
1571
- text: `Failed to execute command: ${errorMessage}`,
1572
- source: message.content.source
1573
- });
1574
- }
1575
- return { success: false, error: errorMessage };
1576
- }
1577
- },
1578
- examples: spec2.examples ?? []
1579
- };
1580
- // actions/processAction.ts
1581
- import { composePromptFromState as composePromptFromState2, logger as logger3, ModelType as ModelType2 } from "@elizaos/core";
1582
- var processActionTemplate = `You are helping extract process management parameters from user messages.
1583
-
1584
- Recent conversation:
1585
- {{recentMessages}}
1586
-
1587
- Based on the conversation, extract the process action parameters:
1588
- - action: The action to perform (list, poll, log, write, send-keys, submit, paste, kill, clear, remove)
1589
- - sessionId: The session ID (required for all actions except "list")
1590
- - data: Data to write (for "write" action)
1591
- - keys: Array of key tokens (for "send-keys" action)
1592
- - literal: Literal string to send (for "send-keys" action)
1593
- - text: Text to paste (for "paste" action)
1594
- - eof: Whether to close stdin after write (for "write" action)
1595
- - offset: Log offset (for "log" action)
1596
- - limit: Log limit (for "log" action)
1597
-
1598
- Respond with a JSON object containing the extracted parameters:
1599
- \`\`\`json
1600
- {
1601
- "action": "list|poll|log|write|send-keys|submit|paste|kill|clear|remove",
1602
- "sessionId": "optional-session-id",
1603
- "data": "optional-data",
1604
- "keys": ["optional", "key", "tokens"],
1605
- "literal": "optional-literal",
1606
- "text": "optional-paste-text",
1607
- "eof": false,
1608
- "offset": 0,
1609
- "limit": 100
1610
- }
1611
- \`\`\``;
1612
- function extractJsonFromResponse(response) {
1613
- const jsonMatch = response.match(/```json\s*([\s\S]*?)\s*```/);
1614
- if (jsonMatch?.[1]) {
1615
- try {
1616
- return JSON.parse(jsonMatch[1]);
1617
- } catch {}
1618
- }
1619
- try {
1620
- const trimmed = response.trim();
1621
- if (trimmed.startsWith("{") && trimmed.endsWith("}")) {
1622
- return JSON.parse(trimmed);
1623
- }
1624
- } catch {}
1625
- return null;
1626
- }
1627
- var processAction = {
1628
- name: "MANAGE_PROCESS",
1629
- similes: [
1630
- "PROCESS_LIST",
1631
- "PROCESS_POLL",
1632
- "PROCESS_LOG",
1633
- "PROCESS_WRITE",
1634
- "PROCESS_KILL",
1635
- "LIST_SESSIONS",
1636
- "POLL_SESSION",
1637
- "KILL_SESSION",
1638
- "CHECK_PROCESS",
1639
- "SEND_KEYS"
1640
- ],
1641
- description: "Manage running shell/exec sessions: list, poll, log, write, send-keys, submit, paste, kill, clear, remove",
1642
- validate: async (_runtime, message) => {
1643
- const text = message.content.text?.toLowerCase() || "";
1644
- const processKeywords = [
1645
- "process",
1646
- "session",
1647
- "sessions",
1648
- "list",
1649
- "poll",
1650
- "log",
1651
- "write",
1652
- "send-keys",
1653
- "send keys",
1654
- "submit",
1655
- "paste",
1656
- "kill",
1657
- "clear",
1658
- "remove",
1659
- "running",
1660
- "background"
1661
- ];
1662
- const actionKeywords = [
1663
- "check",
1664
- "show",
1665
- "get",
1666
- "view",
1667
- "manage",
1668
- "stop",
1669
- "terminate",
1670
- "status"
1671
- ];
1672
- const hasProcessKeyword = processKeywords.some((kw) => text.includes(kw));
1673
- const hasActionKeyword = actionKeywords.some((kw) => text.includes(kw));
1674
- return hasProcessKeyword || hasActionKeyword && text.includes("session");
1675
- },
1676
- handler: async (runtime, message, state) => {
1677
- const shellService = runtime.getService("shell");
1678
- if (!shellService) {
1679
- return {
1680
- success: false,
1681
- text: "Shell service is not available.",
1682
- error: "Shell service not found"
1683
- };
1684
- }
1685
- const composedState = state ?? await runtime.composeState(message);
1686
- const prompt = composePromptFromState2({
1687
- state: composedState,
1688
- template: processActionTemplate
1689
- });
1690
- let params = null;
1691
- const text = message.content.text?.toLowerCase() || "";
1692
- if (text.includes("list") && (text.includes("session") || text.includes("process"))) {
1693
- params = { action: "list" };
1694
- } else {
1695
- try {
1696
- const response = await runtime.useModel(ModelType2.TEXT_SMALL, {
1697
- prompt
1698
- });
1699
- params = extractJsonFromResponse(String(response));
1700
- } catch (error) {
1701
- logger3.error("Failed to extract process parameters:", error);
1702
- }
1703
- }
1704
- if (!params) {
1705
- params = { action: "list" };
1706
- }
1707
- const result = await shellService.processAction(params);
1708
- return {
1709
- success: result.success,
1710
- text: result.message
1711
- };
1712
- },
1713
- examples: [
1714
- [
1715
- {
1716
- name: "{{user1}}",
1717
- content: { text: "List all running processes" }
1718
- },
1719
- {
1720
- name: "{{agentName}}",
1721
- content: {
1722
- text: `Here are the running sessions:
1723
- calm-harbor running 5m30s :: npm install
1724
- brisk-reef completed 2m15s :: git status`,
1725
- action: "MANAGE_PROCESS"
1726
- }
1727
- }
1728
- ],
1729
- [
1730
- {
1731
- name: "{{user1}}",
1732
- content: { text: "Check the status of session calm-harbor" }
1733
- },
1734
- {
1735
- name: "{{agentName}}",
1736
- content: {
1737
- text: `Session calm-harbor is still running.
1738
-
1739
- Output:
1740
- npm WARN deprecated...
1741
-
1742
- Process still running.`,
1743
- action: "MANAGE_PROCESS"
1744
- }
1745
- }
1746
- ],
1747
- [
1748
- {
1749
- name: "{{user1}}",
1750
- content: { text: "Kill the session brisk-reef" }
1751
- },
1752
- {
1753
- name: "{{agentName}}",
1754
- content: {
1755
- text: "Killed session brisk-reef.",
1756
- action: "MANAGE_PROCESS"
1757
- }
1758
- }
1759
- ]
1760
- ]
1761
- };
1762
1376
  // approvals/allowlist.ts
1763
1377
  import crypto2 from "node:crypto";
1764
1378
  import fs from "node:fs";
1765
1379
  import os from "node:os";
1766
1380
  import path from "node:path";
1767
- import { logger as logger4 } from "@elizaos/core";
1381
+ import { logger as logger2 } from "@elizaos/core";
1768
1382
 
1769
1383
  // approvals/types.ts
1770
1384
  var DEFAULT_SAFE_BINS = [
@@ -1902,12 +1516,12 @@ function readApprovalsSnapshot() {
1902
1516
  try {
1903
1517
  parsed = JSON.parse(raw);
1904
1518
  } catch (parseError) {
1905
- logger4.warn({ src: "exec-approval", parseError, filePath }, "Failed to parse approval config snapshot - file may be corrupted");
1519
+ logger2.warn({ src: "exec-approval", parseError, filePath }, "Failed to parse approval config snapshot - file may be corrupted");
1906
1520
  parsed = null;
1907
1521
  }
1908
1522
  const file = parsed?.version === 1 ? normalizeApprovals(parsed) : normalizeApprovals({ version: 1, agents: {} });
1909
1523
  if (parsed && parsed.version !== 1) {
1910
- logger4.warn({ src: "exec-approval", version: parsed.version, filePath }, "Approval config snapshot has unexpected version");
1524
+ logger2.warn({ src: "exec-approval", version: parsed.version, filePath }, "Approval config snapshot has unexpected version");
1911
1525
  }
1912
1526
  return {
1913
1527
  path: filePath,
@@ -1921,7 +1535,7 @@ function loadApprovals() {
1921
1535
  const filePath = getApprovalFilePath();
1922
1536
  try {
1923
1537
  if (!fs.existsSync(filePath)) {
1924
- logger4.debug({ src: "exec-approval", filePath }, "Approval config file does not exist, using defaults");
1538
+ logger2.debug({ src: "exec-approval", filePath }, "Approval config file does not exist, using defaults");
1925
1539
  return normalizeApprovals({ version: 1, agents: {} });
1926
1540
  }
1927
1541
  const raw = fs.readFileSync(filePath, "utf8");
@@ -1929,16 +1543,16 @@ function loadApprovals() {
1929
1543
  try {
1930
1544
  parsed = JSON.parse(raw);
1931
1545
  } catch (parseError) {
1932
- logger4.error({ src: "exec-approval", parseError, filePath }, "Failed to parse approval config JSON - file may be corrupted. Using defaults.");
1546
+ logger2.error({ src: "exec-approval", parseError, filePath }, "Failed to parse approval config JSON - file may be corrupted. Using defaults.");
1933
1547
  return normalizeApprovals({ version: 1, agents: {} });
1934
1548
  }
1935
1549
  if (parsed?.version !== 1) {
1936
- logger4.warn({ src: "exec-approval", version: parsed?.version, filePath }, "Approval config has unexpected version, using defaults");
1550
+ logger2.warn({ src: "exec-approval", version: parsed?.version, filePath }, "Approval config has unexpected version, using defaults");
1937
1551
  return normalizeApprovals({ version: 1, agents: {} });
1938
1552
  }
1939
1553
  return normalizeApprovals(parsed);
1940
1554
  } catch (error) {
1941
- logger4.error({ src: "exec-approval", error, filePath }, "Failed to load approval config - using defaults. This may indicate a permissions issue.");
1555
+ logger2.error({ src: "exec-approval", error, filePath }, "Failed to load approval config - using defaults. This may indicate a permissions issue.");
1942
1556
  return normalizeApprovals({ version: 1, agents: {} });
1943
1557
  }
1944
1558
  }
@@ -1954,7 +1568,7 @@ function saveApprovals(file) {
1954
1568
  fs.chmodSync(filePath, 384);
1955
1569
  } catch {}
1956
1570
  } catch (error) {
1957
- logger4.error({ src: "exec-approval", error, filePath }, "Failed to save approval configuration");
1571
+ logger2.error({ src: "exec-approval", error, filePath }, "Failed to save approval configuration");
1958
1572
  throw new Error(`Failed to save approval configuration to ${filePath}: ${error}`);
1959
1573
  }
1960
1574
  }
@@ -1973,7 +1587,7 @@ function ensureApprovals() {
1973
1587
  try {
1974
1588
  saveApprovals(updated);
1975
1589
  } catch (error) {
1976
- logger4.warn({ src: "exec-approval", error }, "Failed to save approval config during ensureApprovals - " + "returning in-memory config. Changes will not persist.");
1590
+ logger2.warn({ src: "exec-approval", error }, "Failed to save approval config during ensureApprovals - " + "returning in-memory config. Changes will not persist.");
1977
1591
  throw error;
1978
1592
  }
1979
1593
  return updated;
@@ -1995,7 +1609,7 @@ function resolveApprovals(agentId, overrides) {
1995
1609
  try {
1996
1610
  file = ensureApprovals();
1997
1611
  } catch (error) {
1998
- logger4.warn({ src: "exec-approval", error }, "Could not ensure approval config exists - using read-only config");
1612
+ logger2.warn({ src: "exec-approval", error }, "Could not ensure approval config exists - using read-only config");
1999
1613
  file = loadApprovals();
2000
1614
  }
2001
1615
  return resolveApprovalsFromFile({
@@ -2137,7 +1751,7 @@ function recordAllowlistUse(approvals, agentId, entry, command, resolvedPath) {
2137
1751
  saveApprovals(approvals);
2138
1752
  return true;
2139
1753
  } catch (error) {
2140
- logger4.warn({ src: "exec-approval", error, pattern: entry.pattern }, "Failed to record allowlist usage - continuing without update");
1754
+ logger2.warn({ src: "exec-approval", error, pattern: entry.pattern }, "Failed to record allowlist usage - continuing without update");
2141
1755
  return false;
2142
1756
  }
2143
1757
  }
@@ -2148,11 +1762,11 @@ function addAllowlistEntry(approvals, agentId, pattern) {
2148
1762
  const allowlist = Array.isArray(existing.allowlist) ? existing.allowlist : [];
2149
1763
  const trimmed = pattern.trim();
2150
1764
  if (!trimmed) {
2151
- logger4.warn({ src: "exec-approval" }, "Attempted to add empty pattern to allowlist");
1765
+ logger2.warn({ src: "exec-approval" }, "Attempted to add empty pattern to allowlist");
2152
1766
  return false;
2153
1767
  }
2154
1768
  if (allowlist.some((entry) => entry.pattern === trimmed)) {
2155
- logger4.debug({ src: "exec-approval", pattern: trimmed }, "Pattern already in allowlist");
1769
+ logger2.debug({ src: "exec-approval", pattern: trimmed }, "Pattern already in allowlist");
2156
1770
  return false;
2157
1771
  }
2158
1772
  allowlist.push({
@@ -2164,15 +1778,19 @@ function addAllowlistEntry(approvals, agentId, pattern) {
2164
1778
  approvals.agents = agents;
2165
1779
  try {
2166
1780
  saveApprovals(approvals);
2167
- logger4.info({ src: "exec-approval", pattern: trimmed, agentId: target }, "Added pattern to allowlist");
1781
+ logger2.info({ src: "exec-approval", pattern: trimmed, agentId: target }, "Added pattern to allowlist");
2168
1782
  return true;
2169
1783
  } catch (error) {
2170
- logger4.error({ src: "exec-approval", error, pattern: trimmed }, "Failed to save allowlist after adding entry");
1784
+ logger2.error({ src: "exec-approval", error, pattern: trimmed }, "Failed to save allowlist after adding entry");
2171
1785
  return false;
2172
1786
  }
2173
1787
  }
2174
1788
  function minSecurity(a, b) {
2175
- const order = { deny: 0, allowlist: 1, full: 2 };
1789
+ const order = {
1790
+ deny: 0,
1791
+ allowlist: 1,
1792
+ full: 2
1793
+ };
2176
1794
  return order[a] <= order[b] ? a : b;
2177
1795
  }
2178
1796
  function maxAsk(a, b) {
@@ -2182,8 +1800,16 @@ function maxAsk(a, b) {
2182
1800
  // approvals/analysis.ts
2183
1801
  import fs2 from "node:fs";
2184
1802
  import path2 from "node:path";
2185
- var DISALLOWED_PIPELINE_TOKENS = new Set([">", "<", "`", `
2186
- `, "\r", "(", ")"]);
1803
+ var DISALLOWED_PIPELINE_TOKENS = new Set([
1804
+ ">",
1805
+ "<",
1806
+ "`",
1807
+ `
1808
+ `,
1809
+ "\r",
1810
+ "(",
1811
+ ")"
1812
+ ]);
2187
1813
  var DOUBLE_QUOTE_ESCAPES = new Set(["\\", '"', "$", "`", `
2188
1814
  `, "\r"]);
2189
1815
  var WINDOWS_UNSUPPORTED_TOKENS = new Set([
@@ -2494,7 +2120,11 @@ function analyzeShellCommand(params) {
2494
2120
  }
2495
2121
  const segments2 = parseSegmentsFromParts(pipelineSplit.segments, params.cwd, params.env);
2496
2122
  if (!segments2) {
2497
- return { ok: false, reason: "unable to parse shell segment", segments: [] };
2123
+ return {
2124
+ ok: false,
2125
+ reason: "unable to parse shell segment",
2126
+ segments: []
2127
+ };
2498
2128
  }
2499
2129
  chains.push(segments2);
2500
2130
  allSegments.push(...segments2);
@@ -2525,7 +2155,11 @@ function analyzeWindowsCommand(params) {
2525
2155
  }
2526
2156
  const argv = tokenizeWindowsSegment(params.command);
2527
2157
  if (!argv || argv.length === 0) {
2528
- return { ok: false, reason: "unable to parse windows command", segments: [] };
2158
+ return {
2159
+ ok: false,
2160
+ reason: "unable to parse windows command",
2161
+ segments: []
2162
+ };
2529
2163
  }
2530
2164
  return {
2531
2165
  ok: true,
@@ -2780,7 +2414,10 @@ function evaluateExecAllowlist(params) {
2780
2414
  skillBins: params.skillBins,
2781
2415
  autoAllowSkills: params.autoAllowSkills
2782
2416
  });
2783
- return { allowlistSatisfied: result.satisfied, allowlistMatches: result.matches };
2417
+ return {
2418
+ allowlistSatisfied: result.satisfied,
2419
+ allowlistMatches: result.matches
2420
+ };
2784
2421
  }
2785
2422
  function evaluateShellAllowlist(params) {
2786
2423
  const chainParts = isWindowsPlatform(params.platform) ? null : splitCommandChain(params.command);
@@ -2861,7 +2498,7 @@ function requiresExecApproval(params) {
2861
2498
  return params.ask === "always" || params.ask === "on-miss" && params.security === "allowlist" && (!params.analysisOk || !params.allowlistSatisfied);
2862
2499
  }
2863
2500
  // approvals/service.ts
2864
- import { logger as logger5, Service } from "@elizaos/core";
2501
+ import { logger as logger3, Service } from "@elizaos/core";
2865
2502
  var EXEC_APPROVAL_OPTIONS = [
2866
2503
  { name: "allow-once", description: "Allow this one time" },
2867
2504
  { name: "allow-always", description: "Always allow this" },
@@ -2884,7 +2521,7 @@ class ExecApprovalService extends Service {
2884
2521
  try {
2885
2522
  service.approvalConfig = resolveApprovals(runtime.agentId);
2886
2523
  } catch (error) {
2887
- logger5.error({ src: "service:exec_approval", error, agentId: runtime.agentId }, "Failed to load approval config during startup - using in-memory defaults. " + "Approvals may not persist. Check file permissions for ~/.eliza/exec-approvals.json");
2524
+ logger3.error({ src: "service:exec_approval", error, agentId: runtime.agentId }, "Failed to load approval config during startup - using in-memory defaults. " + "Approvals may not persist. Check file permissions for ~/.eliza/exec-approvals.json");
2888
2525
  service.approvalConfig = {
2889
2526
  path: "",
2890
2527
  socketPath: "",
@@ -2905,11 +2542,11 @@ class ExecApprovalService extends Service {
2905
2542
  file: { version: 1, agents: {} }
2906
2543
  };
2907
2544
  }
2908
- logger5.info({ src: "service:exec_approval", agentId: runtime.agentId }, "ExecApprovalService started");
2545
+ logger3.info({ src: "service:exec_approval", agentId: runtime.agentId }, "ExecApprovalService started");
2909
2546
  return service;
2910
2547
  }
2911
2548
  async stop() {
2912
- logger5.debug({ src: "service:exec_approval" }, "ExecApprovalService stopped");
2549
+ logger3.debug({ src: "service:exec_approval" }, "ExecApprovalService stopped");
2913
2550
  }
2914
2551
  loadConfig(agentId) {
2915
2552
  this.approvalConfig = resolveApprovals(agentId ?? this.runtime?.agentId);
@@ -2981,7 +2618,7 @@ class ExecApprovalService extends Service {
2981
2618
  }
2982
2619
  }
2983
2620
  if (recordingFailed) {
2984
- logger5.debug({ src: "service:exec_approval", command: params.command }, "Some allowlist usage records failed to save - command will still proceed");
2621
+ logger3.debug({ src: "service:exec_approval", command: params.command }, "Some allowlist usage records failed to save - command will still proceed");
2985
2622
  }
2986
2623
  return {
2987
2624
  allowed: true,
@@ -3037,13 +2674,17 @@ class ExecApprovalService extends Service {
3037
2674
  async requestApproval(request) {
3038
2675
  const approvalService = this.runtime?.getService("approval");
3039
2676
  if (!approvalService) {
3040
- logger5.warn({ src: "service:exec_approval" }, "ApprovalService not available, denying by default");
2677
+ logger3.warn({ src: "service:exec_approval" }, "ApprovalService not available, denying by default");
3041
2678
  return {
3042
2679
  decision: "deny",
3043
2680
  timedOut: false
3044
2681
  };
3045
2682
  }
3046
- const descriptionLines = ["**Exec Approval Required**", "", `Command: \`${request.command}\``];
2683
+ const descriptionLines = [
2684
+ "**Exec Approval Required**",
2685
+ "",
2686
+ `Command: \`${request.command}\``
2687
+ ];
3047
2688
  if (request.cwd) {
3048
2689
  descriptionLines.push(`CWD: \`${request.cwd}\``);
3049
2690
  }
@@ -3085,13 +2726,17 @@ class ExecApprovalService extends Service {
3085
2726
  async requestApprovalAsync(request, callbacks) {
3086
2727
  const approvalService = this.runtime?.getService("approval");
3087
2728
  if (!approvalService) {
3088
- logger5.warn({ src: "service:exec_approval" }, "ApprovalService not available");
2729
+ logger3.warn({ src: "service:exec_approval" }, "ApprovalService not available");
3089
2730
  if (callbacks?.onDenied) {
3090
2731
  await callbacks.onDenied();
3091
2732
  }
3092
2733
  throw new Error("ApprovalService not available");
3093
2734
  }
3094
- const descriptionLines = ["**Exec Approval Required**", "", `Command: \`${request.command}\``];
2735
+ const descriptionLines = [
2736
+ "**Exec Approval Required**",
2737
+ "",
2738
+ `Command: \`${request.command}\``
2739
+ ];
3095
2740
  if (request.cwd) {
3096
2741
  descriptionLines.push(`CWD: \`${request.cwd}\``);
3097
2742
  }
@@ -3156,7 +2801,7 @@ class ExecApprovalService extends Service {
3156
2801
  }
3157
2802
  async getPendingApprovals(roomId) {
3158
2803
  if (!this.runtime) {
3159
- logger5.warn({ src: "service:exec_approval" }, "Cannot get pending approvals - runtime not available");
2804
+ logger3.warn({ src: "service:exec_approval" }, "Cannot get pending approvals - runtime not available");
3160
2805
  return [];
3161
2806
  }
3162
2807
  try {
@@ -3180,7 +2825,7 @@ class ExecApprovalService extends Service {
3180
2825
  };
3181
2826
  });
3182
2827
  } catch (error) {
3183
- logger5.error({ src: "service:exec_approval", error, roomId }, "Failed to get pending approvals");
2828
+ logger3.error({ src: "service:exec_approval", error, roomId }, "Failed to get pending approvals");
3184
2829
  return [];
3185
2830
  }
3186
2831
  }
@@ -3198,19 +2843,20 @@ function mapOptionToDecision(option) {
3198
2843
  // providers/shellHistoryProvider.ts
3199
2844
  import {
3200
2845
  addHeader,
3201
- logger as logger6
2846
+ logger as logger4
3202
2847
  } from "@elizaos/core";
3203
2848
  var MAX_OUTPUT_LENGTH = 8000;
3204
2849
  var TRUNCATE_SEGMENT_LENGTH = 4000;
3205
- var spec3 = requireProviderSpec("SHELL_HISTORY");
2850
+ var spec2 = requireProviderSpec("SHELL_HISTORY");
3206
2851
  var shellHistoryProvider = {
3207
- name: spec3.name,
2852
+ name: spec2.name,
3208
2853
  description: "Provides recent shell command history, current working directory, and file operations within the restricted environment",
3209
2854
  position: 99,
2855
+ dynamic: true,
3210
2856
  get: async (runtime, message, _state) => {
3211
2857
  const shellService = runtime.getService("shell");
3212
2858
  if (!shellService) {
3213
- logger6.warn("[shellHistoryProvider] Shell service not found");
2859
+ logger4.warn("[shellHistoryProvider] Shell service not found");
3214
2860
  return {
3215
2861
  values: {
3216
2862
  shellHistory: "Shell service is not available",
@@ -3310,15 +2956,62 @@ ${addHeader("# Shell History (Last 10)", historyText)}${fileOpsText}`;
3310
2956
  };
3311
2957
  }
3312
2958
  };
2959
+ // providers/terminalUsage.ts
2960
+ import { validateActionKeywords, validateActionRegex } from "@elizaos/core";
2961
+ var terminalUsageProvider = {
2962
+ name: "terminalUsage",
2963
+ description: "Terminal usage instructions",
2964
+ dynamic: true,
2965
+ relevanceKeywords: [
2966
+ "terminalusage",
2967
+ "terminalusageprovider",
2968
+ "plugin",
2969
+ "shell",
2970
+ "status",
2971
+ "state",
2972
+ "context",
2973
+ "info",
2974
+ "details",
2975
+ "chat",
2976
+ "conversation",
2977
+ "agent",
2978
+ "room",
2979
+ "channel"
2980
+ ],
2981
+ get: async (_runtime, _message, _state) => {
2982
+ const __providerKeywords = ["terminalusage", "terminalusageprovider", "plugin", "shell", "status", "state", "context", "info", "details", "chat", "conversation", "agent", "room", "channel"];
2983
+ const __providerRegex = new RegExp(`\\b(${__providerKeywords.join("|")})\\b`, "i");
2984
+ const __recentMessages = _state?.recentMessagesData || [];
2985
+ const __isRelevant = validateActionKeywords(_message, __recentMessages, __providerKeywords) || validateActionRegex(_message, __recentMessages, __providerRegex);
2986
+ if (!__isRelevant) {
2987
+ return { text: "" };
2988
+ }
2989
+ const settings = _runtime.character?.settings;
2990
+ if (settings?.DISABLE_TERMINAL) {
2991
+ return { text: "" };
2992
+ }
2993
+ return {
2994
+ text: [
2995
+ "## Terminal",
2996
+ "",
2997
+ "You can run shell commands in the user's embedded terminal using the RUN_IN_TERMINAL action.",
2998
+ "Use this when the user asks you to run a command, execute a script, install packages, etc.",
2999
+ "The terminal auto-opens and shows the command output in real time."
3000
+ ].join(`
3001
+ `)
3002
+ };
3003
+ }
3004
+ };
3005
+
3313
3006
  // services/shellService.ts
3314
3007
  import path6 from "node:path";
3315
- import { logger as logger9, Service as Service2 } from "@elizaos/core";
3008
+ import { logger as logger7, Service as Service2 } from "@elizaos/core";
3316
3009
  import spawn2 from "cross-spawn";
3317
3010
 
3318
3011
  // utils/config.ts
3319
3012
  import fs3 from "node:fs";
3320
3013
  import path3 from "node:path";
3321
- import { logger as logger7 } from "@elizaos/core";
3014
+ import { logger as logger5 } from "@elizaos/core";
3322
3015
  import { z } from "zod";
3323
3016
  var configSchema = z.object({
3324
3017
  enabled: z.boolean(),
@@ -3365,7 +3058,9 @@ function loadShellConfig() {
3365
3058
  const defaultBackgroundMs = parseInt(process.env.SHELL_BACKGROUND_MS || "10000", 10);
3366
3059
  const allowBackground = process.env.SHELL_ALLOW_BACKGROUND !== "false";
3367
3060
  const customForbidden = process.env.SHELL_FORBIDDEN_COMMANDS ? process.env.SHELL_FORBIDDEN_COMMANDS.split(",").map((cmd) => cmd.trim()) : [];
3368
- const forbiddenCommands = [...new Set([...DEFAULT_FORBIDDEN_COMMANDS, ...customForbidden])];
3061
+ const forbiddenCommands = [
3062
+ ...new Set([...DEFAULT_FORBIDDEN_COMMANDS, ...customForbidden])
3063
+ ];
3369
3064
  const config = {
3370
3065
  enabled: true,
3371
3066
  allowedDirectory,
@@ -3387,7 +3082,7 @@ function loadShellConfig() {
3387
3082
  throw new Error(`SHELL_ALLOWED_DIRECTORY is not a directory: ${allowedDirectory}`);
3388
3083
  }
3389
3084
  config.allowedDirectory = path3.resolve(allowedDirectory);
3390
- logger7.info(`Shell plugin enabled with allowed directory: ${config.allowedDirectory}, ` + `background: ${allowBackground}, timeout: ${timeout}ms`);
3085
+ logger5.info(`Shell plugin enabled with allowed directory: ${config.allowedDirectory}, ` + `background: ${allowBackground}, timeout: ${timeout}ms`);
3391
3086
  } catch (error) {
3392
3087
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
3393
3088
  throw new Error(`SHELL_ALLOWED_DIRECTORY does not exist: ${allowedDirectory}`);
@@ -3398,35 +3093,42 @@ function loadShellConfig() {
3398
3093
  }
3399
3094
  // utils/pathUtils.ts
3400
3095
  import path4 from "node:path";
3401
- import { logger as logger8 } from "@elizaos/core";
3096
+ import { logger as logger6 } from "@elizaos/core";
3402
3097
  function validatePath(commandPath, allowedDir, currentDir) {
3403
3098
  const resolvedPath = path4.resolve(currentDir, commandPath);
3404
3099
  const normalizedPath = path4.normalize(resolvedPath);
3405
3100
  const normalizedAllowed = path4.normalize(allowedDir);
3406
3101
  if (!normalizedPath.startsWith(normalizedAllowed)) {
3407
- logger8.warn(`Path validation failed: ${normalizedPath} is outside allowed directory ${normalizedAllowed}`);
3102
+ logger6.warn(`Path validation failed: ${normalizedPath} is outside allowed directory ${normalizedAllowed}`);
3408
3103
  return null;
3409
3104
  }
3410
3105
  return normalizedPath;
3411
3106
  }
3412
3107
  function isSafeCommand(command) {
3413
3108
  const pathTraversalPatterns = [/\.\.\//g, /\.\.\\/g, /\/\.\./g, /\\\.\./g];
3414
- const dangerousPatterns = [/\$\(/g, /`[^']*`/g, /\|\s*sudo/g, /;\s*sudo/g, /&\s*&/g, /\|\s*\|/g];
3109
+ const dangerousPatterns = [
3110
+ /\$\(/g,
3111
+ /`[^']*`/g,
3112
+ /\|\s*sudo/g,
3113
+ /;\s*sudo/g,
3114
+ /&\s*&/g,
3115
+ /\|\s*\|/g
3116
+ ];
3415
3117
  for (const pattern of pathTraversalPatterns) {
3416
3118
  if (pattern.test(command)) {
3417
- logger8.warn(`Path traversal detected in command: ${command}`);
3119
+ logger6.warn(`Path traversal detected in command: ${command}`);
3418
3120
  return false;
3419
3121
  }
3420
3122
  }
3421
3123
  for (const pattern of dangerousPatterns) {
3422
3124
  if (pattern.test(command)) {
3423
- logger8.warn(`Dangerous pattern detected in command: ${command}`);
3125
+ logger6.warn(`Dangerous pattern detected in command: ${command}`);
3424
3126
  return false;
3425
3127
  }
3426
3128
  }
3427
3129
  const pipeCount = (command.match(/\|/g) || []).length;
3428
3130
  if (pipeCount > 1) {
3429
- logger8.warn(`Multiple pipes detected in command: ${command}`);
3131
+ logger6.warn(`Multiple pipes detected in command: ${command}`);
3430
3132
  return false;
3431
3133
  }
3432
3134
  return true;
@@ -4159,7 +3861,10 @@ function randomChoice(values, fallback) {
4159
3861
  return values[Math.floor(Math.random() * values.length)] ?? fallback;
4160
3862
  }
4161
3863
  function createSlugBase(words = 2) {
4162
- const parts = [randomChoice(SLUG_ADJECTIVES, "steady"), randomChoice(SLUG_NOUNS, "harbor")];
3864
+ const parts = [
3865
+ randomChoice(SLUG_ADJECTIVES, "steady"),
3866
+ randomChoice(SLUG_NOUNS, "harbor")
3867
+ ];
4163
3868
  if (words > 2) {
4164
3869
  parts.push(randomChoice(SLUG_NOUNS, "reef"));
4165
3870
  }
@@ -4379,7 +4084,7 @@ class ShellService extends Service2 {
4379
4084
  }
4380
4085
  static async start(runtime) {
4381
4086
  const instance = new ShellService(runtime);
4382
- logger9.info("Shell service initialized with PTY, background execution, and history tracking");
4087
+ logger7.info("Shell service initialized with PTY, background execution, and history tracking");
4383
4088
  return instance;
4384
4089
  }
4385
4090
  async stop() {
@@ -4387,13 +4092,13 @@ class ShellService extends Service2 {
4387
4092
  for (const session of runningSessions2) {
4388
4093
  try {
4389
4094
  killSession(session);
4390
- logger9.debug(`Killed shell session: ${session.id}`);
4095
+ logger7.debug(`Killed shell session: ${session.id}`);
4391
4096
  } catch (err) {
4392
- logger9.warn(`Failed to kill shell session ${session.id}: ${err}`);
4097
+ logger7.warn(`Failed to kill shell session ${session.id}: ${err}`);
4393
4098
  }
4394
4099
  }
4395
4100
  this.commandHistory.clear();
4396
- logger9.info(`Shell service stopped, cleaned up ${runningSessions2.length} running sessions`);
4101
+ logger7.info(`Shell service stopped, cleaned up ${runningSessions2.length} running sessions`);
4397
4102
  }
4398
4103
  get capabilityDescription() {
4399
4104
  return "Execute shell commands with PTY support, background execution, and session management";
@@ -4415,7 +4120,7 @@ class ShellService extends Service2 {
4415
4120
  if (this.runtime && this.runtime.sandboxMode) {
4416
4121
  const hostApiUrl = this.runtime.getSetting("SANDBOX_HOST_API_URL") ?? "http://localhost:2138";
4417
4122
  const runtimeFetch = this.runtime.fetch ?? globalThis.fetch;
4418
- logger9.info(`[shell:sandbox] routing exec to ${hostApiUrl}: ${command.substring(0, 100)}`);
4123
+ logger7.info(`[shell:sandbox] routing exec to ${hostApiUrl}: ${command.substring(0, 100)}`);
4419
4124
  try {
4420
4125
  const response = await runtimeFetch(`${hostApiUrl}/api/sandbox/exec`, {
4421
4126
  method: "POST",
@@ -4427,7 +4132,7 @@ class ShellService extends Service2 {
4427
4132
  })
4428
4133
  });
4429
4134
  const result2 = await response.json();
4430
- logger9.info(`[shell:sandbox] exec completed: exit=${result2.exitCode} duration=${result2.durationMs}ms`);
4135
+ logger7.info(`[shell:sandbox] exec completed: exit=${result2.exitCode} duration=${result2.durationMs}ms`);
4431
4136
  return {
4432
4137
  success: result2.exitCode === 0,
4433
4138
  stdout: result2.stdout,
@@ -4437,7 +4142,7 @@ class ShellService extends Service2 {
4437
4142
  };
4438
4143
  } catch (err) {
4439
4144
  const errMsg = err instanceof Error ? err.message : String(err);
4440
- logger9.error(`[shell:sandbox] exec failed: ${errMsg}`);
4145
+ logger7.error(`[shell:sandbox] exec failed: ${errMsg}`);
4441
4146
  return {
4442
4147
  success: false,
4443
4148
  stdout: "",
@@ -5049,7 +4754,7 @@ Warnings:
5049
4754
  }
5050
4755
  clearCommandHistory(conversationId) {
5051
4756
  this.commandHistory.delete(conversationId);
5052
- logger9.info(`Cleared command history for conversation: ${conversationId}`);
4757
+ logger7.info(`Cleared command history for conversation: ${conversationId}`);
5053
4758
  }
5054
4759
  getCurrentDirectory(_conversationId) {
5055
4760
  return this.currentDirectory;
@@ -5109,12 +4814,12 @@ Warnings:
5109
4814
  if (useShell) {
5110
4815
  cmd = "sh";
5111
4816
  args = ["-c", command];
5112
- logger9.info(`Executing shell command: sh -c "${command}" in ${this.currentDirectory}`);
4817
+ logger7.info(`Executing shell command: sh -c "${command}" in ${this.currentDirectory}`);
5113
4818
  } else {
5114
4819
  const parts = command.split(/\s+/);
5115
4820
  cmd = parts[0];
5116
4821
  args = parts.slice(1);
5117
- logger9.info(`Executing command: ${cmd} ${args.join(" ")} in ${this.currentDirectory}`);
4822
+ logger7.info(`Executing command: ${cmd} ${args.join(" ")} in ${this.currentDirectory}`);
5118
4823
  }
5119
4824
  let stdout = "";
5120
4825
  let stderr = "";
@@ -5219,7 +4924,7 @@ Command timed out`,
5219
4924
  } catch (err) {
5220
4925
  const errText = String(err);
5221
4926
  const warning = `Warning: PTY spawn failed (${errText}); retrying without PTY.`;
5222
- logger9.warn(`exec: PTY spawn failed (${errText}); retrying without PTY.`);
4927
+ logger7.warn(`exec: PTY spawn failed (${errText}); retrying without PTY.`);
5223
4928
  opts.warnings.push(warning);
5224
4929
  }
5225
4930
  }
@@ -5508,16 +5213,17 @@ ${String(err)}` : String(err);
5508
5213
  // index.ts
5509
5214
  var shellPlugin = {
5510
5215
  name: "shell",
5511
- description: "Execute shell commands with PTY support, background execution, session management, and approval workflows",
5216
+ description: "Shell observability and history management providers",
5512
5217
  services: [ShellService, ExecApprovalService],
5513
- actions: [executeCommand, clearHistory, processAction],
5514
- providers: [shellHistoryProvider]
5218
+ actions: [clearHistory],
5219
+ providers: [shellHistoryProvider, terminalUsageProvider]
5515
5220
  };
5516
5221
  var typescript_default = shellPlugin;
5517
5222
  export {
5518
5223
  validatePath,
5519
5224
  truncateMiddle,
5520
5225
  trimWithCap,
5226
+ terminalUsageProvider,
5521
5227
  tail,
5522
5228
  stripDsrRequests,
5523
5229
  spawnWithFallback,
@@ -5539,7 +5245,6 @@ export {
5539
5245
  recordAllowlistUse,
5540
5246
  readEnvInt,
5541
5247
  readApprovalsSnapshot,
5542
- processAction,
5543
5248
  pad,
5544
5249
  normalizeSafeBins,
5545
5250
  normalizeApprovals,
@@ -5565,7 +5270,6 @@ export {
5565
5270
  formatSpawnError,
5566
5271
  formatDuration,
5567
5272
  extractBaseCommand,
5568
- executeCommand,
5569
5273
  evaluateShellAllowlist,
5570
5274
  evaluateExecAllowlist,
5571
5275
  ensureApprovals,
@@ -5595,4 +5299,4 @@ export {
5595
5299
  BRACKETED_PASTE_END
5596
5300
  };
5597
5301
 
5598
- //# debugId=20C8338CDBDDBAFA64756E2164756E21
5302
+ //# debugId=EB43D3D65D87A50A64756E2164756E21