@zhushanwen/pi-goal 0.6.4 → 0.6.5
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhushanwen/pi-goal",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"description": "Codex-style /goal command for Pi — persistent goal-driven autonomous loop with evidence-based completion, token/time budgets, blocked detection, and steering templates.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -25,7 +25,8 @@
|
|
|
25
25
|
"@earendil-works/pi-ai": "*",
|
|
26
26
|
"@earendil-works/pi-tui": "*",
|
|
27
27
|
"@earendil-works/pi-coding-agent": "*",
|
|
28
|
-
"typebox": "*"
|
|
28
|
+
"typebox": "*",
|
|
29
|
+
"@zhushanwen/pi-pending-notifications": "0.3.1"
|
|
29
30
|
},
|
|
30
31
|
"dependencies": {
|
|
31
32
|
"@xyz-agent/extension-protocol": "^0.3.1"
|
|
@@ -9,6 +9,10 @@ export const Type = {
|
|
|
9
9
|
Array: (_item: unknown, _opts?: unknown) => ([]),
|
|
10
10
|
Optional: (_item: unknown) => ({}),
|
|
11
11
|
Boolean: (_opts?: unknown) => ({}),
|
|
12
|
+
// 跨扩展依赖(@zhushanwen/pi-pending-notifications 的 registerTool schema)需要:
|
|
13
|
+
// Literal/Union 返回可序列化的 schema 对象即可(测试不校验 schema 语义)。
|
|
14
|
+
Literal: (_value: unknown) => ({ type: "literal" }),
|
|
15
|
+
Union: (_items: unknown[]) => ({ type: "union" }),
|
|
12
16
|
};
|
|
13
17
|
|
|
14
18
|
export type Static<_T> = Record<string, unknown>;
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
22
|
+
import { countActiveFromEntries } from "@zhushanwen/pi-pending-notifications";
|
|
22
23
|
|
|
23
24
|
import { checkBudgetOnTurnEnd } from "../../engine/budget";
|
|
24
25
|
import { isActiveStatus, isTerminalStatus } from "../../engine/goal";
|
|
@@ -28,7 +29,6 @@ import {
|
|
|
28
29
|
} from "../../projection/prompts";
|
|
29
30
|
import { persistAndUpdate, tickState } from "../../service";
|
|
30
31
|
import type { GoalSession } from "../../session";
|
|
31
|
-
import type { SessionEntryLike } from "../../ports";
|
|
32
32
|
import { buildPorts } from "../ports";
|
|
33
33
|
import { makeStaleChecker } from "./shared";
|
|
34
34
|
|
|
@@ -177,7 +177,7 @@ async function handleContinuation(
|
|
|
177
177
|
// 新 turn → 又 agent_end → 又 continuation。
|
|
178
178
|
// 刻意不校验 expiresAt:长任务 subagent(>1h TTL)完成时仍 triggerTurn 唤醒主 agent,
|
|
179
179
|
// 按 TTL 判非活跃会让死循环在长任务场景复现。
|
|
180
|
-
const pendingOps =
|
|
180
|
+
const pendingOps = countActiveFromEntries(ctx.sessionManager.getEntries());
|
|
181
181
|
if (pendingOps.count > 0) {
|
|
182
182
|
pi.appendEntry("goal:log", {
|
|
183
183
|
timestamp: Date.now(),
|
|
@@ -200,31 +200,3 @@ async function handleContinuation(
|
|
|
200
200
|
"followUp",
|
|
201
201
|
);
|
|
202
202
|
}
|
|
203
|
-
|
|
204
|
-
/** 类型守卫:unknown → Record<string, unknown>(替代裸 as 断言访问 entry.data.id)。 */
|
|
205
|
-
const isRecord = (x: unknown): x is Record<string, unknown> =>
|
|
206
|
-
typeof x === "object" && x !== null;
|
|
207
|
-
|
|
208
|
-
/** 计算活跃的 pending async operation(background subagent/workflow)数量。
|
|
209
|
-
* 读 session entries 里 customType="pending:register" 减 "pending:unregister" 的 id 差集。
|
|
210
|
-
* 刻意不校验 expiresAt(见 handleContinuation 守卫注释)。 */
|
|
211
|
-
function countActivePendingOps(
|
|
212
|
-
entries: readonly SessionEntryLike[],
|
|
213
|
-
): { count: number; ids: string[] } {
|
|
214
|
-
const unregistered = new Set<string>();
|
|
215
|
-
for (const e of entries) {
|
|
216
|
-
if (e.type !== "custom" || e.customType !== "pending:unregister") continue;
|
|
217
|
-
const id = isRecord(e.data) ? e.data.id : undefined;
|
|
218
|
-
if (typeof id === "string") unregistered.add(id);
|
|
219
|
-
}
|
|
220
|
-
const activeIds: string[] = [];
|
|
221
|
-
const seen = new Set<string>();
|
|
222
|
-
for (const e of entries) {
|
|
223
|
-
if (e.type !== "custom" || e.customType !== "pending:register") continue;
|
|
224
|
-
const id = isRecord(e.data) ? e.data.id : undefined;
|
|
225
|
-
if (typeof id !== "string" || unregistered.has(id) || seen.has(id)) continue;
|
|
226
|
-
seen.add(id);
|
|
227
|
-
activeIds.push(id);
|
|
228
|
-
}
|
|
229
|
-
return { count: activeIds.length, ids: activeIds };
|
|
230
|
-
}
|