@jun133/kitty 0.0.15 → 0.0.16
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 +8 -6
- package/dist/{App-CBTIS4IK.mjs → App-K7CBA2FU.mjs} +1 -1
- package/dist/{chunk-7FDXKNTM.mjs → chunk-7FOTCUIH.mjs} +207 -197
- package/dist/{chunk-S4QTRPZ7.mjs → chunk-C3MFBHV3.mjs} +221 -221
- package/dist/{chunk-KUP5OMPB.mjs → chunk-FKBVCYPW.mjs} +1 -1
- package/dist/{chunk-NBKU7KA4.mjs → chunk-L27HOXD2.mjs} +192 -196
- package/dist/{chunk-WIKLME2V.mjs → chunk-LCTAPA2B.mjs} +67 -46
- package/dist/{chunk-AQEMM5VH.mjs → chunk-XY3SQDFZ.mjs} +1 -1
- package/dist/cli.js +6486 -6070
- package/dist/cli.js.map +1 -1
- package/dist/{interactive-BQMJFYHZ.mjs → interactive-ZNDB2JQO.mjs} +5 -5
- package/dist/{oneShot-4QBXBCNN.mjs → oneShot-4SH2HITB.mjs} +3 -3
- package/dist/{session-V7AYOK2Q.mjs → session-WJWPSYBD.mjs} +2 -2
- package/dist/tui.mjs +6 -6
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
官网:https://agentjz.github.io/kitty/
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<strong>🐾
|
|
8
|
+
<strong>🐾 一个 agent 编程工作台:搜得到,看得懂,改得准,跑得通,记得住,能继续。</strong>
|
|
9
9
|
</p>
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
- 可恢复的 session 现场
|
|
30
30
|
- CLI、TUI、Telegram 三种入口
|
|
31
31
|
- 当前现场、后台任务、会话事件、memory 和 eval
|
|
32
|
-
- 省 token
|
|
32
|
+
- 省 token 的上下文、缓存事实和工具输出治理
|
|
33
33
|
|
|
34
34
|
## ⚡ 快速开始
|
|
35
35
|
|
|
@@ -101,14 +101,16 @@ kitty "检查这个仓库并修复失败测试"
|
|
|
101
101
|
| `kitty events [sessionId]` | 查看最近会话或指定会话的机器事件 |
|
|
102
102
|
| `kitty config show` | 查看从 `.kitty/.env` 解析出的当前运行配置 |
|
|
103
103
|
| `kitty config path` | 查看当前项目 `.kitty/.env` 路径 |
|
|
104
|
-
| `kitty status` |
|
|
104
|
+
| `kitty status` | 查看当前项目现场:先显示 Current scene,再显示 session、context budget、memory files、skills、project orientation、execution、wake 等 Runtime facts |
|
|
105
105
|
| `kitty memory` | 创建、查看、读取、搜索、删除 runtime memory assets,或把 memory 沉淀到 skill references |
|
|
106
106
|
| `kitty changes` | 查看记录的文件变更 |
|
|
107
107
|
| `kitty undo [changeId]` | 撤销最近一次或指定变更 |
|
|
108
108
|
| `kitty diff [path]` | 查看当前 git diff |
|
|
109
|
-
| `kitty doctor` | 检查 `.kitty` 文件、env contract、provider preset、runtime、provider 连接和下一步 |
|
|
110
|
-
| `kitty eval` | 查看产品验收场景;`kitty eval --run`
|
|
111
|
-
| `kitty telegram serve` | 启动 Telegram 私聊服务 |
|
|
109
|
+
| `kitty doctor` | 检查 `.kitty` 文件、env contract、provider preset、runtime、provider 连接和下一步 |
|
|
110
|
+
| `kitty eval` | 查看产品验收场景;`kitty eval --run-local` 运行本地机器验收;`kitty eval --run-production` 显式运行生产路径验收 |
|
|
111
|
+
| `kitty telegram serve` | 启动 Telegram 私聊服务 |
|
|
112
|
+
|
|
113
|
+
`npm.cmd test` 只跑日常确定性测试,不跑 eval。产品验收独立运行:`npm.cmd run test:eval` 验证 eval harness,`npm.cmd run eval:local` 跑本地验收,`npm.cmd run eval:production` 使用当前 `.kitty/.env` 显式跑生产路径验收。运行 eval 前先执行 `npm.cmd run build`。
|
|
112
114
|
|
|
113
115
|
查看配置:
|
|
114
116
|
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
sliceCurrentUserInputFrame,
|
|
34
34
|
takeLastUnique,
|
|
35
35
|
updateSessionMemory
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-C3MFBHV3.mjs";
|
|
37
37
|
|
|
38
38
|
// src/context/projectContext.ts
|
|
39
39
|
import fs6 from "fs/promises";
|
|
@@ -1535,133 +1535,7 @@ function toChatCompletionMessages(messages) {
|
|
|
1535
1535
|
});
|
|
1536
1536
|
}
|
|
1537
1537
|
|
|
1538
|
-
// src/provider/
|
|
1539
|
-
var responsesAdapter = {
|
|
1540
|
-
wireApi: "responses",
|
|
1541
|
-
async fetchStreaming(client, request) {
|
|
1542
|
-
const startedAt = Date.now();
|
|
1543
|
-
let usage;
|
|
1544
|
-
throwIfAborted(request.abortSignal, "Streaming request aborted");
|
|
1545
|
-
try {
|
|
1546
|
-
const stream = await client.responses.create(
|
|
1547
|
-
{
|
|
1548
|
-
...buildResponsesRequestBody(request),
|
|
1549
|
-
stream: true
|
|
1550
|
-
},
|
|
1551
|
-
{
|
|
1552
|
-
signal: request.abortSignal
|
|
1553
|
-
}
|
|
1554
|
-
);
|
|
1555
|
-
if (request.abortSignal?.aborted) {
|
|
1556
|
-
abortStream2(stream);
|
|
1557
|
-
throw createAbortError("Streaming aborted");
|
|
1558
|
-
}
|
|
1559
|
-
let content = "";
|
|
1560
|
-
let reasoningContent = "";
|
|
1561
|
-
const toolCalls = /* @__PURE__ */ new Map();
|
|
1562
|
-
for await (const event of stream) {
|
|
1563
|
-
if (request.abortSignal?.aborted) {
|
|
1564
|
-
abortStream2(stream);
|
|
1565
|
-
throw createAbortError("Streaming aborted");
|
|
1566
|
-
}
|
|
1567
|
-
usage = normalizeProviderUsage(event.response?.usage) ?? usage;
|
|
1568
|
-
if (event.type === "response.output_text.delta" && typeof event.delta === "string") {
|
|
1569
|
-
content += event.delta;
|
|
1570
|
-
request.callbacks?.onAssistantDelta?.(event.delta);
|
|
1571
|
-
continue;
|
|
1572
|
-
}
|
|
1573
|
-
if ((event.type === "response.reasoning_text.delta" || event.type === "response.reasoning_summary_text.delta") && typeof event.delta === "string") {
|
|
1574
|
-
reasoningContent += event.delta;
|
|
1575
|
-
request.callbacks?.onReasoningDelta?.(event.delta);
|
|
1576
|
-
continue;
|
|
1577
|
-
}
|
|
1578
|
-
if (event.type === "response.function_call_arguments.delta" && typeof event.delta === "string") {
|
|
1579
|
-
const index = typeof event.output_index === "number" ? event.output_index : 0;
|
|
1580
|
-
const existing = toolCalls.get(index) ?? {
|
|
1581
|
-
id: event.item_id ?? `tool-${index}`,
|
|
1582
|
-
name: "",
|
|
1583
|
-
arguments: ""
|
|
1584
|
-
};
|
|
1585
|
-
existing.arguments += event.delta;
|
|
1586
|
-
toolCalls.set(index, existing);
|
|
1587
|
-
continue;
|
|
1588
|
-
}
|
|
1589
|
-
if (event.type === "response.function_call_arguments.done") {
|
|
1590
|
-
const index = typeof event.output_index === "number" ? event.output_index : 0;
|
|
1591
|
-
const existing = toolCalls.get(index) ?? {
|
|
1592
|
-
id: event.item_id ?? `tool-${index}`,
|
|
1593
|
-
name: "",
|
|
1594
|
-
arguments: ""
|
|
1595
|
-
};
|
|
1596
|
-
if (typeof event.name === "string") {
|
|
1597
|
-
existing.name = event.name;
|
|
1598
|
-
}
|
|
1599
|
-
if (typeof event.arguments === "string" && event.arguments.length > 0) {
|
|
1600
|
-
existing.arguments = event.arguments;
|
|
1601
|
-
}
|
|
1602
|
-
toolCalls.set(index, existing);
|
|
1603
|
-
continue;
|
|
1604
|
-
}
|
|
1605
|
-
if (event.type === "response.output_item.done" && event.item?.type === "function_call") {
|
|
1606
|
-
const index = typeof event.output_index === "number" ? event.output_index : 0;
|
|
1607
|
-
toolCalls.set(index, {
|
|
1608
|
-
id: event.item.call_id ?? event.item.id ?? `tool-${index}`,
|
|
1609
|
-
name: event.item.name ?? "",
|
|
1610
|
-
arguments: event.item.arguments ?? ""
|
|
1611
|
-
});
|
|
1612
|
-
}
|
|
1613
|
-
}
|
|
1614
|
-
return {
|
|
1615
|
-
content: content.length > 0 ? content : null,
|
|
1616
|
-
reasoningContent: reasoningContent.length > 0 ? reasoningContent : void 0,
|
|
1617
|
-
streamedAssistantContent: content.length > 0,
|
|
1618
|
-
streamedReasoningContent: reasoningContent.length > 0,
|
|
1619
|
-
toolCalls: [...toolCalls.entries()].sort((left, right) => left[0] - right[0]).map(([, toolCall]) => ({
|
|
1620
|
-
id: toolCall.id,
|
|
1621
|
-
type: "function",
|
|
1622
|
-
function: {
|
|
1623
|
-
name: toolCall.name,
|
|
1624
|
-
arguments: toolCall.arguments
|
|
1625
|
-
}
|
|
1626
|
-
}))
|
|
1627
|
-
};
|
|
1628
|
-
} finally {
|
|
1629
|
-
request.onRequestMetric?.({
|
|
1630
|
-
durationMs: Date.now() - startedAt,
|
|
1631
|
-
usage
|
|
1632
|
-
});
|
|
1633
|
-
}
|
|
1634
|
-
},
|
|
1635
|
-
async fetchNonStreaming(client, request) {
|
|
1636
|
-
const startedAt = Date.now();
|
|
1637
|
-
let usage;
|
|
1638
|
-
throwIfAborted(request.abortSignal, "Request aborted");
|
|
1639
|
-
try {
|
|
1640
|
-
const response = await client.responses.create(
|
|
1641
|
-
{
|
|
1642
|
-
...buildResponsesRequestBody(request),
|
|
1643
|
-
stream: false
|
|
1644
|
-
},
|
|
1645
|
-
{
|
|
1646
|
-
signal: request.abortSignal
|
|
1647
|
-
}
|
|
1648
|
-
);
|
|
1649
|
-
usage = normalizeProviderUsage(response.usage);
|
|
1650
|
-
return {
|
|
1651
|
-
content: normalizeOutputText(response),
|
|
1652
|
-
reasoningContent: readResponseReasoning(response),
|
|
1653
|
-
streamedAssistantContent: false,
|
|
1654
|
-
streamedReasoningContent: false,
|
|
1655
|
-
toolCalls: readResponseToolCalls(response)
|
|
1656
|
-
};
|
|
1657
|
-
} finally {
|
|
1658
|
-
request.onRequestMetric?.({
|
|
1659
|
-
durationMs: Date.now() - startedAt,
|
|
1660
|
-
usage
|
|
1661
|
-
});
|
|
1662
|
-
}
|
|
1663
|
-
}
|
|
1664
|
-
};
|
|
1538
|
+
// src/provider/responsesRequest.ts
|
|
1665
1539
|
function buildResponsesRequestBody(request) {
|
|
1666
1540
|
const capabilities = resolveProviderCapabilities({
|
|
1667
1541
|
provider: request.provider,
|
|
@@ -1745,7 +1619,9 @@ function toResponsesInput(messages) {
|
|
|
1745
1619
|
}
|
|
1746
1620
|
return items;
|
|
1747
1621
|
}
|
|
1748
|
-
|
|
1622
|
+
|
|
1623
|
+
// src/provider/responsesResponse.ts
|
|
1624
|
+
function normalizeResponsesOutputText(response) {
|
|
1749
1625
|
const outputText = response.output_text;
|
|
1750
1626
|
if (typeof outputText === "string" && outputText.trim().length > 0) {
|
|
1751
1627
|
return outputText;
|
|
@@ -1771,7 +1647,7 @@ function normalizeOutputText(response) {
|
|
|
1771
1647
|
});
|
|
1772
1648
|
return fragments.length > 0 ? fragments.join("") : null;
|
|
1773
1649
|
}
|
|
1774
|
-
function
|
|
1650
|
+
function readResponsesToolCalls(response) {
|
|
1775
1651
|
const output = response.output;
|
|
1776
1652
|
if (!Array.isArray(output)) {
|
|
1777
1653
|
return [];
|
|
@@ -1785,7 +1661,7 @@ function readResponseToolCalls(response) {
|
|
|
1785
1661
|
}
|
|
1786
1662
|
}));
|
|
1787
1663
|
}
|
|
1788
|
-
function
|
|
1664
|
+
function readResponsesReasoning(response) {
|
|
1789
1665
|
const output = response.output;
|
|
1790
1666
|
if (!Array.isArray(output)) {
|
|
1791
1667
|
return void 0;
|
|
@@ -1801,6 +1677,134 @@ function readResponseReasoning(response) {
|
|
|
1801
1677
|
});
|
|
1802
1678
|
return fragments.length > 0 ? fragments.join("") : void 0;
|
|
1803
1679
|
}
|
|
1680
|
+
|
|
1681
|
+
// src/provider/responsesAdapter.ts
|
|
1682
|
+
var responsesAdapter = {
|
|
1683
|
+
wireApi: "responses",
|
|
1684
|
+
async fetchStreaming(client, request) {
|
|
1685
|
+
const startedAt = Date.now();
|
|
1686
|
+
let usage;
|
|
1687
|
+
throwIfAborted(request.abortSignal, "Streaming request aborted");
|
|
1688
|
+
try {
|
|
1689
|
+
const stream = await client.responses.create(
|
|
1690
|
+
{
|
|
1691
|
+
...buildResponsesRequestBody(request),
|
|
1692
|
+
stream: true
|
|
1693
|
+
},
|
|
1694
|
+
{
|
|
1695
|
+
signal: request.abortSignal
|
|
1696
|
+
}
|
|
1697
|
+
);
|
|
1698
|
+
if (request.abortSignal?.aborted) {
|
|
1699
|
+
abortStream2(stream);
|
|
1700
|
+
throw createAbortError("Streaming aborted");
|
|
1701
|
+
}
|
|
1702
|
+
let content = "";
|
|
1703
|
+
let reasoningContent = "";
|
|
1704
|
+
const toolCalls = /* @__PURE__ */ new Map();
|
|
1705
|
+
for await (const event of stream) {
|
|
1706
|
+
if (request.abortSignal?.aborted) {
|
|
1707
|
+
abortStream2(stream);
|
|
1708
|
+
throw createAbortError("Streaming aborted");
|
|
1709
|
+
}
|
|
1710
|
+
usage = normalizeProviderUsage(event.response?.usage) ?? usage;
|
|
1711
|
+
if (event.type === "response.output_text.delta" && typeof event.delta === "string") {
|
|
1712
|
+
content += event.delta;
|
|
1713
|
+
request.callbacks?.onAssistantDelta?.(event.delta);
|
|
1714
|
+
continue;
|
|
1715
|
+
}
|
|
1716
|
+
if ((event.type === "response.reasoning_text.delta" || event.type === "response.reasoning_summary_text.delta") && typeof event.delta === "string") {
|
|
1717
|
+
reasoningContent += event.delta;
|
|
1718
|
+
request.callbacks?.onReasoningDelta?.(event.delta);
|
|
1719
|
+
continue;
|
|
1720
|
+
}
|
|
1721
|
+
if (event.type === "response.function_call_arguments.delta" && typeof event.delta === "string") {
|
|
1722
|
+
const index = typeof event.output_index === "number" ? event.output_index : 0;
|
|
1723
|
+
const existing = toolCalls.get(index) ?? {
|
|
1724
|
+
id: event.item_id ?? `tool-${index}`,
|
|
1725
|
+
name: "",
|
|
1726
|
+
arguments: ""
|
|
1727
|
+
};
|
|
1728
|
+
existing.arguments += event.delta;
|
|
1729
|
+
toolCalls.set(index, existing);
|
|
1730
|
+
continue;
|
|
1731
|
+
}
|
|
1732
|
+
if (event.type === "response.function_call_arguments.done") {
|
|
1733
|
+
const index = typeof event.output_index === "number" ? event.output_index : 0;
|
|
1734
|
+
const existing = toolCalls.get(index) ?? {
|
|
1735
|
+
id: event.item_id ?? `tool-${index}`,
|
|
1736
|
+
name: "",
|
|
1737
|
+
arguments: ""
|
|
1738
|
+
};
|
|
1739
|
+
if (typeof event.name === "string") {
|
|
1740
|
+
existing.name = event.name;
|
|
1741
|
+
}
|
|
1742
|
+
if (typeof event.arguments === "string" && event.arguments.length > 0) {
|
|
1743
|
+
existing.arguments = event.arguments;
|
|
1744
|
+
}
|
|
1745
|
+
toolCalls.set(index, existing);
|
|
1746
|
+
continue;
|
|
1747
|
+
}
|
|
1748
|
+
if (event.type === "response.output_item.done" && event.item?.type === "function_call") {
|
|
1749
|
+
const index = typeof event.output_index === "number" ? event.output_index : 0;
|
|
1750
|
+
toolCalls.set(index, {
|
|
1751
|
+
id: event.item.call_id ?? event.item.id ?? `tool-${index}`,
|
|
1752
|
+
name: event.item.name ?? "",
|
|
1753
|
+
arguments: event.item.arguments ?? ""
|
|
1754
|
+
});
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
return {
|
|
1758
|
+
content: content.length > 0 ? content : null,
|
|
1759
|
+
reasoningContent: reasoningContent.length > 0 ? reasoningContent : void 0,
|
|
1760
|
+
streamedAssistantContent: content.length > 0,
|
|
1761
|
+
streamedReasoningContent: reasoningContent.length > 0,
|
|
1762
|
+
toolCalls: [...toolCalls.entries()].sort((left, right) => left[0] - right[0]).map(([, toolCall]) => ({
|
|
1763
|
+
id: toolCall.id,
|
|
1764
|
+
type: "function",
|
|
1765
|
+
function: {
|
|
1766
|
+
name: toolCall.name,
|
|
1767
|
+
arguments: toolCall.arguments
|
|
1768
|
+
}
|
|
1769
|
+
}))
|
|
1770
|
+
};
|
|
1771
|
+
} finally {
|
|
1772
|
+
request.onRequestMetric?.({
|
|
1773
|
+
durationMs: Date.now() - startedAt,
|
|
1774
|
+
usage
|
|
1775
|
+
});
|
|
1776
|
+
}
|
|
1777
|
+
},
|
|
1778
|
+
async fetchNonStreaming(client, request) {
|
|
1779
|
+
const startedAt = Date.now();
|
|
1780
|
+
let usage;
|
|
1781
|
+
throwIfAborted(request.abortSignal, "Request aborted");
|
|
1782
|
+
try {
|
|
1783
|
+
const response = await client.responses.create(
|
|
1784
|
+
{
|
|
1785
|
+
...buildResponsesRequestBody(request),
|
|
1786
|
+
stream: false
|
|
1787
|
+
},
|
|
1788
|
+
{
|
|
1789
|
+
signal: request.abortSignal
|
|
1790
|
+
}
|
|
1791
|
+
);
|
|
1792
|
+
usage = normalizeProviderUsage(response.usage);
|
|
1793
|
+
return {
|
|
1794
|
+
content: normalizeResponsesOutputText(response),
|
|
1795
|
+
reasoningContent: readResponsesReasoning(response),
|
|
1796
|
+
streamedAssistantContent: false,
|
|
1797
|
+
streamedReasoningContent: false,
|
|
1798
|
+
toolCalls: readResponsesToolCalls(response)
|
|
1799
|
+
};
|
|
1800
|
+
} finally {
|
|
1801
|
+
request.onRequestMetric?.({
|
|
1802
|
+
durationMs: Date.now() - startedAt,
|
|
1803
|
+
usage
|
|
1804
|
+
});
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
};
|
|
1804
1808
|
function abortStream2(stream) {
|
|
1805
1809
|
try {
|
|
1806
1810
|
stream?.controller?.abort();
|
|
@@ -2254,25 +2258,25 @@ function buildSessionConversationBriefBlock(brief) {
|
|
|
2254
2258
|
if (!brief?.modelSummary) {
|
|
2255
2259
|
return void 0;
|
|
2256
2260
|
}
|
|
2257
|
-
return buildFieldBlock("
|
|
2261
|
+
return buildFieldBlock("Conversation continuity evidence", [
|
|
2258
2262
|
{
|
|
2259
2263
|
label: "Purpose",
|
|
2260
2264
|
value: "Use these facts as private continuity state. Answer the current request directly. Quote prior turns only when the user asks."
|
|
2261
2265
|
},
|
|
2262
2266
|
brief.modelSummary ? {
|
|
2263
|
-
label: "
|
|
2267
|
+
label: "Model-written session memory",
|
|
2264
2268
|
value: brief.modelSummary
|
|
2265
|
-
} : { label: "
|
|
2269
|
+
} : { label: "Model-written session memory", value: void 0 },
|
|
2266
2270
|
brief.modelSummaryUpdatedAt ? {
|
|
2267
|
-
label: "
|
|
2271
|
+
label: "Updated",
|
|
2268
2272
|
value: brief.modelSummaryUpdatedAt
|
|
2269
|
-
} : { label: "
|
|
2273
|
+
} : { label: "Updated", value: void 0 },
|
|
2270
2274
|
{
|
|
2271
|
-
label: "
|
|
2275
|
+
label: "Near-field visible turns",
|
|
2272
2276
|
value: `${brief.userTurnCount} user turn(s) with current input / ${brief.assistantTurnCount} assistant response(s)`
|
|
2273
2277
|
},
|
|
2274
2278
|
{
|
|
2275
|
-
label: "
|
|
2279
|
+
label: "Recent tool activity",
|
|
2276
2280
|
value: formatSignals(brief.toolActivity)
|
|
2277
2281
|
}
|
|
2278
2282
|
]);
|
|
@@ -2400,7 +2404,7 @@ function buildHistoryBoundaryBlock(memory) {
|
|
|
2400
2404
|
return buildFieldBlock("History boundary", [
|
|
2401
2405
|
{
|
|
2402
2406
|
label: "Policy",
|
|
2403
|
-
value: "Raw session history stays out of the current request.
|
|
2407
|
+
value: "Raw session history stays out of the current request. Conversation continuity evidence and current workset are automatic facts for judgment, not text to narrate."
|
|
2404
2408
|
}
|
|
2405
2409
|
]);
|
|
2406
2410
|
}
|
|
@@ -2643,6 +2647,10 @@ function buildTaskLifecyclePromptBlock(lifecycle) {
|
|
|
2643
2647
|
return void 0;
|
|
2644
2648
|
}
|
|
2645
2649
|
const fields = [
|
|
2650
|
+
{
|
|
2651
|
+
label: "Purpose",
|
|
2652
|
+
value: "Current task-state evidence. Use it to orient the next action; do not treat it as a new user request."
|
|
2653
|
+
},
|
|
2646
2654
|
{ label: "Stage", value: lifecycle.stage },
|
|
2647
2655
|
lifecycle.scope ? { label: "Scope", value: lifecycle.scope } : void 0,
|
|
2648
2656
|
lifecycle.boundary ? { label: "Boundary", value: lifecycle.boundary } : void 0,
|
|
@@ -2653,14 +2661,14 @@ function buildTaskLifecyclePromptBlock(lifecycle) {
|
|
|
2653
2661
|
lifecycle.completionFacts.length > 0 ? { label: "Completion facts", value: formatLimitedList(lifecycle.completionFacts, 4) } : void 0,
|
|
2654
2662
|
{ label: "Updated", value: lifecycle.updatedAt }
|
|
2655
2663
|
];
|
|
2656
|
-
return buildFieldBlock("
|
|
2664
|
+
return buildFieldBlock("Current task scene evidence", fields.filter((field) => Boolean(field)));
|
|
2657
2665
|
}
|
|
2658
2666
|
function buildProjectMapPromptBlock(projectMap) {
|
|
2659
2667
|
if (!projectMap) {
|
|
2660
2668
|
return void 0;
|
|
2661
2669
|
}
|
|
2662
2670
|
const fields = [
|
|
2663
|
-
{ label: "Purpose", value: "
|
|
2671
|
+
{ label: "Purpose", value: "Project orientation evidence. Use as facts for the current turn; do not treat this block as a task route." },
|
|
2664
2672
|
{ label: "Root", value: projectMap.rootDir },
|
|
2665
2673
|
{ label: "Top-level dirs", value: formatLimitedList(projectMap.topLevelDirectories, 10) },
|
|
2666
2674
|
{ label: "Entries", value: formatLimitedList(projectMap.entryFiles, 8) },
|
|
@@ -2674,7 +2682,7 @@ function buildProjectMapPromptBlock(projectMap) {
|
|
|
2674
2682
|
projectMap.git.recentChanges.length > 0 ? { label: "Recent changes", value: formatLimitedList(projectMap.git.recentChanges, 6) } : void 0,
|
|
2675
2683
|
{ label: "Updated", value: projectMap.updatedAt }
|
|
2676
2684
|
];
|
|
2677
|
-
return buildFieldBlock("Project
|
|
2685
|
+
return buildFieldBlock("Project orientation evidence", fields.filter((field) => Boolean(field)));
|
|
2678
2686
|
}
|
|
2679
2687
|
|
|
2680
2688
|
// src/agent/prompt/metrics.ts
|
|
@@ -5117,7 +5125,7 @@ function pathDepth(relativePath) {
|
|
|
5117
5125
|
return relativePath.split("/").filter(Boolean).length;
|
|
5118
5126
|
}
|
|
5119
5127
|
|
|
5120
|
-
// src/tools/
|
|
5128
|
+
// src/tools/outputGovernance/classifier.ts
|
|
5121
5129
|
function classifyToolOutput(source) {
|
|
5122
5130
|
const output = source.output.trim();
|
|
5123
5131
|
if (!output) {
|
|
@@ -5158,7 +5166,7 @@ function looksLikeBuild(command, text) {
|
|
|
5158
5166
|
return /\b(build|compile|cargo check|cargo clippy|npm run build|pnpm build)\b/.test(command) || /\b(compilation failed|build failed|compiled successfully|error\[e\d+\])\b/.test(text);
|
|
5159
5167
|
}
|
|
5160
5168
|
|
|
5161
|
-
// src/tools/
|
|
5169
|
+
// src/tools/outputGovernance/metrics.ts
|
|
5162
5170
|
function estimateTextTokens(value) {
|
|
5163
5171
|
const trimmed = value.trim();
|
|
5164
5172
|
if (!trimmed) {
|
|
@@ -5183,7 +5191,7 @@ function computeSavings(input) {
|
|
|
5183
5191
|
};
|
|
5184
5192
|
}
|
|
5185
5193
|
|
|
5186
|
-
// src/tools/
|
|
5194
|
+
// src/tools/outputGovernance/projectors/shared.ts
|
|
5187
5195
|
function buildHeader(source, label) {
|
|
5188
5196
|
return [
|
|
5189
5197
|
`${source.toolName}: ${label}`,
|
|
@@ -5209,7 +5217,7 @@ function dedupeProjectedLines(lines) {
|
|
|
5209
5217
|
return result;
|
|
5210
5218
|
}
|
|
5211
5219
|
|
|
5212
|
-
// src/tools/
|
|
5220
|
+
// src/tools/outputGovernance/projectors/diagnostic.ts
|
|
5213
5221
|
var STRUCTURED_MAX_LINES = 28;
|
|
5214
5222
|
function buildDiagnosticProjection(source, label) {
|
|
5215
5223
|
const lines = splitOutputLines(source.output);
|
|
@@ -5228,7 +5236,7 @@ function isSummaryLine(line) {
|
|
|
5228
5236
|
return /\b(\d+\s+(passed|failed|skipped|errors?|warnings?)|test result|found \d+ errors?|failed tests?|build failed|compiled successfully)\b/i.test(line);
|
|
5229
5237
|
}
|
|
5230
5238
|
|
|
5231
|
-
// src/tools/
|
|
5239
|
+
// src/tools/outputGovernance/projectors/gitDiff.ts
|
|
5232
5240
|
var DIFF_MAX_FILES = 24;
|
|
5233
5241
|
function buildGitDiffProjection(source) {
|
|
5234
5242
|
const lines = splitOutputLines(source.output);
|
|
@@ -5243,7 +5251,7 @@ function buildGitDiffProjection(source) {
|
|
|
5243
5251
|
].filter((line) => Boolean(line)).join("\n");
|
|
5244
5252
|
}
|
|
5245
5253
|
|
|
5246
|
-
// src/tools/
|
|
5254
|
+
// src/tools/outputGovernance/projectors/generic.ts
|
|
5247
5255
|
var GENERIC_MAX_CHARS = 1500;
|
|
5248
5256
|
function projectEmptyOutput(source) {
|
|
5249
5257
|
return {
|
|
@@ -5285,7 +5293,7 @@ function buildGenericPreview(source) {
|
|
|
5285
5293
|
].filter(Boolean).join("\n");
|
|
5286
5294
|
}
|
|
5287
5295
|
|
|
5288
|
-
// src/tools/
|
|
5296
|
+
// src/tools/outputGovernance/projectors/search.ts
|
|
5289
5297
|
var SEARCH_MAX_MATCHES = 24;
|
|
5290
5298
|
function buildSearchProjection(source) {
|
|
5291
5299
|
const nonEmptyLines = splitOutputLines(source.output).filter((line) => line.trim().length > 0);
|
|
@@ -5298,7 +5306,7 @@ function buildSearchProjection(source) {
|
|
|
5298
5306
|
].join("\n");
|
|
5299
5307
|
}
|
|
5300
5308
|
|
|
5301
|
-
// src/tools/
|
|
5309
|
+
// src/tools/outputGovernance/projectors/recovery.ts
|
|
5302
5310
|
function appendRecoveryHint(projection, governance) {
|
|
5303
5311
|
if (!governance.recoveryHint) {
|
|
5304
5312
|
return projection;
|
|
@@ -5310,7 +5318,7 @@ function appendRecoveryHint(projection, governance) {
|
|
|
5310
5318
|
${governance.recoveryHint}`;
|
|
5311
5319
|
}
|
|
5312
5320
|
|
|
5313
|
-
// src/tools/
|
|
5321
|
+
// src/tools/outputGovernance/projectors.ts
|
|
5314
5322
|
function projectOutputByKind(kind, source) {
|
|
5315
5323
|
switch (kind) {
|
|
5316
5324
|
case "empty":
|
|
@@ -5330,7 +5338,7 @@ function projectOutputByKind(kind, source) {
|
|
|
5330
5338
|
}
|
|
5331
5339
|
}
|
|
5332
5340
|
|
|
5333
|
-
// src/tools/
|
|
5341
|
+
// src/tools/outputGovernance/index.ts
|
|
5334
5342
|
function governToolOutput(source) {
|
|
5335
5343
|
const kind = classifyToolOutput(source);
|
|
5336
5344
|
const projected = projectOutputByKind(kind, source);
|
|
@@ -10156,6 +10164,53 @@ function looksLikeToolProtocolText(content) {
|
|
|
10156
10164
|
return text.includes("<\uFF5C\uFF5CDSML\uFF5C\uFF5Ctool_calls>") || text.includes("<tool_call>") || text.includes('"tool_calls"');
|
|
10157
10165
|
}
|
|
10158
10166
|
|
|
10167
|
+
// src/host/delegatedCloseout.ts
|
|
10168
|
+
async function completeExactDelegatedCloseout(input) {
|
|
10169
|
+
const answer = resolveExactDelegatedAnswer(input.executions);
|
|
10170
|
+
if (!answer) {
|
|
10171
|
+
return void 0;
|
|
10172
|
+
}
|
|
10173
|
+
const transition = createFinalizeTransition({
|
|
10174
|
+
changedPaths: []
|
|
10175
|
+
});
|
|
10176
|
+
const sessionWithAnswer = await input.sessionStore.appendMessages(input.session, [
|
|
10177
|
+
createMessage("assistant", answer)
|
|
10178
|
+
]);
|
|
10179
|
+
const session = await input.sessionStore.save(noteCheckpointCompleted(sessionWithAnswer, transition));
|
|
10180
|
+
const ledger = new ControlPlaneLedger(input.stateRootDir);
|
|
10181
|
+
try {
|
|
10182
|
+
ledger.taskLifecycle.complete({
|
|
10183
|
+
sessionId: session.id,
|
|
10184
|
+
reason: "finalize.delegated_exact_output",
|
|
10185
|
+
completionFacts: [answer]
|
|
10186
|
+
});
|
|
10187
|
+
} finally {
|
|
10188
|
+
ledger.close();
|
|
10189
|
+
}
|
|
10190
|
+
input.callbacks?.onAssistantText?.(answer);
|
|
10191
|
+
input.callbacks?.onAssistantDone?.(answer);
|
|
10192
|
+
return buildRunTurnResult({
|
|
10193
|
+
session,
|
|
10194
|
+
changedPaths: [],
|
|
10195
|
+
transition
|
|
10196
|
+
});
|
|
10197
|
+
}
|
|
10198
|
+
function resolveExactDelegatedAnswer(executions) {
|
|
10199
|
+
if (executions.length !== 1) {
|
|
10200
|
+
return void 0;
|
|
10201
|
+
}
|
|
10202
|
+
const [execution] = executions;
|
|
10203
|
+
if (!execution || execution.status !== "completed") {
|
|
10204
|
+
return void 0;
|
|
10205
|
+
}
|
|
10206
|
+
const expected = execution.assignment?.expectedOutput?.trim();
|
|
10207
|
+
const output = execution.output?.trim();
|
|
10208
|
+
if (!expected || !output || expected !== output) {
|
|
10209
|
+
return void 0;
|
|
10210
|
+
}
|
|
10211
|
+
return output;
|
|
10212
|
+
}
|
|
10213
|
+
|
|
10159
10214
|
// src/observability/crashRecorder.ts
|
|
10160
10215
|
import fs24 from "fs";
|
|
10161
10216
|
import path26 from "path";
|
|
@@ -10432,51 +10487,6 @@ async function runHostTurn(options, dependencies = {}) {
|
|
|
10432
10487
|
await toolRegistry?.close?.().catch(() => void 0);
|
|
10433
10488
|
}
|
|
10434
10489
|
}
|
|
10435
|
-
async function completeExactDelegatedCloseout(input) {
|
|
10436
|
-
const answer = resolveExactDelegatedAnswer(input.executions);
|
|
10437
|
-
if (!answer) {
|
|
10438
|
-
return void 0;
|
|
10439
|
-
}
|
|
10440
|
-
const transition = createFinalizeTransition({
|
|
10441
|
-
changedPaths: []
|
|
10442
|
-
});
|
|
10443
|
-
const sessionWithAnswer = await input.sessionStore.appendMessages(input.session, [
|
|
10444
|
-
createMessage("assistant", answer)
|
|
10445
|
-
]);
|
|
10446
|
-
const session = await input.sessionStore.save(noteCheckpointCompleted(sessionWithAnswer, transition));
|
|
10447
|
-
const ledger = new ControlPlaneLedger(input.stateRootDir);
|
|
10448
|
-
try {
|
|
10449
|
-
ledger.taskLifecycle.complete({
|
|
10450
|
-
sessionId: session.id,
|
|
10451
|
-
reason: "finalize.delegated_exact_output",
|
|
10452
|
-
completionFacts: [answer]
|
|
10453
|
-
});
|
|
10454
|
-
} finally {
|
|
10455
|
-
ledger.close();
|
|
10456
|
-
}
|
|
10457
|
-
input.callbacks?.onAssistantText?.(answer);
|
|
10458
|
-
input.callbacks?.onAssistantDone?.(answer);
|
|
10459
|
-
return buildRunTurnResult({
|
|
10460
|
-
session,
|
|
10461
|
-
changedPaths: [],
|
|
10462
|
-
transition
|
|
10463
|
-
});
|
|
10464
|
-
}
|
|
10465
|
-
function resolveExactDelegatedAnswer(executions) {
|
|
10466
|
-
if (executions.length !== 1) {
|
|
10467
|
-
return void 0;
|
|
10468
|
-
}
|
|
10469
|
-
const [execution] = executions;
|
|
10470
|
-
if (!execution || execution.status !== "completed") {
|
|
10471
|
-
return void 0;
|
|
10472
|
-
}
|
|
10473
|
-
const expected = execution.assignment?.expectedOutput?.trim();
|
|
10474
|
-
const output = execution.output?.trim();
|
|
10475
|
-
if (!expected || !output || expected !== output) {
|
|
10476
|
-
return void 0;
|
|
10477
|
-
}
|
|
10478
|
-
return output;
|
|
10479
|
-
}
|
|
10480
10490
|
function createToollessRegistry(registry) {
|
|
10481
10491
|
return {
|
|
10482
10492
|
...registry,
|