@promptbook/cli 0.112.0-121 → 0.112.0-123
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/apps/agents-server/src/app/agents/[agentName]/api/user-chats/[chatId]/messages/route.ts +4 -11
- package/esm/index.es.js +1353 -277
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-codex-prompts/common/resolveAgentSystemMessage.d.ts +6 -0
- package/esm/scripts/run-codex-prompts/main/findUnwrittenPrompts.d.ts +19 -0
- package/esm/scripts/run-codex-prompts/main/runCodexPromptsServer.d.ts +27 -0
- package/esm/scripts/run-codex-prompts/main/runPromptRound.d.ts +2 -1
- package/esm/scripts/run-codex-prompts/server/coderServerHtml.d.ts +9 -0
- package/esm/scripts/run-codex-prompts/server/runCoderHttpServer.d.ts +23 -0
- package/esm/scripts/run-codex-prompts/server/updatePromptSection.d.ts +9 -0
- package/esm/src/cli/cli-commands/coder/find-unwritten.d.ts +10 -0
- package/esm/src/cli/cli-commands/coder/server.d.ts +13 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/cli/cli-commands/coder/find-unwritten.ts +58 -0
- package/src/cli/cli-commands/coder/init.ts +4 -1
- package/src/cli/cli-commands/coder/run.ts +26 -11
- package/src/cli/cli-commands/coder/server.ts +239 -0
- package/src/cli/cli-commands/coder.ts +6 -0
- package/src/other/templates/getTemplatesPipelineCollection.ts +825 -1034
- package/src/version.ts +2 -2
- package/src/versions.txt +2 -1
- package/umd/index.umd.js +1355 -279
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-codex-prompts/common/resolveAgentSystemMessage.d.ts +6 -0
- package/umd/scripts/run-codex-prompts/main/findUnwrittenPrompts.d.ts +19 -0
- package/umd/scripts/run-codex-prompts/main/runCodexPromptsServer.d.ts +27 -0
- package/umd/scripts/run-codex-prompts/main/runPromptRound.d.ts +2 -1
- package/umd/scripts/run-codex-prompts/server/coderServerHtml.d.ts +9 -0
- package/umd/scripts/run-codex-prompts/server/runCoderHttpServer.d.ts +23 -0
- package/umd/scripts/run-codex-prompts/server/updatePromptSection.d.ts +9 -0
- package/umd/src/cli/cli-commands/coder/find-unwritten.d.ts +10 -0
- package/umd/src/cli/cli-commands/coder/server.d.ts +13 -0
- package/umd/src/version.d.ts +1 -1
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads an optional agent `.book` file and compiles its system message for injection into coder prompts.
|
|
3
|
+
*
|
|
4
|
+
* Returns `undefined` when no agent path is provided.
|
|
5
|
+
*/
|
|
6
|
+
export declare function resolveAgentSystemMessage(agentPath: string | undefined, currentWorkingDirectory: string): Promise<string | undefined>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options for `findUnwrittenPrompts`.
|
|
3
|
+
*/
|
|
4
|
+
export type FindUnwrittenPromptsOptions = {
|
|
5
|
+
/**
|
|
6
|
+
* Minimum priority level — sections below this threshold are excluded.
|
|
7
|
+
* @default 0
|
|
8
|
+
*/
|
|
9
|
+
readonly priority?: number;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Lists and prints all prompt sections that still need to be authored (contain `@@@` placeholder).
|
|
13
|
+
*
|
|
14
|
+
* Reuses the same filtering logic as `ptbk coder run --dry-run`.
|
|
15
|
+
*
|
|
16
|
+
* @returns the number of unwritten prompts found
|
|
17
|
+
* @public exported from `@promptbook/cli`
|
|
18
|
+
*/
|
|
19
|
+
export declare function findUnwrittenPrompts(options?: FindUnwrittenPromptsOptions): Promise<number>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { number_port } from '../../../src/types/number_positive';
|
|
2
|
+
import type { RunOptions } from '../cli/RunOptions';
|
|
3
|
+
/**
|
|
4
|
+
* Options for `ptbk coder server` combining the standard run options with a server port.
|
|
5
|
+
*
|
|
6
|
+
* @private internal type of `ptbk coder server`
|
|
7
|
+
*/
|
|
8
|
+
export type CoderServerRunOptions = RunOptions & {
|
|
9
|
+
/**
|
|
10
|
+
* TCP port on which the kanban HTTP server will listen.
|
|
11
|
+
*/
|
|
12
|
+
port: number_port;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Starts the coder server: runs prompt processing in keepAlive mode while serving a
|
|
16
|
+
* kanban web UI and REST API on the given port.
|
|
17
|
+
*
|
|
18
|
+
* Differences from `runCodexPrompts`:
|
|
19
|
+
* - Does not exit when no runnable prompts are available; instead it polls every few seconds
|
|
20
|
+
* and resumes processing as soon as a new prompt becomes ready.
|
|
21
|
+
* - Starts a lightweight HTTP server that serves a kanban board at `http://localhost:<port>`
|
|
22
|
+
* and exposes REST endpoints for reading prompts, controlling pause state, and editing
|
|
23
|
+
* prompt files directly from the browser.
|
|
24
|
+
*
|
|
25
|
+
* @private internal function of `ptbk coder server`
|
|
26
|
+
*/
|
|
27
|
+
export declare function runCodexPromptsServer(options: CoderServerRunOptions): Promise<void>;
|
|
@@ -17,6 +17,7 @@ type RunPromptRoundOptions = {
|
|
|
17
17
|
nextPrompt: PromptSelection;
|
|
18
18
|
promptLabel: string;
|
|
19
19
|
resolvedCoderContext?: string;
|
|
20
|
+
resolvedAgentSystemMessage?: string;
|
|
20
21
|
isRichUiEnabled: boolean;
|
|
21
22
|
progressDisplay?: CliProgressDisplay;
|
|
22
23
|
uiHandle?: CoderRunUiHandle;
|
|
@@ -27,5 +28,5 @@ type RunPromptRoundOptions = {
|
|
|
27
28
|
*
|
|
28
29
|
* @private function of runCodexPrompts
|
|
29
30
|
*/
|
|
30
|
-
export declare function runPromptRound({ options, runner, runnerMetadata, nextPrompt, promptLabel, resolvedCoderContext, isRichUiEnabled, progressDisplay, uiHandle, waitForRequestedPause, }: RunPromptRoundOptions): Promise<void>;
|
|
31
|
+
export declare function runPromptRound({ options, runner, runnerMetadata, nextPrompt, promptLabel, resolvedCoderContext, resolvedAgentSystemMessage, isRichUiEnabled, progressDisplay, uiHandle, waitForRequestedPause, }: RunPromptRoundOptions): Promise<void>;
|
|
31
32
|
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTML source for the coder server kanban UI.
|
|
3
|
+
*
|
|
4
|
+
* The canonical source lives in `apps/coder-server/index.html`.
|
|
5
|
+
* Keep both files in sync when updating the frontend.
|
|
6
|
+
*
|
|
7
|
+
* @private internal constant of `ptbk coder server`
|
|
8
|
+
*/
|
|
9
|
+
export declare const CODER_SERVER_HTML = "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Ptbk Coder Server</title>\n <style>\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n background: #f4f5f7;\n color: #172b4d;\n min-height: 100vh;\n }\n\n header {\n background: #0052cc;\n color: white;\n padding: 12px 20px;\n display: flex;\n align-items: center;\n gap: 12px;\n position: sticky;\n top: 0;\n z-index: 10;\n box-shadow: 0 2px 8px rgba(0,0,0,0.2);\n }\n header h1 { font-size: 17px; font-weight: 700; flex-shrink: 0; }\n\n .status-badge {\n padding: 3px 10px;\n border-radius: 12px;\n font-size: 11px;\n font-weight: 700;\n letter-spacing: 0.5px;\n text-transform: uppercase;\n flex-shrink: 0;\n }\n .status-RUNNING { background: #00875a; color: white; }\n .status-PAUSING { background: #ff8b00; color: white; }\n .status-PAUSED { background: #bf2600; color: white; }\n\n #pause-label {\n font-size: 12px;\n color: rgba(255,255,255,0.75);\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .btn {\n padding: 6px 14px;\n border: none;\n border-radius: 4px;\n cursor: pointer;\n font-size: 13px;\n font-weight: 600;\n transition: opacity 0.15s;\n flex-shrink: 0;\n }\n .btn:hover { opacity: 0.85; }\n .btn-pause { background: #ffc400; color: #172b4d; }\n .btn-resume { background: #00875a; color: white; }\n\n .board {\n display: flex;\n gap: 14px;\n padding: 16px;\n overflow-x: auto;\n min-height: calc(100vh - 52px);\n align-items: flex-start;\n }\n\n .column {\n background: #ebecf0;\n border-radius: 8px;\n padding: 10px;\n min-width: 250px;\n width: 270px;\n flex-shrink: 0;\n }\n\n .column-header {\n font-size: 12px;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.6px;\n color: #5e6c84;\n margin-bottom: 10px;\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .column-count {\n background: #dfe1e6;\n border-radius: 10px;\n padding: 1px 7px;\n font-size: 11px;\n color: #5e6c84;\n }\n\n .column-cards { min-height: 40px; }\n\n .card {\n background: white;\n border-radius: 6px;\n padding: 10px 12px;\n margin-bottom: 8px;\n box-shadow: 0 1px 3px rgba(0,0,0,0.08);\n cursor: pointer;\n transition: box-shadow 0.15s, transform 0.1s;\n border-left: 3px solid transparent;\n }\n .card:hover {\n box-shadow: 0 4px 10px rgba(0,0,0,0.14);\n transform: translateY(-1px);\n }\n .card-todo { border-left-color: #0052cc; }\n .card-not-ready { border-left-color: #8993a4; }\n .card-done { border-left-color: #00875a; }\n .card-failed { border-left-color: #bf2600; }\n\n .card-file {\n font-size: 10px;\n color: #8993a4;\n margin-bottom: 5px;\n font-weight: 500;\n }\n\n .card-summary {\n font-size: 13px;\n line-height: 1.5;\n color: #172b4d;\n word-break: break-word;\n white-space: pre-wrap;\n max-height: 78px;\n overflow: hidden;\n display: -webkit-box;\n -webkit-line-clamp: 4;\n -webkit-box-orient: vertical;\n }\n\n .card-priority {\n margin-top: 6px;\n color: #ff8b00;\n font-size: 11px;\n font-weight: 700;\n }\n\n .card-edit-hint {\n font-size: 10px;\n color: #c1c7d0;\n margin-top: 6px;\n display: none;\n }\n .card:hover .card-edit-hint { display: block; }\n\n .empty-column {\n color: #b3bac5;\n font-size: 12px;\n padding: 10px 4px;\n text-align: center;\n }\n\n .modal-overlay {\n position: fixed;\n inset: 0;\n background: rgba(9,30,66,0.54);\n display: flex;\n align-items: flex-start;\n justify-content: center;\n padding: 60px 16px 16px;\n z-index: 100;\n animation: fadeIn 0.1s ease;\n }\n .modal-overlay.hidden { display: none; }\n\n @keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }\n\n .modal {\n background: white;\n border-radius: 8px;\n width: 100%;\n max-width: 620px;\n padding: 20px;\n box-shadow: 0 8px 32px rgba(0,0,0,0.25);\n animation: slideIn 0.15s ease;\n }\n @keyframes slideIn { from { transform: translateY(-8px); opacity: 0; } to { transform: none; opacity: 1; } }\n\n .modal-header {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n margin-bottom: 14px;\n gap: 12px;\n }\n\n .modal-meta { flex: 1; min-width: 0; }\n .modal-file { font-size: 11px; color: #8993a4; margin-bottom: 4px; }\n .modal-section-label { font-size: 13px; font-weight: 600; color: #172b4d; }\n\n .modal-status {\n font-size: 11px;\n font-weight: 700;\n padding: 2px 8px;\n border-radius: 10px;\n text-transform: uppercase;\n letter-spacing: 0.4px;\n flex-shrink: 0;\n }\n .status-todo { background: #deebff; color: #0052cc; }\n .status-not-ready { background: #f4f5f7; color: #5e6c84; }\n .status-done { background: #e3fcef; color: #006644; }\n .status-failed { background: #ffebe6; color: #bf2600; }\n\n .modal-close {\n background: none;\n border: none;\n color: #8993a4;\n cursor: pointer;\n font-size: 18px;\n padding: 0 4px;\n line-height: 1;\n flex-shrink: 0;\n }\n .modal-close:hover { color: #172b4d; }\n\n textarea {\n width: 100%;\n min-height: 220px;\n font-family: 'SFMono-Regular', 'Consolas', 'Courier New', monospace;\n font-size: 13px;\n border: 2px solid #dfe1e6;\n border-radius: 4px;\n padding: 10px 12px;\n resize: vertical;\n line-height: 1.65;\n color: #172b4d;\n transition: border-color 0.15s;\n }\n textarea:focus {\n outline: none;\n border-color: #0052cc;\n box-shadow: 0 0 0 3px rgba(0,82,204,0.12);\n }\n\n .modal-hint {\n font-size: 11px;\n color: #8993a4;\n margin-top: 6px;\n }\n\n .modal-actions {\n display: flex;\n gap: 8px;\n margin-top: 14px;\n justify-content: flex-end;\n }\n\n .btn-save { background: #0052cc; color: white; }\n .btn-cancel { background: #f4f5f7; color: #172b4d; }\n .btn-cancel:hover { background: #ebecf0; opacity: 1; }\n\n .error-banner {\n background: #ffebe6;\n border-bottom: 2px solid #bf2600;\n color: #bf2600;\n padding: 8px 20px;\n font-size: 13px;\n font-weight: 500;\n }\n .error-banner.hidden { display: none; }\n </style>\n</head>\n<body>\n\n <div id=\"error-banner\" class=\"error-banner hidden\"></div>\n\n <header>\n <h1>🔧 Ptbk Coder Server</h1>\n <span id=\"status-badge\" class=\"status-badge status-RUNNING\">RUNNING</span>\n <span id=\"pause-label\"></span>\n <button id=\"toggle-btn\" class=\"btn btn-pause\">▮▮ Pause</button>\n </header>\n\n <div class=\"board\">\n <div class=\"column\">\n <div class=\"column-header\">\n To Do\n <span class=\"column-count\" id=\"count-todo\">0</span>\n </div>\n <div class=\"column-cards\" id=\"cards-todo\">\n <div class=\"empty-column\">Loading…</div>\n </div>\n </div>\n\n <div class=\"column\">\n <div class=\"column-header\">\n Not Ready\n <span class=\"column-count\" id=\"count-not-ready\">0</span>\n </div>\n <div class=\"column-cards\" id=\"cards-not-ready\"></div>\n </div>\n\n <div class=\"column\">\n <div class=\"column-header\">\n Done\n <span class=\"column-count\" id=\"count-done\">0</span>\n </div>\n <div class=\"column-cards\" id=\"cards-done\"></div>\n </div>\n\n <div class=\"column\">\n <div class=\"column-header\">\n Failed\n <span class=\"column-count\" id=\"count-failed\">0</span>\n </div>\n <div class=\"column-cards\" id=\"cards-failed\"></div>\n </div>\n </div>\n\n <div class=\"modal-overlay hidden\" id=\"modal-overlay\">\n <div class=\"modal\">\n <div class=\"modal-header\">\n <div class=\"modal-meta\">\n <div class=\"modal-file\" id=\"modal-file\"></div>\n <div class=\"modal-section-label\" id=\"modal-section-label\"></div>\n </div>\n <span class=\"modal-status\" id=\"modal-status-badge\"></span>\n <button class=\"modal-close\" onclick=\"closeModal()\" title=\"Close (Esc)\">✕</button>\n </div>\n\n <textarea id=\"modal-content\" placeholder=\"Prompt content…\"></textarea>\n <div class=\"modal-hint\">Tip: press Ctrl+Enter to save, Esc to cancel.</div>\n\n <div class=\"modal-actions\">\n <button class=\"btn btn-cancel\" onclick=\"closeModal()\">Cancel</button>\n <button class=\"btn btn-save\" onclick=\"saveModal()\">Save</button>\n </div>\n </div>\n </div>\n\n <script>\n 'use strict';\n\n let modalState = null;\n let lastPauseState = 'RUNNING';\n\n function showError(msg) {\n const banner = document.getElementById('error-banner');\n banner.textContent = '\\u26a0 ' + msg;\n banner.classList.remove('hidden');\n clearTimeout(banner._timer);\n banner._timer = setTimeout(() => banner.classList.add('hidden'), 6000);\n }\n\n function escapeHtml(str) {\n const d = document.createElement('div');\n d.textContent = String(str);\n return d.innerHTML;\n }\n\n async function fetchStatus() {\n try {\n const res = await fetch('/api/status');\n if (!res.ok) { showError('Status API error: ' + res.status); return; }\n const data = await res.json();\n\n lastPauseState = data.pauseState;\n\n const badge = document.getElementById('status-badge');\n badge.textContent = data.pauseState;\n badge.className = 'status-badge status-' + data.pauseState;\n\n const btn = document.getElementById('toggle-btn');\n const label = document.getElementById('pause-label');\n\n if (data.pauseState === 'RUNNING') {\n btn.textContent = '\\u23f8 Pause';\n btn.className = 'btn btn-pause';\n label.textContent = '';\n } else if (data.pauseState === 'PAUSING') {\n btn.textContent = '\\u23f5 Resume';\n btn.className = 'btn btn-resume';\n label.textContent = 'Pausing before: ' + (data.pauseTargetLabel || '\\u2026');\n } else {\n btn.textContent = '\\u23f5 Resume';\n btn.className = 'btn btn-resume';\n label.textContent = 'Paused before: ' + (data.pauseTargetLabel || '\\u2026');\n }\n } catch (e) {\n showError('Could not reach coder server: ' + e.message);\n }\n }\n\n async function fetchPrompts() {\n try {\n const res = await fetch('/api/prompts');\n if (!res.ok) { showError('Prompts API error: ' + res.status); return; }\n renderBoard(await res.json());\n } catch (e) {\n showError('Could not load prompts: ' + e.message);\n }\n }\n\n function renderBoard(promptFiles) {\n const columns = { 'todo': [], 'not-ready': [], 'done': [], 'failed': [] };\n\n for (const file of promptFiles) {\n for (const section of file.sections) {\n const col = columns[section.status];\n if (col) col.push({ file, section });\n }\n }\n\n for (const [status, cards] of Object.entries(columns)) {\n const container = document.getElementById('cards-' + status);\n const countEl = document.getElementById('count-' + status);\n if (!container) continue;\n\n countEl.textContent = cards.length;\n container.innerHTML = '';\n\n if (cards.length === 0) {\n container.innerHTML = '<div class=\"empty-column\">Empty</div>';\n continue;\n }\n\n for (const { file, section } of cards) {\n const card = document.createElement('div');\n card.className = 'card card-' + section.status;\n card.innerHTML =\n '<div class=\"card-file\">' + escapeHtml(file.fileName) + ' • #' + (section.index + 1) + '</div>' +\n '<div class=\"card-summary\">' + escapeHtml(section.summary) + '</div>' +\n (section.priority > 0\n ? '<div class=\"card-priority\">' + '!'.repeat(section.priority) + ' priority ' + section.priority + '</div>'\n : '') +\n '<div class=\"card-edit-hint\">Click to edit</div>';\n card.onclick = () => openModal(file, section);\n container.appendChild(card);\n }\n }\n }\n\n function openModal(file, section) {\n modalState = { filePath: file.filePath, sectionIndex: section.index };\n\n document.getElementById('modal-file').textContent = file.fileName;\n document.getElementById('modal-section-label').textContent = 'Section ' + (section.index + 1);\n\n const badge = document.getElementById('modal-status-badge');\n badge.textContent = section.status.replace('-', '\\u2011');\n badge.className = 'modal-status status-' + section.status;\n\n document.getElementById('modal-content').value = section.content;\n document.getElementById('modal-overlay').classList.remove('hidden');\n setTimeout(() => document.getElementById('modal-content').focus(), 50);\n }\n\n function closeModal() {\n document.getElementById('modal-overlay').classList.add('hidden');\n modalState = null;\n }\n\n async function saveModal() {\n if (!modalState) return;\n\n const content = document.getElementById('modal-content').value;\n const saveBtn = document.querySelector('.btn-save');\n saveBtn.disabled = true;\n saveBtn.textContent = 'Saving\\u2026';\n\n try {\n const res = await fetch('/api/prompts/update', {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n filePath: modalState.filePath,\n sectionIndex: modalState.sectionIndex,\n content,\n }),\n });\n if (!res.ok) throw new Error('HTTP ' + res.status);\n closeModal();\n fetchPrompts();\n } catch (e) {\n showError('Save failed: ' + e.message);\n } finally {\n saveBtn.disabled = false;\n saveBtn.textContent = 'Save';\n }\n }\n\n document.getElementById('toggle-btn').onclick = async () => {\n try {\n const endpoint = lastPauseState === 'RUNNING' ? '/api/pause' : '/api/resume';\n await fetch(endpoint, { method: 'POST' });\n await fetchStatus();\n } catch (e) {\n showError('Toggle failed: ' + e.message);\n }\n };\n\n document.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') { closeModal(); return; }\n if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') { saveModal(); return; }\n });\n\n document.getElementById('modal-overlay').addEventListener('click', (e) => {\n if (e.target === document.getElementById('modal-overlay')) closeModal();\n });\n\n fetchStatus();\n fetchPrompts();\n setInterval(fetchStatus, 2000);\n setInterval(fetchPrompts, 5000);\n </script>\n</body>\n</html>";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { number_port } from '../../../src/types/number_positive';
|
|
2
|
+
/**
|
|
3
|
+
* Handle returned by the running coder HTTP server.
|
|
4
|
+
*
|
|
5
|
+
* @private internal type of `ptbk coder server`
|
|
6
|
+
*/
|
|
7
|
+
export type CoderHttpServerHandle = {
|
|
8
|
+
close: () => void;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Starts the lightweight HTTP server that serves the coder kanban UI and REST API.
|
|
12
|
+
*
|
|
13
|
+
* API endpoints:
|
|
14
|
+
* - `GET /` → HTML kanban page
|
|
15
|
+
* - `GET /api/prompts` → JSON list of all prompt files and sections
|
|
16
|
+
* - `GET /api/status` → JSON current pause state
|
|
17
|
+
* - `POST /api/pause` → request pause
|
|
18
|
+
* - `POST /api/resume` → request resume
|
|
19
|
+
* - `PUT /api/prompts/update` → update prompt section content
|
|
20
|
+
*
|
|
21
|
+
* @private internal utility of `ptbk coder server`
|
|
22
|
+
*/
|
|
23
|
+
export declare function startCoderHttpServer(port: number_port): CoderHttpServerHandle;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Overwrites the body of one prompt section with new content, preserving the status line.
|
|
3
|
+
*
|
|
4
|
+
* The `newContent` string is the prompt text without the status marker.
|
|
5
|
+
* The status line (`[ ]`, `[x]`, `[!]`, `[-]`) is kept intact.
|
|
6
|
+
*
|
|
7
|
+
* @private internal utility of `ptbk coder server`
|
|
8
|
+
*/
|
|
9
|
+
export declare function updatePromptSection(filePath: string, sectionIndex: number, newContent: string): Promise<void>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command as Program } from 'commander';
|
|
2
|
+
import type { $side_effect } from '../../../utils/organization/$side_effect';
|
|
3
|
+
/**
|
|
4
|
+
* Initializes `coder find-unwritten` command for Promptbook CLI utilities
|
|
5
|
+
*
|
|
6
|
+
* Note: `$` is used to indicate that this function is not a pure function - it registers a command in the CLI
|
|
7
|
+
*
|
|
8
|
+
* @private internal function of `promptbookCli`
|
|
9
|
+
*/
|
|
10
|
+
export declare function $initializeCoderFindUnwrittenCommand(program: Program): $side_effect;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Command as Program } from 'commander';
|
|
2
|
+
import type { $side_effect } from '../../../utils/organization/$side_effect';
|
|
3
|
+
/**
|
|
4
|
+
* Initializes `coder server` command for Promptbook CLI utilities.
|
|
5
|
+
*
|
|
6
|
+
* Runs the same prompt processing logic as `ptbk coder run` but keeps the process alive
|
|
7
|
+
* and serves a kanban web UI on the configured port.
|
|
8
|
+
*
|
|
9
|
+
* Note: `$` is used to indicate that this function is not a pure function - it registers a command in the CLI
|
|
10
|
+
*
|
|
11
|
+
* @private internal function of `promptbookCli`
|
|
12
|
+
*/
|
|
13
|
+
export declare function $initializeCoderServerCommand(program: Program): $side_effect;
|
package/esm/src/version.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare const BOOK_LANGUAGE_VERSION: string_semantic_version;
|
|
|
15
15
|
export declare const PROMPTBOOK_ENGINE_VERSION: string_promptbook_version;
|
|
16
16
|
/**
|
|
17
17
|
* Represents the version string of the Promptbook engine.
|
|
18
|
-
* It follows semantic versioning (e.g., `0.112.0-
|
|
18
|
+
* It follows semantic versioning (e.g., `0.112.0-122`).
|
|
19
19
|
*
|
|
20
20
|
* @generated
|
|
21
21
|
*/
|
package/package.json
CHANGED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import colors from 'colors';
|
|
2
|
+
import { Command as Program /* <- Note: [🔸] Using Program because Command is misleading name */ } from 'commander';
|
|
3
|
+
import { assertsError } from '../../../errors/assertsError';
|
|
4
|
+
import type { $side_effect } from '../../../utils/organization/$side_effect';
|
|
5
|
+
import { handleActionErrors } from '../common/handleActionErrors';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Initializes `coder find-unwritten` command for Promptbook CLI utilities
|
|
9
|
+
*
|
|
10
|
+
* Note: `$` is used to indicate that this function is not a pure function - it registers a command in the CLI
|
|
11
|
+
*
|
|
12
|
+
* @private internal function of `promptbookCli`
|
|
13
|
+
*/
|
|
14
|
+
export function $initializeCoderFindUnwrittenCommand(program: Program): $side_effect {
|
|
15
|
+
const command = program.command('find-unwritten');
|
|
16
|
+
command.description('List all prompt sections that still need to be authored (contain @@@ placeholder)');
|
|
17
|
+
command.option('--priority <minimum-priority>', 'Filter prompts by minimum priority level', parseIntOption, 0);
|
|
18
|
+
|
|
19
|
+
command.action(
|
|
20
|
+
handleActionErrors(async (cliOptions) => {
|
|
21
|
+
const { priority = 0 } = cliOptions as {
|
|
22
|
+
readonly priority?: number;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Note: Import the function dynamically to avoid loading heavy dependencies until needed
|
|
26
|
+
const { findUnwrittenPrompts } = await import(
|
|
27
|
+
'../../../../scripts/run-codex-prompts/main/findUnwrittenPrompts'
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
await findUnwrittenPrompts({ priority });
|
|
32
|
+
} catch (error) {
|
|
33
|
+
assertsError(error);
|
|
34
|
+
console.error(colors.bgRed(`${error.name}`));
|
|
35
|
+
console.error(colors.red(error.stack || error.message));
|
|
36
|
+
return process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return process.exit(0);
|
|
40
|
+
}),
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Parses an integer option value
|
|
46
|
+
*
|
|
47
|
+
* @private internal utility of `coder find-unwritten` command
|
|
48
|
+
*/
|
|
49
|
+
function parseIntOption(value: string): number {
|
|
50
|
+
const parsed = parseInt(value, 10);
|
|
51
|
+
if (isNaN(parsed)) {
|
|
52
|
+
throw new Error(`Invalid number: ${value}`);
|
|
53
|
+
}
|
|
54
|
+
return parsed;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Note: [🟡] Code for CLI command [find-unwritten](src/cli/cli-commands/coder/find-unwritten.ts) should never be published outside of `@promptbook/cli`
|
|
58
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -8,6 +8,7 @@ import { AGENT_CODING_FILE_PATH } from './agentCodingFile';
|
|
|
8
8
|
import { AGENTS_FILE_PATH } from './agentsFile';
|
|
9
9
|
import { getDefaultCoderProjectPromptTemplateDefinitions } from './boilerplateTemplates';
|
|
10
10
|
import { formatDisplayPath } from './formatDisplayPath';
|
|
11
|
+
import { generatePromptBoilerplate } from './generate-boilerplates';
|
|
11
12
|
import { initializeCoderProjectConfiguration } from './initializeCoderProjectConfiguration';
|
|
12
13
|
import { printInitializationSummary } from './printInitializationSummary';
|
|
13
14
|
|
|
@@ -48,8 +49,10 @@ export function $initializeCoderInitCommand(program: Program): $side_effect {
|
|
|
48
49
|
|
|
49
50
|
command.action(
|
|
50
51
|
handleActionErrors(async () => {
|
|
51
|
-
const
|
|
52
|
+
const projectPath = process.cwd();
|
|
53
|
+
const summary = await initializeCoderProjectConfiguration(projectPath);
|
|
52
54
|
printInitializationSummary(summary);
|
|
55
|
+
await generatePromptBoilerplate({ projectPath, filesCount: 5 });
|
|
53
56
|
}),
|
|
54
57
|
);
|
|
55
58
|
}
|
|
@@ -43,6 +43,10 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
|
|
|
43
43
|
|
|
44
44
|
command.option('--dry-run', 'Print unwritten prompts without executing', false);
|
|
45
45
|
addPromptRunnerSelectionOptions(command);
|
|
46
|
+
command.option(
|
|
47
|
+
'--agent <agent-book-path>',
|
|
48
|
+
'Path to a .book file whose compiled system message is prepended to each coding prompt',
|
|
49
|
+
);
|
|
46
50
|
command.option(
|
|
47
51
|
'--context <context-or-file>',
|
|
48
52
|
'Append extra instructions either inline or from a file path relative to the current project',
|
|
@@ -80,17 +84,27 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
|
|
|
80
84
|
|
|
81
85
|
command.action(
|
|
82
86
|
handleActionErrors(async (cliOptions) => {
|
|
83
|
-
const {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
87
|
+
const {
|
|
88
|
+
dryRun,
|
|
89
|
+
agent,
|
|
90
|
+
context,
|
|
91
|
+
test,
|
|
92
|
+
preserveLogs,
|
|
93
|
+
priority,
|
|
94
|
+
wait,
|
|
95
|
+
autoMigrate,
|
|
96
|
+
allowDestructiveAutoMigrate,
|
|
97
|
+
} = cliOptions as {
|
|
98
|
+
readonly dryRun: boolean;
|
|
99
|
+
readonly agent?: string;
|
|
100
|
+
readonly context?: string;
|
|
101
|
+
readonly test?: string | string[];
|
|
102
|
+
readonly preserveLogs: boolean;
|
|
103
|
+
readonly priority: number;
|
|
104
|
+
readonly wait: boolean | string;
|
|
105
|
+
readonly autoMigrate: boolean;
|
|
106
|
+
readonly allowDestructiveAutoMigrate: boolean;
|
|
107
|
+
} & PromptRunnerCliOptions;
|
|
94
108
|
|
|
95
109
|
const testCommand = normalizeCommandOptionValue(test);
|
|
96
110
|
const runnerOptions = normalizePromptRunnerCliOptions(cliOptions as PromptRunnerCliOptions, {
|
|
@@ -119,6 +133,7 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
|
|
|
119
133
|
ignoreGitChanges: runnerOptions.ignoreGitChanges,
|
|
120
134
|
agentName: runnerOptions.agentName,
|
|
121
135
|
model: runnerOptions.model,
|
|
136
|
+
agent,
|
|
122
137
|
context,
|
|
123
138
|
testCommand,
|
|
124
139
|
preserveLogs,
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
import colors from 'colors';
|
|
2
|
+
import { Command as Program /* <- Note: [🔸] Using Program because Command is misleading name */ } from 'commander';
|
|
3
|
+
import { Option } from 'commander';
|
|
4
|
+
import { spaceTrim } from 'spacetrim';
|
|
5
|
+
import { NETWORK_LIMITS } from '../../../constants';
|
|
6
|
+
import { assertsError } from '../../../errors/assertsError';
|
|
7
|
+
import { NotAllowed } from '../../../errors/NotAllowed';
|
|
8
|
+
import type { number_port } from '../../../types/number_positive';
|
|
9
|
+
import type { $side_effect } from '../../../utils/organization/$side_effect';
|
|
10
|
+
import { handleActionErrors } from '../common/handleActionErrors';
|
|
11
|
+
import type { PromptRunnerCliOptions } from '../common/promptRunnerCliOptions';
|
|
12
|
+
import {
|
|
13
|
+
addPromptRunnerExecutionOptions,
|
|
14
|
+
addPromptRunnerSelectionOptions,
|
|
15
|
+
normalizePromptRunnerCliOptions,
|
|
16
|
+
PROMPT_RUNNER_DESCRIPTION,
|
|
17
|
+
} from '../common/promptRunnerCliOptions';
|
|
18
|
+
import { parseDuration } from '../../../../scripts/run-codex-prompts/common/parseDuration';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Default port used by `ptbk coder server`.
|
|
22
|
+
*
|
|
23
|
+
* @private internal constant of `ptbk coder server`
|
|
24
|
+
*/
|
|
25
|
+
const DEFAULT_CODER_SERVER_PORT = '4441';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Initializes `coder server` command for Promptbook CLI utilities.
|
|
29
|
+
*
|
|
30
|
+
* Runs the same prompt processing logic as `ptbk coder run` but keeps the process alive
|
|
31
|
+
* and serves a kanban web UI on the configured port.
|
|
32
|
+
*
|
|
33
|
+
* Note: `$` is used to indicate that this function is not a pure function - it registers a command in the CLI
|
|
34
|
+
*
|
|
35
|
+
* @private internal function of `promptbookCli`
|
|
36
|
+
*/
|
|
37
|
+
export function $initializeCoderServerCommand(program: Program): $side_effect {
|
|
38
|
+
const command = program.command('server');
|
|
39
|
+
command.description(
|
|
40
|
+
spaceTrim(`
|
|
41
|
+
Start a coder server that watches for prompts and serves a kanban web UI
|
|
42
|
+
|
|
43
|
+
${PROMPT_RUNNER_DESCRIPTION}
|
|
44
|
+
|
|
45
|
+
Features:
|
|
46
|
+
- Runs the same prompt processing as \`ptbk coder run\`
|
|
47
|
+
- Does not exit when all prompts are done; polls for new prompt files instead
|
|
48
|
+
- Serves a kanban board at http://localhost:<port> for visual progress tracking
|
|
49
|
+
- Allows editing prompt files directly from the browser (Trello-style)
|
|
50
|
+
- Play / pause button in the browser stays in sync with the CLI pause state
|
|
51
|
+
- Press "p" in the terminal to pause / resume (same as \`ptbk coder run\`)
|
|
52
|
+
`),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
command.addOption(
|
|
56
|
+
new Option('--port <port>', 'Port to start the coder server on')
|
|
57
|
+
.env('PTBK_CODER_SERVER_PORT')
|
|
58
|
+
.default(DEFAULT_CODER_SERVER_PORT),
|
|
59
|
+
);
|
|
60
|
+
command.option('--dry-run', 'Print unwritten prompts without executing', false);
|
|
61
|
+
addPromptRunnerSelectionOptions(command);
|
|
62
|
+
command.option(
|
|
63
|
+
'--agent <agent-book-path>',
|
|
64
|
+
'Path to a .book file whose compiled system message is prepended to each coding prompt',
|
|
65
|
+
);
|
|
66
|
+
command.option(
|
|
67
|
+
'--context <context-or-file>',
|
|
68
|
+
'Append extra instructions either inline or from a file path relative to the current project',
|
|
69
|
+
);
|
|
70
|
+
command.option(
|
|
71
|
+
'--test <test-command...>',
|
|
72
|
+
'Run a verification command after each prompt; quote it when the command itself contains top-level flags',
|
|
73
|
+
);
|
|
74
|
+
command.option(
|
|
75
|
+
'--preserve-logs',
|
|
76
|
+
'Keep generated temp prompt/log artifacts after successful rounds for debugging and analytics',
|
|
77
|
+
false,
|
|
78
|
+
);
|
|
79
|
+
addPromptRunnerExecutionOptions(command);
|
|
80
|
+
command.option('--priority <minimum-priority>', 'Filter prompts by minimum priority level', parseIntOption, 0);
|
|
81
|
+
command.option(
|
|
82
|
+
'--wait [duration]',
|
|
83
|
+
spaceTrim(`
|
|
84
|
+
Wait between prompt rounds.
|
|
85
|
+
Without a value (default): waits for user confirmation before each prompt (interactive mode).
|
|
86
|
+
With a duration like 1h, 30m, 5s: waits that long between prompts to avoid hitting rate limits of the harness.
|
|
87
|
+
`),
|
|
88
|
+
true,
|
|
89
|
+
);
|
|
90
|
+
command.option('--no-wait', 'Skip all waiting between prompts and run non-interactively');
|
|
91
|
+
command.option(
|
|
92
|
+
'--auto-migrate',
|
|
93
|
+
'Run testing-server database migrations automatically after each successfully processed prompt',
|
|
94
|
+
);
|
|
95
|
+
command.option(
|
|
96
|
+
'--allow-destructive-auto-migrate',
|
|
97
|
+
'Allow auto-migrate even when heuristic SQL safety check flags destructive pending migrations',
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
command.action(
|
|
101
|
+
handleActionErrors(async (cliOptions) => {
|
|
102
|
+
const {
|
|
103
|
+
port: rawPort,
|
|
104
|
+
dryRun,
|
|
105
|
+
agent,
|
|
106
|
+
context,
|
|
107
|
+
test,
|
|
108
|
+
preserveLogs,
|
|
109
|
+
priority,
|
|
110
|
+
wait,
|
|
111
|
+
autoMigrate,
|
|
112
|
+
allowDestructiveAutoMigrate,
|
|
113
|
+
} = cliOptions as {
|
|
114
|
+
readonly port: string;
|
|
115
|
+
readonly dryRun: boolean;
|
|
116
|
+
readonly agent?: string;
|
|
117
|
+
readonly context?: string;
|
|
118
|
+
readonly test?: string | string[];
|
|
119
|
+
readonly preserveLogs: boolean;
|
|
120
|
+
readonly priority: number;
|
|
121
|
+
readonly wait: boolean | string;
|
|
122
|
+
readonly autoMigrate: boolean;
|
|
123
|
+
readonly allowDestructiveAutoMigrate: boolean;
|
|
124
|
+
} & PromptRunnerCliOptions;
|
|
125
|
+
|
|
126
|
+
const port = parseCoderServerPort(rawPort);
|
|
127
|
+
const testCommand = normalizeCommandOptionValue(test);
|
|
128
|
+
const runnerOptions = normalizePromptRunnerCliOptions(cliOptions as PromptRunnerCliOptions, {
|
|
129
|
+
isAgentRequired: !dryRun,
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
// [1] Parse the --wait option (same logic as `coder run`)
|
|
133
|
+
let waitForUser = false;
|
|
134
|
+
let waitBetweenPrompts = 0;
|
|
135
|
+
|
|
136
|
+
if (wait === true) {
|
|
137
|
+
waitForUser = true;
|
|
138
|
+
} else if (typeof wait === 'string' && wait !== '') {
|
|
139
|
+
waitBetweenPrompts = parseDuration(wait);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const runOptions = {
|
|
143
|
+
port,
|
|
144
|
+
dryRun,
|
|
145
|
+
waitForUser,
|
|
146
|
+
waitBetweenPrompts,
|
|
147
|
+
noCommit: runnerOptions.noCommit,
|
|
148
|
+
ignoreGitChanges: runnerOptions.ignoreGitChanges,
|
|
149
|
+
agentName: runnerOptions.agentName,
|
|
150
|
+
model: runnerOptions.model,
|
|
151
|
+
agent,
|
|
152
|
+
context,
|
|
153
|
+
testCommand,
|
|
154
|
+
preserveLogs,
|
|
155
|
+
noUi: runnerOptions.noUi,
|
|
156
|
+
thinkingLevel: runnerOptions.thinkingLevel,
|
|
157
|
+
priority,
|
|
158
|
+
normalizeLineEndings: runnerOptions.normalizeLineEndings,
|
|
159
|
+
allowCredits: runnerOptions.allowCredits,
|
|
160
|
+
autoMigrate,
|
|
161
|
+
allowDestructiveAutoMigrate,
|
|
162
|
+
autoPush: runnerOptions.autoPush,
|
|
163
|
+
autoPull: runnerOptions.autoPull,
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
// Note: Import dynamically to avoid loading heavy dependencies until needed
|
|
167
|
+
const { runCodexPromptsServer } = await import(
|
|
168
|
+
'../../../../scripts/run-codex-prompts/main/runCodexPromptsServer'
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
try {
|
|
172
|
+
await runCodexPromptsServer(runOptions);
|
|
173
|
+
} catch (error) {
|
|
174
|
+
assertsError(error);
|
|
175
|
+
console.error(colors.bgRed(`${error.name}`));
|
|
176
|
+
console.error(colors.red(error.stack || error.message));
|
|
177
|
+
return process.exit(1);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return process.exit(0);
|
|
181
|
+
}),
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Parses and validates the coder server port number.
|
|
187
|
+
*
|
|
188
|
+
* @private internal utility of `coder server` command
|
|
189
|
+
*/
|
|
190
|
+
function parseCoderServerPort(rawPort: string): number_port {
|
|
191
|
+
const port = Number.parseInt(rawPort, 10);
|
|
192
|
+
|
|
193
|
+
if (!Number.isInteger(port) || port <= 0 || port > NETWORK_LIMITS.MAX_PORT) {
|
|
194
|
+
throw new NotAllowed(
|
|
195
|
+
spaceTrim(`
|
|
196
|
+
Invalid coder server port: \`${rawPort}\`.
|
|
197
|
+
|
|
198
|
+
Use \`--port\` or \`PTBK_CODER_SERVER_PORT\` with an integer between \`1\` and \`${NETWORK_LIMITS.MAX_PORT}\`.
|
|
199
|
+
`),
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return port as number_port;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Parses an integer option value.
|
|
208
|
+
*
|
|
209
|
+
* @private internal utility of `coder server` command
|
|
210
|
+
*/
|
|
211
|
+
function parseIntOption(value: string): number {
|
|
212
|
+
const parsed = parseInt(value, 10);
|
|
213
|
+
if (isNaN(parsed)) {
|
|
214
|
+
throw new Error(`Invalid number: ${value}`);
|
|
215
|
+
}
|
|
216
|
+
return parsed;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Joins one Commander option that may be parsed either as a single string or a variadic token array.
|
|
221
|
+
*
|
|
222
|
+
* @private internal utility of `coder server` command
|
|
223
|
+
*/
|
|
224
|
+
function normalizeCommandOptionValue(value: string | string[] | undefined): string | undefined {
|
|
225
|
+
if (value === undefined) {
|
|
226
|
+
return undefined;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const parts = Array.isArray(value) ? value : [value];
|
|
230
|
+
const normalizedValue = parts
|
|
231
|
+
.map((part) => part.trim())
|
|
232
|
+
.filter(Boolean)
|
|
233
|
+
.join(' ')
|
|
234
|
+
.trim();
|
|
235
|
+
return normalizedValue === '' ? undefined : normalizedValue;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Note: [🟡] Code for CLI command [server](src/cli/cli-commands/coder/server.ts) should never be published outside of `@promptbook/cli`
|
|
239
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -6,9 +6,11 @@ import { spaceTrim } from 'spacetrim';
|
|
|
6
6
|
import type { $side_effect } from '../../utils/organization/$side_effect';
|
|
7
7
|
import { $initializeCoderFindFreshEmojiTagCommand } from './coder/find-fresh-emoji-tags';
|
|
8
8
|
import { $initializeCoderFindRefactorCandidatesCommand } from './coder/find-refactor-candidates';
|
|
9
|
+
import { $initializeCoderFindUnwrittenCommand } from './coder/find-unwritten';
|
|
9
10
|
import { $initializeCoderGenerateBoilerplatesCommand } from './coder/generate-boilerplates';
|
|
10
11
|
import { $initializeCoderInitCommand } from './coder/init';
|
|
11
12
|
import { $initializeCoderRunCommand } from './coder/run';
|
|
13
|
+
import { $initializeCoderServerCommand } from './coder/server';
|
|
12
14
|
import { $initializeCoderVerifyCommand } from './coder/verify';
|
|
13
15
|
|
|
14
16
|
/**
|
|
@@ -36,7 +38,9 @@ export function $initializeCoderCommand(program: Program): $side_effect {
|
|
|
36
38
|
- init: Initialize coder configuration in current project
|
|
37
39
|
- generate-boilerplates: Generate prompt boilerplate files
|
|
38
40
|
- find-refactor-candidates: Find files that need refactoring
|
|
41
|
+
- find-unwritten: List prompt sections that still need to be authored
|
|
39
42
|
- run: Run coding prompts with AI agents
|
|
43
|
+
- server: Start a long-running coder server with a kanban web UI
|
|
40
44
|
- verify: Verify completed prompts
|
|
41
45
|
- find-fresh-emoji-tags: Find unused emoji tags
|
|
42
46
|
`),
|
|
@@ -46,7 +50,9 @@ export function $initializeCoderCommand(program: Program): $side_effect {
|
|
|
46
50
|
$initializeCoderInitCommand(coderCommand);
|
|
47
51
|
$initializeCoderGenerateBoilerplatesCommand(coderCommand);
|
|
48
52
|
$initializeCoderFindRefactorCandidatesCommand(coderCommand);
|
|
53
|
+
$initializeCoderFindUnwrittenCommand(coderCommand);
|
|
49
54
|
$initializeCoderRunCommand(coderCommand);
|
|
55
|
+
$initializeCoderServerCommand(coderCommand);
|
|
50
56
|
$initializeCoderVerifyCommand(coderCommand);
|
|
51
57
|
$initializeCoderFindFreshEmojiTagCommand(coderCommand);
|
|
52
58
|
|