@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
@@ -4,360 +4,378 @@
4
4
  import { randomUUID } from "node:crypto";
5
5
  import * as fs from "node:fs";
6
6
  import { getKubbisecConfigPath } from "@kubbisec/home";
7
- import { shouldClarify, } from "../clarify/clarify-gate.js";
7
+ import { shouldClarify } from "../clarify/clarify-gate.js";
8
8
  import { setClarifyGateActive } from "../clarify/clarify-gate-state.js";
9
9
  import { renderClarifySelectPanel } from "../clarify/clarify-select-panel.js";
10
- import { getClarifyUiSnapshot, resetClarifyUiSnapshot, setClarifyUiChangeListener, setClarifyUiSnapshot, } from "../clarify/clarify-ui-state.js";
10
+ import {
11
+ getClarifyUiSnapshot,
12
+ resetClarifyUiSnapshot,
13
+ setClarifyUiChangeListener,
14
+ setClarifyUiSnapshot,
15
+ } from "../clarify/clarify-ui-state.js";
11
16
  import { parseClarifyAnswer } from "../clarify/parse-clarify-answer.js";
12
17
  import { inferScenarioFromMessage } from "../clarify/question-format.js";
13
- import { applyParsedUserAnswerIfPending, executeQuestionnaireTool, questionnaireToolParametersSchema, } from "../clarify/questionnaire-tool.js";
18
+ import {
19
+ applyParsedUserAnswerIfPending,
20
+ executeQuestionnaireTool,
21
+ questionnaireToolParametersSchema,
22
+ } from "../clarify/questionnaire-tool.js";
14
23
  import { discoverScopeHints } from "../clarify/scope-discovery.js";
15
- import { buildClarifyProgressLabel, finalizeQuestionnaireAtRoundLimit, hasMinimumScopeForScenario, readDefaultProjectId, readSessionQuestionnaire, shouldAcceptClarifyAnswer, writeSessionQuestionnaire, } from "../clarify/session-questionnaire.js";
24
+ import {
25
+ buildClarifyProgressLabel,
26
+ finalizeQuestionnaireAtRoundLimit,
27
+ hasMinimumScopeForScenario,
28
+ readDefaultProjectId,
29
+ readSessionQuestionnaire,
30
+ shouldAcceptClarifyAnswer,
31
+ writeSessionQuestionnaire,
32
+ } from "../clarify/session-questionnaire.js";
16
33
  import { resolveResourceBudget } from "../config/resource-budget.js";
17
34
  import { getSessionWorkflowMode } from "../workflow/session-workflow-mode.js";
18
35
  export const CLARIFY_MUTATION_TOOLS = new Set([
19
- "edit",
20
- "write",
21
- "bash",
22
- "delete",
23
- "patch",
24
- "apply_patch",
25
- "set_pipeline_yaml",
36
+ "edit",
37
+ "write",
38
+ "bash",
39
+ "delete",
40
+ "patch",
41
+ "apply_patch",
42
+ "set_pipeline_yaml",
26
43
  ]);
27
44
  export const CLARIFY_READ_ONLY_TOOLS = new Set([
28
- "read",
29
- "grep",
30
- "find",
31
- "ls",
32
- "glob",
33
- "questionnaire",
34
- "aspm_docs",
35
- "naus_pipeline_docs",
36
- "list_findings",
45
+ "read",
46
+ "grep",
47
+ "find",
48
+ "ls",
49
+ "glob",
50
+ "questionnaire",
51
+ "aspm_docs",
52
+ "naus_pipeline_docs",
53
+ "list_findings",
37
54
  ]);
38
- export const CLARIFY_TOOL_BLOCK_REASON = "Complete o questionário de escopo (use o painel acima ou escreva a resposta) antes de editar ficheiros.";
55
+ export const CLARIFY_TOOL_BLOCK_REASON =
56
+ "Complete o questionário de escopo (use o painel acima ou escreva a resposta) antes de editar ficheiros.";
39
57
  export function isClarifyMutationTool(toolName) {
40
- if (CLARIFY_READ_ONLY_TOOLS.has(toolName))
41
- return false;
42
- return CLARIFY_MUTATION_TOOLS.has(toolName);
58
+ if (CLARIFY_READ_ONLY_TOOLS.has(toolName)) return false;
59
+ return CLARIFY_MUTATION_TOOLS.has(toolName);
43
60
  }
44
61
  export function shouldBlockClarifyTool(toolName, gateActive, questionnaire) {
45
- if (!gateActive)
46
- return false;
47
- if (!questionnaire || questionnaire.status === "ready")
48
- return false;
49
- if (!isClarifyMutationTool(toolName))
50
- return false;
51
- return true;
62
+ if (!gateActive) return false;
63
+ if (!questionnaire || questionnaire.status === "ready") return false;
64
+ if (!isClarifyMutationTool(toolName)) return false;
65
+ return true;
52
66
  }
53
67
  function readDefaultProjectConfigured() {
54
- if (readDefaultProjectId())
55
- return true;
56
- try {
57
- const raw = fs.readFileSync(getKubbisecConfigPath(), "utf8");
58
- const parsed = JSON.parse(raw);
59
- return Boolean(parsed.defaultProject?.trim());
60
- }
61
- catch {
62
- return false;
63
- }
68
+ if (readDefaultProjectId()) return true;
69
+ try {
70
+ const raw = fs.readFileSync(getKubbisecConfigPath(), "utf8");
71
+ const parsed = JSON.parse(raw);
72
+ return Boolean(parsed.defaultProject?.trim());
73
+ } catch {
74
+ return false;
75
+ }
64
76
  }
65
77
  export function detectChatMode(prompt) {
66
- if (getSessionWorkflowMode() === "plan") {
67
- return "plan";
68
- }
69
- const trimmed = prompt.trim();
70
- if (trimmed.startsWith("/mode:plan") ||
71
- /@plan\b/i.test(trimmed) ||
72
- /@planejar\b/i.test(trimmed)) {
73
- return "plan";
74
- }
75
- const envMode = process.env.KUBBISEC_CHAT_MODE?.trim().toLowerCase();
76
- if (envMode === "plan")
77
- return "plan";
78
- return "default";
78
+ if (getSessionWorkflowMode() === "plan") {
79
+ return "plan";
80
+ }
81
+ const trimmed = prompt.trim();
82
+ if (
83
+ trimmed.startsWith("/mode:plan") ||
84
+ /@plan\b/i.test(trimmed) ||
85
+ /@planejar\b/i.test(trimmed)
86
+ ) {
87
+ return "plan";
88
+ }
89
+ const envMode = process.env.KUBBISEC_CHAT_MODE?.trim().toLowerCase();
90
+ if (envMode === "plan") return "plan";
91
+ return "default";
79
92
  }
80
93
  function resolveSurface() {
81
- const surface = process.env.KUBBISEC_CLARIFY_SURFACE?.trim().toLowerCase();
82
- if (surface === "fix" || surface === "watch" || surface === "task-consumer") {
83
- return surface;
84
- }
85
- if (process.env.KUBBISEC_FIX_MODE === "1" || process.env.KUBBISEC_WATCH_MODE === "1") {
86
- return process.env.KUBBISEC_WATCH_MODE === "1" ? "watch" : "fix";
87
- }
88
- return "chat";
94
+ const surface = process.env.KUBBISEC_CLARIFY_SURFACE?.trim().toLowerCase();
95
+ if (surface === "fix" || surface === "watch" || surface === "task-consumer") {
96
+ return surface;
97
+ }
98
+ if (process.env.KUBBISEC_FIX_MODE === "1" || process.env.KUBBISEC_WATCH_MODE === "1") {
99
+ return process.env.KUBBISEC_WATCH_MODE === "1" ? "watch" : "fix";
100
+ }
101
+ return "chat";
89
102
  }
90
103
  function buildGateInput(prompt, questionnaire) {
91
- const msg = prompt.trim();
92
- const budget = resolveResourceBudget();
93
- const scenario = questionnaire.scenario ?? inferScenarioFromMessage(msg);
94
- return {
95
- surface: resolveSurface(),
96
- userMessage: msg,
97
- hasProjectId: readDefaultProjectConfigured() || questionnaire.fields.projectIds.length > 0,
98
- hasVulnerabilityId: /\b(cve-|vuln|finding)/i.test(msg),
99
- hasSeverityFilter: Boolean(questionnaire.fields.severityMin) || /\b(severity|critical|high)\b/i.test(msg),
100
- mode: detectChatMode(msg),
101
- scenario,
102
- questionnaireStatus: questionnaire.status,
103
- fields: questionnaire.fields,
104
- historyCount: questionnaire.history.length,
105
- clarifyMaxRounds: budget.clarifyMaxRounds,
106
- };
104
+ const msg = prompt.trim();
105
+ const budget = resolveResourceBudget();
106
+ const scenario = questionnaire.scenario ?? inferScenarioFromMessage(msg);
107
+ return {
108
+ surface: resolveSurface(),
109
+ userMessage: msg,
110
+ hasProjectId: readDefaultProjectConfigured() || questionnaire.fields.projectIds.length > 0,
111
+ hasVulnerabilityId: /\b(cve-|vuln|finding)/i.test(msg),
112
+ hasSeverityFilter:
113
+ Boolean(questionnaire.fields.severityMin) || /\b(severity|critical|high)\b/i.test(msg),
114
+ mode: detectChatMode(msg),
115
+ scenario,
116
+ questionnaireStatus: questionnaire.status,
117
+ fields: questionnaire.fields,
118
+ historyCount: questionnaire.history.length,
119
+ clarifyMaxRounds: budget.clarifyMaxRounds,
120
+ };
107
121
  }
108
122
  export function buildClarifyContextMessage(questionnaire) {
109
- const panelReady = questionnaire.awaitingUserAnswer && questionnaire.pending?.questionMarkdown;
110
- return `[SCOPE GATE — internal only, never repeat to user]
123
+ const panelReady = questionnaire.awaitingUserAnswer && questionnaire.pending?.questionMarkdown;
124
+ return `[SCOPE GATE — internal only, never repeat to user]
111
125
  ${panelReady ? "Questionnaire panel is visible — do NOT ask user to look at the panel." : "Scope still missing — questionnaire auto-ask may run."}
112
126
  Read-only until scope ready. User-facing replies: max 2 sentences; no chain-of-thought.
113
127
  ${questionnaire.awaitingUserAnswer ? "Wait for panel answer or free text." : "Use questionnaire record if user already gave scope in prose."}`;
114
128
  }
115
129
  function extractQuestionText(markdown) {
116
- for (const line of markdown.split("\n")) {
117
- const trimmed = line.trim();
118
- if (trimmed && !/^[A-D]\)/.test(trimmed))
119
- return trimmed;
120
- }
121
- return markdown.split("\n")[0]?.trim() ?? "";
130
+ for (const line of markdown.split("\n")) {
131
+ const trimmed = line.trim();
132
+ if (trimmed && !/^[A-D]\)/.test(trimmed)) return trimmed;
133
+ }
134
+ return markdown.split("\n")[0]?.trim() ?? "";
122
135
  }
123
136
  export function syncClarifyUi(questionnaire) {
124
- if (questionnaire.status === "ready") {
125
- setClarifyUiSnapshot({
126
- phase: "ready",
127
- progressLabel: null,
128
- questionMarkdown: null,
129
- questionText: null,
130
- optionLabels: [],
131
- selected: [],
132
- focusedIndex: 0,
133
- });
134
- return;
135
- }
136
- if (!questionnaire.awaitingUserAnswer || !questionnaire.pending?.questionMarkdown) {
137
- setClarifyUiSnapshot({
138
- phase: "idle",
139
- progressLabel: null,
140
- questionMarkdown: null,
141
- questionText: null,
142
- optionLabels: [],
143
- selected: [],
144
- focusedIndex: 0,
145
- });
146
- return;
147
- }
148
- const pending = questionnaire.pending;
137
+ if (questionnaire.status === "ready") {
149
138
  setClarifyUiSnapshot({
150
- phase: "asking",
151
- progressLabel: buildClarifyProgressLabel(questionnaire),
152
- questionMarkdown: pending.questionMarkdown,
153
- questionText: extractQuestionText(pending.questionMarkdown),
154
- optionLabels: pending.optionLabels,
155
- selectionMode: pending.selectionMode ?? "single",
156
- selected: [],
157
- focusedIndex: 0,
139
+ phase: "ready",
140
+ progressLabel: null,
141
+ questionMarkdown: null,
142
+ questionText: null,
143
+ optionLabels: [],
144
+ selected: [],
145
+ focusedIndex: 0,
158
146
  });
147
+ return;
148
+ }
149
+ if (!questionnaire.awaitingUserAnswer || !questionnaire.pending?.questionMarkdown) {
150
+ setClarifyUiSnapshot({
151
+ phase: "idle",
152
+ progressLabel: null,
153
+ questionMarkdown: null,
154
+ questionText: null,
155
+ optionLabels: [],
156
+ selected: [],
157
+ focusedIndex: 0,
158
+ });
159
+ return;
160
+ }
161
+ const pending = questionnaire.pending;
162
+ setClarifyUiSnapshot({
163
+ phase: "asking",
164
+ progressLabel: buildClarifyProgressLabel(questionnaire),
165
+ questionMarkdown: pending.questionMarkdown,
166
+ questionText: extractQuestionText(pending.questionMarkdown),
167
+ optionLabels: pending.optionLabels,
168
+ selectionMode: pending.selectionMode ?? "single",
169
+ selected: [],
170
+ focusedIndex: 0,
171
+ });
159
172
  }
160
173
  function applyDiscoveredScope(questionnaire, prompt, cwd) {
161
- const discovered = discoverScopeHints(cwd, prompt);
162
- if (!discovered.fields || Object.keys(discovered.fields).length === 0) {
163
- return questionnaire;
164
- }
165
- const result = executeQuestionnaireTool(questionnaire, {
166
- action: "record",
167
- scenario: discovered.scenario,
168
- fields: discovered.fields,
169
- });
170
- return result.questionnaire;
174
+ const discovered = discoverScopeHints(cwd, prompt);
175
+ if (!discovered.fields || Object.keys(discovered.fields).length === 0) {
176
+ return questionnaire;
177
+ }
178
+ const result = executeQuestionnaireTool(questionnaire, {
179
+ action: "record",
180
+ scenario: discovered.scenario,
181
+ fields: discovered.fields,
182
+ });
183
+ return result.questionnaire;
171
184
  }
172
185
  export function autoAskNextQuestion(questionnaire, prompt) {
173
- if (questionnaire.awaitingUserAnswer || questionnaire.status === "ready") {
174
- return questionnaire;
175
- }
176
- const scenario = questionnaire.scenario ?? inferScenarioFromMessage(prompt);
177
- const result = executeQuestionnaireTool(questionnaire, {
178
- action: "ask",
179
- scenario,
180
- });
181
- if (!result.ok)
182
- return questionnaire;
183
- return result.questionnaire;
186
+ if (questionnaire.awaitingUserAnswer || questionnaire.status === "ready") {
187
+ return questionnaire;
188
+ }
189
+ const scenario = questionnaire.scenario ?? inferScenarioFromMessage(prompt);
190
+ const result = executeQuestionnaireTool(questionnaire, {
191
+ action: "ask",
192
+ scenario,
193
+ });
194
+ if (!result.ok) return questionnaire;
195
+ return result.questionnaire;
184
196
  }
185
197
  function maybeMarkReady(questionnaire) {
186
- const scenario = questionnaire.scenario ?? "remediation";
187
- if (questionnaire.status === "collecting" &&
188
- !questionnaire.awaitingUserAnswer &&
189
- hasMinimumScopeForScenario(scenario, questionnaire.fields)) {
190
- return { ...questionnaire, status: "ready", pending: null };
191
- }
192
- return questionnaire;
198
+ const scenario = questionnaire.scenario ?? "remediation";
199
+ if (
200
+ questionnaire.status === "collecting" &&
201
+ !questionnaire.awaitingUserAnswer &&
202
+ hasMinimumScopeForScenario(scenario, questionnaire.fields)
203
+ ) {
204
+ return { ...questionnaire, status: "ready", pending: null };
205
+ }
206
+ return questionnaire;
193
207
  }
194
208
  export function updateClarifyStatus(ctx, questionnaire) {
195
- if (!ctx.hasUI)
196
- return;
197
- if (questionnaire.status === "ready") {
198
- ctx.ui.setStatus("kubbisec-clarify", undefined);
199
- return;
200
- }
201
- if (questionnaire.awaitingUserAnswer) {
202
- ctx.ui.setStatus("kubbisec-clarify", ctx.ui.theme.fg("warning", `questionário · ${questionnaire.status}`));
203
- return;
204
- }
209
+ if (!ctx.hasUI) return;
210
+ if (questionnaire.status === "ready") {
205
211
  ctx.ui.setStatus("kubbisec-clarify", undefined);
212
+ return;
213
+ }
214
+ if (questionnaire.awaitingUserAnswer) {
215
+ ctx.ui.setStatus(
216
+ "kubbisec-clarify",
217
+ ctx.ui.theme.fg("warning", `questionário · ${questionnaire.status}`),
218
+ );
219
+ return;
220
+ }
221
+ ctx.ui.setStatus("kubbisec-clarify", undefined);
206
222
  }
207
223
  export function processClarifyPrompt(questionnaire, prompt, cwd, clarifyMaxRounds) {
208
- let next = questionnaire;
209
- if (next.status === "collecting" && prompt.trim()) {
210
- const selectionMode = next.pending?.selectionMode ?? "single";
211
- const parsed = parseClarifyAnswer(prompt, selectionMode);
212
- if (shouldAcceptClarifyAnswer(next, parsed)) {
213
- next = applyParsedUserAnswerIfPending(next, parsed);
214
- next = finalizeQuestionnaireAtRoundLimit(next, clarifyMaxRounds);
215
- next = maybeMarkReady(next);
216
- }
224
+ let next = questionnaire;
225
+ if (next.status === "collecting" && prompt.trim()) {
226
+ const selectionMode = next.pending?.selectionMode ?? "single";
227
+ const parsed = parseClarifyAnswer(prompt, selectionMode);
228
+ if (shouldAcceptClarifyAnswer(next, parsed)) {
229
+ next = applyParsedUserAnswerIfPending(next, parsed);
230
+ next = finalizeQuestionnaireAtRoundLimit(next, clarifyMaxRounds);
231
+ next = maybeMarkReady(next);
217
232
  }
218
- next = applyDiscoveredScope(next, prompt, cwd);
219
- next = maybeMarkReady(next);
220
- return next;
233
+ }
234
+ next = applyDiscoveredScope(next, prompt, cwd);
235
+ next = maybeMarkReady(next);
236
+ return next;
221
237
  }
222
238
  export default function kubbisecClarify(api) {
223
- const sessionId = randomUUID();
224
- let questionnaire = readSessionQuestionnaire(process.cwd(), sessionId);
225
- let gateActive = false;
226
- let clarifyWidgetRegistered = false;
227
- let lastUserMessage = "";
228
- let sessionCwd = process.cwd();
229
- function persist(ctx, next) {
230
- questionnaire = next;
231
- try {
232
- writeSessionQuestionnaire(ctx.cwd, next);
233
- }
234
- catch (error) {
235
- console.warn("[kubbisec-clarify] Failed to persist session questionnaire:", error);
236
- }
237
- updateClarifyStatus(ctx, next);
238
- syncClarifyUi(next);
239
+ const sessionId = randomUUID();
240
+ let questionnaire = readSessionQuestionnaire(process.cwd(), sessionId);
241
+ let gateActive = false;
242
+ let clarifyWidgetRegistered = false;
243
+ let lastUserMessage = "";
244
+ let sessionCwd = process.cwd();
245
+ function persist(ctx, next) {
246
+ questionnaire = next;
247
+ try {
248
+ writeSessionQuestionnaire(ctx.cwd, next);
249
+ } catch (error) {
250
+ console.warn("[kubbisec-clarify] Failed to persist session questionnaire:", error);
239
251
  }
240
- function ensureClarifyWidget(ctx) {
241
- if (!ctx.hasUI || clarifyWidgetRegistered)
242
- return;
243
- clarifyWidgetRegistered = true;
244
- ctx.ui.setWidget("kubbisec-clarify-panel", (tui, theme) => {
245
- setClarifyUiChangeListener(() => {
246
- tui.requestRender();
247
- });
248
- return {
249
- dispose() {
250
- setClarifyUiChangeListener(undefined);
251
- },
252
- invalidate() {
253
- tui.requestRender();
254
- },
255
- render(w) {
256
- return renderClarifySelectPanel(w, getClarifyUiSnapshot(), theme);
257
- },
258
- };
259
- }, { placement: "aboveEditor" });
252
+ updateClarifyStatus(ctx, next);
253
+ syncClarifyUi(next);
254
+ }
255
+ function ensureClarifyWidget(ctx) {
256
+ if (!ctx.hasUI || clarifyWidgetRegistered) return;
257
+ clarifyWidgetRegistered = true;
258
+ ctx.ui.setWidget(
259
+ "kubbisec-clarify-panel",
260
+ (tui, theme) => {
261
+ setClarifyUiChangeListener(() => {
262
+ tui.requestRender();
263
+ });
264
+ return {
265
+ dispose() {
266
+ setClarifyUiChangeListener(undefined);
267
+ },
268
+ invalidate() {
269
+ tui.requestRender();
270
+ },
271
+ render(w) {
272
+ return renderClarifySelectPanel(w, getClarifyUiSnapshot(), theme);
273
+ },
274
+ };
275
+ },
276
+ { placement: "aboveEditor" },
277
+ );
278
+ }
279
+ api.registerTool({
280
+ name: "questionnaire",
281
+ label: "Scope questionnaire",
282
+ description:
283
+ "Format and track contextual scope questions (ask/record/status/complete). KubbiSec renders options in the panel above the editor.",
284
+ parameters: questionnaireToolParametersSchema(),
285
+ async execute(_toolCallId, params) {
286
+ const input = params;
287
+ const result = executeQuestionnaireTool(questionnaire, input, lastUserMessage);
288
+ questionnaire = result.questionnaire;
289
+ try {
290
+ writeSessionQuestionnaire(sessionCwd, questionnaire);
291
+ } catch {
292
+ // best effort
293
+ }
294
+ syncClarifyUi(questionnaire);
295
+ return {
296
+ content: [{ type: "text", text: result.message }],
297
+ details: { ok: result.ok, status: result.status, action: result.action },
298
+ };
299
+ },
300
+ });
301
+ api.on("session_start", async (_event, ctx) => {
302
+ sessionCwd = ctx.cwd;
303
+ questionnaire = readSessionQuestionnaire(ctx.cwd, sessionId);
304
+ gateActive = false;
305
+ setClarifyGateActive(false);
306
+ lastUserMessage = "";
307
+ resetClarifyUiSnapshot();
308
+ ensureClarifyWidget(ctx);
309
+ updateClarifyStatus(ctx, questionnaire);
310
+ syncClarifyUi(questionnaire);
311
+ });
312
+ api.on("session_shutdown", async () => {
313
+ resetClarifyUiSnapshot();
314
+ setClarifyGateActive(false);
315
+ });
316
+ api.on("before_agent_start", async (event, ctx) => {
317
+ const { prompt } = event;
318
+ lastUserMessage = prompt;
319
+ const surface = resolveSurface();
320
+ ensureClarifyWidget(ctx);
321
+ if (surface !== "chat") {
322
+ gateActive = false;
323
+ setClarifyGateActive(false);
324
+ resetClarifyUiSnapshot();
325
+ return undefined;
260
326
  }
261
- api.registerTool({
262
- name: "questionnaire",
263
- label: "Scope questionnaire",
264
- description: "Format and track contextual scope questions (ask/record/status/complete). KubbiSec renders options in the panel above the editor.",
265
- parameters: questionnaireToolParametersSchema(),
266
- async execute(_toolCallId, params) {
267
- const input = params;
268
- const result = executeQuestionnaireTool(questionnaire, input, lastUserMessage);
269
- questionnaire = result.questionnaire;
270
- try {
271
- writeSessionQuestionnaire(sessionCwd, questionnaire);
272
- }
273
- catch {
274
- // best effort
275
- }
276
- syncClarifyUi(questionnaire);
277
- return {
278
- content: [{ type: "text", text: result.message }],
279
- details: { ok: result.ok, status: result.status, action: result.action },
280
- };
281
- },
282
- });
283
- api.on("session_start", async (_event, ctx) => {
284
- sessionCwd = ctx.cwd;
285
- questionnaire = readSessionQuestionnaire(ctx.cwd, sessionId);
286
- gateActive = false;
287
- setClarifyGateActive(false);
288
- lastUserMessage = "";
289
- resetClarifyUiSnapshot();
290
- ensureClarifyWidget(ctx);
291
- updateClarifyStatus(ctx, questionnaire);
292
- syncClarifyUi(questionnaire);
293
- });
294
- api.on("session_shutdown", async () => {
295
- resetClarifyUiSnapshot();
296
- setClarifyGateActive(false);
297
- });
298
- api.on("before_agent_start", async (event, ctx) => {
299
- const { prompt } = event;
300
- lastUserMessage = prompt;
301
- const surface = resolveSurface();
302
- ensureClarifyWidget(ctx);
303
- if (surface !== "chat") {
304
- gateActive = false;
305
- setClarifyGateActive(false);
306
- resetClarifyUiSnapshot();
307
- return undefined;
308
- }
309
- const budget = resolveResourceBudget();
310
- let next = readSessionQuestionnaire(ctx.cwd, questionnaire.sessionId);
311
- next = processClarifyPrompt(next, prompt, ctx.cwd, budget.clarifyMaxRounds);
312
- const gateInput = buildGateInput(prompt, next);
313
- gateActive = shouldClarify(gateInput);
314
- setClarifyGateActive(gateActive);
315
- if (!gateActive) {
316
- next = maybeMarkReady(next);
317
- persist(ctx, next);
318
- return undefined;
319
- }
320
- if (next.status === "collecting" && !next.awaitingUserAnswer) {
321
- next = autoAskNextQuestion(next, prompt);
322
- next = maybeMarkReady(next);
323
- persist(ctx, next);
324
- if (next.awaitingUserAnswer) {
325
- return {
326
- message: {
327
- customType: "kubbisec-clarify",
328
- content: buildClarifyContextMessage(next),
329
- display: false,
330
- },
331
- };
332
- }
333
- return {
334
- message: {
335
- customType: "kubbisec-clarify",
336
- content: buildClarifyContextMessage(next),
337
- display: false,
338
- },
339
- };
340
- }
341
- persist(ctx, next);
342
- return undefined;
343
- });
344
- api.on("tool_call", async (event, ctx) => {
345
- const surface = resolveSurface();
346
- if (surface !== "chat") {
347
- return undefined;
348
- }
349
- questionnaire = readSessionQuestionnaire(ctx.cwd, questionnaire.sessionId);
350
- const { toolName } = event;
351
- if (toolName === "questionnaire") {
352
- return undefined;
353
- }
354
- if (!shouldBlockClarifyTool(toolName, gateActive, questionnaire)) {
355
- return undefined;
356
- }
327
+ const budget = resolveResourceBudget();
328
+ let next = readSessionQuestionnaire(ctx.cwd, questionnaire.sessionId);
329
+ next = processClarifyPrompt(next, prompt, ctx.cwd, budget.clarifyMaxRounds);
330
+ const gateInput = buildGateInput(prompt, next);
331
+ gateActive = shouldClarify(gateInput);
332
+ setClarifyGateActive(gateActive);
333
+ if (!gateActive) {
334
+ next = maybeMarkReady(next);
335
+ persist(ctx, next);
336
+ return undefined;
337
+ }
338
+ if (next.status === "collecting" && !next.awaitingUserAnswer) {
339
+ next = autoAskNextQuestion(next, prompt);
340
+ next = maybeMarkReady(next);
341
+ persist(ctx, next);
342
+ if (next.awaitingUserAnswer) {
357
343
  return {
358
- block: true,
359
- reason: CLARIFY_TOOL_BLOCK_REASON,
344
+ message: {
345
+ customType: "kubbisec-clarify",
346
+ content: buildClarifyContextMessage(next),
347
+ display: false,
348
+ },
360
349
  };
361
- });
350
+ }
351
+ return {
352
+ message: {
353
+ customType: "kubbisec-clarify",
354
+ content: buildClarifyContextMessage(next),
355
+ display: false,
356
+ },
357
+ };
358
+ }
359
+ persist(ctx, next);
360
+ return undefined;
361
+ });
362
+ api.on("tool_call", async (event, ctx) => {
363
+ const surface = resolveSurface();
364
+ if (surface !== "chat") {
365
+ return undefined;
366
+ }
367
+ questionnaire = readSessionQuestionnaire(ctx.cwd, questionnaire.sessionId);
368
+ const { toolName } = event;
369
+ if (toolName === "questionnaire") {
370
+ return undefined;
371
+ }
372
+ if (!shouldBlockClarifyTool(toolName, gateActive, questionnaire)) {
373
+ return undefined;
374
+ }
375
+ return {
376
+ block: true,
377
+ reason: CLARIFY_TOOL_BLOCK_REASON,
378
+ };
379
+ });
362
380
  }
363
- //# sourceMappingURL=kubbisec-clarify.extension.js.map
381
+ //# sourceMappingURL=kubbisec-clarify.extension.js.map