opencode-next-prompt 0.0.3 → 0.0.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/README.md +1 -2
- package/dist/index.js +3 -7
- package/dist/predict.js +9 -21
- package/dist/ui.d.ts +1 -3
- package/dist/ui.js +1 -36
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Restart opencode. The package and its dependencies are installed automatically.
|
|
|
19
19
|
## Usage
|
|
20
20
|
|
|
21
21
|
- After each reply, a suggested next message appears at the input in gray
|
|
22
|
-
- Press
|
|
22
|
+
- Press the accept key (**↓** by default) while the input is empty to fill it; with text in the input, the key keeps its normal cursor behavior
|
|
23
23
|
- Typing hides the suggestion; clearing the input re-shows it
|
|
24
24
|
|
|
25
25
|
## Config
|
|
@@ -37,7 +37,6 @@ Restart opencode. The package and its dependencies are installed automatically.
|
|
|
37
37
|
| Key | Default | Description |
|
|
38
38
|
|---|---|---|
|
|
39
39
|
| `acceptKey` | `down` | Key to accept the suggestion (only effective while the input is empty) |
|
|
40
|
-
| `position` | `right` | Where the suggestion shows: `left` inside the input; `right` below-right of the input |
|
|
41
40
|
| `timeoutMs` | `20000` | Per-prediction timeout; the suggestion is dropped on timeout |
|
|
42
41
|
|
|
43
42
|
## How it works
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { InputRenderable } from "@opentui/core";
|
|
2
2
|
import { createSuggestionStore } from "./state.js";
|
|
3
3
|
import { createPredictor } from "./predict.js";
|
|
4
|
-
import {
|
|
4
|
+
import { renderSuggestionPlaceholder } from "./ui.js";
|
|
5
5
|
const DEFAULT_OPTIONS = {
|
|
6
|
-
acceptKey: "
|
|
7
|
-
position: "left",
|
|
6
|
+
acceptKey: "down",
|
|
8
7
|
timeoutMs: 20_000,
|
|
9
8
|
};
|
|
10
9
|
const opencodeNextPrompt = async (api, rawOptions) => {
|
|
@@ -118,13 +117,10 @@ const opencodeNextPrompt = async (api, rawOptions) => {
|
|
|
118
117
|
{ key: options.acceptKey, cmd: "next-prompt.accept", preventDefault: false, fallthrough: true },
|
|
119
118
|
],
|
|
120
119
|
});
|
|
121
|
-
const inputEmpty = options.position === "right" ? createInputEmpty(api) : undefined;
|
|
122
120
|
api.slots.register({
|
|
123
121
|
id: "opencode-next-prompt",
|
|
124
122
|
slots: {
|
|
125
|
-
session_prompt_right: (ctx, props) => options.
|
|
126
|
-
? renderSuggestionSlot(ctx, props, store.read, options.acceptKey, inputEmpty)
|
|
127
|
-
: renderSuggestionPlaceholder(api, props, store.read, options.acceptKey),
|
|
123
|
+
session_prompt_right: (ctx, props) => renderSuggestionPlaceholder(api, props, store.read, options.acceptKey),
|
|
128
124
|
},
|
|
129
125
|
});
|
|
130
126
|
};
|
package/dist/predict.js
CHANGED
|
@@ -1,28 +1,16 @@
|
|
|
1
1
|
const TITLE = "next-prompt-suggestion";
|
|
2
|
-
const PROMPT = `You are
|
|
3
|
-
|
|
2
|
+
const PROMPT = `You are the user in a conversation with an AI coding assistant. The
|
|
3
|
+
assistant just finished replying to your latest message.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
Write your next message — your natural reaction to what you just read.
|
|
6
|
+
Address the assistant directly: a request, a question, or an instruction
|
|
7
|
+
(the assistant acts; you never describe doing things yourself). React to
|
|
8
|
+
what was said, not to how it was said. One line, natural and brief, in
|
|
9
|
+
your language and tone.
|
|
7
10
|
|
|
8
|
-
|
|
9
|
-
- Output exactly one line, 170 characters max. Be concise.
|
|
10
|
-
- Write as the user speaking to the assistant (for example: "Can you...", "Help me...", "Let's...").
|
|
11
|
-
- Match the user's tone and language; keep it natural and human.
|
|
12
|
-
- Prefer a concrete action over a broad question.
|
|
13
|
-
- If the conversation is vague or small-talk, steer toward a practical starter request.
|
|
14
|
-
- If there is no meaningful or appropriate next step to suggest, output exactly: NO_SUGGESTION
|
|
15
|
-
- Avoid corporate or robotic phrasing.
|
|
16
|
-
- Avoid asking multiple discovery questions in one sentence.
|
|
17
|
-
- Do not include quotes, labels, markdown, or explanations.
|
|
11
|
+
If nothing plausible remains to say, reply with exactly: NO_SUGGESTION
|
|
18
12
|
|
|
19
|
-
|
|
20
|
-
- Greeting context -> "Can you scan this repo and suggest the best first task to tackle?"
|
|
21
|
-
- Bug-fix context -> "Can you reproduce this bug and propose the smallest safe fix?"
|
|
22
|
-
- Feature context -> "Let's implement this incrementally; start with the MVP version first."
|
|
23
|
-
- Conversation is complete -> "NO_SUGGESTION"
|
|
24
|
-
|
|
25
|
-
Conversation:
|
|
13
|
+
Conversation (oldest first):
|
|
26
14
|
`;
|
|
27
15
|
const MAX_PREDICTION_CHARS = 170;
|
|
28
16
|
export function createPredictor(client, directory, options) {
|
package/dist/ui.d.ts
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type { JSX } from "@opentui/solid";
|
|
2
|
-
import type { TuiPluginApi
|
|
2
|
+
import type { TuiPluginApi } from "@opencode-ai/plugin/tui";
|
|
3
3
|
import type { Accessor } from "solid-js";
|
|
4
4
|
import type { SuggestionState } from "./state.ts";
|
|
5
5
|
export type PromptSlotProps = {
|
|
6
6
|
session_id: string;
|
|
7
7
|
};
|
|
8
8
|
export declare function renderSuggestionPlaceholder(api: TuiPluginApi, props: PromptSlotProps, state: Accessor<SuggestionState>, acceptKey: string): JSX.Element;
|
|
9
|
-
export declare function createInputEmpty(api: TuiPluginApi): Accessor<boolean>;
|
|
10
|
-
export declare function renderSuggestionSlot(ctx: TuiSlotContext, props: PromptSlotProps, state: Accessor<SuggestionState>, acceptKey: string, inputEmpty: Accessor<boolean>): JSX.Element;
|
package/dist/ui.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { createEffect, createSignal, onCleanup } from "solid-js";
|
|
1
|
+
import { createEffect, onCleanup } from "solid-js";
|
|
3
2
|
import { InputRenderable, TextareaRenderable } from "@opentui/core";
|
|
4
3
|
const ARROW_KEYS = {
|
|
5
4
|
right: "→",
|
|
@@ -28,37 +27,3 @@ export function renderSuggestionPlaceholder(api, props, state, acceptKey) {
|
|
|
28
27
|
});
|
|
29
28
|
return null;
|
|
30
29
|
}
|
|
31
|
-
export function createInputEmpty(api) {
|
|
32
|
-
const [inputEmpty, setInputEmpty] = createSignal(true);
|
|
33
|
-
const apply = () => {
|
|
34
|
-
const editor = api.renderer.currentFocusedEditor;
|
|
35
|
-
setInputEmpty(editor === null || (!(editor instanceof InputRenderable) && editor.editBuffer.getText() === ""));
|
|
36
|
-
};
|
|
37
|
-
const offs = new Set();
|
|
38
|
-
const subscribe = (editor) => {
|
|
39
|
-
if (!editor)
|
|
40
|
-
return;
|
|
41
|
-
const handler = () => apply();
|
|
42
|
-
editor.editBuffer.on("content-changed", handler);
|
|
43
|
-
editor.editBuffer.on("cursor-changed", handler);
|
|
44
|
-
offs.add(() => {
|
|
45
|
-
editor.editBuffer.off("content-changed", handler);
|
|
46
|
-
editor.editBuffer.off("cursor-changed", handler);
|
|
47
|
-
});
|
|
48
|
-
};
|
|
49
|
-
api.renderer.on("focused_editor", (current) => {
|
|
50
|
-
offs.forEach((off) => off());
|
|
51
|
-
offs.clear();
|
|
52
|
-
subscribe(current);
|
|
53
|
-
apply();
|
|
54
|
-
});
|
|
55
|
-
subscribe(api.renderer.currentFocusedEditor);
|
|
56
|
-
apply();
|
|
57
|
-
return inputEmpty;
|
|
58
|
-
}
|
|
59
|
-
export function renderSuggestionSlot(ctx, props, state, acceptKey, inputEmpty) {
|
|
60
|
-
const current = state();
|
|
61
|
-
if (current.kind !== "ready" || current.sessionID !== props.session_id || !inputEmpty())
|
|
62
|
-
return null;
|
|
63
|
-
return _jsx("text", { fg: ctx.theme.current.textMuted, children: `[${displayKey(acceptKey)}] ${current.text}` });
|
|
64
|
-
}
|
package/package.json
CHANGED