@link-assistant/hive-mind 1.65.2 ā 1.67.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/CHANGELOG.md +12 -0
- package/package.json +2 -1
- package/src/agent.prompts.lib.mjs +2 -1
- package/src/claude-quiet-config.lib.mjs +28 -2
- package/src/claude.lib.mjs +7 -1
- package/src/claude.prompts.lib.mjs +2 -1
- package/src/codex.prompts.lib.mjs +2 -1
- package/src/gemini.prompts.lib.mjs +2 -1
- package/src/hive.mjs +3 -0
- package/src/i18n.lib.mjs +239 -0
- package/src/locales/en.lino +131 -0
- package/src/locales/hi.lino +131 -0
- package/src/locales/ru.lino +131 -0
- package/src/locales/zh.lino +131 -0
- package/src/opencode.prompts.lib.mjs +2 -1
- package/src/qwen.prompts.lib.mjs +2 -1
- package/src/review.mjs +23 -0
- package/src/solve.config.lib.mjs +15 -0
- package/src/solve.mjs +10 -0
- package/src/task.config.lib.mjs +15 -0
- package/src/task.mjs +8 -0
- package/src/telegram-bot.mjs +56 -25
- package/src/telegram-language-command.lib.mjs +49 -0
- package/src/telegram-task-command.lib.mjs +16 -2
- package/src/work-language.prompts.lib.mjs +22 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 1.67.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- d88aa94: Add `--ui-language` and `--work-language` flags for two-track i18n (issue #378). The existing `--language LOCALE` continues to set both tracks at once; `--ui-language LOCALE` overrides only UI/log strings, and `--work-language LOCALE` overrides only the language the AI uses for free-form output (PR/issue comments, commit messages, chat replies). Code, identifiers, and CLI strings stay in their original form. Supported locales: `en` (default), `ru`, `zh`, `hi`. The Telegram bot now resolves the user's effective locale and propagates it as `--language` to spawned solve/hive/task processes when no language flag is already present.
|
|
8
|
+
|
|
9
|
+
## 1.66.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- f744d5a: Add internationalisation (i18n) for user-facing terminal output and the Telegram bot. Translations are stored in `links-notation` files under `src/locales/` (`en`, `ru`, `zh`, `hi`) and loaded via `lino-objects-codec`. Adds a `--language <en|ru|zh|hi>` option to `solve`, `hive`, `task`, and `review` (defaults to detected system locale). The Telegram bot picks each user's language from `ctx.from.language_code` with a per-user override settable through a new `/language <code|default>` command (in-memory, resets on bot restart). Built-in commands `/limits`, `/version`, `/solve`, `/hive`, and `/language` now reply in the user's selected language. AI prompts are intentionally untouched - only human-facing strings are translated.
|
|
14
|
+
|
|
3
15
|
## 1.65.2
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@link-assistant/hive-mind",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.67.0",
|
|
4
4
|
"description": "AI-powered issue solver and hive mind for collaborative problem solving",
|
|
5
5
|
"main": "src/hive.mjs",
|
|
6
6
|
"type": "module",
|
|
@@ -76,6 +76,7 @@
|
|
|
76
76
|
"dayjs": "^1.11.19",
|
|
77
77
|
"decimal.js-light": "^2.5.1",
|
|
78
78
|
"lino-arguments": "^0.3.0",
|
|
79
|
+
"lino-objects-codec": "^0.3.6",
|
|
79
80
|
"secretlint": "^11.2.5",
|
|
80
81
|
"semver": "^7.7.3"
|
|
81
82
|
},
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { getArchitectureCareSubPrompt } from './architecture-care.prompts.lib.mjs';
|
|
7
7
|
import { getExperimentsExamplesSubPrompt } from './experiments-examples.prompts.lib.mjs';
|
|
8
8
|
import { getThinkingPromptInstruction } from './thinking-prompt.lib.mjs';
|
|
9
|
+
import { buildWorkLanguageDirective } from './work-language.prompts.lib.mjs';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Build the user prompt for Agent
|
|
@@ -257,7 +258,7 @@ Visual UI work and screenshots.
|
|
|
257
258
|
- When the fix is visual, include side-by-side or sequential comparison of before/after states in the PR description.
|
|
258
259
|
- When possible, create automated visual regression tests to prevent the UI bug from recurring.`
|
|
259
260
|
: ''
|
|
260
|
-
}${ciExamples}${getArchitectureCareSubPrompt(argv)}`;
|
|
261
|
+
}${ciExamples}${getArchitectureCareSubPrompt(argv)}${buildWorkLanguageDirective()}`;
|
|
261
262
|
};
|
|
262
263
|
|
|
263
264
|
// Export all functions as default object too
|
|
@@ -60,7 +60,22 @@ export const formatClaudeQuietConfigSummary = () => {
|
|
|
60
60
|
|
|
61
61
|
const isPlainObject = value => value && typeof value === 'object' && !Array.isArray(value);
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
// Map our 2-letter locale to the BCP-47-like language string Claude Code accepts.
|
|
64
|
+
// See https://code.claude.com/docs/en/settings#available-settings for the
|
|
65
|
+
// supported `language` values.
|
|
66
|
+
const LOCALE_TO_CLAUDE_LANGUAGE = Object.freeze({
|
|
67
|
+
en: 'English',
|
|
68
|
+
ru: 'Russian',
|
|
69
|
+
zh: 'Chinese (Simplified)',
|
|
70
|
+
hi: 'Hindi',
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export function resolveClaudeLanguageSetting(locale) {
|
|
74
|
+
if (!locale) return null;
|
|
75
|
+
return LOCALE_TO_CLAUDE_LANGUAGE[locale] || null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const ensureClaudeQuietConfig = async ({ settingsPath, log, workLanguage = null } = {}) => {
|
|
64
79
|
const resolvedPath = settingsPath || path.join(os.homedir(), '.claude', 'settings.json');
|
|
65
80
|
let settings = {};
|
|
66
81
|
try {
|
|
@@ -118,7 +133,18 @@ export const ensureClaudeQuietConfig = async ({ settingsPath, log } = {}) => {
|
|
|
118
133
|
}
|
|
119
134
|
settings.env = existingEnv;
|
|
120
135
|
|
|
121
|
-
|
|
136
|
+
// Issue #378: write Claude Code's `language` setting from --work-language.
|
|
137
|
+
// When workLanguage is null, we deliberately leave any existing value alone
|
|
138
|
+
// so the user's manual override stays intact between solve invocations.
|
|
139
|
+
const desiredLanguage = resolveClaudeLanguageSetting(workLanguage);
|
|
140
|
+
let updatedLanguage = false;
|
|
141
|
+
if (desiredLanguage && settings.language !== desiredLanguage) {
|
|
142
|
+
settings.language = desiredLanguage;
|
|
143
|
+
updatedSettingsKeys.push('language');
|
|
144
|
+
updatedLanguage = true;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const changed = updatedSettingsKeys.length > 0 || updatedEnvKeys.length > 0 || updatedLanguage;
|
|
122
148
|
try {
|
|
123
149
|
if (changed) {
|
|
124
150
|
await fs.mkdir(path.dirname(resolvedPath), { recursive: true });
|
package/src/claude.lib.mjs
CHANGED
|
@@ -719,7 +719,13 @@ export const executeClaudeCommand = async params => {
|
|
|
719
719
|
await log(`š Resuming from session: ${argv.resume}`);
|
|
720
720
|
claudeArgs = `--resume ${argv.resume} ${claudeArgs}`;
|
|
721
721
|
}
|
|
722
|
-
|
|
722
|
+
let claudeWorkLanguage = null;
|
|
723
|
+
try {
|
|
724
|
+
claudeWorkLanguage = (await import('./i18n.lib.mjs')).getWorkLocale?.() ?? null;
|
|
725
|
+
} catch {
|
|
726
|
+
/* ignore */
|
|
727
|
+
}
|
|
728
|
+
await ensureClaudeQuietConfig({ log, workLanguage: claudeWorkLanguage });
|
|
723
729
|
const { mcpConfigPath, disallowedToolsList } = await resolveClaudeSessionToolFlags({ argv, log, fallbackBuildMcpConfigWithoutPlaywright: buildMcpConfigWithoutPlaywright });
|
|
724
730
|
if (mcpConfigPath) claudeArgs += ` --strict-mcp-config --mcp-config "${mcpConfigPath}"`;
|
|
725
731
|
if (disallowedToolsList.length) claudeArgs += ` --disallowedTools ${disallowedToolsList.join(' ')}`;
|
|
@@ -7,6 +7,7 @@ import { getArchitectureCareSubPrompt } from './architecture-care.prompts.lib.mj
|
|
|
7
7
|
import { getExperimentsExamplesSubPrompt } from './experiments-examples.prompts.lib.mjs';
|
|
8
8
|
import { primaryModelNames } from './models/index.mjs';
|
|
9
9
|
import { getThinkingPromptInstruction } from './thinking-prompt.lib.mjs';
|
|
10
|
+
import { buildWorkLanguageDirective } from './work-language.prompts.lib.mjs';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Build the user prompt for Claude
|
|
@@ -328,7 +329,7 @@ Visual UI work and screenshots.
|
|
|
328
329
|
- When the fix is visual, include side-by-side or sequential comparison of before/after states in the PR description.
|
|
329
330
|
- When possible, create automated visual regression tests to prevent the UI bug from recurring.`
|
|
330
331
|
: ''
|
|
331
|
-
}${ciExamples}${getArchitectureCareSubPrompt(argv)}`;
|
|
332
|
+
}${ciExamples}${getArchitectureCareSubPrompt(argv)}${buildWorkLanguageDirective()}`;
|
|
332
333
|
};
|
|
333
334
|
|
|
334
335
|
// Export all functions as default object too
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { getArchitectureCareSubPrompt } from './architecture-care.prompts.lib.mjs';
|
|
7
7
|
import { getExperimentsExamplesSubPrompt } from './experiments-examples.prompts.lib.mjs';
|
|
8
8
|
import { getThinkingPromptInstruction } from './thinking-prompt.lib.mjs';
|
|
9
|
+
import { buildWorkLanguageDirective } from './work-language.prompts.lib.mjs';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Build the user prompt for Codex
|
|
@@ -305,7 +306,7 @@ Visual UI work and screenshots.
|
|
|
305
306
|
- When the fix is visual, include side-by-side or sequential comparison of before/after states in the PR description.
|
|
306
307
|
- When possible, create automated visual regression tests to prevent the UI bug from recurring.`
|
|
307
308
|
: ''
|
|
308
|
-
}${ciExamples}${getArchitectureCareSubPrompt(argv)}`;
|
|
309
|
+
}${ciExamples}${getArchitectureCareSubPrompt(argv)}${buildWorkLanguageDirective()}`;
|
|
309
310
|
};
|
|
310
311
|
|
|
311
312
|
// Export all functions as default object too
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import { getArchitectureCareSubPrompt } from './architecture-care.prompts.lib.mjs';
|
|
7
7
|
import { getExperimentsExamplesSubPrompt } from './experiments-examples.prompts.lib.mjs';
|
|
8
8
|
import { getThinkingPromptInstruction } from './thinking-prompt.lib.mjs';
|
|
9
|
+
import { buildWorkLanguageDirective } from './work-language.prompts.lib.mjs';
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Build the user prompt for Gemini
|
|
@@ -227,7 +228,7 @@ Visual UI work and screenshots.
|
|
|
227
228
|
- When you work on visual UI changes, include a render or screenshot of the final result in the pull request description.
|
|
228
229
|
- When you save screenshots to the repository, use permanent links in the PR description such as https://github.com/${screenshotRepoPath}/blob/${branchName}/docs/screenshots/result.png?raw=true.`
|
|
229
230
|
: ''
|
|
230
|
-
}${ciExamples}${getArchitectureCareSubPrompt(argv)}`;
|
|
231
|
+
}${ciExamples}${getArchitectureCareSubPrompt(argv)}${buildWorkLanguageDirective()}`;
|
|
231
232
|
};
|
|
232
233
|
|
|
233
234
|
export default {
|
package/src/hive.mjs
CHANGED
|
@@ -292,6 +292,9 @@ if (isRunningDirectly) {
|
|
|
292
292
|
// Set global verbose mode
|
|
293
293
|
global.verboseMode = argv.verbose;
|
|
294
294
|
|
|
295
|
+
const { initI18n } = await import('./i18n.lib.mjs');
|
|
296
|
+
await initI18n({ language: argv.language, uiLanguage: argv.uiLanguage, workLanguage: argv.workLanguage });
|
|
297
|
+
|
|
295
298
|
setupVerboseLogInterceptor(); // Issue #1466: capture [VERBOSE] output in log files
|
|
296
299
|
setupStdioLogInterceptor(); // Issue #1549: capture ALL terminal output in log file
|
|
297
300
|
|
package/src/i18n.lib.mjs
ADDED
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
// i18n module for hive-mind.
|
|
2
|
+
// - Translation files live in src/locales/<locale>.lino and are stored
|
|
3
|
+
// in Links Notation, parsed via lino-objects-codec.
|
|
4
|
+
// - Supported locales: en (default fallback), ru, zh, hi.
|
|
5
|
+
// - Two locale tracks: ui (user-facing strings) and work (AI prompts /
|
|
6
|
+
// tool preferred language). Both default to the value of --language.
|
|
7
|
+
// - Public API: initI18n, t, getCurrentLocale, getUiLocale, getWorkLocale,
|
|
8
|
+
// setLocale, setUiLocale, setWorkLocale, getSupportedLocales,
|
|
9
|
+
// normalizeLocale, getUserLocale, setUserLocale, clearUserLocale,
|
|
10
|
+
// resolveLocaleFromTelegramCtx.
|
|
11
|
+
|
|
12
|
+
import { promises as fs } from 'fs';
|
|
13
|
+
import path from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
import { parseIndented } from 'lino-objects-codec';
|
|
16
|
+
|
|
17
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
18
|
+
const __dirname = path.dirname(__filename);
|
|
19
|
+
|
|
20
|
+
const DEFAULT_LOCALE = 'en';
|
|
21
|
+
const SUPPORTED_LOCALES = ['en', 'ru', 'zh', 'hi'];
|
|
22
|
+
|
|
23
|
+
const localeCache = new Map(); // locale -> { key: string }
|
|
24
|
+
const userLocales = new Map(); // userId/chatId -> locale (in-memory)
|
|
25
|
+
|
|
26
|
+
let currentUiLocale = DEFAULT_LOCALE;
|
|
27
|
+
let currentWorkLocale = DEFAULT_LOCALE;
|
|
28
|
+
let fallbackLoaded = false;
|
|
29
|
+
|
|
30
|
+
export function getSupportedLocales() {
|
|
31
|
+
return [...SUPPORTED_LOCALES];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function normalizeLocale(input) {
|
|
35
|
+
if (!input || typeof input !== 'string') return null;
|
|
36
|
+
const lower = input.toLowerCase();
|
|
37
|
+
// Take only the language part (before "_" or "-")
|
|
38
|
+
const lang = lower.split(/[_\-.]/)[0];
|
|
39
|
+
if (SUPPORTED_LOCALES.includes(lang)) return lang;
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function detectLocale() {
|
|
44
|
+
const envLocale = process.env.LANG || process.env.LANGUAGE || process.env.LC_ALL || process.env.LC_MESSAGES || '';
|
|
45
|
+
return normalizeLocale(envLocale) || DEFAULT_LOCALE;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async function readLocaleFile(locale) {
|
|
49
|
+
const localesDir = path.join(__dirname, 'locales');
|
|
50
|
+
const linoFile = path.join(localesDir, `${locale}.lino`);
|
|
51
|
+
const data = await fs.readFile(linoFile, 'utf-8');
|
|
52
|
+
return parseIndentedToFlatMap(data);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// parseIndented returns { id, obj } where obj is the key->value map.
|
|
56
|
+
// Some keys contain dots (e.g., error.invalid_github_url). The parser
|
|
57
|
+
// supports them when the key is a plain reference (no spaces/quotes).
|
|
58
|
+
function unescapeString(s) {
|
|
59
|
+
// Convert literal escape sequences (e.g., "\n" inside a quoted string in
|
|
60
|
+
// Links Notation) into the corresponding JS characters. This keeps the
|
|
61
|
+
// .lino files single-line and human-friendly.
|
|
62
|
+
return s.replace(/\\n/g, '\n').replace(/\\t/g, '\t').replace(/\\r/g, '\r').replace(/\\\\/g, '\\');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function parseIndentedToFlatMap(text) {
|
|
66
|
+
const parsed = parseIndented({ text });
|
|
67
|
+
// parsed: { id: <localeName>, obj: { key: value, ... } }
|
|
68
|
+
if (!parsed || !parsed.obj) return {};
|
|
69
|
+
const out = {};
|
|
70
|
+
for (const [k, v] of Object.entries(parsed.obj)) {
|
|
71
|
+
out[k] = typeof v === 'string' ? unescapeString(v) : String(v);
|
|
72
|
+
}
|
|
73
|
+
return out;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export async function loadTranslations(locale) {
|
|
77
|
+
if (localeCache.has(locale)) return localeCache.get(locale);
|
|
78
|
+
|
|
79
|
+
let translations = {};
|
|
80
|
+
try {
|
|
81
|
+
translations = await readLocaleFile(locale);
|
|
82
|
+
} catch {
|
|
83
|
+
translations = {};
|
|
84
|
+
}
|
|
85
|
+
localeCache.set(locale, translations);
|
|
86
|
+
|
|
87
|
+
// Always have the fallback (English) ready
|
|
88
|
+
if (!fallbackLoaded && locale !== DEFAULT_LOCALE) {
|
|
89
|
+
try {
|
|
90
|
+
const fb = await readLocaleFile(DEFAULT_LOCALE);
|
|
91
|
+
localeCache.set(DEFAULT_LOCALE, fb);
|
|
92
|
+
} catch {
|
|
93
|
+
localeCache.set(DEFAULT_LOCALE, {});
|
|
94
|
+
}
|
|
95
|
+
fallbackLoaded = true;
|
|
96
|
+
} else if (locale === DEFAULT_LOCALE) {
|
|
97
|
+
fallbackLoaded = true;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return translations;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// initI18n accepts either a single locale string (legacy) that sets both
|
|
104
|
+
// ui and work locales, or an object { language, uiLanguage, workLanguage }.
|
|
105
|
+
// Resolution rules:
|
|
106
|
+
// - If uiLanguage given, use it for UI; else use language; else detect.
|
|
107
|
+
// - If workLanguage given, use it for work; else use language; else detect.
|
|
108
|
+
export async function initI18n(input = null) {
|
|
109
|
+
let language = null;
|
|
110
|
+
let uiLanguage = null;
|
|
111
|
+
let workLanguage = null;
|
|
112
|
+
|
|
113
|
+
if (input && typeof input === 'object') {
|
|
114
|
+
language = input.language ?? null;
|
|
115
|
+
uiLanguage = input.uiLanguage ?? null;
|
|
116
|
+
workLanguage = input.workLanguage ?? null;
|
|
117
|
+
} else if (typeof input === 'string') {
|
|
118
|
+
language = input;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const baseLocale = (language ? normalizeLocale(language) : null) || detectLocale();
|
|
122
|
+
const uiLocale = (uiLanguage ? normalizeLocale(uiLanguage) : null) || baseLocale;
|
|
123
|
+
const workLocale = (workLanguage ? normalizeLocale(workLanguage) : null) || baseLocale;
|
|
124
|
+
|
|
125
|
+
currentUiLocale = uiLocale;
|
|
126
|
+
currentWorkLocale = workLocale;
|
|
127
|
+
|
|
128
|
+
await loadTranslations(uiLocale);
|
|
129
|
+
if (workLocale !== uiLocale) {
|
|
130
|
+
await loadTranslations(workLocale);
|
|
131
|
+
}
|
|
132
|
+
if (uiLocale !== DEFAULT_LOCALE && workLocale !== DEFAULT_LOCALE) {
|
|
133
|
+
await loadTranslations(DEFAULT_LOCALE);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return { uiLocale, workLocale };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function applyParams(text, params) {
|
|
140
|
+
if (!params) return text;
|
|
141
|
+
let out = text;
|
|
142
|
+
for (const [k, v] of Object.entries(params)) {
|
|
143
|
+
out = out.replace(new RegExp(`{{${k}}}`, 'g'), String(v));
|
|
144
|
+
}
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// t() returns a translated string. By default uses the UI locale.
|
|
149
|
+
// Pass options.locale to override; pass options.track = 'work' to use the
|
|
150
|
+
// work locale (for AI prompts).
|
|
151
|
+
export function t(key, params = {}, options = {}) {
|
|
152
|
+
let locale;
|
|
153
|
+
if (options.locale) {
|
|
154
|
+
locale = normalizeLocale(options.locale) || currentUiLocale;
|
|
155
|
+
} else if (options.track === 'work') {
|
|
156
|
+
locale = currentWorkLocale;
|
|
157
|
+
} else {
|
|
158
|
+
locale = currentUiLocale;
|
|
159
|
+
}
|
|
160
|
+
const main = localeCache.get(locale) || {};
|
|
161
|
+
const fallback = localeCache.get(DEFAULT_LOCALE) || {};
|
|
162
|
+
const value = main[key] ?? fallback[key] ?? key;
|
|
163
|
+
return applyParams(value, params);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Convenience helper for work-language strings (AI prompts).
|
|
167
|
+
export function tWork(key, params = {}) {
|
|
168
|
+
return t(key, params, { track: 'work' });
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function getCurrentLocale() {
|
|
172
|
+
return currentUiLocale;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export function getUiLocale() {
|
|
176
|
+
return currentUiLocale;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function getWorkLocale() {
|
|
180
|
+
return currentWorkLocale;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function setLocale(locale) {
|
|
184
|
+
const normalized = normalizeLocale(locale);
|
|
185
|
+
if (normalized) {
|
|
186
|
+
currentUiLocale = normalized;
|
|
187
|
+
currentWorkLocale = normalized;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function setUiLocale(locale) {
|
|
192
|
+
const normalized = normalizeLocale(locale);
|
|
193
|
+
if (normalized) currentUiLocale = normalized;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function setWorkLocale(locale) {
|
|
197
|
+
const normalized = normalizeLocale(locale);
|
|
198
|
+
if (normalized) currentWorkLocale = normalized;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// In-memory per-user locale store (used by the Telegram bot).
|
|
202
|
+
export function getUserLocale(userId) {
|
|
203
|
+
if (userId === undefined || userId === null) return null;
|
|
204
|
+
return userLocales.get(String(userId)) || null;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export function setUserLocale(userId, locale) {
|
|
208
|
+
const normalized = normalizeLocale(locale);
|
|
209
|
+
if (!normalized || userId === undefined || userId === null) return false;
|
|
210
|
+
userLocales.set(String(userId), normalized);
|
|
211
|
+
return true;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function clearUserLocale(userId) {
|
|
215
|
+
if (userId === undefined || userId === null) return false;
|
|
216
|
+
return userLocales.delete(String(userId));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Resolve the best locale for a Telegram update context.
|
|
220
|
+
// Priority: per-user override -> ctx.from.language_code -> current default.
|
|
221
|
+
export function resolveLocaleFromTelegramCtx(ctx) {
|
|
222
|
+
const userId = ctx?.from?.id;
|
|
223
|
+
const userOverride = getUserLocale(userId);
|
|
224
|
+
if (userOverride) return userOverride;
|
|
225
|
+
const fromTelegram = normalizeLocale(ctx?.from?.language_code);
|
|
226
|
+
if (fromTelegram) return fromTelegram;
|
|
227
|
+
return currentUiLocale;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Pre-load every supported locale (handy for the Telegram bot at startup).
|
|
231
|
+
export async function preloadAllLocales() {
|
|
232
|
+
for (const loc of SUPPORTED_LOCALES) {
|
|
233
|
+
try {
|
|
234
|
+
await loadTranslations(loc);
|
|
235
|
+
} catch {
|
|
236
|
+
// ignore - missing files fall back to English
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
en
|
|
2
|
+
error "Error"
|
|
3
|
+
success "Success"
|
|
4
|
+
warning "Warning"
|
|
5
|
+
failed "Failed"
|
|
6
|
+
info "Info"
|
|
7
|
+
error.invalid_github_url "Error: Invalid GitHub URL format"
|
|
8
|
+
error.invalid_github_url_monitoring "Error: Invalid GitHub URL for monitoring"
|
|
9
|
+
error.missing_required_url "Error: Missing required github issue or pull request URL"
|
|
10
|
+
error.unable_determine_version "Error: Unable to determine version"
|
|
11
|
+
error.invalid_url_type "Error: Invalid GitHub URL format"
|
|
12
|
+
error.url_type_not_supported "URL type '{{type}}' is not supported"
|
|
13
|
+
error.failed_to_get_current_user "Error: Failed to get current user"
|
|
14
|
+
error.failed_to_initialize_repository "Error: Failed to initialize repository"
|
|
15
|
+
error.failed_to_create_fork "Failed to create fork after all retries"
|
|
16
|
+
error.fork_not_accessible "Fork exists but not accessible after multiple retries"
|
|
17
|
+
error.failed_to_add_upstream_remote "Failed to add upstream remote"
|
|
18
|
+
error.failed_to_checkout "Failed to checkout {{branch}}"
|
|
19
|
+
error.failed_to_sync "Failed to sync {{branch}} with upstream"
|
|
20
|
+
error.failed_to_get_default_branch "Failed to get default branch name"
|
|
21
|
+
error.failed_to_get_current_branch "Failed to get current branch"
|
|
22
|
+
error.failed_to_fetch_upstream "Failed to fetch upstream"
|
|
23
|
+
error.failed_to_add_pr_fork_remote "Failed to add pr-fork remote"
|
|
24
|
+
error.failed_to_fetch_from_pr_fork "Failed to fetch from pr-fork"
|
|
25
|
+
error.pr_does_not_exist "Error: PR #{{prNumber}} does not exist in {{owner}}/{{repo}}"
|
|
26
|
+
error.youtrack_url_detected_no_config "Error: YouTrack URL detected but YouTrack configuration not found"
|
|
27
|
+
error.telegram_bot_token_not_set "Error: TELEGRAM_BOT_TOKEN environment variable or --token option is not set"
|
|
28
|
+
error.invalid_github_url_solve "Error: Invalid GitHub URL for solve command"
|
|
29
|
+
error.invalid_language "Invalid language '{{value}}'. Supported: {{supported}}"
|
|
30
|
+
success.readme_created "README.md created successfully"
|
|
31
|
+
success.process_completed "Process completed"
|
|
32
|
+
success.error_reported_to_sentry "Error reported to Sentry successfully"
|
|
33
|
+
success.language_set "Language set to {{language}}"
|
|
34
|
+
warning.session_log_not_found "Warning: Session log for {{session}} not found, but continuing with resume attempt"
|
|
35
|
+
warning.failed_to_create_readme "Failed: Could not create README.md"
|
|
36
|
+
warning.could_not_determine_root_repository "Could not determine root repository"
|
|
37
|
+
warning.could_not_check_fork_status "Warning: Could not check fork status: {{message}}"
|
|
38
|
+
warning.no_linked_issue_found "Warning: No linked issue found in PR body"
|
|
39
|
+
warning.could_not_search_for_existing_prs "Warning: Could not search for existing PRs: {{message}}"
|
|
40
|
+
warning.could_not_get_current_user "Warning: Could not get current GitHub user"
|
|
41
|
+
warning.could_not_check_github_permissions "Warning: Could not check GitHub permissions: {{message}}"
|
|
42
|
+
warning.could_not_determine_token_scopes "Warning: Could not determine token scopes from auth status"
|
|
43
|
+
warning.failed_to_fetch_branches "Warning: Failed to fetch branches from remote"
|
|
44
|
+
warning.error_during_auto_pr_creation "Warning: Error during auto PR creation: {{message}}"
|
|
45
|
+
warning.could_not_convert_pr_to_draft "Warning: Could not convert PR to draft"
|
|
46
|
+
warning.could_not_check_convert_pr_draft_status "Warning: Could not check/convert PR draft status"
|
|
47
|
+
warning.could_not_post_work_start_comment "Warning: Could not post work start comment"
|
|
48
|
+
warning.could_not_post_work_end_comment "Warning: Could not post work end comment"
|
|
49
|
+
warning.could_not_convert_pr_to_ready "Warning: Could not convert PR to ready"
|
|
50
|
+
warning.could_not_convert_pr_to_ready_status "Warning: Could not convert PR to ready status"
|
|
51
|
+
warning.pr_created_but_no_url "Warning: PR created but no URL returned"
|
|
52
|
+
warning.could_not_assign_user "Could not assign user"
|
|
53
|
+
info.expected_github_url_format "Expected: https://github.com/owner or https://github.com/owner/repo"
|
|
54
|
+
info.you_can_use_formats "You can use any of these formats:"
|
|
55
|
+
info.format_https_owner "- https://github.com/owner"
|
|
56
|
+
info.format_https_owner_repo "- https://github.com/owner/repo"
|
|
57
|
+
info.format_http_owner "- http://github.com/owner (will be converted to https)"
|
|
58
|
+
info.format_github_owner "- github.com/owner (will add https://)"
|
|
59
|
+
info.format_owner "- owner (will be converted to https://github.com/owner)"
|
|
60
|
+
info.format_owner_repo "- owner/repo (will be converted to https://github.com/owner/repo)"
|
|
61
|
+
info.full_log_file "Full log file: {{path}}"
|
|
62
|
+
info.process_exited_with_code "Process exited with code {{code}}"
|
|
63
|
+
info.current_configuration "Current Configuration:"
|
|
64
|
+
process.using_repository_fallback "Using repository-by-repository fallback for {{scope}}: {{owner}}"
|
|
65
|
+
process.fetching_repository_list "Fetching repository list..."
|
|
66
|
+
process.command "Command: {{command}}"
|
|
67
|
+
check.number "Check #{{iteration}}:"
|
|
68
|
+
time.current "Current time: {{time}}"
|
|
69
|
+
telegram.fetching_limits "š Fetching usage limits..."
|
|
70
|
+
telegram.gathering_version "š Gathering version information..."
|
|
71
|
+
telegram.usage_limits_title "š *Usage Limits*"
|
|
72
|
+
telegram.version_information_title "š¤ *Version Information*"
|
|
73
|
+
telegram.limits_only_in_groups "ā The /limits command only works in group chats. Please add this bot to a group and make it an admin."
|
|
74
|
+
telegram.version_only_in_groups "ā The /version command only works in group chats. Please add this bot to a group and make it an admin."
|
|
75
|
+
telegram.solve_only_in_groups "ā The {{commandDisplay}} command only works in group chats. Please add this bot to a group and make it an admin."
|
|
76
|
+
telegram.hive_only_in_groups "ā The /hive command only works in group chats. Please add this bot to a group and make it an admin."
|
|
77
|
+
telegram.solve_disabled "ā The solve command is disabled on this bot instance."
|
|
78
|
+
telegram.hive_disabled "ā The /hive command is disabled on this bot instance."
|
|
79
|
+
telegram.no_github_link_in_reply "ā No GitHub issue/PR link found in the replied message.\n\nExample: Reply to a message containing a GitHub issue link with `/solve`\n\nOr with options: `/solve --model opus`"
|
|
80
|
+
telegram.invalid_options "ā Invalid options: {{message}}\n\nUse /help to see available options"
|
|
81
|
+
telegram.invalid_isolation "ā Invalid --isolation value '{{value}}'. Must be: screen, tmux, or docker"
|
|
82
|
+
telegram.invalid_locked_isolation "ā Invalid locked --isolation value '{{value}}'. Must be: screen, tmux, or docker"
|
|
83
|
+
telegram.option_syntax_check "Please check your option syntax."
|
|
84
|
+
telegram.url_status_active "ā This URL is {{statusText}}.\n\nURL: {{url}}\nStatus: {{status}}\n\nš” Use /solve_queue to check the queue status."
|
|
85
|
+
telegram.url_session_running "ā A working session is already running for this URL.\n\nURL: {{url}}\nSession: `{{session}}`\n\nš” Wait for the current session to complete, or use /solve\\_stop to cancel it."
|
|
86
|
+
telegram.solve_rejected "ā Solve command rejected.\n\n{{infoBlock}}\n\nš« Reason: {{reason}}"
|
|
87
|
+
telegram.language_invalid "ā Invalid language. Supported: {{supported}}.\nUsage: /language <code>"
|
|
88
|
+
telegram.language_set "ā
Language set to *{{language}}*."
|
|
89
|
+
telegram.language_current "š Current language: *{{language}}*.\nSupported: {{supported}}.\nUsage: /language <code>"
|
|
90
|
+
language.en "English"
|
|
91
|
+
language.ru "Russian"
|
|
92
|
+
language.zh "Chinese"
|
|
93
|
+
language.hi "Hindi"
|
|
94
|
+
prompt.user.issue_to_solve "Issue to solve: {{issueUrl}}"
|
|
95
|
+
prompt.user.issue_linked_to_pr "Issue to solve: Issue linked to PR #{{prNumber}}"
|
|
96
|
+
prompt.user.prepared_branch "Your prepared branch: {{branchName}}"
|
|
97
|
+
prompt.user.prepared_working_directory "Your prepared working directory: {{tempDir}}"
|
|
98
|
+
prompt.user.prepared_tmp_directory "Your prepared tmp directory for logs and downloads: {{workspaceTmpDir}}"
|
|
99
|
+
prompt.user.prepared_pull_request "Your prepared Pull Request: {{prUrl}}"
|
|
100
|
+
prompt.user.forked_repository "Your forked repository: {{forkedRepo}}"
|
|
101
|
+
prompt.user.original_repository "Original repository (upstream): {{owner}}/{{repo}}"
|
|
102
|
+
prompt.user.fork_actions_url "GitHub Actions on your fork: {{forkActionsUrl}}"
|
|
103
|
+
prompt.user.continue "Continue."
|
|
104
|
+
prompt.user.proceed "Proceed."
|
|
105
|
+
prompt.system.intro 'You are an AI issue solver. When you investigate issues, prefer root-cause analysis. When you communicate, prefer facts you have checked yourself or cite sources that provide evidence, such as quoted code or references to documents or web pages. When you are unsure or working from assumptions, test them yourself or ask clarifying questions.'
|
|
106
|
+
prompt.system.workspace_instructions 'Workspace tmp directory.\n - Use {{workspaceTmpDir}} for all temporary files, logs, and downloads.\n - When saving command output to files, save to {{workspaceTmpDir}}/command-output.log.\n - When downloading CI logs, save to {{workspaceTmpDir}}/ci-logs/.\n - When saving diffs for review, save to {{workspaceTmpDir}}/diffs/.\n - When creating debug files, save to {{workspaceTmpDir}}/debug/.'
|
|
107
|
+
prompt.system.general_guidelines_header 'General guidelines.'
|
|
108
|
+
prompt.system.general_guidelines_body ' - When you execute commands and the output becomes large, save the logs to files for easier review.\n - When running commands, avoid setting a timeout yourself. Let them run as long as needed. The default timeout of 2 minutes is usually enough, and once commands finish, review the logs in the file.\n - When running sudo commands, especially package installations like apt-get, yum, or npm install, run them in the background to avoid timeout issues and permission errors when the process needs to be killed. Use the run_in_background parameter or append & to the command.'
|
|
109
|
+
prompt.system.issue_reporting ' - When you spot errors, bugs, or minor issues during the working session that are unrelated to the main task requirements, create issues to track them when they do not already exist. The issue should include reproducible examples, ideally a minimum reproducible example, workarounds, and suggestions for fixing the issue in code. For issues in the current repository, use gh issue create --repo {{owner}}/{{repo}} --title "Issue title" --body "Issue description". For issues in third-party GitHub repositories used by the working repository, use gh issue create --repo owner/repo --title "Issue title" --body "Issue description". When similar issues may already exist, check first with gh issue list --repo owner/repo --search "keywords" to avoid duplicates. If a similar issue already exists, add a comment with gh issue comment <issue-number> --repo owner/repo --body "Comment text" describing your specific case, including anonymized logs with personal or sensitive data redacted, reproduction steps, a minimum reproducible example when practical, workarounds, and suggestions for a fix.'
|
|
110
|
+
prompt.system.ci_investigation ' - When CI is failing or user reports failures, consider adding a detailed investigation protocol to your todo list with these steps:\n Step 1: List recent runs with timestamps using: gh run list --repo {{owner}}/{{repo}} --branch {{branchName}} --limit 5 --json databaseId,conclusion,createdAt,headSha\n Step 2: Verify runs are after the latest commit by checking timestamps and SHA\n Step 3: For each non-passing run, download logs to preserve them: gh run view {run-id} --repo {{owner}}/{{repo}} --log > ci-logs/{workflow}-{run-id}.log\n Step 4: Read each downloaded log file with the Read tool to understand the actual failures\n Step 5: Report findings with specific errors and line numbers from logs\n This detailed investigation is especially helpful when user mentions CI failures, asks to investigate logs, you see non-passing status, or when finalizing a PR.\n Note: If user says failing but tools show passing, this might indicate stale data - consider downloading fresh logs and checking timestamps to resolve the discrepancy.'
|
|
111
|
+
prompt.system.large_files " - When a code or log file has more than 1500 lines, read it in chunks of 1500 lines."
|
|
112
|
+
prompt.system.complex_problems " - When facing a complex problem, do as much tracing as possible and turn on all verbose modes."
|
|
113
|
+
prompt.system.divide_and_conquer " - When you face something extremely hard, use divide and conquer."
|
|
114
|
+
prompt.system.initial_research_header "Initial research."
|
|
115
|
+
prompt.system.initial_research_body ' - When you start, create a detailed plan for yourself and follow your todo list step by step. Add as many relevant points from these guidelines to the todo list as practical so you can track the work clearly.\n - When the user mentions CI failures or asks to investigate logs, consider adding these todos to track the investigation: (1) list recent CI runs with timestamps, (2) download logs from failed runs to the ci-logs/ directory, (3) analyze error messages and identify the root cause, (4) implement a fix, (5) verify that the fix resolves the specific errors found in the logs.\n - When you read the issue, read all details and comments thoroughly.\n - When you see screenshots or images in issue descriptions, pull request descriptions, comments, or discussions, download the image to a local file first, then use the Read tool to view and analyze it. Before reading downloaded images with the Read tool, verify that the file is a valid image rather than HTML by using a CLI tool such as the file command. When corrupted or non-image files, such as GitHub Not Found pages saved as .png, are read, they can cause Could not process image errors and crash the AI solver process. When the file command shows HTML, text, or ASCII text, the download failed, so do not call Read on that file. Instead: (1) when images are from GitHub issues or PRs, such as URLs containing github.com/user-attachments, retry with: curl -L -H "Authorization: token $(gh auth token)" -o <filename> "<url>" (2) when the retry still fails, skip the image and note that it was unavailable.\n - When you need issue details, use gh issue view https://github.com/{{owner}}/{{repo}}/issues/{{issueNumber}}.\n - When you need related code, use gh search code --owner {{owner}} [keywords].\n - When you need repo context, read files in your working directory.'
|
|
116
|
+
prompt.system.explore_subagent " - When you need to learn something about the codebase structure, patterns, or how things work, use the Task tool with subagent_type=Explore to thoroughly explore the codebase."
|
|
117
|
+
prompt.system.check_sibling_prs " - When you study related work, study the most recent related pull requests."
|
|
118
|
+
prompt.system.initial_research_tail ' - When the issue is not defined clearly enough, write a comment with clarifying questions.\n - When accessing GitHub Gists (especially private ones), use gh gist view command instead of direct URL fetching to ensure proper authentication.\n - When you are fixing a bug, find the actual root cause first and run as many experiments as needed.\n - When you are fixing a bug and the code does not have enough tracing or logs, add them and keep them in the code with the default state switched off.\n - When you need comments on a pull request, note that GitHub has three different comment types with different API endpoints:\n 1. PR review comments (inline code comments): gh api repos/{{owner}}/{{repo}}/pulls/{{prNumber}}/comments --paginate\n 2. PR conversation comments (general discussion): gh api repos/{{owner}}/{{repo}}/issues/{{prNumber}}/comments --paginate\n 3. PR reviews (approve/request changes): gh api repos/{{owner}}/{{repo}}/pulls/{{prNumber}}/reviews --paginate\n Note: The command "gh pr view --json comments" only returns conversation comments and misses review comments.\n - When you need the latest comments on the issue, use gh api repos/{{owner}}/{{repo}}/issues/{{issueNumber}}/comments --paginate.'
|
|
119
|
+
prompt.system.general_purpose_subagent " - When the task is large and requires processing many files or folders, use `general-purpose` sub-agents to delegate work. Each separate file or folder can be delegated to a sub-agent for more efficient processing."
|
|
120
|
+
prompt.system.case_studies " - When working on this issue, create a comprehensive case study in the ./docs/case-studies/issue-{{issueNumber}}/ directory. Download all logs and data related to the issue to the repository. Perform deep case study analysis by searching online for additional facts and data, reconstructing the timeline/sequence of events, identifying root causes of the problem, and proposing possible solutions. Include files like README.md (executive summary, problem statement, timeline, root cause), TECHNICAL_SUMMARY.md (deep technical analysis), ANALYSIS.md (detailed investigation findings), improvements.md (proposed solutions), and supporting logs/data files."
|
|
121
|
+
prompt.system.solution_development 'Solution development and testing.\n - When issue is solvable, first create a test that reproduces the problem, then implement the fix.\n - When implementing features, search for similar existing implementations in the codebase and use them as examples instead of implementing everything from scratch.\n - When coding, commit each atomic step that is useful on its own to the pull request branch so interrupted work remains preserved in the pull request.\n - When you test:\n start from testing of small functions using separate scripts;\n write unit tests with mocks for easy and quick start.\n - When you test integrations, use existing framework.\n - When you test solution draft, include automated checks in pr.\n - When you write or modify tests, consider setting reasonable timeouts at test, suite, and CI job levels so failures surface quickly instead of hanging.\n - When you see repeated test timeout patterns in CI, investigate the root cause rather than increasing timeouts.\n - When the issue is unclear, write a comment on the issue with questions.\n - When you encounter problems that you cannot solve yourself and need human help, write a comment on the pull request asking for help.\n - When you need human help, use gh pr comment {{prNumber}} --body "your message" to comment on existing PR.'
|
|
122
|
+
prompt.system.reproducible_testing "Reproducible testing.\n - When fixing a bug, create a test that reproduces the problem before implementing the fix. When you cannot reproduce the problem, you cannot verify the fix.\n - When encountering logic bugs, write an automated test that fails due to the bug, then implement the fix to make it pass.\n - When encountering UI bugs, capture a screenshot showing the problem state, then create a visual regression test or manual verification screenshot after the fix.\n - When creating tests, prefer minimum reproducible examples, meaning the simplest test case that demonstrates the issue.\n - When submitting a fix, include in the PR description: (1) how to reproduce the issue, (2) the automated test that verifies the fix, (3) before/after screenshots for UI issues.\n - When a bug fix does not have a reproducing test, treat the fix as incomplete because regressions can occur later without notice."
|
|
123
|
+
prompt.system.preparing_pr 'Preparing pull request.\n - When you code, follow contributing guidelines.\n - When you commit, write clear message.\n - When you need examples of style, use gh pr list --repo {{owner}}/{{repo}} --state merged --search [keywords].\n - When you open pr, describe solution draft and include tests.\n - When there is a package with version and GitHub Actions workflows for automatic release, update the version (or other necessary release trigger) in your pull request to prepare for next release.\n - When you update existing pr {{prNumber}}, use gh pr edit to modify title and description.\n - When you are about to commit or push code, run local CI checks first if they are available in contributing guidelines (like ruff check, mypy, eslint, etc.) to catch errors before pushing.\n - When you finalize the pull request:\n follow style from merged prs for code, title, and description,\n check that no uncommitted changes corresponding to the original requirements are left behind,\n check that the default branch is merged into the pull request branch,\n check that all CI checks are passing if they exist before you finish,\n check for latest comments on the issue and pull request to ensure no recent feedback was missed,\n double-check that all changes in the pull request address the original requirements of the issue,\n check for newly introduced bugs in the pull request by carefully reading gh pr diff,\n check that no previously existing features were removed without an explicit request in the issue description, issue comments, or pull request comments.\n - When you finish implementation, use gh pr ready {{prNumber}}.'
|
|
124
|
+
prompt.system.workflow "Workflow and collaboration.\n - When you check branch, verify with git branch --show-current.\n - When you push, push only to branch {{branchName}}.\n - When you finish, create a pull request from branch {{branchName}}. (Note: PR {{prNumber}} already exists, update it instead)\n - When you organize workflow, use pull requests instead of direct merges to default branch (main or master).\n - When you manage commits, preserve commit history for later analysis.\n - When you contribute, keep repository history forward-moving with regular commits, pushes, and reverts if needed.\n - When you face conflict that you cannot resolve yourself, ask for help.\n - When you collaborate, respect branch protections by working only on {{branchName}}.\n - When you mention a result, include the pull request URL or comment URL.\n - When you need to create pr, remember pr {{prNumber}} already exists for this branch."
|
|
125
|
+
prompt.system.self_review_header "Self review.\n - When you check your solution draft, run all tests locally.\n - When you check your solution draft, verify git status shows a clean working tree with no uncommitted changes.\n - When you compare with repo style, use gh pr diff [number].\n - When you finalize, confirm code, tests, and description are consistent."
|
|
126
|
+
prompt.system.ensure_all_requirements " - When no explicit feedback or requirements are provided, ensure all changes are correct, consistent, validated, tested, logged, and aligned with all discussed requirements by checking the issue description and all comments on the issue and pull request. Check that all CI or CD checks are passing."
|
|
127
|
+
prompt.system.github_cli_patterns 'GitHub CLI command patterns.\n - When fetching lists from GitHub API, use the --paginate flag to ensure all results are returned (GitHub returns max 30 per page by default).\n - When listing PR review comments (inline code comments), use gh api repos/OWNER/REPO/pulls/NUMBER/comments --paginate.\n - When listing PR conversation comments, use gh api repos/OWNER/REPO/issues/NUMBER/comments --paginate.\n - When listing PR reviews, use gh api repos/OWNER/REPO/pulls/NUMBER/reviews --paginate.\n - When listing issue comments, use gh api repos/OWNER/REPO/issues/NUMBER/comments --paginate.\n - When adding PR comment, use gh pr comment NUMBER --body "text" --repo OWNER/REPO.\n - When adding issue comment, use gh issue comment NUMBER --body "text" --repo OWNER/REPO.\n - When viewing PR details, use gh pr view NUMBER --repo OWNER/REPO.\n - When filtering with jq, use gh api repos/{{owner}}/{{repo}}/pulls/{{prNumber}}/comments --paginate --jq reverse-then-slice-first-five.'
|
|
128
|
+
prompt.system.playwright_mcp "Playwright MCP usage (browser automation via mcp__playwright__* tools).\n - When you develop frontend web applications (HTML, CSS, JavaScript, React, Vue, Angular, etc.), use Playwright MCP tools to test the UI in a real browser.\n - When WebFetch tool fails to retrieve expected content (e.g., returns empty content, JavaScript-rendered pages, or login-protected pages), use Playwright MCP tools (browser_navigate, browser_snapshot) as a fallback for web browsing.\n - When WebSearch tool fails or returns insufficient results, use Playwright MCP tools (browser_navigate, browser_snapshot) as a fallback for internet search.\n - When you need to interact with dynamic web pages that require JavaScript execution, use Playwright MCP tools.\n - When you need to visually verify how a web page looks or take screenshots, use browser_take_screenshot from Playwright MCP.\n - When you need to fill forms, click buttons, or perform user interactions on web pages, use Playwright MCP tools (browser_click, browser_type, browser_fill_form).\n - When you need to test responsive design or different viewport sizes, use browser_resize from Playwright MCP.\n - When you finish using the browser, close it with browser_close to free resources.\n - When reproducing UI bugs, use browser_take_screenshot to capture the problem state before implementing any fix.\n - When fixing UI bugs, take before/after screenshots to provide visual evidence of the fix for human verification.\n - When creating UI tests, save baseline screenshots to the repository for visual regression testing.\n - When verifying UI fixes, compare screenshots to ensure the fix does not introduce unintended visual changes."
|
|
129
|
+
prompt.system.plan_subagent 'Plan sub-agent usage.\n - When you start working on a task, consider using the Plan sub-agent to research the codebase and create an implementation plan.\n - When using the Plan sub-agent, you can add it as the first item in your todo list.\n - When you delegate planning, use the Task tool with subagent_type="Plan" before starting implementation work.'
|
|
130
|
+
prompt.system.visual_ui 'Visual UI work and screenshots.\n - When you work on visual UI changes (frontend, CSS, HTML, design), include a render or screenshot of the final result in the pull request description.\n - When you need to show visual results, take a screenshot and save it to the repository (e.g., in a docs/screenshots/ or assets/ folder).\n - When you save screenshots to the repository, use permanent links in the pull request description markdown (e.g., https://github.com/{{screenshotRepoPath}}/blob/{{branchName}}/docs/screenshots/result.png?raw=true).\n - When uploading images, commit them to the branch first, then reference them using the GitHub blob URL format with ?raw=true suffix (works for both public and private repositories).\n - When the visual result is important for review, mention it explicitly in the pull request description with the embedded image.\n - When fixing UI bugs, capture both the "before" (problem) and "after" (fixed) screenshots as evidence for human verification.\n - When reporting UI bugs, include a screenshot of the problem state to enable visual verification of the fix.\n - When the fix is visual, include side-by-side or sequential comparison of before/after states in the PR description.\n - When possible, create automated visual regression tests to prevent the UI bug from recurring.'
|
|
131
|
+
prompt.system.ci_examples "CI investigation with workspace tmp directory.\n - When downloading CI run logs:\n gh run view RUN_ID --repo {{owner}}/{{repo}} --log > {{workspaceTmpDir}}/ci-logs/run-RUN_ID.log\n - When downloading failed job logs:\n gh run view RUN_ID --repo {{owner}}/{{repo}} --log-failed > {{workspaceTmpDir}}/ci-logs/run-RUN_ID-failed.log\n - When listing CI runs with details:\n gh run list --repo {{owner}}/{{repo}} --branch {{branchName}} --limit 5 --json databaseId,conclusion,createdAt,headSha > {{workspaceTmpDir}}/ci-logs/recent-runs.json\n - When saving PR diff for review:\n gh pr diff {{prNumber}} --repo {{owner}}/{{repo}} > {{workspaceTmpDir}}/diffs/pr-{{prNumber}}.diff\n - When saving command output with stderr:\n npm test 2>&1 | tee {{workspaceTmpDir}}/test-output.log\n - When investigating issue details:\n gh issue view {{issueNumber}} --repo {{owner}}/{{repo}} --json body,comments > {{workspaceTmpDir}}/issue-{{issueNumber}}.json"
|