@theia/ai-ide 1.71.0-next.8 → 1.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/browser/agent-mode-confirmation-service.d.ts.map +1 -1
- package/lib/browser/agent-mode-confirmation-service.js +15 -15
- package/lib/browser/agent-mode-confirmation-service.js.map +1 -1
- package/lib/browser/ai-configuration/agent-configuration-widget.js +2 -2
- package/lib/browser/ai-configuration/agent-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/ai-configuration-view-contribution.js +1 -1
- package/lib/browser/ai-configuration/ai-configuration-view-contribution.js.map +1 -1
- package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.js +2 -1
- package/lib/browser/ai-configuration/prompt-fragments-configuration-widget.js.map +1 -1
- package/lib/browser/ai-configuration/skills-configuration-widget.d.ts.map +1 -1
- package/lib/browser/ai-configuration/skills-configuration-widget.js +2 -1
- package/lib/browser/ai-configuration/skills-configuration-widget.js.map +1 -1
- package/lib/browser/ai-ide-activation-service.d.ts +10 -1
- package/lib/browser/ai-ide-activation-service.d.ts.map +1 -1
- package/lib/browser/ai-ide-activation-service.js +41 -1
- package/lib/browser/ai-ide-activation-service.js.map +1 -1
- package/lib/browser/ai-workspace-restriction-contribution.d.ts +7 -0
- package/lib/browser/ai-workspace-restriction-contribution.d.ts.map +1 -0
- package/lib/browser/ai-workspace-restriction-contribution.js +42 -0
- package/lib/browser/ai-workspace-restriction-contribution.js.map +1 -0
- package/lib/browser/app-tester-prompt-template.js +1 -1
- package/lib/browser/architect-agent.d.ts +1 -0
- package/lib/browser/architect-agent.d.ts.map +1 -1
- package/lib/browser/architect-agent.js +5 -3
- package/lib/browser/architect-agent.js.map +1 -1
- package/lib/browser/architect-prompt-template.js +3 -3
- package/lib/browser/chat-session-card-action-contribution.js +1 -1
- package/lib/browser/chat-session-card-action-contribution.js.map +1 -1
- package/lib/browser/chat-sessions-welcome-message-provider.d.ts +1 -0
- package/lib/browser/chat-sessions-welcome-message-provider.d.ts.map +1 -1
- package/lib/browser/chat-sessions-welcome-message-provider.js +7 -1
- package/lib/browser/chat-sessions-welcome-message-provider.js.map +1 -1
- package/lib/browser/code-reviewer-agent.d.ts +1 -0
- package/lib/browser/code-reviewer-agent.d.ts.map +1 -1
- package/lib/browser/code-reviewer-agent.js +1 -0
- package/lib/browser/code-reviewer-agent.js.map +1 -1
- package/lib/browser/coder-agent.d.ts +4 -0
- package/lib/browser/coder-agent.d.ts.map +1 -1
- package/lib/browser/coder-agent.js +28 -4
- package/lib/browser/coder-agent.js.map +1 -1
- package/lib/browser/create-skill-agent.d.ts +1 -0
- package/lib/browser/create-skill-agent.d.ts.map +1 -1
- package/lib/browser/create-skill-agent.js +1 -0
- package/lib/browser/create-skill-agent.js.map +1 -1
- package/lib/browser/explore-agent.d.ts +1 -0
- package/lib/browser/explore-agent.d.ts.map +1 -1
- package/lib/browser/explore-agent.js +1 -0
- package/lib/browser/explore-agent.js.map +1 -1
- package/lib/browser/file-changeset-functions.d.ts.map +1 -1
- package/lib/browser/file-changeset-functions.js +17 -9
- package/lib/browser/file-changeset-functions.js.map +1 -1
- package/lib/browser/frontend-module.d.ts.map +1 -1
- package/lib/browser/frontend-module.js +12 -10
- package/lib/browser/frontend-module.js.map +1 -1
- package/lib/browser/github-capability-contribution.js +1 -1
- package/lib/browser/github-capability-contribution.js.map +1 -1
- package/lib/browser/github-prompt-template.js +1 -1
- package/lib/browser/ide-chat-welcome-message-provider.d.ts +4 -0
- package/lib/browser/ide-chat-welcome-message-provider.d.ts.map +1 -1
- package/lib/browser/ide-chat-welcome-message-provider.js +34 -0
- package/lib/browser/ide-chat-welcome-message-provider.js.map +1 -1
- package/lib/browser/project-info-agent.d.ts +1 -0
- package/lib/browser/project-info-agent.d.ts.map +1 -1
- package/lib/browser/project-info-agent.js +1 -0
- package/lib/browser/project-info-agent.js.map +1 -1
- package/lib/browser/{junior-agent.d.ts → review/pr-review-agent.d.ts} +7 -5
- package/lib/browser/review/pr-review-agent.d.ts.map +1 -0
- package/lib/browser/{junior-agent.js → review/pr-review-agent.js} +17 -15
- package/lib/browser/review/pr-review-agent.js.map +1 -0
- package/lib/browser/review/pr-review-prompt-template.d.ts +4 -0
- package/lib/browser/review/pr-review-prompt-template.d.ts.map +1 -0
- package/lib/browser/review/pr-review-prompt-template.js +437 -0
- package/lib/browser/review/pr-review-prompt-template.js.map +1 -0
- package/lib/browser/template-preference-contribution.d.ts +2 -0
- package/lib/browser/template-preference-contribution.d.ts.map +1 -1
- package/lib/browser/template-preference-contribution.js +43 -14
- package/lib/browser/template-preference-contribution.js.map +1 -1
- package/lib/browser/todo-tool-renderer.d.ts +1 -1
- package/lib/browser/todo-tool-renderer.d.ts.map +1 -1
- package/lib/browser/todo-tool-renderer.js +1 -1
- package/lib/browser/todo-tool-renderer.js.map +1 -1
- package/lib/browser/todo-tool.d.ts +0 -1
- package/lib/browser/todo-tool.d.ts.map +1 -1
- package/lib/browser/todo-tool.js +36 -16
- package/lib/browser/todo-tool.js.map +1 -1
- package/lib/browser/todo-tool.spec.d.ts +2 -0
- package/lib/browser/todo-tool.spec.d.ts.map +1 -0
- package/lib/browser/todo-tool.spec.js +44 -0
- package/lib/browser/todo-tool.spec.js.map +1 -0
- package/lib/browser/user-interaction-tool-renderer.d.ts +18 -0
- package/lib/browser/user-interaction-tool-renderer.d.ts.map +1 -0
- package/lib/browser/user-interaction-tool-renderer.js +330 -0
- package/lib/browser/user-interaction-tool-renderer.js.map +1 -0
- package/lib/browser/user-interaction-tool.d.ts +47 -0
- package/lib/browser/user-interaction-tool.d.ts.map +1 -0
- package/lib/browser/user-interaction-tool.js +397 -0
- package/lib/browser/user-interaction-tool.js.map +1 -0
- package/lib/browser/user-interaction-tool.spec.d.ts +2 -0
- package/lib/browser/user-interaction-tool.spec.d.ts.map +1 -0
- package/lib/browser/user-interaction-tool.spec.js +336 -0
- package/lib/browser/user-interaction-tool.spec.js.map +1 -0
- package/lib/browser/workspace-functions.d.ts.map +1 -1
- package/lib/browser/workspace-functions.js +9 -2
- package/lib/browser/workspace-functions.js.map +1 -1
- package/lib/browser/workspace-launch-provider.d.ts.map +1 -1
- package/lib/browser/workspace-launch-provider.js +9 -4
- package/lib/browser/workspace-launch-provider.js.map +1 -1
- package/lib/browser/workspace-launch-provider.spec.js +4 -4
- package/lib/browser/workspace-launch-provider.spec.js.map +1 -1
- package/lib/browser/workspace-task-provider.d.ts.map +1 -1
- package/lib/browser/workspace-task-provider.js +4 -1
- package/lib/browser/workspace-task-provider.js.map +1 -1
- package/lib/browser/workspace-task-provider.spec.js +90 -1
- package/lib/browser/workspace-task-provider.spec.js.map +1 -1
- package/lib/common/ai-ide-preferences.d.ts +1 -1
- package/lib/common/ai-ide-preferences.d.ts.map +1 -1
- package/lib/common/ai-ide-preferences.js +6 -6
- package/lib/common/ai-ide-preferences.js.map +1 -1
- package/lib/common/coder-replace-prompt-template.d.ts.map +1 -1
- package/lib/common/coder-replace-prompt-template.js +133 -17
- package/lib/common/coder-replace-prompt-template.js.map +1 -1
- package/lib/common/command-chat-agents.d.ts +1 -0
- package/lib/common/command-chat-agents.d.ts.map +1 -1
- package/lib/common/command-chat-agents.js +1 -0
- package/lib/common/command-chat-agents.js.map +1 -1
- package/lib/common/command-prompt-template.js +1 -1
- package/lib/common/orchestrator-chat-agent.d.ts.map +1 -1
- package/lib/common/orchestrator-chat-agent.js +2 -2
- package/lib/common/orchestrator-chat-agent.js.map +1 -1
- package/lib/common/universal-chat-agent.d.ts +1 -0
- package/lib/common/universal-chat-agent.d.ts.map +1 -1
- package/lib/common/universal-chat-agent.js +1 -0
- package/lib/common/universal-chat-agent.js.map +1 -1
- package/lib/common/universal-prompt-template.js +1 -1
- package/lib/common/user-interaction-tool.d.ts +53 -0
- package/lib/common/user-interaction-tool.d.ts.map +1 -0
- package/lib/common/user-interaction-tool.js +176 -0
- package/lib/common/user-interaction-tool.js.map +1 -0
- package/lib/common/user-interaction-tool.spec.d.ts +2 -0
- package/lib/common/user-interaction-tool.spec.d.ts.map +1 -0
- package/lib/common/user-interaction-tool.spec.js +216 -0
- package/lib/common/user-interaction-tool.spec.js.map +1 -0
- package/package.json +27 -27
- package/src/browser/agent-mode-confirmation-service.ts +19 -18
- package/src/browser/ai-configuration/agent-configuration-widget.tsx +2 -2
- package/src/browser/ai-configuration/ai-configuration-view-contribution.ts +1 -1
- package/src/browser/ai-configuration/prompt-fragments-configuration-widget.tsx +2 -1
- package/src/browser/ai-configuration/skills-configuration-widget.tsx +2 -1
- package/src/browser/ai-ide-activation-service.ts +43 -3
- package/src/browser/ai-workspace-restriction-contribution.ts +39 -0
- package/src/browser/app-tester-prompt-template.ts +1 -1
- package/src/browser/architect-agent.ts +6 -3
- package/src/browser/architect-prompt-template.ts +3 -3
- package/src/browser/chat-session-card-action-contribution.ts +1 -1
- package/src/browser/chat-sessions-welcome-message-provider.tsx +11 -2
- package/src/browser/code-reviewer-agent.ts +1 -0
- package/src/browser/coder-agent.ts +31 -4
- package/src/browser/create-skill-agent.ts +1 -0
- package/src/browser/explore-agent.ts +1 -0
- package/src/browser/file-changeset-functions.ts +17 -8
- package/src/browser/frontend-module.ts +14 -12
- package/src/browser/github-capability-contribution.ts +1 -1
- package/src/browser/github-prompt-template.ts +1 -1
- package/src/browser/ide-chat-welcome-message-provider.tsx +53 -0
- package/src/browser/project-info-agent.ts +1 -1
- package/src/browser/{context-reviewer-agent.ts → review/pr-review-agent.ts} +13 -11
- package/src/browser/review/pr-review-prompt-template.ts +449 -0
- package/src/browser/style/index.css +299 -0
- package/src/browser/template-preference-contribution.ts +40 -14
- package/src/browser/todo-tool-renderer.tsx +1 -1
- package/src/browser/todo-tool.spec.ts +49 -0
- package/src/browser/todo-tool.ts +35 -14
- package/src/browser/user-interaction-tool-renderer.tsx +531 -0
- package/src/browser/user-interaction-tool.spec.ts +396 -0
- package/src/browser/user-interaction-tool.ts +423 -0
- package/src/browser/workspace-functions.ts +10 -3
- package/src/browser/workspace-launch-provider.spec.ts +4 -4
- package/src/browser/workspace-launch-provider.ts +10 -6
- package/src/browser/workspace-task-provider.spec.ts +119 -1
- package/src/browser/workspace-task-provider.ts +4 -1
- package/src/common/ai-ide-preferences.ts +7 -7
- package/src/common/coder-replace-prompt-template.ts +133 -17
- package/src/common/command-chat-agents.ts +1 -0
- package/src/common/command-prompt-template.ts +1 -1
- package/src/common/orchestrator-chat-agent.ts +2 -2
- package/src/common/universal-chat-agent.ts +1 -0
- package/src/common/universal-prompt-template.ts +1 -1
- package/src/common/user-interaction-tool.spec.ts +241 -0
- package/src/common/user-interaction-tool.ts +237 -0
- package/lib/browser/context-reviewer-agent.d.ts +0 -17
- package/lib/browser/context-reviewer-agent.d.ts.map +0 -1
- package/lib/browser/context-reviewer-agent.js +0 -45
- package/lib/browser/context-reviewer-agent.js.map +0 -1
- package/lib/browser/context-reviewer-prompt-template.d.ts +0 -4
- package/lib/browser/context-reviewer-prompt-template.d.ts.map +0 -1
- package/lib/browser/context-reviewer-prompt-template.js +0 -160
- package/lib/browser/context-reviewer-prompt-template.js.map +0 -1
- package/lib/browser/junior-agent.d.ts.map +0 -1
- package/lib/browser/junior-agent.js.map +0 -1
- package/lib/browser/junior-plan-capability-contribution.d.ts +0 -8
- package/lib/browser/junior-plan-capability-contribution.d.ts.map +0 -1
- package/lib/browser/junior-plan-capability-contribution.js +0 -131
- package/lib/browser/junior-plan-capability-contribution.js.map +0 -1
- package/lib/browser/junior-prompt-template.d.ts +0 -4
- package/lib/browser/junior-prompt-template.d.ts.map +0 -1
- package/lib/browser/junior-prompt-template.js +0 -149
- package/lib/browser/junior-prompt-template.js.map +0 -1
- package/src/browser/context-reviewer-prompt-template.ts +0 -160
- package/src/browser/junior-agent.ts +0 -40
- package/src/browser/junior-plan-capability-contribution.ts +0 -129
- package/src/browser/junior-prompt-template.ts +0 -149
|
@@ -113,7 +113,10 @@ export class TaskRunnerProvider implements ToolProvider {
|
|
|
113
113
|
return `Did not find a task for the label: '${args.taskName}'`;
|
|
114
114
|
}
|
|
115
115
|
cancellationToken?.onCancellationRequested(() => {
|
|
116
|
-
|
|
116
|
+
// Only terminate if the task is still running
|
|
117
|
+
if (this.taskService.isTaskRunning(taskInfo.taskId)) {
|
|
118
|
+
this.taskService.terminateTask(taskInfo);
|
|
119
|
+
}
|
|
117
120
|
});
|
|
118
121
|
if (cancellationToken?.isCancellationRequested) {
|
|
119
122
|
return JSON.stringify({ error: 'Operation cancelled by user' });
|
|
@@ -15,12 +15,12 @@
|
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
17
|
import { AI_CORE_PREFERENCES_TITLE } from '@theia/ai-core/lib/common';
|
|
18
|
-
import { nls, PreferenceSchema } from '@theia/core';
|
|
18
|
+
import { nls, PreferenceSchema, PreferenceScope } from '@theia/core';
|
|
19
19
|
|
|
20
20
|
// We reuse the context key for the preference name
|
|
21
21
|
export const PREFERENCE_NAME_ENABLE_AI = 'ai-features.AiEnable.enableAI';
|
|
22
22
|
export const PREFERENCE_NAME_ORCHESTRATOR_EXCLUSION_LIST = 'ai-features.orchestrator.excludedAgents';
|
|
23
|
-
export const
|
|
23
|
+
export const PREFERENCE_NAME_AGENT_MODE_ENABLED = 'ai-features.agentMode.enabled';
|
|
24
24
|
export const aiIdePreferenceSchema: PreferenceSchema = {
|
|
25
25
|
properties: {
|
|
26
26
|
[PREFERENCE_NAME_ENABLE_AI]: {
|
|
@@ -49,14 +49,14 @@ export const aiIdePreferenceSchema: PreferenceSchema = {
|
|
|
49
49
|
},
|
|
50
50
|
default: ['ClaudeCode', 'Codex'],
|
|
51
51
|
},
|
|
52
|
-
[
|
|
52
|
+
[PREFERENCE_NAME_AGENT_MODE_ENABLED]: {
|
|
53
53
|
title: AI_CORE_PREFERENCES_TITLE,
|
|
54
|
-
|
|
55
|
-
'
|
|
56
|
-
|
|
57
|
-
+ 'Set to `false` to see the confirmation again on the next agent mode request.'),
|
|
54
|
+
description: nls.localize('theia/ai/ide/agentMode/enabled/mdDescription',
|
|
55
|
+
'Enable agent mode for the Coder agent. Agent mode allows autonomous file modifications without further confirmation.\
|
|
56
|
+
A first-use confirmation dialog is shown when using agent mode until this is set to `true`.'),
|
|
58
57
|
type: 'boolean',
|
|
59
58
|
default: false,
|
|
59
|
+
scope: PreferenceScope.User
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
};
|
|
@@ -49,7 +49,7 @@ https://github.com/eclipse-theia/theia/discussions/new?category=prompt-template-
|
|
|
49
49
|
|
|
50
50
|
# Identity
|
|
51
51
|
|
|
52
|
-
You are an **autonomous AI agent** embedded in
|
|
52
|
+
You are an **autonomous AI agent** embedded in {{productName}}. Your purpose is to assist developers with implementing features, fixing bugs, \
|
|
53
53
|
refactoring code, and improving code quality.
|
|
54
54
|
You must independently analyze, implement, validate, and finalize all changes — only yield control when all relevant tasks are completed.
|
|
55
55
|
|
|
@@ -276,9 +276,11 @@ https://github.com/eclipse-theia/theia/discussions/new?category=prompt-template-
|
|
|
276
276
|
|
|
277
277
|
# Identity
|
|
278
278
|
|
|
279
|
-
You are an **autonomous AI agent** embedded in
|
|
279
|
+
You are an **autonomous AI agent** embedded in {{productName}}. Your purpose is to assist developers with implementing features, fixing bugs, \
|
|
280
280
|
refactoring code, and improving code quality.
|
|
281
281
|
You must independently analyze, implement, validate, and finalize all changes — only yield control when all relevant tasks are completed.
|
|
282
|
+
You operate within the boundaries of the current workspace. You cannot access external networks, install system-level packages, or modify files \
|
|
283
|
+
outside the project root unless explicitly enabled via capabilities.
|
|
282
284
|
|
|
283
285
|
# Core Principles
|
|
284
286
|
|
|
@@ -305,10 +307,14 @@ When multiple independent operations are needed, execute them **all in a single
|
|
|
305
307
|
- Searching for different patterns → search in parallel
|
|
306
308
|
- Running independent validations → run together
|
|
307
309
|
**Never run independent operations one at a time.** Only run sequentially when there are true dependencies.
|
|
310
|
+
**Do NOT write to the same file in parallel.** Parallel reads are always safe; parallel writes to the same file will conflict.
|
|
308
311
|
|
|
309
312
|
## Planning and Reflection
|
|
310
313
|
For complex decisions, think step-by-step and explain your reasoning.
|
|
311
|
-
After tool calls, reflect
|
|
314
|
+
After tool calls, reflect before continuing:
|
|
315
|
+
1. **What did I learn?** — Did the results match expectations?
|
|
316
|
+
2. **Does this change my plan?** — If assumptions were invalidated, adjust your approach rather than continuing with the original plan
|
|
317
|
+
3. **What's next and why?** — Base your next step on evidence, not the initial plan
|
|
312
318
|
|
|
313
319
|
# Code Quality Guidelines
|
|
314
320
|
|
|
@@ -321,6 +327,13 @@ Only make changes that are directly requested or clearly necessary. Keep solutio
|
|
|
321
327
|
- Three similar lines of code is better than a premature abstraction
|
|
322
328
|
- Delete unused code completely — no backwards-compatibility hacks, no \`// removed\` comments
|
|
323
329
|
|
|
330
|
+
## Minimize Your Diff
|
|
331
|
+
- Only touch lines that need to change
|
|
332
|
+
- Do NOT reformat or reorganize surrounding code
|
|
333
|
+
- Do NOT reorganize imports unless your change requires new imports
|
|
334
|
+
- Do NOT update comments on unchanged code
|
|
335
|
+
- A smaller diff is easier to review and less likely to introduce bugs
|
|
336
|
+
|
|
324
337
|
## Security Awareness
|
|
325
338
|
Be careful not to introduce security vulnerabilities:
|
|
326
339
|
- Command injection, XSS, SQL injection
|
|
@@ -351,6 +364,7 @@ Choose the right tool for the job:
|
|
|
351
364
|
- **Looking for code/text content** → use ~{${SEARCH_IN_WORKSPACE_FUNCTION_ID}}
|
|
352
365
|
- **Exploring directory structure** → use ~{${GET_WORKSPACE_FILE_LIST_FUNCTION_ID}}
|
|
353
366
|
- **Never search for files whose paths you already know**
|
|
367
|
+
- **File too large to read** → do NOT retry or read in chunks. Use ~{${SEARCH_IN_WORKSPACE_FUNCTION_ID}} to find the specific section you need
|
|
354
368
|
|
|
355
369
|
## Code Editing
|
|
356
370
|
|
|
@@ -361,15 +375,40 @@ Choose the right tool for the job:
|
|
|
361
375
|
- ~{${WRITE_FILE_REPLACEMENTS_ID}} — immediately apply targeted code changes (no user review)
|
|
362
376
|
- ~{${WRITE_FILE_CONTENT_ID}} — immediately overwrite a file with new content (no user review)
|
|
363
377
|
|
|
378
|
+
Prefer ~{${WRITE_FILE_REPLACEMENTS_ID}} over ~{${WRITE_FILE_CONTENT_ID}} — targeted replacements are safer and preserve content you haven't read. \
|
|
379
|
+
Only use ~{${WRITE_FILE_CONTENT_ID}} for new files or when replacements fail repeatedly.
|
|
380
|
+
|
|
364
381
|
### Editing Guidelines
|
|
365
382
|
- For incremental changes, use multiple ~{${WRITE_FILE_REPLACEMENTS_ID}} calls
|
|
366
383
|
- If ~{${WRITE_FILE_REPLACEMENTS_ID}} fails, the likely cause is non-unique \`oldContent\`. Re-read the file and include more surrounding context, \
|
|
367
384
|
or switch to ~{${WRITE_FILE_CONTENT_ID}}
|
|
368
385
|
- **Do NOT add comments explaining what you changed or why**
|
|
369
386
|
|
|
387
|
+
### Change Ordering
|
|
388
|
+
When making related changes across multiple files, order them to keep the build valid at each step:
|
|
389
|
+
- Add new code before updating callers to use it
|
|
390
|
+
- Update all consumers of an API before removing the old API
|
|
391
|
+
- Add imports before using new symbols
|
|
392
|
+
|
|
393
|
+
### Verify Critical Changes
|
|
394
|
+
After applying complex edits (multi-site refactors, or files you've modified multiple times in this session), re-read the file with \
|
|
395
|
+
~{${FILE_CONTENT_FUNCTION_ID}} to confirm changes were applied correctly. This catches replacement mismatches, overlapping edits, and formatting issues.
|
|
396
|
+
|
|
397
|
+
### Ripple Effect Awareness
|
|
398
|
+
When you change any of the following, search for ALL usages before proceeding:
|
|
399
|
+
- Function/method signatures (parameters, return types)
|
|
400
|
+
- Interface or type definitions
|
|
401
|
+
- Exported constants or enums
|
|
402
|
+
- File paths or module names (imports will break)
|
|
403
|
+
|
|
404
|
+
Use ~{${SEARCH_IN_WORKSPACE_FUNCTION_ID}} to find all references before making breaking changes.
|
|
405
|
+
|
|
370
406
|
## Validation
|
|
371
407
|
- ~{${GET_FILE_DIAGNOSTICS_ID}} — detect syntax, lint, or type errors
|
|
372
408
|
|
|
409
|
+
Prefer ~{${GET_FILE_DIAGNOSTICS_ID}} (fast, single file) over ~{${RUN_TASK_FUNCTION_ID}} with a full build (slow) for quick checks during implementation. \
|
|
410
|
+
Use full build/test runs for final validation.
|
|
411
|
+
|
|
373
412
|
## Testing & Tasks
|
|
374
413
|
- ~{${LIST_TASKS_FUNCTION_ID}} — discover available test, lint, and build tasks
|
|
375
414
|
- ~{${RUN_TASK_FUNCTION_ID}} — execute linting, building, or test suites
|
|
@@ -393,10 +432,14 @@ Launch configurations are defined in \`.vscode/launch.json\`. If none exist or y
|
|
|
393
432
|
## Progress Tracking
|
|
394
433
|
- ~{${TODO_WRITE_FUNCTION_ID}} — track task progress with a todo list visible to the user
|
|
395
434
|
|
|
396
|
-
|
|
397
|
-
-
|
|
398
|
-
-
|
|
399
|
-
-
|
|
435
|
+
**For any task involving 3+ files or 3+ logical steps, you MUST create a todo list before starting implementation.** This is not optional for complex tasks — it serves as:
|
|
436
|
+
- Your external memory and execution plan
|
|
437
|
+
- A progress indicator for the user
|
|
438
|
+
- A recovery mechanism if you lose track mid-task
|
|
439
|
+
|
|
440
|
+
Update item status as you progress. If you discover additional work mid-task, add new items.
|
|
441
|
+
**Important:** Each ~{${TODO_WRITE_FUNCTION_ID}} call replaces the entire list. Always include ALL items (completed, in-progress, \
|
|
442
|
+
and pending) in every call — do not send only changed items.
|
|
400
443
|
|
|
401
444
|
{{capability:shell-execution default off}}
|
|
402
445
|
|
|
@@ -405,15 +448,25 @@ Use the todo tool for complex multi-step tasks to:
|
|
|
405
448
|
# Workflow
|
|
406
449
|
|
|
407
450
|
## Understand the Task
|
|
408
|
-
Analyze the user input
|
|
451
|
+
Analyze the user input and any provided task context.
|
|
452
|
+
If a task context is present (see the "Current Task Context" section), treat it as the authoritative plan. Skip broad exploration and proceed directly to implementation.
|
|
409
453
|
|
|
410
454
|
## Investigate
|
|
411
455
|
Use directory listing, file retrieval, and search to gather all needed context.
|
|
412
456
|
Bookmark files you'll reference multiple times with ~{${UPDATE_CONTEXT_FILES_FUNCTION_ID}} — this is more efficient than re-reading repeatedly.
|
|
413
457
|
|
|
458
|
+
Tailor your investigation to the task type:
|
|
459
|
+
- **Bug fix:** Reproduce the issue mentally from the code, find related tests, trace the data/control flow to the root cause
|
|
460
|
+
- **Feature:** Find similar existing features to use as a pattern, identify all integration points
|
|
461
|
+
- **Refactor:** Map all usages of the code being changed, understand the dependency graph
|
|
462
|
+
|
|
414
463
|
## Plan and Implement
|
|
415
464
|
Develop a step-by-step strategy. Implement changes via tool calls.
|
|
416
465
|
When referencing code locations, use the format \`file_path:line_number\` (e.g., \`src/utils.ts:42\`).
|
|
466
|
+
If the task involves 3+ files or steps, create a todo list now (see Progress Tracking).
|
|
467
|
+
If a task context is present, skip broad exploration entirely. Use ~{${FILE_CONTENT_FUNCTION_ID}} only for the specific files named in the plan.
|
|
468
|
+
However, evaluate each step critically as you implement it. If a step introduces unnecessary complexity, conflicts with existing patterns, \
|
|
469
|
+
or has a simpler alternative, deviate from the plan and explain why. The plan is a starting point, not a mandate — you are the engineer, not a typist.
|
|
417
470
|
|
|
418
471
|
## Validate
|
|
419
472
|
|
|
@@ -437,6 +490,22 @@ When referencing code locations, use the format \`file_path:line_number\` (e.g.,
|
|
|
437
490
|
- Lint: "npm: lint", "lint"
|
|
438
491
|
- Test: "npm: test", "test"
|
|
439
492
|
|
|
493
|
+
### Review Feedback Handling
|
|
494
|
+
|
|
495
|
+
When review feedback is recorded in the task context (REVISE verdict):
|
|
496
|
+
- Read the findings from the task context
|
|
497
|
+
- Evaluate each finding critically — do not blindly accept all feedback
|
|
498
|
+
- If a finding is incorrect or there's a better approach, explain your reasoning in the task context before making changes
|
|
499
|
+
- Fix legitimate issues, push back on questionable ones with reasoning
|
|
500
|
+
|
|
501
|
+
### Validate Incrementally
|
|
502
|
+
Do not wait until all changes are complete to validate:
|
|
503
|
+
- After modifying a core type or interface → run diagnostics on dependent files
|
|
504
|
+
- After a complex refactor → build immediately before continuing
|
|
505
|
+
- After fixing a test → run that specific test before fixing the next one
|
|
506
|
+
|
|
507
|
+
Catching errors early prevents cascading mistakes.
|
|
508
|
+
|
|
440
509
|
## Test and Iterate
|
|
441
510
|
Run all relevant tests:
|
|
442
511
|
- If failures are found, debug and fix
|
|
@@ -456,19 +525,61 @@ Reflect on whether all objectives are met:
|
|
|
456
525
|
|
|
457
526
|
Only when **everything is done**, end your turn.
|
|
458
527
|
|
|
459
|
-
|
|
528
|
+
## Handling Follow-Up Requests
|
|
529
|
+
When the user provides corrections or additional requests after your initial completion:
|
|
530
|
+
- Re-read any files you need to modify — they may have changed since your last edit
|
|
531
|
+
- If asked to revert, restore the original content using ~{${WRITE_FILE_CONTENT_ID}}
|
|
532
|
+
- Re-run full validation after follow-up changes — do not assume prior build/test results still hold
|
|
533
|
+
- Treat each follow-up as a mini-task: understand → implement → validate
|
|
460
534
|
|
|
461
|
-
|
|
462
|
-
1. Read the **full error message** carefully
|
|
463
|
-
2. If a tool call fails repeatedly (3+ times), try an alternative approach
|
|
464
|
-
3. For build/lint errors, fix ALL errors before re-running
|
|
465
|
-
4. If stuck in a loop, step back and reconsider the overall approach
|
|
535
|
+
# Output Format
|
|
466
536
|
|
|
467
|
-
|
|
537
|
+
When the task is complete, report:
|
|
538
|
+
1. **Modified files** — list of files changed with brief description of each change
|
|
539
|
+
2. **Summary** — one paragraph describing what was done and why
|
|
540
|
+
3. **Build/lint/test evidence** — which validations were run and their results (PASS/FAIL)
|
|
541
|
+
4. **UI files touched** — Yes/No, whether any UI/frontend files were modified
|
|
542
|
+
|
|
543
|
+
# Error Recovery
|
|
544
|
+
|
|
545
|
+
## Hypothesis-Driven Debugging
|
|
546
|
+
When a build fails, a test breaks, or behavior is unexpected:
|
|
547
|
+
1. **Read the full error** — including stack traces, not just the first line
|
|
548
|
+
2. **Form a hypothesis** — "I think X is failing because Y"
|
|
549
|
+
3. **Gather evidence** — Use targeted tool calls to confirm or refute your hypothesis
|
|
550
|
+
4. **Fix based on evidence** — Do NOT shotgun multiple speculative changes hoping one works
|
|
551
|
+
5. **Verify the fix** — Re-run the specific failing validation
|
|
552
|
+
|
|
553
|
+
## Dead-End Detection
|
|
554
|
+
If you notice any of these patterns, STOP and reconsider your approach:
|
|
555
|
+
- You've edited the same file 3+ times to fix the same issue
|
|
556
|
+
- A fix in one place keeps breaking something in another
|
|
557
|
+
- You're adding increasingly complex workarounds
|
|
558
|
+
- The same test has been failing for 3+ attempts with different fixes
|
|
559
|
+
|
|
560
|
+
When stuck:
|
|
561
|
+
1. Record in ~{${TODO_WRITE_FUNCTION_ID}}:
|
|
562
|
+
(a) what you tried,
|
|
563
|
+
(b) why it failed,
|
|
564
|
+
(c) what you'll try differently
|
|
565
|
+
— this persists even as earlier conversation context scrolls away
|
|
566
|
+
2. Re-read the original requirements
|
|
567
|
+
3. Consider a fundamentally different approach
|
|
568
|
+
4. If truly blocked, ask the user — this is a valid reason to seek clarification
|
|
569
|
+
|
|
570
|
+
### Reverting Failed Changes
|
|
571
|
+
When changing approach after a dead end:
|
|
572
|
+
- Restore the file to its original state using ~{${WRITE_FILE_CONTENT_ID}} with the content you read before making changes (you read it per the "Read Before Edit" rule)
|
|
573
|
+
- If you no longer have the original content in context, re-read a known-good version or reconstruct it
|
|
574
|
+
- Do NOT continue building on top of changes from a failed approach — revert first, then restart
|
|
575
|
+
|
|
576
|
+
## Common Tool Failure Patterns
|
|
468
577
|
- **Replacement "not found"**: Re-read the file first (content may have changed), then adjust \`oldContent\` to include more context
|
|
469
578
|
- **File not found**: Verify the path exists using ~{${FIND_FILES_BY_PATTERN_FUNCTION_ID}}
|
|
470
579
|
- **Task not found**: Use ~{${LIST_TASKS_FUNCTION_ID}} to discover available task names
|
|
471
580
|
|
|
581
|
+
For build/lint errors, fix ALL errors before re-running (not one at a time).
|
|
582
|
+
|
|
472
583
|
# When to Seek Clarification
|
|
473
584
|
|
|
474
585
|
Ask the user **before proceeding** only if:
|
|
@@ -476,17 +587,22 @@ Ask the user **before proceeding** only if:
|
|
|
476
587
|
- Requirements are ambiguous and could lead to substantial wasted work
|
|
477
588
|
- You discover the task scope is significantly larger than initially apparent
|
|
478
589
|
- You encounter blocking issues that cannot be resolved autonomously
|
|
590
|
+
- A decision could go either way — present options with trade-offs rather than choosing
|
|
479
591
|
|
|
480
592
|
Do NOT ask for confirmation on:
|
|
481
593
|
- Intermediate implementation steps
|
|
482
594
|
- Minor technical decisions
|
|
483
595
|
- Standard coding patterns
|
|
484
596
|
|
|
597
|
+
**Do NOT assume every request requires code changes.** If the user asks a question, provides information for discussion, \
|
|
598
|
+
or shares content for review — respond conversationally. Only search for files to modify when the user explicitly requests a change.
|
|
599
|
+
|
|
485
600
|
# Communication Style
|
|
486
601
|
|
|
487
602
|
- Keep responses concise — focus on what you did and what's next, not detailed explanations of what you're about to do
|
|
488
603
|
- Use markdown formatting for code blocks and structure
|
|
489
604
|
- When referencing code, use \`file_path:line_number\` format (e.g., \`src/utils.ts:42\`)
|
|
605
|
+
- For long tasks, provide a one-line progress update after completing each major phase (e.g., "Investigation complete — 5 files identified. Starting implementation.")
|
|
490
606
|
|
|
491
607
|
# Context
|
|
492
608
|
|
|
@@ -496,7 +612,7 @@ Always retrieve relevant files using ~{${FILE_CONTENT_FUNCTION_ID}} to understan
|
|
|
496
612
|
{{${CONTEXT_FILES_VARIABLE_ID}}}
|
|
497
613
|
|
|
498
614
|
## Previously Changed Files
|
|
499
|
-
{{
|
|
615
|
+
{{${CHANGE_SET_SUMMARY_VARIABLE_ID}}}
|
|
500
616
|
|
|
501
617
|
## Project Info
|
|
502
618
|
{{prompt:project-info}}
|
|
@@ -535,7 +651,7 @@ function getCoderEditPromptTemplate(): string {
|
|
|
535
651
|
return `{{!-- This prompt is licensed under the MIT License (https://opensource.org/license/mit).
|
|
536
652
|
Made improvements or adaptations to this prompt template? We'd love for you to share it with the community! Contribute back here:
|
|
537
653
|
https://github.com/eclipse-theia/theia/discussions/new?category=prompt-template-contribution --}}
|
|
538
|
-
You are an AI assistant integrated into
|
|
654
|
+
You are an AI assistant integrated into {{productName}}, designed to assist software developers with code tasks. You can interact with the code base and suggest changes, \
|
|
539
655
|
which will be reviewed and accepted by the user.
|
|
540
656
|
|
|
541
657
|
## Context Retrieval
|
|
@@ -54,6 +54,7 @@ export class CommandChatAgent extends AbstractTextToModelParsingChatAgent<Parsed
|
|
|
54
54
|
purpose: 'command',
|
|
55
55
|
identifier: 'default/universal',
|
|
56
56
|
}];
|
|
57
|
+
override iconClass: string = 'codicon codicon-server-process';
|
|
57
58
|
protected defaultLanguageModelPurpose: string = 'command';
|
|
58
59
|
|
|
59
60
|
override description = nls.localize('theia/ai/ide/commandAgent/description',
|
|
@@ -20,7 +20,7 @@ Made improvements or adaptations to this prompt template? We\u2019d love for you
|
|
|
20
20
|
https://github.com/eclipse-theia/theia/discussions/new?category=prompt-template-contribution --}}
|
|
21
21
|
# System Prompt
|
|
22
22
|
|
|
23
|
-
You are a service that helps users find commands to execute in
|
|
23
|
+
You are a service that helps users find commands to execute in {{productName}}.
|
|
24
24
|
You reply with stringified JSON Objects that tell the user which command to execute and its arguments, if any.
|
|
25
25
|
|
|
26
26
|
# Examples
|
|
@@ -41,7 +41,7 @@ export class OrchestratorChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
41
41
|
override description = nls.localize('theia/ai/chat/orchestrator/description',
|
|
42
42
|
'This agent analyzes the user request against the description of all available chat agents and selects the best fitting agent to answer the request \
|
|
43
43
|
(by using AI).The user\'s request will be directly delegated to the selected agent without further confirmation.');
|
|
44
|
-
override iconClass: string = 'codicon codicon-
|
|
44
|
+
override iconClass: string = 'codicon codicon-milestone';
|
|
45
45
|
override agentSpecificVariables = [{
|
|
46
46
|
name: 'availableChatAgents',
|
|
47
47
|
description: nls.localize('theia/ai/chat/orchestrator/vars/availableChatAgents/description',
|
|
@@ -122,7 +122,7 @@ export class OrchestratorChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
122
122
|
messages,
|
|
123
123
|
tools,
|
|
124
124
|
settings,
|
|
125
|
-
|
|
125
|
+
reasoning: commonSettings?.reasoning,
|
|
126
126
|
agentId: this.id,
|
|
127
127
|
sessionId: request.session.id,
|
|
128
128
|
requestId: request.id,
|
|
@@ -37,4 +37,5 @@ export class UniversalChatAgent extends AbstractStreamParsingChatAgent {
|
|
|
37
37
|
|
|
38
38
|
override prompts = [{ id: 'universal-system', defaultVariant: universalTemplate, variants: [universalTemplateVariant] }];
|
|
39
39
|
protected override systemPromptId: string = 'universal-system';
|
|
40
|
+
override iconClass: string = 'codicon codicon-comment';
|
|
40
41
|
}
|
|
@@ -18,7 +18,7 @@ export const universalTemplate: BasePromptFragment = {
|
|
|
18
18
|
Made improvements or adaptations to this prompt template? We’d love for you to share it with the community! Contribute back here:
|
|
19
19
|
https://github.com/eclipse-theia/theia/discussions/new?category=prompt-template-contribution --}}
|
|
20
20
|
|
|
21
|
-
You are an assistant integrated into
|
|
21
|
+
You are an assistant integrated into {{productName}}, designed to assist software developers.
|
|
22
22
|
|
|
23
23
|
## Current Context
|
|
24
24
|
Some files and other pieces of data may have been added by the user to the context of the chat. If any have, the details can be found below.
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
// *****************************************************************************
|
|
2
|
+
// Copyright (C) 2026 EclipseSource GmbH.
|
|
3
|
+
//
|
|
4
|
+
// This program and the accompanying materials are made available under the
|
|
5
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
6
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
7
|
+
//
|
|
8
|
+
// This Source Code may also be made available under the following Secondary
|
|
9
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
10
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
11
|
+
// with the GNU Classpath Exception which is available at
|
|
12
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
13
|
+
//
|
|
14
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
|
+
// *****************************************************************************
|
|
16
|
+
|
|
17
|
+
import { expect } from 'chai';
|
|
18
|
+
import { buildDiffLabel, parseUserInteractionArgs, parseUserInteractionInput } from './user-interaction-tool';
|
|
19
|
+
|
|
20
|
+
describe('parseUserInteractionArgs', () => {
|
|
21
|
+
it('should return undefined for undefined input', () => {
|
|
22
|
+
expect(parseUserInteractionArgs(undefined)).to.be.undefined;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('should return undefined for invalid JSON', () => {
|
|
26
|
+
expect(parseUserInteractionArgs('not json')).to.be.undefined;
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should return undefined when interactions is missing', () => {
|
|
30
|
+
const input = JSON.stringify({ foo: 'bar' });
|
|
31
|
+
expect(parseUserInteractionArgs(input)).to.be.undefined;
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('should return undefined when interactions is not an array', () => {
|
|
35
|
+
const input = JSON.stringify({ interactions: 'nope' });
|
|
36
|
+
expect(parseUserInteractionArgs(input)).to.be.undefined;
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should return undefined when no step is valid', () => {
|
|
40
|
+
const input = JSON.stringify({ interactions: [{ foo: 'bar' }, { title: 1 }] });
|
|
41
|
+
expect(parseUserInteractionArgs(input)).to.be.undefined;
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('should drop steps that are missing title or message', () => {
|
|
45
|
+
const input = JSON.stringify({
|
|
46
|
+
interactions: [
|
|
47
|
+
{ title: 'Valid', message: 'Hello' },
|
|
48
|
+
{ title: 'No message' },
|
|
49
|
+
{ message: 'No title' }
|
|
50
|
+
]
|
|
51
|
+
});
|
|
52
|
+
const result = parseUserInteractionArgs(input);
|
|
53
|
+
expect(result).to.not.be.undefined;
|
|
54
|
+
expect(result!.interactions).to.have.length(1);
|
|
55
|
+
expect(result!.interactions[0].title).to.equal('Valid');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should accept a step without options (informational)', () => {
|
|
59
|
+
const input = JSON.stringify({
|
|
60
|
+
interactions: [{ title: 'Info', message: 'Just so you know' }]
|
|
61
|
+
});
|
|
62
|
+
const result = parseUserInteractionArgs(input);
|
|
63
|
+
expect(result).to.not.be.undefined;
|
|
64
|
+
expect(result!.interactions[0].options).to.be.undefined;
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should filter out invalid options within a step', () => {
|
|
68
|
+
const input = JSON.stringify({
|
|
69
|
+
interactions: [{
|
|
70
|
+
title: 'T', message: 'M',
|
|
71
|
+
options: [{ text: 'A', value: 'a' }, { bad: true }, { text: 'B', value: 'b' }]
|
|
72
|
+
}]
|
|
73
|
+
});
|
|
74
|
+
const result = parseUserInteractionArgs(input);
|
|
75
|
+
expect(result!.interactions[0].options).to.have.length(2);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it('should drop options array if no options are valid', () => {
|
|
79
|
+
const input = JSON.stringify({
|
|
80
|
+
interactions: [{
|
|
81
|
+
title: 'T', message: 'M',
|
|
82
|
+
options: [{ bad: true }]
|
|
83
|
+
}]
|
|
84
|
+
});
|
|
85
|
+
const result = parseUserInteractionArgs(input);
|
|
86
|
+
expect(result!.interactions[0].options).to.be.undefined;
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it('should normalize singular link into a links array on a step', () => {
|
|
90
|
+
const input = JSON.stringify({
|
|
91
|
+
interactions: [{
|
|
92
|
+
title: 'T', message: 'M',
|
|
93
|
+
options: [{ text: 'A', value: 'a' }],
|
|
94
|
+
link: { ref: 'src/index.ts' }
|
|
95
|
+
}]
|
|
96
|
+
});
|
|
97
|
+
const result = parseUserInteractionArgs(input);
|
|
98
|
+
expect(result!.interactions[0].links).to.deep.equal([{ ref: 'src/index.ts' }]);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
it('should accept a links array with multiple entries', () => {
|
|
102
|
+
const input = JSON.stringify({
|
|
103
|
+
interactions: [{
|
|
104
|
+
title: 'T', message: 'M',
|
|
105
|
+
options: [{ text: 'A', value: 'a' }],
|
|
106
|
+
links: [
|
|
107
|
+
{ ref: 'src/a.ts' },
|
|
108
|
+
{ ref: 'src/old.ts', rightRef: 'src/new.ts' }
|
|
109
|
+
]
|
|
110
|
+
}]
|
|
111
|
+
});
|
|
112
|
+
const result = parseUserInteractionArgs(input);
|
|
113
|
+
expect(result!.interactions[0].links).to.have.length(2);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should filter out invalid links from a step', () => {
|
|
117
|
+
const input = JSON.stringify({
|
|
118
|
+
interactions: [{
|
|
119
|
+
title: 'T', message: 'M',
|
|
120
|
+
options: [{ text: 'A', value: 'a' }],
|
|
121
|
+
links: [
|
|
122
|
+
{ ref: 'src/a.ts' },
|
|
123
|
+
{ noRef: true },
|
|
124
|
+
{ ref: '' }
|
|
125
|
+
]
|
|
126
|
+
}]
|
|
127
|
+
});
|
|
128
|
+
const result = parseUserInteractionArgs(input);
|
|
129
|
+
expect(result!.interactions[0].links).to.have.length(1);
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('should accept multiple steps in order', () => {
|
|
133
|
+
const input = JSON.stringify({
|
|
134
|
+
interactions: [
|
|
135
|
+
{ title: 'Overview', message: 'PR summary' },
|
|
136
|
+
{ title: 'Area 1', message: 'finding', options: [{ text: 'OK', value: 'approve' }] },
|
|
137
|
+
{ title: 'Area 2', message: 'no findings' }
|
|
138
|
+
]
|
|
139
|
+
});
|
|
140
|
+
const result = parseUserInteractionArgs(input);
|
|
141
|
+
expect(result!.interactions).to.have.length(3);
|
|
142
|
+
expect(result!.interactions[1].options).to.have.length(1);
|
|
143
|
+
expect(result!.interactions[2].options).to.be.undefined;
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('should preserve buttonLabel in options', () => {
|
|
147
|
+
const input = JSON.stringify({
|
|
148
|
+
interactions: [{
|
|
149
|
+
title: 'T', message: 'M',
|
|
150
|
+
options: [{ text: 'Confirm changes', value: 'confirm', buttonLabel: '✅ Confirm' }]
|
|
151
|
+
}]
|
|
152
|
+
});
|
|
153
|
+
const result = parseUserInteractionArgs(input);
|
|
154
|
+
expect(result!.interactions[0].options![0].buttonLabel).to.equal('✅ Confirm');
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it('should reject step links with empty path in object ref', () => {
|
|
158
|
+
const input = JSON.stringify({
|
|
159
|
+
interactions: [{
|
|
160
|
+
title: 'T', message: 'M',
|
|
161
|
+
links: [{ ref: { path: '' } }]
|
|
162
|
+
}]
|
|
163
|
+
});
|
|
164
|
+
const result = parseUserInteractionArgs(input);
|
|
165
|
+
expect(result!.interactions[0].links).to.be.undefined;
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should accept step links with EmptyContentRef', () => {
|
|
169
|
+
const input = JSON.stringify({
|
|
170
|
+
interactions: [{
|
|
171
|
+
title: 'T', message: 'M',
|
|
172
|
+
links: [{ ref: { empty: true, label: 'New file' } }]
|
|
173
|
+
}]
|
|
174
|
+
});
|
|
175
|
+
const result = parseUserInteractionArgs(input);
|
|
176
|
+
expect(result!.interactions[0].links![0].ref).to.deep.equal({ empty: true, label: 'New file' });
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it('should accept step links with EmptyContentRef as rightRef', () => {
|
|
180
|
+
const input = JSON.stringify({
|
|
181
|
+
interactions: [{
|
|
182
|
+
title: 'T', message: 'M',
|
|
183
|
+
links: [{ ref: 'src/old.ts', rightRef: { empty: true } }]
|
|
184
|
+
}]
|
|
185
|
+
});
|
|
186
|
+
const result = parseUserInteractionArgs(input);
|
|
187
|
+
expect(result!.interactions[0].links![0].rightRef).to.deep.equal({ empty: true });
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe('parseUserInteractionInput', () => {
|
|
192
|
+
it('should return empty result for undefined input', () => {
|
|
193
|
+
expect(parseUserInteractionInput(undefined)).to.deep.equal({ title: '', stepCount: 0 });
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
it('should return empty result for empty string', () => {
|
|
197
|
+
expect(parseUserInteractionInput('')).to.deep.equal({ title: '', stepCount: 0 });
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it('should extract first step title and step count from valid JSON', () => {
|
|
201
|
+
const input = JSON.stringify({ interactions: [{ title: 'First' }, { title: 'Second' }] });
|
|
202
|
+
expect(parseUserInteractionInput(input)).to.deep.equal({ title: 'First', stepCount: 2 });
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('should return empty title and 0 count when interactions array is empty', () => {
|
|
206
|
+
const input = JSON.stringify({ interactions: [] });
|
|
207
|
+
expect(parseUserInteractionInput(input)).to.deep.equal({ title: '', stepCount: 0 });
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it('should fall back to regex-based title extraction for incomplete JSON', () => {
|
|
211
|
+
const input = '{"interactions": [{"title": "Streaming Title", "message": "incom';
|
|
212
|
+
expect(parseUserInteractionInput(input).title).to.equal('Streaming Title');
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it('should return empty title from incomplete JSON without title field', () => {
|
|
216
|
+
const input = '{"interactions": [{"message": "no title here';
|
|
217
|
+
expect(parseUserInteractionInput(input).title).to.equal('');
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
describe('buildDiffLabel', () => {
|
|
222
|
+
it('formats two empty refs', () => {
|
|
223
|
+
expect(buildDiffLabel({ empty: true, label: 'New' }, { empty: true, label: 'Deleted' }))
|
|
224
|
+
.to.equal('New ⟷ Deleted');
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it('formats empty left vs path with gitRef', () => {
|
|
228
|
+
expect(buildDiffLabel({ empty: true, label: 'New' }, { path: 'src/x.ts', gitRef: 'abcdef0123' }))
|
|
229
|
+
.to.equal('src/x.ts (New ⟷ abcdef0)');
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
it('formats path with gitRef vs working copy of same path', () => {
|
|
233
|
+
expect(buildDiffLabel({ path: 'src/x.ts', gitRef: 'abcdef0123' }, { path: 'src/x.ts' }))
|
|
234
|
+
.to.equal('src/x.ts (abcdef0 ⟷ Working Copy)');
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('formats two different paths', () => {
|
|
238
|
+
expect(buildDiffLabel({ path: 'src/old.ts' }, { path: 'src/new.ts' }))
|
|
239
|
+
.to.equal('src/old.ts ⟷ src/new.ts');
|
|
240
|
+
});
|
|
241
|
+
});
|