replicas-cli 0.2.544 → 0.2.546
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/README.md +1 -1
- package/dist/index.cjs +259 -113
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,7 @@ Display current authenticated user.
|
|
|
36
36
|
Display current organization.
|
|
37
37
|
|
|
38
38
|
### `replicas org switch`
|
|
39
|
-
|
|
39
|
+
Choose the organization used by organization-scoped commands. The selection persists across sessions.
|
|
40
40
|
|
|
41
41
|
### `replicas connect <workspace-name>`
|
|
42
42
|
Connect to a workspace via SSH.
|
package/dist/index.cjs
CHANGED
|
@@ -7408,10 +7408,15 @@ function writeConfig(config3) {
|
|
|
7408
7408
|
throw error51;
|
|
7409
7409
|
}
|
|
7410
7410
|
}
|
|
7411
|
-
function
|
|
7412
|
-
|
|
7413
|
-
|
|
7414
|
-
|
|
7411
|
+
function clearAuthentication() {
|
|
7412
|
+
const config3 = readConfig();
|
|
7413
|
+
if (!config3) return;
|
|
7414
|
+
writeConfig({
|
|
7415
|
+
...config3,
|
|
7416
|
+
access_token: "",
|
|
7417
|
+
refresh_token: "",
|
|
7418
|
+
expires_at: 0
|
|
7419
|
+
});
|
|
7415
7420
|
}
|
|
7416
7421
|
function isAuthenticated() {
|
|
7417
7422
|
const config3 = readConfig();
|
|
@@ -7431,6 +7436,7 @@ function setOrganizationId(organizationId) {
|
|
|
7431
7436
|
throw new Error("No config file found. Please login first.");
|
|
7432
7437
|
}
|
|
7433
7438
|
config3.organization_id = organizationId;
|
|
7439
|
+
config3.organization_selection_confirmed = true;
|
|
7434
7440
|
writeConfig(config3);
|
|
7435
7441
|
}
|
|
7436
7442
|
function clearOrganizationId() {
|
|
@@ -7439,12 +7445,20 @@ function clearOrganizationId() {
|
|
|
7439
7445
|
return;
|
|
7440
7446
|
}
|
|
7441
7447
|
delete config3.organization_id;
|
|
7448
|
+
delete config3.organization_selection_confirmed;
|
|
7442
7449
|
writeConfig(config3);
|
|
7443
7450
|
}
|
|
7444
7451
|
function getOrganizationId() {
|
|
7445
7452
|
const config3 = readConfig();
|
|
7446
7453
|
return config3?.organization_id || null;
|
|
7447
7454
|
}
|
|
7455
|
+
function getConfirmedOrganizationId() {
|
|
7456
|
+
const config3 = readConfig();
|
|
7457
|
+
return config3?.organization_selection_confirmed === true ? config3.organization_id || null : null;
|
|
7458
|
+
}
|
|
7459
|
+
function isOrganizationSelectionConfirmed() {
|
|
7460
|
+
return readConfig()?.organization_selection_confirmed === true;
|
|
7461
|
+
}
|
|
7448
7462
|
function setIdeCommand(ideCommand) {
|
|
7449
7463
|
const config3 = readConfig();
|
|
7450
7464
|
if (!config3) {
|
|
@@ -7553,7 +7567,7 @@ async function refreshToken() {
|
|
|
7553
7567
|
}
|
|
7554
7568
|
async function getValidToken() {
|
|
7555
7569
|
const config3 = readConfig();
|
|
7556
|
-
if (!config3) {
|
|
7570
|
+
if (!config3?.access_token) {
|
|
7557
7571
|
throw new NotAuthenticatedError();
|
|
7558
7572
|
}
|
|
7559
7573
|
if (isTokenExpired(config3.expires_at)) {
|
|
@@ -7631,6 +7645,7 @@ var AGENT = {
|
|
|
7631
7645
|
CURSOR: "cursor",
|
|
7632
7646
|
DEEPSEEK: "deepseek",
|
|
7633
7647
|
FX: "fx",
|
|
7648
|
+
KIMI: "kimi",
|
|
7634
7649
|
OPENCODE: "opencode",
|
|
7635
7650
|
PI: "pi",
|
|
7636
7651
|
RELAY: "relay"
|
|
@@ -7672,6 +7687,11 @@ var AGENT_PROVIDER_OPTIONS = [
|
|
|
7672
7687
|
label: "fx",
|
|
7673
7688
|
description: "Use fx for tasks"
|
|
7674
7689
|
},
|
|
7690
|
+
{
|
|
7691
|
+
value: "kimi",
|
|
7692
|
+
label: "Kimi Code",
|
|
7693
|
+
description: "Use Kimi Code for tasks"
|
|
7694
|
+
},
|
|
7675
7695
|
{
|
|
7676
7696
|
value: "opencode",
|
|
7677
7697
|
label: "Opencode",
|
|
@@ -7696,6 +7716,7 @@ var THINKING_LEVELS_BY_AGENT = {
|
|
|
7696
7716
|
cursor: STANDARD_THINKING_LEVELS,
|
|
7697
7717
|
deepseek: STANDARD_THINKING_LEVELS,
|
|
7698
7718
|
fx: STANDARD_THINKING_LEVELS,
|
|
7719
|
+
kimi: STANDARD_THINKING_LEVELS,
|
|
7699
7720
|
opencode: STANDARD_THINKING_LEVELS,
|
|
7700
7721
|
pi: STANDARD_THINKING_LEVELS,
|
|
7701
7722
|
relay: [...STANDARD_THINKING_LEVELS, "ultracode"]
|
|
@@ -7719,6 +7740,8 @@ function getProviderDisplayName(provider, variant = "short") {
|
|
|
7719
7740
|
return variant === "long" ? "DeepSeek Harness" : "DeepSeek";
|
|
7720
7741
|
case "fx":
|
|
7721
7742
|
return "fx";
|
|
7743
|
+
case "kimi":
|
|
7744
|
+
return variant === "long" ? "Kimi Code" : "Kimi";
|
|
7722
7745
|
case "opencode":
|
|
7723
7746
|
return "Opencode";
|
|
7724
7747
|
case "pi":
|
|
@@ -7787,6 +7810,9 @@ var AGENT_CREDENTIAL_METHODS_IN_ORDER = {
|
|
|
7787
7810
|
[AGENT.FX]: [
|
|
7788
7811
|
{ method: CREDENTIAL_METHOD.AI_GATEWAY, credentialType: CREDENTIAL_TYPE.AI_GATEWAY_API_KEY }
|
|
7789
7812
|
],
|
|
7813
|
+
[AGENT.KIMI]: [
|
|
7814
|
+
{ method: CREDENTIAL_METHOD.AI_GATEWAY, credentialType: CREDENTIAL_TYPE.AI_GATEWAY_API_KEY }
|
|
7815
|
+
],
|
|
7790
7816
|
[AGENT.OPENCODE]: [
|
|
7791
7817
|
{ method: CREDENTIAL_METHOD.OPENCODE_GO, credentialType: CREDENTIAL_TYPE.OPENCODE_GO_API_KEY },
|
|
7792
7818
|
{ method: CREDENTIAL_METHOD.ASTER, credentialType: CREDENTIAL_TYPE.ASTER_API_KEY },
|
|
@@ -22401,6 +22427,7 @@ var DEFAULT_OPENCODE_MODEL = "z-ai/glm-5.2";
|
|
|
22401
22427
|
var DEEPSEEK_V4_PRO_MODEL = "deepseek/deepseek-v4-pro-0813";
|
|
22402
22428
|
var DEEPSEEK_V4_FLASH_MODEL = "deepseek/deepseek-v4-flash-0731";
|
|
22403
22429
|
var DEFAULT_FX_MODEL = "zai/glm-5.2";
|
|
22430
|
+
var DEFAULT_KIMI_MODEL = "moonshotai/kimi-k2.6";
|
|
22404
22431
|
var OPENROUTER_MODELS = [
|
|
22405
22432
|
DEFAULT_OPENCODE_MODEL,
|
|
22406
22433
|
DEEPSEEK_V4_PRO_MODEL,
|
|
@@ -22487,6 +22514,7 @@ var AGENT_MODELS = {
|
|
|
22487
22514
|
],
|
|
22488
22515
|
deepseek: prioritizeDeepseekModels(OPENROUTER_MODELS),
|
|
22489
22516
|
fx: [DEFAULT_FX_MODEL],
|
|
22517
|
+
kimi: [DEFAULT_KIMI_MODEL],
|
|
22490
22518
|
opencode: [...OPENROUTER_MODELS, ...ASTER_MODELS],
|
|
22491
22519
|
pi: [...OPENROUTER_MODELS, ...ASTER_MODELS],
|
|
22492
22520
|
relay: [CLAUDE_FABLE_5_MODEL, CLAUDE_OPUS_5_MODEL, CLAUDE_OPUS_4_8_MODEL, CLAUDE_SONNET_5_MODEL]
|
|
@@ -24378,7 +24406,7 @@ var headlessFilesystemAgentResultSchema = external_exports.object({
|
|
|
24378
24406
|
});
|
|
24379
24407
|
|
|
24380
24408
|
// ../shared/src/cli-version.ts
|
|
24381
|
-
var CLI_VERSION = "0.2.
|
|
24409
|
+
var CLI_VERSION = "0.2.546";
|
|
24382
24410
|
|
|
24383
24411
|
// ../shared/src/version.ts
|
|
24384
24412
|
function compareVersions(v1, v2) {
|
|
@@ -25494,71 +25522,146 @@ function parseDeepseekEvents(events) {
|
|
|
25494
25522
|
return messages;
|
|
25495
25523
|
}
|
|
25496
25524
|
|
|
25497
|
-
// ../shared/src/display-message/parsers/
|
|
25498
|
-
|
|
25525
|
+
// ../shared/src/display-message/parsers/acp-parser.ts
|
|
25526
|
+
var FX_CONTEXT_DIAGNOSTIC = /^\[context\] skill catalog omitted .*?(?:\r?\n|$)/;
|
|
25527
|
+
function getAcpTextChunk(update, kind) {
|
|
25499
25528
|
if (!isRecord(update) || update.sessionUpdate !== kind || !isRecord(update.content) || update.content.type !== "text") return null;
|
|
25500
|
-
return typeof update.content.text === "string" && update.content.text ? update.content.text : null;
|
|
25529
|
+
return typeof update.content.text === "string" && update.content.text.length > 0 ? update.content.text : null;
|
|
25501
25530
|
}
|
|
25502
|
-
function
|
|
25531
|
+
function isProviderEvent(event, provider, suffix) {
|
|
25532
|
+
return event.type === `acp-${suffix}` && (event.payload.provider === void 0 || event.payload.provider === provider) || event.type === `${provider}-${suffix}`;
|
|
25533
|
+
}
|
|
25534
|
+
function parseAcpEvents(events, provider) {
|
|
25503
25535
|
const messages = [];
|
|
25536
|
+
const activeChunks = {};
|
|
25537
|
+
const resolvedInputs = /* @__PURE__ */ new Map();
|
|
25538
|
+
let chunkSequence = 0;
|
|
25504
25539
|
for (const event of events) {
|
|
25505
|
-
const
|
|
25506
|
-
if (
|
|
25507
|
-
|
|
25540
|
+
const userContent = getUserMessage(event);
|
|
25541
|
+
if (userContent !== null) {
|
|
25542
|
+
activeChunks.agent_message_chunk = void 0;
|
|
25543
|
+
activeChunks.agent_thought_chunk = void 0;
|
|
25544
|
+
if (userContent.trim()) {
|
|
25508
25545
|
messages.push({
|
|
25509
|
-
id: getUserMessageId(event) ??
|
|
25546
|
+
id: getUserMessageId(event) ?? `${provider}-user-${event.timestamp}`,
|
|
25510
25547
|
type: "user",
|
|
25511
|
-
content,
|
|
25548
|
+
content: userContent,
|
|
25512
25549
|
timestamp: event.timestamp
|
|
25513
25550
|
});
|
|
25514
25551
|
}
|
|
25515
25552
|
continue;
|
|
25516
25553
|
}
|
|
25517
|
-
if (event
|
|
25554
|
+
if (isProviderEvent(event, provider, "error")) {
|
|
25518
25555
|
messages.push({
|
|
25519
|
-
id:
|
|
25556
|
+
id: `${provider}-error-${event.timestamp}`,
|
|
25520
25557
|
type: "error",
|
|
25521
|
-
message: typeof event.payload.message === "string" ? event.payload.message :
|
|
25558
|
+
message: typeof event.payload.message === "string" ? event.payload.message : `${provider} failed`,
|
|
25522
25559
|
timestamp: event.timestamp
|
|
25523
25560
|
});
|
|
25524
25561
|
continue;
|
|
25525
25562
|
}
|
|
25526
|
-
if (event
|
|
25563
|
+
if (isProviderEvent(event, provider, "turn-complete")) {
|
|
25527
25564
|
for (const message of messages) {
|
|
25528
25565
|
if (message.type === "reasoning" && message.status === "in_progress") message.status = "completed";
|
|
25529
25566
|
}
|
|
25567
|
+
activeChunks.agent_message_chunk = void 0;
|
|
25568
|
+
activeChunks.agent_thought_chunk = void 0;
|
|
25569
|
+
continue;
|
|
25570
|
+
}
|
|
25571
|
+
if (event.type === "replicas-tool-input-request" && typeof event.payload.toolUseId === "string" && typeof event.payload.requestId === "string") {
|
|
25572
|
+
const message = messages.find((candidate) => candidate.type === "tool_call" && candidate.id === `${provider}-tool-${event.payload.toolUseId}`);
|
|
25573
|
+
if (message && (Array.isArray(event.payload.options) || Array.isArray(event.payload.questions))) {
|
|
25574
|
+
const resolved = resolvedInputs.get(event.payload.toolUseId);
|
|
25575
|
+
message.inputRequest = {
|
|
25576
|
+
requestId: event.payload.requestId,
|
|
25577
|
+
status: resolved?.selectionId === "aborted" ? "aborted" : resolved ? "resolved" : "pending",
|
|
25578
|
+
...Array.isArray(event.payload.options) ? { options: event.payload.options } : {},
|
|
25579
|
+
...Array.isArray(event.payload.questions) ? { questions: event.payload.questions } : {},
|
|
25580
|
+
...resolved ? { selectionId: resolved.selectionId } : {},
|
|
25581
|
+
...resolved?.selectionSummary ? { selectionSummary: resolved.selectionSummary } : {}
|
|
25582
|
+
};
|
|
25583
|
+
}
|
|
25584
|
+
continue;
|
|
25585
|
+
}
|
|
25586
|
+
if (event.type === "replicas-tool-input-resolved" && typeof event.payload.toolUseId === "string" && typeof event.payload.selectionId === "string") {
|
|
25587
|
+
const resolved = {
|
|
25588
|
+
selectionId: event.payload.selectionId,
|
|
25589
|
+
...typeof event.payload.selectionSummary === "string" ? { selectionSummary: event.payload.selectionSummary } : {}
|
|
25590
|
+
};
|
|
25591
|
+
resolvedInputs.set(event.payload.toolUseId, resolved);
|
|
25592
|
+
const message = messages.find((candidate) => candidate.type === "tool_call" && candidate.id === `${provider}-tool-${event.payload.toolUseId}`);
|
|
25593
|
+
if (message?.inputRequest) {
|
|
25594
|
+
message.inputRequest = {
|
|
25595
|
+
...message.inputRequest,
|
|
25596
|
+
status: resolved.selectionId === "aborted" ? "aborted" : "resolved",
|
|
25597
|
+
...resolved
|
|
25598
|
+
};
|
|
25599
|
+
}
|
|
25530
25600
|
continue;
|
|
25531
25601
|
}
|
|
25532
|
-
if (event
|
|
25602
|
+
if (!isProviderEvent(event, provider, "session-update") || !isRecord(event.payload.update)) continue;
|
|
25533
25603
|
const update = event.payload.update;
|
|
25534
25604
|
const kind = update.sessionUpdate;
|
|
25535
25605
|
if (kind === "agent_message_chunk" || kind === "agent_thought_chunk") {
|
|
25536
|
-
const
|
|
25537
|
-
if (
|
|
25538
|
-
const
|
|
25606
|
+
const content = getAcpTextChunk(update, kind);
|
|
25607
|
+
if (content === null) continue;
|
|
25608
|
+
const explicitId = typeof update.messageId === "string" && update.messageId.length > 0 ? `${provider}-${kind}-${update.messageId}` : null;
|
|
25609
|
+
const id = explicitId ?? activeChunks[kind] ?? `${provider}-${kind}-${chunkSequence++}`;
|
|
25610
|
+
activeChunks[kind] = id;
|
|
25611
|
+
const otherKind = kind === "agent_message_chunk" ? "agent_thought_chunk" : "agent_message_chunk";
|
|
25612
|
+
if (!explicitId) activeChunks[otherKind] = void 0;
|
|
25539
25613
|
const existing = messages.find((message) => message.id === id);
|
|
25540
|
-
const text = `${existing && "content" in existing && typeof existing.content === "string" ? existing.content : ""}${
|
|
25614
|
+
const text = `${existing && "content" in existing && typeof existing.content === "string" ? existing.content : ""}${content}`.replace(provider === "fx" ? FX_CONTEXT_DIAGNOSTIC : /$^/, "");
|
|
25615
|
+
if (!text) continue;
|
|
25541
25616
|
upsertDisplayMessage(messages, kind === "agent_thought_chunk" ? { id, type: "reasoning", content: text, status: "in_progress", timestamp: existing?.timestamp ?? event.timestamp } : { id, type: "agent", content: text, timestamp: existing?.timestamp ?? event.timestamp });
|
|
25542
25617
|
continue;
|
|
25543
25618
|
}
|
|
25619
|
+
activeChunks.agent_message_chunk = void 0;
|
|
25620
|
+
activeChunks.agent_thought_chunk = void 0;
|
|
25544
25621
|
if ((kind === "tool_call" || kind === "tool_call_update") && typeof update.toolCallId === "string") {
|
|
25545
|
-
const id =
|
|
25622
|
+
const id = `${provider}-tool-${update.toolCallId}`;
|
|
25546
25623
|
const existing = messages.find((message) => message.id === id && message.type === "tool_call");
|
|
25547
25624
|
const status = update.status === "completed" || update.status === "failed" ? update.status === "failed" ? "failed" : "completed" : "in_progress";
|
|
25625
|
+
const contentOutput = Array.isArray(update.content) && update.content.length > 0 ? stringifyDisplayValue(update.content) : void 0;
|
|
25548
25626
|
upsertDisplayMessage(messages, createCallDisplayMessage({
|
|
25549
25627
|
id,
|
|
25550
|
-
server:
|
|
25551
|
-
tool: typeof update.name === "string" ? update.name : typeof update.title === "string" ? update.title : existing?.tool ?? "tool",
|
|
25628
|
+
server: provider,
|
|
25629
|
+
tool: typeof update.name === "string" && update.name ? update.name : typeof update.title === "string" && update.title ? update.title : existing?.tool ?? (typeof update.kind === "string" ? update.kind : "tool"),
|
|
25552
25630
|
input: update.rawInput === void 0 ? existing?.input : isRecord(update.rawInput) ? update.rawInput : stringifyDisplayValue(update.rawInput),
|
|
25553
|
-
output: update.rawOutput === void 0 ? existing?.output : stringifyDisplayValue(update.rawOutput),
|
|
25631
|
+
output: update.rawOutput === void 0 ? contentOutput ?? existing?.output : stringifyDisplayValue(update.rawOutput),
|
|
25554
25632
|
status,
|
|
25555
|
-
timestamp: event.timestamp
|
|
25633
|
+
timestamp: existing?.timestamp ?? event.timestamp
|
|
25556
25634
|
}));
|
|
25635
|
+
continue;
|
|
25636
|
+
}
|
|
25637
|
+
const plan = kind === "plan" ? update : isRecord(update.plan) ? update.plan : void 0;
|
|
25638
|
+
if ((kind === "plan" || kind === "plan_update") && plan && Array.isArray(plan.entries)) {
|
|
25639
|
+
const items = plan.entries.flatMap((entry) => {
|
|
25640
|
+
if (!isRecord(entry) || typeof entry.content !== "string") return [];
|
|
25641
|
+
const itemStatus = entry.status === "completed" || entry.status === "in_progress" ? entry.status : "pending";
|
|
25642
|
+
return [{
|
|
25643
|
+
text: entry.content,
|
|
25644
|
+
completed: entry.status === "completed",
|
|
25645
|
+
itemStatus
|
|
25646
|
+
}];
|
|
25647
|
+
});
|
|
25648
|
+
upsertDisplayMessage(messages, {
|
|
25649
|
+
id: `${provider}-plan-${typeof plan.planId === "string" ? plan.planId : "current"}`,
|
|
25650
|
+
type: "todo_list",
|
|
25651
|
+
items,
|
|
25652
|
+
status: items.every((item) => item.completed) ? "completed" : "in_progress",
|
|
25653
|
+
timestamp: event.timestamp
|
|
25654
|
+
});
|
|
25557
25655
|
}
|
|
25558
25656
|
}
|
|
25559
25657
|
return messages;
|
|
25560
25658
|
}
|
|
25561
25659
|
|
|
25660
|
+
// ../shared/src/display-message/parsers/fx-parser.ts
|
|
25661
|
+
function parseFxEvents(events) {
|
|
25662
|
+
return parseAcpEvents(events, "fx");
|
|
25663
|
+
}
|
|
25664
|
+
|
|
25562
25665
|
// ../shared/src/display-message/parsers/opencode-parser.ts
|
|
25563
25666
|
function timestampFromMs(value, fallback) {
|
|
25564
25667
|
return typeof value === "number" && Number.isFinite(value) ? new Date(value).toISOString() : fallback;
|
|
@@ -26726,6 +26829,9 @@ function parseAgentEvents(events, agentType) {
|
|
|
26726
26829
|
if (agentType === "fx") {
|
|
26727
26830
|
return parseFxEvents(events);
|
|
26728
26831
|
}
|
|
26832
|
+
if (agentType === "kimi") {
|
|
26833
|
+
return parseAcpEvents(events, "kimi");
|
|
26834
|
+
}
|
|
26729
26835
|
if (agentType === "opencode") {
|
|
26730
26836
|
return parseOpencodeEvents(events);
|
|
26731
26837
|
}
|
|
@@ -26924,45 +27030,7 @@ async function readSseStream(body, onEvent, shouldContinue = () => true) {
|
|
|
26924
27030
|
// src/lib/monolith-url.ts
|
|
26925
27031
|
var MONOLITH_URL = process.env.REPLICAS_MONOLITH_URL || process.env.MONOLITH_URL || "https://api.tryreplicas.com";
|
|
26926
27032
|
|
|
26927
|
-
// src/lib/api.ts
|
|
26928
|
-
async function buildOrgAuthHeaders() {
|
|
26929
|
-
const extraHeaders = {};
|
|
26930
|
-
if (isAgentMode()) {
|
|
26931
|
-
const agent = readAgentConfig();
|
|
26932
|
-
if (!agent) {
|
|
26933
|
-
throw new Error("Agent mode config is incomplete");
|
|
26934
|
-
}
|
|
26935
|
-
extraHeaders["X-Workspace-Id"] = agent.workspace_id;
|
|
26936
|
-
return { bearer: agent.engine_secret, extraHeaders };
|
|
26937
|
-
}
|
|
26938
|
-
const bearer = await getValidToken();
|
|
26939
|
-
const organizationId = getOrganizationId();
|
|
26940
|
-
if (!organizationId) {
|
|
26941
|
-
throw new Error(
|
|
26942
|
-
'No organization selected. Please run "replicas org switch" to select an organization.'
|
|
26943
|
-
);
|
|
26944
|
-
}
|
|
26945
|
-
extraHeaders["Replicas-Org-Id"] = organizationId;
|
|
26946
|
-
return { bearer, extraHeaders };
|
|
26947
|
-
}
|
|
26948
|
-
async function authenticatedFetch(url2, options) {
|
|
26949
|
-
const token = await getValidToken();
|
|
26950
|
-
if (!token) {
|
|
26951
|
-
throw new Error("No access token available");
|
|
26952
|
-
}
|
|
26953
|
-
return apiFetch(url2, {
|
|
26954
|
-
"Authorization": `Bearer ${token}`,
|
|
26955
|
-
...options?.headers || {}
|
|
26956
|
-
}, options);
|
|
26957
|
-
}
|
|
26958
|
-
async function orgAuthenticatedFetch(url2, options) {
|
|
26959
|
-
const { bearer, extraHeaders } = await buildOrgAuthHeaders();
|
|
26960
|
-
return apiFetch(url2, {
|
|
26961
|
-
"Authorization": `Bearer ${bearer}`,
|
|
26962
|
-
...extraHeaders,
|
|
26963
|
-
...options?.headers || {}
|
|
26964
|
-
}, options);
|
|
26965
|
-
}
|
|
27033
|
+
// src/lib/authenticated-api.ts
|
|
26966
27034
|
var ApiError = class extends Error {
|
|
26967
27035
|
constructor(message, status) {
|
|
26968
27036
|
super(message);
|
|
@@ -26975,39 +27043,24 @@ async function throwResponseError(response) {
|
|
|
26975
27043
|
throw new ApiError(error51.error || `Request failed with status ${response.status}`, response.status);
|
|
26976
27044
|
}
|
|
26977
27045
|
async function apiFetch(url2, headers, options) {
|
|
26978
|
-
const requestHeaders = {
|
|
26979
|
-
|
|
26980
|
-
|
|
26981
|
-
};
|
|
26982
|
-
const absoluteUrl = `${MONOLITH_URL}${url2}`;
|
|
26983
|
-
const requestInit = {
|
|
27046
|
+
const requestHeaders = new Headers({ "Content-Type": "application/json", ...headers });
|
|
27047
|
+
new Headers(options?.headers).forEach((value, key) => requestHeaders.set(key, value));
|
|
27048
|
+
const response = await fetchWithRedirects(`${MONOLITH_URL}${url2}`, {
|
|
26984
27049
|
...options,
|
|
26985
27050
|
headers: requestHeaders,
|
|
26986
27051
|
body: options?.body !== void 0 ? JSON.stringify(options.body) : void 0
|
|
26987
|
-
};
|
|
26988
|
-
const response = await fetchWithRedirects(absoluteUrl, requestInit);
|
|
27052
|
+
});
|
|
26989
27053
|
if (!response.ok) {
|
|
26990
27054
|
await throwResponseError(response);
|
|
26991
27055
|
}
|
|
26992
27056
|
return response.json();
|
|
26993
27057
|
}
|
|
26994
|
-
async function
|
|
26995
|
-
const
|
|
26996
|
-
|
|
26997
|
-
|
|
26998
|
-
headers: {
|
|
26999
|
-
"Authorization": `Bearer ${bearer}`,
|
|
27000
|
-
"Content-Type": "application/json",
|
|
27001
|
-
"Accept": "text/event-stream",
|
|
27002
|
-
...extraHeaders
|
|
27003
|
-
},
|
|
27004
|
-
body: JSON.stringify(options.body)
|
|
27005
|
-
});
|
|
27006
|
-
if (!response.ok || !response.body) {
|
|
27007
|
-
await throwResponseError(response);
|
|
27008
|
-
return;
|
|
27058
|
+
async function authenticatedFetch(url2, options) {
|
|
27059
|
+
const token = await getValidToken();
|
|
27060
|
+
if (!token) {
|
|
27061
|
+
throw new Error("No access token available");
|
|
27009
27062
|
}
|
|
27010
|
-
|
|
27063
|
+
return apiFetch(url2, { Authorization: `Bearer ${token}` }, options);
|
|
27011
27064
|
}
|
|
27012
27065
|
|
|
27013
27066
|
// src/lib/organization.ts
|
|
@@ -27018,7 +27071,11 @@ async function fetchOrganizations() {
|
|
|
27018
27071
|
return response.organizations;
|
|
27019
27072
|
}
|
|
27020
27073
|
async function fetchActiveRole() {
|
|
27021
|
-
|
|
27074
|
+
const organizationId = getConfirmedOrganizationId();
|
|
27075
|
+
if (!organizationId) return null;
|
|
27076
|
+
return authenticatedFetch("/v1/organization/membership", {
|
|
27077
|
+
headers: { "Replicas-Org-Id": organizationId }
|
|
27078
|
+
}).then((response) => response.role).catch(() => null);
|
|
27022
27079
|
}
|
|
27023
27080
|
async function setActiveOrganization(organizationId) {
|
|
27024
27081
|
const organizations = await fetchOrganizations();
|
|
@@ -27031,7 +27088,14 @@ async function setActiveOrganization(organizationId) {
|
|
|
27031
27088
|
async function findActiveOrganization() {
|
|
27032
27089
|
const organizations = await fetchOrganizations();
|
|
27033
27090
|
const currentId = getOrganizationId();
|
|
27034
|
-
|
|
27091
|
+
const storedOrganization = organizations.find((org2) => org2.id === currentId) ?? null;
|
|
27092
|
+
if (currentId && !storedOrganization) {
|
|
27093
|
+
clearOrganizationId();
|
|
27094
|
+
}
|
|
27095
|
+
return {
|
|
27096
|
+
organizations,
|
|
27097
|
+
organization: isOrganizationSelectionConfirmed() ? storedOrganization : null
|
|
27098
|
+
};
|
|
27035
27099
|
}
|
|
27036
27100
|
async function promptForOrganization(organizations, currentId) {
|
|
27037
27101
|
const { organizationId } = await (0, import_prompts3.default)({
|
|
@@ -27046,30 +27110,30 @@ async function promptForOrganization(organizations, currentId) {
|
|
|
27046
27110
|
});
|
|
27047
27111
|
return organizations.find((org2) => org2.id === organizationId) ?? null;
|
|
27048
27112
|
}
|
|
27049
|
-
async function
|
|
27113
|
+
async function ensureOrganizationSelection(options = {}) {
|
|
27050
27114
|
const { organizations, organization } = await findActiveOrganization();
|
|
27051
27115
|
if (organizations.length === 0) {
|
|
27052
27116
|
throw new Error("You are not a member of any organization. Please contact support.");
|
|
27053
27117
|
}
|
|
27054
27118
|
if (organization) {
|
|
27055
|
-
return { organization, total: organizations.length
|
|
27119
|
+
return { organization, total: organizations.length };
|
|
27056
27120
|
}
|
|
27057
|
-
const canAsk = options.interactive === true &&
|
|
27121
|
+
const canAsk = options.interactive === true && !!process.stdin.isTTY;
|
|
27058
27122
|
if (canAsk) {
|
|
27059
27123
|
const chosen = await promptForOrganization(organizations, null);
|
|
27060
27124
|
if (!chosen) {
|
|
27061
|
-
|
|
27062
|
-
return { organization: null, total: organizations.length, role: null };
|
|
27125
|
+
return { organization: null, total: organizations.length };
|
|
27063
27126
|
}
|
|
27064
27127
|
setOrganizationId(chosen.id);
|
|
27065
|
-
return { organization: chosen, total: organizations.length
|
|
27128
|
+
return { organization: chosen, total: organizations.length };
|
|
27066
27129
|
}
|
|
27067
|
-
|
|
27068
|
-
|
|
27130
|
+
return { organization: null, total: organizations.length };
|
|
27131
|
+
}
|
|
27132
|
+
async function ensureOrganization(options = {}) {
|
|
27133
|
+
const selection = await ensureOrganizationSelection(options);
|
|
27069
27134
|
return {
|
|
27070
|
-
|
|
27071
|
-
|
|
27072
|
-
role: await fetchActiveRole()
|
|
27135
|
+
...selection,
|
|
27136
|
+
role: selection.organization ? await fetchActiveRole() : null
|
|
27073
27137
|
};
|
|
27074
27138
|
}
|
|
27075
27139
|
async function resolveActiveOrganization() {
|
|
@@ -27124,7 +27188,7 @@ async function resolveAuthFlowTarget(identity) {
|
|
|
27124
27188
|
}
|
|
27125
27189
|
const [replicasAccount, active] = await Promise.all([
|
|
27126
27190
|
getCurrentUser().then((user) => user.email).catch(() => null),
|
|
27127
|
-
|
|
27191
|
+
ensureOrganization({ interactive: true })
|
|
27128
27192
|
]);
|
|
27129
27193
|
return {
|
|
27130
27194
|
...identity,
|
|
@@ -27320,6 +27384,7 @@ async function loginCommand() {
|
|
|
27320
27384
|
refresh_token: refreshToken2,
|
|
27321
27385
|
expires_at: parseInt(expiresAt, 10),
|
|
27322
27386
|
organization_id: existingConfig?.organization_id,
|
|
27387
|
+
organization_selection_confirmed: existingConfig?.organization_selection_confirmed,
|
|
27323
27388
|
ide_command: existingConfig?.ide_command
|
|
27324
27389
|
};
|
|
27325
27390
|
try {
|
|
@@ -27408,7 +27473,7 @@ function logoutCommand() {
|
|
|
27408
27473
|
console.log(import_chalk3.default.yellow("You are not logged in."));
|
|
27409
27474
|
return;
|
|
27410
27475
|
}
|
|
27411
|
-
|
|
27476
|
+
clearAuthentication();
|
|
27412
27477
|
console.log(import_chalk3.default.green("\u2713 Successfully logged out!"));
|
|
27413
27478
|
}
|
|
27414
27479
|
|
|
@@ -27476,6 +27541,54 @@ async function connectSSH(token, host, proxyCommand) {
|
|
|
27476
27541
|
var import_chalk5 = __toESM(require("chalk"));
|
|
27477
27542
|
var import_prompts5 = __toESM(require("prompts"));
|
|
27478
27543
|
|
|
27544
|
+
// src/lib/api.ts
|
|
27545
|
+
async function buildOrgAuthHeaders() {
|
|
27546
|
+
const extraHeaders = {};
|
|
27547
|
+
if (isAgentMode()) {
|
|
27548
|
+
const agent = readAgentConfig();
|
|
27549
|
+
if (!agent) {
|
|
27550
|
+
throw new Error("Agent mode config is incomplete");
|
|
27551
|
+
}
|
|
27552
|
+
extraHeaders["X-Workspace-Id"] = agent.workspace_id;
|
|
27553
|
+
return { bearer: agent.engine_secret, extraHeaders };
|
|
27554
|
+
}
|
|
27555
|
+
const bearer = await getValidToken();
|
|
27556
|
+
const selectedId = getConfirmedOrganizationId();
|
|
27557
|
+
const organizationId = selectedId ?? (await ensureOrganizationSelection({ interactive: true })).organization?.id;
|
|
27558
|
+
if (!organizationId) {
|
|
27559
|
+
throw new Error(
|
|
27560
|
+
'No organization selected. Please run "replicas org switch" to select an organization.'
|
|
27561
|
+
);
|
|
27562
|
+
}
|
|
27563
|
+
extraHeaders["Replicas-Org-Id"] = organizationId;
|
|
27564
|
+
return { bearer, extraHeaders };
|
|
27565
|
+
}
|
|
27566
|
+
async function orgAuthenticatedFetch(url2, options) {
|
|
27567
|
+
const { bearer, extraHeaders } = await buildOrgAuthHeaders();
|
|
27568
|
+
return apiFetch(url2, {
|
|
27569
|
+
"Authorization": `Bearer ${bearer}`,
|
|
27570
|
+
...extraHeaders
|
|
27571
|
+
}, options);
|
|
27572
|
+
}
|
|
27573
|
+
async function orgAuthenticatedSseStream(url2, options) {
|
|
27574
|
+
const { bearer, extraHeaders } = await buildOrgAuthHeaders();
|
|
27575
|
+
const response = await fetch(`${MONOLITH_URL}${url2}`, {
|
|
27576
|
+
method: "POST",
|
|
27577
|
+
headers: {
|
|
27578
|
+
"Authorization": `Bearer ${bearer}`,
|
|
27579
|
+
"Content-Type": "application/json",
|
|
27580
|
+
"Accept": "text/event-stream",
|
|
27581
|
+
...extraHeaders
|
|
27582
|
+
},
|
|
27583
|
+
body: JSON.stringify(options.body)
|
|
27584
|
+
});
|
|
27585
|
+
if (!response.ok || !response.body) {
|
|
27586
|
+
await throwResponseError(response);
|
|
27587
|
+
return;
|
|
27588
|
+
}
|
|
27589
|
+
await readSseStream(response.body, options.onEvent);
|
|
27590
|
+
}
|
|
27591
|
+
|
|
27479
27592
|
// src/lib/git.ts
|
|
27480
27593
|
var import_child_process2 = require("child_process");
|
|
27481
27594
|
var import_path2 = __toESM(require("path"));
|
|
@@ -27770,7 +27883,7 @@ async function orgCommand() {
|
|
|
27770
27883
|
process.exit(1);
|
|
27771
27884
|
}
|
|
27772
27885
|
try {
|
|
27773
|
-
const currentOrgId =
|
|
27886
|
+
const currentOrgId = getConfirmedOrganizationId();
|
|
27774
27887
|
const organizations = await fetchOrganizations();
|
|
27775
27888
|
if (!currentOrgId) {
|
|
27776
27889
|
console.log(import_chalk8.default.yellow("\n No organization selected."));
|
|
@@ -27779,6 +27892,7 @@ async function orgCommand() {
|
|
|
27779
27892
|
}
|
|
27780
27893
|
const currentOrg = organizations.find((org2) => org2.id === currentOrgId);
|
|
27781
27894
|
if (!currentOrg) {
|
|
27895
|
+
clearOrganizationId();
|
|
27782
27896
|
console.log(import_chalk8.default.yellow("\n The selected organization is no longer available to you."));
|
|
27783
27897
|
console.log(import_chalk8.default.gray(' Run "replicas org switch" to select another.\n'));
|
|
27784
27898
|
return;
|
|
@@ -27813,7 +27927,7 @@ async function orgSwitchCommand() {
|
|
|
27813
27927
|
console.log(import_chalk8.default.gray(" Please contact support.\n"));
|
|
27814
27928
|
return;
|
|
27815
27929
|
}
|
|
27816
|
-
const currentOrgId =
|
|
27930
|
+
const currentOrgId = getConfirmedOrganizationId();
|
|
27817
27931
|
let selectedId = organizations[0].id;
|
|
27818
27932
|
if (organizations.length > 1) {
|
|
27819
27933
|
const chosen = await promptForOrganization(organizations, currentOrgId);
|
|
@@ -28062,7 +28176,7 @@ async function runCodexOAuthFlow(totalSteps) {
|
|
|
28062
28176
|
// src/lib/credential-upload.ts
|
|
28063
28177
|
var import_chalk10 = __toESM(require("chalk"));
|
|
28064
28178
|
var UPLOAD_STEPS = 1;
|
|
28065
|
-
async function withAuthRecovery(operation,
|
|
28179
|
+
async function withAuthRecovery(operation, afterReauthentication) {
|
|
28066
28180
|
try {
|
|
28067
28181
|
return { result: await operation(), reauthenticated: false };
|
|
28068
28182
|
} catch (error51) {
|
|
@@ -28073,8 +28187,8 @@ async function withAuthRecovery(operation, assertStillApproved) {
|
|
|
28073
28187
|
console.log(import_chalk10.default.yellow(`
|
|
28074
28188
|
${message}`));
|
|
28075
28189
|
await loginCommand();
|
|
28076
|
-
await
|
|
28077
|
-
console.log(import_chalk10.default.gray(" Retrying
|
|
28190
|
+
await afterReauthentication?.();
|
|
28191
|
+
console.log(import_chalk10.default.gray(" Retrying..."));
|
|
28078
28192
|
return { result: await operation(), reauthenticated: true };
|
|
28079
28193
|
}
|
|
28080
28194
|
}
|
|
@@ -28101,7 +28215,7 @@ async function runCredentialAuthFlow(options, flow) {
|
|
|
28101
28215
|
if (options.org === true && options.user === true) {
|
|
28102
28216
|
throw new Error("Pass either --org or --user, not both.");
|
|
28103
28217
|
}
|
|
28104
|
-
const target = await resolveAuthFlowTarget(identity);
|
|
28218
|
+
const { result: target } = await withAuthRecovery(() => resolveAuthFlowTarget(identity));
|
|
28105
28219
|
if (!isUserScoped && !target.organization) {
|
|
28106
28220
|
throw new Error(
|
|
28107
28221
|
"Could not determine which organization to save to. Re-run the command, or use --user to save to your personal account."
|
|
@@ -30841,6 +30955,38 @@ function parseBooleanOption(value) {
|
|
|
30841
30955
|
}
|
|
30842
30956
|
var program = new import_commander.Command();
|
|
30843
30957
|
program.name("replicas").description("CLI for managing Replicas workspaces").version(CLI_VERSION);
|
|
30958
|
+
var organizationOptionalCommands = /* @__PURE__ */ new Set([
|
|
30959
|
+
"computer",
|
|
30960
|
+
"claude-auth",
|
|
30961
|
+
"codex-auth",
|
|
30962
|
+
"config",
|
|
30963
|
+
"init",
|
|
30964
|
+
"login",
|
|
30965
|
+
"logout",
|
|
30966
|
+
"media",
|
|
30967
|
+
"mothership",
|
|
30968
|
+
"org",
|
|
30969
|
+
"service",
|
|
30970
|
+
"whoami"
|
|
30971
|
+
]);
|
|
30972
|
+
program.hook("preAction", async (_command, actionCommand) => {
|
|
30973
|
+
let rootCommand = actionCommand;
|
|
30974
|
+
while (rootCommand.parent && rootCommand.parent !== program) {
|
|
30975
|
+
rootCommand = rootCommand.parent;
|
|
30976
|
+
}
|
|
30977
|
+
if (isAgentMode() || !isAuthenticated() || organizationOptionalCommands.has(rootCommand.name())) return;
|
|
30978
|
+
try {
|
|
30979
|
+
const { organization } = await ensureOrganizationSelection({ interactive: true });
|
|
30980
|
+
if (!organization) {
|
|
30981
|
+
throw new Error('No organization selected. Run "replicas org switch" to select one.');
|
|
30982
|
+
}
|
|
30983
|
+
} catch (error51) {
|
|
30984
|
+
console.error(import_chalk22.default.red(`
|
|
30985
|
+
\u2717 ${error51 instanceof Error ? error51.message : "Unknown error"}
|
|
30986
|
+
`));
|
|
30987
|
+
process.exit(1);
|
|
30988
|
+
}
|
|
30989
|
+
});
|
|
30844
30990
|
function registerSlackCommands(parent) {
|
|
30845
30991
|
const slack = parent.command("slack").description("Manage Slack thread routing");
|
|
30846
30992
|
const slackThread = slack.command("thread").description("Attach or switch the Slack thread that routes to a workspace");
|