@aiwg/cli 2026.7.23 → 2026.7.25
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/src/artifacts/browser-export.js +2 -0
- package/dist/src/artifacts/index-builder.js +44 -8
- package/dist/src/artifacts/query-engine.js +1 -1
- package/dist/src/artifacts/types.js +1 -0
- package/dist/src/cli/handlers/index.js +5 -1
- package/dist/src/cli/handlers/setup-manifest.js +800 -0
- package/dist/src/cli/handlers/use.js +127 -17
- package/dist/src/config/aiwg-config.js +6 -2
- package/dist/src/extensions/commands/definitions.js +99 -0
- package/dist/src/serve/sandbox-registry.js +34 -0
- package/package.json +1 -1
|
@@ -576,7 +576,7 @@ function printSessionReloadNotice(provider) {
|
|
|
576
576
|
*
|
|
577
577
|
* @implements #609
|
|
578
578
|
*/
|
|
579
|
-
async function countDeployedArtifacts(target, paths) {
|
|
579
|
+
async function countDeployedArtifacts(target, paths, provider) {
|
|
580
580
|
const countMd = async (dir) => {
|
|
581
581
|
if (!dir)
|
|
582
582
|
return 0;
|
|
@@ -633,13 +633,11 @@ async function countDeployedArtifacts(target, paths) {
|
|
|
633
633
|
}
|
|
634
634
|
};
|
|
635
635
|
// Kernel skills deploy to the platform-native skills dir (always-loaded
|
|
636
|
-
// set) while standard skills sequester under <provider>/.aiwg/skills
|
|
637
|
-
//
|
|
638
|
-
//
|
|
639
|
-
//
|
|
640
|
-
const kernelSkillsPath =
|
|
641
|
-
? paths.skills.replace(/(^|\/)\.aiwg\/skills?$/, '$1skills')
|
|
642
|
-
: '';
|
|
636
|
+
// set) while standard skills may sequester under <provider>/.aiwg/skills.
|
|
637
|
+
// Count the provider-declared kernel path directly; deriving it by stripping
|
|
638
|
+
// `.aiwg/` from the standard path produced `.codex/skills` instead of
|
|
639
|
+
// Codex's native `.agents/skills` path (#766).
|
|
640
|
+
const kernelSkillsPath = provider ? getProviderKernelSkillsPath(provider) : '';
|
|
643
641
|
return {
|
|
644
642
|
agents: await countMd(paths.agents),
|
|
645
643
|
commands: await countMd(paths.commands),
|
|
@@ -785,6 +783,117 @@ async function countBundleSourceArtifacts(bundlePath) {
|
|
|
785
783
|
rules: await countMd('rules'),
|
|
786
784
|
};
|
|
787
785
|
}
|
|
786
|
+
async function fileExists(filePath) {
|
|
787
|
+
try {
|
|
788
|
+
await fs.access(filePath);
|
|
789
|
+
return true;
|
|
790
|
+
}
|
|
791
|
+
catch {
|
|
792
|
+
return false;
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
function resolveDeployPath(target, deployPath) {
|
|
796
|
+
return path.isAbsolute(deployPath) ? deployPath : path.join(target, deployPath);
|
|
797
|
+
}
|
|
798
|
+
async function listBundleMdStems(bundlePath, subdir) {
|
|
799
|
+
try {
|
|
800
|
+
const entries = await fs.readdir(path.join(bundlePath, subdir));
|
|
801
|
+
return entries
|
|
802
|
+
.filter(entry => entry.endsWith('.md'))
|
|
803
|
+
.map(entry => path.basename(entry, '.md'));
|
|
804
|
+
}
|
|
805
|
+
catch {
|
|
806
|
+
return [];
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
async function countDeployedBundleFiles(bundlePath, subdir, target, deployPath, extensions) {
|
|
810
|
+
if (!deployPath)
|
|
811
|
+
return 0;
|
|
812
|
+
const stems = await listBundleMdStems(bundlePath, subdir);
|
|
813
|
+
if (stems.length === 0)
|
|
814
|
+
return 0;
|
|
815
|
+
const destDir = resolveDeployPath(target, deployPath);
|
|
816
|
+
let count = 0;
|
|
817
|
+
for (const stem of stems) {
|
|
818
|
+
for (const ext of extensions) {
|
|
819
|
+
if (await fileExists(path.join(destDir, `${stem}${ext}`))) {
|
|
820
|
+
count++;
|
|
821
|
+
break;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
}
|
|
825
|
+
return count;
|
|
826
|
+
}
|
|
827
|
+
async function listBundleSkillNameCandidates(bundlePath) {
|
|
828
|
+
const skillsRoot = path.join(bundlePath, 'skills');
|
|
829
|
+
try {
|
|
830
|
+
const entries = await fs.readdir(skillsRoot, { withFileTypes: true });
|
|
831
|
+
const candidates = [];
|
|
832
|
+
for (const entry of entries) {
|
|
833
|
+
if (!entry.isDirectory())
|
|
834
|
+
continue;
|
|
835
|
+
const sourceName = entry.name;
|
|
836
|
+
const skillMd = path.join(skillsRoot, sourceName, 'SKILL.md');
|
|
837
|
+
let deployedName = sourceName;
|
|
838
|
+
try {
|
|
839
|
+
const content = await fs.readFile(skillMd, 'utf-8');
|
|
840
|
+
const match = content.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
841
|
+
if (match) {
|
|
842
|
+
const parsed = YAML.parse(match[1]);
|
|
843
|
+
if (typeof parsed?.name === 'string' && parsed.name.trim()) {
|
|
844
|
+
deployedName = parsed.name.trim();
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
}
|
|
848
|
+
catch {
|
|
849
|
+
// Missing or invalid frontmatter still leaves the source dir name as
|
|
850
|
+
// the best deployed-name approximation for providers that copy dirs.
|
|
851
|
+
}
|
|
852
|
+
candidates.push([...new Set([deployedName, sourceName])]);
|
|
853
|
+
}
|
|
854
|
+
return candidates;
|
|
855
|
+
}
|
|
856
|
+
catch {
|
|
857
|
+
return [];
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
async function countDeployedBundleSkills(bundlePath, target, provider, paths) {
|
|
861
|
+
const skillCandidates = await listBundleSkillNameCandidates(bundlePath);
|
|
862
|
+
if (skillCandidates.length === 0)
|
|
863
|
+
return 0;
|
|
864
|
+
const candidateDirs = [
|
|
865
|
+
paths.skills,
|
|
866
|
+
getProviderKernelSkillsPath(provider),
|
|
867
|
+
]
|
|
868
|
+
.filter(Boolean)
|
|
869
|
+
.map(dir => resolveDeployPath(target, dir));
|
|
870
|
+
const uniqueCandidateDirs = [...new Set(candidateDirs)];
|
|
871
|
+
let count = 0;
|
|
872
|
+
for (const names of skillCandidates) {
|
|
873
|
+
let found = false;
|
|
874
|
+
for (const dir of uniqueCandidateDirs) {
|
|
875
|
+
for (const name of names) {
|
|
876
|
+
if (!(await fileExists(path.join(dir, name, 'SKILL.md'))))
|
|
877
|
+
continue;
|
|
878
|
+
count++;
|
|
879
|
+
found = true;
|
|
880
|
+
break;
|
|
881
|
+
}
|
|
882
|
+
if (found)
|
|
883
|
+
break;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
return count;
|
|
887
|
+
}
|
|
888
|
+
async function countBundleDeployedArtifacts(bundlePath, target, provider) {
|
|
889
|
+
const paths = getProviderPaths(provider);
|
|
890
|
+
return {
|
|
891
|
+
agents: await countDeployedBundleFiles(bundlePath, 'agents', target, paths.agents, ['.md', '.toml']),
|
|
892
|
+
commands: await countDeployedBundleFiles(bundlePath, 'commands', target, paths.commands, ['.md']),
|
|
893
|
+
skills: await countDeployedBundleSkills(bundlePath, target, provider, paths),
|
|
894
|
+
rules: await countDeployedBundleFiles(bundlePath, 'rules', target, paths.rules, ['.md', '.mdc']),
|
|
895
|
+
};
|
|
896
|
+
}
|
|
788
897
|
/**
|
|
789
898
|
* Deploy a single project-local bundle to one provider via deploy-agents.mjs.
|
|
790
899
|
* Runs the same script and flags used for upstream addons, with the bundle
|
|
@@ -794,8 +903,8 @@ async function countBundleSourceArtifacts(bundlePath) {
|
|
|
794
903
|
*/
|
|
795
904
|
async function deployOneProjectLocalBundle(opts) {
|
|
796
905
|
const { bundle, ctx, frameworkRoot, provider, target, dryRun, verbose, quiet, modelArgs } = opts;
|
|
797
|
-
const
|
|
798
|
-
const artifactTotal =
|
|
906
|
+
const sourceCounts = await countBundleSourceArtifacts(bundle.artifactPath);
|
|
907
|
+
const artifactTotal = sourceCounts.agents + sourceCounts.commands + sourceCounts.skills + sourceCounts.rules;
|
|
799
908
|
let cliCommandCount = 0;
|
|
800
909
|
try {
|
|
801
910
|
const contribution = await loadCliCommandsContribution(bundle.artifactPath);
|
|
@@ -803,14 +912,14 @@ async function deployOneProjectLocalBundle(opts) {
|
|
|
803
912
|
}
|
|
804
913
|
catch (error) {
|
|
805
914
|
ui.warn(`Invalid CLI contribution for project-local '${bundle.id}': ${error.message}`);
|
|
806
|
-
return { exitCode: 1, counts };
|
|
915
|
+
return { exitCode: 1, counts: sourceCounts };
|
|
807
916
|
}
|
|
808
917
|
if (verbose || dryRun) {
|
|
809
|
-
ui.dim(` Artifacts: agents=${
|
|
918
|
+
ui.dim(` Artifacts: agents=${sourceCounts.agents} commands=${sourceCounts.commands} skills=${sourceCounts.skills} rules=${sourceCounts.rules} cli=${cliCommandCount}`);
|
|
810
919
|
}
|
|
811
920
|
if (artifactTotal === 0 && cliCommandCount === 0) {
|
|
812
921
|
ui.warn(`Project-local ${bundle.type} '${bundle.id}' has no deployable agents, commands, skills, rules, or CLI commands at ${bundle.artifactPath}`);
|
|
813
|
-
return { exitCode: 1, counts };
|
|
922
|
+
return { exitCode: 1, counts: sourceCounts };
|
|
814
923
|
}
|
|
815
924
|
let exitCode = 0;
|
|
816
925
|
if (artifactTotal > 0) {
|
|
@@ -868,8 +977,9 @@ async function deployOneProjectLocalBundle(opts) {
|
|
|
868
977
|
exitCode = 1;
|
|
869
978
|
}
|
|
870
979
|
}
|
|
871
|
-
|
|
872
|
-
|
|
980
|
+
const counts = exitCode === 0 && !dryRun
|
|
981
|
+
? await countBundleDeployedArtifacts(bundle.artifactPath, target, provider)
|
|
982
|
+
: sourceCounts;
|
|
873
983
|
void ctx;
|
|
874
984
|
return { exitCode, counts };
|
|
875
985
|
}
|
|
@@ -1865,7 +1975,7 @@ export class UseHandler {
|
|
|
1865
1975
|
provider: providerName,
|
|
1866
1976
|
cwd: target,
|
|
1867
1977
|
});
|
|
1868
|
-
const counts = await countDeployedArtifacts(target, paths);
|
|
1978
|
+
const counts = await countDeployedArtifacts(target, paths, providerName);
|
|
1869
1979
|
if (quiet) {
|
|
1870
1980
|
ui.blank();
|
|
1871
1981
|
if (counts.agents > 0)
|
|
@@ -2548,7 +2658,7 @@ export class UseHandler {
|
|
|
2548
2658
|
if (quiet) {
|
|
2549
2659
|
// Count deployed artifacts
|
|
2550
2660
|
const paths = getProviderPaths(provider);
|
|
2551
|
-
counts = await countDeployedArtifacts(target, paths);
|
|
2661
|
+
counts = await countDeployedArtifacts(target, paths, provider);
|
|
2552
2662
|
if (counts.agents > 0)
|
|
2553
2663
|
ui.deployCount('Agents', counts.agents);
|
|
2554
2664
|
if (counts.commands > 0)
|
|
@@ -12,7 +12,7 @@ import { readFile, writeFile, mkdir, access, readdir, rename, unlink } from 'fs/
|
|
|
12
12
|
import { createHash, randomBytes } from 'crypto';
|
|
13
13
|
import { resolve, join, isAbsolute } from 'path';
|
|
14
14
|
import { normalizeNamedCaptures } from '../artifacts/index-builder.js';
|
|
15
|
-
import { getProviderDefinition, PROVIDER_IDS, resolveProviderPathValue, } from '../providers/provider-definitions.js';
|
|
15
|
+
import { getProviderDefinition, getProviderKernelSkillPath, PROVIDER_IDS, resolveProviderPathValue, } from '../providers/provider-definitions.js';
|
|
16
16
|
import { validateAuthorization, } from '../policy/authorization.js';
|
|
17
17
|
import { projectAiwgPath, resolveProjectAiwgDir } from './project-artifacts.js';
|
|
18
18
|
import { defaultThreatAssessmentConfig, validateThreatAssessmentConfig, } from '../security/threat-assessment-config.js';
|
|
@@ -835,6 +835,7 @@ function getProviderDeployDirs(provider, projectDir) {
|
|
|
835
835
|
return {
|
|
836
836
|
agents: resolveProviderPathValue(artifacts.agents, projectDir),
|
|
837
837
|
skills: resolveProviderPathValue(artifacts.skills, projectDir),
|
|
838
|
+
kernelSkills: resolveProviderPathValue(getProviderKernelSkillPath(provider), projectDir),
|
|
838
839
|
commands: resolveProviderPathValue(artifacts.commands, projectDir),
|
|
839
840
|
rules: resolveProviderPathValue(artifacts.rules, projectDir),
|
|
840
841
|
};
|
|
@@ -877,7 +878,10 @@ export async function populateDeployedTo(config, projectDir) {
|
|
|
877
878
|
const counts = {
|
|
878
879
|
agents: await countDeployedInDir(projectDir, dirs.agents, 'md'),
|
|
879
880
|
commands: await countDeployedInDir(projectDir, dirs.commands, 'md'),
|
|
880
|
-
skills: await countDeployedInDir(projectDir, dirs.skills, 'dirs')
|
|
881
|
+
skills: (await countDeployedInDir(projectDir, dirs.skills, 'dirs')) +
|
|
882
|
+
(dirs.kernelSkills && dirs.kernelSkills !== dirs.skills
|
|
883
|
+
? await countDeployedInDir(projectDir, dirs.kernelSkills, 'dirs')
|
|
884
|
+
: 0),
|
|
881
885
|
rules: await countDeployedInDir(projectDir, dirs.rules, 'md'),
|
|
882
886
|
};
|
|
883
887
|
// Only populate if at least one artifact type is present
|
|
@@ -593,6 +593,102 @@ export const setupCommand = {
|
|
|
593
593
|
},
|
|
594
594
|
},
|
|
595
595
|
};
|
|
596
|
+
export const setupGenerateCommand = {
|
|
597
|
+
id: 'setup-generate',
|
|
598
|
+
type: 'skill',
|
|
599
|
+
name: 'Setup Generate',
|
|
600
|
+
description: 'Generate starter setup.aiwg.io/v1 SetupManifest assets for agentic installer automation',
|
|
601
|
+
version: '1.0.0',
|
|
602
|
+
capabilities: ['cli', 'project', 'setup', 'setup-manifest', 'agentic-installer', 'generation', 'automation'],
|
|
603
|
+
keywords: ['setup-generate', 'setup generate', 'SetupManifest', 'setup.aiwg.io/v1', 'agentic-installer', 'manifest generation', 'starter manifest'],
|
|
604
|
+
category: 'project',
|
|
605
|
+
platforms: {
|
|
606
|
+
claude: 'full',
|
|
607
|
+
generic: 'full',
|
|
608
|
+
},
|
|
609
|
+
deployment: {
|
|
610
|
+
pathTemplate: '.{platform}/commands/{id}.md',
|
|
611
|
+
core: true,
|
|
612
|
+
},
|
|
613
|
+
metadata: {
|
|
614
|
+
type: 'skill',
|
|
615
|
+
triggerPhrases: [
|
|
616
|
+
'generate setup manifest',
|
|
617
|
+
'create setup.manifest.yaml',
|
|
618
|
+
'setup-generate',
|
|
619
|
+
'scaffold installer manifest',
|
|
620
|
+
],
|
|
621
|
+
commandHint: {
|
|
622
|
+
template: 'utility',
|
|
623
|
+
argumentHint: '[--output <path>] [--name <name>] [--type user|developer|ci] [--platform <os>] [--force] [--json]',
|
|
624
|
+
allowedTools: ['Read', 'Write', 'Bash'],
|
|
625
|
+
},
|
|
626
|
+
},
|
|
627
|
+
};
|
|
628
|
+
export const setupValidateCommand = {
|
|
629
|
+
id: 'setup-validate',
|
|
630
|
+
type: 'skill',
|
|
631
|
+
name: 'Setup Validate',
|
|
632
|
+
description: 'Validate setup.aiwg.io/v1 SetupManifest files against the canonical schema and installer consistency checks',
|
|
633
|
+
version: '1.0.0',
|
|
634
|
+
capabilities: ['cli', 'project', 'setup', 'setup-manifest', 'agentic-installer', 'validation', 'schema'],
|
|
635
|
+
keywords: ['setup-validate', 'setup validate', 'SetupManifest', 'setup.aiwg.io/v1', 'agentic-installer', 'manifest validation', 'schema validation', 'installer consistency'],
|
|
636
|
+
category: 'project',
|
|
637
|
+
platforms: {
|
|
638
|
+
claude: 'full',
|
|
639
|
+
generic: 'full',
|
|
640
|
+
},
|
|
641
|
+
deployment: {
|
|
642
|
+
pathTemplate: '.{platform}/commands/{id}.md',
|
|
643
|
+
core: true,
|
|
644
|
+
},
|
|
645
|
+
metadata: {
|
|
646
|
+
type: 'skill',
|
|
647
|
+
triggerPhrases: [
|
|
648
|
+
'validate setup manifest',
|
|
649
|
+
'check setup.manifest.yaml',
|
|
650
|
+
'setup-validate',
|
|
651
|
+
'lint installer manifest',
|
|
652
|
+
],
|
|
653
|
+
commandHint: {
|
|
654
|
+
template: 'utility',
|
|
655
|
+
argumentHint: '[manifest-path] [--manifest <path>] [--strict] [--fix] [--json]',
|
|
656
|
+
allowedTools: ['Read', 'Bash'],
|
|
657
|
+
},
|
|
658
|
+
},
|
|
659
|
+
};
|
|
660
|
+
export const setupRunCommand = {
|
|
661
|
+
id: 'setup-run',
|
|
662
|
+
type: 'skill',
|
|
663
|
+
name: 'Setup Run',
|
|
664
|
+
description: 'Validate and execute setup.aiwg.io/v1 SetupManifest files with installer safety gates',
|
|
665
|
+
version: '1.0.0',
|
|
666
|
+
capabilities: ['cli', 'project', 'setup', 'setup-manifest', 'agentic-installer', 'installer', 'dry-run'],
|
|
667
|
+
keywords: ['setup-run', 'setup run', 'SetupManifest', 'setup.aiwg.io/v1', 'agentic-installer', 'installer runner', 'dry run', 'recovery', 'params'],
|
|
668
|
+
category: 'project',
|
|
669
|
+
platforms: {
|
|
670
|
+
claude: 'full',
|
|
671
|
+
generic: 'full',
|
|
672
|
+
},
|
|
673
|
+
deployment: {
|
|
674
|
+
pathTemplate: '.{platform}/commands/{id}.md',
|
|
675
|
+
core: true,
|
|
676
|
+
},
|
|
677
|
+
metadata: {
|
|
678
|
+
type: 'skill',
|
|
679
|
+
triggerPhrases: [
|
|
680
|
+
'run setup manifest',
|
|
681
|
+
'execute installer manifest',
|
|
682
|
+
'setup-run',
|
|
683
|
+
'run dev setup',
|
|
684
|
+
],
|
|
685
|
+
commandHint: {
|
|
686
|
+
template: 'utility',
|
|
687
|
+
argumentHint: '[manifest-path] [--manifest <path>] [--dry-run] [--platform <os>] [--params-file <path>] [--param KEY=VALUE] [--step <id>] [--skip <ids>] [--yes]',
|
|
688
|
+
allowedTools: ['Read', 'Bash'],
|
|
689
|
+
},
|
|
690
|
+
},
|
|
691
|
+
};
|
|
596
692
|
export const issueCommand = {
|
|
597
693
|
id: 'issue',
|
|
598
694
|
type: 'skill',
|
|
@@ -3362,6 +3458,9 @@ export const commandDefinitions = [
|
|
|
3362
3458
|
newCommand,
|
|
3363
3459
|
initCommand,
|
|
3364
3460
|
setupCommand,
|
|
3461
|
+
setupGenerateCommand,
|
|
3462
|
+
setupValidateCommand,
|
|
3463
|
+
setupRunCommand,
|
|
3365
3464
|
issueCommand,
|
|
3366
3465
|
issueAuditCommand,
|
|
3367
3466
|
addressIssuesCommand,
|
|
@@ -241,6 +241,35 @@ export function normalizeSandboxEvent(raw) {
|
|
|
241
241
|
* Matches the sandbox's 5 s retry interval — suppressess flicker on rapid restarts.
|
|
242
242
|
*/
|
|
243
243
|
const DEBOUNCE_MS = 5_000;
|
|
244
|
+
function safeTrustRef(value) {
|
|
245
|
+
const ref = typeof value === 'string' ? value.trim() : '';
|
|
246
|
+
if (!ref)
|
|
247
|
+
return undefined;
|
|
248
|
+
if (/-----BEGIN|PRIVATE KEY|TOKEN|SECRET|PASSWORD|[\r\n]/i.test(ref))
|
|
249
|
+
return '[redacted]';
|
|
250
|
+
return ref.slice(0, 160);
|
|
251
|
+
}
|
|
252
|
+
function sanitizeTrustPosture(posture) {
|
|
253
|
+
if (!posture || typeof posture !== 'object')
|
|
254
|
+
return undefined;
|
|
255
|
+
const status = ['secure', 'degraded', 'disabled', 'unknown'].includes(String(posture.status))
|
|
256
|
+
? posture.status
|
|
257
|
+
: 'unknown';
|
|
258
|
+
return {
|
|
259
|
+
status,
|
|
260
|
+
mode: safeTrustRef(posture.mode),
|
|
261
|
+
ca_provider_ref: safeTrustRef(posture.ca_provider_ref),
|
|
262
|
+
trust_bundle_ref: safeTrustRef(posture.trust_bundle_ref),
|
|
263
|
+
client_identity_ref: safeTrustRef(posture.client_identity_ref),
|
|
264
|
+
rotation_state: safeTrustRef(posture.rotation_state),
|
|
265
|
+
expires_at: safeTrustRef(posture.expires_at),
|
|
266
|
+
trust_bundle_fresh: posture.trust_bundle_fresh,
|
|
267
|
+
missing_required_material: Array.isArray(posture.missing_required_material)
|
|
268
|
+
? posture.missing_required_material.map((item) => safeTrustRef(item)).filter((item) => Boolean(item))
|
|
269
|
+
: undefined,
|
|
270
|
+
recovery: safeTrustRef(posture.recovery),
|
|
271
|
+
};
|
|
272
|
+
}
|
|
244
273
|
export class SandboxRegistry {
|
|
245
274
|
sandboxes = new Map();
|
|
246
275
|
hitlRequests = new Map();
|
|
@@ -336,6 +365,9 @@ export class SandboxRegistry {
|
|
|
336
365
|
if (req.ws_capabilities) {
|
|
337
366
|
existing.wsCapabilities = req.ws_capabilities;
|
|
338
367
|
}
|
|
368
|
+
if (req.trust_posture) {
|
|
369
|
+
existing.trustPosture = sanitizeTrustPosture(req.trust_posture);
|
|
370
|
+
}
|
|
339
371
|
this.lastRegistrationTime.set(instanceId, now);
|
|
340
372
|
return { sandbox_id: existingId, token: existing.token };
|
|
341
373
|
}
|
|
@@ -370,6 +402,7 @@ export class SandboxRegistry {
|
|
|
370
402
|
agents: new Map(),
|
|
371
403
|
sandboxInventory,
|
|
372
404
|
wsCapabilities: req.ws_capabilities,
|
|
405
|
+
trustPosture: sanitizeTrustPosture(req.trust_posture),
|
|
373
406
|
};
|
|
374
407
|
this.sandboxes.set(id, registration);
|
|
375
408
|
if (instanceId) {
|
|
@@ -825,6 +858,7 @@ function toSummary(s) {
|
|
|
825
858
|
agents: [...s.agents.values()],
|
|
826
859
|
sandboxInventory: s.sandboxInventory,
|
|
827
860
|
wsCapabilities: s.wsCapabilities,
|
|
861
|
+
trustPosture: s.trustPosture,
|
|
828
862
|
};
|
|
829
863
|
}
|
|
830
864
|
// Singleton instance
|