@dharma-ai-labs/agent-fabric 0.2.79 → 0.2.81
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/dist/demoEnrollment.d.ts +41 -0
- package/dist/demoEnrollment.d.ts.map +1 -0
- package/dist/demoEnrollment.js +207 -0
- package/dist/demoEnrollment.js.map +1 -0
- package/dist/demoEnrollment.test.d.ts +2 -0
- package/dist/demoEnrollment.test.d.ts.map +1 -0
- package/dist/demoEnrollment.test.js +165 -0
- package/dist/demoEnrollment.test.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +53 -2
- package/dist/index.js.map +1 -1
- package/dist/index.test.js +47 -3
- package/dist/index.test.js.map +1 -1
- package/dist/usage.d.ts +1 -1
- package/dist/usage.d.ts.map +1 -1
- package/dist/usage.js +1 -1
- package/dist/usage.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -33,7 +33,8 @@ import { askRepositoryRoleQuestion, readRepositoryRoleReply } from './repository
|
|
|
33
33
|
import { deriveRepositoryRole } from './repositoryRoleDerivation.js';
|
|
34
34
|
import { withOnboardingStage } from './onboardingStage.js';
|
|
35
35
|
import { waitForRepositoryReadiness } from './repositoryReadinessWait.js';
|
|
36
|
-
|
|
36
|
+
import { connectDemoDevice, verifyDemoDevice } from './demoEnrollment.js';
|
|
37
|
+
const VERSION = '0.2.81';
|
|
37
38
|
const USAGE = CLI_USAGE;
|
|
38
39
|
const execFileAsync = promisify(execFile);
|
|
39
40
|
const LOCAL_PROVIDER_IDS = ['codex', 'claude', 'agy', 'hermes'];
|
|
@@ -252,12 +253,13 @@ export function rawLocalRetentionDays(policy) {
|
|
|
252
253
|
}
|
|
253
254
|
return Number(value);
|
|
254
255
|
}
|
|
255
|
-
async function syncPendingRetentionCapsules(vault, fabric, policy, workspaceId) {
|
|
256
|
+
export async function syncPendingRetentionCapsules(vault, fabric, policy, workspaceId) {
|
|
256
257
|
// The caller must obtain this policy from an authoritative control-plane
|
|
257
258
|
// refresh. An expired policy pauses the queue instead of mutating it.
|
|
258
259
|
assertPolicy(policy);
|
|
259
260
|
let synced = 0;
|
|
260
261
|
let offset = 0;
|
|
262
|
+
let warnedPreviousDevice = false;
|
|
261
263
|
for (;;) {
|
|
262
264
|
const pending = await vault.listPendingCapsuleSyncs(1_000, offset);
|
|
263
265
|
if (pending.length === 0)
|
|
@@ -274,6 +276,15 @@ async function syncPendingRetentionCapsules(vault, fabric, policy, workspaceId)
|
|
|
274
276
|
vault.discardPendingCapsuleSync(item.trajectoryId, item.revision, 'capsule_integrity_failed');
|
|
275
277
|
continue;
|
|
276
278
|
}
|
|
279
|
+
if (item.capsule.organizationId === fabric.config.organizationId
|
|
280
|
+
&& item.capsule.deviceId !== fabric.config.deviceId) {
|
|
281
|
+
vault.discardPendingCapsuleSync(item.trajectoryId, item.revision, 'device_binding_changed');
|
|
282
|
+
if (!warnedPreviousDevice) {
|
|
283
|
+
process.stderr.write('Queued trajectory capsules from a previous device were preserved locally and excluded from upload. Recapture eligible provider sessions under the current device.\n');
|
|
284
|
+
warnedPreviousDevice = true;
|
|
285
|
+
}
|
|
286
|
+
continue;
|
|
287
|
+
}
|
|
277
288
|
// Policy expiry and signature failure pause the queue. Only a capsule
|
|
278
289
|
// mismatch under a still-current policy is an authoritative discard.
|
|
279
290
|
assertPolicy(policy);
|
|
@@ -2204,6 +2215,10 @@ async function capture(flags, batch = false) {
|
|
|
2204
2215
|
const fabric = flags.has('sync')
|
|
2205
2216
|
? await client()
|
|
2206
2217
|
: null;
|
|
2218
|
+
if (fabric && (fabric.config.organizationId !== device.organizationId
|
|
2219
|
+
|| fabric.config.deviceId !== device.deviceId)) {
|
|
2220
|
+
throw new Error('The enrolled device changed during evidence capture. Retry from the current device home.');
|
|
2221
|
+
}
|
|
2207
2222
|
if (fabric)
|
|
2208
2223
|
policy = await refreshVerifiedWorkspacePolicyForTransmission(policyPath, registered.workspaceId, fabric);
|
|
2209
2224
|
const vault = await LocalVault.open({
|
|
@@ -5361,6 +5376,42 @@ export async function run(argv) {
|
|
|
5361
5376
|
return USAGE;
|
|
5362
5377
|
if (flags.has('version') || command === 'version')
|
|
5363
5378
|
return { version: VERSION };
|
|
5379
|
+
if (command === 'demo' && ['connect', 'status'].includes(String(subcommand))) {
|
|
5380
|
+
const hqUrl = normalizeHqUrl(portalUrl(flags));
|
|
5381
|
+
const organizationId = required(flags, 'organization-id');
|
|
5382
|
+
const repositoryId = required(flags, 'repository-id');
|
|
5383
|
+
const normalizedRepository = required(flags, 'normalized-repository');
|
|
5384
|
+
const workspace = await realpath(String(flags.get('workspace') || '.'));
|
|
5385
|
+
const root = await gitValue(workspace, ['rev-parse', '--show-toplevel']);
|
|
5386
|
+
if (!root)
|
|
5387
|
+
throw new Error('Demo device setup must run inside the exact Git repository.');
|
|
5388
|
+
const remote = await gitValue(workspace, ['config', '--get', 'remote.origin.url']);
|
|
5389
|
+
if (!remote || normalizeGitRemoteIdentity(remote) !== normalizedRepository) {
|
|
5390
|
+
throw new Error('Local Git remote does not match the private Demo repository binding.');
|
|
5391
|
+
}
|
|
5392
|
+
if (flags.has('dry-run'))
|
|
5393
|
+
return { ok: true, stage: 'demo_device_plan',
|
|
5394
|
+
organizationId, repositoryId, normalizedRepository, workspaceVerified: true,
|
|
5395
|
+
repositoryPackageState: 'not_connected' };
|
|
5396
|
+
const grant = subcommand === 'connect' ? required(flags, 'grant') : null;
|
|
5397
|
+
const scope = {
|
|
5398
|
+
hqUrl, organizationId, repositoryId, normalizedRepository,
|
|
5399
|
+
installationId: await loadOrCreateInstallationId(), stateRoot: dharmaHome(),
|
|
5400
|
+
};
|
|
5401
|
+
const connected = subcommand === 'status'
|
|
5402
|
+
? await verifyDemoDevice(scope)
|
|
5403
|
+
: await connectDemoDevice({
|
|
5404
|
+
...scope, grant: grant,
|
|
5405
|
+
deviceName: String(flags.get('device-name') || `${process.env.USER || process.env.USERNAME || 'developer'} device`),
|
|
5406
|
+
platform: await platform(),
|
|
5407
|
+
}, { onApprovalRequired: async (url) => {
|
|
5408
|
+
if (!flags.has('no-browser'))
|
|
5409
|
+
await openVerificationUri(url);
|
|
5410
|
+
process.stderr.write(`Approve this exact Demo device in your signed-in Dharma session: ${url}\n`);
|
|
5411
|
+
} });
|
|
5412
|
+
const { configPath: _configPath, ...receipt } = connected;
|
|
5413
|
+
return receipt;
|
|
5414
|
+
}
|
|
5364
5415
|
if (command === 'bootstrap')
|
|
5365
5416
|
return bootstrap(flags);
|
|
5366
5417
|
if (command === 'onboard')
|