oh-pi 0.1.52 → 0.1.53
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/dist/bin/oh-pi.js +4 -0
- package/dist/tui/agents-select.d.ts +8 -0
- package/dist/tui/agents-select.js +8 -0
- package/dist/tui/confirm-apply.d.ts +5 -0
- package/dist/tui/confirm-apply.js +11 -0
- package/dist/tui/extension-select.d.ts +5 -0
- package/dist/tui/extension-select.js +5 -0
- package/dist/tui/keybinding-select.d.ts +7 -0
- package/dist/tui/keybinding-select.js +7 -0
- package/dist/tui/mode-select.d.ts +5 -0
- package/dist/tui/mode-select.js +5 -0
- package/dist/tui/preset-select.d.ts +5 -0
- package/dist/tui/preset-select.js +9 -0
- package/dist/tui/provider-setup.d.ts +5 -0
- package/dist/tui/provider-setup.js +30 -1
- package/dist/tui/theme-select.d.ts +5 -0
- package/dist/tui/theme-select.js +5 -0
- package/dist/tui/welcome.d.ts +4 -0
- package/dist/tui/welcome.js +9 -0
- package/dist/utils/resources.d.ts +1 -0
- package/dist/utils/resources.js +1 -0
- package/package.json +1 -1
- package/pi-package/extensions/ant-colony/concurrency.ts +6 -1
- package/pi-package/extensions/ant-colony/index.ts +69 -0
- package/pi-package/extensions/ant-colony/nest.ts +2 -2
- package/pi-package/extensions/ant-colony/queen.ts +2 -3
- package/pi-package/extensions/ant-colony/spawner.ts +3 -0
package/dist/bin/oh-pi.js
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @module oh-pi CLI 入口脚本
|
|
4
|
+
* 处理 Windows 终端 UTF-8 编码,然后启动主流程。
|
|
5
|
+
*/
|
|
2
6
|
import { execSync } from "node:child_process";
|
|
3
7
|
// Windows terminals default to non-UTF-8 codepage (e.g. GBK/CP936),
|
|
4
8
|
// causing garbled emoji and Unicode output. Force UTF-8 before any output.
|
|
@@ -1 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Presents an interactive prompt for the user to select an agent template
|
|
3
|
+
* (e.g. general developer, fullstack, security, data/AI, colony operator).
|
|
4
|
+
*
|
|
5
|
+
* Exits the process if the user cancels the selection.
|
|
6
|
+
*
|
|
7
|
+
* @returns The selected agent template identifier string.
|
|
8
|
+
*/
|
|
1
9
|
export declare function selectAgents(): Promise<string>;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import { t } from "../i18n.js";
|
|
3
|
+
/**
|
|
4
|
+
* Presents an interactive prompt for the user to select an agent template
|
|
5
|
+
* (e.g. general developer, fullstack, security, data/AI, colony operator).
|
|
6
|
+
*
|
|
7
|
+
* Exits the process if the user cancels the selection.
|
|
8
|
+
*
|
|
9
|
+
* @returns The selected agent template identifier string.
|
|
10
|
+
*/
|
|
3
11
|
export async function selectAgents() {
|
|
4
12
|
const agent = await p.select({
|
|
5
13
|
message: t("agent.select"),
|
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
import type { OhPConfig } from "../types.js";
|
|
2
2
|
import type { EnvInfo } from "../utils/detect.js";
|
|
3
|
+
/**
|
|
4
|
+
* 展示配置摘要,处理已有配置的备份/覆盖,安装 pi(如需),并应用最终配置。
|
|
5
|
+
* @param config - 用户选择的配置对象
|
|
6
|
+
* @param env - 当前环境信息
|
|
7
|
+
*/
|
|
3
8
|
export declare function confirmApply(config: OhPConfig, env: EnvInfo): Promise<void>;
|
|
@@ -2,9 +2,20 @@ import * as p from "@clack/prompts";
|
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { t } from "../i18n.js";
|
|
4
4
|
import { applyConfig, installPi, backupConfig } from "../utils/install.js";
|
|
5
|
+
/**
|
|
6
|
+
* 统计已有配置中指定目录下的文件数量。
|
|
7
|
+
* @param env - 环境信息
|
|
8
|
+
* @param dir - 目录名称前缀
|
|
9
|
+
* @returns 匹配的文件数
|
|
10
|
+
*/
|
|
5
11
|
function countExisting(env, dir) {
|
|
6
12
|
return env.existingFiles.filter(f => f.startsWith(dir + "/")).length;
|
|
7
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* 展示配置摘要,处理已有配置的备份/覆盖,安装 pi(如需),并应用最终配置。
|
|
16
|
+
* @param config - 用户选择的配置对象
|
|
17
|
+
* @param env - 当前环境信息
|
|
18
|
+
*/
|
|
8
19
|
export async function confirmApply(config, env) {
|
|
9
20
|
// ═══ Summary ═══
|
|
10
21
|
const summary = [
|
|
@@ -1 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompts the user to select enabled extensions from the available list via a multi-select TUI prompt.
|
|
3
|
+
* Exits the process if the user cancels the selection.
|
|
4
|
+
* @returns A promise that resolves to an array of selected extension names.
|
|
5
|
+
*/
|
|
1
6
|
export declare function selectExtensions(): Promise<string[]>;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import { t } from "../i18n.js";
|
|
3
3
|
import { EXTENSIONS } from "../types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Prompts the user to select enabled extensions from the available list via a multi-select TUI prompt.
|
|
6
|
+
* Exits the process if the user cancels the selection.
|
|
7
|
+
* @returns A promise that resolves to an array of selected extension names.
|
|
8
|
+
*/
|
|
4
9
|
export async function selectExtensions() {
|
|
5
10
|
const exts = await p.multiselect({
|
|
6
11
|
message: t("ext.select"),
|
|
@@ -1 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompts the user to select a keybinding scheme (default, Vim, or Emacs).
|
|
3
|
+
*
|
|
4
|
+
* Displays an interactive select prompt and exits the process if the user cancels.
|
|
5
|
+
*
|
|
6
|
+
* @returns The name of the selected keybinding scheme.
|
|
7
|
+
*/
|
|
1
8
|
export declare function selectKeybindings(): Promise<string>;
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import { t } from "../i18n.js";
|
|
3
|
+
/**
|
|
4
|
+
* Prompts the user to select a keybinding scheme (default, Vim, or Emacs).
|
|
5
|
+
*
|
|
6
|
+
* Displays an interactive select prompt and exits the process if the user cancels.
|
|
7
|
+
*
|
|
8
|
+
* @returns The name of the selected keybinding scheme.
|
|
9
|
+
*/
|
|
3
10
|
export async function selectKeybindings() {
|
|
4
11
|
const kb = await p.select({
|
|
5
12
|
message: t("kb.select"),
|
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
import type { EnvInfo } from "../utils/detect.js";
|
|
2
2
|
export type Mode = "quick" | "custom" | "preset";
|
|
3
|
+
/**
|
|
4
|
+
* Prompt the user to select a configuration mode: quick, preset, or custom.
|
|
5
|
+
* @param {EnvInfo} env - Detected environment information
|
|
6
|
+
* @returns {Promise<Mode>} The mode selected by the user
|
|
7
|
+
*/
|
|
3
8
|
export declare function selectMode(env: EnvInfo): Promise<Mode>;
|
package/dist/tui/mode-select.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import { t } from "../i18n.js";
|
|
3
|
+
/**
|
|
4
|
+
* Prompt the user to select a configuration mode: quick, preset, or custom.
|
|
5
|
+
* @param {EnvInfo} env - Detected environment information
|
|
6
|
+
* @returns {Promise<Mode>} The mode selected by the user
|
|
7
|
+
*/
|
|
3
8
|
export async function selectMode(env) {
|
|
4
9
|
const mode = await p.select({
|
|
5
10
|
message: t("mode.select"),
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { OhPConfig } from "../types.js";
|
|
2
2
|
interface Preset extends Omit<OhPConfig, "providers"> {
|
|
3
3
|
}
|
|
4
|
+
/**
|
|
5
|
+
* Prompts the user to select a configuration preset via an interactive TUI menu.
|
|
6
|
+
* Exits the process if the user cancels the selection.
|
|
7
|
+
* @returns The {@link Preset} configuration object for the chosen preset.
|
|
8
|
+
*/
|
|
4
9
|
export declare function selectPreset(): Promise<Preset>;
|
|
5
10
|
export {};
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import { t } from "../i18n.js";
|
|
3
|
+
/**
|
|
4
|
+
* Registry of built-in configuration presets (Full Power / Clean / Colony).
|
|
5
|
+
* Each entry maps a preset key to its i18n label/hint keys and a full {@link Preset} config object.
|
|
6
|
+
*/
|
|
3
7
|
const PRESETS = {
|
|
4
8
|
full: {
|
|
5
9
|
labelKey: "preset.full", hintKey: "preset.fullHint",
|
|
@@ -27,6 +31,11 @@ const PRESETS = {
|
|
|
27
31
|
},
|
|
28
32
|
},
|
|
29
33
|
};
|
|
34
|
+
/**
|
|
35
|
+
* Prompts the user to select a configuration preset via an interactive TUI menu.
|
|
36
|
+
* Exits the process if the user cancels the selection.
|
|
37
|
+
* @returns The {@link Preset} configuration object for the chosen preset.
|
|
38
|
+
*/
|
|
30
39
|
export async function selectPreset() {
|
|
31
40
|
const key = await p.select({
|
|
32
41
|
message: t("preset.select"),
|
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
import { type ProviderConfig } from "../types.js";
|
|
2
2
|
import type { EnvInfo } from "../utils/detect.js";
|
|
3
|
+
/**
|
|
4
|
+
* Interactively configure API providers, detecting existing keys, allowing multi-select, and supporting custom endpoints.
|
|
5
|
+
* @param env - Current environment info with detected providers
|
|
6
|
+
* @returns Configured provider list
|
|
7
|
+
*/
|
|
3
8
|
export declare function setupProviders(env?: EnvInfo): Promise<ProviderConfig[]>;
|
|
@@ -12,7 +12,13 @@ const PROVIDER_API_URLS = {
|
|
|
12
12
|
xai: "https://api.x.ai",
|
|
13
13
|
mistral: "https://api.mistral.ai",
|
|
14
14
|
};
|
|
15
|
-
/**
|
|
15
|
+
/**
|
|
16
|
+
* 动态获取模型列表,依次尝试 Anthropic、Google、OpenAI 兼容 API 风格。
|
|
17
|
+
* @param provider - 提供商名称
|
|
18
|
+
* @param baseUrl - API 基础地址
|
|
19
|
+
* @param apiKey - API 密钥或环境变量名
|
|
20
|
+
* @returns 发现的模型列表及检测到的 API 类型
|
|
21
|
+
*/
|
|
16
22
|
async function fetchModels(provider, baseUrl, apiKey) {
|
|
17
23
|
const base = baseUrl.replace(/\/+$/, "");
|
|
18
24
|
const resolvedKey = process.env[apiKey] ?? apiKey;
|
|
@@ -91,6 +97,11 @@ async function fetchModels(provider, baseUrl, apiKey) {
|
|
|
91
97
|
catch { /* fall through */ }
|
|
92
98
|
return { models: [] };
|
|
93
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Interactively configure API providers, detecting existing keys, allowing multi-select, and supporting custom endpoints.
|
|
102
|
+
* @param env - Current environment info with detected providers
|
|
103
|
+
* @returns Configured provider list
|
|
104
|
+
*/
|
|
94
105
|
export async function setupProviders(env) {
|
|
95
106
|
const entries = Object.entries(PROVIDERS);
|
|
96
107
|
// Detect existing providers — offer skip or add new
|
|
@@ -175,6 +186,10 @@ export async function setupProviders(env) {
|
|
|
175
186
|
}
|
|
176
187
|
return configs;
|
|
177
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Interactively configure a custom provider (Ollama, vLLM, or other OpenAI-compatible endpoints).
|
|
191
|
+
* @returns Custom provider config, or null if cancelled
|
|
192
|
+
*/
|
|
178
193
|
async function setupCustomProvider() {
|
|
179
194
|
const name = await p.text({
|
|
180
195
|
message: t("provider.name"),
|
|
@@ -207,6 +222,15 @@ async function setupCustomProvider() {
|
|
|
207
222
|
p.log.success(t("provider.customConfigured", { name, url: baseUrl }));
|
|
208
223
|
return { name, apiKey, defaultModel, baseUrl, api, discoveredModels };
|
|
209
224
|
}
|
|
225
|
+
/**
|
|
226
|
+
* Select a default model by dynamically fetching available models, falling back to a static list or manual input.
|
|
227
|
+
* @param provider - Provider name
|
|
228
|
+
* @param label - Provider display label
|
|
229
|
+
* @param staticModels - Static model list fallback
|
|
230
|
+
* @param baseUrl - API base URL
|
|
231
|
+
* @param apiKey - API key
|
|
232
|
+
* @returns Selected model and discovered model metadata
|
|
233
|
+
*/
|
|
210
234
|
async function selectModelWithMeta(provider, label, staticModels, baseUrl, apiKey) {
|
|
211
235
|
let modelIds = staticModels;
|
|
212
236
|
let discoveredModels;
|
|
@@ -246,6 +270,11 @@ async function selectModelWithMeta(provider, label, staticModels, baseUrl, apiKe
|
|
|
246
270
|
}
|
|
247
271
|
return { defaultModel: model, discoveredModels, api };
|
|
248
272
|
}
|
|
273
|
+
/**
|
|
274
|
+
* Prompt the user to enter an API key.
|
|
275
|
+
* @param label - Provider display label
|
|
276
|
+
* @returns The entered API key
|
|
277
|
+
*/
|
|
249
278
|
async function promptKey(label) {
|
|
250
279
|
const key = await p.password({
|
|
251
280
|
message: t("provider.apiKey", { label }),
|
package/dist/tui/theme-select.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import { t } from "../i18n.js";
|
|
3
3
|
import { THEMES } from "../types.js";
|
|
4
|
+
/**
|
|
5
|
+
* Prompts the user to select a theme from the available themes list.
|
|
6
|
+
* Exits the process if the user cancels the selection.
|
|
7
|
+
* @returns The name of the selected theme.
|
|
8
|
+
*/
|
|
4
9
|
export async function selectTheme() {
|
|
5
10
|
const theme = await p.select({
|
|
6
11
|
message: t("theme.select"),
|
package/dist/tui/welcome.d.ts
CHANGED
package/dist/tui/welcome.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import * as p from "@clack/prompts";
|
|
2
2
|
import chalk from "chalk";
|
|
3
3
|
import { t } from "../i18n.js";
|
|
4
|
+
/**
|
|
5
|
+
* 展示欢迎界面,显示 pi 安装状态、环境信息及已有配置概况。
|
|
6
|
+
* @param {EnvInfo} env - 当前检测到的环境信息
|
|
7
|
+
*/
|
|
4
8
|
export function welcome(env) {
|
|
5
9
|
console.clear();
|
|
6
10
|
p.intro(chalk.cyan.bold(" oh-pi ") + chalk.dim(t("welcome.title")));
|
|
@@ -19,6 +23,11 @@ export function welcome(env) {
|
|
|
19
23
|
categorize(env.existingFiles), t("welcome.existingConfig"));
|
|
20
24
|
}
|
|
21
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* 按顶层目录分类统计文件数量,返回格式化字符串。
|
|
28
|
+
* @param {string[]} files - 文件相对路径列表
|
|
29
|
+
* @returns {string} 分类统计字符串,如 "extensions (3) prompts (5)"
|
|
30
|
+
*/
|
|
22
31
|
function categorize(files) {
|
|
23
32
|
const cats = {};
|
|
24
33
|
for (const f of files) {
|
package/dist/utils/resources.js
CHANGED
|
@@ -5,6 +5,7 @@ import { join, dirname } from "node:path";
|
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
const PKG_ROOT = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
|
|
7
7
|
const RESOURCES = join(PKG_ROOT, "pi-package");
|
|
8
|
+
/** 资源路径映射对象 */
|
|
8
9
|
export const resources = {
|
|
9
10
|
agent: (name) => join(RESOURCES, "agents", `${name}.md`),
|
|
10
11
|
extension: (name) => join(RESOURCES, "extensions", name),
|
package/package.json
CHANGED
|
@@ -67,7 +67,7 @@ export function adapt(config: ConcurrencyConfig, pendingTasks: number): Concurre
|
|
|
67
67
|
// 不超过待处理任务数
|
|
68
68
|
const taskCap = Math.min(pendingTasks, config.max);
|
|
69
69
|
|
|
70
|
-
if (samples.length <
|
|
70
|
+
if (samples.length < 2) {
|
|
71
71
|
// 冷启动:直接给一半 max,快速利用并发
|
|
72
72
|
next.current = Math.min(Math.ceil(config.max / 2), taskCap);
|
|
73
73
|
return next;
|
|
@@ -111,5 +111,10 @@ export function adapt(config: ConcurrencyConfig, pendingTasks: number): Concurre
|
|
|
111
111
|
}
|
|
112
112
|
// 否则保持不变
|
|
113
113
|
|
|
114
|
+
// 429 recovery: restore to optimal when CPU is underutilized (e.g. after backoff)
|
|
115
|
+
if (latest.cpuLoad < 0.5 && next.current < config.optimal) {
|
|
116
|
+
next.current = config.optimal;
|
|
117
|
+
}
|
|
118
|
+
|
|
114
119
|
return next;
|
|
115
120
|
}
|
|
@@ -558,6 +558,75 @@ export default function antColonyExtension(pi: ExtensionAPI) {
|
|
|
558
558
|
},
|
|
559
559
|
});
|
|
560
560
|
|
|
561
|
+
// ═══ Helper: build status summary ═══
|
|
562
|
+
|
|
563
|
+
function buildStatusText(): string {
|
|
564
|
+
if (!activeColony) return "No colony is currently running.";
|
|
565
|
+
const c = activeColony;
|
|
566
|
+
const state = c.state;
|
|
567
|
+
const elapsed = state ? formatDuration(Date.now() - state.createdAt) : "0s";
|
|
568
|
+
const m = state?.metrics;
|
|
569
|
+
const tasks = state?.tasks || [];
|
|
570
|
+
const ants = state?.ants || [];
|
|
571
|
+
const streams = Array.from(c.antStreams.values());
|
|
572
|
+
|
|
573
|
+
const lines: string[] = [
|
|
574
|
+
`## 🐜 Colony Status`,
|
|
575
|
+
`**Goal:** ${c.goal}`,
|
|
576
|
+
`**Phase:** ${c.phase}`,
|
|
577
|
+
`**Duration:** ${elapsed}`,
|
|
578
|
+
];
|
|
579
|
+
|
|
580
|
+
if (m) {
|
|
581
|
+
lines.push(`**Tasks:** ${m.tasksDone}/${m.tasksTotal} done, ${m.tasksFailed} failed`);
|
|
582
|
+
lines.push(`**Ants spawned:** ${m.antsSpawned} | **Active:** ${streams.length}`);
|
|
583
|
+
lines.push(`**Cost:** ${formatCost(m.totalCost)} | **Tokens:** ${formatTokens(m.totalTokens)}`);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
if (tasks.length > 0) {
|
|
587
|
+
lines.push("", "### Tasks");
|
|
588
|
+
for (const t of tasks) {
|
|
589
|
+
const icon = t.status === "done" ? "✓" : t.status === "failed" ? "✗" : t.status === "active" ? "●" : "○";
|
|
590
|
+
const dur = t.finishedAt && t.startedAt ? ` (${formatDuration(t.finishedAt - t.startedAt)})` : "";
|
|
591
|
+
lines.push(`- ${icon} [${t.caste}] ${t.title}${dur}`);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
if (streams.length > 0) {
|
|
596
|
+
lines.push("", "### Active Ants");
|
|
597
|
+
for (const s of streams) {
|
|
598
|
+
lines.push(`- ${casteIcon(s.caste)} ${s.antId.slice(0, 14)} | ${s.tokens}tok | ${s.lastLine.slice(0, 60)}`);
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
return lines.join("\n");
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// ═══ Tool: bg_colony_status ═══
|
|
606
|
+
pi.registerTool({
|
|
607
|
+
name: "bg_colony_status",
|
|
608
|
+
label: "Colony Status",
|
|
609
|
+
description: "Check the status of a running background ant colony. Use this instead of bg_status to monitor colony progress.",
|
|
610
|
+
parameters: Type.Object({}),
|
|
611
|
+
async execute() {
|
|
612
|
+
return {
|
|
613
|
+
content: [{ type: "text" as const, text: buildStatusText() }],
|
|
614
|
+
};
|
|
615
|
+
},
|
|
616
|
+
});
|
|
617
|
+
|
|
618
|
+
// ═══ Command: /colony-status ═══
|
|
619
|
+
pi.registerCommand("colony-status", {
|
|
620
|
+
description: "Show current colony progress",
|
|
621
|
+
async handler(_args, ctx) {
|
|
622
|
+
if (!activeColony) {
|
|
623
|
+
ctx.ui.notify("No colony is currently running.", "info");
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
ctx.ui.notify(buildStatusText(), "info");
|
|
627
|
+
},
|
|
628
|
+
});
|
|
629
|
+
|
|
561
630
|
// ═══ Command: /colony-stop ═══
|
|
562
631
|
pi.registerCommand("colony-stop", {
|
|
563
632
|
description: "Stop the running background colony",
|
|
@@ -226,8 +226,8 @@ export class Nest {
|
|
|
226
226
|
// ═══ Internal ═══
|
|
227
227
|
|
|
228
228
|
private withStateLock<T>(fn: () => T): T {
|
|
229
|
-
const MAX_WAIT =
|
|
230
|
-
const SPIN_MS =
|
|
229
|
+
const MAX_WAIT = 3000;
|
|
230
|
+
const SPIN_MS = 1;
|
|
231
231
|
const start = Date.now();
|
|
232
232
|
while (true) {
|
|
233
233
|
try {
|
|
@@ -378,7 +378,6 @@ export async function runColony(opts: QueenOptions): Promise<ColonyState> {
|
|
|
378
378
|
nest.updateState({ status: "failed", finishedAt: Date.now() });
|
|
379
379
|
const finalState = nest.getState();
|
|
380
380
|
callbacks.onComplete(finalState);
|
|
381
|
-
cleanup();
|
|
382
381
|
return finalState;
|
|
383
382
|
}
|
|
384
383
|
|
|
@@ -424,14 +423,14 @@ export async function runColony(opts: QueenOptions): Promise<ColonyState> {
|
|
|
424
423
|
nest.updateState({ status: "done", finishedAt: Date.now(), metrics: finalMetrics });
|
|
425
424
|
const finalState = nest.getState();
|
|
426
425
|
callbacks.onComplete(finalState);
|
|
427
|
-
cleanup();
|
|
428
426
|
return finalState;
|
|
429
427
|
|
|
430
428
|
} catch (e) {
|
|
431
429
|
nest.updateState({ status: "failed", finishedAt: Date.now() });
|
|
432
430
|
const failState = nest.getState();
|
|
433
431
|
callbacks.onComplete(failState);
|
|
434
|
-
cleanup();
|
|
435
432
|
return failState;
|
|
433
|
+
} finally {
|
|
434
|
+
cleanup();
|
|
436
435
|
}
|
|
437
436
|
}
|
|
@@ -142,6 +142,9 @@ function buildPrompt(task: Task, pheromoneContext: string, castePrompt: string,
|
|
|
142
142
|
if (task.files.length > 0) {
|
|
143
143
|
prompt += `**Files scope:** ${task.files.join(", ")}\n`;
|
|
144
144
|
}
|
|
145
|
+
if (/[\u4e00-\u9fff]/.test(task.description)) {
|
|
146
|
+
prompt += '\nIMPORTANT: Follow the language requirements specified in the task description. If the task says to write in Chinese, write in Chinese.\n';
|
|
147
|
+
}
|
|
145
148
|
return prompt;
|
|
146
149
|
}
|
|
147
150
|
|