@commonlyai/cli 0.1.172 → 0.1.173

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.
package/README.md CHANGED
@@ -33,11 +33,21 @@ Keep active-instance precedence separate from the newest-match fallback; back-to
33
33
  A hosted agent's local handoff card includes `--memory-from <hosted-agent>` and
34
34
  `--memory-instance <hosted-instance>` on the attach command. After login, attach
35
35
  copies that source's long-term memory into the local identity before returning
36
- its runnable configuration. Both identities must be accessible through the
37
- logged-in account's owner memory API. No hosted runtime credential is moved.
36
+ its runnable configuration. The source and target must belong to the logged-in
37
+ owner. No hosted runtime credential is moved.
38
38
 
39
39
  This is a snapshot, not a shared identity or continuing synchronization. Attach
40
40
  refuses to replace different existing local memory or copy into a non-private
41
- long-term section. A failed copy stops attach; correct the error and retry before
42
- running the local agent. A retry resumes only your matching active local installation,
41
+ long-term section. The install request completes memory authorization and the
42
+ revision-checked copy before joining the pod, creating an installation or posting
43
+ a greeting. A refused copy leaves those effects absent (an existing installation
44
+ is preserved). A later identity-creation or pod-join refusal can leave the copied
45
+ memory without an installation; retries recognize the snapshot as already copied.
46
+ The server claims the registry name before copying. On copy failure it releases
47
+ only the new, unchanged claim when no installation uses it; a claim touched by
48
+ another in-flight handoff is retained. Memory is not rolled back across later
49
+ identity or pod-join operations. Correct the error and
50
+ retry before running the local agent.
51
+ The CLI checks server support before publishing or installing; deploy the backend
52
+ with install-time handoff support before distributing the updated CLI. A retry resumes only your matching active local installation,
43
53
  without changing its configuration or scopes. Repeating a copy with identical memory is safe.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commonlyai/cli",
3
- "version": "0.1.172",
3
+ "version": "0.1.173",
4
4
  "license": "Apache-2.0",
5
5
  "description": "The Commonly CLI — connect agents, manage pods, iterate fast",
6
6
  "type": "module",
@@ -22,7 +22,6 @@ import { createHash } from 'crypto';
22
22
 
23
23
  import { requireSeatModel } from '../lib/adapters/seat-model.js';
24
24
  import { createClient } from '../lib/api.js';
25
- import { copyHandoffMemory } from '../lib/handoff-memory.js';
26
25
  import {
27
26
  buildSpawnId,
28
27
  createSpawnCredentialLease,
@@ -987,6 +986,13 @@ export const performAttach = async ({
987
986
  // server via legacy normalization).
988
987
  const runtimeType = adapter.runtimeType || adapter.name;
989
988
 
989
+ if (memoryFrom) {
990
+ const capability = await client.get('/api/registry/install/memory-handoff');
991
+ if (capability?.installTimeMemoryHandoff !== true) {
992
+ throw new Error('Server does not support install-time memory handoff; upgrade the server before attaching');
993
+ }
994
+ }
995
+
990
996
  // Idempotent publish — already-published is expected and fine. Install will
991
997
  // surface the real error if the manifest is truly unusable.
992
998
  try {
@@ -1010,7 +1016,9 @@ export const performAttach = async ({
1010
1016
  // on config.environment so cross-driver implementations can realize it
1011
1017
  // server-side without re-reading the user's file.
1012
1018
  const installResult = await client.post('/api/registry/install', {
1013
- ...(memoryFrom ? { resumeExisting: true } : {}),
1019
+ ...(memoryFrom ? {
1020
+ resumeExisting: true, memoryFrom: { agentName: memoryFrom, instanceId: memoryInstance },
1021
+ } : {}),
1014
1022
  agentName,
1015
1023
  podId,
1016
1024
  displayName: displayName || agentName,
@@ -1034,10 +1042,8 @@ export const performAttach = async ({
1034
1042
  const instanceId = installation.instanceId || 'default';
1035
1043
 
1036
1044
  if (memoryFrom) {
1037
- const memoryCopy = await copyHandoffMemory(client, {
1038
- sourceAgentName: memoryFrom, sourceInstanceId: memoryInstance,
1039
- targetAgentName: installation.agentName, targetInstanceId: instanceId,
1040
- });
1045
+ const memoryCopy = installResult.memoryCopy;
1046
+ if (!memoryCopy) throw new Error('Server does not support install-time memory handoff; upgrade the server before attaching');
1041
1047
  log(memoryCopy.reason === 'source-empty'
1042
1048
  ? 'hosted agent has no long-term memory to copy'
1043
1049
  : 'hosted long-term memory is present in the local agent');
@@ -1,23 +0,0 @@
1
- /** Copy only long-term memory using the logged-in owner's revision-checked API. */
2
- export const copyHandoffMemory = async (client, {
3
- sourceAgentName, sourceInstanceId = 'default', targetAgentName, targetInstanceId = 'default',
4
- }) => {
5
- const endpoint = (name, instance) => `/api/agent-memory/${encodeURIComponent(name)}/${encodeURIComponent(instance)}/editable`;
6
- const source = await client.get(endpoint(sourceAgentName, sourceInstanceId));
7
- const content = source?.sections?.long_term?.content;
8
- if (typeof content !== 'string') throw new Error('Hosted memory response is missing long_term content');
9
- if (!content) return { copied: false, reason: 'source-empty' };
10
- const targetPath = endpoint(targetAgentName, targetInstanceId);
11
- const target = await client.get(targetPath);
12
- const prior = target?.sections?.long_term;
13
- if (typeof prior?.content !== 'string') throw new Error('Local memory response is missing long_term content');
14
- if (prior.visibility !== 'private') throw new Error('Local long-term memory must be private before copying hosted memory');
15
- if (prior.content === content) return { copied: false, reason: 'already-copied' };
16
- if (prior.content) throw new Error('Local agent already has different memory; choose a new local name');
17
- // A concurrent first write wins rather than being overwritten by this copy.
18
- await client.patch(`${targetPath}/long_term`, {
19
- copyFrom: { agentName: sourceAgentName, instanceId: sourceInstanceId },
20
- expectedUpdatedAt: prior.updatedAt ?? null,
21
- });
22
- return { copied: true };
23
- };