flavor-code 1.3.0 → 1.3.3
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/README.md +5 -3
- package/README.zh-CN.md +5 -3
- package/dist/{app-FOPTLLK5.js → app-NXOGWGSI.js} +1 -1
- package/dist/{chunk-IX65GYUF.js → chunk-JKJOQRAL.js} +1 -1
- package/dist/{chunk-KL4UHJ2Q.js → chunk-YY5H6GFN.js} +88 -33
- package/dist/cli.js +21 -5
- package/dist/desktop/main.js +1363 -178
- package/dist/desktop/pals-broker-entry.js +1308 -0
- package/dist/desktop/preload.cjs +91 -2
- package/dist/desktop-renderer/assets/index-CdeAi527.css +1 -0
- package/dist/desktop-renderer/assets/index-CnGHSdJ6.js +154 -0
- package/dist/desktop-renderer/assets/interactive-terminal-BpNgJ_fv.js +35 -0
- package/dist/desktop-renderer/index.html +3 -3
- package/dist/init/project.d.ts +2 -2
- package/dist/pals/broker-cli.d.ts +8 -0
- package/dist/production.d.ts +8 -3
- package/dist/sdk/index.js +2 -2
- package/dist/ui/session.d.ts +2 -0
- package/package.json +11 -8
- package//346/212/200/346/234/257/346/226/271/346/241/210/346/212/245/345/221/212.md +2 -2
- package/dist/codeisland/activate.mjs +0 -74
- package/dist/codeisland/bridge.mjs +0 -97
- package/dist/codeisland/flavor-plugin.json +0 -27
- package/dist/desktop-renderer/assets/index-BmXr_vX3.js +0 -151
- package/dist/desktop-renderer/assets/index-DEL8gXBO.css +0 -1
package/README.md
CHANGED
|
@@ -204,7 +204,9 @@ npm run desktop:pack # Windows portable directory
|
|
|
204
204
|
npm run desktop:dist # Windows NSIS installer
|
|
205
205
|
```
|
|
206
206
|
|
|
207
|
-
The desktop app
|
|
207
|
+
The desktop app keeps multiple projects open and can run up to four independent tasks concurrently inside one project; switching projects or tasks does not stop background work. Completion, failure, attention, and interruption events enter a persistent activity inbox and trigger native notifications, while unread completions retain a blue dot. Projects can be pinned, renamed, closed, revealed, or copied; tasks can be searched, renamed, pinned, and archived.
|
|
208
|
+
|
|
209
|
+
Use `Ctrl+P` to switch projects, `Ctrl+K` for the command palette, and `Ctrl+N` for a new task; the title bar also supports back/forward navigation. Interrupted work gets a recovery banner after an abnormal exit. The **Git Changes** view provides per-file diffs, stage/unstage/discard, commits, and `/review` handoff. Streaming Markdown, permission confirmations, and Skills, MCP, memory, and model management remain available.
|
|
208
210
|
|
|
209
211
|
The **E2E** module in the sidebar drives a rough requirement or an existing design export through the full delivery pipeline: it generates a PRD and an interactive prototype for review, then moves into D2C visual implementation (Vue 3 / React) under `src/d2c-output/<task>/`. A Vite dev server starts automatically for pixel-level comparison, producing a visual-fidelity score and a structured diff report (region offsets, color deviations, font differences); the results workbench offers overlay, curtain, flicker, and heatmap modes, an SVG annotation layer, and a severity-sorted issue list. After visual review, a Swagger/OpenAPI contract is generated or imported to auto-create Axios wrappers and an Express mock server, followed by autonomous interactive acceptance and scored delivery.
|
|
210
212
|
|
|
@@ -250,10 +252,10 @@ flavor mcp disable docs
|
|
|
250
252
|
|
|
251
253
|
A Skill is a `SKILL.md` with YAML frontmatter, placed in `.flavor/skills/<name>/` or `~/.flavor-code/skills/<name>/`. Flavor loads skills progressively based on the task, and you can invoke one explicitly with `/<skill-name>`. Skill bodies support `$ARGUMENTS`, `$ARGUMENTS[N]`, and `$N` substitutions. A running composite Skill can load a dependency through the read-only `Skill` tool; plugin-qualified names such as `superharness:test-driven-development` resolve to discovered skills.
|
|
252
254
|
|
|
253
|
-
Plugins live in `.flavor/plugins/` and can register commands, tools, hooks, Skill roots, and model adapters. `additionalContext` returned by `SessionStart` and `UserPromptSubmit` hooks is added to the current task context, enabling reliable project-level engineering policy injection.
|
|
255
|
+
Plugins live in `.flavor/plugins/` and can register commands, tools, hooks, Skill roots, and model adapters. `additionalContext` returned by `SessionStart` and `UserPromptSubmit` hooks is added to the current task context, enabling reliable project-level engineering policy injection. Plugin loads record a content fingerprint plus declared capabilities. Worker/vm isolation is available through the embedding API's `pluginSandbox: true` option; the compatibility default remains in-process because bundled and existing plugins use Node.js APIs that the isolated runtime does not yet mediate.
|
|
254
256
|
|
|
255
257
|
> [!WARNING]
|
|
256
|
-
> Sandboxing reduces ambient access but does not make untrusted instructions safe
|
|
258
|
+
> The default in-process plugin runtime grants full Node.js access. Only install and enable plugins you trust. Sandboxing reduces ambient access but does not make untrusted instructions safe, and plugins that import Node.js built-ins will not load with `pluginSandbox: true` yet.
|
|
257
259
|
|
|
258
260
|
## Sessions, Memory & Execution Records
|
|
259
261
|
|
package/README.zh-CN.md
CHANGED
|
@@ -204,7 +204,9 @@ npm run desktop:pack # Windows 免安装目录
|
|
|
204
204
|
npm run desktop:dist # Windows NSIS 安装包
|
|
205
205
|
```
|
|
206
206
|
|
|
207
|
-
|
|
207
|
+
桌面端可以同时保持多个项目打开,同一项目也可并行运行最多 4 个独立任务;切换项目或任务不会中止后台执行。运行中的任务显示动态活动标记;完成、失败、等待确认和异常中断会进入持久活动中心并触发系统通知,未读完成项保留蓝点。项目支持置顶、别名、关闭、定位和复制路径,任务支持搜索、重命名、置顶和归档。
|
|
208
|
+
|
|
209
|
+
使用 `Ctrl+P` 快速切换项目、`Ctrl+K` 打开命令面板、`Ctrl+N` 新建任务,标题栏支持前进/后退。异常退出后会出现恢复条。**Git 变更**视图提供逐文件 Diff、暂存、取消暂存、还原、提交及 `/review` 联动。桌面端还提供流式 Markdown、权限确认、Skill、MCP、记忆和模型管理。
|
|
208
210
|
|
|
209
211
|
侧栏的 **E2E** 模块覆盖从粗需求到可验收成果物的完整交付链路:从粗需求生成 PRD 与可交互原型(支持审阅与退回),确认后进入 D2C 视觉还原(Vue 3 / React),自动启动 Vite dev server 进行像素级对比,输出视觉还原度评分与结构化差异报告,并提供叠加、帘幕、闪烁与热力图等对比模式、SVG 标注层和按严重度排序的问题列表;视觉审阅通过后,自动生成或导入 Swagger/OpenAPI 契约以创建 Axios 封装与 Express mock 服务,随后进行自主交互验收,最终完成评分与成果物交付。
|
|
210
212
|
|
|
@@ -250,10 +252,10 @@ flavor mcp disable docs
|
|
|
250
252
|
|
|
251
253
|
Skill 是带有 YAML 头信息的 `SKILL.md`,放在 `.flavor/skills/<name>/` 或 `~/.flavor-code/skills/<name>/`。Flavor 会按任务渐进加载,也支持通过 `/<skill-name>` 显式调用。Skill 正文支持 `$ARGUMENTS`、`$ARGUMENTS[N]` 和 `$N` 参数占位符;运行中的组合 Skill 可以使用只读 `Skill` 工具继续加载依赖 Skill,插件限定名称(如 `superharness:test-driven-development`)会安全解析到已发现的 Skill。
|
|
252
254
|
|
|
253
|
-
插件放在 `.flavor/plugins/`,可以注册命令、工具、Hook、Skill 根目录和模型适配器。`SessionStart` 与 `UserPromptSubmit` Hook 返回的 `additionalContext`
|
|
255
|
+
插件放在 `.flavor/plugins/`,可以注册命令、工具、Hook、Skill 根目录和模型适配器。`SessionStart` 与 `UserPromptSubmit` Hook 返回的 `additionalContext` 会进入当前任务上下文,可用于注入项目级工程规则。插件加载会记录内容指纹与声明的能力。可通过嵌入 API 的 `pluginSandbox: true` 启用 Worker/vm 隔离;由于内置插件和已有插件依赖沙箱尚未代理的 Node.js API,当前兼容默认值仍为进程内运行。
|
|
254
256
|
|
|
255
257
|
> [!WARNING]
|
|
256
|
-
>
|
|
258
|
+
> 默认的进程内插件运行时拥有完整 Node.js 权限,只安装和启用你信任的插件。沙箱会降低环境权限,但不能让不可信指令自动变安全;目前导入 Node.js 内置模块的插件在 `pluginSandbox: true` 下仍无法加载。
|
|
257
259
|
|
|
258
260
|
## 会话、记忆与执行记录
|
|
259
261
|
|
|
@@ -561,7 +561,7 @@ function redactSecrets(input, secrets) {
|
|
|
561
561
|
|
|
562
562
|
// src/init/project.ts
|
|
563
563
|
import { lstat, mkdir, readdir, readFile, realpath, writeFile } from "fs/promises";
|
|
564
|
-
import { copyFileSync, mkdirSync, readdirSync
|
|
564
|
+
import { copyFileSync, mkdirSync, readdirSync } from "fs";
|
|
565
565
|
import { basename, dirname as dirname2, isAbsolute as isAbsolute2, join, relative as relative2, sep as sep2 } from "path";
|
|
566
566
|
import { fileURLToPath } from "url";
|
|
567
567
|
var GENERATED_START = "<!-- flavor-code:start -->";
|
|
@@ -1014,22 +1014,6 @@ async function createExampleFlavorConfig(cwd) {
|
|
|
1014
1014
|
};
|
|
1015
1015
|
await writeFile(configPath, JSON.stringify(example, null, 2) + "\n");
|
|
1016
1016
|
}
|
|
1017
|
-
var CODEISLAND_SRC_DIR = join(dirname2(fileURLToPath(import.meta.url)), "codeisland");
|
|
1018
|
-
var CODEISLAND_FILES = ["flavor-plugin.json", "activate.mjs", "bridge.mjs"];
|
|
1019
|
-
async function copyCodeIslandPlugin(cwd) {
|
|
1020
|
-
const pluginDir = join(cwd, ".flavor", "plugins", "codeisland");
|
|
1021
|
-
try {
|
|
1022
|
-
await lstat(pluginDir);
|
|
1023
|
-
return;
|
|
1024
|
-
} catch (error) {
|
|
1025
|
-
if (!isMissingPathError(error)) throw error;
|
|
1026
|
-
}
|
|
1027
|
-
await mkdir(pluginDir, { recursive: true, mode: 448 });
|
|
1028
|
-
for (const name of CODEISLAND_FILES) {
|
|
1029
|
-
const content = readFileSync(join(CODEISLAND_SRC_DIR, name), "utf8");
|
|
1030
|
-
await writeFile(join(pluginDir, name), content);
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
1017
|
var ASTGRAPH_SRC_DIR = join(dirname2(fileURLToPath(import.meta.url)), "astgraph");
|
|
1034
1018
|
async function copyAstgraphPlugin(cwd) {
|
|
1035
1019
|
const pluginDir = join(cwd, ".flavor", "plugins", "astgraph");
|
|
@@ -1052,7 +1036,6 @@ function copyDirectory(from, to) {
|
|
|
1052
1036
|
}
|
|
1053
1037
|
async function initializeFlavor(cwd) {
|
|
1054
1038
|
await ensureFlavorDirectories(cwd);
|
|
1055
|
-
await copyCodeIslandPlugin(cwd);
|
|
1056
1039
|
await copyAstgraphPlugin(cwd);
|
|
1057
1040
|
await createExampleFlavorConfig(cwd);
|
|
1058
1041
|
const facts = await inspectProject(cwd);
|
|
@@ -1074,7 +1057,7 @@ async function initializeFlavor(cwd) {
|
|
|
1074
1057
|
}
|
|
1075
1058
|
|
|
1076
1059
|
// src/utils/version.ts
|
|
1077
|
-
import { readFileSync
|
|
1060
|
+
import { readFileSync } from "fs";
|
|
1078
1061
|
import { dirname as dirname3, join as join2 } from "path";
|
|
1079
1062
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
1080
1063
|
var cached;
|
|
@@ -1083,7 +1066,7 @@ function packageVersion() {
|
|
|
1083
1066
|
let directory = dirname3(fileURLToPath2(import.meta.url));
|
|
1084
1067
|
for (; ; ) {
|
|
1085
1068
|
try {
|
|
1086
|
-
const manifest = JSON.parse(
|
|
1069
|
+
const manifest = JSON.parse(readFileSync(join2(directory, "package.json"), "utf8"));
|
|
1087
1070
|
if (typeof manifest.version === "string" && manifest.version.length > 0) {
|
|
1088
1071
|
cached = manifest.version;
|
|
1089
1072
|
return cached;
|
|
@@ -4952,18 +4935,25 @@ function startupLockPath(address) {
|
|
|
4952
4935
|
async function spawnProductionBroker(address) {
|
|
4953
4936
|
const entry2 = process.argv[1];
|
|
4954
4937
|
if (entry2 === void 0) throw new Error("Cannot auto-start pals broker without a CLI entry point");
|
|
4938
|
+
return spawnPalBrokerProcess({ address, executable: process.execPath, args: [entry2, "--pals-broker", address] });
|
|
4939
|
+
}
|
|
4940
|
+
async function spawnPalBrokerProcess(options) {
|
|
4941
|
+
if (options.executable.trim() === "" || options.args.length === 0) throw new Error("Pals broker process requires an executable and entry arguments");
|
|
4942
|
+
const address = options.address;
|
|
4955
4943
|
const lockPath = startupLockPath(address);
|
|
4956
4944
|
const lock = await acquirePalFileLock({ path: lockPath, endpointLive: () => canConnect2(address) });
|
|
4957
4945
|
if (lock === void 0) return;
|
|
4958
4946
|
try {
|
|
4959
|
-
const child = spawn3(
|
|
4947
|
+
const child = spawn3(options.executable, [...options.args], {
|
|
4960
4948
|
detached: true,
|
|
4961
4949
|
stdio: "ignore",
|
|
4962
|
-
windowsHide: true
|
|
4950
|
+
windowsHide: true,
|
|
4951
|
+
...options.environment === void 0 ? {} : { env: options.environment }
|
|
4963
4952
|
});
|
|
4964
4953
|
child.unref();
|
|
4965
4954
|
const deadline = Date.now() + 5e3;
|
|
4966
4955
|
while (Date.now() < deadline && !await canConnect2(address)) await delay(25);
|
|
4956
|
+
if (!await canConnect2(address)) throw new Error(`Pals broker process did not become ready at '${address}'`);
|
|
4967
4957
|
} finally {
|
|
4968
4958
|
await lock.release();
|
|
4969
4959
|
}
|
|
@@ -7995,7 +7985,7 @@ function toModelTool(tool) {
|
|
|
7995
7985
|
|
|
7996
7986
|
// src/harness/journal.ts
|
|
7997
7987
|
import { createHash as createHash6, randomUUID as randomUUID8 } from "crypto";
|
|
7998
|
-
import { closeSync, constants, existsSync as existsSync2, fsyncSync, mkdirSync as mkdirSync2, openSync, readFileSync as
|
|
7988
|
+
import { closeSync, constants, existsSync as existsSync2, fsyncSync, mkdirSync as mkdirSync2, openSync, readFileSync as readFileSync2, realpathSync as realpathSync2, statSync, truncateSync, writeSync } from "fs";
|
|
7999
7989
|
import { join as join8, relative as relative7, resolve as resolve8, sep as sep7 } from "path";
|
|
8000
7990
|
import { z as z10 } from "zod";
|
|
8001
7991
|
|
|
@@ -8213,7 +8203,7 @@ var HarnessJournal = class {
|
|
|
8213
8203
|
const metadata = statSync(this.#path);
|
|
8214
8204
|
if (!metadata.isFile()) throw new Error("Harness journal path is not a regular file");
|
|
8215
8205
|
if (metadata.size > this.#maxBytes) throw new Error(`Harness journal exceeds ${this.#maxBytes} bytes`);
|
|
8216
|
-
const raw =
|
|
8206
|
+
const raw = readFileSync2(this.#path, "utf8");
|
|
8217
8207
|
const committed = raw.endsWith("\n") ? raw : raw.slice(0, Math.max(0, raw.lastIndexOf("\n") + 1));
|
|
8218
8208
|
if (committed.length !== raw.length) truncateSync(this.#path, Buffer.byteLength(committed));
|
|
8219
8209
|
const lines = committed.split("\n").filter(Boolean);
|
|
@@ -20213,6 +20203,51 @@ var INTERRUPTED_TASK_PLAN_CONTEXT = [
|
|
|
20213
20203
|
"Reassess the current query independently.",
|
|
20214
20204
|
"If the current work needs a plan, create a fresh one with TaskPlan before using TaskUpdate."
|
|
20215
20205
|
].join(" ");
|
|
20206
|
+
function recoverablePalClient(client, onRecovered) {
|
|
20207
|
+
let presence;
|
|
20208
|
+
let starting;
|
|
20209
|
+
const ensure = () => {
|
|
20210
|
+
if (presence !== void 0) return Promise.resolve(presence);
|
|
20211
|
+
if (starting !== void 0) return starting;
|
|
20212
|
+
starting = client.start().then((value) => {
|
|
20213
|
+
presence = value;
|
|
20214
|
+
onRecovered();
|
|
20215
|
+
return value;
|
|
20216
|
+
}).finally(() => {
|
|
20217
|
+
starting = void 0;
|
|
20218
|
+
});
|
|
20219
|
+
return starting;
|
|
20220
|
+
};
|
|
20221
|
+
const invoke = async (run) => {
|
|
20222
|
+
await ensure();
|
|
20223
|
+
try {
|
|
20224
|
+
return await run();
|
|
20225
|
+
} catch (error) {
|
|
20226
|
+
const detail = message(error);
|
|
20227
|
+
if (!/not connected|connection closed|ECONNRESET|ECONNREFUSED|EPIPE/i.test(detail)) throw error;
|
|
20228
|
+
presence = void 0;
|
|
20229
|
+
await ensure();
|
|
20230
|
+
return run();
|
|
20231
|
+
}
|
|
20232
|
+
};
|
|
20233
|
+
return {
|
|
20234
|
+
start: ensure,
|
|
20235
|
+
list: () => invoke(() => client.list()),
|
|
20236
|
+
rename: (alias) => invoke(() => client.rename(alias)),
|
|
20237
|
+
sendTask: (target, value) => invoke(() => client.sendTask(target, value)),
|
|
20238
|
+
sendChat: (target, value) => invoke(() => client.sendChat(target, value)),
|
|
20239
|
+
startCoWork: (input) => invoke(() => client.startCoWork(input)),
|
|
20240
|
+
coWorkAction: (action) => invoke(() => client.coWorkAction(action)),
|
|
20241
|
+
coWorkStatus: (coWorkId) => invoke(() => client.coWorkStatus(coWorkId)),
|
|
20242
|
+
integrateCoWork: (input) => invoke(() => client.integrateCoWork(input)),
|
|
20243
|
+
cancelCoWork: (coWorkId, reason) => invoke(() => client.cancelCoWork(coWorkId, reason)),
|
|
20244
|
+
subscribe: (listener) => client.subscribe(listener),
|
|
20245
|
+
close: async () => {
|
|
20246
|
+
presence = void 0;
|
|
20247
|
+
await client.close();
|
|
20248
|
+
}
|
|
20249
|
+
};
|
|
20250
|
+
}
|
|
20216
20251
|
var DEFAULT_SHUTDOWN_STEP_TIMEOUT_MS = 3e3;
|
|
20217
20252
|
function createPromptEnvironment(input = {}) {
|
|
20218
20253
|
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
@@ -20472,7 +20507,10 @@ async function createProductionRuntime(options) {
|
|
|
20472
20507
|
globalPluginDirs: [join24(home, ".flavor-code", "plugins")],
|
|
20473
20508
|
projectPluginDirs: [join24(workspace, ".flavor", "plugins")],
|
|
20474
20509
|
config,
|
|
20475
|
-
|
|
20510
|
+
// Existing project plugins (including astgraph and superharness) use Node.js
|
|
20511
|
+
// built-ins. The Worker/vm sandbox deliberately blocks those imports, so it
|
|
20512
|
+
// must stay opt-in until equivalent mediated capabilities are available.
|
|
20513
|
+
sandbox: options.pluginSandbox ?? false,
|
|
20476
20514
|
registrations: {
|
|
20477
20515
|
command(name, handler, description) {
|
|
20478
20516
|
if (typeof handler !== "function") throw new Error(`Plugin command "${name}" must be a function.`);
|
|
@@ -20533,6 +20571,7 @@ async function createProductionRuntime(options) {
|
|
|
20533
20571
|
tools.push(evolveService.toolDefinition());
|
|
20534
20572
|
let sleepScheduler;
|
|
20535
20573
|
let collaborationClient;
|
|
20574
|
+
let collaborationUnavailableDiagnostic;
|
|
20536
20575
|
let unsubscribeCollaboration;
|
|
20537
20576
|
let collaborationSession;
|
|
20538
20577
|
let deliverCollaborationEvent;
|
|
@@ -20575,7 +20614,7 @@ async function createProductionRuntime(options) {
|
|
|
20575
20614
|
userScope: home,
|
|
20576
20615
|
runtimeDir: join24(tmpdir3(), `flavor-code-pals-${createHash17("sha256").update(home).digest("hex").slice(0, 16)}`)
|
|
20577
20616
|
});
|
|
20578
|
-
|
|
20617
|
+
const baseCollaborationClient = collaboration.client ?? collaboration.createClient?.({
|
|
20579
20618
|
instanceId: collaboration.instanceId,
|
|
20580
20619
|
alias,
|
|
20581
20620
|
projectPath: workspace
|
|
@@ -20583,8 +20622,13 @@ async function createProductionRuntime(options) {
|
|
|
20583
20622
|
address,
|
|
20584
20623
|
authHome: home,
|
|
20585
20624
|
registration: { id: collaboration.instanceId, alias, projectPath: workspace },
|
|
20586
|
-
startBroker: () => ensurePalBrokerRunning({ address })
|
|
20625
|
+
startBroker: () => ensurePalBrokerRunning({ address, ...collaboration.startBroker === void 0 ? {} : { startBroker: () => collaboration.startBroker(address) } })
|
|
20587
20626
|
});
|
|
20627
|
+
collaborationClient = collaboration.optional ? recoverablePalClient(baseCollaborationClient, () => {
|
|
20628
|
+
if (collaborationUnavailableDiagnostic === void 0) return;
|
|
20629
|
+
remove(diagnostics, collaborationUnavailableDiagnostic);
|
|
20630
|
+
collaborationUnavailableDiagnostic = void 0;
|
|
20631
|
+
}) : baseCollaborationClient;
|
|
20588
20632
|
deliverCollaborationEvent = async (event) => {
|
|
20589
20633
|
const session2 = collaborationSession;
|
|
20590
20634
|
const client = collaborationClient;
|
|
@@ -20639,11 +20683,19 @@ async function createProductionRuntime(options) {
|
|
|
20639
20683
|
}
|
|
20640
20684
|
};
|
|
20641
20685
|
unsubscribeCollaboration = collaborationClient.subscribe(enqueueCollaborationEvent);
|
|
20642
|
-
|
|
20643
|
-
|
|
20644
|
-
|
|
20645
|
-
|
|
20646
|
-
|
|
20686
|
+
try {
|
|
20687
|
+
await collaborationClient.start();
|
|
20688
|
+
} catch (error) {
|
|
20689
|
+
if (!collaboration.optional) throw error;
|
|
20690
|
+
collaborationUnavailableDiagnostic = `Pals unavailable: ${message(error)}`;
|
|
20691
|
+
diagnostics.push(collaborationUnavailableDiagnostic);
|
|
20692
|
+
}
|
|
20693
|
+
if (collaborationClient !== void 0) {
|
|
20694
|
+
tools.push(...createPalsTools(collaborationClient, {
|
|
20695
|
+
selfId: collaboration.instanceId,
|
|
20696
|
+
shareGuard: new CollaborationShareGuard({ redact: (value) => redactSecrets(value, secrets) })
|
|
20697
|
+
}));
|
|
20698
|
+
}
|
|
20647
20699
|
}
|
|
20648
20700
|
const syncMcpTools = () => {
|
|
20649
20701
|
for (const tool of mcpTools) remove(tools, tool);
|
|
@@ -21400,6 +21452,7 @@ async function createProductionRuntime(options) {
|
|
|
21400
21452
|
}),
|
|
21401
21453
|
rename: (alias) => collaborationClient.rename(alias),
|
|
21402
21454
|
info: (target) => resolveCollaborationTarget(target),
|
|
21455
|
+
sendChat: (target, message2) => collaborationClient.sendChat(target, message2),
|
|
21403
21456
|
sendTask: (target, goal) => collaborationClient.sendTask(target, goal),
|
|
21404
21457
|
startCoWork: async (target, goal) => {
|
|
21405
21458
|
const recipient = await resolveCollaborationTarget(target);
|
|
@@ -21660,6 +21713,7 @@ ${summary2}`;
|
|
|
21660
21713
|
return sessionHistory.checkpoint(tagged, harness.main.context.snapshot());
|
|
21661
21714
|
},
|
|
21662
21715
|
tree: () => sessionHistory.tree(),
|
|
21716
|
+
historyLeaf: () => sessionHistory.leafId,
|
|
21663
21717
|
rewind: async (nodeId) => {
|
|
21664
21718
|
await sessionHistory.rewind(nodeId, harness.main.context.snapshot());
|
|
21665
21719
|
await persist();
|
|
@@ -21848,7 +21902,7 @@ ${renderMemoryDocument(entries)}`;
|
|
|
21848
21902
|
approvals,
|
|
21849
21903
|
memoryReviews,
|
|
21850
21904
|
restoredTranscript,
|
|
21851
|
-
jobs: { list: () => jobs.list(), subscribe: (listener) => jobs.subscribe(listener) },
|
|
21905
|
+
jobs: { list: () => jobs.list(), read: (id, owner2, cursor) => jobs.read(id, owner2, cursor), subscribe: (listener) => jobs.subscribe(listener) },
|
|
21852
21906
|
get sessionId() {
|
|
21853
21907
|
return sessionId;
|
|
21854
21908
|
},
|
|
@@ -22691,6 +22745,7 @@ export {
|
|
|
22691
22745
|
COMMAND_DESCRIPTIONS,
|
|
22692
22746
|
AgentMessageQueue,
|
|
22693
22747
|
FlavorSession,
|
|
22748
|
+
classifyMemoryHeat,
|
|
22694
22749
|
MemoryStore,
|
|
22695
22750
|
buildDockerInvocation,
|
|
22696
22751
|
DockerExecutionEnvironment,
|
package/dist/cli.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createRequire } from "node:module"; const require = createRequire(impor
|
|
|
3
3
|
import {
|
|
4
4
|
FlavorRpcServer,
|
|
5
5
|
TraceRecorder
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-JKJOQRAL.js";
|
|
7
7
|
import {
|
|
8
8
|
staticTaskLines
|
|
9
9
|
} from "./chunk-KKIBYDJI.js";
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
MemoryStore,
|
|
15
15
|
PluginManifestSchema,
|
|
16
16
|
SkillRegistry,
|
|
17
|
+
classifyMemoryHeat,
|
|
17
18
|
createExecutionEnvironment,
|
|
18
19
|
createProductionRuntime,
|
|
19
20
|
executeShell,
|
|
@@ -22,7 +23,7 @@ import {
|
|
|
22
23
|
packageVersion,
|
|
23
24
|
redactErrorText,
|
|
24
25
|
runPalBroker
|
|
25
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-YY5H6GFN.js";
|
|
26
27
|
import {
|
|
27
28
|
McpServerConfigSchema,
|
|
28
29
|
McpServerNameSchema,
|
|
@@ -283,11 +284,22 @@ var ProjectMemoryManager = class {
|
|
|
283
284
|
this.#store = store;
|
|
284
285
|
this.#enabled = enabled;
|
|
285
286
|
}
|
|
286
|
-
async snapshot() {
|
|
287
|
+
async snapshot(now = /* @__PURE__ */ new Date()) {
|
|
288
|
+
const references = this.#enabled ? await this.#store.references() : [];
|
|
287
289
|
return {
|
|
288
290
|
enabled: this.#enabled,
|
|
289
291
|
path: this.#store.path,
|
|
290
|
-
entries:
|
|
292
|
+
entries: references.map((reference) => {
|
|
293
|
+
const lastRecalledAt = Object.values(reference.recalls).sort().at(-1);
|
|
294
|
+
return {
|
|
295
|
+
id: reference.id,
|
|
296
|
+
type: reference.type,
|
|
297
|
+
content: reference.summary,
|
|
298
|
+
recallTotal: reference.recallTotal,
|
|
299
|
+
heat: classifyMemoryHeat(reference, now),
|
|
300
|
+
...lastRecalledAt === void 0 ? {} : { lastRecalledAt }
|
|
301
|
+
};
|
|
302
|
+
})
|
|
291
303
|
};
|
|
292
304
|
}
|
|
293
305
|
async remember(candidate) {
|
|
@@ -304,6 +316,10 @@ var ProjectMemoryManager = class {
|
|
|
304
316
|
this.#assertEnabled();
|
|
305
317
|
return this.#store.delete(id);
|
|
306
318
|
}
|
|
319
|
+
async deleteCold(now = /* @__PURE__ */ new Date()) {
|
|
320
|
+
this.#assertEnabled();
|
|
321
|
+
return this.#store.forgetCold(now);
|
|
322
|
+
}
|
|
307
323
|
#assertEnabled() {
|
|
308
324
|
if (!this.#enabled) throw new Error("Long-term memory is disabled for this project");
|
|
309
325
|
}
|
|
@@ -861,7 +877,7 @@ async function runInteractiveCli(props) {
|
|
|
861
877
|
const [{ render, AlternateScreen }, { createElement }, { App }] = await Promise.all([
|
|
862
878
|
import("./claude-ink-ORUA7GWG.js"),
|
|
863
879
|
import("react"),
|
|
864
|
-
import("./app-
|
|
880
|
+
import("./app-NXOGWGSI.js")
|
|
865
881
|
]);
|
|
866
882
|
const instance = await render(createElement(
|
|
867
883
|
AlternateScreen,
|