@biznetgio/neo-app 0.4.46 → 0.4.48

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/package.json +1 -1
  2. package/src/mcp/tools.js +13 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@biznetgio/neo-app",
3
- "version": "0.4.46",
3
+ "version": "0.4.48",
4
4
  "description": "NEO App CLI — one-command agent onboarding, MCP server, and project ops for coding agents (Codex, Claude Code).",
5
5
  "type": "module",
6
6
  "bin": {
package/src/mcp/tools.js CHANGED
@@ -1293,7 +1293,9 @@ export const TOOLS = [
1293
1293
  required: ['planId', 'planHash', 'confirmationId'],
1294
1294
  },
1295
1295
  async call(api, args) {
1296
- const { status, data } = await api.post(`/api/v1/plans/${args.planId}/apply`, { planHash: args.planHash, confirmationId: args.confirmationId, idempotencyKey: args.idempotencyKey });
1296
+ // Always send an idempotency key (reuse the same one on a retry to dedup/resume).
1297
+ const idempotencyKey = args.idempotencyKey || `idem-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
1298
+ const { status, data } = await api.post(`/api/v1/plans/${args.planId}/apply`, { planHash: args.planHash, confirmationId: args.confirmationId, idempotencyKey });
1297
1299
  return redactSecrets(result(status, data));
1298
1300
  },
1299
1301
  },
@@ -1406,23 +1408,29 @@ export const TOOLS = [
1406
1408
  },
1407
1409
  {
1408
1410
  name: 'neo_wait_operation',
1409
- description: 'Wait for a stack apply (operationId from neo_apply_stack) to finish — polls until the status is terminal (applied | partial | failed) or the timeout elapses, then returns the final operation with per-resource status (secrets redacted). Convenience over polling neo_get_operation yourself.',
1411
+ description: 'Wait for an operation — a stack apply (neo_apply_stack) OR a project deletion (neo_apply_project_deletion) — to finish: polls until the status is terminal (applied | partial | failed) or the timeout elapses, then returns the final operation with per-resource status (secrets redacted). Pass afterRevision to also return as soon as the operation advances past a revision you already saw (resume observation after a disconnect). Convenience over polling neo_get_operation yourself.',
1410
1412
  mutating: false,
1411
1413
  schema: {
1412
1414
  type: 'object',
1413
- properties: { operationId: str('Operation id (= plan id)'), timeoutMs: int('Max wait in milliseconds (default 180000)') },
1415
+ properties: {
1416
+ operationId: str('Operation id (= plan id)'),
1417
+ timeoutMs: int('Max wait in milliseconds (default 180000)'),
1418
+ afterRevision: int('Return as soon as the operation revision exceeds this (resume observation); omit to wait for a terminal status'),
1419
+ },
1414
1420
  required: ['operationId'],
1415
1421
  },
1416
1422
  async call(api, args) {
1417
1423
  const deadline = Date.now() + (args.timeoutMs && args.timeoutMs > 0 ? args.timeoutMs : 180000);
1418
1424
  const terminal = new Set(['applied', 'partial', 'failed']);
1425
+ const after = Number.isInteger(args.afterRevision) ? args.afterRevision : undefined;
1419
1426
  let op;
1420
1427
  for (;;) {
1421
1428
  op = redactSecrets((await api.get(`/api/v1/plans/${args.operationId}`)).data);
1422
- if (terminal.has(op.status) || Date.now() >= deadline) break;
1429
+ const advanced = after !== undefined && typeof op.revision === 'number' && op.revision > after;
1430
+ if (terminal.has(op.status) || advanced || Date.now() >= deadline) break;
1423
1431
  await new Promise((r) => setTimeout(r, 5000));
1424
1432
  }
1425
- if (op && !terminal.has(op.status)) return { ...op, timedOut: true, note: 'still in progress at timeout — call neo_get_operation again' };
1433
+ if (op && !terminal.has(op.status) && Date.now() >= deadline) return { ...op, timedOut: true, note: 'still in progress at timeout — call neo_get_operation again' };
1426
1434
  return op;
1427
1435
  },
1428
1436
  },