@proagentstore/cli 0.4.64 → 0.4.66

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.
@@ -428,7 +428,26 @@ export class HeadlessSession {
428
428
  }
429
429
  });
430
430
  }
431
- /** Send a user turn. `author` names who wrote it, because `role` cannot — see turn-author.ts (#505). */
431
+ /**
432
+ * Does the engine carry its own conversation into THIS turn (#693 slice 2)?
433
+ *
434
+ * The boundary ADR 0005 draws, stated where the runner applies it: the platform's record is the
435
+ * source of truth and the engine's own memory is an optimisation preferred when it is there. It is
436
+ * there for a PERSISTENT process (Claude's stream-json session, a persistent REPL), which holds
437
+ * every turn since it started, and for a structured Codex turn that will resume its explicit
438
+ * thread (#848). A one-shot raw process has nothing: each turn is a new process.
439
+ */
440
+ get holdsConversationThisTurn() {
441
+ return this.adapter.persistent || this.codexResumeThreadId !== null;
442
+ }
443
+ /**
444
+ * Send a user turn. `author` names who wrote it, because `role` cannot — see turn-author.ts (#505).
445
+ *
446
+ * `replay` is the cloud's per-turn composition of the platform's record (#693 slice 2). It is spent
447
+ * only when {@link holdsConversationThisTurn} is false, so an engine with its own memory is never
448
+ * handed a summary of the conversation it is already in; when spent it replaces the one-shot
449
+ * session-start brief, being the same record composed later.
450
+ */
432
451
  input(text, opts = {}) {
433
452
  // The Engine reads the preamble, the pane the short marker; the instruction stays evidence.
434
453
  const sent = authoredTurn(text, opts.author);
@@ -437,11 +456,14 @@ export class HeadlessSession {
437
456
  // Pilot re-read through `/coding/capture` and twelve thousand characters of reconstructed
438
457
  // history would evict the live output they are looking at — the same budget argument
439
458
  // `turn-author.ts` makes for its two-word marker.
440
- const seed = this.pendingSeed;
459
+ const replay = this.holdsConversationThisTurn ? null : opts.replay?.trim() || null;
460
+ const seed = replay ?? this.pendingSeed;
441
461
  this.pendingSeed = null;
442
462
  if (!this.alive)
443
463
  this.start();
444
- if (seed)
464
+ if (replay)
465
+ this.push("[pags] this engine keeps no memory between turns, so ProAgentStore's record of the conversation so far was delivered with this turn — a reconstruction, not the engine's own memory");
466
+ else if (seed)
445
467
  this.push("[pags] a context brief from ProAgentStore's record was delivered with this turn — a reconstruction, not the previous conversation");
446
468
  this.push(`\n❯ [${stamp()}] ${authorTag(opts.author)}${text}`); // ❯ — your turn, timestamped
447
469
  this.run = "thinking";
@@ -216,7 +216,7 @@ export class CodingRuntime {
216
216
  case "message":
217
217
  // Narrowed rather than trusted: this runner is a published package any caller can
218
218
  // POST to, and an unrecognised author must read as "unstated", not become a label.
219
- session.input(action.text, { author: asTurnAuthor(action.author) });
219
+ session.input(action.text, { author: asTurnAuthor(action.author), replay: typeof action.replay === "string" ? action.replay : undefined });
220
220
  break;
221
221
  case "keys": {
222
222
  // A snapshot is no longer the whole answer (#448). `key()` records the attempt and
package/dist/index.js CHANGED
@@ -1298,6 +1298,13 @@ function partitionByPin(instances, thisNode, alsoKnownAs = []) {
1298
1298
  for (const inst of instances) (isEligible(inst, thisNode, alsoKnownAs) ? here : elsewhere).push(inst);
1299
1299
  return { here, elsewhere };
1300
1300
  }
1301
+ function pinnedAway(held, instances, thisNode, alsoKnownAs = []) {
1302
+ const pins = new Map(instances.map((i) => [i.id, i.config?.runnerNode]));
1303
+ return [...held].filter((id) => {
1304
+ const pin = pins.get(id);
1305
+ return !!pin && pin !== thisNode && !alsoKnownAs.includes(pin);
1306
+ });
1307
+ }
1301
1308
  function registrationStatus(attached, registered) {
1302
1309
  const ids = [...attached];
1303
1310
  const have = ids.filter((id) => registered.has(id)).length;
@@ -1311,6 +1318,7 @@ function instanceLabel(inst) {
1311
1318
  function reattachPlan(request, state) {
1312
1319
  const target = typeof request?.attach === "string" && request.attach ? request.attach : null;
1313
1320
  const force = target !== null && request?.force === true;
1321
+ if (!state.watching && !target) return { target, unblock: false, detach: false, force: false, release: true };
1314
1322
  if (!state.watching && !(target && state.scope.includes(target))) {
1315
1323
  return {
1316
1324
  target,
@@ -1459,6 +1467,13 @@ async function connectViaRelay(instanceIds, localUrl, runnerToken, opts, force =
1459
1467
  const named = typeof request?.attach === "string" ? request.attach : "";
1460
1468
  const plan = reattachPlan(request, { held: attached.has(named), blocked: blocked.has(named), watching: watchInstances, scope: instanceIds });
1461
1469
  if (plan.refuse) return { status: 409, result: { error: plan.refuse } };
1470
+ if (plan.release) {
1471
+ const res = await requestPags("GET", "/v1/instances/my/instances", { ...opts, pagsToken });
1472
+ const released = pinnedAway(attached.keys(), res.instances ?? [], runnerNode, machine.names);
1473
+ for (const id of released) detach(id, `${id.slice(0, 8)}\u2026 (pinned to another machine now)`);
1474
+ if (released.length && attached.size === 0) writeLine("This `pags up --instance` holds no agent now \u2014 close it, or restart it without --instance.");
1475
+ return { status: 200, result: { attached: [...attached.keys()], released } };
1476
+ }
1462
1477
  if (plan.target) {
1463
1478
  if (plan.unblock) blocked.delete(plan.target);
1464
1479
  if (plan.detach) detach(plan.target);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@proagentstore/cli",
3
- "version": "0.4.64",
3
+ "version": "0.4.66",
4
4
  "description": "CLI for creating, publishing, and running ProAgentStore agents",
5
5
  "license": "MIT",
6
6
  "type": "module",