atris 3.15.49 → 3.15.50

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.
@@ -544,6 +544,7 @@ function parseComputerOptions(argv) {
544
544
  let workspaceId = null;
545
545
  let waitForResult = true;
546
546
  let message = null;
547
+ let force = false;
547
548
 
548
549
  for (let i = 0; i < argv.length; i++) {
549
550
  const arg = argv[i];
@@ -600,6 +601,10 @@ function parseComputerOptions(argv) {
600
601
  waitForResult = false;
601
602
  continue;
602
603
  }
604
+ if (arg === '--force') {
605
+ force = true;
606
+ continue;
607
+ }
603
608
  positional.push(arg);
604
609
  }
605
610
 
@@ -618,6 +623,7 @@ function parseComputerOptions(argv) {
618
623
  workspaceId: workspaceId ? String(workspaceId).trim() : null,
619
624
  waitForResult,
620
625
  message,
626
+ force,
621
627
  },
622
628
  };
623
629
  }
@@ -1174,7 +1180,8 @@ function printComputerCommandFailure(result, ctx = null) {
1174
1180
  if (result?.status === 409) {
1175
1181
  const mismatch = extractAttachedWorkspaceMismatch(detail, result?.data);
1176
1182
  const targetWorkspace = mismatch?.requestedWorkspaceId || ctx?.workspaceId || '<workspace-id>';
1177
- console.error(`Run: atris computer activate --business ${businessSelector(ctx)} --workspace ${targetWorkspace}`);
1183
+ const forceFlag = /--force|force to take over|re-run with --force/i.test(detail) ? ' --force' : '';
1184
+ console.error(`Run: atris computer activate --business ${businessSelector(ctx)} --workspace ${targetWorkspace}${forceFlag}`);
1178
1185
  }
1179
1186
  }
1180
1187
 
@@ -1253,6 +1260,17 @@ function formatWorkspaceRef(workspace) {
1253
1260
  return workspace.name ? `${workspace.name} (${workspace.id})` : workspace.id;
1254
1261
  }
1255
1262
 
1263
+ function formatLeaseAge(seconds) {
1264
+ const value = Number(seconds);
1265
+ if (!Number.isFinite(value) || value < 0) return '-';
1266
+ if (value < 60) return `${Math.floor(value)}s`;
1267
+ const minutes = Math.floor(value / 60);
1268
+ if (minutes < 60) return `${minutes}m`;
1269
+ const hours = Math.floor(minutes / 60);
1270
+ if (hours < 48) return `${hours}h`;
1271
+ return `${Math.floor(hours / 24)}d`;
1272
+ }
1273
+
1256
1274
  async function probeAttachedWorkspace(token, ctx) {
1257
1275
  const result = await apiRequestJson(
1258
1276
  `/business/${ctx.businessId}/workspaces/${ctx.workspaceId}/terminal`,
@@ -1272,7 +1290,7 @@ async function probeAttachedWorkspace(token, ctx) {
1272
1290
  return { workspaceId: null, health: 'degraded', result };
1273
1291
  }
1274
1292
 
1275
- async function bootstrapBusinessComputerRuntime(token, ctx, boundary = 'computer-wake') {
1293
+ async function bootstrapBusinessComputerRuntime(token, ctx, boundary = 'computer-wake', options = {}) {
1276
1294
  if (!ctx?.businessId || !ctx?.workspaceId) {
1277
1295
  return { ok: false, skipped: true, reason: 'missing_workspace' };
1278
1296
  }
@@ -1288,8 +1306,10 @@ async function bootstrapBusinessComputerRuntime(token, ctx, boundary = 'computer
1288
1306
  });
1289
1307
  const result = await runBusinessTerminalCommand(token, ctx, command, 120);
1290
1308
  if (!result.ok) {
1291
- console.log(' Runtime: bootstrap could not run.');
1292
- console.log(` Recovery: atris computer run "npm install --prefix /workspace/.atris-npm atris@latest && /workspace/.atris-npm/node_modules/.bin/atris update" --business ${ctx.slug || ctx.businessId} --workspace ${ctx.workspaceId}`);
1309
+ if (!options.quiet) {
1310
+ console.log(' Runtime: bootstrap could not run.');
1311
+ console.log(` Recovery: atris computer run "npm install --prefix /workspace/.atris-npm atris@latest && /workspace/.atris-npm/node_modules/.bin/atris update" --business ${ctx.slug || ctx.businessId} --workspace ${ctx.workspaceId}`);
1312
+ }
1293
1313
  return { ok: false, result };
1294
1314
  }
1295
1315
 
@@ -1297,13 +1317,15 @@ async function bootstrapBusinessComputerRuntime(token, ctx, boundary = 'computer
1297
1317
  const output = String(data.stdout || data.output || data.result || '').trim();
1298
1318
  const line = output.split('\n').find((entry) => entry.includes('atris_runtime_bootstrap'));
1299
1319
  const recovery = output.split('\n').find((entry) => entry.startsWith('recovery='));
1300
- if (line) {
1301
- console.log(` Runtime: ${line.replace(/^atris_runtime_bootstrap\s*/, '')}`);
1302
- } else {
1303
- console.log(' Runtime: Atris bootstrap receipt written.');
1304
- }
1305
- if (recovery) {
1306
- console.log(` Recovery: atris computer run "${recovery.slice('recovery='.length)}" --business ${ctx.slug || ctx.businessId} --workspace ${ctx.workspaceId}`);
1320
+ if (!options.quiet) {
1321
+ if (line) {
1322
+ console.log(` Runtime: ${line.replace(/^atris_runtime_bootstrap\s*/, '')}`);
1323
+ } else {
1324
+ console.log(' Runtime: Atris bootstrap receipt written.');
1325
+ }
1326
+ if (recovery) {
1327
+ console.log(` Recovery: atris computer run "${recovery.slice('recovery='.length)}" --business ${ctx.slug || ctx.businessId} --workspace ${ctx.workspaceId}`);
1328
+ }
1307
1329
  }
1308
1330
  return { ok: true, output };
1309
1331
  }
@@ -1471,7 +1493,7 @@ async function ensureBusinessAwake(token, ctx, maxWaitSec = 90, options = {}) {
1471
1493
  if (next.ok && next.data && next.data.status === 'running' && next.data.endpoint) {
1472
1494
  const elapsed = Math.floor((Date.now() - start) / 1000);
1473
1495
  if (!options.quiet) console.log(`awake (${elapsed}s)`);
1474
- await bootstrapBusinessComputerRuntime(token, ctx, 'computer-auto-wake');
1496
+ await bootstrapBusinessComputerRuntime(token, ctx, 'computer-auto-wake', options);
1475
1497
  return true;
1476
1498
  }
1477
1499
  }
@@ -1500,10 +1522,24 @@ async function computerStatus(token, ctx = null) {
1500
1522
  const targetWorkspace = workspaces.find((workspace) => workspace.id === ctx.workspaceId) || (ctx.workspaceId ? { id: ctx.workspaceId } : null);
1501
1523
  console.log(` Default workspace: ${formatWorkspaceRef(defaultWorkspace)}`);
1502
1524
  console.log(` Target workspace: ${formatWorkspaceRef(targetWorkspace)}`);
1525
+ const attachedFromStatus = d.attached_workspace_id
1526
+ ? { workspaceId: d.attached_workspace_id, health: null }
1527
+ : null;
1528
+ if (attachedFromStatus) {
1529
+ const attachedWorkspace = workspaces.find((workspace) => workspace.id === attachedFromStatus.workspaceId)
1530
+ || { id: attachedFromStatus.workspaceId, name: d.attached_workspace_name || null };
1531
+ console.log(` Attached workspace: ${formatWorkspaceRef(attachedWorkspace)}`);
1532
+ console.log(` Attached by: ${d.attached_by || '-'}`);
1533
+ console.log(` Attached at: ${d.attached_at || '-'}`);
1534
+ console.log(` Lease age: ${formatLeaseAge(d.lease_age_seconds)}`);
1535
+ if (d.takeover_hint) console.log(` Takeover hint: ${d.takeover_hint}`);
1536
+ }
1503
1537
  if (status === 'running' && d.endpoint && ctx.workspaceId) {
1504
1538
  const attached = await probeAttachedWorkspace(token, ctx);
1505
- const attachedWorkspace = workspaces.find((workspace) => workspace.id === attached.workspaceId) || (attached.workspaceId ? { id: attached.workspaceId } : null);
1506
- console.log(` Attached workspace: ${formatWorkspaceRef(attachedWorkspace)}`);
1539
+ if (!attachedFromStatus) {
1540
+ const attachedWorkspace = workspaces.find((workspace) => workspace.id === attached.workspaceId) || (attached.workspaceId ? { id: attached.workspaceId } : null);
1541
+ console.log(` Attached workspace: ${formatWorkspaceRef(attachedWorkspace)}`);
1542
+ }
1507
1543
  if (attached.health === 'workspace_mismatch') {
1508
1544
  printComputerCommandFailure(attached.result, ctx);
1509
1545
  } else if (attached.health !== 'ready') {
@@ -1686,7 +1722,7 @@ async function computerCreate(token, args = [], defaults = {}) {
1686
1722
  console.log(` atris computer sleep --business ${owner} --workspace ${workspaceId}`);
1687
1723
  }
1688
1724
 
1689
- async function computerActivate(token, ctx = null) {
1725
+ async function computerActivate(token, ctx = null, options = {}) {
1690
1726
  if (!ctx?.businessId || !ctx?.workspaceId) {
1691
1727
  console.error('Usage: atris computer activate --business <slug> --workspace <id>');
1692
1728
  process.exitCode = 1;
@@ -1696,7 +1732,7 @@ async function computerActivate(token, ctx = null) {
1696
1732
  const result = await apiRequestJson(`/business/${ctx.businessId}/workspaces/${ctx.workspaceId}/activate`, {
1697
1733
  method: 'POST',
1698
1734
  token,
1699
- body: {},
1735
+ body: { force: Boolean(options.force) },
1700
1736
  });
1701
1737
  if (!result.ok) {
1702
1738
  printComputerCommandFailure(result, ctx);
@@ -2581,10 +2617,10 @@ async function computerChat(token, ctx, initialOptions = {}) {
2581
2617
  }
2582
2618
 
2583
2619
  const isCodeOps = initialOptions.mode === 'codeops' || ctx.slug === 'atris-codeops';
2620
+ const oneShotMessage = initialOptions.message != null;
2584
2621
  const chatSystemPrompt = isCodeOps
2585
2622
  ? appendSystemPrompt(initialOptions.systemPrompt, CODEOPS_WORKFLOW_PROMPT)
2586
2623
  : initialOptions.systemPrompt;
2587
- const oneShotMessage = initialOptions.message != null;
2588
2624
  let sessionId = `biz-${ctx.businessId.slice(0, 8)}-${Date.now().toString(36)}`;
2589
2625
  const pipedInput = initialOptions.message != null ? null : await readPipedStdin();
2590
2626
  const scriptedInput = initialOptions.message != null ? String(initialOptions.message) : pipedInput;
@@ -3398,7 +3434,7 @@ async function runComputer() {
3398
3434
  case 'chat': return computerChat(token, ctx, cloudOptions);
3399
3435
  case 'card': return computerCard(args.slice(1));
3400
3436
  case 'proof': return computerProof(token, ctx, cloudOptions);
3401
- case 'activate': return computerActivate(token, ctx);
3437
+ case 'activate': return computerActivate(token, ctx, cloudOptions);
3402
3438
  case 'status': return computerStatus(token, ctx);
3403
3439
  case 'up':
3404
3440
  case 'wake': return computerWake(token, ctx);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "atris",
3
- "version": "3.15.49",
3
+ "version": "3.15.50",
4
4
  "main": "bin/atris.js",
5
5
  "bin": {
6
6
  "atris": "bin/atris.js",