maka-agent 0.2.0-dev.3.20260830 → 0.2.0-dev.4.20260830

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 (25) hide show
  1. package/dist/cli-core.js +1 -0
  2. package/dist/runtime-host-cli.js +37 -3
  3. package/dist/runtime-host-peer-mesh-management-command.js +17 -0
  4. package/dist/runtime-host-setup-command.js +33 -15
  5. package/dist/runtime-host-systemd-service.js +9 -3
  6. package/native/runtime-host-peer/prebuilds/darwin-arm64/maka_runtime_host_peer.node +0 -0
  7. package/native/runtime-host-peer/prebuilds/linux-arm64/maka_runtime_host_peer.node +0 -0
  8. package/native/runtime-host-peer/prebuilds/linux-x64/maka_runtime_host_peer.node +0 -0
  9. package/native/runtime-host-peer/prebuilds/win32-x64/maka_runtime_host_peer.node +0 -0
  10. package/node_modules/@maka/runtime/dist/sandbox/macos-seatbelt.js +68 -9
  11. package/node_modules/@maka/runtime-host/dist/client/peer-client.js +22 -3
  12. package/node_modules/@maka/runtime-host/dist/operator/peer-mesh-management-frame.js +14 -0
  13. package/node_modules/@maka/runtime-host/dist/peer-mesh/display-name.js +30 -0
  14. package/node_modules/@maka/runtime-host/dist/peer-mesh/model.js +32 -21
  15. package/node_modules/@maka/runtime-host/dist/peer-mesh/node.js +207 -47
  16. package/node_modules/@maka/runtime-host/dist/peer-mesh/owner.js +2 -0
  17. package/node_modules/@maka/runtime-host/dist/peer-mesh/store.js +18 -5
  18. package/node_modules/@maka/runtime-host/dist/protocol/index.js +5 -1
  19. package/node_modules/@maka/runtime-host/dist/protocol/peer-mesh.js +59 -2
  20. package/node_modules/@maka/runtime-host/dist/server/access-authority.js +11 -7
  21. package/node_modules/@maka/runtime-host/dist/server/connection-session.js +3 -0
  22. package/node_modules/@maka/runtime-host/dist/server/execution-service.js +1 -0
  23. package/node_modules/@maka/runtime-host/dist/server/host-kernel.js +1 -1
  24. package/node_modules/@maka/runtime-host/dist/server/peer-mesh-authority.js +19 -0
  25. package/package.json +1 -1
@@ -18,6 +18,7 @@
18
18
  */
19
19
  import { assertExactKeys, requireCount, requireExactRecord, requireRecord, requireString, } from './codec.js';
20
20
  import { defineOperation } from './operation-spec.js';
21
+ import { canonicalPeerMeshDisplayName } from '../peer-mesh/display-name.js';
21
22
  import { PEER_MESH_MAX_MEMBERS, PEER_MESH_MAX_MESHES, PEER_MESH_MAX_ROUTE_HINTS, } from '../peer-mesh/limits.js';
22
23
  const PEER_ID_MAX_BYTES = 256;
23
24
  const MESH_ID_MAX_BYTES = 128;
@@ -93,6 +94,20 @@ export const PEER_MESH_OPERATION_SPECS = {
93
94
  decodeInput: decodePeerMeshTransitSetInput,
94
95
  decodeOutput: decodePeerMeshQueryResult,
95
96
  }),
97
+ 'peer.mesh.display-name.set': defineOperation({
98
+ mode: 'command',
99
+ availability: 'ready',
100
+ errors: MUTATION_ERRORS,
101
+ decodeInput: decodePeerMeshDisplayNameSetInput,
102
+ decodeOutput: decodePeerMeshQueryResult,
103
+ }),
104
+ 'peer.mesh.rename': defineOperation({
105
+ mode: 'command',
106
+ availability: 'ready',
107
+ errors: MUTATION_ERRORS,
108
+ decodeInput: decodePeerMeshRenameInput,
109
+ decodeOutput: decodePeerMeshQueryResult,
110
+ }),
96
111
  };
97
112
  function decodeEmptyInput(value) {
98
113
  requireExactRecord(value, 'Peer Mesh operation input', []);
@@ -104,6 +119,19 @@ function decodePeerMeshTargetInput(value) {
104
119
  meshId: requireString(record.meshId, 'Peer Mesh meshId', MESH_ID_MAX_BYTES),
105
120
  };
106
121
  }
122
+ function decodePeerMeshDisplayNameSetInput(value) {
123
+ const record = requireExactRecord(value, 'Peer Mesh display name input', ['displayName']);
124
+ return {
125
+ displayName: record.displayName === null ? null : canonicalPeerMeshDisplayName(record.displayName),
126
+ };
127
+ }
128
+ function decodePeerMeshRenameInput(value) {
129
+ const record = requireExactRecord(value, 'Peer Mesh rename input', ['meshId', 'displayName']);
130
+ return {
131
+ meshId: requireString(record.meshId, 'Peer Mesh meshId', MESH_ID_MAX_BYTES),
132
+ displayName: record.displayName === null ? null : canonicalPeerMeshDisplayName(record.displayName),
133
+ };
134
+ }
107
135
  function decodePeerMeshInviteInput(value) {
108
136
  return decodePeerMeshTargetInput(value);
109
137
  }
@@ -171,7 +199,13 @@ export function decodePeerMeshQueryResult(value) {
171
199
  const record = requireRecord(value, 'Peer Mesh query result');
172
200
  assertExactKeys(record, 'Peer Mesh query result', record.localPeerId === undefined
173
201
  ? ['available', 'meshes']
174
- : ['available', 'localPeerId', 'meshes', 'transit']);
202
+ : [
203
+ 'available',
204
+ 'localPeerId',
205
+ ...(record.localDisplayName === undefined ? [] : ['localDisplayName']),
206
+ 'meshes',
207
+ 'transit',
208
+ ]);
175
209
  if (typeof record.available !== 'boolean' ||
176
210
  !Array.isArray(record.meshes) ||
177
211
  record.meshes.length > PEER_MESH_MAX_MESHES) {
@@ -187,14 +221,19 @@ export function decodePeerMeshQueryResult(value) {
187
221
  ? {}
188
222
  : {
189
223
  localPeerId: requireString(localPeerId, 'Peer Mesh localPeerId', PEER_ID_MAX_BYTES),
224
+ ...(record.localDisplayName === undefined
225
+ ? {}
226
+ : { localDisplayName: canonicalPeerMeshDisplayName(record.localDisplayName) }),
190
227
  transit: decodePeerMeshTransitProjection(record.transit),
191
228
  }),
192
229
  meshes: Object.freeze(record.meshes.map(decodePeerMeshProjection)),
193
230
  };
194
231
  }
195
232
  export function decodePeerMeshProjection(value) {
233
+ const valueRecord = requireRecord(value, 'Peer Mesh projection');
196
234
  const record = requireExactRecord(value, 'Peer Mesh projection', [
197
235
  'meshId',
236
+ ...(valueRecord.displayName === undefined ? [] : ['displayName']),
198
237
  'role',
199
238
  'authorityPeerId',
200
239
  'revision',
@@ -214,6 +253,9 @@ export function decodePeerMeshProjection(value) {
214
253
  }
215
254
  return {
216
255
  meshId: requireString(record.meshId, 'Peer Mesh meshId', MESH_ID_MAX_BYTES),
256
+ ...(record.displayName === undefined
257
+ ? {}
258
+ : { displayName: canonicalPeerMeshDisplayName(record.displayName) }),
217
259
  role: record.role,
218
260
  authorityPeerId: requireString(record.authorityPeerId, 'Peer Mesh authorityPeerId', PEER_ID_MAX_BYTES),
219
261
  revision: requireCount(record.revision, 'Peer Mesh revision'),
@@ -250,7 +292,13 @@ function decodePeerMeshTransitProjection(value) {
250
292
  }
251
293
  function decodePeerMeshMemberProjection(value) {
252
294
  const record = requireRecord(value, 'Peer Mesh member route');
253
- assertExactKeys(record, 'Peer Mesh member route', record.expiresAt === undefined ? ['peerId', 'state'] : ['peerId', 'state', 'expiresAt']);
295
+ assertExactKeys(record, 'Peer Mesh member route', [
296
+ 'peerId',
297
+ 'state',
298
+ ...(record.endpointKind === undefined ? [] : ['endpointKind']),
299
+ ...(record.displayName === undefined ? [] : ['displayName']),
300
+ ...(record.expiresAt === undefined ? [] : ['expiresAt']),
301
+ ]);
254
302
  if (record.state !== 'local' &&
255
303
  record.state !== 'route_available' &&
256
304
  record.state !== 'coordination_only' &&
@@ -258,8 +306,17 @@ function decodePeerMeshMemberProjection(value) {
258
306
  record.state !== 'unknown') {
259
307
  throw new Error('Invalid Peer Mesh member route state');
260
308
  }
309
+ if (record.endpointKind !== undefined &&
310
+ record.endpointKind !== 'client' &&
311
+ record.endpointKind !== 'host') {
312
+ throw new Error('Invalid Peer Mesh member endpoint kind');
313
+ }
261
314
  return {
262
315
  peerId: requireString(record.peerId, 'Peer Mesh member route peerId', PEER_ID_MAX_BYTES),
316
+ ...(record.endpointKind === undefined ? {} : { endpointKind: record.endpointKind }),
317
+ ...(record.displayName === undefined
318
+ ? {}
319
+ : { displayName: canonicalPeerMeshDisplayName(record.displayName) }),
263
320
  state: record.state,
264
321
  ...(record.expiresAt === undefined
265
322
  ? {}
@@ -78,7 +78,9 @@ class FileRuntimeHostAccessAuthority {
78
78
  credentialId: match.credentialId,
79
79
  operationGrants: match.bindClientInstanceOnFinalize
80
80
  ? ['host.status', 'access.credential.finalize']
81
- : match.operationGrants,
81
+ : match.clientInstanceId
82
+ ? [...match.operationGrants, 'access.credential.finalize']
83
+ : match.operationGrants,
82
84
  canPublishClientCapabilities: !match.bindClientInstanceOnFinalize && match.canPublishClientCapabilities,
83
85
  canUseHostPaths: !match.bindClientInstanceOnFinalize && match.canUseHostPaths,
84
86
  ...(match.clientInstanceId ? { clientInstanceId: match.clientInstanceId } : {}),
@@ -476,21 +478,23 @@ class FileRuntimeHostAccessAuthority {
476
478
  await this.#commit(createNextAccessCredentialFile(this.#file, credentials, this.#file.sessionGrants), [current, ...pendingForPrincipal].map((credential) => credential.credentialId));
477
479
  return { credentialId, revoked: true };
478
480
  }
479
- finalize(credentialId, clientInstanceId) {
481
+ finalize(credentialId, clientInstanceId, connectionAlreadyFinalized) {
480
482
  return this.#mutate(async () => {
481
483
  const retained = this.#file.credentials.find((credential) => credential.credentialId === credentialId);
482
484
  if (!retained || retained.status === 'revoked') {
483
485
  throw new RuntimeHostAccessInputError('The current access credential is no longer active');
484
486
  }
485
- return this.#finalize(retained, clientInstanceId);
487
+ return this.#finalize(retained, clientInstanceId, connectionAlreadyFinalized);
486
488
  });
487
489
  }
488
- async #finalize(retained, clientInstanceId) {
490
+ async #finalize(retained, clientInstanceId, connectionAlreadyFinalized) {
489
491
  if (retained.status === 'active') {
490
492
  if (retained.clientInstanceId && retained.clientInstanceId !== clientInstanceId) {
491
493
  throw new RuntimeHostAccessInputError('The pairing candidate was claimed by another Client');
492
494
  }
493
- return { reconnectRequired: retained.clientInstanceId !== undefined };
495
+ return {
496
+ reconnectRequired: retained.clientInstanceId !== undefined && !connectionAlreadyFinalized,
497
+ };
494
498
  }
495
499
  if (Date.parse(retained.expiresAt) <= Date.now()) {
496
500
  await this.#expirePending();
@@ -776,7 +780,7 @@ export async function revokeAccessCredentialRotation(authority, input) {
776
780
  return accessPersistenceFailure(error, 'Access credential rotation revocation outcome is unknown', 'Access credential could not be revoked');
777
781
  }
778
782
  }
779
- export async function finalizeAccessCredential(authority, credentialId, clientInstanceId) {
783
+ export async function finalizeAccessCredential(authority, credentialId, clientInstanceId, credentialClientInstanceId) {
780
784
  if (!authority)
781
785
  return unavailable('finalize');
782
786
  if (!credentialId) {
@@ -800,7 +804,7 @@ export async function finalizeAccessCredential(authority, credentialId, clientIn
800
804
  try {
801
805
  return {
802
806
  ok: true,
803
- result: await authority.finalize(credentialId, clientInstanceId),
807
+ result: await authority.finalize(credentialId, clientInstanceId, credentialClientInstanceId === clientInstanceId),
804
808
  };
805
809
  }
806
810
  catch (error) {
@@ -164,6 +164,9 @@ export class RuntimeHostConnectionSession {
164
164
  ...(this.#options.connection.authority.credentialId
165
165
  ? { credentialId: this.#options.connection.authority.credentialId }
166
166
  : {}),
167
+ ...(this.#options.connection.authority.clientInstanceId
168
+ ? { credentialClientInstanceId: this.#options.connection.authority.clientInstanceId }
169
+ : {}),
167
170
  acquireResidency: () => admission.acquireResidency(),
168
171
  });
169
172
  admission.seal();
@@ -54,6 +54,7 @@ export async function startExecutionRuntimeHostService(options, dependencies = {
54
54
  peerOwner = await openRuntimeHostPeerMeshOwner({
55
55
  ...options.peer,
56
56
  dataRoot: options.peer.meshDataRoot,
57
+ endpointKind: 'host',
57
58
  });
58
59
  }
59
60
  catch (error) {
@@ -524,7 +524,7 @@ export class RuntimeHostKernel {
524
524
  'access.principal.revoke': async (input) => this.#settleAccessCredentialMutation(revokeAccessPrincipal(this.#options.accessAuthority, input)),
525
525
  'access.credential.rotation.prepare': async (input) => this.#settleAccessCredentialMutation(prepareAccessCredentialRotation(this.#options.accessAuthority, input)),
526
526
  'access.credential.rotation.revoke': async (input) => this.#settleAccessCredentialMutation(revokeAccessCredentialRotation(this.#options.accessAuthority, input)),
527
- 'access.credential.finalize': async (_input, context) => this.#settleAccessCredentialMutation(finalizeAccessCredential(this.#options.accessAuthority, context.credentialId, context.clientInstanceId)),
527
+ 'access.credential.finalize': async (_input, context) => this.#settleAccessCredentialMutation(finalizeAccessCredential(this.#options.accessAuthority, context.credentialId, context.clientInstanceId, context.credentialClientInstanceId)),
528
528
  'collaboration.invitation.prepare': async (input) => this.#settleAccessCredentialMutation(prepareCollaborationInvitation(this.#options.accessAuthority, this.rootId, input)),
529
529
  'collaboration.access.query': async (input) => this.#options.accessAuthority
530
530
  ? {
@@ -128,11 +128,28 @@ export function createPeerMeshOperationHandlers(mesh, options = {}) {
128
128
  return { ok: true, result: query() };
129
129
  });
130
130
  },
131
+ 'peer.mesh.display-name.set': async (input) => {
132
+ if (!mesh)
133
+ return unavailable();
134
+ return mutate(async () => {
135
+ await mesh.setDisplayName(input.displayName);
136
+ return { ok: true, result: query() };
137
+ });
138
+ },
139
+ 'peer.mesh.rename': async (input) => {
140
+ if (!mesh)
141
+ return unavailable();
142
+ return mutate(async () => {
143
+ await mesh.setMeshDisplayName(input.meshId, input.displayName);
144
+ return { ok: true, result: query() };
145
+ });
146
+ },
131
147
  };
132
148
  }
133
149
  export function projectPeerMeshStatus(status) {
134
150
  return Object.freeze({
135
151
  meshId: status.roster.roster.meshId,
152
+ ...(status.roster.roster.displayName ? { displayName: status.roster.roster.displayName } : {}),
136
153
  role: status.role,
137
154
  authorityPeerId: status.authority.peerId,
138
155
  revision: status.roster.roster.revision,
@@ -144,9 +161,11 @@ export function projectPeerMeshStatus(status) {
144
161
  export function projectPeerMeshQuery(mesh) {
145
162
  if (!mesh)
146
163
  return { available: false, meshes: [] };
164
+ const displayName = mesh.displayName();
147
165
  return Object.freeze({
148
166
  available: true,
149
167
  localPeerId: mesh.localPeerId(),
168
+ ...(displayName ? { localDisplayName: displayName } : {}),
150
169
  meshes: Object.freeze(mesh.status().map(projectPeerMeshStatus)),
151
170
  transit: projectTransitSnapshot(mesh.transitMeshId(), mesh.transitSnapshot()),
152
171
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maka-agent",
3
- "version": "0.2.0-dev.3.20260830",
3
+ "version": "0.2.0-dev.4.20260830",
4
4
  "description": "Apache Maka (Incubating) developer snapshot; not an Apache release.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",