replicas-engine 0.1.626 → 0.1.627

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/src/index.js +85 -10
  2. package/package.json +1 -1
package/dist/src/index.js CHANGED
@@ -5375,6 +5375,63 @@ var MEDIA_KIND = {
5375
5375
  var MEDIA_KINDS = [MEDIA_KIND.IMAGE, MEDIA_KIND.VIDEO, MEDIA_KIND.AUDIO, MEDIA_KIND.HTML];
5376
5376
  var PUBLIC_MEDIA_KINDS = [MEDIA_KIND.IMAGE, MEDIA_KIND.VIDEO, MEDIA_KIND.AUDIO];
5377
5377
  var MAX_ENGINE_LOG_BYTES = 50 * 1024 * 1024;
5378
+ function normalizeChatMessageSenders(value) {
5379
+ if (!Array.isArray(value)) return void 0;
5380
+ const senders = value.flatMap((sender) => {
5381
+ if (!isChatMessageSender(sender)) return [];
5382
+ const { senderUserId, senderEmail, senderDisplayName, senderAvatarUrl, recordedAt } = sender;
5383
+ return [{
5384
+ senderUserId,
5385
+ senderEmail,
5386
+ ...typeof senderDisplayName === "string" ? { senderDisplayName } : {},
5387
+ ...typeof senderAvatarUrl === "string" ? { senderAvatarUrl } : {},
5388
+ recordedAt
5389
+ }];
5390
+ });
5391
+ return senders;
5392
+ }
5393
+ function normalizeChatTranscriptMetadata(value) {
5394
+ if (!isRecord(value)) return {};
5395
+ const metadata = {};
5396
+ const {
5397
+ provider,
5398
+ title,
5399
+ createdAt,
5400
+ updatedAt,
5401
+ parentChatId,
5402
+ deletedAt,
5403
+ senders,
5404
+ captureId,
5405
+ captureReason,
5406
+ sha256
5407
+ } = value;
5408
+ if (typeof provider === "string" && isValidAgentProvider(provider)) metadata.provider = provider;
5409
+ if (typeof title === "string") metadata.title = title;
5410
+ if (typeof createdAt === "string") metadata.createdAt = createdAt;
5411
+ if (typeof updatedAt === "string") metadata.updatedAt = updatedAt;
5412
+ if (typeof parentChatId === "string" || parentChatId === null) metadata.parentChatId = parentChatId;
5413
+ if (typeof deletedAt === "string" || deletedAt === null) metadata.deletedAt = deletedAt;
5414
+ const normalizedSenders = normalizeChatMessageSenders(senders);
5415
+ if (normalizedSenders) metadata.senders = normalizedSenders;
5416
+ if (typeof captureId === "string") metadata.captureId = captureId;
5417
+ if (captureReason === "workspace_sleep") metadata.captureReason = captureReason;
5418
+ if (typeof sha256 === "string") metadata.sha256 = sha256;
5419
+ return metadata;
5420
+ }
5421
+ function parseChatTranscriptArtifact(value) {
5422
+ if (!isRecord(value) || typeof value.id !== "string" || typeof value.workspace_id !== "string" || value.kind !== "chat_transcript" || value.provider !== "s3" || typeof value.bucket !== "string" || typeof value.key !== "string" || typeof value.size !== "number" || typeof value.created_at !== "string") return null;
5423
+ return {
5424
+ id: value.id,
5425
+ workspace_id: value.workspace_id,
5426
+ kind: "chat_transcript",
5427
+ provider: "s3",
5428
+ bucket: value.bucket,
5429
+ key: value.key,
5430
+ size: value.size,
5431
+ metadata: normalizeChatTranscriptMetadata(value.metadata),
5432
+ created_at: value.created_at
5433
+ };
5434
+ }
5378
5435
 
5379
5436
  // ../shared/src/memory.ts
5380
5437
  var MEMORY_ROOT = `${SANDBOX_PATHS.REPLICAS_DIR}/memories`;
@@ -10972,7 +11029,7 @@ var DEFAULT_CODEX_ARGS = [
10972
11029
  var MIN_CODEX_CLI_VERSION = "0.144.6";
10973
11030
  var CODEX_UPGRADE_TIMEOUT_MS = 12e4;
10974
11031
  var codexCliVersionEnsured = null;
10975
- var ENGINE_PACKAGE_VERSION = "0.1.626";
11032
+ var ENGINE_PACKAGE_VERSION = "0.1.627";
10976
11033
  var INITIALIZE_METHOD = "initialize";
10977
11034
  var INITIALIZED_NOTIFICATION = "initialized";
10978
11035
  var ACCOUNT_LOGIN_START_METHOD = "account/login/start";
@@ -15932,6 +15989,7 @@ async function reconcileCanvasItems(filenames) {
15932
15989
 
15933
15990
  // src/services/upload-chat-transcripts.ts
15934
15991
  import { createReadStream } from "fs";
15992
+ import { createHash as createHash2 } from "crypto";
15935
15993
  import { readdir as readdir8, readFile as readFile14, stat as stat4 } from "fs/promises";
15936
15994
  import { request as httpRequest } from "http";
15937
15995
  import { request as httpsRequest } from "https";
@@ -15989,9 +16047,10 @@ async function putTranscript(uploadUrl, filePath, size) {
15989
16047
  file.pipe(request);
15990
16048
  });
15991
16049
  }
15992
- async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
16050
+ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map(), capture) {
15993
16051
  let flushed = 0;
15994
16052
  let failed = 0;
16053
+ const revisions = [];
15995
16054
  const tasks = [];
15996
16055
  for (const dir of HISTORY_DIRS) {
15997
16056
  let entries;
@@ -16004,8 +16063,9 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
16004
16063
  if (!entry.endsWith(".jsonl")) continue;
16005
16064
  const chatId = basename2(entry, ".jsonl");
16006
16065
  tasks.push(
16007
- uploadChatTranscript(chatId, join25(dir, entry), chatsById.get(chatId)).then(() => {
16066
+ uploadChatTranscript(chatId, join25(dir, entry), chatsById.get(chatId), capture).then((artifact) => {
16008
16067
  flushed++;
16068
+ if (artifact && capture) revisions.push(artifact);
16009
16069
  }).catch((err) => {
16010
16070
  failed++;
16011
16071
  console.error("[ChatTranscriptUploader] upload failed:", { chatId, err });
@@ -16014,11 +16074,11 @@ async function flushAllChatTranscripts(chatsById = /* @__PURE__ */ new Map()) {
16014
16074
  }
16015
16075
  }
16016
16076
  await Promise.all(tasks);
16017
- return { flushed, failed };
16077
+ return capture ? { flushed, failed, captureSupported: true, revisions } : { flushed, failed };
16018
16078
  }
16019
- async function uploadChatTranscript(chatId, filePath, chat) {
16079
+ async function uploadChatTranscript(chatId, filePath, chat, capture) {
16020
16080
  const { size } = await stat4(filePath);
16021
- if (size === 0) return;
16081
+ if (size === 0) return null;
16022
16082
  const metadata = chat ? {
16023
16083
  provider: chat.provider,
16024
16084
  title: chat.title,
@@ -16027,6 +16087,13 @@ async function uploadChatTranscript(chatId, filePath, chat) {
16027
16087
  parentChatId: chat.parentChatId,
16028
16088
  deletedAt: chat.deletedAt ?? null
16029
16089
  } : {};
16090
+ if (capture) {
16091
+ const hash = createHash2("sha256");
16092
+ for await (const chunk of createReadStream(filePath)) hash.update(chunk);
16093
+ metadata.captureId = capture.captureId;
16094
+ metadata.captureReason = capture.reason;
16095
+ metadata.sha256 = hash.digest("hex");
16096
+ }
16030
16097
  try {
16031
16098
  metadata.senders = parseChatMessageSendersJsonl(
16032
16099
  await readFile14(chatMessageSendersFilePath(chatId), "utf-8")
@@ -16045,7 +16112,7 @@ async function uploadChatTranscript(chatId, filePath, chat) {
16045
16112
  if (!isRecord(prepareBody) || typeof prepareBody.uploadUrl !== "string" && prepareBody.uploadUrl !== null) {
16046
16113
  throw new Error("prepare failed: invalid response");
16047
16114
  }
16048
- if (prepareBody.uploadUrl === null) return;
16115
+ if (prepareBody.uploadUrl === null) return null;
16049
16116
  await putTranscript(prepareBody.uploadUrl, filePath, size);
16050
16117
  const finalizeResponse = await monolithRequest("/v1/engine/chat-transcripts/finalize", {
16051
16118
  body: uploadRequest
@@ -16053,6 +16120,12 @@ async function uploadChatTranscript(chatId, filePath, chat) {
16053
16120
  if (!finalizeResponse.ok) {
16054
16121
  throw new Error(`finalize failed: ${finalizeResponse.status} ${await finalizeResponse.text()}`);
16055
16122
  }
16123
+ const finalizeBody = await finalizeResponse.json();
16124
+ if (!isRecord(finalizeBody)) throw new Error("finalize failed: invalid response");
16125
+ if (finalizeBody.artifact === null) return null;
16126
+ const artifact = parseChatTranscriptArtifact(finalizeBody.artifact);
16127
+ if (!artifact) throw new Error("finalize failed: invalid artifact");
16128
+ return artifact;
16056
16129
  }
16057
16130
 
16058
16131
  // src/services/upload-repo-state.ts
@@ -16759,12 +16832,12 @@ var ChatService = class {
16759
16832
  [...this.chats.entries()].map(([chatId, chat]) => [chatId, this.toSummary(chat)])
16760
16833
  ));
16761
16834
  }
16762
- async flushAllWorkspaceArtifacts() {
16835
+ async flushAllWorkspaceArtifacts(capture) {
16763
16836
  const chatsById = new Map(
16764
16837
  [...this.chats.entries()].map(([chatId, chat]) => [chatId, this.toSummary(chat)])
16765
16838
  );
16766
16839
  const [chatTranscripts, canvas, repoState, engineLogs, chatActivity] = await Promise.all([
16767
- flushAllChatTranscripts(chatsById),
16840
+ flushAllChatTranscripts(chatsById, capture),
16768
16841
  flushAllCanvasItems(),
16769
16842
  flushRepoState(),
16770
16843
  flushAllEngineLogs(),
@@ -18255,7 +18328,9 @@ function createV1Routes(deps) {
18255
18328
  });
18256
18329
  app2.post("/workspace-artifacts/flush-all", async (c) => {
18257
18330
  try {
18258
- const result = await deps.chatService.flushAllWorkspaceArtifacts();
18331
+ const body = await c.req.json().catch(() => void 0);
18332
+ const capture = body && typeof body.captureId === "string" && body.reason === "workspace_sleep" ? body : void 0;
18333
+ const result = await deps.chatService.flushAllWorkspaceArtifacts(capture);
18259
18334
  return c.json(result);
18260
18335
  } catch (error) {
18261
18336
  return c.json(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-engine",
3
- "version": "0.1.626",
3
+ "version": "0.1.627",
4
4
  "description": "Lightweight API server for Replicas workspaces",
5
5
  "type": "module",
6
6
  "main": "dist/src/index.js",