@aifabrix/builder 2.54.1 → 2.55.0
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/README.md +8 -0
- package/lib/agent-kit/apply-ops.js +82 -0
- package/lib/agent-kit/checksums.js +28 -0
- package/lib/agent-kit/classify.js +113 -0
- package/lib/agent-kit/claude-shim.js +61 -0
- package/lib/agent-kit/constants.js +55 -0
- package/lib/agent-kit/file-list.js +103 -0
- package/lib/agent-kit/host-approve.js +130 -0
- package/lib/agent-kit/hosting/github.js +63 -0
- package/lib/agent-kit/hosts.js +71 -0
- package/lib/agent-kit/init.js +319 -0
- package/lib/agent-kit/kit-root.js +17 -0
- package/lib/agent-kit/managed-section.js +79 -0
- package/lib/agent-kit/package-load.js +45 -0
- package/lib/agent-kit/plan-ops.js +69 -0
- package/lib/agent-kit/remote-prompts.js +239 -0
- package/lib/agent-kit/render-host-markdown.js +40 -0
- package/lib/agent-kit/repo-guard.js +47 -0
- package/lib/agent-kit/report.js +107 -0
- package/lib/agent-kit/run.js +82 -0
- package/lib/agent-kit/scm/git.js +122 -0
- package/lib/agent-kit/state-file.js +83 -0
- package/lib/agent-kit/status.js +50 -0
- package/lib/agent-kit/v1-detect.js +81 -0
- package/lib/agent-kit/validate-kit.js +87 -0
- package/lib/agent-kit/workspace-name.js +40 -0
- package/lib/agent-kit/workspace-skeleton.js +103 -0
- package/lib/api/role-assistant-test-pack.api.js +86 -0
- package/lib/api/work-search.api.js +31 -4
- package/lib/api/work.api.js +19 -12
- package/lib/app/list-external-systems.js +2 -1
- package/lib/app/show-display.js +33 -6
- package/lib/app/show.js +25 -2
- package/lib/channels/add-channel.js +1 -0
- package/lib/channels/approval-guides/claude.js +2 -2
- package/lib/channels/channel-add-failure.js +1 -0
- package/lib/channels/channel-add-remaining.js +15 -9
- package/lib/channels/channel-definition-status.js +115 -0
- package/lib/channels/channel-description.js +2 -1
- package/lib/channels/channel-install-envelope.js +4 -2
- package/lib/channels/channel-integration-generator.js +2 -0
- package/lib/channels/channel-runtime-resolver.js +14 -0
- package/lib/channels/channel-targets.js +31 -5
- package/lib/channels/claude-setup-values.js +4 -1
- package/lib/channels/slack-channel-add.js +59 -6
- package/lib/channels/slack-mcp-callback.js +51 -0
- package/lib/channels/slack-mcp-runtime.js +156 -0
- package/lib/channels/slack-provisioning/install-cli.js +14 -2
- package/lib/channels/slack-provisioning/with-curl-on-path.js +6 -1
- package/lib/cli/index.js +4 -0
- package/lib/cli/setup-certification-commands.js +2 -2
- package/lib/cli/setup-certification.help.js +3 -1
- package/lib/commands/agent-kit-help.js +79 -0
- package/lib/commands/agent-kit.js +346 -0
- package/lib/commands/channel-add-help.js +5 -5
- package/lib/commands/datasource-capability-relate-cli.js +5 -4
- package/lib/commands/repair-auth-apply.js +1 -1
- package/lib/commands/repair-datasource-key-skip.js +39 -0
- package/lib/commands/repair-datasource-keys.js +24 -12
- package/lib/commands/repair-rbac.js +16 -10
- package/lib/commands/role-assistant-copy-output.js +61 -0
- package/lib/commands/role-assistant-copy.js +155 -0
- package/lib/commands/role-assistant-test-output.js +8 -9
- package/lib/commands/role-assistant-test-result-rows.js +42 -0
- package/lib/commands/role-assistant.js +117 -48
- package/lib/commands/search.js +143 -0
- package/lib/commands/test-trust-external.js +7 -5
- package/lib/commands/upload-sidecar-followups.js +4 -1
- package/lib/commands/verify-operations-skip-e2e.js +131 -0
- package/lib/commands/verify-operations-step-plan.js +6 -33
- package/lib/commands/verify-operations-steps.js +3 -1
- package/lib/datasource/capability/relate-operations.js +28 -10
- package/lib/datasource/capability/run-capability-relate.js +48 -25
- package/lib/datasource/datasource-identifier.js +13 -5
- package/lib/deployment/deployer-poll-run.js +117 -35
- package/lib/external-system/deploy-dataplane-published.js +70 -0
- package/lib/external-system/deploy.js +12 -2
- package/lib/external-system/download-role-assistant.js +41 -15
- package/lib/external-system/download.js +7 -1
- package/lib/generator/wizard-datasource-key.js +54 -0
- package/lib/generator/wizard.js +55 -54
- package/lib/integration-definition/apply-datasource-keys.js +75 -0
- package/lib/integration-definition/apply-relationships.js +195 -0
- package/lib/integration-definition/apply-static-enterprise.js +229 -0
- package/lib/integration-definition/apply-system-file.js +71 -0
- package/lib/integration-definition/apply-test-endpoint.js +89 -0
- package/lib/integration-definition/apply-viewpoint-defaults.js +157 -0
- package/lib/integration-definition/apply.js +78 -59
- package/lib/integration-definition/enrich-openapi-operations.js +36 -10
- package/lib/integration-definition/enrich-openapi-pick.js +87 -0
- package/lib/lifecycle/role-assistant-governance.js +56 -21
- package/lib/programmatic/capability-registry.js +1 -0
- package/lib/programmatic/index.js +2 -0
- package/lib/programmatic/openapi-apply-result-schemas.js +8 -0
- package/lib/programmatic/openapi-channel-install-schemas.js +4 -1
- package/lib/programmatic/openapi-component-schemas.js +1 -0
- package/lib/programmatic/openapi-descriptions.js +9 -3
- package/lib/programmatic/openapi-envelope-examples.js +7 -0
- package/lib/programmatic/openapi-operation-bindings.js +5 -0
- package/lib/programmatic/openapi-request-schemas.js +5 -0
- package/lib/programmatic/openapi-schema-descriptions-channel.js +8 -5
- package/lib/programmatic/openapi-schema-descriptions-operations.js +19 -0
- package/lib/programmatic/openapi-spec.js +1 -0
- package/lib/programmatic/request-timeout.js +3 -0
- package/lib/programmatic/route-handler-map.js +7 -0
- package/lib/programmatic/run-channel-catalog.js +50 -8
- package/lib/programmatic/run-channel-install-options.js +5 -1
- package/lib/programmatic/run-download.js +41 -0
- package/lib/protection/auth-context.js +3 -1
- package/lib/protection/protection-display.js +3 -2
- package/lib/protection/report-exit.js +50 -0
- package/lib/protection/run-commands.js +2 -0
- package/lib/role-assistant/package-validate.js +175 -0
- package/lib/role-assistant/test-case-assertion-row.js +36 -0
- package/lib/role-assistant/test-case-copy-bind.js +77 -0
- package/lib/role-assistant/test-case-copy-expected.js +127 -0
- package/lib/role-assistant/test-case-copy-from-work.js +90 -0
- package/lib/role-assistant/test-case-copy-interactions.js +67 -0
- package/lib/role-assistant/test-case-copy.js +119 -0
- package/lib/role-assistant/test-case-expected-catalog.js +135 -0
- package/lib/role-assistant/test-case-validate.js +88 -0
- package/lib/role-assistant/test-cases-bid.js +117 -4
- package/lib/role-assistant/test-cases-evaluate.js +137 -30
- package/lib/role-assistant/test-cases-honesty.js +155 -6
- package/lib/role-assistant/test-cases-lifecycle.js +291 -0
- package/lib/role-assistant/test-cases-search-graph.js +122 -0
- package/lib/role-assistant/test-cases-search.js +20 -2
- package/lib/role-assistant/test-cases.js +34 -168
- package/lib/role-assistant/test-pack-map.js +180 -0
- package/lib/role-assistant/test-pack-sync.js +187 -0
- package/lib/role-assistant/test-runner-debug.js +54 -0
- package/lib/role-assistant/test-runner-respond-body.js +36 -0
- package/lib/role-assistant/test-runner-search.js +20 -5
- package/lib/role-assistant/test-runner-start-payload.js +63 -10
- package/lib/role-assistant/test-runner-workhub-answers.js +45 -16
- package/lib/role-assistant/test-runner-workhub.js +45 -21
- package/lib/role-assistant/test-runner.js +50 -10
- package/lib/schema/external-datasource.schema.json +36 -5
- package/lib/schema/external-system.schema.json +20 -2
- package/lib/schema/role-assistant-test-case.schema.json +408 -0
- package/lib/search/dataplane-context.js +23 -0
- package/lib/search/search-args.js +211 -0
- package/lib/search/search-display.js +238 -0
- package/lib/search/search-errors.js +50 -0
- package/lib/search/search-prompts.js +119 -0
- package/lib/search/search-roles.js +85 -0
- package/lib/search/search-run.js +241 -0
- package/lib/search/search-skills.js +198 -0
- package/lib/utils/authentication-slot-show.js +153 -0
- package/lib/utils/credential-display.js +43 -1
- package/lib/utils/external-system-readiness-compact-blocks.js +5 -1
- package/lib/utils/external-system-readiness-compact-display.js +30 -1
- package/lib/utils/external-system-validators.js +2 -1
- package/lib/utils/help-builder.js +3 -1
- package/lib/utils/schema-loader.js +37 -0
- package/lib/validation/validate-external-file.js +5 -1
- package/lib/validation/validate.js +3 -2
- package/package.json +1 -1
- package/templates/agent-kit/adapters/claude/nested.CLAUDE.md +1 -0
- package/templates/agent-kit/adapters/claude/root.CLAUDE.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-0-plan.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-1-validate.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-2-build.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-3-push.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-1-validate.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-2-build.md +5 -0
- package/templates/agent-kit/adapters/cursor/commands/cust-biz-3-prove.md +5 -0
- package/templates/agent-kit/agent-kit.yaml +45 -0
- package/templates/agent-kit/instructions/AGENTKIT.md +83 -0
- package/templates/agent-kit/instructions/integration.AGENTS.md +25 -0
- package/templates/agent-kit/instructions/role-assistant.AGENTS.md +22 -0
- package/templates/agent-kit/instructions/root.AGENTS.md +37 -0
- package/templates/agent-kit/parity-inventory.yaml +188 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/SKILL.md +58 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/contract-checklist.md +40 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/delivery-gates.md +54 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/references/production-safety.md +35 -0
- package/templates/agent-kit/skills/aifabrix-connected-system/scripts/reserved-system-key.js +19 -0
- package/templates/agent-kit/skills/aifabrix-plan/SKILL.md +51 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/challenge-checklist.md +108 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/interaction.md +34 -0
- package/templates/agent-kit/skills/aifabrix-plan/references/plan-template.md +182 -0
- package/templates/agent-kit/skills/aifabrix-prove/SKILL.md +50 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/demo-template.md +65 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/evidence-lifecycle.md +68 -0
- package/templates/agent-kit/skills/aifabrix-prove/references/learning-template.md +66 -0
- package/templates/agent-kit/skills/aifabrix-role-assistant/SKILL.md +42 -0
- package/templates/agent-kit/skills/aifabrix-role-assistant/references/package-boundary.md +21 -0
- package/templates/agent-kit/skills/shared/hosts.md +78 -0
- package/templates/agent-kit/workspace/.cursor/plans/README.md +22 -0
- package/templates/agent-kit/workspace/LICENSE.mit +21 -0
- package/templates/agent-kit/workspace/README.md +89 -0
- package/templates/applications/builder-api/Dockerfile +3 -1
- package/templates/applications/dataplane/application.yaml +2 -2
- package/templates/applications/dataplane/env.template +1 -1
- package/templates/applications/dataplane/rbac.yaml +28 -0
- package/templates/applications/keycloak/env.template +3 -3
- package/templates/applications/miso-controller/application.yaml +1 -1
- package/templates/applications/miso-controller/env.template +8 -9
- package/templates/channels/claude/TROUBLESHOOTING.md +3 -0
- package/templates/channels/claude/channel.json +1 -1
- package/templates/channels/claude/install.template.md.hbs +1 -0
- package/templates/channels/claude/integration/claude-system.json +1 -1
- package/templates/channels/slack/channel.json +11 -0
- package/templates/channels/slack/install.template.md.hbs +9 -0
- package/templates/channels/slack/integration/slack-system.json +11 -0
- package/templates/channels/slack/manifest.template.json.hbs +6 -3
- package/templates/channels/teams-bot/channel.json +1 -0
- package/templates/python/docker-compose.hbs +14 -0
- package/templates/typescript/docker-compose.hbs +14 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Installed Agent Kit state file.
|
|
3
|
+
* @fileoverview Read/write .aifabrix/agent-kit.yaml
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const yaml = require('js-yaml');
|
|
10
|
+
const fs = require('../internal/fs-real-sync');
|
|
11
|
+
const { STATE_RELATIVE, SECTION_ID } = require('./constants');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {string} repoRoot
|
|
15
|
+
* @returns {string}
|
|
16
|
+
*/
|
|
17
|
+
function statePath(repoRoot) {
|
|
18
|
+
return path.join(repoRoot, STATE_RELATIVE);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {string} repoRoot
|
|
23
|
+
* @returns {object|null}
|
|
24
|
+
*/
|
|
25
|
+
function loadState(repoRoot) {
|
|
26
|
+
const filePath = statePath(repoRoot);
|
|
27
|
+
if (!fs.existsSync(filePath)) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
const parsed = yaml.load(fs.readFileSync(filePath, 'utf8'));
|
|
31
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return parsed;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @param {object} kit
|
|
39
|
+
* @param {string[]} hosts
|
|
40
|
+
* @param {object[]} ops
|
|
41
|
+
* @param {string} builderVersion
|
|
42
|
+
* @returns {object}
|
|
43
|
+
*/
|
|
44
|
+
function buildStateDocument(kit, hosts, ops, builderVersion) {
|
|
45
|
+
const managedFiles = [];
|
|
46
|
+
for (const op of ops) {
|
|
47
|
+
if (op.action === 'delete' || op.action === 'retain' || op.action === 'conflict') {
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
if (op.action === 'skip' && op.fileState === 'MISSING') {
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
if (!op.targetRel || op.mode === 'obsolete' || op.mode === 'if-missing') {
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const row = { path: op.targetRel, sha256: op.sourceHash };
|
|
57
|
+
if (op.mode === 'managed-section') {
|
|
58
|
+
row.section = SECTION_ID;
|
|
59
|
+
}
|
|
60
|
+
managedFiles.push(row);
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
schemaVersion: '1',
|
|
64
|
+
kitVersion: kit.manifest.kitVersion,
|
|
65
|
+
builderVersion,
|
|
66
|
+
installedAt: new Date().toISOString(),
|
|
67
|
+
hosts,
|
|
68
|
+
managedFiles
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @param {string} repoRoot
|
|
74
|
+
* @param {object} doc
|
|
75
|
+
* @returns {void}
|
|
76
|
+
*/
|
|
77
|
+
function writeState(repoRoot, doc) {
|
|
78
|
+
const filePath = statePath(repoRoot);
|
|
79
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
80
|
+
fs.writeFileSync(filePath, yaml.dump(doc, { lineWidth: 120, noRefs: true, sortKeys: false }), 'utf8');
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
module.exports = { statePath, loadState, buildStateDocument, writeState };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Kit status.
|
|
3
|
+
* @fileoverview Classify installed files without writing
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const { getCliVersion } = require('../utils/installation-log-core');
|
|
9
|
+
const { resolveGitRoot } = require('./repo-guard');
|
|
10
|
+
const { loadKitPackage } = require('./package-load');
|
|
11
|
+
const { listManagedTargets } = require('./file-list');
|
|
12
|
+
const { classifyItems } = require('./classify');
|
|
13
|
+
const { detectV1, listObsoleteV1Items } = require('./v1-detect');
|
|
14
|
+
const { loadState } = require('./state-file');
|
|
15
|
+
const { ACTION } = require('./constants');
|
|
16
|
+
const { kitStateName, buildJsonReport } = require('./report');
|
|
17
|
+
const { ALL_HOSTS } = require('./hosts');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {object} options
|
|
21
|
+
* @returns {object}
|
|
22
|
+
*/
|
|
23
|
+
function runStatus(options) {
|
|
24
|
+
const repoRoot = resolveGitRoot(options.cwd || process.cwd());
|
|
25
|
+
const kit = loadKitPackage();
|
|
26
|
+
const state = loadState(repoRoot);
|
|
27
|
+
const includeShims = detectV1(repoRoot);
|
|
28
|
+
const hosts = (state && state.hosts) || ALL_HOSTS.slice();
|
|
29
|
+
const includeClaude = hosts.includes('claude');
|
|
30
|
+
const items = listManagedTargets(kit, repoRoot, {
|
|
31
|
+
includeShims: includeShims && hosts.includes('cursor'),
|
|
32
|
+
includeClaude
|
|
33
|
+
});
|
|
34
|
+
classifyItems(items, state, hosts);
|
|
35
|
+
items.push(...listObsoleteV1Items(kit, repoRoot, new Set(items.map((item) => item.targetRel))));
|
|
36
|
+
const ops = items.map((item) => ({ ...item, action: ACTION.SKIP }));
|
|
37
|
+
const kitState = kitStateName(state, kit, ops);
|
|
38
|
+
return buildJsonReport({
|
|
39
|
+
command: 'status',
|
|
40
|
+
kit,
|
|
41
|
+
state,
|
|
42
|
+
hosts,
|
|
43
|
+
ops,
|
|
44
|
+
dryRun: true,
|
|
45
|
+
builderVersion: getCliVersion(),
|
|
46
|
+
kitState
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = { runStatus };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect v1 Agent Kit files in a customer repository.
|
|
3
|
+
* @fileoverview Name + hash detection for migration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('../internal/fs-real-sync');
|
|
10
|
+
const { V1_MARKERS, FILE_STATE } = require('./constants');
|
|
11
|
+
const { sha256File } = require('./checksums');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {string} repoRoot
|
|
15
|
+
* @returns {boolean}
|
|
16
|
+
*/
|
|
17
|
+
function detectV1(repoRoot) {
|
|
18
|
+
return V1_MARKERS.some((rel) => fs.existsSync(path.join(repoRoot, rel)));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {object} kit
|
|
23
|
+
* @param {string} repoRoot
|
|
24
|
+
* @param {Set<string>} managedRels
|
|
25
|
+
* @returns {object[]}
|
|
26
|
+
*/
|
|
27
|
+
function listObsoleteV1Items(kit, repoRoot, managedRels) {
|
|
28
|
+
const rows = (kit.inventory && kit.inventory.v1Files) || [];
|
|
29
|
+
const items = [];
|
|
30
|
+
for (const row of rows) {
|
|
31
|
+
if (row.disposition === 'shim' || !row.installedPath) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
if (managedRels.has(row.installedPath)) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
const targetAbs = path.join(repoRoot, row.installedPath);
|
|
38
|
+
if (!fs.existsSync(targetAbs)) {
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
const hash = sha256File(targetAbs);
|
|
42
|
+
const unchanged = hash === row.sha256;
|
|
43
|
+
items.push({
|
|
44
|
+
sourceAbs: null,
|
|
45
|
+
targetRel: row.installedPath,
|
|
46
|
+
targetAbs,
|
|
47
|
+
mode: 'obsolete',
|
|
48
|
+
sourceHash: row.sha256,
|
|
49
|
+
currentHash: hash,
|
|
50
|
+
fileState: unchanged
|
|
51
|
+
? FILE_STATE.OBSOLETE_UNCHANGED_MANAGED
|
|
52
|
+
: FILE_STATE.OBSOLETE_MODIFIED_MANAGED,
|
|
53
|
+
v1Owner: row.owner
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return items;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Replace unmodified v1 command files with thin shims on install.
|
|
61
|
+
* @param {object[]} items
|
|
62
|
+
* @param {object} kit
|
|
63
|
+
* @returns {void}
|
|
64
|
+
*/
|
|
65
|
+
function markV1ShimReplacements(items, kit) {
|
|
66
|
+
const byPath = new Map();
|
|
67
|
+
for (const row of (kit.inventory && kit.inventory.v1Files) || []) {
|
|
68
|
+
byPath.set(row.installedPath, row);
|
|
69
|
+
}
|
|
70
|
+
for (const item of items) {
|
|
71
|
+
if (!item.optional || !item.currentHash) {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
const row = byPath.get(item.targetRel);
|
|
75
|
+
if (row && row.disposition === 'shim' && item.currentHash === row.sha256) {
|
|
76
|
+
item.replaceOnInstall = true;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
module.exports = { detectV1, listObsoleteV1Items, markV1ShimReplacements };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validate bundled Agent Kit package and optional install.
|
|
3
|
+
* @fileoverview Schema, paths, skill names, installed conflicts
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('../internal/fs-real-sync');
|
|
10
|
+
const { loadKitPackage } = require('./package-load');
|
|
11
|
+
const { listTreeFiles } = require('./file-list');
|
|
12
|
+
const { runStatus } = require('./status');
|
|
13
|
+
const { KIT_STATE } = require('./constants');
|
|
14
|
+
|
|
15
|
+
const FORBIDDEN_RE = /@[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,}|kv:\/\/[^\s]+\/[A-Za-z0-9+/]{12,}|\/home\/[a-z0-9]+\/(?!dev)/i;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @param {object} kit
|
|
19
|
+
* @returns {string[]}
|
|
20
|
+
*/
|
|
21
|
+
function collectPackageErrors(kit) {
|
|
22
|
+
const errors = [];
|
|
23
|
+
const names = kit.manifest.skills || [];
|
|
24
|
+
if (new Set(names).size !== names.length) {
|
|
25
|
+
errors.push('Duplicate skill name in agent-kit.yaml.');
|
|
26
|
+
}
|
|
27
|
+
for (const name of names) {
|
|
28
|
+
const skillMd = path.join(kit.root, 'skills', name, 'SKILL.md');
|
|
29
|
+
if (!fs.existsSync(skillMd)) {
|
|
30
|
+
errors.push(`Missing SKILL.md for ${name}.`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
for (const spec of [...(kit.manifest.managed || []), ...(kit.manifest.optional || [])]) {
|
|
34
|
+
const sourceAbs = path.join(kit.root, spec.source);
|
|
35
|
+
if (!fs.existsSync(sourceAbs)) {
|
|
36
|
+
errors.push(`Managed source missing: ${spec.source}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return errors;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {object} kit
|
|
44
|
+
* @returns {string[]}
|
|
45
|
+
*/
|
|
46
|
+
function collectContentErrors(kit) {
|
|
47
|
+
const errors = [];
|
|
48
|
+
for (const file of listTreeFiles(kit.root, '')) {
|
|
49
|
+
if (file.rel === 'parity-inventory.yaml') {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
const text = fs.readFileSync(file.abs, 'utf8');
|
|
53
|
+
if (FORBIDDEN_RE.test(text)) {
|
|
54
|
+
errors.push(`Forbidden customer/secret pattern in ${file.rel}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return errors;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* @param {object} [options]
|
|
62
|
+
* @returns {object}
|
|
63
|
+
*/
|
|
64
|
+
function runValidate(options = {}) {
|
|
65
|
+
const kit = loadKitPackage();
|
|
66
|
+
const errors = [...collectPackageErrors(kit), ...collectContentErrors(kit)];
|
|
67
|
+
let install = null;
|
|
68
|
+
try {
|
|
69
|
+
install = runStatus(options);
|
|
70
|
+
} catch (error) {
|
|
71
|
+
if (!String(error.message || '').includes('git repository')) {
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (install && install.state === KIT_STATE.CONFLICTS) {
|
|
76
|
+
errors.push(`Install conflicts: ${install.conflicts.join(', ')}`);
|
|
77
|
+
}
|
|
78
|
+
return {
|
|
79
|
+
success: errors.length === 0,
|
|
80
|
+
command: 'validate',
|
|
81
|
+
kitVersion: kit.manifest.kitVersion,
|
|
82
|
+
errors,
|
|
83
|
+
install
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = { runValidate, collectPackageErrors, collectContentErrors };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve workspace directory name for agent-kit init.
|
|
3
|
+
* @fileoverview Name authority — never rewrite cust-* to aif-*
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {string|undefined} nameOrPath
|
|
12
|
+
* @param {string} cwd
|
|
13
|
+
* @returns {{ targetAbs: string, workspaceName: string }}
|
|
14
|
+
*/
|
|
15
|
+
function resolveWorkspaceTarget(nameOrPath, cwd) {
|
|
16
|
+
const base = path.resolve(cwd || process.cwd());
|
|
17
|
+
if (!nameOrPath || !String(nameOrPath).trim()) {
|
|
18
|
+
throw new Error('Workspace name or path is required. Example: aifabrix agent-kit init cust-demo');
|
|
19
|
+
}
|
|
20
|
+
const raw = String(nameOrPath).trim();
|
|
21
|
+
const looksLikePath =
|
|
22
|
+
path.isAbsolute(raw) || raw.includes('/') || raw.includes('\\') || raw === '.' || raw.startsWith('.');
|
|
23
|
+
const targetAbs = looksLikePath ? path.resolve(base, raw) : path.join(base, raw);
|
|
24
|
+
const workspaceName = path.basename(targetAbs);
|
|
25
|
+
if (!workspaceName || workspaceName === '.' || workspaceName === '..') {
|
|
26
|
+
throw new Error('Could not derive a workspace name from the path.');
|
|
27
|
+
}
|
|
28
|
+
return { targetAbs, workspaceName };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Preserve user-supplied names; never rewrite cust-* prefixes.
|
|
33
|
+
* @param {string} name
|
|
34
|
+
* @returns {string}
|
|
35
|
+
*/
|
|
36
|
+
function assertNameUnchanged(name) {
|
|
37
|
+
return name;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = { resolveWorkspaceTarget, assertNameUnchanged };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copy product-neutral workspace skeleton for agent-kit init.
|
|
3
|
+
* @fileoverview templates/agent-kit/workspace → target
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('../internal/fs-real-sync');
|
|
10
|
+
const { getKitRoot } = require('./kit-root');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
function getWorkspaceTemplateRoot() {
|
|
16
|
+
return path.join(getKitRoot(), 'workspace');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} text
|
|
21
|
+
* @param {{ workspaceName: string, year?: number, copyrightHolder?: string }} vars
|
|
22
|
+
* @returns {string}
|
|
23
|
+
*/
|
|
24
|
+
function applyPlaceholders(text, vars) {
|
|
25
|
+
return String(text)
|
|
26
|
+
.replace(/\{\{workspaceName\}\}/g, vars.workspaceName)
|
|
27
|
+
.replace(/\{\{year\}\}/g, String(vars.year || new Date().getFullYear()))
|
|
28
|
+
.replace(/\{\{copyrightHolder\}\}/g, vars.copyrightHolder || 'Copyright Holder');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {string} absDir
|
|
33
|
+
* @param {string} relPrefix
|
|
34
|
+
* @returns {{ rel: string, abs: string }[]}
|
|
35
|
+
*/
|
|
36
|
+
function listTemplateFiles(absDir, relPrefix) {
|
|
37
|
+
if (!fs.existsSync(absDir)) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
const out = [];
|
|
41
|
+
for (const ent of fs.readdirSync(absDir, { withFileTypes: true })) {
|
|
42
|
+
const rel = relPrefix ? `${relPrefix}/${ent.name}` : ent.name;
|
|
43
|
+
const abs = path.join(absDir, ent.name);
|
|
44
|
+
if (ent.isDirectory()) {
|
|
45
|
+
out.push(...listTemplateFiles(abs, rel));
|
|
46
|
+
} else if (ent.name !== 'LICENSE.mit') {
|
|
47
|
+
out.push({ rel, abs });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* @param {string} targetAbs
|
|
55
|
+
* @param {{ workspaceName: string, license?: string, dryRun?: boolean }} options
|
|
56
|
+
* @returns {string[]} written relative paths
|
|
57
|
+
*/
|
|
58
|
+
function writeWorkspaceSkeleton(targetAbs, options) {
|
|
59
|
+
const written = [];
|
|
60
|
+
const vars = { workspaceName: options.workspaceName };
|
|
61
|
+
const root = getWorkspaceTemplateRoot();
|
|
62
|
+
for (const file of listTemplateFiles(root, '')) {
|
|
63
|
+
const dest = path.join(targetAbs, file.rel);
|
|
64
|
+
if (!options.dryRun) {
|
|
65
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
66
|
+
const body = applyPlaceholders(fs.readFileSync(file.abs, 'utf8'), vars);
|
|
67
|
+
fs.writeFileSync(dest, body, 'utf8');
|
|
68
|
+
}
|
|
69
|
+
written.push(file.rel);
|
|
70
|
+
}
|
|
71
|
+
if (options.license === 'mit') {
|
|
72
|
+
const src = path.join(root, 'LICENSE.mit');
|
|
73
|
+
const dest = path.join(targetAbs, 'LICENSE');
|
|
74
|
+
if (!options.dryRun && fs.existsSync(src)) {
|
|
75
|
+
fs.writeFileSync(dest, applyPlaceholders(fs.readFileSync(src, 'utf8'), vars), 'utf8');
|
|
76
|
+
}
|
|
77
|
+
written.push('LICENSE');
|
|
78
|
+
}
|
|
79
|
+
if (!options.dryRun) {
|
|
80
|
+
fs.mkdirSync(path.join(targetAbs, 'integration'), { recursive: true });
|
|
81
|
+
fs.mkdirSync(path.join(targetAbs, 'role-assistant'), { recursive: true });
|
|
82
|
+
}
|
|
83
|
+
return written;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @param {string} targetAbs
|
|
88
|
+
* @returns {boolean}
|
|
89
|
+
*/
|
|
90
|
+
function isNonEmptyDirectory(targetAbs) {
|
|
91
|
+
if (!fs.existsSync(targetAbs)) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
const entries = fs.readdirSync(targetAbs).filter((name) => name !== '.git');
|
|
95
|
+
return entries.length > 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
module.exports = {
|
|
99
|
+
getWorkspaceTemplateRoot,
|
|
100
|
+
applyPlaceholders,
|
|
101
|
+
writeWorkspaceSkeleton,
|
|
102
|
+
isNonEmptyDirectory
|
|
103
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dataplane Role Assistant test pack CRUD + case status.
|
|
3
|
+
*
|
|
4
|
+
* @fileoverview PUT/GET pack and PATCH case status
|
|
5
|
+
* @author AI Fabrix Team
|
|
6
|
+
* @version 1.0.0
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
'use strict';
|
|
10
|
+
|
|
11
|
+
const { createDataplaneApiClient } = require('./index');
|
|
12
|
+
const { throwIfApiFailed } = require('./api-response-errors');
|
|
13
|
+
const { unwrapApiData } = require('../utils/external-system-readiness-core');
|
|
14
|
+
|
|
15
|
+
function packEndpoint(dataplaneUrl, systemIdOrKey, suffix) {
|
|
16
|
+
const base = String(dataplaneUrl || '').replace(/\/$/, '');
|
|
17
|
+
const key = encodeURIComponent(systemIdOrKey);
|
|
18
|
+
return `${base}/api/v1/external/systems/${key}/role-assistant-tests${suffix || ''}`;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function packPath(systemIdOrKey, suffix) {
|
|
22
|
+
const key = encodeURIComponent(systemIdOrKey);
|
|
23
|
+
return `/api/v1/external/systems/${key}/role-assistant-tests${suffix || ''}`;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function isMissingPackResponse(res) {
|
|
27
|
+
return Boolean(res && res.success === false && Number(res.status) === 404);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* PUT /api/v1/external/systems/{systemIdOrKey}/role-assistant-tests
|
|
32
|
+
* @requiresPermission {Dataplane} external-system:update
|
|
33
|
+
* @async
|
|
34
|
+
*/
|
|
35
|
+
async function upsertRoleAssistantTestPack(dataplaneUrl, authConfig, systemIdOrKey, pack) {
|
|
36
|
+
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
37
|
+
const res = await client.put(packPath(systemIdOrKey), { body: { pack } });
|
|
38
|
+
throwIfApiFailed(res, {
|
|
39
|
+
endpointUrl: packEndpoint(dataplaneUrl, systemIdOrKey, '')
|
|
40
|
+
});
|
|
41
|
+
return unwrapApiData(res);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* GET /api/v1/external/systems/{systemIdOrKey}/role-assistant-tests
|
|
46
|
+
* @requiresPermission {Dataplane} external-system:read
|
|
47
|
+
* @async
|
|
48
|
+
*/
|
|
49
|
+
async function getRoleAssistantTestPack(dataplaneUrl, authConfig, systemIdOrKey, options = {}) {
|
|
50
|
+
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
51
|
+
const res = await client.get(packPath(systemIdOrKey));
|
|
52
|
+
if (options.allowMissing === true && isMissingPackResponse(res)) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
throwIfApiFailed(res, {
|
|
56
|
+
endpointUrl: packEndpoint(dataplaneUrl, systemIdOrKey, '')
|
|
57
|
+
});
|
|
58
|
+
return unwrapApiData(res);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* PATCH /api/v1/external/systems/{systemIdOrKey}/role-assistant-tests/cases/{caseId}/status
|
|
63
|
+
* @requiresPermission {Dataplane} external-system:update
|
|
64
|
+
* @async
|
|
65
|
+
*/
|
|
66
|
+
async function patchRoleAssistantTestCaseStatus(
|
|
67
|
+
dataplaneUrl,
|
|
68
|
+
authConfig,
|
|
69
|
+
systemIdOrKey,
|
|
70
|
+
caseId,
|
|
71
|
+
body
|
|
72
|
+
) {
|
|
73
|
+
const suffix = `/cases/${encodeURIComponent(caseId)}/status`;
|
|
74
|
+
const client = createDataplaneApiClient(dataplaneUrl, authConfig);
|
|
75
|
+
const res = await client.patch(packPath(systemIdOrKey, suffix), { body });
|
|
76
|
+
throwIfApiFailed(res, {
|
|
77
|
+
endpointUrl: packEndpoint(dataplaneUrl, systemIdOrKey, suffix)
|
|
78
|
+
});
|
|
79
|
+
return unwrapApiData(res);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
module.exports = {
|
|
83
|
+
upsertRoleAssistantTestPack,
|
|
84
|
+
getRoleAssistantTestPack,
|
|
85
|
+
patchRoleAssistantTestCaseStatus
|
|
86
|
+
};
|
|
@@ -14,6 +14,7 @@ const { unwrapApiData } = require('../utils/external-system-readiness-core');
|
|
|
14
14
|
const SEARCH_TIMEOUT_MS = 120000;
|
|
15
15
|
const LAYER_B_SYSTEM_KEY = process.env.RUNTIME_ORCHESTRATION_SYSTEM_KEY || 'runtime-orchestration';
|
|
16
16
|
const LAYER_B_TOOLS = Object.freeze({
|
|
17
|
+
roles: { resourceType: 'work-roles', toolName: 'work_roles.list' },
|
|
17
18
|
skills: { resourceType: 'work-skills', toolName: 'work_skills.get' },
|
|
18
19
|
search: { resourceType: 'work-search', toolName: 'work_search.create' }
|
|
19
20
|
});
|
|
@@ -45,19 +46,31 @@ function extractErrorText(res) {
|
|
|
45
46
|
return parts.join(' ');
|
|
46
47
|
}
|
|
47
48
|
|
|
49
|
+
/**
|
|
50
|
+
* MCP execute sometimes wraps a single JSON object as a one-element array.
|
|
51
|
+
* @param {*} value
|
|
52
|
+
* @returns {*}
|
|
53
|
+
*/
|
|
54
|
+
function unwrapSingletonObject(value) {
|
|
55
|
+
if (Array.isArray(value) && value.length === 1 && value[0] && typeof value[0] === 'object') {
|
|
56
|
+
return value[0];
|
|
57
|
+
}
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
|
|
48
61
|
function unwrapExecutePayload(res) {
|
|
49
|
-
const body = unwrapApiData(res);
|
|
62
|
+
const body = unwrapSingletonObject(unwrapApiData(res));
|
|
50
63
|
if (!body || typeof body !== 'object') {
|
|
51
64
|
return body;
|
|
52
65
|
}
|
|
53
66
|
if (body.result && typeof body.result === 'object') {
|
|
54
|
-
return body.result;
|
|
67
|
+
return unwrapSingletonObject(body.result);
|
|
55
68
|
}
|
|
56
69
|
if (body.json && typeof body.json === 'object') {
|
|
57
|
-
return body.json;
|
|
70
|
+
return unwrapSingletonObject(body.json);
|
|
58
71
|
}
|
|
59
72
|
if (body.root && typeof body.root === 'object') {
|
|
60
|
-
return body.root;
|
|
73
|
+
return unwrapSingletonObject(body.root);
|
|
61
74
|
}
|
|
62
75
|
return body;
|
|
63
76
|
}
|
|
@@ -94,6 +107,18 @@ async function executeLayerBTool(dataplaneUrl, authConfig, tool, args = {}) {
|
|
|
94
107
|
return normalizeLayerBResult(res);
|
|
95
108
|
}
|
|
96
109
|
|
|
110
|
+
/**
|
|
111
|
+
* GET-equivalent work.roles for the current caller.
|
|
112
|
+
* @requiresPermission {Dataplane} Authenticated (oauth2: [])
|
|
113
|
+
* @async
|
|
114
|
+
* @param {string} dataplaneUrl
|
|
115
|
+
* @param {Object} authConfig
|
|
116
|
+
* @returns {Promise<{ status: number, payload: Object|null, errorText: string, raw: Object }>}
|
|
117
|
+
*/
|
|
118
|
+
async function getWorkRoles(dataplaneUrl, authConfig) {
|
|
119
|
+
return executeLayerBTool(dataplaneUrl, authConfig, LAYER_B_TOOLS.roles, {});
|
|
120
|
+
}
|
|
121
|
+
|
|
97
122
|
/**
|
|
98
123
|
* GET-equivalent work.skills for one roleRef.
|
|
99
124
|
* Requests detail=full so search.resourceTypes (executable grammar) is present.
|
|
@@ -128,9 +153,11 @@ module.exports = {
|
|
|
128
153
|
SEARCH_TIMEOUT_MS,
|
|
129
154
|
buildLayerBExecutePath,
|
|
130
155
|
extractErrorText,
|
|
156
|
+
unwrapSingletonObject,
|
|
131
157
|
unwrapExecutePayload,
|
|
132
158
|
normalizeLayerBResult,
|
|
133
159
|
executeLayerBTool,
|
|
160
|
+
getWorkRoles,
|
|
134
161
|
getWorkSkills,
|
|
135
162
|
searchWork
|
|
136
163
|
};
|