replicas-cli 0.2.458 → 0.2.460

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 (2) hide show
  1. package/dist/index.mjs +88 -7
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -8105,7 +8105,7 @@ var ENTERPRISE_PLAN = PLANS.enterprise;
8105
8105
 
8106
8106
  // ../shared/src/sandbox.ts
8107
8107
  var SANDBOX_LIFECYCLE = {
8108
- AUTO_STOP_MINUTES: 6 * 60,
8108
+ AUTO_STOP_MINUTES: 60,
8109
8109
  AUTO_ARCHIVE_MINUTES: 60 * 24 * 7,
8110
8110
  AUTO_DELETE_MINUTES: -1,
8111
8111
  SSH_TOKEN_EXPIRATION_MINUTES: 3 * 60
@@ -10078,7 +10078,7 @@ function formatTurnElapsed(ms) {
10078
10078
  }
10079
10079
 
10080
10080
  // ../shared/src/cli-version.ts
10081
- var CLI_VERSION = "0.2.458";
10081
+ var CLI_VERSION = "0.2.460";
10082
10082
 
10083
10083
  // ../shared/src/version.ts
10084
10084
  function compareVersions(v1, v2) {
@@ -25076,16 +25076,27 @@ function parseSkillName(tool, input) {
25076
25076
  const skillName = parsedInput.skill ?? parsedInput.name;
25077
25077
  return typeof skillName === "string" && skillName ? skillName : null;
25078
25078
  }
25079
+ function skillNameFromFilePath(path6) {
25080
+ const skillName = skillNameFromSkillRootPath(path6);
25081
+ if (skillName) return skillName;
25082
+ const parts = path6.split(/[\\/]+/).filter(Boolean);
25083
+ if (parts.length < 2 || parts[parts.length - 1].toLowerCase() !== "skill.md") return null;
25084
+ const fallbackSkillName = parts[parts.length - 2];
25085
+ return fallbackSkillName && fallbackSkillName.toLowerCase() !== "skills" ? fallbackSkillName : null;
25086
+ }
25087
+ function skillNameFromSkillRootPath(path6) {
25088
+ const parts = path6.split(/[\\/]+/).filter(Boolean);
25089
+ const skillsIndex = parts.findLastIndex((part) => part.toLowerCase() === "skills");
25090
+ if (skillsIndex === -1) return null;
25091
+ const skillName = parts[skillsIndex + 1];
25092
+ return skillName && skillName.toLowerCase() !== "skill.md" ? skillName : null;
25093
+ }
25079
25094
  function parseSkillFilePath(input) {
25080
25095
  const parsedInput = typeof input === "string" ? safeJsonParse(input, null) : input;
25081
25096
  if (!isRecord(parsedInput)) return null;
25082
25097
  const path6 = [parsedInput.path, parsedInput.filePath, parsedInput.file_path].find((value) => typeof value === "string" && value.length > 0);
25083
25098
  if (!path6) return null;
25084
- const parts = path6.split(/[\\/]+/).filter(Boolean);
25085
- if (parts.length < 2) return null;
25086
- if (parts[parts.length - 1].toLowerCase() !== "skill.md") return null;
25087
- const skillName = parts[parts.length - 2];
25088
- return skillName && skillName.toLowerCase() !== "skills" ? skillName : null;
25099
+ return skillNameFromFilePath(path6);
25089
25100
  }
25090
25101
  function skillNameFromToolCall(tool, input) {
25091
25102
  const directSkillName = parseSkillName(tool, input);
@@ -25110,6 +25121,70 @@ function formatStoppedAfter(durationMs) {
25110
25121
  if (durationMs === void 0) return "You stopped";
25111
25122
  return `You stopped after ${formatTurnElapsed(durationMs)}`;
25112
25123
  }
25124
+ function unquoteShellArg(value) {
25125
+ const trimmed = value.trim();
25126
+ if (trimmed.length < 2) return trimmed;
25127
+ if (trimmed[0] === "'" && trimmed[trimmed.length - 1] === "'") {
25128
+ return trimmed.slice(1, -1).replace(/'\\''/g, "'");
25129
+ }
25130
+ if (trimmed[0] === '"' && trimmed[trimmed.length - 1] === '"') {
25131
+ return trimmed.slice(1, -1).replace(/\\(["\\$`])/g, "$1");
25132
+ }
25133
+ return trimmed;
25134
+ }
25135
+ function shellPayload(command) {
25136
+ const match = command.trim().match(/^(?:\S*\/)?(?:ba|z|c|fi)?sh\s+-(?:[a-zA-Z]*c[a-zA-Z]*|c)\s+([\s\S]+)$/);
25137
+ return match ? unquoteShellArg(match[1]) : command.trim();
25138
+ }
25139
+ function splitShellWords(command) {
25140
+ const words = [];
25141
+ let word = "";
25142
+ let quote = null;
25143
+ let escaped = false;
25144
+ for (const char of command) {
25145
+ if (escaped) {
25146
+ word += char;
25147
+ escaped = false;
25148
+ continue;
25149
+ }
25150
+ if (char === "\\" && quote !== "'") {
25151
+ escaped = true;
25152
+ continue;
25153
+ }
25154
+ if (quote) {
25155
+ if (char === quote) quote = null;
25156
+ else word += char;
25157
+ continue;
25158
+ }
25159
+ if (char === '"' || char === "'") {
25160
+ quote = char;
25161
+ continue;
25162
+ }
25163
+ if (/\s/.test(char)) {
25164
+ if (word) {
25165
+ words.push(word);
25166
+ word = "";
25167
+ }
25168
+ continue;
25169
+ }
25170
+ word += char;
25171
+ }
25172
+ if (word) words.push(word);
25173
+ return words;
25174
+ }
25175
+ function commandWords(command) {
25176
+ const payload = shellPayload(command);
25177
+ if (!payload || /[;|<>]|&&/.test(payload)) return null;
25178
+ return splitShellWords(payload);
25179
+ }
25180
+ function skillNamesFromCommand(command) {
25181
+ const words = commandWords(command);
25182
+ if (!words) return [];
25183
+ return Array.from(new Set(words.flatMap((word) => {
25184
+ const skillName = skillNameFromSkillRootPath(word);
25185
+ return skillName ? [skillName] : [];
25186
+ })));
25187
+ }
25113
25188
 
25114
25189
  // ../shared/src/user-message-matching.ts
25115
25190
  function parseTimestampMs(timestamp) {
@@ -25294,10 +25369,12 @@ function parseCodexEvents(events) {
25294
25369
  const callId = event.payload.call_id;
25295
25370
  const args = safeJsonParse(event.payload.arguments || "{}", {});
25296
25371
  const command = args.cmd || (Array.isArray(args.command) ? args.command.join(" ") : args.command) || "";
25372
+ const skillNames = skillNamesFromCommand(command);
25297
25373
  const msg = {
25298
25374
  id: `command-${callId || "no-call-id"}-${eventIndex}`,
25299
25375
  type: "command",
25300
25376
  command,
25377
+ ...skillNames.length > 0 ? { skillNames } : {},
25301
25378
  output: "",
25302
25379
  status: "in_progress",
25303
25380
  timestamp: event.timestamp
@@ -26170,10 +26247,12 @@ function parseClaudeEvents(events, parentToolUseId) {
26170
26247
  } else if (toolName === "Bash" || toolName === "bash" || toolName === "shell") {
26171
26248
  const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
26172
26249
  const command = inputObj.command || "";
26250
+ const skillNames = skillNamesFromCommand(command);
26173
26251
  messages.push({
26174
26252
  id: `command-${event.timestamp}-${messages.length}`,
26175
26253
  type: "command",
26176
26254
  command,
26255
+ ...skillNames.length > 0 ? { skillNames } : {},
26177
26256
  output: "",
26178
26257
  status: "in_progress",
26179
26258
  timestamp: event.timestamp
@@ -26493,10 +26572,12 @@ function messageForItem(item) {
26493
26572
  };
26494
26573
  }
26495
26574
  if (item.type === "commandExecution") {
26575
+ const skillNames = skillNamesFromCommand(item.command);
26496
26576
  return {
26497
26577
  id: `command-${item.id}`,
26498
26578
  type: "command",
26499
26579
  command: item.command,
26580
+ ...skillNames.length > 0 ? { skillNames } : {},
26500
26581
  output: item.output,
26501
26582
  exitCode: item.exitCode ?? void 0,
26502
26583
  status: normalizeCodexAspTranscriptStatus(item.status),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-cli",
3
- "version": "0.2.458",
3
+ "version": "0.2.460",
4
4
  "description": "CLI for managing Replicas workspaces - SSH into cloud dev environments with automatic port forwarding",
5
5
  "main": "dist/index.mjs",
6
6
  "bin": {