@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,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalize Agent Kit --host values.
|
|
3
|
+
* @fileoverview Host selection for install reporting and adapters
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const ALL_HOSTS = ['cursor', 'codex', 'claude'];
|
|
9
|
+
const HOST_LABELS = {
|
|
10
|
+
cursor: 'Cursor',
|
|
11
|
+
codex: 'Codex',
|
|
12
|
+
claude: 'Claude Code'
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {string|string[]} [value]
|
|
17
|
+
* @returns {string[]}
|
|
18
|
+
*/
|
|
19
|
+
function normalizeHosts(value) {
|
|
20
|
+
if (Array.isArray(value)) {
|
|
21
|
+
const unique = [...new Set(value.map((h) => String(h || '').trim()).filter(Boolean))];
|
|
22
|
+
if (!unique.length) {
|
|
23
|
+
throw new Error('Invalid --host. Use all, cursor, codex, or claude.');
|
|
24
|
+
}
|
|
25
|
+
if (unique.some((h) => !ALL_HOSTS.includes(h) && h !== 'all')) {
|
|
26
|
+
throw new Error('Invalid --host. Use all, cursor, codex, or claude.');
|
|
27
|
+
}
|
|
28
|
+
if (unique.includes('all') || unique.length === ALL_HOSTS.length) {
|
|
29
|
+
return ALL_HOSTS.slice();
|
|
30
|
+
}
|
|
31
|
+
return unique.filter((h) => ALL_HOSTS.includes(h));
|
|
32
|
+
}
|
|
33
|
+
const host = value || 'all';
|
|
34
|
+
if (host === 'all') {
|
|
35
|
+
return ALL_HOSTS.slice();
|
|
36
|
+
}
|
|
37
|
+
if (host.includes(',')) {
|
|
38
|
+
return normalizeHosts(host.split(',').map((part) => part.trim()));
|
|
39
|
+
}
|
|
40
|
+
if (ALL_HOSTS.includes(host)) {
|
|
41
|
+
return [host];
|
|
42
|
+
}
|
|
43
|
+
throw new Error('Invalid --host. Use all, cursor, codex, or claude.');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @param {string} host
|
|
48
|
+
* @returns {string}
|
|
49
|
+
*/
|
|
50
|
+
function hostLabel(host) {
|
|
51
|
+
return HOST_LABELS[host] || host;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Install uses --host (default all). Update keeps recorded hosts unless --host is set.
|
|
56
|
+
* @param {object} [options]
|
|
57
|
+
* @param {object|null} [state]
|
|
58
|
+
* @param {'install'|'update'} [mode]
|
|
59
|
+
* @returns {string[]}
|
|
60
|
+
*/
|
|
61
|
+
function resolveManagedHosts(options, state, mode) {
|
|
62
|
+
if (options && options.host) {
|
|
63
|
+
return normalizeHosts(options.host);
|
|
64
|
+
}
|
|
65
|
+
if (mode === 'update' && state && Array.isArray(state.hosts) && state.hosts.length) {
|
|
66
|
+
return normalizeHosts(state.hosts);
|
|
67
|
+
}
|
|
68
|
+
return normalizeHosts('all');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
module.exports = { ALL_HOSTS, HOST_LABELS, normalizeHosts, hostLabel, resolveManagedHosts };
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Kit workspace init and remote-create runners.
|
|
3
|
+
* @fileoverview Skeleton + git + install + optional GitHub remote
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('../internal/fs-real-sync');
|
|
10
|
+
const { isUnsafeRoot } = require('./repo-guard');
|
|
11
|
+
const { resolveWorkspaceTarget } = require('./workspace-name');
|
|
12
|
+
const { writeWorkspaceSkeleton, isNonEmptyDirectory } = require('./workspace-skeleton');
|
|
13
|
+
const { ensureGitRepository, ensureInitialCommit, hasOriginRemote, isGitRepository } = require('./scm/git');
|
|
14
|
+
const { getGithubAuthStatus, createGithubRemote } = require('./hosting/github');
|
|
15
|
+
const { runInstall } = require('./run');
|
|
16
|
+
const { loadKitPackage } = require('./package-load');
|
|
17
|
+
const { getCliVersion } = require('../utils/installation-log-core');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} scm
|
|
21
|
+
* @returns {string}
|
|
22
|
+
*/
|
|
23
|
+
function normalizeScm(scm) {
|
|
24
|
+
const value = scm || 'git';
|
|
25
|
+
if (value !== 'git' && value !== 'none') {
|
|
26
|
+
throw new Error('Invalid --scm. Use git or none.');
|
|
27
|
+
}
|
|
28
|
+
return value;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* @param {string} visibility
|
|
33
|
+
* @returns {string}
|
|
34
|
+
*/
|
|
35
|
+
function normalizeVisibility(visibility) {
|
|
36
|
+
const value = visibility || 'private';
|
|
37
|
+
if (value !== 'private' && value !== 'public') {
|
|
38
|
+
throw new Error('Invalid --visibility. Use private or public.');
|
|
39
|
+
}
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* @param {object} options
|
|
45
|
+
* @returns {boolean}
|
|
46
|
+
*/
|
|
47
|
+
function wantsRemote(options) {
|
|
48
|
+
if (options.noRemote) {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
return Boolean(options.remote);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param {string} targetAbs
|
|
56
|
+
* @param {boolean} force
|
|
57
|
+
*/
|
|
58
|
+
function assertSafeTarget(targetAbs, force) {
|
|
59
|
+
if (isUnsafeRoot(targetAbs)) {
|
|
60
|
+
throw new Error('Refusing to init the Agent Kit into a filesystem root or home directory.');
|
|
61
|
+
}
|
|
62
|
+
if (isNonEmptyDirectory(targetAbs) && !force) {
|
|
63
|
+
throw new Error(
|
|
64
|
+
`Target is not empty: ${targetAbs}. Use --force to continue, or choose another path.`
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* @param {object} options
|
|
71
|
+
* @param {boolean} interactive
|
|
72
|
+
*/
|
|
73
|
+
function assertRemoteFlags(options, interactive) {
|
|
74
|
+
if (!wantsRemote(options)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (!interactive && !options.org) {
|
|
78
|
+
throw new Error('Non-interactive --remote requires --org <owner>.');
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @param {object} options
|
|
84
|
+
* @returns {object}
|
|
85
|
+
*/
|
|
86
|
+
function checkRemoteAuth(options) {
|
|
87
|
+
const auth = getGithubAuthStatus({ execFileSync: options.execFileSync });
|
|
88
|
+
if (!auth.authenticated) {
|
|
89
|
+
throw new Error(
|
|
90
|
+
'GitHub authentication required for --remote. Run: gh auth login\n' +
|
|
91
|
+
'Then retry, or omit --remote and later run: aifabrix agent-kit remote create'
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
return auth;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param {object} ctx
|
|
99
|
+
* @returns {object|null}
|
|
100
|
+
*/
|
|
101
|
+
function maybeCreateRemote(ctx) {
|
|
102
|
+
const { options, targetAbs, workspaceName, dryRun } = ctx;
|
|
103
|
+
if (!wantsRemote(options)) {
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
checkRemoteAuth(options);
|
|
107
|
+
return createGithubRemote({
|
|
108
|
+
name: workspaceName,
|
|
109
|
+
org: options.org,
|
|
110
|
+
visibility: normalizeVisibility(options.visibility),
|
|
111
|
+
cwd: targetAbs,
|
|
112
|
+
dryRun,
|
|
113
|
+
execFileSync: options.execFileSync
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* @param {object} options
|
|
119
|
+
* @returns {object}
|
|
120
|
+
*/
|
|
121
|
+
function runInit(options) {
|
|
122
|
+
const cwd = options.cwd || process.cwd();
|
|
123
|
+
const dryRun = Boolean(options.dryRun);
|
|
124
|
+
const scm = normalizeScm(options.scm);
|
|
125
|
+
const interactive =
|
|
126
|
+
typeof options.interactive === 'boolean' ? options.interactive : Boolean(process.stdout.isTTY);
|
|
127
|
+
const { targetAbs, workspaceName } = resolveWorkspaceTarget(options.nameOrPath, cwd);
|
|
128
|
+
assertSafeTarget(targetAbs, Boolean(options.force));
|
|
129
|
+
assertRemoteFlags(options, interactive);
|
|
130
|
+
|
|
131
|
+
const phases = [];
|
|
132
|
+
if (!dryRun) {
|
|
133
|
+
fs.mkdirSync(targetAbs, { recursive: true });
|
|
134
|
+
}
|
|
135
|
+
const skeletonFiles = writeWorkspaceSkeleton(targetAbs, {
|
|
136
|
+
workspaceName,
|
|
137
|
+
license: options.license === 'mit' ? 'mit' : 'none',
|
|
138
|
+
dryRun
|
|
139
|
+
});
|
|
140
|
+
phases.push({ phase: 'skeleton', files: skeletonFiles });
|
|
141
|
+
|
|
142
|
+
let gitResult = { initialized: false, skipped: true };
|
|
143
|
+
if (scm === 'git') {
|
|
144
|
+
gitResult = ensureGitRepository(targetAbs, { dryRun, execFileSync: options.execFileSync });
|
|
145
|
+
phases.push({ phase: 'scm', provider: 'git', ...gitResult });
|
|
146
|
+
} else {
|
|
147
|
+
phases.push({ phase: 'scm', provider: 'none' });
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const kit = installKitPhase({
|
|
151
|
+
scm,
|
|
152
|
+
dryRun,
|
|
153
|
+
targetAbs,
|
|
154
|
+
host: options.host || 'all',
|
|
155
|
+
approveAll: Boolean(options.approveAll),
|
|
156
|
+
force: Boolean(options.force),
|
|
157
|
+
gitResult,
|
|
158
|
+
phases
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const remote = remotePhase({ options, targetAbs, workspaceName, dryRun, phases });
|
|
162
|
+
|
|
163
|
+
return buildInitReport({
|
|
164
|
+
dryRun,
|
|
165
|
+
targetAbs,
|
|
166
|
+
workspaceName,
|
|
167
|
+
scm,
|
|
168
|
+
kit,
|
|
169
|
+
remote,
|
|
170
|
+
phases
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @param {object} p
|
|
176
|
+
* @returns {object|null}
|
|
177
|
+
*/
|
|
178
|
+
function installKitPhase(p) {
|
|
179
|
+
if (p.scm !== 'git') {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
if (p.dryRun) {
|
|
183
|
+
const kitPkg = loadKitPackage();
|
|
184
|
+
const skills = (kitPkg.manifest.skills || []).length;
|
|
185
|
+
p.phases.push({ phase: 'agent-kit', planned: true });
|
|
186
|
+
return {
|
|
187
|
+
state: 'CURRENT',
|
|
188
|
+
kitVersion: kitPkg.manifest.kitVersion,
|
|
189
|
+
skills: { expected: skills, installed: 0 }
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
if (!isGitRepository(p.targetAbs) && !p.gitResult.initialized) {
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
const kit = runInstall({
|
|
196
|
+
cwd: p.targetAbs,
|
|
197
|
+
host: p.host,
|
|
198
|
+
approveAll: Boolean(p.approveAll),
|
|
199
|
+
force: Boolean(p.force)
|
|
200
|
+
});
|
|
201
|
+
p.phases.push({ phase: 'agent-kit', state: kit.state });
|
|
202
|
+
return kit;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* @param {object} p
|
|
207
|
+
* @returns {object|null}
|
|
208
|
+
*/
|
|
209
|
+
function remotePhase(p) {
|
|
210
|
+
if (!wantsRemote(p.options)) {
|
|
211
|
+
p.phases.push({
|
|
212
|
+
phase: 'remote',
|
|
213
|
+
skipped: true,
|
|
214
|
+
hint: 'aifabrix agent-kit remote create'
|
|
215
|
+
});
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
const commit = ensureInitialCommit(p.targetAbs, {
|
|
219
|
+
dryRun: p.dryRun,
|
|
220
|
+
execFileSync: p.options.execFileSync
|
|
221
|
+
});
|
|
222
|
+
p.phases.push({ phase: 'commit', ...commit });
|
|
223
|
+
const remote = maybeCreateRemote(p);
|
|
224
|
+
p.phases.push({ phase: 'remote', ...remote });
|
|
225
|
+
return remote;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* @param {object} p
|
|
230
|
+
* @returns {object}
|
|
231
|
+
*/
|
|
232
|
+
function buildInitReport(p) {
|
|
233
|
+
return {
|
|
234
|
+
success: true,
|
|
235
|
+
command: 'init',
|
|
236
|
+
dryRun: p.dryRun,
|
|
237
|
+
path: p.targetAbs,
|
|
238
|
+
name: p.workspaceName,
|
|
239
|
+
scm: p.scm,
|
|
240
|
+
hosts: p.kit && p.kit.hosts ? p.kit.hosts : undefined,
|
|
241
|
+
remote: p.remote,
|
|
242
|
+
builderVersion: getCliVersion(),
|
|
243
|
+
kit: p.kit
|
|
244
|
+
? {
|
|
245
|
+
state: p.kit.state,
|
|
246
|
+
kitVersion: p.kit.kitVersion,
|
|
247
|
+
skills: p.kit.skills
|
|
248
|
+
}
|
|
249
|
+
: null,
|
|
250
|
+
phases: p.phases
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* @param {object} options
|
|
256
|
+
* @returns {object}
|
|
257
|
+
*/
|
|
258
|
+
function runRemoteCreate(options) {
|
|
259
|
+
const cwd = options.cwd || process.cwd();
|
|
260
|
+
const dryRun = Boolean(options.dryRun);
|
|
261
|
+
const interactive =
|
|
262
|
+
typeof options.interactive === 'boolean' ? options.interactive : Boolean(process.stdout.isTTY);
|
|
263
|
+
const targetAbs = path.resolve(cwd);
|
|
264
|
+
if (isUnsafeRoot(targetAbs)) {
|
|
265
|
+
throw new Error(
|
|
266
|
+
'Run remote create from inside the workspace (for example: cd ~/cust-demo && aifabrix agent-kit remote create).'
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
if (!isGitRepository(targetAbs)) {
|
|
270
|
+
throw new Error(
|
|
271
|
+
'remote create requires a git repository. cd into the workspace, then run: aifabrix agent-kit remote create'
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
if (hasOriginRemote(targetAbs, { execFileSync: options.execFileSync })) {
|
|
275
|
+
return {
|
|
276
|
+
success: true,
|
|
277
|
+
command: 'remote-create',
|
|
278
|
+
dryRun,
|
|
279
|
+
path: targetAbs,
|
|
280
|
+
remote: { provider: 'github', skipped: true, reason: 'origin-exists' },
|
|
281
|
+
builderVersion: getCliVersion()
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
if (!interactive && !options.org) {
|
|
285
|
+
throw new Error('Non-interactive remote create requires --org <owner>.');
|
|
286
|
+
}
|
|
287
|
+
checkRemoteAuth(options);
|
|
288
|
+
const commit = ensureInitialCommit(targetAbs, {
|
|
289
|
+
dryRun,
|
|
290
|
+
execFileSync: options.execFileSync
|
|
291
|
+
});
|
|
292
|
+
const name = options.name || path.basename(targetAbs);
|
|
293
|
+
const remote = createGithubRemote({
|
|
294
|
+
name,
|
|
295
|
+
org: options.org,
|
|
296
|
+
visibility: normalizeVisibility(options.visibility),
|
|
297
|
+
cwd: targetAbs,
|
|
298
|
+
dryRun,
|
|
299
|
+
execFileSync: options.execFileSync
|
|
300
|
+
});
|
|
301
|
+
return {
|
|
302
|
+
success: true,
|
|
303
|
+
command: 'remote-create',
|
|
304
|
+
dryRun,
|
|
305
|
+
path: targetAbs,
|
|
306
|
+
name,
|
|
307
|
+
commit,
|
|
308
|
+
remote,
|
|
309
|
+
builderVersion: getCliVersion()
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
module.exports = {
|
|
314
|
+
runInit,
|
|
315
|
+
runRemoteCreate,
|
|
316
|
+
normalizeScm,
|
|
317
|
+
normalizeVisibility,
|
|
318
|
+
wantsRemote
|
|
319
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the bundled Agent Kit template root.
|
|
3
|
+
* @fileoverview Path to templates/agent-kit
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
function getKitRoot() {
|
|
14
|
+
return path.join(__dirname, '..', '..', 'templates', 'agent-kit');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
module.exports = { getKitRoot };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Managed-section markers for kit-owned markdown (AGENTS.md, CLAUDE.md).
|
|
3
|
+
* @fileoverview Extract, append, and replace kit-owned sections
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const { BEGIN_MARKER, END_MARKER } = require('./constants');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {string} body
|
|
12
|
+
* @returns {string}
|
|
13
|
+
*/
|
|
14
|
+
function wrapSection(body) {
|
|
15
|
+
const trimmed = String(body || '').replace(/^\n+|\n+$/g, '');
|
|
16
|
+
return `${BEGIN_MARKER}\n${trimmed}\n${END_MARKER}\n`;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @param {string} text
|
|
21
|
+
* @returns {string|null}
|
|
22
|
+
*/
|
|
23
|
+
function extractSection(text) {
|
|
24
|
+
const start = text.indexOf(BEGIN_MARKER);
|
|
25
|
+
const end = text.indexOf(END_MARKER);
|
|
26
|
+
if (start < 0 || end < 0 || end <= start) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
return text.slice(start + BEGIN_MARKER.length, end).replace(/^\n+|\n+$/g, '');
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {string} text
|
|
34
|
+
* @returns {boolean}
|
|
35
|
+
*/
|
|
36
|
+
function hasManagedSection(text) {
|
|
37
|
+
return extractSection(text) !== null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Append a managed section; leave existing bytes unchanged.
|
|
42
|
+
* @param {string} text
|
|
43
|
+
* @param {string} body
|
|
44
|
+
* @returns {string}
|
|
45
|
+
*/
|
|
46
|
+
function appendManagedSection(text, body) {
|
|
47
|
+
const wrapped = wrapSection(body);
|
|
48
|
+
if (!text) {
|
|
49
|
+
return wrapped;
|
|
50
|
+
}
|
|
51
|
+
const prefix = text.endsWith('\n') ? text : `${text}\n`;
|
|
52
|
+
return `${prefix}\n${wrapped}`;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Replace only the marked section. Unmarked prose stays byte-identical.
|
|
57
|
+
* @param {string} text
|
|
58
|
+
* @param {string} body
|
|
59
|
+
* @returns {string}
|
|
60
|
+
*/
|
|
61
|
+
function replaceManagedSection(text, body) {
|
|
62
|
+
if (!hasManagedSection(text)) {
|
|
63
|
+
return appendManagedSection(text, body);
|
|
64
|
+
}
|
|
65
|
+
const start = text.indexOf(BEGIN_MARKER);
|
|
66
|
+
const end = text.indexOf(END_MARKER) + END_MARKER.length;
|
|
67
|
+
const after = text.slice(end);
|
|
68
|
+
const wrapped = wrapSection(body).replace(/\n$/, '');
|
|
69
|
+
const suffix = after.startsWith('\n') || after.length === 0 ? after : `\n${after}`;
|
|
70
|
+
return `${text.slice(0, start)}${wrapped}${suffix}`;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
module.exports = {
|
|
74
|
+
wrapSection,
|
|
75
|
+
extractSection,
|
|
76
|
+
hasManagedSection,
|
|
77
|
+
appendManagedSection,
|
|
78
|
+
replaceManagedSection
|
|
79
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Load bundled Agent Kit package manifest and inventory.
|
|
3
|
+
* @fileoverview Read templates/agent-kit YAML contracts
|
|
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 { getKitRoot } = require('./kit-root');
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {string} relativeName
|
|
15
|
+
* @returns {object}
|
|
16
|
+
*/
|
|
17
|
+
function loadYamlFromKit(relativeName) {
|
|
18
|
+
const filePath = path.join(getKitRoot(), relativeName);
|
|
19
|
+
const raw = fs.readFileSync(filePath, 'utf8');
|
|
20
|
+
const parsed = yaml.load(raw);
|
|
21
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
22
|
+
throw new Error(`Invalid Agent Kit file: ${relativeName} (${typeof raw})`);
|
|
23
|
+
}
|
|
24
|
+
return parsed;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* @returns {object}
|
|
29
|
+
*/
|
|
30
|
+
function loadKitPackage() {
|
|
31
|
+
const manifest = loadYamlFromKit('agent-kit.yaml');
|
|
32
|
+
if (manifest.schemaVersion !== '1' || !manifest.kitVersion) {
|
|
33
|
+
throw new Error('agent-kit.yaml must declare schemaVersion 1 and kitVersion.');
|
|
34
|
+
}
|
|
35
|
+
if (!Array.isArray(manifest.skills) || manifest.skills.length !== 4) {
|
|
36
|
+
throw new Error('agent-kit.yaml must list exactly four skills.');
|
|
37
|
+
}
|
|
38
|
+
return {
|
|
39
|
+
root: getKitRoot(),
|
|
40
|
+
manifest,
|
|
41
|
+
inventory: loadYamlFromKit('parity-inventory.yaml')
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = { loadKitPackage, loadYamlFromKit };
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Map file classification to install/update actions.
|
|
3
|
+
* @fileoverview Agent Kit action planner
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
'use strict';
|
|
7
|
+
|
|
8
|
+
const { ACTION, FILE_STATE } = require('./constants');
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {object} item
|
|
12
|
+
* @param {boolean} force
|
|
13
|
+
* @returns {string}
|
|
14
|
+
*/
|
|
15
|
+
function actionForInstall(item, force) {
|
|
16
|
+
if (item.mode === 'if-missing') {
|
|
17
|
+
return item.fileState === FILE_STATE.MISSING ? ACTION.CREATE : ACTION.SKIP;
|
|
18
|
+
}
|
|
19
|
+
if (item.replaceOnInstall) {
|
|
20
|
+
return ACTION.REPLACE;
|
|
21
|
+
}
|
|
22
|
+
const fileState = item.fileState;
|
|
23
|
+
if (fileState === FILE_STATE.MISSING) {
|
|
24
|
+
return ACTION.CREATE;
|
|
25
|
+
}
|
|
26
|
+
if (fileState === FILE_STATE.UNCHANGED_MANAGED) {
|
|
27
|
+
return ACTION.SKIP;
|
|
28
|
+
}
|
|
29
|
+
if (fileState === FILE_STATE.USER_FILE_NO_MANAGED_SECTION) {
|
|
30
|
+
return ACTION.APPEND_SECTION;
|
|
31
|
+
}
|
|
32
|
+
if (fileState === FILE_STATE.MODIFIED_MANAGED) {
|
|
33
|
+
return force ? ACTION.REPLACE : ACTION.CONFLICT;
|
|
34
|
+
}
|
|
35
|
+
if (fileState === FILE_STATE.OBSOLETE_UNCHANGED_MANAGED) {
|
|
36
|
+
return ACTION.DELETE;
|
|
37
|
+
}
|
|
38
|
+
if (fileState === FILE_STATE.OBSOLETE_MODIFIED_MANAGED) {
|
|
39
|
+
return ACTION.RETAIN;
|
|
40
|
+
}
|
|
41
|
+
return ACTION.SKIP;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {object} item
|
|
46
|
+
* @param {boolean} force
|
|
47
|
+
* @returns {string}
|
|
48
|
+
*/
|
|
49
|
+
function actionForUpdate(item, force) {
|
|
50
|
+
if (item.mode === 'if-missing') {
|
|
51
|
+
return item.fileState === FILE_STATE.MISSING ? ACTION.CREATE : ACTION.SKIP;
|
|
52
|
+
}
|
|
53
|
+
if (item.fileState === FILE_STATE.UNCHANGED_MANAGED) {
|
|
54
|
+
return ACTION.REPLACE;
|
|
55
|
+
}
|
|
56
|
+
return actionForInstall({ ...item, replaceOnInstall: item.replaceOnInstall }, force);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* @param {object[]} items
|
|
61
|
+
* @param {(item: object, force: boolean) => string} picker
|
|
62
|
+
* @param {boolean} force
|
|
63
|
+
* @returns {object[]}
|
|
64
|
+
*/
|
|
65
|
+
function assignActions(items, picker, force) {
|
|
66
|
+
return items.map((item) => ({ ...item, action: picker(item, force) }));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = { actionForInstall, actionForUpdate, assignActions };
|