@promptbook/cli 0.112.0-121 → 0.112.0-124
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 +14 -14
- package/agents/default/developer.book +23 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/user-chats/[chatId]/messages/route.ts +4 -11
- package/apps/agents-server/src/app/api/scrape/route.ts +18 -0
- package/apps/agents-server/src/tools/createAgentProgressTools.ts +6 -4
- package/apps/agents-server/src/utils/assertSafeUrl.ts +136 -0
- package/apps/agents-server/src/utils/authenticateUser.ts +2 -1
- package/apps/agents-server/src/utils/getCurrentUser.ts +2 -1
- package/apps/agents-server/src/utils/isAdminPasswordEqual.ts +28 -0
- package/apps/agents-server/src/utils/isUserGlobalAdmin.ts +3 -1
- package/apps/agents-server/src/utils/userChat/createRunUserChatJobPersistenceController.ts +21 -0
- package/apps/agents-server/src/utils/userChat/retryUserChatJob.ts +4 -0
- package/apps/agents-server/src/utils/userChat/userChatMessageLifecycle.ts +2 -0
- package/apps/agents-server/src/utils/userChat/userChatProgressCard.ts +288 -0
- package/esm/index.es.js +1430 -283
- 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/ensureCoderDeveloperAgentFile.d.ts +25 -0
- package/esm/src/cli/cli-commands/coder/find-unwritten.d.ts +10 -0
- package/esm/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.d.ts +2 -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/ensureCoderDeveloperAgentFile.ts +79 -0
- package/src/cli/cli-commands/coder/find-unwritten.ts +58 -0
- package/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.ts +1 -1
- package/src/cli/cli-commands/coder/init.ts +6 -1
- package/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts +10 -0
- package/src/cli/cli-commands/coder/printInitializationSummary.ts +3 -0
- 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 +727 -1105
- package/src/version.ts +2 -2
- package/src/versions.txt +3 -1
- package/umd/index.umd.js +1431 -284
- 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/ensureCoderDeveloperAgentFile.d.ts +25 -0
- package/umd/src/cli/cli-commands/coder/find-unwritten.d.ts +10 -0
- package/umd/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.d.ts +2 -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,25 @@
|
|
|
1
|
+
import type { InitializationStatus } from './boilerplateTemplates';
|
|
2
|
+
/**
|
|
3
|
+
* Relative directory path for agents initialized by `ptbk coder init`.
|
|
4
|
+
*
|
|
5
|
+
* @private internal utility of `coder init` command
|
|
6
|
+
*/
|
|
7
|
+
export declare const CODER_AGENTS_DIRECTORY_PATH = "agents";
|
|
8
|
+
/**
|
|
9
|
+
* Relative file path to the default developer agent initialized by `ptbk coder init`.
|
|
10
|
+
*
|
|
11
|
+
* @private internal utility of `coder init` command
|
|
12
|
+
*/
|
|
13
|
+
export declare const CODER_DEVELOPER_AGENT_FILE_PATH = "agents/developer.book";
|
|
14
|
+
/**
|
|
15
|
+
* Source file path of the bundled developer agent inside the Promptbook repository.
|
|
16
|
+
*
|
|
17
|
+
* @private internal utility of `coder init` command
|
|
18
|
+
*/
|
|
19
|
+
export declare const DEFAULT_CODER_DEVELOPER_AGENT_SOURCE_FILE_PATH = "agents/default/developer.book";
|
|
20
|
+
/**
|
|
21
|
+
* Ensures the default developer agent exists in the initialized project.
|
|
22
|
+
*
|
|
23
|
+
* @private function of `initializeCoderProjectConfiguration`
|
|
24
|
+
*/
|
|
25
|
+
export declare function ensureCoderDeveloperAgentFile(projectPath: string): Promise<InitializationStatus>;
|
|
@@ -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;
|
|
@@ -9,6 +9,8 @@ export type CoderInitializationSummary = {
|
|
|
9
9
|
readonly promptsDoneDirectoryStatus: InitializationStatus;
|
|
10
10
|
readonly promptsTemplatesDirectoryStatus: InitializationStatus;
|
|
11
11
|
readonly promptTemplateFileStatuses: ReadonlyArray<EnsuredCoderPromptTemplateFile>;
|
|
12
|
+
readonly agentsDirectoryStatus: InitializationStatus;
|
|
13
|
+
readonly developerAgentFileStatus: InitializationStatus;
|
|
12
14
|
readonly agentsFileStatus: InitializationStatus;
|
|
13
15
|
readonly agentCodingFileStatus: InitializationStatus;
|
|
14
16
|
readonly envFileStatus: InitializationStatus;
|
|
@@ -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-123`).
|
|
19
19
|
*
|
|
20
20
|
* @generated
|
|
21
21
|
*/
|
package/package.json
CHANGED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { copyFile, stat } from 'fs/promises';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { spaceTrim } from 'spacetrim';
|
|
4
|
+
import { NotAllowed } from '../../../errors/NotAllowed';
|
|
5
|
+
import type { InitializationStatus } from './boilerplateTemplates';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Relative directory path for agents initialized by `ptbk coder init`.
|
|
9
|
+
*
|
|
10
|
+
* @private internal utility of `coder init` command
|
|
11
|
+
*/
|
|
12
|
+
export const CODER_AGENTS_DIRECTORY_PATH = 'agents';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Relative file path to the default developer agent initialized by `ptbk coder init`.
|
|
16
|
+
*
|
|
17
|
+
* @private internal utility of `coder init` command
|
|
18
|
+
*/
|
|
19
|
+
export const CODER_DEVELOPER_AGENT_FILE_PATH = 'agents/developer.book';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Source file path of the bundled developer agent inside the Promptbook repository.
|
|
23
|
+
*
|
|
24
|
+
* @private internal utility of `coder init` command
|
|
25
|
+
*/
|
|
26
|
+
export const DEFAULT_CODER_DEVELOPER_AGENT_SOURCE_FILE_PATH = 'agents/default/developer.book';
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Ensures the default developer agent exists in the initialized project.
|
|
30
|
+
*
|
|
31
|
+
* @private function of `initializeCoderProjectConfiguration`
|
|
32
|
+
*/
|
|
33
|
+
export async function ensureCoderDeveloperAgentFile(projectPath: string): Promise<InitializationStatus> {
|
|
34
|
+
const absoluteFilePath = join(projectPath, CODER_DEVELOPER_AGENT_FILE_PATH);
|
|
35
|
+
if (await isExistingFile(absoluteFilePath)) {
|
|
36
|
+
return 'unchanged';
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
await copyFile(await resolveDefaultCoderDeveloperAgentFilePath(), absoluteFilePath);
|
|
40
|
+
return 'created';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Resolves the bundled developer agent from a source checkout or generated CLI package.
|
|
45
|
+
*/
|
|
46
|
+
async function resolveDefaultCoderDeveloperAgentFilePath(): Promise<string> {
|
|
47
|
+
const candidates = [
|
|
48
|
+
join(__dirname, '..', DEFAULT_CODER_DEVELOPER_AGENT_SOURCE_FILE_PATH),
|
|
49
|
+
join(__dirname, '..', '..', '..', '..', DEFAULT_CODER_DEVELOPER_AGENT_SOURCE_FILE_PATH),
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
for (const candidate of candidates) {
|
|
53
|
+
if (await isExistingFile(candidate)) {
|
|
54
|
+
return candidate;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
throw new NotAllowed(
|
|
59
|
+
spaceTrim(`
|
|
60
|
+
Cannot find the bundled Promptbook developer agent.
|
|
61
|
+
|
|
62
|
+
Checked:
|
|
63
|
+
${candidates.map((candidate) => `- \`${candidate}\``).join('\n')}
|
|
64
|
+
`),
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Checks whether a path exists and is a file.
|
|
70
|
+
*/
|
|
71
|
+
async function isExistingFile(path: string): Promise<boolean> {
|
|
72
|
+
try {
|
|
73
|
+
return (await stat(path)).isFile();
|
|
74
|
+
} catch {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Note: [🟡] Code for coder init developer agent bootstrapping [ensureCoderDeveloperAgentFile](src/cli/cli-commands/coder/ensureCoderDeveloperAgentFile.ts) should never be published outside of `@promptbook/cli`
|
|
@@ -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
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
const DEFAULT_CODER_PACKAGE_JSON_SCRIPTS = {
|
|
5
5
|
'coder:generate-boilerplates': 'ptbk coder generate-boilerplates --template ./prompts/templates/common.md',
|
|
6
6
|
'coder:run':
|
|
7
|
-
'ptbk coder run --harness openai-codex --model gpt-5.4 --thinking-level xhigh --context AGENTS.md --no-wait',
|
|
7
|
+
'ptbk coder run --harness openai-codex --model gpt-5.4 --thinking-level xhigh --agent agents/developer.book --context AGENTS.md --no-wait',
|
|
8
8
|
// 'coder:find-refactor-candidates': 'ptbk coder find-refactor-candidates',
|
|
9
9
|
'coder:verify': 'ptbk coder verify',
|
|
10
10
|
} as const satisfies Readonly<Record<string, string>>;
|
|
@@ -7,7 +7,9 @@ import { handleActionErrors } from '../common/handleActionErrors';
|
|
|
7
7
|
import { AGENT_CODING_FILE_PATH } from './agentCodingFile';
|
|
8
8
|
import { AGENTS_FILE_PATH } from './agentsFile';
|
|
9
9
|
import { getDefaultCoderProjectPromptTemplateDefinitions } from './boilerplateTemplates';
|
|
10
|
+
import { CODER_DEVELOPER_AGENT_FILE_PATH } from './ensureCoderDeveloperAgentFile';
|
|
10
11
|
import { formatDisplayPath } from './formatDisplayPath';
|
|
12
|
+
import { generatePromptBoilerplate } from './generate-boilerplates';
|
|
11
13
|
import { initializeCoderProjectConfiguration } from './initializeCoderProjectConfiguration';
|
|
12
14
|
import { printInitializationSummary } from './printInitializationSummary';
|
|
13
15
|
|
|
@@ -33,6 +35,7 @@ export function $initializeCoderInitCommand(program: Program): $side_effect {
|
|
|
33
35
|
- prompts/
|
|
34
36
|
- prompts/done/
|
|
35
37
|
${listDefaultCoderProjectPromptTemplateDisplayPaths()}
|
|
38
|
+
- ${CODER_DEVELOPER_AGENT_FILE_PATH}
|
|
36
39
|
- ${AGENTS_FILE_PATH}
|
|
37
40
|
- ${AGENT_CODING_FILE_PATH}
|
|
38
41
|
- .gitignore
|
|
@@ -48,8 +51,10 @@ export function $initializeCoderInitCommand(program: Program): $side_effect {
|
|
|
48
51
|
|
|
49
52
|
command.action(
|
|
50
53
|
handleActionErrors(async () => {
|
|
51
|
-
const
|
|
54
|
+
const projectPath = process.cwd();
|
|
55
|
+
const summary = await initializeCoderProjectConfiguration(projectPath);
|
|
52
56
|
printInitializationSummary(summary);
|
|
57
|
+
await generatePromptBoilerplate({ projectPath, filesCount: 5 });
|
|
53
58
|
}),
|
|
54
59
|
);
|
|
55
60
|
}
|
|
@@ -8,6 +8,10 @@ import {
|
|
|
8
8
|
PROMPTS_TEMPLATES_DIRECTORY_PATH,
|
|
9
9
|
} from './boilerplateTemplates';
|
|
10
10
|
import { ensureCoderEnvFile } from './ensureCoderEnvFile';
|
|
11
|
+
import {
|
|
12
|
+
CODER_AGENTS_DIRECTORY_PATH,
|
|
13
|
+
ensureCoderDeveloperAgentFile,
|
|
14
|
+
} from './ensureCoderDeveloperAgentFile';
|
|
11
15
|
import { ensureCoderGitignoreFile } from './ensureCoderGitignoreFile';
|
|
12
16
|
import { ensureCoderMarkdownFile } from './ensureCoderMarkdownFile';
|
|
13
17
|
import { ensureCoderPackageJsonFile } from './ensureCoderPackageJsonFile';
|
|
@@ -25,6 +29,8 @@ export type CoderInitializationSummary = {
|
|
|
25
29
|
readonly promptsDoneDirectoryStatus: InitializationStatus;
|
|
26
30
|
readonly promptsTemplatesDirectoryStatus: InitializationStatus;
|
|
27
31
|
readonly promptTemplateFileStatuses: ReadonlyArray<EnsuredCoderPromptTemplateFile>;
|
|
32
|
+
readonly agentsDirectoryStatus: InitializationStatus;
|
|
33
|
+
readonly developerAgentFileStatus: InitializationStatus;
|
|
28
34
|
readonly agentsFileStatus: InitializationStatus;
|
|
29
35
|
readonly agentCodingFileStatus: InitializationStatus;
|
|
30
36
|
readonly envFileStatus: InitializationStatus;
|
|
@@ -44,6 +50,8 @@ export async function initializeCoderProjectConfiguration(projectPath: string):
|
|
|
44
50
|
const promptsDoneDirectoryStatus = await ensureDirectory(projectPath, PROMPTS_DONE_DIRECTORY_PATH);
|
|
45
51
|
const promptsTemplatesDirectoryStatus = await ensureDirectory(projectPath, PROMPTS_TEMPLATES_DIRECTORY_PATH);
|
|
46
52
|
const promptTemplateFileStatuses = await ensureDefaultCoderPromptTemplateFiles(projectPath);
|
|
53
|
+
const agentsDirectoryStatus = await ensureDirectory(projectPath, CODER_AGENTS_DIRECTORY_PATH);
|
|
54
|
+
const developerAgentFileStatus = await ensureCoderDeveloperAgentFile(projectPath);
|
|
47
55
|
const agentsFileStatus = await ensureCoderMarkdownFile(
|
|
48
56
|
projectPath,
|
|
49
57
|
AGENTS_FILE_PATH,
|
|
@@ -66,6 +74,8 @@ export async function initializeCoderProjectConfiguration(projectPath: string):
|
|
|
66
74
|
promptsDoneDirectoryStatus,
|
|
67
75
|
promptsTemplatesDirectoryStatus,
|
|
68
76
|
promptTemplateFileStatuses,
|
|
77
|
+
agentsDirectoryStatus,
|
|
78
|
+
developerAgentFileStatus,
|
|
69
79
|
agentsFileStatus,
|
|
70
80
|
agentCodingFileStatus,
|
|
71
81
|
envFileStatus,
|
|
@@ -2,6 +2,7 @@ import colors from 'colors';
|
|
|
2
2
|
import { AGENT_CODING_FILE_PATH } from './agentCodingFile';
|
|
3
3
|
import { AGENTS_FILE_PATH } from './agentsFile';
|
|
4
4
|
import type { InitializationStatus } from './boilerplateTemplates';
|
|
5
|
+
import { CODER_DEVELOPER_AGENT_FILE_PATH } from './ensureCoderDeveloperAgentFile';
|
|
5
6
|
import { formatDisplayPath } from './formatDisplayPath';
|
|
6
7
|
import type { CoderInitializationSummary } from './initializeCoderProjectConfiguration';
|
|
7
8
|
|
|
@@ -23,6 +24,8 @@ export function printInitializationSummary(summary: CoderInitializationSummary):
|
|
|
23
24
|
);
|
|
24
25
|
}
|
|
25
26
|
|
|
27
|
+
printInitializationStatusLine('agents/', summary.agentsDirectoryStatus);
|
|
28
|
+
printInitializationStatusLine(CODER_DEVELOPER_AGENT_FILE_PATH, summary.developerAgentFileStatus);
|
|
26
29
|
printInitializationStatusLine(AGENTS_FILE_PATH, summary.agentsFileStatus);
|
|
27
30
|
printInitializationStatusLine(AGENT_CODING_FILE_PATH, summary.agentCodingFileStatus);
|
|
28
31
|
printInitializationStatusLine('.env', summary.envFileStatus);
|
|
@@ -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,
|