replicas-cli 0.2.533 → 0.2.535

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.cjs +184 -5
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -7629,6 +7629,7 @@ var AGENT = {
7629
7629
  CLAUDE: "claude",
7630
7630
  CODEX: "codex",
7631
7631
  CURSOR: "cursor",
7632
+ DEEPSEEK: "deepseek",
7632
7633
  OPENCODE: "opencode",
7633
7634
  PI: "pi",
7634
7635
  RELAY: "relay"
@@ -7660,6 +7661,11 @@ var AGENT_PROVIDER_OPTIONS = [
7660
7661
  label: "Cursor",
7661
7662
  description: "Use Cursor for tasks"
7662
7663
  },
7664
+ {
7665
+ value: "deepseek",
7666
+ label: "DeepSeek Harness",
7667
+ description: "Use DeepSeek Harness for tasks"
7668
+ },
7663
7669
  {
7664
7670
  value: "opencode",
7665
7671
  label: "Opencode",
@@ -7682,6 +7688,7 @@ var THINKING_LEVELS_BY_AGENT = {
7682
7688
  claude: [...STANDARD_THINKING_LEVELS, "ultracode"],
7683
7689
  codex: [...STANDARD_THINKING_LEVELS, "ultra"],
7684
7690
  cursor: STANDARD_THINKING_LEVELS,
7691
+ deepseek: STANDARD_THINKING_LEVELS,
7685
7692
  opencode: STANDARD_THINKING_LEVELS,
7686
7693
  pi: STANDARD_THINKING_LEVELS,
7687
7694
  relay: [...STANDARD_THINKING_LEVELS, "ultracode"]
@@ -7701,6 +7708,8 @@ function getProviderDisplayName(provider, variant = "short") {
7701
7708
  return "Codex";
7702
7709
  case "cursor":
7703
7710
  return "Cursor";
7711
+ case "deepseek":
7712
+ return variant === "long" ? "DeepSeek Harness" : "DeepSeek";
7704
7713
  case "opencode":
7705
7714
  return "Opencode";
7706
7715
  case "pi":
@@ -7761,6 +7770,9 @@ var AGENT_CREDENTIAL_METHODS_IN_ORDER = {
7761
7770
  [AGENT.CURSOR]: [
7762
7771
  { method: CREDENTIAL_METHOD.API_KEY, credentialType: CREDENTIAL_TYPE.CURSOR_API_KEY }
7763
7772
  ],
7773
+ [AGENT.DEEPSEEK]: [
7774
+ { method: CREDENTIAL_METHOD.OPENROUTER, credentialType: CREDENTIAL_TYPE.OPENROUTER_API_KEY }
7775
+ ],
7764
7776
  [AGENT.OPENCODE]: [
7765
7777
  { method: CREDENTIAL_METHOD.OPENCODE_GO, credentialType: CREDENTIAL_TYPE.OPENCODE_GO_API_KEY },
7766
7778
  { method: CREDENTIAL_METHOD.ASTER, credentialType: CREDENTIAL_TYPE.ASTER_API_KEY },
@@ -22447,6 +22459,7 @@ var AGENT_MODELS = {
22447
22459
  CLAUDE_HAIKU_4_5_MODEL,
22448
22460
  "kimi-k2.5"
22449
22461
  ],
22462
+ deepseek: [...OPENROUTER_MODELS],
22450
22463
  opencode: [...OPENROUTER_MODELS, ...ASTER_MODELS],
22451
22464
  pi: [...OPENROUTER_MODELS, ...ASTER_MODELS],
22452
22465
  relay: [CLAUDE_FABLE_5_MODEL, CLAUDE_OPUS_5_MODEL, CLAUDE_OPUS_4_8_MODEL, CLAUDE_SONNET_5_MODEL]
@@ -24336,7 +24349,7 @@ var headlessFilesystemAgentResultSchema = external_exports.object({
24336
24349
  });
24337
24350
 
24338
24351
  // ../shared/src/cli-version.ts
24339
- var CLI_VERSION = "0.2.533";
24352
+ var CLI_VERSION = "0.2.535";
24340
24353
 
24341
24354
  // ../shared/src/version.ts
24342
24355
  function compareVersions(v1, v2) {
@@ -24403,6 +24416,12 @@ function normalizeCodexAspTranscriptStatus(status, failed = false) {
24403
24416
  if (status === "completed") return "completed";
24404
24417
  return "in_progress";
24405
24418
  }
24419
+ function getCodexAspTurnResponse(turn) {
24420
+ const finalAnswer = turn.items.find((item) => item.type === "agentMessage" && item.phase === "final_answer");
24421
+ if (finalAnswer) return finalAnswer;
24422
+ if (normalizeCodexAspTranscriptStatus(turn.status) === "in_progress") return null;
24423
+ return turn.items.findLast((item) => item.type === "agentMessage") ?? null;
24424
+ }
24406
24425
 
24407
24426
  // ../shared/src/routes/user.ts
24408
24427
  var PROFILE_AVATAR_MAX_SIZE_BYTES = 5 * 1024 * 1024;
@@ -25278,6 +25297,162 @@ function parseCursorEvents(events) {
25278
25297
  return messages;
25279
25298
  }
25280
25299
 
25300
+ // ../shared/src/display-message/parsers/deepseek-parser.ts
25301
+ function parseArguments(value) {
25302
+ if (typeof value !== "string") return void 0;
25303
+ const parsed = safeJsonParse(value, value);
25304
+ return isRecord(parsed) ? parsed : stringifyDisplayValue(parsed);
25305
+ }
25306
+ function getDeepseekAssistantMessageText(event, blockType) {
25307
+ if (!isRecord(event) || event.type !== "assistant/message" || !isRecord(event.data) || !isRecord(event.data.message) || !Array.isArray(event.data.message.content)) return "";
25308
+ return event.data.message.content.flatMap((block) => isRecord(block) && block.type === blockType && typeof block.text === "string" ? [block.text] : []).join("");
25309
+ }
25310
+ function parseDeepseekEvents(events) {
25311
+ const messages = [];
25312
+ for (const source of events) {
25313
+ if (source.type === "event_msg" && source.payload.type === "user_message") {
25314
+ if (typeof source.payload.message === "string" && source.payload.message.trim()) {
25315
+ const messageId = source.payload[USER_MESSAGE_ID_PAYLOAD_KEY];
25316
+ messages.push({
25317
+ id: typeof messageId === "string" ? messageId : `deepseek-user-${source.timestamp}`,
25318
+ type: "user",
25319
+ content: source.payload.message,
25320
+ timestamp: source.timestamp
25321
+ });
25322
+ }
25323
+ continue;
25324
+ }
25325
+ if (source.type === "deepseek-error") {
25326
+ messages.push({
25327
+ id: `deepseek-error-${source.timestamp}`,
25328
+ type: "error",
25329
+ message: typeof source.payload.message === "string" ? source.payload.message : "DeepSeek Harness failed",
25330
+ timestamp: source.timestamp
25331
+ });
25332
+ continue;
25333
+ }
25334
+ if (source.type === "deepseek-input-request") {
25335
+ const requestId = typeof source.payload.requestId === "string" ? source.payload.requestId : `deepseek-input-${source.timestamp}`;
25336
+ if (source.payload.kind === "approval") {
25337
+ upsertDisplayMessage(messages, createCallDisplayMessage({
25338
+ id: requestId,
25339
+ server: "deepseek",
25340
+ tool: typeof source.payload.toolName === "string" ? source.payload.toolName : "approval",
25341
+ input: typeof source.payload.reason === "string" ? source.payload.reason : void 0,
25342
+ status: "in_progress",
25343
+ timestamp: source.timestamp,
25344
+ inputRequest: {
25345
+ requestId,
25346
+ status: "pending",
25347
+ options: [
25348
+ { id: "deny", label: "Deny", variant: "secondary" },
25349
+ { id: "allow", label: "Allow once", variant: "primary" }
25350
+ ]
25351
+ }
25352
+ }));
25353
+ } else {
25354
+ const questions = Array.isArray(source.payload.questions) ? source.payload.questions : [];
25355
+ upsertDisplayMessage(messages, createCallDisplayMessage({
25356
+ id: requestId,
25357
+ server: "deepseek",
25358
+ tool: "ask_user",
25359
+ status: "in_progress",
25360
+ timestamp: source.timestamp,
25361
+ inputRequest: {
25362
+ requestId,
25363
+ status: "pending",
25364
+ questions: questions.flatMap((question) => {
25365
+ if (!isRecord(question) || typeof question.id !== "string" || typeof question.question !== "string") return [];
25366
+ const options = Array.isArray(question.options) ? question.options : [];
25367
+ return [{
25368
+ id: question.id,
25369
+ prompt: question.question,
25370
+ multiSelect: question.multiSelect === true,
25371
+ options: options.flatMap((option) => isRecord(option) && typeof option.label === "string" ? [{ id: `${question.id}:${option.label}`, label: option.label, ...typeof option.description === "string" ? { description: option.description } : {} }] : [])
25372
+ }];
25373
+ })
25374
+ }
25375
+ }));
25376
+ }
25377
+ continue;
25378
+ }
25379
+ if (source.type === "deepseek-input-resolved") {
25380
+ const requestId = typeof source.payload.requestId === "string" ? source.payload.requestId : "";
25381
+ const existing = messages.find((message) => message.type === "tool_call" && message.inputRequest?.requestId === requestId);
25382
+ if (existing?.type === "tool_call" && existing.inputRequest) {
25383
+ existing.inputRequest.status = source.payload.status === "aborted" ? "aborted" : "resolved";
25384
+ existing.status = source.payload.status === "aborted" ? "failed" : "completed";
25385
+ }
25386
+ continue;
25387
+ }
25388
+ if (source.type === "deepseek-jobs" && Array.isArray(source.payload.jobs)) {
25389
+ for (const job of source.payload.jobs) {
25390
+ if (!isRecord(job) || typeof job.id !== "string") continue;
25391
+ const existing = messages.find((message) => message.type === "background_task" && message.taskId === job.id);
25392
+ const status = normalizeBackgroundTaskStatus(job.status);
25393
+ const next = {
25394
+ id: existing?.id ?? `deepseek-job-${job.id}`,
25395
+ type: "background_task",
25396
+ taskId: job.id,
25397
+ status,
25398
+ description: typeof job.label === "string" ? job.label : void 0,
25399
+ taskType: typeof job.kind === "string" ? job.kind : void 0,
25400
+ error: status === "failed" && typeof job.detail === "string" ? job.detail : void 0,
25401
+ timestamp: existing?.timestamp ?? source.timestamp
25402
+ };
25403
+ if (existing?.type === "background_task") Object.assign(existing, next);
25404
+ else messages.push(next);
25405
+ }
25406
+ continue;
25407
+ }
25408
+ if (source.type !== "deepseek-session-event" || !isRecord(source.payload.event)) continue;
25409
+ const event = source.payload.event;
25410
+ const data = isRecord(event.data) ? event.data : {};
25411
+ const seq = typeof event.seq === "number" ? event.seq : source.timestamp;
25412
+ if (event.type === "assistant/message") {
25413
+ const content = getDeepseekAssistantMessageText(event, "text");
25414
+ const reasoning = getDeepseekAssistantMessageText(event, "reasoning");
25415
+ if (reasoning.trim()) messages.push({ id: `deepseek-reasoning-${seq}`, type: "reasoning", content: reasoning, status: "completed", timestamp: source.timestamp });
25416
+ if (content.trim()) messages.push({ id: `deepseek-assistant-${seq}`, type: "agent", content, timestamp: source.timestamp });
25417
+ continue;
25418
+ }
25419
+ if (event.type === "tool/call") {
25420
+ const callId = typeof data.callId === "string" ? data.callId : String(seq);
25421
+ upsertDisplayMessage(messages, createCallDisplayMessage({
25422
+ id: `deepseek-tool-${callId}`,
25423
+ server: "deepseek",
25424
+ tool: typeof data.name === "string" ? data.name : "tool",
25425
+ input: parseArguments(data.arguments),
25426
+ status: "in_progress",
25427
+ timestamp: source.timestamp
25428
+ }));
25429
+ continue;
25430
+ }
25431
+ if (event.type === "tool/result") {
25432
+ const callId = typeof data.callId === "string" ? data.callId : String(seq);
25433
+ const existing = messages.find((message) => message.id === `deepseek-tool-${callId}` && message.type === "tool_call");
25434
+ if (existing?.type === "tool_call") {
25435
+ existing.output = stringifyDisplayValue(data.message ?? data.result);
25436
+ existing.status = data.isError === true ? "failed" : "completed";
25437
+ }
25438
+ continue;
25439
+ }
25440
+ if (event.type === "todo/write" && Array.isArray(data.items)) {
25441
+ messages.push({
25442
+ id: `deepseek-todo-${seq}`,
25443
+ type: "todo_list",
25444
+ items: data.items.flatMap((item) => {
25445
+ if (!isRecord(item) || typeof item.content !== "string") return [];
25446
+ const itemStatus = item.status === "in_progress" || item.status === "completed" ? item.status : "pending";
25447
+ return [{ text: item.content, completed: itemStatus === "completed", itemStatus }];
25448
+ }),
25449
+ timestamp: source.timestamp
25450
+ });
25451
+ }
25452
+ }
25453
+ return messages;
25454
+ }
25455
+
25281
25456
  // ../shared/src/display-message/parsers/opencode-parser.ts
25282
25457
  function timestampFromMs(value, fallback) {
25283
25458
  return typeof value === "number" && Number.isFinite(value) ? new Date(value).toISOString() : fallback;
@@ -26406,10 +26581,11 @@ function parseCodexAspTranscript(transcript) {
26406
26581
  for (const turn of transcript.turns) {
26407
26582
  const reasoningIndex = coalescedItems.findIndex(({ item, turn: itemTurn }) => itemTurn.id === turn.id && item.type === "reasoning");
26408
26583
  if (reasoningIndex === -1) continue;
26409
- let finalAnswerIndex = coalescedItems.findIndex(({ item, turn: itemTurn }) => itemTurn.id === turn.id && item.type === "agentMessage" && item.phase === "final_answer");
26410
- if (finalAnswerIndex === -1 && normalizeCodexAspTranscriptStatus(turn.status) !== "in_progress") {
26411
- finalAnswerIndex = coalescedItems.findLastIndex(({ item, turn: itemTurn }) => itemTurn.id === turn.id && item.type === "agentMessage");
26412
- }
26584
+ const responseItem = getCodexAspTurnResponse({
26585
+ status: turn.status,
26586
+ items: coalescedItems.filter(({ turn: itemTurn }) => itemTurn.id === turn.id).map(({ item }) => item)
26587
+ });
26588
+ const finalAnswerIndex = responseItem ? coalescedItems.findIndex(({ item }) => item === responseItem) : -1;
26413
26589
  if (finalAnswerIndex === -1 || reasoningIndex < finalAnswerIndex) continue;
26414
26590
  const [reasoning] = coalescedItems.splice(reasoningIndex, 1);
26415
26591
  coalescedItems.splice(finalAnswerIndex, 0, reasoning);
@@ -26433,6 +26609,9 @@ function parseAgentEvents(events, agentType) {
26433
26609
  if (agentType === "cursor") {
26434
26610
  return parseCursorEvents(events);
26435
26611
  }
26612
+ if (agentType === "deepseek") {
26613
+ return parseDeepseekEvents(events);
26614
+ }
26436
26615
  if (agentType === "opencode") {
26437
26616
  return parseOpencodeEvents(events);
26438
26617
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-cli",
3
- "version": "0.2.533",
3
+ "version": "0.2.535",
4
4
  "description": "CLI for managing Replicas workspaces - SSH into cloud dev environments with automatic port forwarding",
5
5
  "main": "dist/index.cjs",
6
6
  "bin": {