@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,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keep human.respond bodies on the OpenAPI request shape.
|
|
3
|
+
* WaitPayload.prompt is server-owned and must not be echoed.
|
|
4
|
+
* @fileoverview Strip extra wait fields from RA respond payloads
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
'use strict';
|
|
8
|
+
|
|
9
|
+
const HUMAN_RESPOND_KEYS = [
|
|
10
|
+
'respondIdempotencyKey',
|
|
11
|
+
'answerType',
|
|
12
|
+
'value',
|
|
13
|
+
'evidenceRef',
|
|
14
|
+
'declined',
|
|
15
|
+
'selectedOptionId',
|
|
16
|
+
'approvalDecision',
|
|
17
|
+
'proposedPatch',
|
|
18
|
+
'requestVersion',
|
|
19
|
+
'stateVersionRef',
|
|
20
|
+
'requestFingerprint'
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
function pickHumanRespondBody(payload) {
|
|
24
|
+
const out = {};
|
|
25
|
+
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
|
|
26
|
+
return out;
|
|
27
|
+
}
|
|
28
|
+
for (const key of HUMAN_RESPOND_KEYS) {
|
|
29
|
+
if (payload[key] !== undefined) {
|
|
30
|
+
out[key] = payload[key];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
module.exports = { pickHumanRespondBody };
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
'use strict';
|
|
10
10
|
|
|
11
11
|
const { getWorkSkills, searchWork } = require('../api/work-search.api');
|
|
12
|
+
const { resourceTypesMap } = require('../search/search-skills');
|
|
12
13
|
const { roleAssistantSystemKey } = require('../utils/role-assistant-paths');
|
|
13
14
|
const {
|
|
14
15
|
resolveInput,
|
|
@@ -32,11 +33,6 @@ function operationKeys(spec) {
|
|
|
32
33
|
return keys;
|
|
33
34
|
}
|
|
34
35
|
|
|
35
|
-
function resourceTypesMap(skillsPayload) {
|
|
36
|
-
const rts = skillsPayload && skillsPayload.search && skillsPayload.search.resourceTypes;
|
|
37
|
-
return rts && typeof rts === 'object' && !Array.isArray(rts) ? rts : {};
|
|
38
|
-
}
|
|
39
|
-
|
|
40
36
|
function pickResourceType(skillsPayload, operation) {
|
|
41
37
|
const rts = resourceTypesMap(skillsPayload);
|
|
42
38
|
const keys = Object.keys(rts);
|
|
@@ -73,6 +69,24 @@ function assignOptionalNumber(args, input, key) {
|
|
|
73
69
|
}
|
|
74
70
|
}
|
|
75
71
|
|
|
72
|
+
function assignGraphFields(args, input) {
|
|
73
|
+
if (input.graph === true) {
|
|
74
|
+
args.graph = { depth: 1 };
|
|
75
|
+
} else if (input.graph && typeof input.graph === 'object' && !Array.isArray(input.graph)) {
|
|
76
|
+
args.graph = { depth: 1 };
|
|
77
|
+
}
|
|
78
|
+
if (typeof input.query === 'string' && input.query.trim()) {
|
|
79
|
+
args.query = input.query.trim();
|
|
80
|
+
}
|
|
81
|
+
if (!Array.isArray(input.knowledgeKeys) || !input.knowledgeKeys.length) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const keys = input.knowledgeKeys.map((item) => String(item || '').trim()).filter(Boolean);
|
|
85
|
+
if (keys.length) {
|
|
86
|
+
args.knowledgeKeys = keys;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
76
90
|
function buildSearchArguments(roleRef, input, skillsPayload) {
|
|
77
91
|
const args = { roleRef };
|
|
78
92
|
const resourceType =
|
|
@@ -91,6 +105,7 @@ function buildSearchArguments(roleRef, input, skillsPayload) {
|
|
|
91
105
|
if (Array.isArray(input.fields) && input.fields.length) {
|
|
92
106
|
args.fields = input.fields;
|
|
93
107
|
}
|
|
108
|
+
assignGraphFields(args, input);
|
|
94
109
|
return args;
|
|
95
110
|
}
|
|
96
111
|
|
|
@@ -37,6 +37,16 @@ function resolveInputMessage(testCase) {
|
|
|
37
37
|
return '';
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
function applyObjectiveField(payload, message) {
|
|
41
|
+
if (message) {
|
|
42
|
+
payload.objective = message;
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (typeof payload.content === 'string' && payload.content.trim()) {
|
|
46
|
+
payload.objective = payload.content.trim();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
40
50
|
function applyStartPayloadOptionalFields(payload, input) {
|
|
41
51
|
const mappedFields = [
|
|
42
52
|
['activationId', 'activationId'],
|
|
@@ -58,34 +68,77 @@ function buildStartPayloadSourceMetadata(roleKey, testCase, input) {
|
|
|
58
68
|
};
|
|
59
69
|
}
|
|
60
70
|
|
|
61
|
-
function
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
71
|
+
function resolveCaseMetadata(testCase) {
|
|
72
|
+
if (testCase && typeof testCase.metadata === 'object' && testCase.metadata) {
|
|
73
|
+
return testCase.metadata;
|
|
74
|
+
}
|
|
75
|
+
return {};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function resolveLearningLevel(metadata) {
|
|
79
|
+
if (typeof metadata.learningLevel === 'string' && metadata.learningLevel.trim()) {
|
|
80
|
+
return metadata.learningLevel.trim();
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function assertHasStartContent(testCase, hasContent, message) {
|
|
65
86
|
if (!hasContent && !message) {
|
|
66
87
|
throw new Error(
|
|
67
88
|
`Role assistant test case "${testCase.caseId}" is missing input.message or input.content for runtime execution.`
|
|
68
89
|
);
|
|
69
90
|
}
|
|
70
|
-
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function resolveComVocabulary(input) {
|
|
94
|
+
if (Array.isArray(input.comVocabulary) && input.comVocabulary.length > 0) {
|
|
95
|
+
return input.comVocabulary.map((row) => String(row));
|
|
96
|
+
}
|
|
97
|
+
return ['objective', 'entity', 'action'];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function buildStartIntentBasePayload(roleKey, testCase, input, message, hasContent) {
|
|
101
|
+
return {
|
|
71
102
|
submissionId: String(input.submissionId || buildRuntimeId(`ra-${roleKey}`)),
|
|
72
103
|
content: hasContent ? input.content : message,
|
|
73
104
|
comModelRef: String(input.comModelRef || 'aifabrix.com/intent/default'),
|
|
74
105
|
comModelVersion: String(input.comModelVersion || '1.0'),
|
|
75
|
-
comVocabulary:
|
|
76
|
-
Array.isArray(input.comVocabulary) && input.comVocabulary.length > 0
|
|
77
|
-
? input.comVocabulary.map((row) => String(row))
|
|
78
|
-
: ['objective', 'entity', 'action'],
|
|
106
|
+
comVocabulary: resolveComVocabulary(input),
|
|
79
107
|
sourceType: String(input.sourceType || 'api'),
|
|
80
108
|
sourceLanguage: String(input.sourceLanguage || 'en'),
|
|
81
109
|
responseLanguage: String(input.responseLanguage || input.sourceLanguage || 'en'),
|
|
82
110
|
sourceMetadata: buildStartPayloadSourceMetadata(roleKey, testCase, input)
|
|
83
111
|
};
|
|
84
|
-
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function applyLearningLevel(payload, learningLevel) {
|
|
115
|
+
if (learningLevel === null) {
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
payload.learningLevel = learningLevel;
|
|
119
|
+
payload.sourceMetadata = {
|
|
120
|
+
...(payload.sourceMetadata || {}),
|
|
121
|
+
learningLevel
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function applyStartAttachments(payload, testCase) {
|
|
85
126
|
const attachments = buildStartAttachments(testCase);
|
|
86
127
|
if (attachments && attachments.length > 0) {
|
|
87
128
|
payload.attachments = attachments;
|
|
88
129
|
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function buildStartIntentPayload(roleKey, testCase) {
|
|
133
|
+
const input = resolveInputObject(testCase);
|
|
134
|
+
const message = resolveInputMessage(testCase);
|
|
135
|
+
const hasContent = typeof input.content !== 'undefined';
|
|
136
|
+
assertHasStartContent(testCase, hasContent, message);
|
|
137
|
+
const payload = buildStartIntentBasePayload(roleKey, testCase, input, message, hasContent);
|
|
138
|
+
applyObjectiveField(payload, message);
|
|
139
|
+
applyStartPayloadOptionalFields(payload, input);
|
|
140
|
+
applyLearningLevel(payload, resolveLearningLevel(resolveCaseMetadata(testCase)));
|
|
141
|
+
applyStartAttachments(payload, testCase);
|
|
89
142
|
return payload;
|
|
90
143
|
}
|
|
91
144
|
|
|
@@ -11,6 +11,7 @@ const {
|
|
|
11
11
|
resolveSuiteRunId,
|
|
12
12
|
loadCaseBidDocument
|
|
13
13
|
} = require('./test-runner-bid-document');
|
|
14
|
+
const { pickHumanRespondBody } = require('./test-runner-respond-body');
|
|
14
15
|
|
|
15
16
|
function resolveWorkHubAnswerValue(answer) {
|
|
16
17
|
if (answer === null || answer === undefined) {
|
|
@@ -31,24 +32,41 @@ function resolveWorkHubAnswerValue(answer) {
|
|
|
31
32
|
return undefined;
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
function asPlainObject(value) {
|
|
36
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
37
|
+
return {};
|
|
38
|
+
}
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function firstNormalizedKey(candidates) {
|
|
43
|
+
for (const part of candidates) {
|
|
44
|
+
const text = String(part || '').trim().toLowerCase();
|
|
45
|
+
if (text) {
|
|
46
|
+
return text;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return '';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function waitQuestionKey(wait) {
|
|
53
|
+
const row = asPlainObject(wait);
|
|
54
|
+
const objectRef = asPlainObject(row.objectRef);
|
|
55
|
+
return firstNormalizedKey([row.questionKey, row.requestKey, objectRef.capabilityKey]);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function answerWhenKey(entry) {
|
|
59
|
+
const when = asPlainObject(asPlainObject(entry).when);
|
|
60
|
+
return firstNormalizedKey([when.questionKey, when.requestKey, when.key]);
|
|
61
|
+
}
|
|
62
|
+
|
|
34
63
|
function pickAnswerForWait(answers, wait) {
|
|
35
|
-
const questionKey =
|
|
64
|
+
const questionKey = waitQuestionKey(wait);
|
|
36
65
|
if (!questionKey) {
|
|
37
66
|
return null;
|
|
38
67
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
continue;
|
|
42
|
-
}
|
|
43
|
-
const when = entry.when && typeof entry.when === 'object' ? entry.when : {};
|
|
44
|
-
const matchKey = String(when.questionKey || when.requestKey || when.key || '')
|
|
45
|
-
.trim()
|
|
46
|
-
.toLowerCase();
|
|
47
|
-
if (matchKey && matchKey === questionKey) {
|
|
48
|
-
return entry;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
return null;
|
|
68
|
+
const list = Array.isArray(answers) ? answers : [];
|
|
69
|
+
return list.find((entry) => answerWhenKey(entry) === questionKey) || null;
|
|
52
70
|
}
|
|
53
71
|
|
|
54
72
|
function parseFieldsFromPrompt(prompt) {
|
|
@@ -423,14 +441,25 @@ function buildRespondPayload(peId, wait, testCase, statusRow, interactions, obje
|
|
|
423
441
|
};
|
|
424
442
|
if (answerType === 'approval') {
|
|
425
443
|
payload.approvalDecision = 'approved';
|
|
426
|
-
return payload;
|
|
444
|
+
return pickHumanRespondBody(payload);
|
|
427
445
|
}
|
|
428
446
|
const value = resolveRespondValue(testCase, wait, statusRow, objective);
|
|
429
447
|
if (value === undefined) {
|
|
430
448
|
return null;
|
|
431
449
|
}
|
|
450
|
+
const choiceIds = Array.isArray(wait.allowedChoiceIds) ? wait.allowedChoiceIds : [];
|
|
451
|
+
const isChoice =
|
|
452
|
+
String(wait.interactionKind || '').toLowerCase() === 'choice' || choiceIds.length > 0;
|
|
453
|
+
if (isChoice) {
|
|
454
|
+
const selected = typeof value === 'string' ? value.trim() : '';
|
|
455
|
+
if (!selected) {
|
|
456
|
+
return null;
|
|
457
|
+
}
|
|
458
|
+
payload.selectedOptionId = selected;
|
|
459
|
+
return pickHumanRespondBody(payload);
|
|
460
|
+
}
|
|
432
461
|
payload.value = value;
|
|
433
|
-
return payload;
|
|
462
|
+
return pickHumanRespondBody(payload);
|
|
434
463
|
}
|
|
435
464
|
|
|
436
465
|
module.exports = {
|
|
@@ -14,8 +14,7 @@ const {
|
|
|
14
14
|
approveWorkTask,
|
|
15
15
|
getWorkExecutionStatus,
|
|
16
16
|
respondWorkExecution,
|
|
17
|
-
continueWorkExecution
|
|
18
|
-
getWorkExecutionResult
|
|
17
|
+
continueWorkExecution
|
|
19
18
|
} = require('../api/work.api');
|
|
20
19
|
const {
|
|
21
20
|
synthesizeWaitAnswer,
|
|
@@ -367,16 +366,9 @@ async function pollWorkHubTask(dataplaneUrl, authConfig, taskId, testCase, optio
|
|
|
367
366
|
};
|
|
368
367
|
}
|
|
369
368
|
|
|
370
|
-
async function fetchBusinessResult(dataplaneUrl, authConfig, processExecutionId) {
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
requestedDepth: 'business',
|
|
374
|
-
format: 'json'
|
|
375
|
-
});
|
|
376
|
-
return { workResult, workResultError: null };
|
|
377
|
-
} catch (error) {
|
|
378
|
-
return { workResult: null, workResultError: error.message || String(error) };
|
|
379
|
-
}
|
|
369
|
+
async function fetchBusinessResult(dataplaneUrl, authConfig, processExecutionId, options = {}) {
|
|
370
|
+
const { fetchWorkHubResult } = require('./test-runner-debug');
|
|
371
|
+
return fetchWorkHubResult(dataplaneUrl, authConfig, processExecutionId, options);
|
|
380
372
|
}
|
|
381
373
|
|
|
382
374
|
function buildWorkHubLifecycleResult(roleKey, testCase, started, pollState, peBundle) {
|
|
@@ -406,6 +398,38 @@ function buildWorkHubLifecycleResult(roleKey, testCase, started, pollState, peBu
|
|
|
406
398
|
};
|
|
407
399
|
}
|
|
408
400
|
|
|
401
|
+
async function finishWorkHubAfterPoll(args) {
|
|
402
|
+
const {
|
|
403
|
+
roleKey,
|
|
404
|
+
testCase,
|
|
405
|
+
started,
|
|
406
|
+
pollState,
|
|
407
|
+
dataplaneUrl,
|
|
408
|
+
authConfig,
|
|
409
|
+
options
|
|
410
|
+
} = args;
|
|
411
|
+
const processExecutionId = extractPeFromTask(pollState.finalTask);
|
|
412
|
+
if (!processExecutionId) {
|
|
413
|
+
throw new Error(`Work Hub task ${started.taskId} finished without processExecutionId.`);
|
|
414
|
+
}
|
|
415
|
+
const { persistRoleAssistantDebugLog } = require('./test-runner-debug');
|
|
416
|
+
const peBundle = {
|
|
417
|
+
processExecutionId,
|
|
418
|
+
...(await fetchBusinessResult(dataplaneUrl, authConfig, processExecutionId, options))
|
|
419
|
+
};
|
|
420
|
+
await persistRoleAssistantDebugLog(
|
|
421
|
+
roleKey,
|
|
422
|
+
{
|
|
423
|
+
processExecutionId,
|
|
424
|
+
requestedDepth: options && options.debug === true ? 'technical' : 'business',
|
|
425
|
+
workResult: peBundle.workResult,
|
|
426
|
+
workResultError: peBundle.workResultError
|
|
427
|
+
},
|
|
428
|
+
options
|
|
429
|
+
);
|
|
430
|
+
return buildWorkHubLifecycleResult(roleKey, testCase, started, pollState, peBundle);
|
|
431
|
+
}
|
|
432
|
+
|
|
409
433
|
async function runWorkHubCaseLifecycle(roleKey, testCase, runtimeContext, options = {}) {
|
|
410
434
|
const { startWorkHubOrSoftClarify } = require('./test-runner-workhub-soft');
|
|
411
435
|
const dataplaneUrl = runtimeContext?.dataplaneUrl;
|
|
@@ -440,15 +464,15 @@ async function runWorkHubCaseLifecycle(roleKey, testCase, runtimeContext, option
|
|
|
440
464
|
testCase,
|
|
441
465
|
options
|
|
442
466
|
);
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
467
|
+
return finishWorkHubAfterPoll({
|
|
468
|
+
roleKey,
|
|
469
|
+
testCase,
|
|
470
|
+
started,
|
|
471
|
+
pollState,
|
|
472
|
+
dataplaneUrl,
|
|
473
|
+
authConfig,
|
|
474
|
+
options
|
|
475
|
+
});
|
|
452
476
|
}
|
|
453
477
|
|
|
454
478
|
module.exports = {
|
|
@@ -24,6 +24,7 @@ const {
|
|
|
24
24
|
resolveInputObject,
|
|
25
25
|
resolveInputMessage
|
|
26
26
|
} = require('./test-runner-start-payload');
|
|
27
|
+
const { pickHumanRespondBody } = require('./test-runner-respond-body');
|
|
27
28
|
const TERMINAL_STATUSES = new Set(['completed', 'stopped']);
|
|
28
29
|
const WAITING_STATUS = 'waiting';
|
|
29
30
|
|
|
@@ -74,6 +75,7 @@ function isExecutableRoleAssistantCase(testCase) {
|
|
|
74
75
|
|
|
75
76
|
function extractProcessExecutionId(startResponse) {
|
|
76
77
|
const candidates = [
|
|
78
|
+
startResponse?.work?.processExecutionId,
|
|
77
79
|
startResponse?.intent?.processExecutionId,
|
|
78
80
|
startResponse?.processExecutionId,
|
|
79
81
|
startResponse?.status?.processExecutionId
|
|
@@ -111,6 +113,8 @@ function collectWaitMatchTokens(wait) {
|
|
|
111
113
|
add(wait.objectRef.name);
|
|
112
114
|
add(wait.objectRef.type);
|
|
113
115
|
add(wait.objectRef.id);
|
|
116
|
+
add(wait.objectRef.capabilityKey);
|
|
117
|
+
add(wait.objectRef.resourceType);
|
|
114
118
|
}
|
|
115
119
|
if (wait.safeProjection && typeof wait.safeProjection === 'object') {
|
|
116
120
|
add(wait.safeProjection.capabilityKey);
|
|
@@ -197,22 +201,40 @@ function applyWaitVersioningFields(payload, wait) {
|
|
|
197
201
|
applyOptionalStringField(payload, wait.requestFingerprint, 'requestFingerprint');
|
|
198
202
|
}
|
|
199
203
|
|
|
204
|
+
function waitIsChoice(wait) {
|
|
205
|
+
const ids = wait && Array.isArray(wait.allowedChoiceIds) ? wait.allowedChoiceIds : [];
|
|
206
|
+
return String((wait && wait.interactionKind) || '').toLowerCase() === 'choice' || ids.length > 0;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function choiceIdFromAnswer(answerEntry, respond) {
|
|
210
|
+
if (typeof respond.selectedOptionId === 'string' && respond.selectedOptionId.trim()) {
|
|
211
|
+
return respond.selectedOptionId.trim();
|
|
212
|
+
}
|
|
213
|
+
if (typeof answerEntry?.value === 'string' && answerEntry.value.trim()) {
|
|
214
|
+
return answerEntry.value.trim();
|
|
215
|
+
}
|
|
216
|
+
return '';
|
|
217
|
+
}
|
|
218
|
+
|
|
200
219
|
function buildAskRespondPayload(answerEntry, wait) {
|
|
201
220
|
const respond = answerEntry && typeof answerEntry.respond === 'object' && answerEntry.respond
|
|
202
221
|
? answerEntry.respond
|
|
203
222
|
: {};
|
|
204
223
|
const payload = {
|
|
205
224
|
respondIdempotencyKey: buildRuntimeId('ra-answer'),
|
|
206
|
-
answerType: 'ask'
|
|
207
|
-
value: resolveAskRespondValue(respond)
|
|
225
|
+
answerType: 'ask'
|
|
208
226
|
};
|
|
209
|
-
|
|
210
|
-
|
|
227
|
+
if (waitIsChoice(wait)) {
|
|
228
|
+
applyOptionalStringField(payload, choiceIdFromAnswer(answerEntry, respond), 'selectedOptionId');
|
|
229
|
+
} else {
|
|
230
|
+
payload.value = resolveAskRespondValue(Object.keys(respond).length ? respond : answerEntry);
|
|
231
|
+
applyOptionalStringField(payload, respond.evidenceRef, 'evidenceRef');
|
|
232
|
+
}
|
|
211
233
|
if (respond.declined === true) {
|
|
212
234
|
payload.declined = true;
|
|
213
235
|
}
|
|
214
236
|
applyWaitVersioningFields(payload, wait);
|
|
215
|
-
return payload;
|
|
237
|
+
return pickHumanRespondBody(payload);
|
|
216
238
|
}
|
|
217
239
|
|
|
218
240
|
function buildApprovalRespondPayload(approvalEntry, wait) {
|
|
@@ -228,7 +250,7 @@ function buildApprovalRespondPayload(approvalEntry, wait) {
|
|
|
228
250
|
approvalDecision: decision
|
|
229
251
|
};
|
|
230
252
|
applyWaitVersioningFields(payload, wait);
|
|
231
|
-
return payload;
|
|
253
|
+
return pickHumanRespondBody(payload);
|
|
232
254
|
}
|
|
233
255
|
|
|
234
256
|
function buildStatusSnapshot(statusRow) {
|
|
@@ -247,7 +269,8 @@ function buildRunnerOptions(options = {}) {
|
|
|
247
269
|
return {
|
|
248
270
|
maxStatusPolls: Number.isFinite(maxStatusPolls) && maxStatusPolls > 0 ? maxStatusPolls : 20,
|
|
249
271
|
statusPollIntervalMs:
|
|
250
|
-
Number.isFinite(statusPollIntervalMs) && statusPollIntervalMs >= 0 ? statusPollIntervalMs : 750
|
|
272
|
+
Number.isFinite(statusPollIntervalMs) && statusPollIntervalMs >= 0 ? statusPollIntervalMs : 750,
|
|
273
|
+
debug: options.debug === true
|
|
251
274
|
};
|
|
252
275
|
}
|
|
253
276
|
|
|
@@ -270,6 +293,18 @@ function finalizeWaitingAdvanceStatus(respondResult, continueResult) {
|
|
|
270
293
|
: afterRespondStatus;
|
|
271
294
|
}
|
|
272
295
|
|
|
296
|
+
async function continueAfterRespond(dataplaneUrl, authConfig, processExecutionId) {
|
|
297
|
+
try {
|
|
298
|
+
return await continueWorkExecution(dataplaneUrl, authConfig, processExecutionId, {});
|
|
299
|
+
} catch (error) {
|
|
300
|
+
const text = String(error && error.message ? error.message : error);
|
|
301
|
+
if (/already terminal/i.test(text)) {
|
|
302
|
+
return getWorkExecutionStatus(dataplaneUrl, authConfig, processExecutionId);
|
|
303
|
+
}
|
|
304
|
+
throw error;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
273
308
|
async function advanceApprovalWaitingExecution(context, approvals, wait) {
|
|
274
309
|
const { dataplaneUrl, authConfig, processExecutionId, usedApprovalIndexes } = context;
|
|
275
310
|
const match = findMatchingEntry(approvals, usedApprovalIndexes, wait);
|
|
@@ -279,7 +314,7 @@ async function advanceApprovalWaitingExecution(context, approvals, wait) {
|
|
|
279
314
|
usedApprovalIndexes.add(match.index);
|
|
280
315
|
const payload = buildApprovalRespondPayload(match.entry, wait);
|
|
281
316
|
const respondResult = await respondWorkExecution(dataplaneUrl, authConfig, processExecutionId, payload);
|
|
282
|
-
const continueResult = await
|
|
317
|
+
const continueResult = await continueAfterRespond(dataplaneUrl, authConfig, processExecutionId);
|
|
283
318
|
return {
|
|
284
319
|
status: finalizeWaitingAdvanceStatus(respondResult, continueResult),
|
|
285
320
|
matched: true,
|
|
@@ -297,7 +332,7 @@ async function advanceAskWaitingExecution(context, answers, wait) {
|
|
|
297
332
|
usedAnswerIndexes.add(match.index);
|
|
298
333
|
const payload = buildAskRespondPayload(match.entry, wait);
|
|
299
334
|
const respondResult = await respondWorkExecution(dataplaneUrl, authConfig, processExecutionId, payload);
|
|
300
|
-
const continueResult = await
|
|
335
|
+
const continueResult = await continueAfterRespond(dataplaneUrl, authConfig, processExecutionId);
|
|
301
336
|
return {
|
|
302
337
|
status: finalizeWaitingAdvanceStatus(respondResult, continueResult),
|
|
303
338
|
matched: true,
|
|
@@ -344,7 +379,11 @@ async function pollCaseExecutionStatus(dataplaneUrl, authConfig, processExecutio
|
|
|
344
379
|
type: advanced.interactionType,
|
|
345
380
|
waitReason: wait.waitReason || wait.answerType || wait.interactionKind || null,
|
|
346
381
|
matched: advanced.matched === true,
|
|
347
|
-
questionKey:
|
|
382
|
+
questionKey:
|
|
383
|
+
wait.questionKey ||
|
|
384
|
+
wait.requestKey ||
|
|
385
|
+
(wait.objectRef && wait.objectRef.capabilityKey) ||
|
|
386
|
+
null
|
|
348
387
|
});
|
|
349
388
|
if (!advanced.matched || !advanced.status) {
|
|
350
389
|
break;
|
|
@@ -451,6 +490,7 @@ function lifecycleVerdictFromCaseExecution(executionResult, fallbackVerdict) {
|
|
|
451
490
|
module.exports = {
|
|
452
491
|
isExecutableRoleAssistantCase,
|
|
453
492
|
buildStartIntentPayload,
|
|
493
|
+
buildRunnerOptions,
|
|
454
494
|
runRoleAssistantCaseLifecycle,
|
|
455
495
|
mergeCaseExecutionIntoLifecycleResult,
|
|
456
496
|
lifecycleVerdictFromCaseExecution
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"key":"external-datasource-schema",
|
|
8
8
|
"name":"External Data Source Configuration Schema",
|
|
9
9
|
"description":"JSON schema for validating ExternalDataSource configuration files",
|
|
10
|
-
"version":"2.9.
|
|
10
|
+
"version":"2.9.11",
|
|
11
11
|
"type":"schema",
|
|
12
12
|
"category":"integration",
|
|
13
13
|
"author":"AI Fabrix Team",
|
|
14
14
|
"createdAt":"2024-01-01T00:00:00Z",
|
|
15
|
-
"updatedAt":"2026-08-
|
|
15
|
+
"updatedAt":"2026-08-30T00:00:00Z",
|
|
16
16
|
"compatibility":{
|
|
17
17
|
"minVersion":"1.0.0",
|
|
18
18
|
"maxVersion":"3.0.0",
|
|
@@ -31,6 +31,22 @@
|
|
|
31
31
|
"external-system.schema.json"
|
|
32
32
|
],
|
|
33
33
|
"changelog":[
|
|
34
|
+
{
|
|
35
|
+
"version":"2.9.11",
|
|
36
|
+
"date":"2026-08-30T00:00:00Z",
|
|
37
|
+
"changes":[
|
|
38
|
+
"Documented fieldMappings.attributes.expression closed pipe-function allow-list (toLower, toUpper, trim, substring, replace, default, coalesce, join, split, normalizeWhitespace, index). CIP $defs unchanged (543 visual N/A)."
|
|
39
|
+
],
|
|
40
|
+
"breaking":false
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"version":"2.9.10",
|
|
44
|
+
"date":"2026-08-29T00:00:00Z",
|
|
45
|
+
"changes":[
|
|
46
|
+
"Added optional sync.incrementalKey (CIP list fetch.query filter already on the list operation) and optional sync.incrementalSchedule (only when incrementalKey is set). schedule is the full-set (sync all) cron. CIP $defs unchanged (543 visual N/A)."
|
|
47
|
+
],
|
|
48
|
+
"breaking":false
|
|
49
|
+
},
|
|
34
50
|
{
|
|
35
51
|
"version":"2.9.9",
|
|
36
52
|
"date":"2026-08-27T00:00:00Z",
|
|
@@ -623,7 +639,7 @@
|
|
|
623
639
|
"properties":{
|
|
624
640
|
"expression":{
|
|
625
641
|
"type":"string",
|
|
626
|
-
"description":"Pipe-based DSL expression. Allowed roots: raw.<path>, fk.<fk>.metadata.<field>, fk.<fk>.dimension.<dimension>[.label], dimension.<dimension>[.label]. FK traversal in DSL is one-hop only.",
|
|
642
|
+
"description":"Pipe-based DSL expression. Allowed roots: raw.<path>, fk.<fk>.metadata.<field>, fk.<fk>.dimension.<dimension>[.label], dimension.<dimension>[.label]. FK traversal in DSL is one-hop only. Closed pipe functions: toLower, toUpper, trim, substring, replace, default, coalesce, join, split, normalizeWhitespace, index.",
|
|
627
643
|
"maxLength":512,
|
|
628
644
|
"pattern":"^\\s*\\{\\{(raw\\.[a-zA-Z0-9_\\[\\].]+|fk\\.[a-z][a-zA-Z0-9]*\\.metadata\\.[a-z][a-zA-Z0-9]*|fk\\.[a-z][a-zA-Z0-9]*\\.dimension\\.[a-zA-Z0-9_]+(\\.label)?|dimension\\.[a-zA-Z0-9_]+(\\.label)?)\\}\\}(\\s*\\|\\s*[a-zA-Z0-9_]+(\\([^)]*\\))?)*\\s*$"
|
|
629
645
|
},
|
|
@@ -857,7 +873,7 @@
|
|
|
857
873
|
},
|
|
858
874
|
"schedule":{
|
|
859
875
|
"type":"string",
|
|
860
|
-
"description":"Cron
|
|
876
|
+
"description":"Cron for full-set (sync all) jobs. Supports 5-field cron syntax or @hourly/@daily/@weekly/@monthly.",
|
|
861
877
|
"pattern":"^(@hourly|@daily|@weekly|@monthly|([0-9*/,-]+\\s+){4}[0-9*/,-]+)$"
|
|
862
878
|
},
|
|
863
879
|
"batchSize":{
|
|
@@ -865,8 +881,23 @@
|
|
|
865
881
|
"minimum":1,
|
|
866
882
|
"maximum":10000,
|
|
867
883
|
"default":500
|
|
884
|
+
},
|
|
885
|
+
"incrementalKey":{
|
|
886
|
+
"type":"string",
|
|
887
|
+
"description":"Name of the list CIP fetch.query filter already authored on the list operation. Must map to a metadataSchema field of type date, date-time, or integer (unix time). Incremental jobs bind lastSyncedAt into that key. Never inferred from field names.",
|
|
888
|
+
"pattern":"^[a-zA-Z_$][a-zA-Z0-9_$]*$"
|
|
889
|
+
},
|
|
890
|
+
"incrementalSchedule":{
|
|
891
|
+
"type":"string",
|
|
892
|
+
"description":"Optional cron for incremental jobs. Allowed only when incrementalKey is set. schedule remains the full-set (sync all) cron.",
|
|
893
|
+
"pattern":"^(@hourly|@daily|@weekly|@monthly|([0-9*/,-]+\\s+){4}[0-9*/,-]+)$"
|
|
868
894
|
}
|
|
869
895
|
},
|
|
896
|
+
"dependentRequired":{
|
|
897
|
+
"incrementalSchedule":[
|
|
898
|
+
"incrementalKey"
|
|
899
|
+
]
|
|
900
|
+
},
|
|
870
901
|
"additionalProperties":false
|
|
871
902
|
},
|
|
872
903
|
"openapi":{
|
|
@@ -3004,7 +3035,7 @@
|
|
|
3004
3035
|
"description":"Optional inline mapping overrides { normalizedField -> expression }.",
|
|
3005
3036
|
"additionalProperties":{
|
|
3006
3037
|
"type":"string",
|
|
3007
|
-
"description":"Pipe-based DSL expression overriding fieldMappings expression."
|
|
3038
|
+
"description":"Pipe-based DSL expression overriding fieldMappings expression. Same closed function allow-list as fieldMappings.attributes.expression."
|
|
3008
3039
|
}
|
|
3009
3040
|
}
|
|
3010
3041
|
},
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
"key": "external-system-schema",
|
|
8
8
|
"name": "External System Configuration Schema",
|
|
9
9
|
"description": "JSON schema for validating ExternalSystem configuration files",
|
|
10
|
-
"version": "1.
|
|
10
|
+
"version": "1.17.0",
|
|
11
11
|
"type": "schema",
|
|
12
12
|
"category": "integration",
|
|
13
13
|
"author": "AI Fabrix Team",
|
|
14
14
|
"createdAt": "2024-01-01T00:00:00Z",
|
|
15
|
-
"updatedAt": "2026-08-
|
|
15
|
+
"updatedAt": "2026-08-28T00:00:00Z",
|
|
16
16
|
"compatibility": {
|
|
17
17
|
"minVersion": "1.4.0",
|
|
18
18
|
"maxVersion": "2.0.0",
|
|
@@ -27,6 +27,14 @@
|
|
|
27
27
|
],
|
|
28
28
|
"dependencies": [],
|
|
29
29
|
"changelog": [
|
|
30
|
+
{
|
|
31
|
+
"version": "1.17.0",
|
|
32
|
+
"date": "2026-08-28T00:00:00Z",
|
|
33
|
+
"changes": [
|
|
34
|
+
"Added optional channel.status (visible | hide | coming-soon) for Channel Definition catalog and install. Omit for visible. hide: omitted from catalog and refused for new install. coming-soon: catalog read-only, new install refused."
|
|
35
|
+
],
|
|
36
|
+
"breaking": false
|
|
37
|
+
},
|
|
30
38
|
{
|
|
31
39
|
"version": "1.16.0",
|
|
32
40
|
"date": "2026-08-23T00:00:00Z",
|
|
@@ -1789,6 +1797,16 @@
|
|
|
1789
1797
|
"type": "boolean",
|
|
1790
1798
|
"default": false
|
|
1791
1799
|
},
|
|
1800
|
+
"status": {
|
|
1801
|
+
"type": "string",
|
|
1802
|
+
"enum": [
|
|
1803
|
+
"visible",
|
|
1804
|
+
"hide",
|
|
1805
|
+
"coming-soon"
|
|
1806
|
+
],
|
|
1807
|
+
"default": "visible",
|
|
1808
|
+
"description": "Channel catalog and install availability. Omit or visible: listed and installable. hide: omitted from the catalog; new install is refused (CLI and API). coming-soon: listed read-only with a coming-soon indication; new install is refused (CLI and API). Does not disable existing installations. Distinct from experimental (opt-in CLI)."
|
|
1809
|
+
},
|
|
1792
1810
|
"maxInstances": {
|
|
1793
1811
|
"type": "integer",
|
|
1794
1812
|
"minimum": 1,
|