@amaster.ai/pi-goal 0.1.2-beta.42

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.
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Prompt templates for the goal engine.
3
+ *
4
+ * The evaluator and activation prompts are adapted almost verbatim from Claude
5
+ * Code's own stop-hook prompts (agent-prompt-hook-condition-evaluator-stop,
6
+ * system-reminder-session-stop-hook-active), tuned only where pi's mechanics
7
+ * differ (a `/goal` command instead of CC's). The derive prompt has no CC
8
+ * analogue — CC always takes an explicit condition — so it is ours.
9
+ */
10
+ export const DERIVE_SYSTEM_PROMPT = `You infer a single, concrete completion condition from a coding conversation.
11
+
12
+ Given the recent transcript, output ONE line describing the measurable outcome that would mean the user's current objective is fully handled. This condition will later be used to judge whether the agent may stop working.
13
+
14
+ Rules:
15
+ - Output ONLY the condition text — no preamble, no quotes, no markdown, no trailing explanation.
16
+ - Make it measurable and verifiable (e.g. "All tests pass and \`pnpm lint\` reports no errors", "The /login endpoint returns 200 for valid credentials and 401 otherwise").
17
+ - Base it on the user's most recent intent, not incidental side-quests.
18
+ - Keep it under 300 characters.
19
+ - If the conversation has no actionable objective, output exactly: NONE`;
20
+ export function buildDeriveUserPrompt(transcript) {
21
+ return `## Recent conversation\n\n${transcript}\n\n---\nInfer the single measurable completion condition, or output NONE.`;
22
+ }
23
+ /**
24
+ * Stop-condition evaluator. Adapted from Claude Code's
25
+ * `agent-prompt-hook-condition-evaluator-stop` — the quote-evidence
26
+ * requirement, the "insufficient evidence in transcript" fallback, and the
27
+ * impossible-judgment discipline all come from CC's original wording.
28
+ */
29
+ export const EVALUATE_SYSTEM_PROMPT = `You are evaluating a stop-condition hook. Read the conversation transcript carefully, then judge whether the user-provided condition is satisfied.
30
+
31
+ Your response must be a JSON object with one of these shapes:
32
+ - {"ok": true, "reason": "<quote evidence from the transcript that satisfies the condition>"}
33
+ - {"ok": false, "reason": "<quote what is missing or what blocks the condition>"}
34
+ - {"ok": false, "impossible": true, "reason": "<explain why the condition can never be satisfied>"}
35
+
36
+ Always include a "reason" field, quoting specific text from the transcript whenever possible. If the transcript does not contain clear evidence that the condition is satisfied, return {"ok": false, "reason": "insufficient evidence in transcript"}.
37
+
38
+ Only use {"ok": false, "impossible": true} when the condition is genuinely unachievable in this session — for example: the condition is self-contradictory, it depends on a resource or capability that is unavailable, or the assistant has explicitly tried, exhausted reasonable approaches, and stated it cannot be done. Apply your own judgment when deciding this — the assistant claiming the goal is impossible is evidence, not proof; independently confirm the condition is genuinely unachievable rather than deferring to the assistant's self-assessment. Do not use it just because the goal has not been reached yet or because progress is slow. When in doubt, return {"ok": false} without "impossible".`;
39
+ /**
40
+ * Note prepended to the transcript when older messages were dropped to fit the
41
+ * evaluator's char cap. Adapted from CC's
42
+ * `system-prompt-hook-evaluator-truncated-transcript-note`: if the evidence
43
+ * might be in the omitted prefix, the evaluator should return insufficient
44
+ * evidence rather than guess.
45
+ */
46
+ export function buildTruncationNote(omittedCount) {
47
+ return `[Earlier conversation truncated to fit the evaluator's context window — ${omittedCount} earlier message(s) omitted. Evaluate the condition against the recent transcript below; if the required evidence may be in the omitted prefix, return {"ok": false, "reason": "insufficient evidence in transcript"}.]`;
48
+ }
49
+ export function buildEvaluateUserPrompt(condition, transcript, omittedCount = 0) {
50
+ const note = omittedCount > 0 ? `${buildTruncationNote(omittedCount)}\n\n` : '';
51
+ return `## Conversation transcript\n\n${note}${transcript}\n\n## Condition\n\n${condition}\n\n---\nHas the condition been satisfied? Reply with the JSON verdict only.`;
52
+ }
53
+ /**
54
+ * Injected once when a goal is set, so the main agent starts working toward it.
55
+ * Adapted from CC's `system-reminder-session-stop-hook-active`.
56
+ */
57
+ export function buildActivationMessage(condition) {
58
+ return `A goal is now active with condition: "${condition}". Briefly acknowledge the goal, then immediately start (or continue) working toward it — treat the condition itself as your directive and do not pause to ask the user what to do. Work will be blocked from stopping until the condition holds. It auto-clears once the condition is met — do not tell the user to run \`/goal clear\` after success; that's only for clearing a goal early.`;
59
+ }
60
+ /** Injected after a not-yet-met evaluation to drive the next round of work. */
61
+ export function buildContinueMessage(condition, reason) {
62
+ return `The goal condition is not yet met: "${condition}". ${reason} Continue working toward the condition now — do not stop until it holds.`;
63
+ }
64
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,oBAAoB,GAAG;;;;;;;;;wEASoC,CAAC;AAEzE,MAAM,UAAU,qBAAqB,CAAC,UAAkB;IACtD,OAAO,6BAA6B,UAAU,4EAA4E,CAAC;AAC7H,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;;;;;;;;;6rBASupB,CAAC;AAE9rB;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAAoB;IACtD,OAAO,2EAA2E,YAAY,yNAAyN,CAAC;AAC1T,CAAC;AAED,MAAM,UAAU,uBAAuB,CACrC,SAAiB,EACjB,UAAkB,EAClB,YAAY,GAAG,CAAC;IAEhB,MAAM,IAAI,GAAG,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAChF,OAAO,iCAAiC,IAAI,GAAG,UAAU,uBAAuB,SAAS,8EAA8E,CAAC;AAC1K,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,SAAiB;IACtD,OAAO,yCAAyC,SAAS,gYAAgY,CAAC;AAC5b,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE,MAAc;IACpE,OAAO,uCAAuC,SAAS,MAAM,MAAM,0EAA0E,CAAC;AAChJ,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Build a compact text transcript from agent messages for derive/evaluate.
3
+ * Works backwards from the newest message so the most recent context survives
4
+ * the char cap (same approach as pi-memory's serializer).
5
+ */
6
+ export interface TranscriptResult {
7
+ /** Formatted transcript, oldest included message first. */
8
+ text: string;
9
+ /** Count of text-bearing messages dropped because of the char cap. */
10
+ omitted: number;
11
+ }
12
+ /**
13
+ * Build the transcript and report how many text-bearing messages were dropped
14
+ * to fit the cap. The evaluator uses `omitted` to decide whether to warn that
15
+ * evidence may live in the truncated prefix (see buildTruncationNote).
16
+ */
17
+ export declare function buildTranscriptWithMeta(messages: unknown[], maxChars: number): TranscriptResult;
18
+ export declare function buildTranscript(messages: unknown[], maxChars: number): string;
19
+ export declare function extractText(content: unknown): string;
20
+ //# sourceMappingURL=transcript.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript.d.ts","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,MAAM,WAAW,gBAAgB;IAC/B,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAuB/F;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAgBpD"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Build a compact text transcript from agent messages for derive/evaluate.
3
+ * Works backwards from the newest message so the most recent context survives
4
+ * the char cap (same approach as pi-memory's serializer).
5
+ */
6
+ /**
7
+ * Build the transcript and report how many text-bearing messages were dropped
8
+ * to fit the cap. The evaluator uses `omitted` to decide whether to warn that
9
+ * evidence may live in the truncated prefix (see buildTruncationNote).
10
+ */
11
+ export function buildTranscriptWithMeta(messages, maxChars) {
12
+ const lines = [];
13
+ let total = 0;
14
+ let included = 0;
15
+ let textMessages = 0;
16
+ for (let i = messages.length - 1; i >= 0; i--) {
17
+ const msg = messages[i];
18
+ if (!msg || typeof msg.role !== 'string')
19
+ continue;
20
+ const text = extractText(msg.content);
21
+ if (!text)
22
+ continue;
23
+ textMessages += 1;
24
+ const line = `[${msg.role}] ${text}`;
25
+ if (total + line.length > maxChars && lines.length > 0) {
26
+ // Cap hit: this and every older text message is omitted.
27
+ continue;
28
+ }
29
+ lines.unshift(line);
30
+ total += line.length;
31
+ included += 1;
32
+ }
33
+ return { text: lines.join('\n\n'), omitted: Math.max(0, textMessages - included) };
34
+ }
35
+ export function buildTranscript(messages, maxChars) {
36
+ return buildTranscriptWithMeta(messages, maxChars).text;
37
+ }
38
+ export function extractText(content) {
39
+ if (typeof content === 'string')
40
+ return content.trim();
41
+ if (Array.isArray(content)) {
42
+ return content
43
+ .filter((c) => !!c &&
44
+ typeof c === 'object' &&
45
+ c.type === 'text' &&
46
+ typeof c.text === 'string')
47
+ .map((c) => c.text)
48
+ .join('\n')
49
+ .trim();
50
+ }
51
+ return '';
52
+ }
53
+ //# sourceMappingURL=transcript.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transcript.js","sourceRoot":"","sources":["../src/transcript.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAcH;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,QAAmB,EAAE,QAAgB;IAC3E,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,YAAY,GAAG,CAAC,CAAC;IAErB,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAA4B,CAAC;QACnD,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;YAAE,SAAS;QACnD,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI;YAAE,SAAS;QACpB,YAAY,IAAI,CAAC,CAAC;QAClB,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QACrC,IAAI,KAAK,GAAG,IAAI,CAAC,MAAM,GAAG,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvD,yDAAyD;YACzD,SAAS;QACX,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACpB,KAAK,IAAI,IAAI,CAAC,MAAM,CAAC;QACrB,QAAQ,IAAI,CAAC,CAAC;IAChB,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAC,EAAE,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAmB,EAAE,QAAgB;IACnE,OAAO,uBAAuB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAgB;IAC1C,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;IACvD,IAAI,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,OAAO,OAAO;aACX,MAAM,CACL,CAAC,CAAC,EAAuC,EAAE,CACzC,CAAC,CAAC,CAAC;YACH,OAAO,CAAC,KAAK,QAAQ;YACpB,CAAwB,CAAC,IAAI,KAAK,MAAM;YACzC,OAAQ,CAAwB,CAAC,IAAI,KAAK,QAAQ,CACrD;aACA,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;aAClB,IAAI,CAAC,IAAI,CAAC;aACV,IAAI,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC"}
package/package.json ADDED
@@ -0,0 +1,85 @@
1
+ {
2
+ "name": "@amaster.ai/pi-goal",
3
+ "version": "0.1.2-beta.42",
4
+ "description": "Pi extension that derives a goal from the conversation and keeps the agent working until the condition is met",
5
+ "keywords": [
6
+ "pi-package",
7
+ "pi",
8
+ "extension",
9
+ "goal",
10
+ "autonomous",
11
+ "stop-condition"
12
+ ],
13
+ "license": "Apache-2.0",
14
+ "type": "module",
15
+ "sideEffects": false,
16
+ "main": "./dist/index.js",
17
+ "types": "./dist/index.d.ts",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "default": "./dist/index.js"
22
+ },
23
+ "./extension": {
24
+ "types": "./dist/extension.d.ts",
25
+ "default": "./dist/extension.js"
26
+ },
27
+ "./package.json": {
28
+ "default": "./package.json"
29
+ }
30
+ },
31
+ "pi": {
32
+ "image": "https://raw.githubusercontent.com/TGYD-helige/pi/master/packages/pi-goal/preview.png",
33
+ "extensions": [
34
+ "./dist/index.js"
35
+ ]
36
+ },
37
+ "files": [
38
+ "dist",
39
+ "preview.png",
40
+ "README.md"
41
+ ],
42
+ "publishConfig": {
43
+ "access": "public"
44
+ },
45
+ "repository": {
46
+ "type": "git",
47
+ "url": "https://github.com/TGYD-helige/pi.git",
48
+ "directory": "packages/pi-goal"
49
+ },
50
+ "dependencies": {
51
+ "@amaster.ai/pi-shared": "0.1.2-beta.42"
52
+ },
53
+ "peerDependencies": {
54
+ "@earendil-works/pi-agent-core": ">=0.74.0",
55
+ "@earendil-works/pi-ai": ">=0.80.10",
56
+ "@earendil-works/pi-coding-agent": ">=0.74.0",
57
+ "typebox": "*"
58
+ },
59
+ "peerDependenciesMeta": {
60
+ "@earendil-works/pi-agent-core": {
61
+ "optional": true
62
+ },
63
+ "@earendil-works/pi-ai": {
64
+ "optional": true
65
+ },
66
+ "@earendil-works/pi-coding-agent": {
67
+ "optional": true
68
+ },
69
+ "typebox": {
70
+ "optional": true
71
+ }
72
+ },
73
+ "devDependencies": {
74
+ "@earendil-works/pi-agent-core": "0.80.10",
75
+ "@earendil-works/pi-ai": "0.80.10",
76
+ "@earendil-works/pi-coding-agent": "0.80.10",
77
+ "typebox": "*",
78
+ "vitest": "^4.0.0"
79
+ },
80
+ "scripts": {
81
+ "build": "tsc -b",
82
+ "typecheck": "tsc -b --pretty false",
83
+ "test": "vitest run"
84
+ }
85
+ }