replicas-cli 0.2.758 → 0.2.760
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.
- package/dist/index.cjs +69 -59
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -22927,12 +22927,14 @@ function coerceClaudePartialMessagePayload(payload) {
|
|
|
22927
22927
|
const parentToolUseId = payload.parent_tool_use_id;
|
|
22928
22928
|
const text2 = typeof payload.text === "string" && payload.text ? payload.text : void 0;
|
|
22929
22929
|
const thinking = typeof payload.thinking === "string" && payload.thinking ? payload.thinking : void 0;
|
|
22930
|
-
|
|
22930
|
+
const tool = isRecord(payload.tool) && typeof payload.tool.id === "string" && typeof payload.tool.name === "string" ? typeof payload.tool.filePath === "string" ? { id: payload.tool.id, name: payload.tool.name, filePath: payload.tool.filePath } : typeof payload.tool.command === "string" ? { id: payload.tool.id, name: payload.tool.name, command: payload.tool.command } : void 0 : void 0;
|
|
22931
|
+
if (!text2 && !thinking && !tool) return null;
|
|
22931
22932
|
return {
|
|
22932
22933
|
streamId,
|
|
22933
22934
|
parent_tool_use_id: typeof parentToolUseId === "string" ? parentToolUseId : null,
|
|
22934
22935
|
...text2 ? { text: text2 } : {},
|
|
22935
22936
|
...thinking ? { thinking } : {},
|
|
22937
|
+
...tool ? { tool } : {},
|
|
22936
22938
|
status: payload.status === "completed" ? "completed" : "in_progress"
|
|
22937
22939
|
};
|
|
22938
22940
|
}
|
|
@@ -25404,7 +25406,7 @@ In agent mode the CLI hides commands that don't make sense for in-workspace agen
|
|
|
25404
25406
|
| \`replicas whoami\` | Print the workspace + org identity |
|
|
25405
25407
|
| \`replicas identity token [--audience <aud>]\` | Print the current short-lived workspace identity token for an audience |
|
|
25406
25408
|
| \`replicas identity token --format gcp --audience <aud>\` | Supply a current token to Google's executable credential source |
|
|
25407
|
-
| \`replicas identity aws-credentials --role-arn <arn> [--region <region>]\` | Exchange the current token for AWS credential_process JSON (requires AWS CLI) |
|
|
25409
|
+
| \`replicas identity aws-credentials --role-arn <arn> [--region <region>] [--source-identity]\` | Exchange the current token for AWS credential_process JSON (requires AWS CLI); \`--source-identity\` records the workspace ID in CloudTrail and needs \`sts:SetSourceIdentity\` in the role trust policy |
|
|
25408
25410
|
| \`replicas identity exec [--audience <aud>] -- <command>\` | Run a command with the current token and audience in its environment |
|
|
25409
25411
|
| \`replicas init\` | Create a \`replicas.json\` / \`replicas.yaml\` in the current directory |
|
|
25410
25412
|
| \`replicas connect <name>\` | SSH into another workspace (requires user creds \u2014 usually only useful when scripting locally) |
|
|
@@ -27062,6 +27064,51 @@ function parseMcpToolName(name) {
|
|
|
27062
27064
|
|
|
27063
27065
|
// ../shared/src/display-message/parsers/claude-parser.ts
|
|
27064
27066
|
var ABORTED_TERMINAL_REASONS = /* @__PURE__ */ new Set(["aborted_streaming", "aborted_tools"]);
|
|
27067
|
+
var COMMAND_TOOL_NAMES = /* @__PURE__ */ new Set(["Bash", "bash", "shell"]);
|
|
27068
|
+
var FILE_TOOL_NAMES = /* @__PURE__ */ new Set(["Write", "Edit"]);
|
|
27069
|
+
function fileOrCommandMessage(toolName, toolUseId, input, timestamp) {
|
|
27070
|
+
if (COMMAND_TOOL_NAMES.has(toolName)) {
|
|
27071
|
+
const command = typeof input.command === "string" ? input.command : "";
|
|
27072
|
+
const skillNames = skillNamesFromCommand(command);
|
|
27073
|
+
return {
|
|
27074
|
+
id: `command-${toolUseId}`,
|
|
27075
|
+
type: "command",
|
|
27076
|
+
command,
|
|
27077
|
+
...skillNames.length > 0 ? { skillNames } : {},
|
|
27078
|
+
output: "",
|
|
27079
|
+
status: "in_progress",
|
|
27080
|
+
timestamp
|
|
27081
|
+
};
|
|
27082
|
+
}
|
|
27083
|
+
const filePath = typeof input.file_path === "string" ? input.file_path : "";
|
|
27084
|
+
let diff;
|
|
27085
|
+
if (toolName === "Edit" && typeof input.old_string === "string" && typeof input.new_string === "string") {
|
|
27086
|
+
const oldLines = input.old_string.replace(/\n$/, "").split("\n");
|
|
27087
|
+
const newLines = input.new_string.replace(/\n$/, "").split("\n");
|
|
27088
|
+
diff = [
|
|
27089
|
+
`--- a/${filePath}`,
|
|
27090
|
+
`+++ b/${filePath}`,
|
|
27091
|
+
`@@ -1,${oldLines.length} +1,${newLines.length} @@`,
|
|
27092
|
+
...oldLines.map((l) => `-${l}`),
|
|
27093
|
+
...newLines.map((l) => `+${l}`)
|
|
27094
|
+
].join("\n");
|
|
27095
|
+
} else if (toolName === "Write" && typeof input.content === "string") {
|
|
27096
|
+
const newLines = input.content.replace(/\n$/, "").split("\n");
|
|
27097
|
+
diff = [
|
|
27098
|
+
`--- /dev/null`,
|
|
27099
|
+
`+++ b/${filePath}`,
|
|
27100
|
+
`@@ -0,0 +1,${newLines.length} @@`,
|
|
27101
|
+
...newLines.map((l) => `+${l}`)
|
|
27102
|
+
].join("\n");
|
|
27103
|
+
}
|
|
27104
|
+
return {
|
|
27105
|
+
id: `patch-${toolUseId}`,
|
|
27106
|
+
type: "patch",
|
|
27107
|
+
operations: [{ action: toolName === "Write" ? "add" : "update", path: filePath, diff }],
|
|
27108
|
+
status: "in_progress",
|
|
27109
|
+
timestamp
|
|
27110
|
+
};
|
|
27111
|
+
}
|
|
27065
27112
|
function createSubagentMessage(messageIndex, timestamp, fields) {
|
|
27066
27113
|
const { id = `subagent-${timestamp}-${messageIndex}`, ...message } = fields;
|
|
27067
27114
|
return { id, type: "subagent", ...message, timestamp };
|
|
@@ -27098,6 +27145,7 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
27098
27145
|
const workflowAgentMessageMap = /* @__PURE__ */ new Map();
|
|
27099
27146
|
const ambientTaskIds = /* @__PURE__ */ new Set();
|
|
27100
27147
|
const partialIndexes = /* @__PURE__ */ new Map();
|
|
27148
|
+
const streamingTools = /* @__PURE__ */ new Map();
|
|
27101
27149
|
const completedStreamIds = /* @__PURE__ */ new Set();
|
|
27102
27150
|
const supersededStreamIds = /* @__PURE__ */ new Set();
|
|
27103
27151
|
let liveStreamId = null;
|
|
@@ -27175,6 +27223,7 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
27175
27223
|
if (existing.agent !== void 0) messages[existing.agent] = agentMessage;
|
|
27176
27224
|
else existing.agent = messages.push(agentMessage) - 1;
|
|
27177
27225
|
}
|
|
27226
|
+
if (payload.tool) streamingTools.set(payload.streamId, { tool: payload.tool, timestamp: event.timestamp });
|
|
27178
27227
|
partialIndexes.set(payload.streamId, existing);
|
|
27179
27228
|
return;
|
|
27180
27229
|
}
|
|
@@ -27301,56 +27350,9 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
27301
27350
|
status: "in_progress",
|
|
27302
27351
|
nestedEvents
|
|
27303
27352
|
}));
|
|
27304
|
-
} else if (toolName
|
|
27353
|
+
} else if (COMMAND_TOOL_NAMES.has(toolName) || FILE_TOOL_NAMES.has(toolName)) {
|
|
27305
27354
|
const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
|
|
27306
|
-
|
|
27307
|
-
const skillNames = skillNamesFromCommand(command);
|
|
27308
|
-
messages.push({
|
|
27309
|
-
id: `command-${event.timestamp}-${messages.length}`,
|
|
27310
|
-
type: "command",
|
|
27311
|
-
command,
|
|
27312
|
-
...skillNames.length > 0 ? { skillNames } : {},
|
|
27313
|
-
output: "",
|
|
27314
|
-
status: "in_progress",
|
|
27315
|
-
timestamp: event.timestamp
|
|
27316
|
-
});
|
|
27317
|
-
} else if (toolName === "Write" || toolName === "Edit") {
|
|
27318
|
-
const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
|
|
27319
|
-
const filePath = inputObj.file_path || "";
|
|
27320
|
-
const action = toolName === "Write" ? "add" : "update";
|
|
27321
|
-
let diff;
|
|
27322
|
-
if (toolName === "Edit" && inputObj.old_string != null && inputObj.new_string != null) {
|
|
27323
|
-
const oldLines = inputObj.old_string.replace(/\n$/, "").split("\n");
|
|
27324
|
-
const newLines = inputObj.new_string.replace(/\n$/, "").split("\n");
|
|
27325
|
-
const hunk = `@@ -1,${oldLines.length} +1,${newLines.length} @@`;
|
|
27326
|
-
diff = [
|
|
27327
|
-
`--- a/${filePath}`,
|
|
27328
|
-
`+++ b/${filePath}`,
|
|
27329
|
-
hunk,
|
|
27330
|
-
...oldLines.map((l) => `-${l}`),
|
|
27331
|
-
...newLines.map((l) => `+${l}`)
|
|
27332
|
-
].join("\n");
|
|
27333
|
-
} else if (toolName === "Write" && inputObj.content != null) {
|
|
27334
|
-
const newLines = inputObj.content.replace(/\n$/, "").split("\n");
|
|
27335
|
-
const hunk = `@@ -0,0 +1,${newLines.length} @@`;
|
|
27336
|
-
diff = [
|
|
27337
|
-
`--- /dev/null`,
|
|
27338
|
-
`+++ b/${filePath}`,
|
|
27339
|
-
hunk,
|
|
27340
|
-
...newLines.map((l) => `+${l}`)
|
|
27341
|
-
].join("\n");
|
|
27342
|
-
}
|
|
27343
|
-
messages.push({
|
|
27344
|
-
id: `patch-${event.timestamp}-${messages.length}`,
|
|
27345
|
-
type: "patch",
|
|
27346
|
-
operations: [{
|
|
27347
|
-
action,
|
|
27348
|
-
path: filePath,
|
|
27349
|
-
diff
|
|
27350
|
-
}],
|
|
27351
|
-
status: "in_progress",
|
|
27352
|
-
timestamp: event.timestamp
|
|
27353
|
-
});
|
|
27355
|
+
messages.push(fileOrCommandMessage(toolName, toolUseId, inputObj, event.timestamp));
|
|
27354
27356
|
} else if (toolName === "TaskCreate" || toolName === "TaskUpdate" || toolName === "TaskList") {
|
|
27355
27357
|
taskAccumulator.processContentBlock(block);
|
|
27356
27358
|
const snapshot = taskSnapshot();
|
|
@@ -27530,6 +27532,11 @@ function parseClaudeEvents(events, parentToolUseId) {
|
|
|
27530
27532
|
};
|
|
27531
27533
|
}
|
|
27532
27534
|
});
|
|
27535
|
+
for (const [streamId, { tool, timestamp }] of streamingTools) {
|
|
27536
|
+
if (toolCallMap.has(tool.id) || supersededStreamIds.has(streamId)) continue;
|
|
27537
|
+
if (!COMMAND_TOOL_NAMES.has(tool.name) && !FILE_TOOL_NAMES.has(tool.name)) continue;
|
|
27538
|
+
messages.push(fileOrCommandMessage(tool.name, tool.id, "filePath" in tool ? { file_path: tool.filePath } : { command: tool.command }, timestamp));
|
|
27539
|
+
}
|
|
27533
27540
|
filteredEvents.forEach((event) => {
|
|
27534
27541
|
if (event.type === "claude-user") {
|
|
27535
27542
|
const content = normalizeContentBlocks(event.payload.message?.content);
|
|
@@ -28011,7 +28018,7 @@ var headlessFilesystemAgentResultSchema = external_exports.object({
|
|
|
28011
28018
|
});
|
|
28012
28019
|
|
|
28013
28020
|
// ../shared/src/cli-version.ts
|
|
28014
|
-
var CLI_VERSION = "0.2.
|
|
28021
|
+
var CLI_VERSION = "0.2.760";
|
|
28015
28022
|
|
|
28016
28023
|
// ../shared/src/version.ts
|
|
28017
28024
|
function compareVersions(v1, v2) {
|
|
@@ -28702,6 +28709,7 @@ async function readSseStream(body, onEvent, shouldContinue = () => true) {
|
|
|
28702
28709
|
var import_yaml2 = __toESM(require_dist());
|
|
28703
28710
|
|
|
28704
28711
|
// ../shared/src/workspace-identity.ts
|
|
28712
|
+
var AWS_SOURCE_IDENTITY_CLAIM = "https://aws.amazon.com/source_identity";
|
|
28705
28713
|
var WORKSPACE_TOKEN_TTL_SECONDS = 15 * 60;
|
|
28706
28714
|
var IDENTITY_PROXY_PORT = 17323;
|
|
28707
28715
|
var IDENTITY_TOKEN_PATH = "/token";
|
|
@@ -28711,7 +28719,8 @@ var WORKSPACE_TOKEN_ENV = {
|
|
|
28711
28719
|
};
|
|
28712
28720
|
var workspaceAudienceSchema = external_exports.string().min(1).max(255).regex(/^[\x21-\x7e]+$/, "Audience must be a single printable token without spaces");
|
|
28713
28721
|
var workspaceTokenRequestSchema = external_exports.object({
|
|
28714
|
-
audience: workspaceAudienceSchema.optional()
|
|
28722
|
+
audience: workspaceAudienceSchema.optional(),
|
|
28723
|
+
aws_source_identity: external_exports.boolean().optional()
|
|
28715
28724
|
});
|
|
28716
28725
|
var workspaceTokenClaimsSchema = external_exports.object({
|
|
28717
28726
|
iss: external_exports.string(),
|
|
@@ -28725,7 +28734,8 @@ var workspaceTokenClaimsSchema = external_exports.object({
|
|
|
28725
28734
|
workspace_id: external_exports.string().uuid(),
|
|
28726
28735
|
environment_id: external_exports.string().uuid(),
|
|
28727
28736
|
creator_id: external_exports.string().uuid().nullable(),
|
|
28728
|
-
creator_email: external_exports.string().nullable().default(null)
|
|
28737
|
+
creator_email: external_exports.string().nullable().default(null),
|
|
28738
|
+
[AWS_SOURCE_IDENTITY_CLAIM]: external_exports.string().uuid().optional()
|
|
28729
28739
|
}).passthrough();
|
|
28730
28740
|
var workspaceTokenResponseSchema = external_exports.object({
|
|
28731
28741
|
issuer: external_exports.string(),
|
|
@@ -29249,13 +29259,13 @@ var import_node_child_process = require("child_process");
|
|
|
29249
29259
|
var import_node_os = require("os");
|
|
29250
29260
|
var import_node_path = require("path");
|
|
29251
29261
|
var import_chalk5 = __toESM(require("chalk"));
|
|
29252
|
-
async function fetchToken(audience) {
|
|
29262
|
+
async function fetchToken(audience, awsSourceIdentity) {
|
|
29253
29263
|
let response;
|
|
29254
29264
|
try {
|
|
29255
29265
|
response = await fetch(identityTokenUrl(), {
|
|
29256
29266
|
method: "POST",
|
|
29257
29267
|
headers: { "content-type": "application/json" },
|
|
29258
|
-
body: JSON.stringify(audience
|
|
29268
|
+
body: JSON.stringify({ audience: audience || void 0, aws_source_identity: awsSourceIdentity || void 0 })
|
|
29259
29269
|
});
|
|
29260
29270
|
} catch {
|
|
29261
29271
|
return createErrorResult({ message: "Workspace identity is only available inside a running Replicas workspace." });
|
|
@@ -29310,7 +29320,7 @@ async function identityExecCommand(command, options) {
|
|
|
29310
29320
|
process.exit(result.status ?? 1);
|
|
29311
29321
|
}
|
|
29312
29322
|
async function identityAwsCredentialsCommand(options) {
|
|
29313
|
-
const key = (0, import_node_crypto.createHash)("sha256").update(JSON.stringify([options.roleArn, options.audience, options.region, options.sessionName])).digest("hex");
|
|
29323
|
+
const key = (0, import_node_crypto.createHash)("sha256").update(JSON.stringify([options.roleArn, options.audience, options.region, options.sessionName, options.sourceIdentity])).digest("hex");
|
|
29314
29324
|
const cacheFile = (0, import_node_path.join)((0, import_node_os.homedir)(), ".replicas", "aws-credentials", `${key}.json`);
|
|
29315
29325
|
try {
|
|
29316
29326
|
const cached2 = (0, import_node_fs.readFileSync)(cacheFile, "utf8");
|
|
@@ -29320,7 +29330,7 @@ async function identityAwsCredentialsCommand(options) {
|
|
|
29320
29330
|
}
|
|
29321
29331
|
} catch {
|
|
29322
29332
|
}
|
|
29323
|
-
const result = await fetchToken(options.audience);
|
|
29333
|
+
const result = await fetchToken(options.audience, options.sourceIdentity);
|
|
29324
29334
|
if (!result.ok) {
|
|
29325
29335
|
console.error(import_chalk5.default.red(result.error.message));
|
|
29326
29336
|
process.exitCode = 1;
|
|
@@ -33898,7 +33908,7 @@ if (isEnvironmentSetupWorkspace()) {
|
|
|
33898
33908
|
if (isAgentMode()) {
|
|
33899
33909
|
const identity = program.command("identity").description("Obtain short-lived workspace identity tokens (OIDC) for the services this workspace calls");
|
|
33900
33910
|
identity.command("token").description("Print a workspace token for an audience (defaults to replicas:workspace)").option("-a, --audience <audience>", "Audience (`aud`) the receiving service verifies, for example its URL").addOption(new import_commander.Option("--format <format>", "Output a raw token or Google executable credentials").choices(["text", "gcp"]).default("text")).action(identityTokenCommand);
|
|
33901
|
-
identity.command("aws-credentials").description("Exchange the current token for temporary AWS credentials (for AWS credential_process)").requiredOption("--role-arn <arn>", "IAM role that trusts the Replicas issuer").option("-a, --audience <audience>", "Audience configured on the IAM OIDC provider", "sts.amazonaws.com").option("--region <region>", "AWS region for the STS exchange").option("--session-name <name>", "AWS role session name", "replicas").action(identityAwsCredentialsCommand);
|
|
33911
|
+
identity.command("aws-credentials").description("Exchange the current token for temporary AWS credentials (for AWS credential_process)").requiredOption("--role-arn <arn>", "IAM role that trusts the Replicas issuer").option("-a, --audience <audience>", "Audience configured on the IAM OIDC provider", "sts.amazonaws.com").option("--region <region>", "AWS region for the STS exchange").option("--session-name <name>", "AWS role session name", "replicas").option("--source-identity", "Record the workspace ID as the AWS source identity (role trust policy must allow sts:SetSourceIdentity)").action(identityAwsCredentialsCommand);
|
|
33902
33912
|
identity.command("exec [command...]").description("Run a command with REPLICAS_WORKSPACE_TOKEN set to a fresh token: replicas identity exec -- curl ...").option("-a, --audience <audience>", "Audience (`aud`) the receiving service verifies").action((command, options) => identityExecCommand(command, options));
|
|
33903
33913
|
const service = program.command("service").description("Run long-lived services (dev servers, daemons) detached from the agent session so they survive workspace sleep/wake");
|
|
33904
33914
|
service.command("start <name> [command...]").description('Start (or restart) a named service as a detached daemon. Quote shell operators: replicas service start web "cd app && bun dev"').option("-d, --cwd <dir>", "Working directory for the service (defaults to the current directory)").action(async (name, commandParts, options) => {
|