maka-agent 0.2.0-dev.40.20260917 → 0.2.0-dev.41.20260918

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.
@@ -1386,17 +1386,12 @@ class RuntimeHostMakaSessionDriverImpl {
1386
1386
  async #stopUserCommand(ref, owner) {
1387
1387
  if (this.#activeUserCommands.get(ref) !== owner)
1388
1388
  return;
1389
- const stopped = await this.#request('runtime.resource.stop', {
1389
+ await this.#request('runtime.resource.stop', {
1390
1390
  sessionId: owner.sessionId,
1391
1391
  ref,
1392
1392
  });
1393
- this.#publishShellRunUpdate({
1394
- sessionId: owner.sessionId,
1395
- ownership: { kind: 'local' },
1396
- sourceTurnId: owner.commandId,
1397
- sourceToolCallId: owner.commandId,
1398
- result: stopped.resource,
1399
- });
1393
+ this.#activeUserCommands.delete(ref);
1394
+ this.#publishRuntimeResource(owner.sessionId, ref);
1400
1395
  }
1401
1396
  #publishShellRunUpdate(update) {
1402
1397
  const owner = this.#activeUserCommands.get(update.result.ref);
@@ -75,6 +75,17 @@ export function isTerminalShellRunStatus(value) {
75
75
  export function isActiveShellRunStatus(value) {
76
76
  return SHELL_RUN_ACTIVE_STATUSES.includes(value);
77
77
  }
78
+ /** Desktop interactive-terminal launch identity, persisted as the run's source ids. */
79
+ export const DESKTOP_TERMINAL_LAUNCH_PREFIX = 'desktop-terminal-';
80
+ /**
81
+ * A Desktop-owned interactive terminal carries no transcript tool call, so
82
+ * nothing consumes the output on its update and wire projections.
83
+ */
84
+ export function isDesktopTerminalShellRun(source) {
85
+ return (source.mode === 'pty' &&
86
+ source.sourceTurnId === source.sourceToolCallId &&
87
+ source.sourceTurnId.startsWith(DESKTOP_TERMINAL_LAUNCH_PREFIX));
88
+ }
78
89
  export function isValidShellRunStatusTransition(current, next) {
79
90
  if (current === next)
80
91
  return true;
@@ -66,6 +66,9 @@ export class PtyScreenCollector {
66
66
  this.installProtocolBoundary();
67
67
  this.lastGood = blankPtyOutput(cols, rows);
68
68
  }
69
+ get available() {
70
+ return !this.failure && !this.disposed;
71
+ }
69
72
  accept(data) {
70
73
  if (!data)
71
74
  return;
@@ -75,23 +78,46 @@ export class PtyScreenCollector {
75
78
  }
76
79
  const generation = ++this.admittedGeneration;
77
80
  const bytes = Buffer.byteLength(data, 'utf8');
78
- const entry = { data, bytes, dropped: false };
81
+ // node-pty delivers many tiny events per tick; each queued parse is paced
82
+ // by the headless terminal's write scheduler, so queue depth — not byte
83
+ // volume — is what stalls cut-bound operations. Merge unstarted data into
84
+ // the tail entry: byte order is preserved and protocol replies already
85
+ // batch per write call.
86
+ const tail = this.pending.at(-1);
87
+ if (tail &&
88
+ !tail.dropped &&
89
+ !tail.started &&
90
+ tail.bytes + bytes <= PTY_PARSER_HIGH_WATER_BYTES) {
91
+ tail.data += data;
92
+ tail.bytes += bytes;
93
+ tail.generation = generation;
94
+ }
95
+ else {
96
+ this.enqueue({ data, bytes, generation, dropped: false, started: false });
97
+ }
79
98
  this.pendingBytes += bytes;
80
- this.pending.push(entry);
81
99
  this.evictOldestIfOverBudget();
82
100
  this.options.onDirty(generation);
83
- const parse = this.sequence.then(() => (entry.dropped ? undefined : this.write(entry.data)));
101
+ }
102
+ enqueue(entry) {
103
+ this.pending.push(entry);
104
+ const parse = this.sequence.then(() => {
105
+ if (entry.dropped)
106
+ return undefined;
107
+ entry.started = true;
108
+ return this.write(entry.data);
109
+ });
84
110
  this.sequence = parse.then(() => {
85
111
  if (entry.dropped)
86
112
  return;
87
- this.parsedGeneration = generation;
88
- this.pendingBytes -= bytes;
113
+ this.parsedGeneration = entry.generation;
114
+ this.pendingBytes -= entry.bytes;
89
115
  const index = this.pending.indexOf(entry);
90
116
  if (index >= 0)
91
117
  this.pending.splice(index, 1);
92
118
  }, (error) => {
93
119
  if (!entry.dropped)
94
- this.pendingBytes -= bytes;
120
+ this.pendingBytes -= entry.bytes;
95
121
  this.fail(asError(error, 'PTY parser failed'));
96
122
  });
97
123
  }
@@ -241,7 +241,7 @@ export class ShellRunProcessManager {
241
241
  let resizeChanged = false;
242
242
  let operationFailed = false;
243
243
  let exitBeforeControlCut = false;
244
- const controlCut = live.collector.mutateAndSnapshotAtCut(() => {
244
+ const mutation = () => {
245
245
  if (input.abortSignal?.aborted) {
246
246
  throw abortError('WriteStdin aborted before the control operation was committed');
247
247
  }
@@ -287,8 +287,18 @@ export class ShellRunProcessManager {
287
287
  this.handleIntegrityFailure(live, asError(error, 'PTY input write failed'));
288
288
  }
289
289
  }
290
- });
291
- const persistedControl = this.persistObservation(live, controlCut.then((snapshot) => (operationFailed || exitBeforeControlCut ? undefined : snapshot), () => undefined));
290
+ };
291
+ // Client control replies carry no output, so the keystroke path only needs
292
+ // the ordered mutation, not the snapshot + persist. The record still
293
+ // refreshes through output-driven flushes; a resize changes the screen
294
+ // without output, so that one is persisted eagerly.
295
+ const clientControl = input.caller === 'client';
296
+ const controlCut = clientControl
297
+ ? live.collector.mutateAtCut(mutation).then(() => undefined)
298
+ : live.collector.mutateAndSnapshotAtCut(mutation);
299
+ const persistedControl = clientControl
300
+ ? undefined
301
+ : this.persistObservation(live, controlCut.then((snapshot) => (operationFailed || exitBeforeControlCut ? undefined : snapshot), () => undefined));
292
302
  try {
293
303
  await controlCut;
294
304
  }
@@ -312,20 +322,27 @@ export class ShellRunProcessManager {
312
322
  return shellRunContent(record, operation);
313
323
  }
314
324
  let record;
315
- try {
316
- record = await persistedControl;
317
- }
318
- catch (error) {
319
- if (live.integrityFailure && !live.persistFailure) {
320
- record = await this.markObserved(await live.finished.join());
321
- return shellRunContent(record, ptyControlOperation(input, {
322
- inputQueued,
323
- resizeApplied,
324
- resizeChanged,
325
- failed: true,
326
- }));
325
+ if (persistedControl) {
326
+ try {
327
+ record = await persistedControl;
327
328
  }
328
- throw error;
329
+ catch (error) {
330
+ if (live.integrityFailure && !live.persistFailure) {
331
+ record = await this.markObserved(await live.finished.join());
332
+ return shellRunContent(record, ptyControlOperation(input, {
333
+ inputQueued,
334
+ resizeApplied,
335
+ resizeChanged,
336
+ failed: true,
337
+ }));
338
+ }
339
+ throw error;
340
+ }
341
+ }
342
+ else {
343
+ record = live.record;
344
+ if (resizeChanged)
345
+ void this.persistObservation(live).catch(() => undefined);
329
346
  }
330
347
  if (live.integrityFailure && !live.persistFailure) {
331
348
  record = await this.markObserved(await live.finished.join());
@@ -336,7 +353,6 @@ export class ShellRunProcessManager {
336
353
  failed: true,
337
354
  }));
338
355
  }
339
- // persistObservation decides whether to join finalization at call time.
340
356
  // A real PTY can exit while that persist is still in flight, leaving a
341
357
  // running snapshot here even though finalizeOnce has already started.
342
358
  if (live.driverExit || live.finalizeOnce) {
@@ -345,7 +361,7 @@ export class ShellRunProcessManager {
345
361
  }
346
362
  if (isTerminalShellRunStatus(record.status))
347
363
  record = await this.markObserved(record);
348
- return shellRunContent(record, operation);
364
+ return clientControl ? compactShellRunContent(record) : shellRunContent(record, operation);
349
365
  }
350
366
  async readRuntimeResource(sessionId, ref, abortSignal) {
351
367
  return this.resourceDetail(sessionId, ref, true, abortSignal, true);
@@ -428,11 +444,21 @@ export class ShellRunProcessManager {
428
444
  const live = this.live.get(target.shellRunId);
429
445
  if (!live || live.sessionId !== sessionId || live.mode !== 'pty')
430
446
  return null;
447
+ // The collector dies before the process exit lands: an integrity failure or
448
+ // startup cleanup leaves it throwing while `live` still looks attachable.
449
+ // Report the resource as gone so the caller repairs the stale record.
450
+ if (live.driverExit || live.finalizeOnce || live.integrityFailure)
451
+ return null;
452
+ if (!live.collector.available)
453
+ return null;
454
+ // Flush pending bytes first so the snapshot sequence always names the last
455
+ // published event the buffer already contains.
456
+ this.publishPtyData(live);
431
457
  return {
432
458
  sessionId,
433
459
  ref,
434
460
  sequence: live.rawSequence,
435
- buffer: live.rawBuffer,
461
+ buffer: live.rawBuffer.slice(-PTY_RAW_REPLAY_CHARS),
436
462
  size: live.collector.currentSize(),
437
463
  };
438
464
  }
@@ -762,14 +788,18 @@ export class ShellRunProcessManager {
762
788
  onPtyData(live, data) {
763
789
  if (live.driverExit || live.finalizeOnce)
764
790
  return;
765
- live.rawBuffer = `${live.rawBuffer}${data}`.slice(-PTY_RAW_REPLAY_CHARS);
791
+ // Amortize the tail trim: slicing on every tiny node-pty event copies the
792
+ // whole 16K replay buffer per event.
793
+ live.rawBuffer += data;
794
+ if (live.rawBuffer.length > PTY_RAW_REPLAY_CHARS * 2) {
795
+ live.rawBuffer = live.rawBuffer.slice(-PTY_RAW_REPLAY_CHARS);
796
+ }
766
797
  live.collector.accept(data);
767
798
  for (const chunk of splitPtyData(data)) {
768
799
  const combined = `${live.pendingRawData}${chunk}`;
769
800
  if (live.pendingRawData && encodedPtyDataBytes(combined) > PTY_RAW_PUBLISH_MAX_BYTES) {
770
801
  this.publishPtyData(live);
771
802
  }
772
- live.rawSequence += 1;
773
803
  live.pendingRawData += chunk;
774
804
  if (encodedPtyDataBytes(live.pendingRawData) >= PTY_RAW_PUBLISH_TARGET_BYTES) {
775
805
  this.publishPtyData(live);
@@ -791,6 +821,7 @@ export class ShellRunProcessManager {
791
821
  if (!data)
792
822
  return;
793
823
  live.pendingRawData = '';
824
+ live.rawSequence += 1;
794
825
  const event = {
795
826
  sessionId: live.sessionId,
796
827
  ref: shellRunResourceRef(live.shellRunId),
@@ -17,7 +17,7 @@
17
17
  * under the License.
18
18
  */
19
19
  import { encodedTerminalInputActionsByteLength } from '@maka/core/terminal-input';
20
- import { isActiveShellRunStatus } from '@maka/core/shell-run';
20
+ import { isActiveShellRunStatus, isDesktopTerminalShellRun } from '@maka/core/shell-run';
21
21
  import { shellRunResourceRef } from './shell-run-contract.js';
22
22
  import { truncateToolOutput } from './tool-output.js';
23
23
  import { isLikelySandboxDenial } from './sandbox/detect.js';
@@ -29,7 +29,9 @@ export function shellRunUpdate(record) {
29
29
  ownership: { kind: 'local' },
30
30
  sourceTurnId: record.sourceTurnId,
31
31
  sourceToolCallId: record.sourceToolCallId,
32
- result: shellRunSnapshotContent(record),
32
+ result: isDesktopTerminalShellRun({ ...record, mode: record.output.mode })
33
+ ? shellRunStateContent(record)
34
+ : shellRunSnapshotContent(record),
33
35
  };
34
36
  }
35
37
  export function terminalContent(record) {
@@ -62,7 +62,9 @@ export const RUNTIME_HOST_REGISTRATION_SCHEMA_VERSION = 1;
62
62
  export const RUNTIME_HOST_PROTOCOL_VERSION = 0;
63
63
  // Increment when the same protocol version no longer guarantees safe Client-Host
64
64
  // interoperability. Mismatches are rejected before domain commands are admitted.
65
- export const RUNTIME_HOST_COMPATIBILITY_EPOCH = 161;
65
+ export const RUNTIME_HOST_COMPATIBILITY_EPOCH = 162;
66
+ // 162: Runtime Resource control and stop replies drop the unused resource
67
+ // snapshot; start replies allow compact state. Older peers require snapshots.
66
68
  // 161: Session transcript reads return the whole transcript under a byte budget,
67
69
  // and every page says whether it stops between two Turns. The windowed read's
68
70
  // range edges are gone, and the Turn landmark query takes a Turn to look up, so
@@ -111,7 +111,7 @@ export function decodeRuntimeResourceStartInput(value) {
111
111
  }
112
112
  export function decodeRuntimeResourceStartResult(value) {
113
113
  const result = requireExactRecord(value, 'Runtime Resource start result', ['resource']);
114
- const decoded = { resource: decodeRuntimeResourceSnapshot(result.resource) };
114
+ const decoded = { resource: decodeRuntimeResourceState(result.resource) };
115
115
  requireEncodedByteLimit(decoded, 'Runtime Resource start result', RUNTIME_RESOURCE_RESULT_MAX_BYTES);
116
116
  return decoded;
117
117
  }
@@ -268,15 +268,11 @@ export function decodeRuntimeResourceControllerControlResult(value) {
268
268
  const result = requireExactRecord(value, 'Runtime Resource controller control result', [
269
269
  'controllerId',
270
270
  'sequence',
271
- 'resource',
272
271
  ]);
273
- const decoded = {
272
+ return {
274
273
  controllerId: requireEntityId(result.controllerId, 'controllerId'),
275
274
  sequence: controlSequence(result.sequence, 'controller sequence'),
276
- resource: decodeRuntimeResourceSnapshot(result.resource),
277
275
  };
278
- requireEncodedByteLimit(decoded, 'Runtime Resource controller control result', RUNTIME_RESOURCE_RESULT_MAX_BYTES);
279
- return decoded;
280
276
  }
281
277
  export function decodeRuntimeResourceControllerReleaseInput(value) {
282
278
  return decodeControllerIdentity(value, 'Runtime Resource controller release input');
@@ -302,10 +298,8 @@ export function decodeRuntimeResourceStopInput(value) {
302
298
  };
303
299
  }
304
300
  export function decodeRuntimeResourceStopResult(value) {
305
- const result = requireExactRecord(value, 'Runtime Resource stop result', ['resource']);
306
- const decoded = { resource: decodeRuntimeResourceSnapshot(result.resource) };
307
- requireEncodedByteLimit(decoded, 'Runtime Resource stop result', RUNTIME_RESOURCE_RESULT_MAX_BYTES);
308
- return decoded;
301
+ requireExactRecord(value, 'Runtime Resource stop result', []);
302
+ return {};
309
303
  }
310
304
  export function decodeRuntimeResourceUpdate(value) {
311
305
  const update = requireExactRecord(value, 'Runtime Resource update', [
@@ -332,13 +326,6 @@ export function decodeRuntimeResourceState(value) {
332
326
  }
333
327
  return decoded.content;
334
328
  }
335
- export function decodeRuntimeResourceSnapshot(value) {
336
- const decoded = decodeRuntimeResourceState(value);
337
- if (decoded.output === undefined) {
338
- throw invalidProtocolFrame('Invalid Runtime Resource snapshot');
339
- }
340
- return decoded;
341
- }
342
329
  function decodeControllerIdentity(value, label) {
343
330
  const input = requireExactRecord(value, label, ['sessionId', 'ref', 'controllerId']);
344
331
  return {
@@ -18,6 +18,7 @@
18
18
  */
19
19
  import { JsonArrayPageBudget } from './json-array-page-budget.js';
20
20
  import { ExternalSessionCatalogCursorError, ExternalSessionLimitError, ExternalSessionNotFoundError, } from '@maka/core/external-session';
21
+ import { redactSecrets } from '@maka/core/redaction';
21
22
  import { ExternalSessionImporter } from '@maka/storage/external-sessions';
22
23
  import { EXTERNAL_SESSION_CWD_MAX_BYTES, EXTERNAL_SESSION_IMPORTED_SESSION_IDS_MAX_ITEMS, EXTERNAL_SESSION_NAME_MAX_BYTES, EXTERNAL_SESSION_PAGE_MAX_ITEMS, EXTERNAL_SESSION_RESULT_MAX_BYTES, EXTERNAL_SESSION_SOURCE_MAX_ITEMS, EXTERNAL_SESSION_SOURCE_SESSION_ID_MAX_BYTES, } from '../protocol/index.js';
23
24
  import { projectSessionCatalogRecord, SessionOperationFailure, NoUsableImportModelError, } from './session-catalog-coordinator.js';
@@ -70,7 +71,14 @@ export class HostExternalSessionCoordinator {
70
71
  const headers = await this.#sessions.listHeaders();
71
72
  for (const header of headers) {
72
73
  if (header.transcriptLedgerVersion === 0) {
73
- await this.#prepareStagedSession(header.id);
74
+ try {
75
+ await this.#prepareStagedSession(header.id);
76
+ }
77
+ catch (error) {
78
+ // One staged Session can remain unpublished for a later recovery
79
+ // attempt without preventing unrelated Sessions or Host startup.
80
+ console.error(`[runtime-host] staged import recovery deferred (${header.id}): ${redactSecrets(error instanceof Error ? error.message : String(error))}`);
81
+ }
74
82
  }
75
83
  }
76
84
  }
@@ -19,12 +19,13 @@
19
19
  import { createHash } from 'node:crypto';
20
20
  import { userInfo } from 'node:os';
21
21
  import { isActiveShellRunStatus } from '@maka/core/shell-run';
22
+ import { shellRunStateProjection } from '@maka/core/shell-run-result';
22
23
  import { ShellRunPtyControlClosedError, isShellRunResourceRef, } from '@maka/runtime/shell-run-contract';
23
24
  import { defaultShellPlan, ShellPreferenceError } from '@maka/runtime/shell-detect';
24
25
  import { isSessionNotFoundError } from '@maka/storage/execution-stores';
25
26
  import { decodeRuntimeResourceControllerAcquireResult, decodeRuntimeResourceControllerControlResult, decodeRuntimeResourceQueryResult, decodeRuntimeResourceStopResult, decodeRuntimeResourceStartResult, RUNTIME_RESOURCE_CONTROLLER_ACQUIRE_RESULT_MAX_BYTES, RUNTIME_RESOURCE_MAX_CONTROL_SEQUENCE, } from '../protocol/index.js';
26
27
  import { boundedFailureDiagnostic } from './failure-diagnostic.js';
27
- import { boundedRuntimeResourceSnapshot, canonicalRuntimeResources, createRuntimeResourcePage, runtimeResourceRevision, runtimeResourceSnapshotFromResult, } from './runtime-resource-projection.js';
28
+ import { boundedRuntimeResourceState, canonicalRuntimeResources, createRuntimeResourcePage, runtimeResourceRevision, } from './runtime-resource-projection.js';
28
29
  const MAX_CONTROL_REPLAYS = 128;
29
30
  /** Owns Host Shell/PTY tools plus the connection-scoped Client controller fence. */
30
31
  export class HostRuntimeResourceCoordinator {
@@ -347,22 +348,22 @@ export class HostRuntimeResourceCoordinator {
347
348
  return {
348
349
  ok: true,
349
350
  result: decodeRuntimeResourceStartResult({
350
- resource: boundedRuntimeResourceSnapshot(await this.#manager.inspectResource(input.sessionId, launched.ref)),
351
+ resource: boundedRuntimeResourceState(shellRunStateProjection(launched)),
351
352
  }),
352
353
  };
353
354
  }
354
- catch (inspectError) {
355
+ catch (replyError) {
355
356
  // The command is already live but the operation must not report a
356
357
  // success it cannot honor: stop it so a client retry cannot
357
358
  // double-execute (#3210 review). Best-effort — the surfaced error
358
- // stays the inspection failure.
359
+ // stays the reply failure.
359
360
  try {
360
361
  await this.#manager.stopBackgroundTask(input.sessionId, launched.ref, new AbortController().signal, 'client');
361
362
  }
362
363
  catch {
363
- /* keep the inspection failure as the surfaced cause */
364
+ /* keep the reply failure as the surfaced cause */
364
365
  }
365
- throw inspectError;
366
+ throw replyError;
366
367
  }
367
368
  });
368
369
  }
@@ -388,8 +389,11 @@ export class HostRuntimeResourceCoordinator {
388
389
  if (sessionFailure)
389
390
  return mutationFailure('runtime.resource.controller.acquire', sessionFailure);
390
391
  try {
391
- const snapshot = await this.#manager.inspectResource(input.sessionId, input.ref);
392
- if (snapshot.mode !== 'pty' || !isActiveShellRunStatus(snapshot.status)) {
392
+ const pty = this.#manager.getLivePtySnapshot(input.sessionId, input.ref);
393
+ if (!pty) {
394
+ // No live handle: read through the manager so a stale active record
395
+ // is repaired to orphaned; the reply is a conflict either way.
396
+ await this.#manager.inspectResource(input.sessionId, input.ref);
393
397
  return mutationFailure('runtime.resource.controller.acquire', {
394
398
  code: 'operation_conflict',
395
399
  message: 'Only an active PTY Runtime Resource can be controlled',
@@ -420,14 +424,6 @@ export class HostRuntimeResourceCoordinator {
420
424
  };
421
425
  this.#controllers.set(key, controller);
422
426
  this.#controllerResources.set(identity, key);
423
- const pty = this.#manager.getLivePtySnapshot(input.sessionId, input.ref);
424
- if (!pty) {
425
- this.#releaseController(key);
426
- return mutationFailure('runtime.resource.controller.acquire', {
427
- code: 'operation_conflict',
428
- message: 'Runtime Resource PTY is no longer available',
429
- });
430
- }
431
427
  return {
432
428
  ok: true,
433
429
  result: boundedControllerAcquireResult(controller.controllerId, controller.nextSequence, pty),
@@ -485,7 +481,6 @@ export class HostRuntimeResourceCoordinator {
485
481
  const result = decodeRuntimeResourceControllerControlResult({
486
482
  controllerId: input.controllerId,
487
483
  sequence: input.sequence,
488
- resource: boundedRuntimeResourceSnapshot(runtimeResourceSnapshotFromResult(controlled)),
489
484
  });
490
485
  this.#rememberReplay({
491
486
  connectionId: context.connectionId,
@@ -555,12 +550,7 @@ export class HostRuntimeResourceCoordinator {
555
550
  try {
556
551
  const result = await this.#manager.stopBackgroundTask(input.sessionId, input.ref, new AbortController().signal, 'client');
557
552
  this.#releaseControllerIfTerminal(input.sessionId, input.ref, result);
558
- return {
559
- ok: true,
560
- result: decodeRuntimeResourceStopResult({
561
- resource: boundedRuntimeResourceSnapshot(runtimeResourceSnapshotFromResult(result)),
562
- }),
563
- };
553
+ return { ok: true, result: decodeRuntimeResourceStopResult({}) };
564
554
  }
565
555
  catch (error) {
566
556
  return this.#resourceFailure('runtime.resource.stop', error);
@@ -28,8 +28,11 @@ export function canonicalRuntimeResources(resources) {
28
28
  left.sourceToolCallId.localeCompare(right.sourceToolCallId));
29
29
  }
30
30
  function boundedRuntimeResourceUpdate(update) {
31
- const bounded = structuredClone(update);
32
- shrinkStateToFit(bounded.result);
31
+ return { ...update, result: boundedRuntimeResourceState(update.result) };
32
+ }
33
+ export function boundedRuntimeResourceState(state) {
34
+ const bounded = structuredClone(state);
35
+ shrinkStateToFit(bounded);
33
36
  return bounded;
34
37
  }
35
38
  export function runtimeResourceRevision(resources) {
@@ -68,20 +71,6 @@ export function createRuntimeResourcePage(sessionId, revision, resources, offset
68
71
  nextCursor: nextOffset < resources.length ? String(nextOffset) : null,
69
72
  });
70
73
  }
71
- export function boundedRuntimeResourceSnapshot(snapshot) {
72
- const bounded = structuredClone(snapshot);
73
- shrinkStateToFit(bounded);
74
- if (bounded.output === undefined)
75
- throw new Error('Runtime Resource snapshot lost its output');
76
- return bounded;
77
- }
78
- export function runtimeResourceSnapshotFromResult(result) {
79
- if (result.kind !== 'shell_run' || result.output === undefined) {
80
- throw new Error('Runtime Resource operation did not produce a ShellRun snapshot');
81
- }
82
- const { operation: _operation, ...snapshot } = result;
83
- return snapshot;
84
- }
85
74
  function shrinkStateToFit(state) {
86
75
  while (Buffer.byteLength(JSON.stringify(state), 'utf8') > RUNTIME_RESOURCE_SNAPSHOT_MAX_BYTES) {
87
76
  const fields = mutableTextFields(state).sort((left, right) => Buffer.byteLength(right.value(), 'utf8') - Buffer.byteLength(left.value(), 'utf8'));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "maka-agent",
3
- "version": "0.2.0-dev.40.20260917",
3
+ "version": "0.2.0-dev.41.20260918",
4
4
  "description": "Apache Maka (Incubating) developer snapshot; not an Apache release.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",