@dharma-ai-labs/agent-fabric 0.2.129 → 0.2.131

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 (86) hide show
  1. package/AGENT_FABRIC_ONBOARDING.md +1 -1
  2. package/README.md +43 -0
  3. package/dist/demoEnrollment.d.ts.map +1 -1
  4. package/dist/demoEnrollment.js +3 -2
  5. package/dist/demoEnrollment.js.map +1 -1
  6. package/dist/demoPackage.d.ts.map +1 -1
  7. package/dist/demoPackage.js +29 -9
  8. package/dist/demoPackage.js.map +1 -1
  9. package/dist/demoPackage.test.js +75 -1
  10. package/dist/demoPackage.test.js.map +1 -1
  11. package/dist/demoStateRename.d.ts +7 -0
  12. package/dist/demoStateRename.d.ts.map +1 -0
  13. package/dist/demoStateRename.js +21 -0
  14. package/dist/demoStateRename.js.map +1 -0
  15. package/dist/demoStateRename.test.d.ts +2 -0
  16. package/dist/demoStateRename.test.d.ts.map +1 -0
  17. package/dist/demoStateRename.test.js +67 -0
  18. package/dist/demoStateRename.test.js.map +1 -0
  19. package/dist/index.d.ts +2 -0
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +107 -21
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.test.js +5 -2
  24. package/dist/index.test.js.map +1 -1
  25. package/dist/namedSessionPackageGate.d.ts +22 -0
  26. package/dist/namedSessionPackageGate.d.ts.map +1 -0
  27. package/dist/namedSessionPackageGate.js +135 -0
  28. package/dist/namedSessionPackageGate.js.map +1 -0
  29. package/dist/namedSessionPackageGate.test.d.ts +2 -0
  30. package/dist/namedSessionPackageGate.test.d.ts.map +1 -0
  31. package/dist/namedSessionPackageGate.test.js +20 -0
  32. package/dist/namedSessionPackageGate.test.js.map +1 -0
  33. package/dist/namedSessionRepositoryState.d.ts +65 -0
  34. package/dist/namedSessionRepositoryState.d.ts.map +1 -0
  35. package/dist/namedSessionRepositoryState.js +54 -0
  36. package/dist/namedSessionRepositoryState.js.map +1 -0
  37. package/dist/namedSessionRepositoryState.test.d.ts +2 -0
  38. package/dist/namedSessionRepositoryState.test.d.ts.map +1 -0
  39. package/dist/namedSessionRepositoryState.test.js +76 -0
  40. package/dist/namedSessionRepositoryState.test.js.map +1 -0
  41. package/dist/namedSessionService.d.ts +5 -1
  42. package/dist/namedSessionService.d.ts.map +1 -1
  43. package/dist/namedSessionService.js +26 -2
  44. package/dist/namedSessionService.js.map +1 -1
  45. package/dist/namedSessionService.test.js +47 -3
  46. package/dist/namedSessionService.test.js.map +1 -1
  47. package/dist/namedSessionTaskExport.d.ts +22 -0
  48. package/dist/namedSessionTaskExport.d.ts.map +1 -0
  49. package/dist/namedSessionTaskExport.js +158 -0
  50. package/dist/namedSessionTaskExport.js.map +1 -0
  51. package/dist/namedSessionTaskExport.test.d.ts +2 -0
  52. package/dist/namedSessionTaskExport.test.d.ts.map +1 -0
  53. package/dist/namedSessionTaskExport.test.js +385 -0
  54. package/dist/namedSessionTaskExport.test.js.map +1 -0
  55. package/dist/namedSessionTaskExportSync.d.ts +57 -0
  56. package/dist/namedSessionTaskExportSync.d.ts.map +1 -0
  57. package/dist/namedSessionTaskExportSync.js +193 -0
  58. package/dist/namedSessionTaskExportSync.js.map +1 -0
  59. package/dist/pidLock.test.js +33 -1
  60. package/dist/pidLock.test.js.map +1 -1
  61. package/dist/relayAutostart.d.ts +5 -3
  62. package/dist/relayAutostart.d.ts.map +1 -1
  63. package/dist/relayAutostart.js +151 -24
  64. package/dist/relayAutostart.js.map +1 -1
  65. package/dist/relayAutostart.test.js +138 -2
  66. package/dist/relayAutostart.test.js.map +1 -1
  67. package/dist/relaySupervisor.test.js +9 -4
  68. package/dist/relaySupervisor.test.js.map +1 -1
  69. package/dist/repositoryPackage.d.ts.map +1 -1
  70. package/dist/repositoryPackage.js +18 -2
  71. package/dist/repositoryPackage.js.map +1 -1
  72. package/dist/repositoryPackage.test.js +29 -0
  73. package/dist/repositoryPackage.test.js.map +1 -1
  74. package/dist/repositoryPackageDelivery.test.js +34 -1
  75. package/dist/repositoryPackageDelivery.test.js.map +1 -1
  76. package/dist/repositoryRelaySupervisor.d.ts +1 -1
  77. package/dist/repositoryRelaySupervisor.d.ts.map +1 -1
  78. package/dist/repositoryRelaySupervisor.js +3 -2
  79. package/dist/repositoryRelaySupervisor.js.map +1 -1
  80. package/dist/repositoryRelaySupervisor.test.js +17 -0
  81. package/dist/repositoryRelaySupervisor.test.js.map +1 -1
  82. package/dist/schemas/codex-task-export-upload-receipt.schema.json +24 -0
  83. package/dist/schemas/codex-task-observation.schema.json +99 -0
  84. package/dist/schemas/codex-task-replay-export.schema.json +375 -0
  85. package/dist/schemas/named-session-task-export-outbox.schema.json +29 -0
  86. package/package.json +7 -7
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ import { appendRecoveredWorkspace, applyRegistryRecoveryFile, inspectRegistryRec
24
24
  import { relayRuntimeObservationReady, upgradeRelayRuntime } from './relayRuntimeUpgrade.js';
25
25
  import { assertStudyExactPoll, studyTaskIdFromFlags } from './studyExactTaskSelector.js';
26
26
  import { initializeRepositoryKnowledge, readRepositoryKnowledgeSource } from './repositoryKnowledge.js';
27
- import { inventoryRepositoryPackage, readRepositoryPackageSnapshot, readRepositorySourceBaselineSnapshot, writeRepositoryPackageSnapshot } from './repositoryPackage.js';
27
+ import { inventoryRepositoryPackage, readRepositoryPackageSnapshot, readRepositorySourceBaselineSnapshot, serializeRepositoryPackageSnapshot, writeRepositoryPackageSnapshot } from './repositoryPackage.js';
28
28
  import { validateRepositorySourceAuthorization } from './repositorySourceAuthorization.js';
29
29
  import { advanceRepositorySourceBaseline, BlockedRepositorySourceRetry, fetchRepositorySourceAuthorization, recoverPublishedLocalSourceBaseline, RepositorySourceWatcher, scanRepositorySourceChanges, seedRepositorySourceWatcher } from './repositorySourceSync.js';
30
30
  import { assertRepositoryInstallerOwnership, writeRepositoryInstallerFile } from './repositoryInstallerFiles.js';
@@ -57,11 +57,15 @@ import { createDemoWatchHealthRecorder } from './demoWatchHealth.js';
57
57
  import { demoWatchStatus, disableDemoWatch, enableDemoWatch, inspectDemoWatchSupervisor } from './demoWatchControl.js';
58
58
  import { namedSessionPaths, namedSessionRequest, readNamedSession, saveNamedSession, runNamedSessionService } from './namedSessionService.js';
59
59
  import { queueNamedSessionEvidence } from './namedSessionEvidence.js';
60
+ import { retainNamedSessionRepositoryState } from './namedSessionRepositoryState.js';
61
+ import { syncNamedSessionTaskExports } from './namedSessionTaskExportSync.js';
62
+ import { readNamedSessionPackageContent, verifyNamedSessionVisibleSkill } from './namedSessionPackageGate.js';
60
63
  import { openCodexAppServerTransport } from '@dharma-ai-labs/agent-fabric-provider-adapters/experimental/codex-transport';
64
+ import { readCodexPublicContext } from '@dharma-ai-labs/agent-fabric-provider-adapters/experimental/codex-session';
61
65
  import { createNamedSessionTrust, isNamedSessionOwnerReceipt, renewNamedSessionLifetime } from './namedSessionTrust.js';
62
66
  import { startNamedCodexThread } from './namedCodexThread.js';
63
67
  export { openCooperativeInboxSession } from './cooperativeInboxSession.js';
64
- const VERSION = '0.2.129';
68
+ const VERSION = '0.2.131';
65
69
  const USAGE = CLI_USAGE;
66
70
  const execFileAsync = promisify(execFile);
67
71
  const LOCAL_PROVIDER_IDS = ['codex', 'claude', 'agy', 'hermes'];
@@ -624,7 +628,7 @@ async function acquirePidLock(lockPath, timeoutMs, timeoutMessage) {
624
628
  try {
625
629
  await mkdir(recoveryCandidate);
626
630
  await writeFile(resolve(recoveryCandidate, 'owner'), `${process.pid}\n`, { mode: 0o600 });
627
- for (let attempt = 0;; attempt++) {
631
+ for (;;) {
628
632
  try {
629
633
  await rename(recoveryCandidate, recoveryPath);
630
634
  break;
@@ -647,8 +651,10 @@ async function acquirePidLock(lockPath, timeoutMs, timeoutMessage) {
647
651
  windowsRecoveryOwner = owner;
648
652
  }
649
653
  catch (inspectionError) {
650
- if (inspectionError.code === 'ENOENT' && attempt < 3)
654
+ if (inspectionError.code === 'ENOENT' && Date.now() < deadline) {
655
+ await new Promise((resolvePromise) => setTimeout(resolvePromise, 25));
651
656
  continue;
657
+ }
652
658
  throw renameError;
653
659
  }
654
660
  throw renameError;
@@ -2368,7 +2374,7 @@ async function bootstrap(flags) {
2368
2374
  const role = repositoryReceipt.repositoryRole;
2369
2375
  const roleReady = Boolean(role);
2370
2376
  const relayReady = relay.state === 'running';
2371
- const startupReady = !['win32', 'linux'].includes(process.platform) || autostart.state === 'enabled';
2377
+ const startupReady = !['win32', 'linux', 'darwin'].includes(process.platform) || autostart.state === 'enabled';
2372
2378
  const complete = sharedRepositoryReady && namedSessionReady && firstLearningReady
2373
2379
  && roleReady && relayReady && startupReady;
2374
2380
  return {
@@ -3664,8 +3670,7 @@ async function namedSessionCommand(action, flags) {
3664
3670
  if (!flags.has('apply'))
3665
3671
  return { ok: true, planned: true, name, workspaceId,
3666
3672
  provider: 'codex', localWork: 'workspace_write', peerQuestions: 'read_only', network: 'deny' };
3667
- if (!await repositorySharedReady(item))
3668
- throw new Error('named_session_repository_package_pending');
3673
+ await verifyNamedSessionVisibleSkill(await verifyAgentFabricSkillInstallation({ provider: 'codex', workspace: item.path }), await repositorySharedReady(item));
3669
3674
  if (action === 'start') {
3670
3675
  if (existing && !existing.enabled)
3671
3676
  await saveNamedSession(dharmaHome(), { ...existing, enabled: true });
@@ -3776,15 +3781,89 @@ async function namedSessionCommand(action, flags) {
3776
3781
  } };
3777
3782
  // The durable reservation already suppresses duplicate provider execution.
3778
3783
  const consumed = new Set();
3784
+ let taskState = null;
3785
+ let taskStateFailure = 'source_state_unavailable';
3786
+ const taskSnapshot = async () => {
3787
+ const sourceAuthorization = await fetchRepositorySourceAuthorization(fabric, repositoryRoleScope(item));
3788
+ return inventoryRepositoryPackage({ workspace: item.path, organizationId: item.organizationId,
3789
+ workspaceId, repositoryBindingId: item.repositoryBindingId, repositoryAgentId: item.repositoryAgentId, sourceAuthorization });
3790
+ };
3779
3791
  return await runNamedSessionService({ home: dharmaHome(), registration, vault, signal: controller.signal,
3780
3792
  localWriteRoots: writeRoots,
3781
- withActivationBoundary: operation => withWorkspaceSkillActivationLock(workspaceId, 'codex', async () => {
3793
+ syncTaskExports: () => syncNamedSessionTaskExports({ vault, bindingId: registration.bindingId,
3794
+ identity: registration.identity,
3795
+ loadPolicy: () => refreshVerifiedWorkspacePolicyForTransmission(policyPath, workspaceId, fabric),
3796
+ send: body => fabric.signedPost('/agent-fabric/codex-task-exports', body) }),
3797
+ withActivationBoundary: (operation, work) => withWorkspaceSkillActivationLock(workspaceId, 'codex', async () => {
3782
3798
  await refreshLifetime();
3783
3799
  const skill = await verifyAgentFabricSkillInstallation({ provider: 'codex', workspace: item.path });
3784
- if (!skill.ready || !await repositorySharedReady(item))
3785
- throw new Error('named_session_repository_package_pending');
3786
- return operation();
3800
+ const packageContent = await readNamedSessionPackageContent(skill, await repositorySharedReady(item));
3801
+ const bundleId = packageContent.bundleId;
3802
+ taskState = null;
3803
+ taskStateFailure = 'source_state_unavailable';
3804
+ if (work) {
3805
+ const current = await loadVerifiedWorkspacePolicy(policyPath, workspaceId);
3806
+ if (current.evidence.automaticDisclosure?.mode === 'customer_authorized_content' && skill.activeBundleHash) {
3807
+ try {
3808
+ taskStateFailure = 'public_context_unavailable';
3809
+ const binding = vault.getProviderSessionBinding(registration.bindingId, registration.identity);
3810
+ if (!binding)
3811
+ throw new Error('named_session_binding_unavailable');
3812
+ const retained = await readCodexPublicContext(transport, { threadId: binding.sessionId, workspaceRoot: binding.workspaceRoot });
3813
+ taskStateFailure = 'runtime_version_unavailable';
3814
+ const version = (await execFileAsync('codex', ['--version'], { timeout: 10_000, maxBuffer: 4096,
3815
+ env: providerProcessEnvironment(process.env) })).stdout.trim();
3816
+ if (!/^codex-cli [0-9]+\.[0-9]+\.[0-9]+(?:[-+][a-zA-Z0-9.-]+)?$/.test(version)) {
3817
+ throw new Error('named_session_runtime_version_unavailable');
3818
+ }
3819
+ const contextContentHash = await vault.putBlob(Buffer.from(retained.bytes), 'named-session-public-context');
3820
+ if (contextContentHash !== retained.contextHash)
3821
+ throw new Error('named_session_context_integrity_failed');
3822
+ taskStateFailure = 'source_state_unavailable';
3823
+ const before = await taskSnapshot();
3824
+ const sourceContentHash = await vault.putBlob(Buffer.from(serializeRepositoryPackageSnapshot(before)), 'named-session-source-state');
3825
+ await vault.putBlob(Buffer.from(JSON.stringify({ workId: work.workId, bindingId: registration.bindingId,
3826
+ sourceContentHash, sourceSnapshotHash: before.manifest.snapshotHash, bundleId, bundleHash: skill.activeBundleHash,
3827
+ packageContent, contextContentHash, evidenceRevision: current.revision,
3828
+ consentReceiptId: current.evidence.automaticDisclosure.consentReceiptId })), 'named-session-source-boundary');
3829
+ taskState = { workId: work.workId, before, bundleId, bundleHash: skill.activeBundleHash, packageContent,
3830
+ evidenceRevision: current.revision, consentReceiptId: current.evidence.automaticDisclosure.consentReceiptId,
3831
+ providerContext: { retainedContextHash: retained.contextHash, contextContentHash,
3832
+ runtimeVersion: version.slice('codex-cli '.length), requestedModel: retained.context.configuredModel,
3833
+ executedModel: null, replayMode: 'task_level' } };
3834
+ }
3835
+ catch { /* Source capture failure must not replay or rewrite a coding task. */ }
3836
+ }
3837
+ }
3838
+ try {
3839
+ return await operation();
3840
+ }
3841
+ finally {
3842
+ taskState = null;
3843
+ }
3787
3844
  }),
3845
+ retainRepositoryState: async (capture) => {
3846
+ const current = await loadVerifiedWorkspacePolicy(policyPath, workspaceId);
3847
+ if (current.evidence.automaticDisclosure?.mode !== 'customer_authorized_content') {
3848
+ return { state: 'not_authorized', acceptedLearningObservation: false };
3849
+ }
3850
+ if (!taskState)
3851
+ return { state: 'blocked', code: taskStateFailure, acceptedLearningObservation: false };
3852
+ if (current.revision !== taskState.evidenceRevision
3853
+ || current.evidence.automaticDisclosure.consentReceiptId !== taskState.consentReceiptId) {
3854
+ throw new Error('named_session_repository_state_consent_changed');
3855
+ }
3856
+ const binding = vault.getProviderSessionBinding(registration.bindingId, registration.identity);
3857
+ if (!binding)
3858
+ throw new Error('named_session_binding_unavailable');
3859
+ const receipt = await retainNamedSessionRepositoryState({ vault, binding, capture, workId: taskState.workId,
3860
+ before: taskState.before, after: await taskSnapshot(), activeBundleId: taskState.bundleId, activeBundleHash: taskState.bundleHash,
3861
+ taskExport: { policy: current, contextBytes: await vault.getBlob(taskState.providerContext.contextContentHash),
3862
+ contextHash: taskState.providerContext.retainedContextHash } });
3863
+ return { ...receipt, providerContext: taskState.providerContext,
3864
+ packageContent: { manifestHash: taskState.packageContent.manifestHash,
3865
+ catalogHash: taskState.packageContent.catalogHash, skillsHash: taskState.packageContent.skillsHash } };
3866
+ },
3788
3867
  authorizeLocalWork: async () => {
3789
3868
  const current = await refreshVerifiedWorkspacePolicyForTransmission(policyPath, workspaceId, fabric);
3790
3869
  return writeRoots.every(root => current.tasks.writePaths.includes(`${root}/**`));
@@ -5595,9 +5674,10 @@ export async function verifyAgentFabricSkillInstallation(input) {
5595
5674
  }
5596
5675
  const bootstrapReady = repositoryInstalled && nativeInstalled && nativeDiscovered;
5597
5676
  const config = await readDeviceConfig();
5598
- const activeBundleId = workspaceId && organizationAgentId && config
5599
- ? (await activeSkillAuthorization(input.provider, workspaceId, organizationAgentId, config))?.bundleId ?? null
5677
+ const activeAuthorization = workspaceId && organizationAgentId && config
5678
+ ? await activeSkillAuthorization(input.provider, workspaceId, organizationAgentId, config)
5600
5679
  : null;
5680
+ const activeBundleId = activeAuthorization?.bundleId ?? null;
5601
5681
  let activationAttested = !['agy', 'hermes'].includes(input.provider) ? nativeInstalled : false;
5602
5682
  if (['agy', 'hermes'].includes(input.provider) && activeBundleId && workspaceId) {
5603
5683
  try {
@@ -5629,6 +5709,8 @@ export async function verifyAgentFabricSkillInstallation(input) {
5629
5709
  nativeSkillPath,
5630
5710
  workspaceId: workspaceId || null,
5631
5711
  activeBundleId,
5712
+ activeBundleHash: activeAuthorization?.bundleHash ?? null,
5713
+ signedMarkerBundleId,
5632
5714
  activation: input.provider === 'agy' ? (activationAttested ? 'attested' : 'manual_invocation_required') : 'next_session',
5633
5715
  nextAction: input.provider === 'agy' && bootstrapReady && !activationAttested
5634
5716
  ? 'The Agy bootstrap is installed and discoverable. A signed remediation bundle must include and pass the content-bound activation challenge before full lifecycle support is reported.'
@@ -6718,14 +6800,18 @@ async function relayWorkspaceLoop(flags, signal, serialized) {
6718
6800
  }
6719
6801
  let evidenceRequestId;
6720
6802
  if (canonicalWorkspace.accessMode !== 'knowledge_only' && evidencePolicyFresh && !stopping) {
6721
- const evidenceCycle = await withRepositoryRelayStage('evidence_sync', () => deferUnavailableRelayRetention(async () => {
6722
- const synced = await syncPendingRetentionCapsules(vault, fabric, policy, canonicalWorkspace.workspaceId);
6723
- const evidence = await processEvidenceRequest(fabric, policy, canonicalWorkspace.workspaceId);
6724
- return {
6725
- synced,
6726
- evidenceRequestId: typeof evidence.requestId === 'string' ? evidence.requestId : undefined,
6727
- };
6728
- }));
6803
+ const evidenceCycle = await withRepositoryRelayStage('evidence_sync', async () => {
6804
+ const synced = await withRepositoryRelayStage('pending_capsule_sync', () => deferUnavailableRelayRetention(() => syncPendingRetentionCapsules(vault, fabric, policy, canonicalWorkspace.workspaceId)));
6805
+ if (synced.state === 'deferred')
6806
+ return synced;
6807
+ const evidence = await withRepositoryRelayStage('evidence_request', () => deferUnavailableRelayRetention(() => processEvidenceRequest(fabric, policy, canonicalWorkspace.workspaceId)));
6808
+ if (evidence.state === 'deferred')
6809
+ return evidence;
6810
+ return { state: 'completed', value: {
6811
+ synced: synced.value,
6812
+ evidenceRequestId: typeof evidence.value.requestId === 'string' ? evidence.value.requestId : undefined,
6813
+ } };
6814
+ });
6729
6815
  if (evidenceCycle.state === 'deferred') {
6730
6816
  evidencePolicyFresh = false;
6731
6817
  }