@getpaseo/server 0.4.0-beta.1 → 0.4.0-beta.2

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 (27) hide show
  1. package/dist/server/server/agent/agent-manager.d.ts +5 -0
  2. package/dist/server/server/agent/agent-manager.js +70 -10
  3. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-0ac77347d0adc72ec7a608040c57240c.js → desktop-attachment-bridge-2bd7189b2048681da8d48db76905a8b0.js} +1 -1
  4. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-bridge-0ac77347d0adc72ec7a608040c57240c.js.br → desktop-attachment-bridge-2bd7189b2048681da8d48db76905a8b0.js.br} +0 -0
  5. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-2bd7189b2048681da8d48db76905a8b0.js.gz +0 -0
  6. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-20c92e20c40063e1bf02a5b1f175a07b.js → desktop-attachment-store-43f5b899fc1319ae00b41f0076c7de63.js} +1 -1
  7. package/dist/server/web-ui/_expo/static/js/web/{desktop-attachment-store-20c92e20c40063e1bf02a5b1f175a07b.js.br → desktop-attachment-store-43f5b899fc1319ae00b41f0076c7de63.js.br} +0 -0
  8. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-43f5b899fc1319ae00b41f0076c7de63.js.gz +0 -0
  9. package/dist/server/web-ui/_expo/static/js/web/{index-d0cf5f5cd3c6adbff2cf2a51ca359853.js → index-c0912977316077c5d431b3e3c5fa4d74.js} +190 -188
  10. package/dist/server/web-ui/_expo/static/js/web/index-c0912977316077c5d431b3e3c5fa4d74.js.br +0 -0
  11. package/dist/server/web-ui/_expo/static/js/web/index-c0912977316077c5d431b3e3c5fa4d74.js.gz +0 -0
  12. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-88d6520cb56640c5657f0168d50ea935.js → indexeddb-attachment-store-cd66a81d02c7ff698a41c5306f36593b.js} +1 -1
  13. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-88d6520cb56640c5657f0168d50ea935.js.br → indexeddb-attachment-store-cd66a81d02c7ff698a41c5306f36593b.js.br} +0 -0
  14. package/dist/server/web-ui/_expo/static/js/web/{indexeddb-attachment-store-88d6520cb56640c5657f0168d50ea935.js.gz → indexeddb-attachment-store-cd66a81d02c7ff698a41c5306f36593b.js.gz} +0 -0
  15. package/dist/server/web-ui/_expo/static/js/web/{native-file-attachment-store-cd358058d067f458f93c4fca2e887778.js → native-file-attachment-store-0f19dbb7745360abf16e10347aca604c.js} +3 -3
  16. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-0f19dbb7745360abf16e10347aca604c.js.br +0 -0
  17. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-0f19dbb7745360abf16e10347aca604c.js.gz +0 -0
  18. package/dist/server/web-ui/index.html +1 -1
  19. package/dist/server/web-ui/index.html.br +0 -0
  20. package/dist/server/web-ui/index.html.gz +0 -0
  21. package/package.json +5 -5
  22. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-bridge-0ac77347d0adc72ec7a608040c57240c.js.gz +0 -0
  23. package/dist/server/web-ui/_expo/static/js/web/desktop-attachment-store-20c92e20c40063e1bf02a5b1f175a07b.js.gz +0 -0
  24. package/dist/server/web-ui/_expo/static/js/web/index-d0cf5f5cd3c6adbff2cf2a51ca359853.js.br +0 -0
  25. package/dist/server/web-ui/_expo/static/js/web/index-d0cf5f5cd3c6adbff2cf2a51ca359853.js.gz +0 -0
  26. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-cd358058d067f458f93c4fca2e887778.js.br +0 -0
  27. package/dist/server/web-ui/_expo/static/js/web/native-file-attachment-store-cd358058d067f458f93c4fca2e887778.js.gz +0 -0
@@ -230,6 +230,7 @@ export declare class AgentManager {
230
230
  private readonly backgroundTasks;
231
231
  private readonly agentRegistrationTasks;
232
232
  private readonly inFlightAgentCloses;
233
+ private readonly lifecycleMutationTails;
233
234
  private readonly agentStreamCoalescer;
234
235
  private mcpBaseUrl;
235
236
  private readonly mcpAuthToken;
@@ -318,6 +319,7 @@ export declare class AgentManager {
318
319
  archiveAgent(agentId: string): Promise<{
319
320
  archivedAt: string;
320
321
  }>;
322
+ private archiveAgentUnlocked;
321
323
  private cascadeArchiveChildren;
322
324
  private markRecordArchived;
323
325
  private fireAgentArchived;
@@ -335,6 +337,7 @@ export declare class AgentManager {
335
337
  live: boolean;
336
338
  previousParentAgentId: string | null;
337
339
  }>;
340
+ private detachAgentUnlocked;
338
341
  notifyAgentState(agentId: string): void;
339
342
  clearAgentAttention(agentId: string): Promise<void>;
340
343
  archiveSnapshot(agentId: string, archivedAt: string): Promise<StoredAgentRecord>;
@@ -347,6 +350,8 @@ export declare class AgentManager {
347
350
  title?: string;
348
351
  labels?: Record<string, string>;
349
352
  }): Promise<void>;
353
+ private updateAgentMetadataUnlocked;
354
+ private runLifecycleMutation;
350
355
  runAgent(agentId: string, prompt: AgentPromptInput, options?: AgentRunOptions): Promise<AgentRunResult>;
351
356
  /**
352
357
  * Try to run a prompt out-of-band — i.e. without allocating a foreground turn
@@ -2,7 +2,7 @@ import { randomUUID } from "node:crypto";
2
2
  import { resolve } from "node:path";
3
3
  import { stat } from "node:fs/promises";
4
4
  import { AGENT_LIFECYCLE_STATUSES, } from "@getpaseo/protocol/agent-lifecycle";
5
- import { getParentAgentIdFromLabels, isDelegatedAgent, PARENT_AGENT_ID_LABEL, } from "@getpaseo/protocol/agent-labels";
5
+ import { getParentAgentIdFromLabels, hasOpenAgentTab, isDelegatedAgent, isOpenAgentTabLabel, PARENT_AGENT_ID_LABEL, } from "@getpaseo/protocol/agent-labels";
6
6
  import { z } from "zod";
7
7
  import { getAgentStreamEventTurnId, } from "./agent-sdk-types.js";
8
8
  import { buildArchivedAgentRecord } from "./agent-archive.js";
@@ -223,6 +223,21 @@ function getFirstUserMessageTextFromRows(rows) {
223
223
  }
224
224
  return null;
225
225
  }
226
+ function shouldDetachFromArchivedParent(parent, child) {
227
+ const isCrossWorkspace = parent.workspaceId !== undefined &&
228
+ child.workspaceId !== undefined &&
229
+ parent.workspaceId !== child.workspaceId;
230
+ return isCrossWorkspace || hasOpenAgentTab(child.labels);
231
+ }
232
+ function detachedAgentLabelPatch(labels) {
233
+ const patch = { [PARENT_AGENT_ID_LABEL]: null };
234
+ for (const label of Object.keys(labels)) {
235
+ if (isOpenAgentTabLabel(label)) {
236
+ patch[label] = null;
237
+ }
238
+ }
239
+ return patch;
240
+ }
226
241
  export class AgentManager {
227
242
  constructor(options) {
228
243
  this.clients = new Map();
@@ -239,6 +254,7 @@ export class AgentManager {
239
254
  this.backgroundTasks = new Set();
240
255
  this.agentRegistrationTasks = new Set();
241
256
  this.inFlightAgentCloses = new Map();
257
+ this.lifecycleMutationTails = new Map();
242
258
  this.paseoToolsEnabled = true;
243
259
  this.paseoToolCatalogFactory = null;
244
260
  this.acceptingAgentRegistrations = true;
@@ -879,6 +895,9 @@ export class AgentManager {
879
895
  }
880
896
  }
881
897
  async archiveAgent(agentId) {
898
+ return this.runLifecycleMutation(agentId, () => this.archiveAgentUnlocked(agentId));
899
+ }
900
+ async archiveAgentUnlocked(agentId) {
882
901
  const agent = this.requireAgent(agentId);
883
902
  if (!this.registry) {
884
903
  throw new Error("Agent storage is not configured");
@@ -907,6 +926,10 @@ export class AgentManager {
907
926
  return;
908
927
  }
909
928
  const records = await registry.list();
929
+ const parent = records.find((record) => record.id === parentAgentId);
930
+ if (!parent) {
931
+ throw new Error(`Archived parent ${parentAgentId} not found in storage`);
932
+ }
910
933
  for (const record of records) {
911
934
  if (record.archivedAt) {
912
935
  continue;
@@ -914,12 +937,27 @@ export class AgentManager {
914
937
  if (record.labels?.[PARENT_AGENT_ID_LABEL] !== parentAgentId) {
915
938
  continue;
916
939
  }
917
- if (this.agents.has(record.id)) {
918
- await this.archiveAgent(record.id);
919
- }
920
- else {
921
- await this.archiveSnapshot(record.id, new Date().toISOString());
940
+ const child = await registry.get(record.id);
941
+ if (!child || child.archivedAt || child.labels?.[PARENT_AGENT_ID_LABEL] !== parentAgentId) {
942
+ continue;
922
943
  }
944
+ await this.runLifecycleMutation(child.id, async () => {
945
+ const currentChild = await registry.get(child.id);
946
+ if (!currentChild ||
947
+ currentChild.archivedAt ||
948
+ currentChild.labels?.[PARENT_AGENT_ID_LABEL] !== parentAgentId) {
949
+ return;
950
+ }
951
+ if (shouldDetachFromArchivedParent(parent, currentChild)) {
952
+ await this.detachAgentUnlocked(currentChild.id);
953
+ }
954
+ else if (this.agents.has(currentChild.id)) {
955
+ await this.archiveAgentUnlocked(currentChild.id);
956
+ }
957
+ else {
958
+ await this.archiveSnapshot(currentChild.id, new Date().toISOString());
959
+ }
960
+ });
923
961
  }
924
962
  }
925
963
  async markRecordArchived(record) {
@@ -1067,8 +1105,10 @@ export class AgentManager {
1067
1105
  this.emitState(agent, { persist: false });
1068
1106
  }
1069
1107
  async setLabels(agentId, labels) {
1070
- const agent = this.requireAgent(agentId);
1071
- await this.writeLabels(agent.id, labels);
1108
+ await this.runLifecycleMutation(agentId, async () => {
1109
+ const agent = this.requireAgent(agentId);
1110
+ await this.writeLabels(agent.id, labels);
1111
+ });
1072
1112
  }
1073
1113
  async writeLabels(agentId, patch) {
1074
1114
  const liveAgent = this.agents.get(agentId);
@@ -1099,6 +1139,9 @@ export class AgentManager {
1099
1139
  return nextRecord;
1100
1140
  }
1101
1141
  async detachAgent(agentId) {
1142
+ return this.runLifecycleMutation(agentId, () => this.detachAgentUnlocked(agentId));
1143
+ }
1144
+ async detachAgentUnlocked(agentId) {
1102
1145
  const registry = this.requireRegistry();
1103
1146
  const liveAgent = this.agents.get(agentId);
1104
1147
  if (liveAgent) {
@@ -1111,7 +1154,7 @@ export class AgentManager {
1111
1154
  }
1112
1155
  return { record, live: true, previousParentAgentId: null };
1113
1156
  }
1114
- const { record } = await this.writeLabels(agentId, { [PARENT_AGENT_ID_LABEL]: null });
1157
+ const { record } = await this.writeLabels(agentId, detachedAgentLabelPatch(liveAgent.labels));
1115
1158
  if (!record) {
1116
1159
  throw new Error(`Agent not found in storage after detach: ${agentId}`);
1117
1160
  }
@@ -1125,7 +1168,7 @@ export class AgentManager {
1125
1168
  if (!previousParentAgentId) {
1126
1169
  return { record, live: false, previousParentAgentId: null };
1127
1170
  }
1128
- const result = await this.writeLabels(agentId, { [PARENT_AGENT_ID_LABEL]: null });
1171
+ const result = await this.writeLabels(agentId, detachedAgentLabelPatch(record.labels));
1129
1172
  if (!result.record) {
1130
1173
  throw new Error(`Agent not found in storage after detach: ${agentId}`);
1131
1174
  }
@@ -1205,6 +1248,9 @@ export class AgentManager {
1205
1248
  await this.unarchiveSnapshot(matched.id);
1206
1249
  }
1207
1250
  async updateAgentMetadata(agentId, updates) {
1251
+ await this.runLifecycleMutation(agentId, () => this.updateAgentMetadataUnlocked(agentId, updates));
1252
+ }
1253
+ async updateAgentMetadataUnlocked(agentId, updates) {
1208
1254
  const liveAgent = this.getAgent(agentId);
1209
1255
  if (liveAgent) {
1210
1256
  if (updates.title) {
@@ -1217,6 +1263,20 @@ export class AgentManager {
1217
1263
  }
1218
1264
  await this.writeStoredMetadata(agentId, updates);
1219
1265
  }
1266
+ async runLifecycleMutation(agentId, mutation) {
1267
+ // Parent cascade classifies a child inside the same lane used by open-tab
1268
+ // label writes, so a received ownership update cannot be overtaken.
1269
+ const previous = this.lifecycleMutationTails.get(agentId) ?? Promise.resolve();
1270
+ const result = previous.catch(() => undefined).then(mutation);
1271
+ const tail = result.then(() => undefined, () => undefined);
1272
+ this.lifecycleMutationTails.set(agentId, tail);
1273
+ void tail.finally(() => {
1274
+ if (this.lifecycleMutationTails.get(agentId) === tail) {
1275
+ this.lifecycleMutationTails.delete(agentId);
1276
+ }
1277
+ });
1278
+ return result;
1279
+ }
1220
1280
  async runAgent(agentId, prompt, options) {
1221
1281
  const events = this.streamAgent(agentId, prompt, options);
1222
1282
  const timeline = [];
@@ -1 +1 @@
1
- __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.createDesktopAttachmentBridge=function(){const l=(0,s.createDesktopPreviewUrlResolver)({reader:(0,s.createDesktopFileReader)(),objectUrls:(0,s.createBrowserObjectUrlMinter)()});return{copyFile:t.copyDesktopAttachmentFile,writeBase64:t.writeDesktopAttachmentBase64,writeBytes:t.writeDesktopAttachmentBytes,deleteFile:t.deleteDesktopAttachmentFile,garbageCollect:t.garbageCollectDesktopAttachmentFiles,readFileBase64:s.readDesktopFileBase64,resolvePreviewUrl:t=>l.resolve(t),releasePreviewUrl:t=>l.release(t)}};var t=r(d[0]),s=r(d[1])},4796,[4169,4170]);
1
+ __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.createDesktopAttachmentBridge=function(){const l=(0,s.createDesktopPreviewUrlResolver)({reader:(0,s.createDesktopFileReader)(),objectUrls:(0,s.createBrowserObjectUrlMinter)()});return{copyFile:t.copyDesktopAttachmentFile,writeBase64:t.writeDesktopAttachmentBase64,writeBytes:t.writeDesktopAttachmentBytes,deleteFile:t.deleteDesktopAttachmentFile,garbageCollect:t.garbageCollectDesktopAttachmentFiles,readFileBase64:s.readDesktopFileBase64,resolvePreviewUrl:t=>l.resolve(t),releasePreviewUrl:t=>l.release(t)}};var t=r(d[0]),s=r(d[1])},4798,[4169,4170]);
@@ -1 +1 @@
1
- __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.createDesktopAttachmentStore=function(n){return{storageType:"desktop-file",async save(s){const o=s.id??(0,t.generateAttachmentId)(),l=s.fileName??null;if("file_uri"===s.source.kind)return await c(n,{id:o,uri:s.source.uri,mimeType:s.mimeType,fileName:l});if("data_url"===s.source.kind){const c=(0,t.parseDataUrl)(s.source.dataUrl),p=(0,t.normalizeMimeType)(s.mimeType??c.mimeType);return await y(n,{id:o,base64:c.base64,mimeType:p,fileName:l})}if("bytes"===s.source.kind){const c=(0,t.normalizeMimeType)(s.mimeType);return await p(n,{id:o,bytes:s.source.bytes,mimeType:c,fileName:l})}const f=(0,t.normalizeMimeType)(s.mimeType??s.source.blob.type),u=await(0,t.blobToBase64)(s.source.blob);return await y(n,{id:o,base64:u,mimeType:f,fileName:l})},encodeBase64:async({attachment:t})=>(f(t),await n.readFileBase64(t.storageKey)),resolvePreviewUrl:async({attachment:t})=>(f(t),await n.resolvePreviewUrl(t)),async releasePreviewUrl({attachment:t,url:s}){f(t),await n.releasePreviewUrl({url:s})},async delete({attachment:t}){f(t),await n.deleteFile({path:t.storageKey})},async garbageCollect({referencedIds:t}){await n.garbageCollect({referencedIds:Array.from(t)})}}};var t=r(d[0]);const n={"image/png":".png","image/jpeg":".jpg","image/jpg":".jpg","image/gif":".gif","image/webp":".webp","image/avif":".avif","image/heic":".heic","image/heif":".heif","image/tiff":".tiff","image/bmp":".bmp","image/svg+xml":".svg"};function s(t){const n=t.replace(/\\/g,"/").split("/"),s=n[n.length-1];return s&&s.length>0?s:null}function o(s){const o=(0,t.getFileExtensionFromName)(s.fileName);if(o)return o;const l=(0,t.getFileExtensionFromName)(s.sourcePath);return l||(n[s.mimeType]??".img")}function l(t){return{id:t.id,mimeType:t.mimeType,storageType:"desktop-file",storageKey:t.storagePath,fileName:t.fileName??null,byteSize:t.byteSize,createdAt:Date.now()}}async function c(n,c){const y=(0,t.fileUriToPath)(c.uri),p=c.fileName??s(y),f=(0,t.normalizeMimeType)(c.mimeType),u=o({fileName:p,sourcePath:y,mimeType:f}),T=await n.copyFile({attachmentId:c.id,sourcePath:y,extension:u});return l({id:c.id,mimeType:f,storagePath:T.path,byteSize:T.byteSize,fileName:p})}async function y(t,n){const s=o({fileName:n.fileName,mimeType:n.mimeType}),c=await t.writeBase64({attachmentId:n.id,base64:n.base64,extension:s});return l({id:n.id,mimeType:n.mimeType,storagePath:c.path,byteSize:c.byteSize,fileName:n.fileName})}async function p(t,n){const s=o({fileName:n.fileName,mimeType:n.mimeType}),c=await t.writeBytes({attachmentId:n.id,bytes:n.bytes,extension:s});return l({id:n.id,mimeType:n.mimeType,storagePath:c.path,byteSize:c.byteSize,fileName:n.fileName})}function f(t){if("desktop-file"!==t.storageType)throw new Error(`Unsupported desktop attachment storage type '${t.storageType}'.`)}},4795,[4163]);
1
+ __d(function(g,r,i,a,m,e,d){"use strict";Object.defineProperty(e,'__esModule',{value:!0}),e.createDesktopAttachmentStore=function(n){return{storageType:"desktop-file",async save(s){const o=s.id??(0,t.generateAttachmentId)(),l=s.fileName??null;if("file_uri"===s.source.kind)return await c(n,{id:o,uri:s.source.uri,mimeType:s.mimeType,fileName:l});if("data_url"===s.source.kind){const c=(0,t.parseDataUrl)(s.source.dataUrl),p=(0,t.normalizeMimeType)(s.mimeType??c.mimeType);return await y(n,{id:o,base64:c.base64,mimeType:p,fileName:l})}if("bytes"===s.source.kind){const c=(0,t.normalizeMimeType)(s.mimeType);return await p(n,{id:o,bytes:s.source.bytes,mimeType:c,fileName:l})}const f=(0,t.normalizeMimeType)(s.mimeType??s.source.blob.type),u=await(0,t.blobToBase64)(s.source.blob);return await y(n,{id:o,base64:u,mimeType:f,fileName:l})},encodeBase64:async({attachment:t})=>(f(t),await n.readFileBase64(t.storageKey)),resolvePreviewUrl:async({attachment:t})=>(f(t),await n.resolvePreviewUrl(t)),async releasePreviewUrl({attachment:t,url:s}){f(t),await n.releasePreviewUrl({url:s})},async delete({attachment:t}){f(t),await n.deleteFile({path:t.storageKey})},async garbageCollect({referencedIds:t}){await n.garbageCollect({referencedIds:Array.from(t)})}}};var t=r(d[0]);const n={"image/png":".png","image/jpeg":".jpg","image/jpg":".jpg","image/gif":".gif","image/webp":".webp","image/avif":".avif","image/heic":".heic","image/heif":".heif","image/tiff":".tiff","image/bmp":".bmp","image/svg+xml":".svg"};function s(t){const n=t.replace(/\\/g,"/").split("/"),s=n[n.length-1];return s&&s.length>0?s:null}function o(s){const o=(0,t.getFileExtensionFromName)(s.fileName);if(o)return o;const l=(0,t.getFileExtensionFromName)(s.sourcePath);return l||(n[s.mimeType]??".img")}function l(t){return{id:t.id,mimeType:t.mimeType,storageType:"desktop-file",storageKey:t.storagePath,fileName:t.fileName??null,byteSize:t.byteSize,createdAt:Date.now()}}async function c(n,c){const y=(0,t.fileUriToPath)(c.uri),p=c.fileName??s(y),f=(0,t.normalizeMimeType)(c.mimeType),u=o({fileName:p,sourcePath:y,mimeType:f}),T=await n.copyFile({attachmentId:c.id,sourcePath:y,extension:u});return l({id:c.id,mimeType:f,storagePath:T.path,byteSize:T.byteSize,fileName:p})}async function y(t,n){const s=o({fileName:n.fileName,mimeType:n.mimeType}),c=await t.writeBase64({attachmentId:n.id,base64:n.base64,extension:s});return l({id:n.id,mimeType:n.mimeType,storagePath:c.path,byteSize:c.byteSize,fileName:n.fileName})}async function p(t,n){const s=o({fileName:n.fileName,mimeType:n.mimeType}),c=await t.writeBytes({attachmentId:n.id,bytes:n.bytes,extension:s});return l({id:n.id,mimeType:n.mimeType,storagePath:c.path,byteSize:c.byteSize,fileName:n.fileName})}function f(t){if("desktop-file"!==t.storageType)throw new Error(`Unsupported desktop attachment storage type '${t.storageType}'.`)}},4797,[4163]);