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