@kubbisec/ai-linux-arm64 0.1.21 → 0.1.22
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/bundled/clarify/clarify-gate-state.d.ts +1 -1
- package/bundled/clarify/clarify-gate-state.js +3 -3
- package/bundled/clarify/clarify-gate.d.ts +21 -14
- package/bundled/clarify/clarify-gate.js +118 -111
- package/bundled/clarify/clarify-select-panel.d.ts +16 -9
- package/bundled/clarify/clarify-select-panel.js +65 -67
- package/bundled/clarify/clarify-ui-state.d.ts +12 -10
- package/bundled/clarify/clarify-ui-state.js +26 -26
- package/bundled/clarify/parse-clarify-answer.d.ts +29 -18
- package/bundled/clarify/parse-clarify-answer.js +39 -45
- package/bundled/clarify/question-format.d.ts +34 -23
- package/bundled/clarify/question-format.js +112 -119
- package/bundled/clarify/questionnaire-tool.d.ts +28 -17
- package/bundled/clarify/questionnaire-tool.js +180 -144
- package/bundled/clarify/scope-discovery.d.ts +8 -5
- package/bundled/clarify/scope-discovery.js +102 -110
- package/bundled/clarify/session-questionnaire.d.ts +48 -13
- package/bundled/clarify/session-questionnaire.js +304 -312
- package/bundled/clarify/session-questionnaire.types.d.ts +29 -27
- package/bundled/clarify/session-questionnaire.types.js +10 -10
- package/bundled/components/kubbisec-model-selector.d.ts +47 -34
- package/bundled/components/kubbisec-model-selector.js +187 -177
- package/bundled/config/config.d.ts +6 -6
- package/bundled/config/config.js +55 -55
- package/bundled/config/detect-local-llm-providers.d.ts +26 -16
- package/bundled/config/detect-local-llm-providers.js +130 -142
- package/bundled/config/ensure-kubbisec-project-settings.d.ts +9 -9
- package/bundled/config/ensure-kubbisec-project-settings.js +44 -48
- package/bundled/config/extended-context.d.ts +5 -6
- package/bundled/config/extended-context.js +23 -22
- package/bundled/config/feature-flags.d.ts +10 -2
- package/bundled/config/feature-flags.js +8 -2
- package/bundled/config/format-kubbisec-footer-status.d.ts +1 -1
- package/bundled/config/format-kubbisec-footer-status.js +26 -31
- package/bundled/config/kubbisec-extension-manifest.d.ts +22 -2
- package/bundled/config/kubbisec-extension-manifest.js +20 -20
- package/bundled/config/llm-config-mutations.d.ts +51 -25
- package/bundled/config/llm-config-mutations.js +173 -182
- package/bundled/config/llm-config.d.ts +54 -41
- package/bundled/config/llm-config.js +199 -199
- package/bundled/config/llm-provider-catalog.d.ts +18 -15
- package/bundled/config/llm-provider-catalog.js +45 -46
- package/bundled/config/materialize-kubbisec-pi-resources.d.ts +1 -1
- package/bundled/config/materialize-kubbisec-pi-resources.js +174 -183
- package/bundled/config/register-custom-llm-providers.d.ts +11 -5
- package/bundled/config/register-custom-llm-providers.js +17 -15
- package/bundled/config/register-kubbisec-llm-provider.d.ts +14 -10
- package/bundled/config/register-kubbisec-llm-provider.js +50 -42
- package/bundled/config/resolve-agents-context-file.d.ts +1 -1
- package/bundled/config/resolve-agents-context-file.js +33 -34
- package/bundled/config/resource-budget.d.ts +12 -12
- package/bundled/config/resource-budget.js +28 -28
- package/bundled/config/sync-kubbisec-pi-models.d.ts +6 -3
- package/bundled/config/sync-kubbisec-pi-models.js +58 -58
- package/bundled/copy/cli-reference-index.d.ts +3 -2
- package/bundled/copy/cli-reference-index.js +1 -1
- package/bundled/copy/kubbisec-shell-copy.d.ts +11 -6
- package/bundled/copy/kubbisec-shell-copy.js +1 -1
- package/bundled/extensions/cli-local-shared.d.ts +45 -26
- package/bundled/extensions/cli-local-shared.js +128 -118
- package/bundled/extensions/kubbisec-aspm-local.extension.d.ts +18 -15
- package/bundled/extensions/kubbisec-aspm-local.extension.js +118 -114
- package/bundled/extensions/kubbisec-brand.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-brand.extension.js +25 -25
- package/bundled/extensions/kubbisec-byok-provider.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-byok-provider.extension.js +2 -2
- package/bundled/extensions/kubbisec-clarify.extension.d.ts +64 -35
- package/bundled/extensions/kubbisec-clarify.extension.js +323 -305
- package/bundled/extensions/kubbisec-exit.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-exit.extension.js +29 -32
- package/bundled/extensions/kubbisec-extended-context.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-extended-context.extension.js +56 -43
- package/bundled/extensions/kubbisec-footer.extension.d.ts +14 -14
- package/bundled/extensions/kubbisec-footer.extension.js +205 -215
- package/bundled/extensions/kubbisec-github-local.extension.d.ts +26 -18
- package/bundled/extensions/kubbisec-github-local.extension.js +123 -116
- package/bundled/extensions/kubbisec-llm-config.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-llm-config.extension.js +200 -181
- package/bundled/extensions/kubbisec-memory.extension.d.ts +9 -7
- package/bundled/extensions/kubbisec-memory.extension.js +88 -95
- package/bundled/extensions/kubbisec-naus-local.extension.d.ts +18 -15
- package/bundled/extensions/kubbisec-naus-local.extension.js +132 -111
- package/bundled/extensions/kubbisec-platform-tools.extension.d.ts +31 -21
- package/bundled/extensions/kubbisec-platform-tools.extension.js +152 -152
- package/bundled/extensions/kubbisec-runtime-status.extension.d.ts +10 -8
- package/bundled/extensions/kubbisec-runtime-status.extension.js +15 -13
- package/bundled/extensions/kubbisec-scope.extension.d.ts +12 -7
- package/bundled/extensions/kubbisec-scope.extension.js +13 -13
- package/bundled/extensions/kubbisec-skill-mentions.extension.d.ts +27 -16
- package/bundled/extensions/kubbisec-skill-mentions.extension.js +73 -63
- package/bundled/extensions/kubbisec-skill-telemetry.extension.d.ts +2 -3
- package/bundled/extensions/kubbisec-skill-telemetry.extension.js +59 -64
- package/bundled/extensions/kubbisec-theme-lock.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-theme-lock.extension.js +33 -34
- package/bundled/extensions/kubbisec-ui.extension.d.ts +1 -1
- package/bundled/extensions/kubbisec-ui.extension.js +114 -109
- package/bundled/extensions/kubbisec-workflow.extension.d.ts +20 -18
- package/bundled/extensions/kubbisec-workflow.extension.js +138 -140
- package/bundled/node_modules/@aspm/shared/dist/redaction.test.d.ts +2 -0
- package/bundled/node_modules/@aspm/shared/dist/redaction.test.d.ts.map +1 -0
- package/bundled/node_modules/@aspm/shared/dist/redaction.test.js +626 -0
- package/bundled/node_modules/@aspm/shared/dist/redaction.test.js.map +1 -0
- package/bundled/resolve-bundled-dist-root.js +122 -131
- package/bundled/skills/at-path-mentions.d.ts +1 -1
- package/bundled/skills/at-path-mentions.js +146 -153
- package/bundled/skills/chat-mention-render.d.ts +2 -2
- package/bundled/skills/chat-mention-render.js +121 -126
- package/bundled/skills/chat-mentions.d.ts +17 -8
- package/bundled/skills/chat-mentions.js +76 -76
- package/bundled/skills/list-bundled-skills.d.ts +3 -3
- package/bundled/skills/list-bundled-skills.js +33 -35
- package/bundled/skills/skill-mention.d.ts +10 -2
- package/bundled/skills/skill-mention.js +10 -2
- package/bundled/theme/clear-terminal.d.ts +1 -1
- package/bundled/theme/clear-terminal.js +3 -4
- package/bundled/theme/footer-render-hook.d.ts +1 -1
- package/bundled/theme/footer-render-hook.js +3 -3
- package/bundled/theme/kubbisec-brand-fg.d.ts +1 -1
- package/bundled/theme/kubbisec-brand-fg.js +2 -2
- package/bundled/theme/kubbisec-menu-themes.d.ts +7 -7
- package/bundled/theme/kubbisec-menu-themes.js +30 -31
- package/bundled/theme/kubbisec-theme-name.d.ts +1 -1
- package/bundled/theme/kubbisec-theme-name.js +1 -1
- package/bundled/theme/patch-pi-settings-theme.runtime.d.ts +1 -1
- package/bundled/theme/patch-pi-settings-theme.runtime.js +11 -10
- package/bundled/theme/render-compact-header.d.ts +13 -5
- package/bundled/theme/render-compact-header.js +127 -129
- package/bundled/workflow/session-workflow-mode.d.ts +1 -1
- package/bundled/workflow/session-workflow-mode.js +33 -33
- package/package.json +1 -1
|
@@ -1,372 +1,364 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { getKubbisecConfigPath } from "@kubbisec/home";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
KUBBISEC_CONTEXT_DIR,
|
|
6
|
+
KUBBISEC_PROJECT_CONFIG_DIR,
|
|
7
|
+
} from "../config/ensure-kubbisec-project-settings.js";
|
|
5
8
|
import { syncExtendedContextFromFields } from "../config/extended-context.js";
|
|
6
9
|
import { resolveOptionLabel, severityFromOptionLabel } from "./question-format.js";
|
|
7
10
|
import { createEmptyFields, SESSION_QUESTIONNAIRE_SCHEMA } from "./session-questionnaire.types.js";
|
|
8
11
|
export const SESSION_QUESTIONNAIRE_FILENAME = "session-questionnaire.json";
|
|
9
12
|
export function resolveSessionQuestionnairePath(cwd) {
|
|
10
|
-
|
|
13
|
+
return path.join(
|
|
14
|
+
cwd,
|
|
15
|
+
KUBBISEC_PROJECT_CONFIG_DIR,
|
|
16
|
+
KUBBISEC_CONTEXT_DIR,
|
|
17
|
+
SESSION_QUESTIONNAIRE_FILENAME,
|
|
18
|
+
);
|
|
11
19
|
}
|
|
12
20
|
export function readDefaultProjectId() {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return undefined;
|
|
23
|
-
}
|
|
21
|
+
const fromEnv = process.env.KUBBISEC_CONTEXT_PROJECT_ID?.trim();
|
|
22
|
+
if (fromEnv) return fromEnv;
|
|
23
|
+
try {
|
|
24
|
+
const raw = fs.readFileSync(getKubbisecConfigPath(), "utf8");
|
|
25
|
+
const parsed = JSON.parse(raw);
|
|
26
|
+
return parsed.defaultProject?.trim() || undefined;
|
|
27
|
+
} catch {
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
24
30
|
}
|
|
25
31
|
function isRecord(value) {
|
|
26
|
-
|
|
32
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27
33
|
}
|
|
28
34
|
function parseFields(raw) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
const base = createEmptyFields();
|
|
36
|
+
if (!isRecord(raw)) return base;
|
|
37
|
+
if (Array.isArray(raw.projectIds)) {
|
|
38
|
+
base.projectIds = raw.projectIds.filter((id) => typeof id === "string");
|
|
39
|
+
}
|
|
40
|
+
if (typeof raw.severityMin === "string") base.severityMin = raw.severityMin;
|
|
41
|
+
if (raw.remediationMode === "auto" || raw.remediationMode === "suggestion") {
|
|
42
|
+
base.remediationMode = raw.remediationMode;
|
|
43
|
+
}
|
|
44
|
+
if (typeof raw.nausConstraints === "string") base.nausConstraints = raw.nausConstraints;
|
|
45
|
+
if (typeof raw.extendedContext === "boolean") base.extendedContext = raw.extendedContext;
|
|
46
|
+
if (typeof raw.customNotes === "string") base.customNotes = raw.customNotes;
|
|
47
|
+
if (isRecord(raw.extras)) {
|
|
48
|
+
for (const [key, value] of Object.entries(raw.extras)) {
|
|
49
|
+
if (typeof value === "string") base.extras[key] = value;
|
|
34
50
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (raw.remediationMode === "auto" || raw.remediationMode === "suggestion") {
|
|
38
|
-
base.remediationMode = raw.remediationMode;
|
|
39
|
-
}
|
|
40
|
-
if (typeof raw.nausConstraints === "string")
|
|
41
|
-
base.nausConstraints = raw.nausConstraints;
|
|
42
|
-
if (typeof raw.extendedContext === "boolean")
|
|
43
|
-
base.extendedContext = raw.extendedContext;
|
|
44
|
-
if (typeof raw.customNotes === "string")
|
|
45
|
-
base.customNotes = raw.customNotes;
|
|
46
|
-
if (isRecord(raw.extras)) {
|
|
47
|
-
for (const [key, value] of Object.entries(raw.extras)) {
|
|
48
|
-
if (typeof value === "string")
|
|
49
|
-
base.extras[key] = value;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
return base;
|
|
51
|
+
}
|
|
52
|
+
return base;
|
|
53
53
|
}
|
|
54
54
|
function applyDefaultProjectPrefill(fields) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
return fields;
|
|
60
|
-
return { ...fields, projectIds: [defaultProject] };
|
|
55
|
+
if (fields.projectIds.length > 0) return fields;
|
|
56
|
+
const defaultProject = readDefaultProjectId();
|
|
57
|
+
if (!defaultProject) return fields;
|
|
58
|
+
return { ...fields, projectIds: [defaultProject] };
|
|
61
59
|
}
|
|
62
60
|
function parsePending(raw) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const selectionMode = raw.selectionMode === "multi" ? "multi" : "single";
|
|
71
|
-
return { field: raw.field, questionMarkdown: raw.questionMarkdown, optionLabels, selectionMode };
|
|
61
|
+
if (!isRecord(raw)) return null;
|
|
62
|
+
if (typeof raw.field !== "string" || typeof raw.questionMarkdown !== "string") return null;
|
|
63
|
+
const optionLabels = Array.isArray(raw.optionLabels)
|
|
64
|
+
? raw.optionLabels.filter((v) => typeof v === "string")
|
|
65
|
+
: [];
|
|
66
|
+
const selectionMode = raw.selectionMode === "multi" ? "multi" : "single";
|
|
67
|
+
return { field: raw.field, questionMarkdown: raw.questionMarkdown, optionLabels, selectionMode };
|
|
72
68
|
}
|
|
73
69
|
function parseQuestionnaire(raw, sessionIdFallback) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
70
|
+
if (!isRecord(raw)) return null;
|
|
71
|
+
const sessionId =
|
|
72
|
+
typeof raw.sessionId === "string" && raw.sessionId.trim()
|
|
73
|
+
? raw.sessionId.trim()
|
|
74
|
+
: sessionIdFallback;
|
|
75
|
+
const status = raw.status === "ready" ? "ready" : "collecting";
|
|
76
|
+
const updatedAt =
|
|
77
|
+
typeof raw.updatedAt === "string" && raw.updatedAt.trim()
|
|
78
|
+
? raw.updatedAt
|
|
79
|
+
: new Date().toISOString();
|
|
80
|
+
const scenario =
|
|
81
|
+
raw.scenario === "plan" ||
|
|
82
|
+
raw.scenario === "explore" ||
|
|
83
|
+
raw.scenario === "review" ||
|
|
84
|
+
raw.scenario === "remediation"
|
|
85
|
+
? raw.scenario
|
|
86
|
+
: null;
|
|
87
|
+
return {
|
|
88
|
+
$schema: SESSION_QUESTIONNAIRE_SCHEMA,
|
|
89
|
+
sessionId,
|
|
90
|
+
status,
|
|
91
|
+
scenario,
|
|
92
|
+
updatedAt,
|
|
93
|
+
fields: applyDefaultProjectPrefill(parseFields(raw.fields)),
|
|
94
|
+
history: Array.isArray(raw.history) ? raw.history : [],
|
|
95
|
+
awaitingUserAnswer:
|
|
96
|
+
typeof raw.awaitingUserAnswer === "boolean" ? raw.awaitingUserAnswer : false,
|
|
97
|
+
pending: parsePending(raw.pending),
|
|
98
|
+
};
|
|
100
99
|
}
|
|
101
100
|
export function createCollectingQuestionnaire(sessionId) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
101
|
+
const now = new Date().toISOString();
|
|
102
|
+
return {
|
|
103
|
+
$schema: SESSION_QUESTIONNAIRE_SCHEMA,
|
|
104
|
+
sessionId,
|
|
105
|
+
status: "collecting",
|
|
106
|
+
scenario: null,
|
|
107
|
+
updatedAt: now,
|
|
108
|
+
fields: applyDefaultProjectPrefill(createEmptyFields()),
|
|
109
|
+
history: [],
|
|
110
|
+
awaitingUserAnswer: false,
|
|
111
|
+
pending: null,
|
|
112
|
+
};
|
|
114
113
|
}
|
|
115
114
|
export function readSessionQuestionnaire(cwd, sessionIdFallback) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
return createCollectingQuestionnaire(sessionIdFallback);
|
|
126
|
-
}
|
|
127
|
-
return parsed;
|
|
115
|
+
const filePath = resolveSessionQuestionnairePath(cwd);
|
|
116
|
+
try {
|
|
117
|
+
const raw = fs.readFileSync(filePath, "utf8");
|
|
118
|
+
const parsed = parseQuestionnaire(JSON.parse(raw), sessionIdFallback);
|
|
119
|
+
if (parsed) {
|
|
120
|
+
if (parsed.sessionId !== sessionIdFallback) {
|
|
121
|
+
if (parsed.status === "collecting" && parsed.awaitingUserAnswer && parsed.pending) {
|
|
122
|
+
return { ...parsed, sessionId: sessionIdFallback };
|
|
128
123
|
}
|
|
124
|
+
return createCollectingQuestionnaire(sessionIdFallback);
|
|
125
|
+
}
|
|
126
|
+
return parsed;
|
|
129
127
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
}
|
|
128
|
+
} catch (error) {
|
|
129
|
+
if (error.code !== "ENOENT") {
|
|
130
|
+
console.warn("[kubbisec-clarify] Invalid session questionnaire state; resetting.");
|
|
134
131
|
}
|
|
135
|
-
|
|
132
|
+
}
|
|
133
|
+
return createCollectingQuestionnaire(sessionIdFallback);
|
|
136
134
|
}
|
|
137
135
|
export function writeSessionQuestionnaire(cwd, questionnaire) {
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
136
|
+
const filePath = resolveSessionQuestionnairePath(cwd);
|
|
137
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o755 });
|
|
138
|
+
const payload = {
|
|
139
|
+
...questionnaire,
|
|
140
|
+
updatedAt: new Date().toISOString(),
|
|
141
|
+
};
|
|
142
|
+
const tmpPath = `${filePath}.${process.pid}.tmp`;
|
|
143
|
+
fs.writeFileSync(tmpPath, `${JSON.stringify(payload, null, 2)}\n`, {
|
|
144
|
+
encoding: "utf8",
|
|
145
|
+
mode: 0o600,
|
|
146
|
+
});
|
|
147
|
+
fs.renameSync(tmpPath, filePath);
|
|
150
148
|
}
|
|
151
149
|
export function hasMinimumRemediationScope(fields) {
|
|
152
|
-
|
|
150
|
+
return (
|
|
151
|
+
fields.projectIds.length > 0 && Boolean(fields.severityMin) && Boolean(fields.remediationMode)
|
|
152
|
+
);
|
|
153
153
|
}
|
|
154
154
|
export function hasMinimumPlanScope(fields) {
|
|
155
|
-
|
|
155
|
+
return fields.projectIds.length > 0 && Boolean(fields.customNotes?.trim());
|
|
156
156
|
}
|
|
157
157
|
export function hasMinimumScopeForScenario(scenario, fields) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
}
|
|
158
|
+
switch (scenario) {
|
|
159
|
+
case "plan":
|
|
160
|
+
return hasMinimumPlanScope(fields);
|
|
161
|
+
case "explore":
|
|
162
|
+
case "review":
|
|
163
|
+
return fields.projectIds.length > 0;
|
|
164
|
+
default:
|
|
165
|
+
return hasMinimumRemediationScope(fields);
|
|
166
|
+
}
|
|
168
167
|
}
|
|
169
168
|
export function setFieldValue(fields, field, value) {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
169
|
+
const next = {
|
|
170
|
+
...fields,
|
|
171
|
+
projectIds: [...fields.projectIds],
|
|
172
|
+
extras: { ...fields.extras },
|
|
173
|
+
};
|
|
174
|
+
switch (field) {
|
|
175
|
+
case "projectIds":
|
|
176
|
+
next.projectIds = value ? [value] : [];
|
|
177
|
+
break;
|
|
178
|
+
case "severityMin":
|
|
179
|
+
next.severityMin = severityFromOptionLabel(value);
|
|
180
|
+
break;
|
|
181
|
+
case "remediationMode":
|
|
182
|
+
next.remediationMode = /sugest|suggest|manual|híbrido|hibrido|plano/i.test(value)
|
|
183
|
+
? "suggestion"
|
|
184
|
+
: "auto";
|
|
185
|
+
break;
|
|
186
|
+
case "nausConstraints":
|
|
187
|
+
next.nausConstraints = value;
|
|
188
|
+
break;
|
|
189
|
+
case "extendedContext":
|
|
190
|
+
next.extendedContext = /^(sim|yes|true|1|a)$/i.test(value);
|
|
191
|
+
break;
|
|
192
|
+
case "customNotes":
|
|
193
|
+
next.customNotes = [next.customNotes, value].filter(Boolean).join("\n") || value;
|
|
194
|
+
break;
|
|
195
|
+
default:
|
|
196
|
+
next.extras[field] = value;
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
return next;
|
|
201
200
|
}
|
|
202
201
|
export function mergeRecordedFields(fields, partial) {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
202
|
+
const next = { ...fields, projectIds: [...fields.projectIds], extras: { ...fields.extras } };
|
|
203
|
+
if (Array.isArray(partial.projectIds)) {
|
|
204
|
+
next.projectIds = partial.projectIds.filter((id) => typeof id === "string");
|
|
205
|
+
}
|
|
206
|
+
if (typeof partial.severityMin === "string") next.severityMin = partial.severityMin;
|
|
207
|
+
if (partial.remediationMode === "auto" || partial.remediationMode === "suggestion") {
|
|
208
|
+
next.remediationMode = partial.remediationMode;
|
|
209
|
+
}
|
|
210
|
+
if (typeof partial.nausConstraints === "string") next.nausConstraints = partial.nausConstraints;
|
|
211
|
+
if (typeof partial.extendedContext === "boolean") next.extendedContext = partial.extendedContext;
|
|
212
|
+
if (typeof partial.customNotes === "string") next.customNotes = partial.customNotes;
|
|
213
|
+
for (const [key, value] of Object.entries(partial)) {
|
|
214
|
+
if (
|
|
215
|
+
key === "projectIds" ||
|
|
216
|
+
key === "severityMin" ||
|
|
217
|
+
key === "remediationMode" ||
|
|
218
|
+
key === "nausConstraints" ||
|
|
219
|
+
key === "extendedContext" ||
|
|
220
|
+
key === "customNotes" ||
|
|
221
|
+
key === "extras"
|
|
222
|
+
) {
|
|
223
|
+
continue;
|
|
211
224
|
}
|
|
212
|
-
if (typeof
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
next.extendedContext = partial.extendedContext;
|
|
216
|
-
if (typeof partial.customNotes === "string")
|
|
217
|
-
next.customNotes = partial.customNotes;
|
|
218
|
-
for (const [key, value] of Object.entries(partial)) {
|
|
219
|
-
if (key === "projectIds" ||
|
|
220
|
-
key === "severityMin" ||
|
|
221
|
-
key === "remediationMode" ||
|
|
222
|
-
key === "nausConstraints" ||
|
|
223
|
-
key === "extendedContext" ||
|
|
224
|
-
key === "customNotes" ||
|
|
225
|
-
key === "extras") {
|
|
226
|
-
continue;
|
|
227
|
-
}
|
|
228
|
-
if (typeof value === "string")
|
|
229
|
-
next.extras[key] = value;
|
|
230
|
-
}
|
|
231
|
-
return next;
|
|
225
|
+
if (typeof value === "string") next.extras[key] = value;
|
|
226
|
+
}
|
|
227
|
+
return next;
|
|
232
228
|
}
|
|
233
229
|
export function askQuestion(questionnaire, input) {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
230
|
+
const now = new Date().toISOString();
|
|
231
|
+
return {
|
|
232
|
+
...questionnaire,
|
|
233
|
+
status: "collecting",
|
|
234
|
+
scenario: input.scenario ?? questionnaire.scenario,
|
|
235
|
+
awaitingUserAnswer: true,
|
|
236
|
+
pending: {
|
|
237
|
+
field: input.field,
|
|
238
|
+
questionMarkdown: input.questionMarkdown,
|
|
239
|
+
optionLabels: input.optionLabels,
|
|
240
|
+
selectionMode: input.selectionMode ?? "single",
|
|
241
|
+
},
|
|
242
|
+
updatedAt: now,
|
|
243
|
+
};
|
|
248
244
|
}
|
|
249
245
|
export function completeQuestionnaire(questionnaire) {
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
246
|
+
return {
|
|
247
|
+
...questionnaire,
|
|
248
|
+
status: "ready",
|
|
249
|
+
awaitingUserAnswer: false,
|
|
250
|
+
pending: null,
|
|
251
|
+
updatedAt: new Date().toISOString(),
|
|
252
|
+
};
|
|
257
253
|
}
|
|
258
254
|
const MIN_CUSTOM_ANSWER_LENGTH = 3;
|
|
259
255
|
export function shouldAcceptClarifyAnswer(questionnaire, parsed) {
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (
|
|
265
|
-
|
|
266
|
-
return true;
|
|
267
|
-
if (parsed.kind === "custom") {
|
|
268
|
-
return parsed.text.trim().length >= MIN_CUSTOM_ANSWER_LENGTH;
|
|
269
|
-
}
|
|
270
|
-
return false;
|
|
256
|
+
if (parsed.kind === "invalid") return false;
|
|
257
|
+
if (parsed.kind === "ready") return true;
|
|
258
|
+
if (questionnaire.awaitingUserAnswer && questionnaire.pending) {
|
|
259
|
+
if (parsed.kind === "option" || parsed.kind === "multi") return true;
|
|
260
|
+
if (parsed.kind === "custom") {
|
|
261
|
+
return parsed.text.trim().length >= MIN_CUSTOM_ANSWER_LENGTH;
|
|
271
262
|
}
|
|
272
|
-
return
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
return parsed.kind === "option" || parsed.kind === "multi";
|
|
273
266
|
}
|
|
274
267
|
export function applyPendingAnswer(questionnaire, answer) {
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
const value = labels.length > 0 ? labels.join(", ") : answer.optionIds.join(",");
|
|
293
|
-
const fields = setFieldValue(questionnaire.fields, pending.field, value);
|
|
294
|
-
const history = [
|
|
295
|
-
...questionnaire.history,
|
|
296
|
-
{
|
|
297
|
-
field: pending.field,
|
|
298
|
-
question: pending.questionMarkdown.split("\n")[0] ?? pending.field,
|
|
299
|
-
askedAt: now,
|
|
300
|
-
answer: { kind: "custom", text: value },
|
|
301
|
-
},
|
|
302
|
-
];
|
|
303
|
-
const multiNext = {
|
|
304
|
-
...questionnaire,
|
|
305
|
-
fields,
|
|
306
|
-
history,
|
|
307
|
-
awaitingUserAnswer: false,
|
|
308
|
-
pending: null,
|
|
309
|
-
updatedAt: now,
|
|
310
|
-
};
|
|
311
|
-
syncExtendedContextFromFields(multiNext.fields);
|
|
312
|
-
return multiNext;
|
|
313
|
-
}
|
|
314
|
-
let value = answer.kind === "custom"
|
|
315
|
-
? answer.text
|
|
316
|
-
: (answer.detail ??
|
|
317
|
-
resolveOptionLabel(answer.optionId, pending.optionLabels) ??
|
|
318
|
-
answer.optionId);
|
|
319
|
-
if (pending.field === "projectIds" && answer.kind === "option" && answer.optionId === "A") {
|
|
320
|
-
const label = resolveOptionLabel("A", pending.optionLabels) ?? "";
|
|
321
|
-
if (/padrão|padrao|sessão|sessao|default|session/i.test(label)) {
|
|
322
|
-
const defaultProject = readDefaultProjectId();
|
|
323
|
-
if (defaultProject)
|
|
324
|
-
value = defaultProject;
|
|
325
|
-
}
|
|
326
|
-
}
|
|
268
|
+
const pending = questionnaire.pending;
|
|
269
|
+
if (!pending) {
|
|
270
|
+
if (answer.kind === "ready") return completeQuestionnaire(questionnaire);
|
|
271
|
+
return questionnaire;
|
|
272
|
+
}
|
|
273
|
+
const now = new Date().toISOString();
|
|
274
|
+
if (answer.kind === "ready") {
|
|
275
|
+
return completeQuestionnaire(questionnaire);
|
|
276
|
+
}
|
|
277
|
+
if (answer.kind === "invalid") {
|
|
278
|
+
return { ...questionnaire, updatedAt: now };
|
|
279
|
+
}
|
|
280
|
+
if (answer.kind === "multi") {
|
|
281
|
+
const labels = answer.optionIds
|
|
282
|
+
.map((id) => resolveOptionLabel(id, pending.optionLabels))
|
|
283
|
+
.filter((label) => Boolean(label));
|
|
284
|
+
const value = labels.length > 0 ? labels.join(", ") : answer.optionIds.join(",");
|
|
327
285
|
const fields = setFieldValue(questionnaire.fields, pending.field, value);
|
|
328
286
|
const history = [
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
kind: "option",
|
|
337
|
-
optionId: answer.optionId,
|
|
338
|
-
detail: answer.detail,
|
|
339
|
-
label: resolveOptionLabel(answer.optionId, pending.optionLabels) ?? undefined,
|
|
340
|
-
}
|
|
341
|
-
: { kind: "custom", text: answer.text },
|
|
342
|
-
},
|
|
287
|
+
...questionnaire.history,
|
|
288
|
+
{
|
|
289
|
+
field: pending.field,
|
|
290
|
+
question: pending.questionMarkdown.split("\n")[0] ?? pending.field,
|
|
291
|
+
askedAt: now,
|
|
292
|
+
answer: { kind: "custom", text: value },
|
|
293
|
+
},
|
|
343
294
|
];
|
|
344
|
-
const
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
295
|
+
const multiNext = {
|
|
296
|
+
...questionnaire,
|
|
297
|
+
fields,
|
|
298
|
+
history,
|
|
299
|
+
awaitingUserAnswer: false,
|
|
300
|
+
pending: null,
|
|
301
|
+
updatedAt: now,
|
|
351
302
|
};
|
|
352
|
-
syncExtendedContextFromFields(
|
|
353
|
-
return
|
|
303
|
+
syncExtendedContextFromFields(multiNext.fields);
|
|
304
|
+
return multiNext;
|
|
305
|
+
}
|
|
306
|
+
let value =
|
|
307
|
+
answer.kind === "custom"
|
|
308
|
+
? answer.text
|
|
309
|
+
: (answer.detail ??
|
|
310
|
+
resolveOptionLabel(answer.optionId, pending.optionLabels) ??
|
|
311
|
+
answer.optionId);
|
|
312
|
+
if (pending.field === "projectIds" && answer.kind === "option" && answer.optionId === "A") {
|
|
313
|
+
const label = resolveOptionLabel("A", pending.optionLabels) ?? "";
|
|
314
|
+
if (/padrão|padrao|sessão|sessao|default|session/i.test(label)) {
|
|
315
|
+
const defaultProject = readDefaultProjectId();
|
|
316
|
+
if (defaultProject) value = defaultProject;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
const fields = setFieldValue(questionnaire.fields, pending.field, value);
|
|
320
|
+
const history = [
|
|
321
|
+
...questionnaire.history,
|
|
322
|
+
{
|
|
323
|
+
field: pending.field,
|
|
324
|
+
question: pending.questionMarkdown.split("\n")[0] ?? pending.field,
|
|
325
|
+
askedAt: now,
|
|
326
|
+
answer:
|
|
327
|
+
answer.kind === "option"
|
|
328
|
+
? {
|
|
329
|
+
kind: "option",
|
|
330
|
+
optionId: answer.optionId,
|
|
331
|
+
detail: answer.detail,
|
|
332
|
+
label: resolveOptionLabel(answer.optionId, pending.optionLabels) ?? undefined,
|
|
333
|
+
}
|
|
334
|
+
: { kind: "custom", text: answer.text },
|
|
335
|
+
},
|
|
336
|
+
];
|
|
337
|
+
const next = {
|
|
338
|
+
...questionnaire,
|
|
339
|
+
fields,
|
|
340
|
+
history,
|
|
341
|
+
awaitingUserAnswer: false,
|
|
342
|
+
pending: null,
|
|
343
|
+
updatedAt: now,
|
|
344
|
+
};
|
|
345
|
+
syncExtendedContextFromFields(next.fields);
|
|
346
|
+
return next;
|
|
354
347
|
}
|
|
355
348
|
export function finalizeQuestionnaireAtRoundLimit(questionnaire, maxRounds) {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
});
|
|
349
|
+
if (questionnaire.history.length < maxRounds) return questionnaire;
|
|
350
|
+
const note = `Questionnaire capped at ${maxRounds} rounds; proceeding with partial scope.`;
|
|
351
|
+
return completeQuestionnaire({
|
|
352
|
+
...questionnaire,
|
|
353
|
+
fields: {
|
|
354
|
+
...questionnaire.fields,
|
|
355
|
+
customNotes: [questionnaire.fields.customNotes, note].filter(Boolean).join("\n"),
|
|
356
|
+
},
|
|
357
|
+
});
|
|
366
358
|
}
|
|
367
359
|
export function buildClarifyProgressLabel(questionnaire) {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
360
|
+
const answered = questionnaire.history.length;
|
|
361
|
+
const total = Math.max(answered + (questionnaire.awaitingUserAnswer ? 1 : 0), 1);
|
|
362
|
+
return `Questionário · ${Math.min(answered + 1, total)}/${total}`;
|
|
371
363
|
}
|
|
372
|
-
//# sourceMappingURL=session-questionnaire.js.map
|
|
364
|
+
//# sourceMappingURL=session-questionnaire.js.map
|