bonecode 1.2.3 → 1.4.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/README.md +62 -0
- package/compat/opencode_adapter.ts +69 -8
- package/dist/compat/opencode_adapter.js +63 -7
- package/dist/compat/opencode_adapter.js.map +1 -1
- package/dist/src/db_adapter.js +30 -0
- package/dist/src/db_adapter.js.map +1 -1
- package/dist/src/engine/agent/prompt/compaction.txt +9 -0
- package/dist/src/engine/agent/prompt/explore.txt +18 -0
- package/dist/src/engine/agent/prompt/scout.txt +36 -0
- package/dist/src/engine/agent/prompt/summary.txt +11 -0
- package/dist/src/engine/agent/prompt/title.txt +44 -0
- package/dist/src/engine/session/build_mode.d.ts +83 -0
- package/dist/src/engine/session/build_mode.js +789 -0
- package/dist/src/engine/session/build_mode.js.map +1 -0
- package/dist/src/engine/session/build_mode_helpers.d.ts +6 -0
- package/dist/src/engine/session/build_mode_helpers.js +61 -0
- package/dist/src/engine/session/build_mode_helpers.js.map +1 -0
- package/dist/src/engine/session/prompt/anthropic.txt +105 -0
- package/dist/src/engine/session/prompt/beast.txt +147 -0
- package/dist/src/engine/session/prompt/bonescript.txt +402 -0
- package/dist/src/engine/session/prompt/build-switch.txt +5 -0
- package/dist/src/engine/session/prompt/codex.txt +79 -0
- package/dist/src/engine/session/prompt/copilot-gpt-5.txt +143 -0
- package/dist/src/engine/session/prompt/default.txt +105 -0
- package/dist/src/engine/session/prompt/gemini.txt +155 -0
- package/dist/src/engine/session/prompt/gpt.txt +107 -0
- package/dist/src/engine/session/prompt/kimi.txt +95 -0
- package/dist/src/engine/session/prompt/max-steps.txt +16 -0
- package/dist/src/engine/session/prompt/plan-reminder-anthropic.txt +67 -0
- package/dist/src/engine/session/prompt/plan.txt +26 -0
- package/dist/src/engine/session/prompt/trinity.txt +97 -0
- package/dist/src/engine/session/prompt.js +92 -4
- package/dist/src/engine/session/prompt.js.map +1 -1
- package/dist/src/engine/skill/prompt/customize-opencode.md +377 -0
- package/dist/src/engine/tool/apply_patch.txt +33 -0
- package/dist/src/engine/tool/edit.txt +10 -0
- package/dist/src/engine/tool/glob.txt +6 -0
- package/dist/src/engine/tool/grep.txt +8 -0
- package/dist/src/engine/tool/lsp.txt +24 -0
- package/dist/src/engine/tool/plan-enter.txt +14 -0
- package/dist/src/engine/tool/plan-exit.txt +13 -0
- package/dist/src/engine/tool/question.txt +10 -0
- package/dist/src/engine/tool/read.txt +14 -0
- package/dist/src/engine/tool/repo_clone.txt +5 -0
- package/dist/src/engine/tool/repo_overview.txt +4 -0
- package/dist/src/engine/tool/shell/shell.txt +77 -0
- package/dist/src/engine/tool/skill.txt +5 -0
- package/dist/src/engine/tool/task.txt +58 -0
- package/dist/src/engine/tool/task_status.txt +13 -0
- package/dist/src/engine/tool/todowrite.txt +167 -0
- package/dist/src/engine/tool/tool/apply_patch.txt +33 -0
- package/dist/src/engine/tool/tool/edit.txt +10 -0
- package/dist/src/engine/tool/tool/glob.txt +6 -0
- package/dist/src/engine/tool/tool/grep.txt +8 -0
- package/dist/src/engine/tool/tool/lsp.txt +24 -0
- package/dist/src/engine/tool/tool/plan-enter.txt +14 -0
- package/dist/src/engine/tool/tool/plan-exit.txt +13 -0
- package/dist/src/engine/tool/tool/question.txt +10 -0
- package/dist/src/engine/tool/tool/read.txt +14 -0
- package/dist/src/engine/tool/tool/repo_clone.txt +5 -0
- package/dist/src/engine/tool/tool/repo_overview.txt +4 -0
- package/dist/src/engine/tool/tool/shell/shell.txt +77 -0
- package/dist/src/engine/tool/tool/skill.txt +5 -0
- package/dist/src/engine/tool/tool/task.txt +58 -0
- package/dist/src/engine/tool/tool/task_status.txt +13 -0
- package/dist/src/engine/tool/tool/todowrite.txt +167 -0
- package/dist/src/engine/tool/tool/webfetch.txt +13 -0
- package/dist/src/engine/tool/tool/websearch.txt +14 -0
- package/dist/src/engine/tool/tool/write.txt +8 -0
- package/dist/src/engine/tool/webfetch.txt +13 -0
- package/dist/src/engine/tool/websearch.txt +14 -0
- package/dist/src/engine/tool/write.txt +8 -0
- package/dist/src/tui.js +146 -9
- package/dist/src/tui.js.map +1 -1
- package/package.json +2 -2
- package/scripts/copy_prompts.js +58 -0
- package/scripts/test_bonescript_primer.js +111 -0
- package/scripts/test_build_fallback.js +221 -0
- package/scripts/test_build_mode.js +301 -0
- package/src/db_adapter.ts +29 -0
- package/src/engine/session/build_mode.ts +895 -0
- package/src/engine/session/build_mode_helpers.ts +72 -0
- package/src/engine/session/prompt/bonescript.txt +402 -0
- package/src/engine/session/prompt.ts +105 -4
- package/src/tui.ts +147 -9
package/src/tui.ts
CHANGED
|
@@ -84,6 +84,7 @@ interface Command {
|
|
|
84
84
|
|
|
85
85
|
const COMMANDS: Command[] = [
|
|
86
86
|
{ name: "/new", description: "Start a new session" },
|
|
87
|
+
{ name: "/build", description: "Start autonomous build mode", args: "<project description>" },
|
|
87
88
|
{ name: "/session", description: "Show current session ID" },
|
|
88
89
|
{ name: "/sessions", description: "List recent sessions" },
|
|
89
90
|
{ name: "/model", description: "Switch model", args: "<provider/model>" },
|
|
@@ -702,6 +703,88 @@ async function streamPrompt(opts: {
|
|
|
702
703
|
nl(` ${BLUE}⊕ Context compacted${R}`);
|
|
703
704
|
continue;
|
|
704
705
|
}
|
|
706
|
+
|
|
707
|
+
// Build mode events — autonomous orchestration progress
|
|
708
|
+
if (ev.type === "session.warning") {
|
|
709
|
+
flushTextLine();
|
|
710
|
+
nl(` ${YELLOW}⚠ ${ev.message || ""}${R}`);
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
713
|
+
if (ev.type === "build.stage") {
|
|
714
|
+
flushTextLine();
|
|
715
|
+
const stage = (ev.stage || "?").toUpperCase();
|
|
716
|
+
nl(` ${CYAN}${BOLD}▶ Build stage: ${stage}${R}`);
|
|
717
|
+
continue;
|
|
718
|
+
}
|
|
719
|
+
if (ev.type === "build.questions") {
|
|
720
|
+
flushTextLine();
|
|
721
|
+
nl(` ${CYAN}${BOLD}? Clarifying questions:${R}`);
|
|
722
|
+
for (const q of ev.questions || []) {
|
|
723
|
+
nl(` ${WHITE}- ${q}${R}`);
|
|
724
|
+
}
|
|
725
|
+
nl(` ${GRAY}Reply with your answers to continue.${R}`);
|
|
726
|
+
continue;
|
|
727
|
+
}
|
|
728
|
+
if (ev.type === "build.design") {
|
|
729
|
+
flushTextLine();
|
|
730
|
+
const d = ev.design || {};
|
|
731
|
+
nl(` ${CYAN}${BOLD}✓ Design locked in${R}`);
|
|
732
|
+
if (d.goal) nl(` ${GRAY}goal: ${d.goal}${R}`);
|
|
733
|
+
if (Array.isArray(d.requirements)) nl(` ${GRAY}${d.requirements.length} requirement(s), ${d.artifacts?.length || 0} artifact(s)${R}`);
|
|
734
|
+
continue;
|
|
735
|
+
}
|
|
736
|
+
if (ev.type === "build.plan") {
|
|
737
|
+
flushTextLine();
|
|
738
|
+
const todos = ev.todos || [];
|
|
739
|
+
nl(` ${CYAN}${BOLD}✓ Plan: ${todos.length} task(s)${R}`);
|
|
740
|
+
for (let i = 0; i < Math.min(todos.length, 10); i++) {
|
|
741
|
+
const t = todos[i];
|
|
742
|
+
nl(` ${GRAY}${(i + 1).toString().padStart(2, " ")}. ${t.title}${R}`);
|
|
743
|
+
}
|
|
744
|
+
if (todos.length > 10) nl(` ${GRAY}... ${todos.length - 10} more${R}`);
|
|
745
|
+
continue;
|
|
746
|
+
}
|
|
747
|
+
if (ev.type === "build.todo.start") {
|
|
748
|
+
flushTextLine();
|
|
749
|
+
const t = ev.todo || {};
|
|
750
|
+
nl(` ${WHITE}● ${t.title || ""}${R}`);
|
|
751
|
+
continue;
|
|
752
|
+
}
|
|
753
|
+
if (ev.type === "build.todo.done") {
|
|
754
|
+
flushTextLine();
|
|
755
|
+
const t = ev.todo || {};
|
|
756
|
+
nl(` ${GREEN}✓ ${t.title || ""}${R}${t.evidence ? ` ${GRAY}(${t.evidence})${R}` : ""}`);
|
|
757
|
+
continue;
|
|
758
|
+
}
|
|
759
|
+
if (ev.type === "build.todo.retry") {
|
|
760
|
+
flushTextLine();
|
|
761
|
+
const t = ev.todo || {};
|
|
762
|
+
nl(` ${YELLOW}⟳ Retry ${ev.attempt || ""}: ${t.title || ""}${R}`);
|
|
763
|
+
continue;
|
|
764
|
+
}
|
|
765
|
+
if (ev.type === "build.todo.failed") {
|
|
766
|
+
flushTextLine();
|
|
767
|
+
const t = ev.todo || {};
|
|
768
|
+
nl(` ${RED}✗ ${t.title || ""}${R} ${GRAY}${ev.reason || ""}${R}`);
|
|
769
|
+
continue;
|
|
770
|
+
}
|
|
771
|
+
if (ev.type === "build.verify.item") {
|
|
772
|
+
flushTextLine();
|
|
773
|
+
const icon = ev.satisfied ? `${GREEN}✓${R}` : `${RED}✗${R}`;
|
|
774
|
+
nl(` ${icon} ${WHITE}${ev.requirement || ""}${R}`);
|
|
775
|
+
if (ev.evidence) nl(` ${GRAY}${ev.evidence}${R}`);
|
|
776
|
+
continue;
|
|
777
|
+
}
|
|
778
|
+
if (ev.type === "build.replan") {
|
|
779
|
+
flushTextLine();
|
|
780
|
+
nl(` ${YELLOW}↻ Re-planning: ${ev.added || 0} new task(s) to address gaps${R}`);
|
|
781
|
+
continue;
|
|
782
|
+
}
|
|
783
|
+
if (ev.type === "build.done") {
|
|
784
|
+
flushTextLine();
|
|
785
|
+
nl(` ${GREEN}${BOLD}✓✓ Build complete — all requirements satisfied${R}`);
|
|
786
|
+
continue;
|
|
787
|
+
}
|
|
705
788
|
} catch {
|
|
706
789
|
// Ignore malformed events
|
|
707
790
|
}
|
|
@@ -856,36 +939,62 @@ export async function runTUI(opts: {
|
|
|
856
939
|
const promptStr = () => `${CYAN}${BOLD}>${R} `;
|
|
857
940
|
|
|
858
941
|
// ─── Ctrl+C handling ──────────────────────────────────────────────────────
|
|
859
|
-
//
|
|
860
|
-
//
|
|
942
|
+
// Windows quirk: rl.on("SIGINT") only fires when readline is actively
|
|
943
|
+
// reading. We pause readline during streaming, which makes Ctrl+C dead.
|
|
944
|
+
// Use process.on("SIGINT") as the always-on handler so streaming aborts work.
|
|
945
|
+
|
|
946
|
+
let interruptCount = 0;
|
|
947
|
+
|
|
861
948
|
const onSigint = async () => {
|
|
862
949
|
if (streaming && abort) {
|
|
863
950
|
abort.abort();
|
|
864
|
-
//
|
|
951
|
+
// Tell the server to cancel the agent loop too
|
|
865
952
|
try {
|
|
866
953
|
await fetch(`http://localhost:${port}/v2/session/${sessionId}/cancel`, {
|
|
867
954
|
method: "POST",
|
|
868
955
|
headers: { "Authorization": `Bearer ${token}` },
|
|
869
956
|
});
|
|
870
957
|
} catch { /* server may not have the endpoint, abort is enough */ }
|
|
958
|
+
out(`\n${YELLOW}interrupted${R}\n`);
|
|
871
959
|
// Don't reprompt here — the streamPrompt finally block will handle UI
|
|
872
960
|
return;
|
|
873
961
|
}
|
|
874
962
|
|
|
875
|
-
|
|
963
|
+
interruptCount++;
|
|
964
|
+
|
|
965
|
+
// Idle: clear menu/input first, then on second Ctrl+C, exit
|
|
876
966
|
if (menu.visible) {
|
|
877
967
|
clearMenu(menu.rowsRendered);
|
|
878
968
|
menu.visible = false;
|
|
879
969
|
menu.rowsRendered = 0;
|
|
880
970
|
menu.selected = 0;
|
|
971
|
+
interruptCount = 0;
|
|
972
|
+
out(`\n${promptStr()}`);
|
|
973
|
+
return;
|
|
881
974
|
}
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
rl.
|
|
975
|
+
|
|
976
|
+
// If user typed something, clear it
|
|
977
|
+
const lineLen = ((rl as any).line || "").length;
|
|
978
|
+
if (lineLen > 0) {
|
|
979
|
+
(rl as any).line = "";
|
|
980
|
+
(rl as any).cursor = 0;
|
|
981
|
+
out(`\r${ESC}[2K${promptStr()}`);
|
|
982
|
+
interruptCount = 0;
|
|
983
|
+
return;
|
|
984
|
+
}
|
|
985
|
+
|
|
986
|
+
// Empty prompt + Ctrl+C: first time hint, second time exit
|
|
987
|
+
if (interruptCount >= 2) {
|
|
988
|
+
out(`\n${GRAY}Goodbye.${R}\n`);
|
|
989
|
+
process.exit(0);
|
|
990
|
+
}
|
|
991
|
+
out(`\n${GRAY}(Press Ctrl+C again or Ctrl+D to exit)${R}\n${promptStr()}`);
|
|
885
992
|
};
|
|
886
993
|
|
|
887
|
-
//
|
|
888
|
-
//
|
|
994
|
+
// Register on BOTH process and readline so it works during streaming AND
|
|
995
|
+
// during input. Process-level catches signals while rl is paused; readline
|
|
996
|
+
// catches them while the user is typing.
|
|
997
|
+
process.on("SIGINT", onSigint);
|
|
889
998
|
rl.on("SIGINT", onSigint);
|
|
890
999
|
|
|
891
1000
|
rl.on("close", () => {
|
|
@@ -1043,6 +1152,35 @@ export async function runTUI(opts: {
|
|
|
1043
1152
|
} catch (e: any) { nl(`${RED}✗ ${e.message}${R}`); }
|
|
1044
1153
|
break;
|
|
1045
1154
|
|
|
1155
|
+
case "build": {
|
|
1156
|
+
// /build <description> — start autonomous build mode for this prompt
|
|
1157
|
+
const description = args.join(" ").trim();
|
|
1158
|
+
if (!description) {
|
|
1159
|
+
nl(`${YELLOW}Usage:${R} /build <project description>`);
|
|
1160
|
+
nl(`${GRAY}Example: /build a 2D market simulation with 1000 shops over 100 years${R}`);
|
|
1161
|
+
break;
|
|
1162
|
+
}
|
|
1163
|
+
// Send the prompt prefixed with /build so the server enters build mode
|
|
1164
|
+
rl.pause();
|
|
1165
|
+
renderUserMessage(`/build ${description}`);
|
|
1166
|
+
out(` ${GRAY}entering build mode...${R}`);
|
|
1167
|
+
streaming = true;
|
|
1168
|
+
abort = new AbortController();
|
|
1169
|
+
const result = await streamPrompt({
|
|
1170
|
+
port, token, sessionId: sessionId!, model, provider,
|
|
1171
|
+
message: `/build ${description}`,
|
|
1172
|
+
worktree, abortSignal: abort.signal,
|
|
1173
|
+
});
|
|
1174
|
+
streaming = false;
|
|
1175
|
+
abort = null;
|
|
1176
|
+
if (!result.text && !result.error) clearLine();
|
|
1177
|
+
renderTurnEnd(model, result.elapsedMs, result.interrupted);
|
|
1178
|
+
if (result.error && !result.interrupted) nl(` ${RED}✗ ${result.error}${R}`);
|
|
1179
|
+
nl();
|
|
1180
|
+
rl.resume();
|
|
1181
|
+
break;
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1046
1184
|
case "session":
|
|
1047
1185
|
nl(`${GRAY}${sessionId}${R}`);
|
|
1048
1186
|
break;
|