@dharma-ai-labs/agent-fabric 0.2.124 → 0.2.126
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/AGENT_FABRIC_ONBOARDING.md +3 -3
- package/README.md +18 -7
- package/dist/bin.js +2 -1
- package/dist/bin.js.map +1 -1
- package/dist/bootstrapRepositorySelection.d.ts +17 -0
- package/dist/bootstrapRepositorySelection.d.ts.map +1 -0
- package/dist/bootstrapRepositorySelection.js +145 -0
- package/dist/bootstrapRepositorySelection.js.map +1 -0
- package/dist/bootstrapRepositorySelection.test.d.ts +2 -0
- package/dist/bootstrapRepositorySelection.test.d.ts.map +1 -0
- package/dist/bootstrapRepositorySelection.test.js +145 -0
- package/dist/bootstrapRepositorySelection.test.js.map +1 -0
- package/dist/bootstrapResume.test.js +14 -1
- package/dist/bootstrapResume.test.js.map +1 -1
- package/dist/index.d.ts +6 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +116 -35
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +90 -7
- package/dist/index.test.js.map +1 -1
- package/dist/namedSessionService.d.ts.map +1 -1
- package/dist/namedSessionService.js +50 -10
- package/dist/namedSessionService.js.map +1 -1
- package/dist/namedSessionService.test.js +10 -0
- package/dist/namedSessionService.test.js.map +1 -1
- package/dist/onboardingContract.test.js +2 -0
- package/dist/onboardingContract.test.js.map +1 -1
- package/dist/repositoryOnboardingCaller.test.js +66 -2
- package/dist/repositoryOnboardingCaller.test.js.map +1 -1
- package/package.json +1 -1
package/dist/index.test.js
CHANGED
|
@@ -7,9 +7,10 @@ import { join } from 'node:path';
|
|
|
7
7
|
import test from 'node:test';
|
|
8
8
|
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
9
9
|
import { promisify } from 'node:util';
|
|
10
|
-
import { acceptedTrajectoryHead, activateAgyPlugin, attestAgySkillActivation, attestHermesSkillBundleActivation, actionDecisionCapabilityFreshUntil, canonicalFilesystemPath, controlAgentDecisionUrl, installAvailableNativeAgentFabricBootstraps, assertCapsuleAuthorizedByCurrentPolicy, assertRecoveredTaskWorkspacePolicy, assertTaskWorkspacePolicy, assertTaskSkillPin, installNativeAgentFabricBootstrap, installClaudeReadOnlyProjectPermissions, installRepositoryAgentFabricSkill, isDirectExecution, isTransientBootstrapError, loadAgentFabricOnboardingContract, loadOrCreateInstallationId, materializeWorkspacePolicy, applyServerEvidencePolicy, materializeInlineSkillFiles, validateSkillBundleSources, nativeSkillDirectory, nativeSkillDirectoryForWorkspace, nativeSkillRootMatchingAuthorization, normalizeGitRemoteIdentity, postTaskOutcome, parseCliOptions, parseSelectedProviderIds, pathExistsOrThrow, portalUrl, providerHintFromEnvironment, providerHintFromProcessArgv, probeRelayConnection, preflightBootstrapWorkspaceIdentity, rawLocalRetentionDays, syncPendingRetentionCapsules, requireCompletedBootstrapEvidence, retryBootstrapOnboarding, synchronizeBootstrapEvidence, deferUnavailableRelayRetention, recoverLegacySkillBundleIdAfterAuthorizationFailure, installedBundleIdForSkillPollAfterAuthorizationFailure, recoveredTaskPolicyWasSuperseded, acquireRelayProcessLease, acquireRelaySupervisorLease, relayProcessState, relaySupervisorProcessState, releaseDailyContentUpload, reserveDailyContentUpload, run, runAssistantCommand, sourceRepositoryFingerprint, stableRepositoryLauncherContents, summarizeBootstrapOrganizationApi, ensureAgyReadOnlyAttestationPermission, attestAgySkillBundleActivation, responseTextFromEvent, taskResponsePreview, taskReceiptSession, taskSkillPinFailureCode, verifyAgentFabricSkillInstallation, waitForRelayReadiness, withWorkspacePolicyRefreshLock, withRelayStartupMutation, withWorkspaceSkillActivationLock, } from './index.js';
|
|
10
|
+
import { acceptedTrajectoryHead, activateAgyPlugin, attestAgySkillActivation, attestHermesSkillBundleActivation, actionDecisionCapabilityFreshUntil, canonicalFilesystemPath, controlAgentDecisionUrl, installAvailableNativeAgentFabricBootstraps, assertCapsuleAuthorizedByCurrentPolicy, assertRecoveredTaskWorkspacePolicy, assertTaskWorkspacePolicy, assertTaskSkillPin, installNativeAgentFabricBootstrap, installClaudeReadOnlyProjectPermissions, installRepositoryAgentFabricSkill, initialBootstrapEvidenceDisposition, isDirectExecution, isTransientBootstrapError, loadAgentFabricOnboardingContract, loadOrCreateInstallationId, materializeWorkspacePolicy, applyServerEvidencePolicy, materializeInlineSkillFiles, validateSkillBundleSources, nativeSkillDirectory, nativeSkillDirectoryForWorkspace, nativeSkillRootMatchingAuthorization, normalizeGitRemoteIdentity, postTaskOutcome, parseCliOptions, parseSelectedProviderIds, pathExistsOrThrow, portalUrl, providerHintFromEnvironment, providerHintFromProcessArgv, probeRelayConnection, preflightBootstrapWorkspaceIdentity, publishedPackageCanDeferSecretEvidence, rawLocalRetentionDays, syncPendingRetentionCapsules, requireCompletedBootstrapEvidence, retryBootstrapOnboarding, synchronizeBootstrapEvidence, deferUnavailableRelayRetention, recoverLegacySkillBundleIdAfterAuthorizationFailure, installedBundleIdForSkillPollAfterAuthorizationFailure, recoveredTaskPolicyWasSuperseded, acquireRelayProcessLease, acquireRelaySupervisorLease, relayProcessState, relaySupervisorProcessState, releaseDailyContentUpload, reserveDailyContentUpload, run, runAssistantCommand, sourceRepositoryFingerprint, stableRepositoryLauncherContents, summarizeBootstrapOrganizationApi, ensureAgyReadOnlyAttestationPermission, attestAgySkillBundleActivation, responseTextFromEvent, taskResponsePreview, taskReceiptSession, taskSkillPinFailureCode, verifyAgentFabricSkillInstallation, waitForRelayReadiness, withWorkspacePolicyRefreshLock, withRelayStartupMutation, withWorkspaceSkillActivationLock, } from './index.js';
|
|
11
11
|
import { canonicalize, signCanonicalObject } from '@dharma-ai-labs/agent-fabric-contracts';
|
|
12
12
|
import { buildTrajectoryCapsule, trajectoryCapsuleHash } from '@dharma-ai-labs/agent-fabric-evidence-reduction';
|
|
13
|
+
import { AgentFabricRequestError } from '@dharma-ai-labs/agent-fabric-relay-client';
|
|
13
14
|
import { CLI_USAGE } from './usage.js';
|
|
14
15
|
import { workspaceIdForDevice } from './onboardingWorkspace.js';
|
|
15
16
|
import { isSupportedNodeVersion, launchWithRuntime, nodeRuntimeCandidates, runtimeBootstrapHint, } from './runtime-bootstrap.js';
|
|
@@ -140,20 +141,37 @@ test('bootstrap defers policy-rejected evidence without weakening the disclosure
|
|
|
140
141
|
});
|
|
141
142
|
assert.deepEqual(result, {
|
|
142
143
|
state: 'deferred',
|
|
143
|
-
captured:
|
|
144
|
-
synced:
|
|
144
|
+
captured: null,
|
|
145
|
+
synced: null,
|
|
145
146
|
reason: 'policy_boundary',
|
|
146
147
|
errorCode: 'local_path_disclosure_forbidden',
|
|
147
148
|
});
|
|
148
149
|
});
|
|
150
|
+
test('only a published package under the same source policy can defer a definitive secret rejection', async () => {
|
|
151
|
+
const denied = await synchronizeBootstrapEvidence(async () => {
|
|
152
|
+
throw new AgentFabricRequestError({ error: { code: 'policy_boundary',
|
|
153
|
+
message: 'secret_disclosure_forbidden' } }, 403, true);
|
|
154
|
+
});
|
|
155
|
+
assert.equal(denied.errorCode, 'secret_disclosure_forbidden');
|
|
156
|
+
const published = { state: 'published', releaseId: '11111111-1111-4111-8111-111111111111',
|
|
157
|
+
sourcePolicyGenerationId: '22222222-2222-4222-8222-222222222222' };
|
|
158
|
+
assert.equal(publishedPackageCanDeferSecretEvidence(denied, published, '22222222-2222-4222-8222-222222222222'), true);
|
|
159
|
+
assert.equal(publishedPackageCanDeferSecretEvidence(denied, published, '33333333-3333-4333-8333-333333333333'), false);
|
|
160
|
+
assert.equal(publishedPackageCanDeferSecretEvidence(denied, { ...published, state: 'accepted' }, '22222222-2222-4222-8222-222222222222'), false);
|
|
161
|
+
const ambiguous = await synchronizeBootstrapEvidence(async () => {
|
|
162
|
+
throw new AgentFabricRequestError({ error: { code: 'policy_boundary',
|
|
163
|
+
message: 'secret_disclosure_forbidden' } }, 503, false);
|
|
164
|
+
});
|
|
165
|
+
assert.equal(publishedPackageCanDeferSecretEvidence(ambiguous, published, '22222222-2222-4222-8222-222222222222'), false);
|
|
166
|
+
});
|
|
149
167
|
test('bootstrap reports non-policy evidence failures without returning sensitive error text', async () => {
|
|
150
168
|
const result = await synchronizeBootstrapEvidence(async () => {
|
|
151
169
|
throw new Error('fetch failed for C:/Users/customer/private-session.json');
|
|
152
170
|
});
|
|
153
171
|
assert.deepEqual(result, {
|
|
154
172
|
state: 'deferred',
|
|
155
|
-
captured:
|
|
156
|
-
synced:
|
|
173
|
+
captured: null,
|
|
174
|
+
synced: null,
|
|
157
175
|
reason: 'capture_unavailable',
|
|
158
176
|
errorCode: 'evidence_capture_failed',
|
|
159
177
|
});
|
|
@@ -165,8 +183,8 @@ test('bootstrap identifies unavailable retention without weakening other capture
|
|
|
165
183
|
});
|
|
166
184
|
assert.deepEqual(result, {
|
|
167
185
|
state: 'deferred',
|
|
168
|
-
captured:
|
|
169
|
-
synced:
|
|
186
|
+
captured: null,
|
|
187
|
+
synced: null,
|
|
170
188
|
reason: 'retention_not_ready',
|
|
171
189
|
errorCode: 'agent_fabric_retention_not_ready',
|
|
172
190
|
});
|
|
@@ -175,6 +193,16 @@ test('bootstrap records successful evidence synchronization', async () => {
|
|
|
175
193
|
const result = await synchronizeBootstrapEvidence(async () => ({ captured: 2, synced: 2 }));
|
|
176
194
|
assert.deepEqual(result, { state: 'synchronized', captured: 2, synced: 2 });
|
|
177
195
|
});
|
|
196
|
+
test('eligible history without disclosure is reported as denied, not synchronized', () => {
|
|
197
|
+
assert.deepEqual(initialBootstrapEvidenceDisposition(3, false), {
|
|
198
|
+
state: 'denied_disclosure', captured: 0, synced: 0,
|
|
199
|
+
reason: 'policy_boundary', errorCode: 'automatic_disclosure_not_ready',
|
|
200
|
+
});
|
|
201
|
+
assert.deepEqual(initialBootstrapEvidenceDisposition(0, false), {
|
|
202
|
+
state: 'synchronized', captured: 0, synced: 0,
|
|
203
|
+
});
|
|
204
|
+
assert.throws(() => initialBootstrapEvidenceDisposition(Number.NaN, true), /invalid trajectory count/);
|
|
205
|
+
});
|
|
178
206
|
test('relay defers unavailable retention without stopping signed task polling', async () => {
|
|
179
207
|
const result = await deferUnavailableRelayRetention(async () => {
|
|
180
208
|
throw new Error('agent_fabric_retention_not_ready: Content synchronization is unavailable until retention is enabled.');
|
|
@@ -1480,6 +1508,61 @@ test('queued capsules from a replaced device are retained locally but never sent
|
|
|
1480
1508
|
assert.deepEqual(sent, [current.trajectoryId]);
|
|
1481
1509
|
assert.equal(old.deviceId, '11111111-1111-4111-8111-111111111111');
|
|
1482
1510
|
});
|
|
1511
|
+
test('definitive secret rejection retires only its upload queue row and leaves later work eligible', async () => {
|
|
1512
|
+
const base = await materializeWorkspacePolicy({
|
|
1513
|
+
workspace: await mkdtemp(join(tmpdir(), 'dharma-secret-rejection-')),
|
|
1514
|
+
organizationId: 'org_northstar', revision: 'local',
|
|
1515
|
+
});
|
|
1516
|
+
const deviceId = '22222222-2222-4222-8222-222222222222';
|
|
1517
|
+
const session = (sessionId) => ({
|
|
1518
|
+
provider: 'codex', sessionId, sourcePath: '/private/codex.jsonl',
|
|
1519
|
+
workspace: '/repo', coverage: 'observed',
|
|
1520
|
+
startedAt: '2026-09-23T00:00:00.000Z', endedAt: '2026-09-23T00:00:01.000Z',
|
|
1521
|
+
records: [{ native: { type: 'message' }, sourcePath: '/private/codex.jsonl', line: 1,
|
|
1522
|
+
workspace: '/repo', timestamp: '2026-09-23T00:00:00.000Z', kind: 'metadata' }],
|
|
1523
|
+
});
|
|
1524
|
+
const capsules = ['denied', 'allowed'].map(sessionId => buildTrajectoryCapsule({
|
|
1525
|
+
organizationId: 'org_northstar', deviceId, workspaceId: 'workspace-northstar',
|
|
1526
|
+
session: session(sessionId), policy: base.policy,
|
|
1527
|
+
rawContentId: `sha256:${'a'.repeat(64)}`, rawBytes: 32,
|
|
1528
|
+
}));
|
|
1529
|
+
const pending = [...capsules];
|
|
1530
|
+
const discarded = [];
|
|
1531
|
+
const synced = [];
|
|
1532
|
+
const vault = {
|
|
1533
|
+
listPendingCapsuleSyncs: async () => pending.map(capsule => ({ trajectoryId: capsule.trajectoryId,
|
|
1534
|
+
revision: capsule.revision, capsule })),
|
|
1535
|
+
markCapsuleSynced: (trajectoryId) => {
|
|
1536
|
+
synced.push(trajectoryId);
|
|
1537
|
+
pending.splice(pending.findIndex(c => c.trajectoryId === trajectoryId), 1);
|
|
1538
|
+
},
|
|
1539
|
+
discardPendingCapsuleSync: (trajectoryId, _revision, reason) => {
|
|
1540
|
+
discarded.push(reason);
|
|
1541
|
+
pending.splice(pending.findIndex(c => c.trajectoryId === trajectoryId), 1);
|
|
1542
|
+
},
|
|
1543
|
+
};
|
|
1544
|
+
const fabric = {
|
|
1545
|
+
config: { organizationId: 'org_northstar', deviceId },
|
|
1546
|
+
syncTrajectory: async (capsule) => {
|
|
1547
|
+
if (capsule.trajectoryId === capsules[0].trajectoryId) {
|
|
1548
|
+
throw new AgentFabricRequestError({ error: { code: 'policy_boundary',
|
|
1549
|
+
message: 'secret_disclosure_forbidden' } }, 403, true);
|
|
1550
|
+
}
|
|
1551
|
+
},
|
|
1552
|
+
};
|
|
1553
|
+
assert.equal(await syncPendingRetentionCapsules(vault, fabric, base.policy, 'workspace-northstar'), 1);
|
|
1554
|
+
assert.deepEqual(discarded, ['secret_disclosure_forbidden']);
|
|
1555
|
+
assert.deepEqual(synced, [capsules[1].trajectoryId]);
|
|
1556
|
+
assert.equal(pending.length, 0);
|
|
1557
|
+
pending.push(capsules[0]);
|
|
1558
|
+
fabric.syncTrajectory = async () => {
|
|
1559
|
+
throw new AgentFabricRequestError({ error: { code: 'policy_boundary',
|
|
1560
|
+
message: 'secret_disclosure_forbidden' } }, 503, false);
|
|
1561
|
+
};
|
|
1562
|
+
await assert.rejects(() => syncPendingRetentionCapsules(vault, fabric, base.policy, 'workspace-northstar'), /secret_disclosure_forbidden/);
|
|
1563
|
+
assert.equal(pending.length, 1);
|
|
1564
|
+
assert.deepEqual(discarded, ['secret_disclosure_forbidden']);
|
|
1565
|
+
});
|
|
1483
1566
|
test('oversized queued current-device revision is retired only after checking the accepted head', async () => {
|
|
1484
1567
|
const base = await materializeWorkspacePolicy({
|
|
1485
1568
|
workspace: await mkdtemp(join(tmpdir(), 'dharma-oversized-capsule-')),
|