opencodekit 0.21.0 → 0.21.1
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/index.js +1 -1
- package/dist/template/.opencode/AGENTS.md +13 -1
- package/dist/template/.opencode/memory.db +0 -0
- package/dist/template/.opencode/memory.db-shm +0 -0
- package/dist/template/.opencode/memory.db-wal +0 -0
- package/dist/template/.opencode/package.json +2 -2
- package/dist/template/.opencode/plugin/copilot-auth.ts +59 -0
- package/dist/template/.opencode/plugin/prompt-leverage.ts +136 -138
- package/package.json +1 -1
- package/dist/template/.opencode/plugin/prompt-leverage.ts.bak +0 -228
package/dist/index.js
CHANGED
|
@@ -102,12 +102,16 @@ If a newer user instruction conflicts with an earlier one, follow the newer inst
|
|
|
102
102
|
- Don't stop early when another tool call would improve the result
|
|
103
103
|
- Keep calling tools until the task is complete **and** verification passes
|
|
104
104
|
- If a tool returns empty or partial results, retry with a different strategy before giving up (see Empty Result Recovery)
|
|
105
|
+
- For present-day facts, external APIs, provider behavior, and prior-session context claims, check tools or memory first instead of answering from stale recall
|
|
106
|
+
- If the user provides a specific URL, file path, error log, screenshot, or artifact, inspect that exact evidence before abstracting from it
|
|
105
107
|
|
|
106
108
|
### Dependency Checks
|
|
107
109
|
|
|
108
110
|
- Before taking an action, check whether prerequisite discovery, lookup, or memory retrieval steps are required
|
|
109
111
|
- Don't skip prerequisite steps because the final action seems obvious
|
|
110
112
|
- If a task depends on the output of a prior step, resolve that dependency first
|
|
113
|
+
- Don't claim a capability, tool, or context is unavailable until you've checked the relevant tool, memory, or file evidence
|
|
114
|
+
- If the user writes as if prior context exists ("continue", "that bug", "my project", "what we decided"), search memory or prior sessions before asking them to restate it
|
|
111
115
|
|
|
112
116
|
### Empty Result Recovery
|
|
113
117
|
|
|
@@ -115,7 +119,8 @@ If a lookup, search, or tool call returns empty, partial, or suspiciously narrow
|
|
|
115
119
|
|
|
116
120
|
1. Don't immediately conclude that no results exist
|
|
117
121
|
2. Try at least 1-2 fallback strategies (alternative query terms, broader filters, different source/tool)
|
|
118
|
-
3.
|
|
122
|
+
3. If results look off-target, refine and retry before concluding the task is blocked
|
|
123
|
+
4. Only then report "no results found" along with what strategies were attempted
|
|
119
124
|
|
|
120
125
|
### Completeness Tracking
|
|
121
126
|
|
|
@@ -123,6 +128,8 @@ If a lookup, search, or tool call returns empty, partial, or suspiciously narrow
|
|
|
123
128
|
- Maintain an internal checklist of deliverables (use TodoWrite for multi-step work)
|
|
124
129
|
- For lists, batches, or paginated results: determine expected scope, track processed items, confirm full coverage
|
|
125
130
|
- If any item is blocked by missing data, mark it `[blocked]` and state exactly what is missing
|
|
131
|
+
- For multi-part requests, address every part and synthesize the result instead of making the user inspect raw logs or partial outputs
|
|
132
|
+
- Once you start a task, see it through to a natural stopping point unless blocked by a real dependency or reversibility constraint
|
|
126
133
|
|
|
127
134
|
### Plan Quality Gate
|
|
128
135
|
|
|
@@ -311,6 +318,9 @@ Ask only when:
|
|
|
311
318
|
- Ambiguity materially changes outcome
|
|
312
319
|
- Action is destructive/irreversible
|
|
313
320
|
|
|
321
|
+
Before asking, prefer a reversible action, tool lookup, or narrow assumption when that can resolve the ambiguity safely.
|
|
322
|
+
If a question is still needed, ask at most one targeted question when possible.
|
|
323
|
+
|
|
314
324
|
Keep questions targeted and minimal.
|
|
315
325
|
|
|
316
326
|
---
|
|
@@ -461,12 +471,14 @@ When tilth MCP is available with `--edit` mode, use hash-anchored edits as a **f
|
|
|
461
471
|
## Output Style
|
|
462
472
|
|
|
463
473
|
- Be concise, direct, and collaborative
|
|
474
|
+
- Keep tone constructive and matter-of-fact; avoid condescension
|
|
464
475
|
- Prefer deterministic outputs over prose-heavy explanations
|
|
465
476
|
- Cite concrete file paths and line numbers for non-trivial claims
|
|
466
477
|
- **No cheerleading** — avoid motivational language, artificial reassurance, or filler ("Got it!", "Great question!", "Sure thing!")
|
|
467
478
|
- **Never narrate abstractly** — explain what you're doing and why, not that you're "going to look into this"
|
|
468
479
|
- **Code reviews: bugs first** — identify bugs, risks, and regressions before style or readability comments
|
|
469
480
|
- **Flat lists preferred** — use sections for hierarchy instead of deeply nested bullets
|
|
481
|
+
- Own mistakes directly and fix them without excessive apology or self-abasement
|
|
470
482
|
|
|
471
483
|
_Complexity is the enemy. Minimize moving parts._
|
|
472
484
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -12,11 +12,11 @@
|
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@google/stitch-sdk": "^0.0.3",
|
|
15
|
-
"@opencode-ai/plugin": "1.4.
|
|
15
|
+
"@opencode-ai/plugin": "1.4.9"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@types/node": "^25.3.0",
|
|
19
19
|
"bun-types": "^1.3.9",
|
|
20
20
|
"typescript": "^5.9.3"
|
|
21
21
|
}
|
|
22
|
-
}
|
|
22
|
+
}
|
|
@@ -864,6 +864,65 @@ export const CopilotAuthPlugin: Plugin = async ({ client: sdk, directory }) => {
|
|
|
864
864
|
),
|
|
865
865
|
);
|
|
866
866
|
}
|
|
867
|
+
|
|
868
|
+
// Sanitize tool definitions: strip non-standard fields like
|
|
869
|
+
// "custom" (wrapping eager_input_streaming) injected by
|
|
870
|
+
// runtime layers. These cause "Extra inputs are not permitted"
|
|
871
|
+
// on the Copilot API.
|
|
872
|
+
const toolSource = modifiedBody || body;
|
|
873
|
+
if (Array.isArray(toolSource?.tools)) {
|
|
874
|
+
let toolsChanged = false;
|
|
875
|
+
const sanitizedTools = toolSource.tools.map(
|
|
876
|
+
(tool: any) => {
|
|
877
|
+
if (!tool || typeof tool !== "object") return tool;
|
|
878
|
+
|
|
879
|
+
let result = tool;
|
|
880
|
+
|
|
881
|
+
// Strip top-level non-standard fields from tool object
|
|
882
|
+
if (
|
|
883
|
+
"custom" in result ||
|
|
884
|
+
"eager_input_streaming" in result
|
|
885
|
+
) {
|
|
886
|
+
toolsChanged = true;
|
|
887
|
+
const {
|
|
888
|
+
custom: _custom,
|
|
889
|
+
eager_input_streaming: _eis,
|
|
890
|
+
...clean
|
|
891
|
+
} = result;
|
|
892
|
+
result = clean;
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
// Also check nested function object (Chat Completions format)
|
|
896
|
+
if (
|
|
897
|
+
result.function &&
|
|
898
|
+
typeof result.function === "object" &&
|
|
899
|
+
("custom" in result.function ||
|
|
900
|
+
"eager_input_streaming" in result.function)
|
|
901
|
+
) {
|
|
902
|
+
toolsChanged = true;
|
|
903
|
+
const {
|
|
904
|
+
custom: _c,
|
|
905
|
+
eager_input_streaming: _e,
|
|
906
|
+
...cleanFn
|
|
907
|
+
} = result.function;
|
|
908
|
+
result = { ...result, function: cleanFn };
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
return result;
|
|
912
|
+
},
|
|
913
|
+
);
|
|
914
|
+
|
|
915
|
+
if (toolsChanged) {
|
|
916
|
+
modifiedBody = {
|
|
917
|
+
...(modifiedBody || body),
|
|
918
|
+
tools: sanitizedTools,
|
|
919
|
+
};
|
|
920
|
+
log(
|
|
921
|
+
"debug",
|
|
922
|
+
"Stripped non-standard fields (custom/eager_input_streaming) from tool definitions",
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
867
926
|
} catch {}
|
|
868
927
|
|
|
869
928
|
const headers: Record<string, string> = {
|
|
@@ -8,116 +8,116 @@
|
|
|
8
8
|
import type { Plugin } from "@opencode-ai/plugin";
|
|
9
9
|
|
|
10
10
|
const TASK_KEYWORDS: Record<string, string[]> = {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
11
|
+
coding: [
|
|
12
|
+
"code",
|
|
13
|
+
"bug",
|
|
14
|
+
"repo",
|
|
15
|
+
"refactor",
|
|
16
|
+
"test",
|
|
17
|
+
"implement",
|
|
18
|
+
"fix",
|
|
19
|
+
"function",
|
|
20
|
+
"api",
|
|
21
|
+
"add",
|
|
22
|
+
"update",
|
|
23
|
+
"remove",
|
|
24
|
+
],
|
|
25
|
+
research: [
|
|
26
|
+
"research",
|
|
27
|
+
"compare",
|
|
28
|
+
"find",
|
|
29
|
+
"latest",
|
|
30
|
+
"sources",
|
|
31
|
+
"analyze",
|
|
32
|
+
"look up",
|
|
33
|
+
],
|
|
34
|
+
writing: [
|
|
35
|
+
"write",
|
|
36
|
+
"rewrite",
|
|
37
|
+
"draft",
|
|
38
|
+
"email",
|
|
39
|
+
"memo",
|
|
40
|
+
"blog",
|
|
41
|
+
"copy",
|
|
42
|
+
"tone",
|
|
43
|
+
],
|
|
44
|
+
review: ["review", "audit", "critique", "inspect", "evaluate", "assess"],
|
|
45
|
+
planning: ["plan", "roadmap", "strategy", "framework", "outline"],
|
|
46
|
+
analysis: ["analyze", "explain", "break down", "diagnose", "root cause"],
|
|
47
47
|
};
|
|
48
48
|
|
|
49
49
|
function detectTask(prompt: string): string {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
const lowered = prompt.toLowerCase();
|
|
51
|
+
const scores: Record<string, number> = {};
|
|
52
|
+
for (const [task, keywords] of Object.entries(TASK_KEYWORDS)) {
|
|
53
|
+
scores[task] = keywords.filter((k) => lowered.includes(k)).length;
|
|
54
|
+
}
|
|
55
|
+
const best = Object.entries(scores).sort((a, b) => b[1] - a[1]);
|
|
56
|
+
return best[0]?.[1] ? best[0][0] : "analysis";
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
function inferIntensity(prompt: string, task: string): string {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
60
|
+
const lowered = prompt.toLowerCase();
|
|
61
|
+
if (
|
|
62
|
+
["careful", "deep", "thorough", "critical", "production"].some((t) =>
|
|
63
|
+
lowered.includes(t),
|
|
64
|
+
)
|
|
65
|
+
) {
|
|
66
|
+
return "Deep";
|
|
67
|
+
}
|
|
68
|
+
if (task === "coding" || task === "research" || task === "review") {
|
|
69
|
+
return "Standard";
|
|
70
|
+
}
|
|
71
|
+
return "Light";
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
function buildToolRules(task: string): string {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
75
|
+
const rules: Record<string, string> = {
|
|
76
|
+
coding:
|
|
77
|
+
"Inspect the relevant files and dependencies first. Validate the final change with the narrowest useful checks before broadening scope.",
|
|
78
|
+
research:
|
|
79
|
+
"Retrieve evidence from reliable sources before concluding. Do not guess facts that can be checked.",
|
|
80
|
+
review:
|
|
81
|
+
"Read enough surrounding context to understand intent before critiquing. Distinguish confirmed issues from plausible risks.",
|
|
82
|
+
};
|
|
83
|
+
return (
|
|
84
|
+
rules[task] ||
|
|
85
|
+
"Use tools or extra context only when they materially improve correctness or completeness."
|
|
86
|
+
);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
function buildOutputContract(task: string): string {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
90
|
+
const contracts: Record<string, string> = {
|
|
91
|
+
coding:
|
|
92
|
+
"Return the result in a practical execution format: concise summary, concrete changes or code, validation notes, and any remaining risks.",
|
|
93
|
+
research:
|
|
94
|
+
"Return a structured synthesis with key findings, supporting evidence, uncertainty where relevant, and a concise bottom line.",
|
|
95
|
+
writing:
|
|
96
|
+
"Return polished final copy in the requested tone and format. If useful, include a short rationale for major editorial choices.",
|
|
97
|
+
review:
|
|
98
|
+
"Return findings grouped by severity or importance, explain why each matters, and suggest the smallest credible next step.",
|
|
99
|
+
};
|
|
100
|
+
return (
|
|
101
|
+
contracts[task] ||
|
|
102
|
+
"Return a clear, well-structured response matched to the task, with no unnecessary verbosity."
|
|
103
|
+
);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
function upgradePrompt(userPrompt: string): string {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
107
|
+
const normalized = userPrompt.trim().replace(/\s+/g, " ");
|
|
108
|
+
const task = detectTask(normalized);
|
|
109
|
+
const intensity = inferIntensity(normalized, task);
|
|
110
|
+
const toolRules = buildToolRules(task);
|
|
111
|
+
const outputContract = buildOutputContract(task);
|
|
112
|
+
|
|
113
|
+
if (normalized.includes("Objective:") && normalized.includes("Context:")) {
|
|
114
|
+
return userPrompt;
|
|
115
|
+
}
|
|
116
|
+
if (normalized.length < 15 || normalized.split(" ").length < 3) {
|
|
117
|
+
return userPrompt;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return `Objective:
|
|
121
121
|
- Complete this task: ${normalized}
|
|
122
122
|
- Optimize for a correct, useful result rather than a merely plausible one.
|
|
123
123
|
|
|
@@ -147,47 +147,45 @@ Done Criteria:
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
export const PromptLeverage: Plugin = async ({ client }) => {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
},
|
|
192
|
-
};
|
|
150
|
+
const showToast = async (message: string) => {
|
|
151
|
+
try {
|
|
152
|
+
await client.tui.showToast({
|
|
153
|
+
body: {
|
|
154
|
+
title: "PromptLeverage",
|
|
155
|
+
message,
|
|
156
|
+
variant: "info",
|
|
157
|
+
duration: 3000,
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
} catch {
|
|
161
|
+
/* Toast API unavailable */
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
return {
|
|
166
|
+
"experimental.chat.messages.transform": async (input: any, output: any) => {
|
|
167
|
+
try {
|
|
168
|
+
const msgs = output.messages || input.messages || [];
|
|
169
|
+
|
|
170
|
+
// Find the last message with parts (user message)
|
|
171
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
172
|
+
const msg = msgs[i];
|
|
173
|
+
if (msg?.parts) {
|
|
174
|
+
for (const part of msg.parts) {
|
|
175
|
+
if (part.type === "text" && part.text) {
|
|
176
|
+
const upgraded = upgradePrompt(part.text);
|
|
177
|
+
if (upgraded !== part.text) {
|
|
178
|
+
part.text = upgraded;
|
|
179
|
+
showToast("Upgraded prompt!");
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
break; // Only upgrade the most recent message
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
} catch (e: any) {
|
|
187
|
+
showToast(`Error: ${e.message}`);
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
};
|
|
193
191
|
};
|
package/package.json
CHANGED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Prompt Leverage Plugin
|
|
3
|
-
*
|
|
4
|
-
* Automatically upgrades every user prompt with the seven-block framework before the AI processes it.
|
|
5
|
-
* This enforces prompt-leverage on ALL user input without relying on the AI to remember the rule.
|
|
6
|
-
*
|
|
7
|
-
* Hooks used:
|
|
8
|
-
* - chat.message: Upgrades user message as it arrives
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { Plugin } from "@opencode-ai/plugin";
|
|
12
|
-
|
|
13
|
-
interface PromptFramework {
|
|
14
|
-
objective: string;
|
|
15
|
-
context: string;
|
|
16
|
-
workStyle: string;
|
|
17
|
-
toolRules: string;
|
|
18
|
-
outputContract: string;
|
|
19
|
-
verification: string;
|
|
20
|
-
doneCriteria: string;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const TASK_KEYWORDS: Record<string, string[]> = {
|
|
24
|
-
coding: [
|
|
25
|
-
"code",
|
|
26
|
-
"bug",
|
|
27
|
-
"repo",
|
|
28
|
-
"refactor",
|
|
29
|
-
"test",
|
|
30
|
-
"implement",
|
|
31
|
-
"fix",
|
|
32
|
-
"function",
|
|
33
|
-
"api",
|
|
34
|
-
"add",
|
|
35
|
-
"update",
|
|
36
|
-
"remove",
|
|
37
|
-
],
|
|
38
|
-
research: [
|
|
39
|
-
"research",
|
|
40
|
-
"compare",
|
|
41
|
-
"find",
|
|
42
|
-
"latest",
|
|
43
|
-
"sources",
|
|
44
|
-
"analyze",
|
|
45
|
-
"look up",
|
|
46
|
-
],
|
|
47
|
-
writing: [
|
|
48
|
-
"write",
|
|
49
|
-
"rewrite",
|
|
50
|
-
"draft",
|
|
51
|
-
"email",
|
|
52
|
-
"memo",
|
|
53
|
-
"blog",
|
|
54
|
-
"copy",
|
|
55
|
-
"tone",
|
|
56
|
-
],
|
|
57
|
-
review: ["review", "audit", "critique", "inspect", "evaluate", "assess"],
|
|
58
|
-
planning: ["plan", "roadmap", "strategy", "framework", "outline"],
|
|
59
|
-
analysis: ["analyze", "explain", "break down", "diagnose", "root cause"],
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
function detectTask(prompt: string): string {
|
|
63
|
-
const lowered = prompt.toLowerCase();
|
|
64
|
-
const scores: Record<string, number> = {};
|
|
65
|
-
|
|
66
|
-
for (const [task, keywords] of Object.entries(TASK_KEYWORDS)) {
|
|
67
|
-
scores[task] = keywords.filter((k) => lowered.includes(k)).length;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const best = Object.entries(scores).sort((a, b) => b[1] - a[1]);
|
|
71
|
-
return best[0]?.[1] ? best[0][0] : "analysis";
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function inferIntensity(prompt: string, task: string): string {
|
|
75
|
-
const lowered = prompt.toLowerCase();
|
|
76
|
-
if (
|
|
77
|
-
lowered.includes("careful") ||
|
|
78
|
-
lowered.includes("deep") ||
|
|
79
|
-
lowered.includes("thorough") ||
|
|
80
|
-
lowered.includes("critical") ||
|
|
81
|
-
lowered.includes("production")
|
|
82
|
-
) {
|
|
83
|
-
return "Deep";
|
|
84
|
-
}
|
|
85
|
-
if (task === "coding" || task === "research" || task === "review") {
|
|
86
|
-
return "Standard";
|
|
87
|
-
}
|
|
88
|
-
return "Light";
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function buildToolRules(task: string): string {
|
|
92
|
-
const rules: Record<string, string> = {
|
|
93
|
-
coding:
|
|
94
|
-
"Inspect the relevant files and dependencies first. Validate the final change with the narrowest useful checks before broadening scope.",
|
|
95
|
-
research:
|
|
96
|
-
"Retrieve evidence from reliable sources before concluding. Do not guess facts that can be checked.",
|
|
97
|
-
review:
|
|
98
|
-
"Read enough surrounding context to understand intent before critiquing. Distinguish confirmed issues from plausible risks.",
|
|
99
|
-
};
|
|
100
|
-
return (
|
|
101
|
-
rules[task] ||
|
|
102
|
-
"Use tools or extra context only when they materially improve correctness or completeness."
|
|
103
|
-
);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
function buildOutputContract(task: string): string {
|
|
107
|
-
const contracts: Record<string, string> = {
|
|
108
|
-
coding:
|
|
109
|
-
"Return the result in a practical execution format: concise summary, concrete changes or code, validation notes, and any remaining risks.",
|
|
110
|
-
research:
|
|
111
|
-
"Return a structured synthesis with key findings, supporting evidence, uncertainty where relevant, and a concise bottom line.",
|
|
112
|
-
writing:
|
|
113
|
-
"Return polished final copy in the requested tone and format. If useful, include a short rationale for major editorial choices.",
|
|
114
|
-
review:
|
|
115
|
-
"Return findings grouped by severity or importance, explain why each matters, and suggest the smallest credible next step.",
|
|
116
|
-
};
|
|
117
|
-
return (
|
|
118
|
-
contracts[task] ||
|
|
119
|
-
"Return a clear, well-structured response matched to the task, with no unnecessary verbosity."
|
|
120
|
-
);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function upgradePrompt(userPrompt: string): string {
|
|
124
|
-
const normalized = userPrompt.trim().replace(/\s+/g, " ");
|
|
125
|
-
const task = detectTask(normalized);
|
|
126
|
-
const intensity = inferIntensity(normalized, task);
|
|
127
|
-
const toolRules = buildToolRules(task);
|
|
128
|
-
const outputContract = buildOutputContract(task);
|
|
129
|
-
|
|
130
|
-
// If prompt is already upgraded (contains framework blocks), skip
|
|
131
|
-
if (normalized.includes("Objective:") && normalized.includes("Context:")) {
|
|
132
|
-
return userPrompt;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Simple prompts don't need full framework
|
|
136
|
-
if (normalized.length < 15 || normalized.split(" ").length < 3) {
|
|
137
|
-
return userPrompt;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
return `Objective:
|
|
141
|
-
- Complete this task: ${normalized}
|
|
142
|
-
- Optimize for a correct, useful result rather than a merely plausible one.
|
|
143
|
-
|
|
144
|
-
Context:
|
|
145
|
-
- Preserve the user's original intent and constraints.
|
|
146
|
-
- Surface any key assumptions if required information is missing.
|
|
147
|
-
|
|
148
|
-
Work Style:
|
|
149
|
-
- Task type: ${task}
|
|
150
|
-
- Effort level: ${intensity}
|
|
151
|
-
- Understand the problem broadly enough to avoid narrow mistakes, then go deep where the risk or complexity is highest.
|
|
152
|
-
- Use first-principles reasoning before proposing changes.
|
|
153
|
-
- For non-trivial work, review the result once with fresh eyes before finalizing.
|
|
154
|
-
|
|
155
|
-
Tool Rules:
|
|
156
|
-
- ${toolRules}
|
|
157
|
-
|
|
158
|
-
Output Contract:
|
|
159
|
-
- ${outputContract}
|
|
160
|
-
|
|
161
|
-
Verification:
|
|
162
|
-
- Check correctness, completeness, and edge cases.
|
|
163
|
-
- Improve obvious weaknesses if a better approach is available within scope.
|
|
164
|
-
|
|
165
|
-
Done Criteria:
|
|
166
|
-
- Stop only when the response satisfies the task, matches the requested format, and passes the verification step.`;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
export const PromptLeverage: Plugin = async ({ client }) => {
|
|
170
|
-
console.log("PromptLeverage: Initializing...");
|
|
171
|
-
|
|
172
|
-
const showToast = async (message: string) => {
|
|
173
|
-
try {
|
|
174
|
-
await client.tui.showToast({
|
|
175
|
-
body: {
|
|
176
|
-
title: "PromptLeverage",
|
|
177
|
-
message,
|
|
178
|
-
variant: "info",
|
|
179
|
-
duration: 3000,
|
|
180
|
-
},
|
|
181
|
-
});
|
|
182
|
-
} catch {
|
|
183
|
-
/* Toast API unavailable */
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
return {
|
|
188
|
-
"chat.message": async (input, output) => {
|
|
189
|
-
// Upgrade user message - check different structures
|
|
190
|
-
showToast(
|
|
191
|
-
`Hook fired, msg: ${JSON.stringify(input.message).slice(0, 100)}`,
|
|
192
|
-
);
|
|
193
|
-
|
|
194
|
-
// Try parts array
|
|
195
|
-
if (input.message?.parts) {
|
|
196
|
-
for (const part of input.message.parts) {
|
|
197
|
-
if (part.type === "text" && part.text) {
|
|
198
|
-
const upgraded = upgradePrompt(part.text);
|
|
199
|
-
if (upgraded !== part.text) {
|
|
200
|
-
part.text = upgraded;
|
|
201
|
-
showToast("Upgraded user prompt");
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
// Try direct text field
|
|
207
|
-
else if (input.message?.text) {
|
|
208
|
-
const upgraded = upgradePrompt(input.message.text);
|
|
209
|
-
if (upgraded !== input.message.text) {
|
|
210
|
-
input.message.text = upgraded;
|
|
211
|
-
showToast("Upgraded user prompt");
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
// Try content array
|
|
215
|
-
else if (input.message?.content) {
|
|
216
|
-
for (const part of input.message.content) {
|
|
217
|
-
if (part.type === "text" && part.text) {
|
|
218
|
-
const upgraded = upgradePrompt(part.text);
|
|
219
|
-
if (upgraded !== part.text) {
|
|
220
|
-
part.text = upgraded;
|
|
221
|
-
showToast("Upgraded user prompt");
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
},
|
|
227
|
-
};
|
|
228
|
-
};
|