@bopen-io/tortuga-plugin 0.0.4 → 0.0.6

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.
@@ -0,0 +1,51 @@
1
+ const PLUGIN_ID = "bopen-io.tortuga-plugin";
2
+ const PLUGIN_VERSION = "0.0.3";
3
+ const PAGE_ROUTE = "tortuga";
4
+ const SLOT_IDS = {
5
+ dashboardWidget: "tortuga-dashboard-widget",
6
+ page: "tortuga-page",
7
+ sidebar: "tortuga-sidebar-link"
8
+ };
9
+ const EXPORT_NAMES = {
10
+ dashboardWidget: "FleetStatusWidget",
11
+ page: "FleetMonitorPage",
12
+ sidebar: "TortugaSidebarLink"
13
+ };
14
+ const JOB_KEYS = {
15
+ fleetHealth: "fleet-health"
16
+ };
17
+ const STREAM_CHANNELS = {
18
+ fleetStatus: "tortuga:fleet-status"
19
+ };
20
+ const DATA_KEYS = {
21
+ fleetOverview: "fleet-overview",
22
+ agentDetail: "agent-detail"
23
+ };
24
+ const ACTION_KEYS = {
25
+ pauseAgent: "pause-agent",
26
+ resumeAgent: "resume-agent",
27
+ invokeAgent: "invoke-agent"
28
+ };
29
+ const STATE_KEYS = {
30
+ /** Per-agent health snapshot: status, lastHeartbeat, run counts */
31
+ agentHealth: "health",
32
+ /** Instance-level: last fleet health check timestamp */
33
+ lastHealthCheck: "last-health-check",
34
+ /** Per-agent last-run timestamp */
35
+ lastRun: "last-run",
36
+ /** Per-agent run counters: started, completed, failed */
37
+ runCounts: "run-counts"
38
+ };
39
+ export {
40
+ ACTION_KEYS,
41
+ DATA_KEYS,
42
+ EXPORT_NAMES,
43
+ JOB_KEYS,
44
+ PAGE_ROUTE,
45
+ PLUGIN_ID,
46
+ PLUGIN_VERSION,
47
+ SLOT_IDS,
48
+ STATE_KEYS,
49
+ STREAM_CHANNELS
50
+ };
51
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/constants.ts"],
4
+ "sourcesContent": ["export const PLUGIN_ID = \"bopen-io.tortuga-plugin\";\nexport const PLUGIN_VERSION = \"0.0.3\";\nexport const PAGE_ROUTE = \"tortuga\";\n\nexport const SLOT_IDS = {\n dashboardWidget: \"tortuga-dashboard-widget\",\n page: \"tortuga-page\",\n sidebar: \"tortuga-sidebar-link\",\n} as const;\n\nexport const EXPORT_NAMES = {\n dashboardWidget: \"FleetStatusWidget\",\n page: \"FleetMonitorPage\",\n sidebar: \"TortugaSidebarLink\",\n} as const;\n\nexport const JOB_KEYS = {\n fleetHealth: \"fleet-health\",\n} as const;\n\nexport const STREAM_CHANNELS = {\n fleetStatus: \"tortuga:fleet-status\",\n} as const;\n\nexport const DATA_KEYS = {\n fleetOverview: \"fleet-overview\",\n agentDetail: \"agent-detail\",\n} as const;\n\nexport const ACTION_KEYS = {\n pauseAgent: \"pause-agent\",\n resumeAgent: \"resume-agent\",\n invokeAgent: \"invoke-agent\",\n} as const;\n\nexport const STATE_KEYS = {\n /** Per-agent health snapshot: status, lastHeartbeat, run counts */\n agentHealth: \"health\",\n /** Instance-level: last fleet health check timestamp */\n lastHealthCheck: \"last-health-check\",\n /** Per-agent last-run timestamp */\n lastRun: \"last-run\",\n /** Per-agent run counters: started, completed, failed */\n runCounts: \"run-counts\",\n} as const;\n"],
5
+ "mappings": "AAAO,MAAM,YAAY;AAClB,MAAM,iBAAiB;AACvB,MAAM,aAAa;AAEnB,MAAM,WAAW;AAAA,EACtB,iBAAiB;AAAA,EACjB,MAAM;AAAA,EACN,SAAS;AACX;AAEO,MAAM,eAAe;AAAA,EAC1B,iBAAiB;AAAA,EACjB,MAAM;AAAA,EACN,SAAS;AACX;AAEO,MAAM,WAAW;AAAA,EACtB,aAAa;AACf;AAEO,MAAM,kBAAkB;AAAA,EAC7B,aAAa;AACf;AAEO,MAAM,YAAY;AAAA,EACvB,eAAe;AAAA,EACf,aAAa;AACf;AAEO,MAAM,cAAc;AAAA,EACzB,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,aAAa;AACf;AAEO,MAAM,aAAa;AAAA;AAAA,EAExB,aAAa;AAAA;AAAA,EAEb,iBAAiB;AAAA;AAAA,EAEjB,SAAS;AAAA;AAAA,EAET,WAAW;AACb;",
6
+ "names": []
7
+ }
package/dist/worker.js CHANGED
@@ -6130,19 +6130,7 @@ var JOB_KEYS = {
6130
6130
  fleetHealth: "fleet-health"
6131
6131
  };
6132
6132
  var STREAM_CHANNELS = {
6133
- fleetStatus: "fleet-status"
6134
- };
6135
-
6136
- // src/worker.ts
6137
- var STATE_KEYS = {
6138
- /** Per-agent health snapshot: status, lastHeartbeat, run counts */
6139
- agentHealth: "health",
6140
- /** Per-agent last-run timestamp */
6141
- lastRun: "last-run",
6142
- /** Per-agent run counters: started, completed, failed */
6143
- runCounts: "run-counts",
6144
- /** Instance-level: last fleet health check timestamp */
6145
- lastHealthCheck: "last-health-check"
6133
+ fleetStatus: "tortuga:fleet-status"
6146
6134
  };
6147
6135
  var DATA_KEYS = {
6148
6136
  fleetOverview: "fleet-overview",
@@ -6153,8 +6141,26 @@ var ACTION_KEYS = {
6153
6141
  resumeAgent: "resume-agent",
6154
6142
  invokeAgent: "invoke-agent"
6155
6143
  };
6144
+ var STATE_KEYS = {
6145
+ /** Per-agent health snapshot: status, lastHeartbeat, run counts */
6146
+ agentHealth: "health",
6147
+ /** Instance-level: last fleet health check timestamp */
6148
+ lastHealthCheck: "last-health-check",
6149
+ /** Per-agent last-run timestamp */
6150
+ lastRun: "last-run",
6151
+ /** Per-agent run counters: started, completed, failed */
6152
+ runCounts: "run-counts"
6153
+ };
6154
+
6155
+ // src/worker.ts
6156
6156
  var currentContext = null;
6157
- var openStreams = /* @__PURE__ */ new Set();
6157
+ var agentLocks = /* @__PURE__ */ new Map();
6158
+ async function withAgentLock(agentId, fn) {
6159
+ const prev = agentLocks.get(agentId) ?? Promise.resolve();
6160
+ const next = prev.then(fn, fn);
6161
+ agentLocks.set(agentId, next);
6162
+ await next;
6163
+ }
6158
6164
  function summarizeError(error) {
6159
6165
  if (error instanceof Error) return error.message;
6160
6166
  return String(error);
@@ -6334,15 +6340,17 @@ function registerEventHandlers(ctx) {
6334
6340
  if (!agentId) return;
6335
6341
  const payload = event.payload;
6336
6342
  ctx.logger.info("Agent run started", { agentId, runId: payload.runId });
6337
- const counts = await getRunCounts(ctx, agentId);
6338
- counts.started++;
6339
- await setRunCounts(ctx, agentId, counts);
6340
- const healthState = await getAgentHealthState(ctx, agentId);
6341
- if (healthState) {
6342
- healthState.lastRunAt = event.occurredAt;
6343
- healthState.runCounts = counts;
6344
- await setAgentHealthState(ctx, agentId, healthState);
6345
- }
6343
+ await withAgentLock(agentId, async () => {
6344
+ const counts = await getRunCounts(ctx, agentId);
6345
+ counts.started++;
6346
+ await setRunCounts(ctx, agentId, counts);
6347
+ const healthState = await getAgentHealthState(ctx, agentId);
6348
+ if (healthState) {
6349
+ healthState.lastRunAt = event.occurredAt;
6350
+ healthState.runCounts = counts;
6351
+ await setAgentHealthState(ctx, agentId, healthState);
6352
+ }
6353
+ });
6346
6354
  ctx.streams.emit(STREAM_CHANNELS.fleetStatus, {
6347
6355
  type: "run-started",
6348
6356
  agentId,
@@ -6356,15 +6364,17 @@ function registerEventHandlers(ctx) {
6356
6364
  if (!agentId) return;
6357
6365
  const payload = event.payload;
6358
6366
  ctx.logger.info("Agent run finished", { agentId, runId: payload.runId });
6359
- const counts = await getRunCounts(ctx, agentId);
6360
- counts.completed++;
6361
- await setRunCounts(ctx, agentId, counts);
6362
- const healthState = await getAgentHealthState(ctx, agentId);
6363
- if (healthState) {
6364
- healthState.lastRunAt = event.occurredAt;
6365
- healthState.runCounts = counts;
6366
- await setAgentHealthState(ctx, agentId, healthState);
6367
- }
6367
+ await withAgentLock(agentId, async () => {
6368
+ const counts = await getRunCounts(ctx, agentId);
6369
+ counts.completed++;
6370
+ await setRunCounts(ctx, agentId, counts);
6371
+ const healthState = await getAgentHealthState(ctx, agentId);
6372
+ if (healthState) {
6373
+ healthState.lastRunAt = event.occurredAt;
6374
+ healthState.runCounts = counts;
6375
+ await setAgentHealthState(ctx, agentId, healthState);
6376
+ }
6377
+ });
6368
6378
  ctx.streams.emit(STREAM_CHANNELS.fleetStatus, {
6369
6379
  type: "run-finished",
6370
6380
  agentId,
@@ -6382,15 +6392,17 @@ function registerEventHandlers(ctx) {
6382
6392
  runId: payload.runId,
6383
6393
  error: payload.error
6384
6394
  });
6385
- const counts = await getRunCounts(ctx, agentId);
6386
- counts.failed++;
6387
- await setRunCounts(ctx, agentId, counts);
6388
- const healthState = await getAgentHealthState(ctx, agentId);
6389
- if (healthState) {
6390
- healthState.lastRunAt = event.occurredAt;
6391
- healthState.runCounts = counts;
6392
- await setAgentHealthState(ctx, agentId, healthState);
6393
- }
6395
+ await withAgentLock(agentId, async () => {
6396
+ const counts = await getRunCounts(ctx, agentId);
6397
+ counts.failed++;
6398
+ await setRunCounts(ctx, agentId, counts);
6399
+ const healthState = await getAgentHealthState(ctx, agentId);
6400
+ if (healthState) {
6401
+ healthState.lastRunAt = event.occurredAt;
6402
+ healthState.runCounts = counts;
6403
+ await setAgentHealthState(ctx, agentId, healthState);
6404
+ }
6405
+ });
6394
6406
  ctx.streams.emit(STREAM_CHANNELS.fleetStatus, {
6395
6407
  type: "run-failed",
6396
6408
  agentId,
@@ -6515,6 +6527,10 @@ function registerActionHandlers(ctx) {
6515
6527
  const companyId = requireParam(params, "companyId");
6516
6528
  const prompt = requireParam(params, "prompt");
6517
6529
  const reason = typeof params.reason === "string" ? params.reason : void 0;
6530
+ const MAX_PROMPT_LENGTH = 1e4;
6531
+ if (prompt.length > MAX_PROMPT_LENGTH) {
6532
+ throw new Error(`prompt exceeds maximum length of ${MAX_PROMPT_LENGTH} characters`);
6533
+ }
6518
6534
  ctx.logger.info("Invoking agent", { agentId, companyId, reason });
6519
6535
  const { runId } = await ctx.agents.invoke(agentId, companyId, { prompt, reason });
6520
6536
  return {
@@ -6599,15 +6615,6 @@ var plugin = definePlugin({
6599
6615
  }
6600
6616
  },
6601
6617
  async onShutdown() {
6602
- if (currentContext) {
6603
- for (const channel of openStreams) {
6604
- try {
6605
- currentContext.streams.close(channel);
6606
- } catch {
6607
- }
6608
- }
6609
- openStreams.clear();
6610
- }
6611
6618
  currentContext = null;
6612
6619
  }
6613
6620
  });