@promptbook/cli 0.113.0-4 → 0.113.0-8
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/admin/update/AdvancedOriginRepositoryPanel.tsx +76 -0
- package/apps/agents-server/src/app/admin/update/CurrentDeploymentCard.tsx +160 -0
- package/apps/agents-server/src/app/admin/update/PendingCommitsCard.tsx +86 -0
- package/apps/agents-server/src/app/admin/update/TargetEnvironmentCard.tsx +331 -0
- package/apps/agents-server/src/app/admin/update/UpdateClient.tsx +20 -873
- package/apps/agents-server/src/app/admin/update/UpdateJobCard.tsx +329 -0
- package/apps/agents-server/src/app/admin/update/UpdateOverview.ts +74 -0
- package/apps/agents-server/src/app/admin/update/buildDeploymentTimeBehindLabel.ts +29 -0
- package/apps/agents-server/src/app/admin/update/formatHumanReadableTimestamp.ts +18 -0
- package/apps/agents-server/src/app/admin/update/getUpdateJobFailureMessage.ts +13 -0
- package/apps/agents-server/src/app/admin/update/getUpdateJobSuccessMessage.ts +13 -0
- package/apps/agents-server/src/app/admin/update/useUpdateClientState.ts +441 -0
- package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +13 -1
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageClient.tsx +14 -559
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageHeader.tsx +84 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/AgentCodePageSection.tsx +52 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/GeneratedCodePreview.tsx +138 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/GeneratedHarnessSection.tsx +98 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/SourceBookSection.tsx +66 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/TranspiledCodeErrorBanner.tsx +30 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/TranspiledCodeExportWarningBanner.tsx +62 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/Transpiler.ts +9 -0
- package/apps/agents-server/src/app/agents/[agentName]/export-as-transpiled-code/useAgentCodeExportState.ts +478 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/cloneMockedChatPreset.ts +17 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/confirmDeleteMockedChat.ts +16 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedMessage.ts +81 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedParticipant.ts +146 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/createDraftWithUpdatedSettings.ts +19 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/createDuplicatedDraft.ts +66 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/findMockedChatById.ts +51 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/persistMockedChats.ts +51 -0
- package/apps/agents-server/src/app/system/utilities/mocked-chats/useMockedChatsEditorState.ts +16 -426
- package/apps/agents-server/src/components/Homepage/buildFreeGraphBoxLayout.ts +446 -0
- package/apps/agents-server/src/components/Homepage/buildGraphLayoutNodes.ts +415 -157
- package/apps/agents-server/src/components/Homepage/useAgentsGraphCanvasState.ts +2 -1
- package/apps/agents-server/src/database/sqlite/$provideLocalSqliteSupabase.ts +3 -1541
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/LocalSqliteQueryBuilder.ts +623 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/LocalSqliteSupabaseClient.ts +64 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/ensureTable.ts +93 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteFilters.ts +202 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteMutationPayload.ts +131 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteRowOperations.ts +102 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteSql.ts +59 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteTableSchema.ts +329 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteTypes.ts +84 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/localSqliteValueCodec.ts +63 -0
- package/apps/agents-server/src/database/sqlite/localSqliteSupabase/normalizeSqliteError.ts +22 -0
- package/apps/agents-server/src/search/createDefaultServerSearchProviders/loadLocalOrganizationSearchDataset.ts +12 -1
- package/apps/agents-server/src/tools/send_email.ts +1 -2
- package/apps/agents-server/src/utils/agentOrganization/loadAgentOrganizationState.ts +13 -1
- package/apps/agents-server/src/utils/backup/createServerBackupZipStream.ts +7 -1382
- package/apps/agents-server/src/utils/backup/serverBackup/appendAgentBackupEntriesToZip.ts +27 -0
- package/apps/agents-server/src/utils/backup/serverBackup/appendConversationBackupEntriesToZip.ts +140 -0
- package/apps/agents-server/src/utils/backup/serverBackup/appendFileBackupEntriesToZip.ts +147 -0
- package/apps/agents-server/src/utils/backup/serverBackup/appendMessageBackupEntriesToZip.ts +65 -0
- package/apps/agents-server/src/utils/backup/serverBackup/appendMetadataBackupEntriesToZip.ts +39 -0
- package/apps/agents-server/src/utils/backup/serverBackup/appendSectionEntriesToZip.ts +92 -0
- package/apps/agents-server/src/utils/backup/serverBackup/appendUserBackupEntriesToZip.ts +80 -0
- package/apps/agents-server/src/utils/backup/serverBackup/createRedactedWalletBackupRecord.ts +34 -0
- package/apps/agents-server/src/utils/backup/serverBackup/createServerBackupManifest.ts +82 -0
- package/apps/agents-server/src/utils/backup/serverBackup/downloadBackupBinaryContent.ts +39 -0
- package/apps/agents-server/src/utils/backup/serverBackup/resolveFeedbackThreadMessages.ts +53 -0
- package/apps/agents-server/src/utils/backup/serverBackup/serverBackupAttachments.ts +151 -0
- package/apps/agents-server/src/utils/backup/serverBackup/serverBackupContext.ts +167 -0
- package/apps/agents-server/src/utils/backup/serverBackup/serverBackupFilenames.ts +161 -0
- package/apps/agents-server/src/utils/backup/serverBackup/serverBackupPreviews.ts +97 -0
- package/apps/agents-server/src/utils/backup/serverBackup/serverBackupRowUtilities.ts +158 -0
- package/apps/agents-server/src/utils/backup/serverBackup/serverBackupTypes.ts +59 -0
- package/apps/agents-server/src/utils/createLocalAgentSourceImporter.ts +159 -0
- package/apps/agents-server/src/utils/createMissingImportedAgentFallback.ts +60 -0
- package/apps/agents-server/src/utils/customDomainRouting.ts +157 -12
- package/apps/agents-server/src/utils/externalChatRunner/processExternalUserChatJob.ts +1 -1
- package/apps/agents-server/src/utils/importAgentWithFallback.ts +1 -58
- package/apps/agents-server/src/utils/localAgentRouteReferences.ts +167 -0
- package/apps/agents-server/src/utils/localChatRunner/processLocalUserChatJob.ts +1 -1
- package/apps/agents-server/src/utils/managementApi/managementApiAgents.ts +17 -3
- package/apps/agents-server/src/utils/messages/sendMessage.ts +5 -3
- package/apps/agents-server/src/utils/resolveAgentStateFromSource.ts +7 -1
- package/apps/agents-server/src/utils/resolveInheritedAgentSource.ts +54 -5
- package/apps/agents-server/src/utils/resolveServerAgentContext.ts +12 -1
- package/apps/agents-server/src/utils/resolveStoredAgentState.ts +2 -1
- package/apps/agents-server/src/utils/speech-to-text/SpeechToTextFailoverRecognition/SpeechToTextFailoverRecognitionProviderRuntime.ts +0 -1
- package/apps/agents-server/src/utils/speech-to-text/SpeechToTextFailoverRecognition.ts +34 -2
- package/apps/agents-server/src/utils/userChat/userChatMessageLifecycle.ts +39 -9
- package/apps/agents-server/tests/e2e/support/ChatHistoryNavigationSupport.ts +5 -0
- package/esm/index.es.js +875 -60
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/find-refactor-candidates/find-refactor-candidates.d.ts +7 -0
- package/esm/scripts/find-refactor-candidates/selectMostImportantRefactorCandidates.d.ts +12 -0
- package/esm/scripts/run-codex-prompts/common/resolveCoderAgent.d.ts +20 -0
- package/esm/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +5 -0
- package/esm/scripts/run-codex-prompts/ui/buildCoderRunAgentVisual.d.ts +29 -0
- package/esm/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +4 -0
- package/esm/src/avatars/renderAvatarVisualAsciiArt.d.ts +75 -0
- package/esm/src/book-components/Chat/Chat/insertDictationChunk.d.ts +1 -1
- package/esm/src/book-components/Chat/Chat/insertDictationChunk.test.d.ts +1 -0
- package/esm/src/book-components/Chat/Chat/learnDictationDictionary.test.d.ts +1 -0
- package/esm/src/book-components/Chat/Chat/refineFinalDictationChunk.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/common/createPositiveIntegerOptionParser.d.ts +10 -0
- package/esm/src/utils/ascii-art/$detectTerminalAnsiColorDepth.d.ts +15 -0
- package/esm/src/utils/ascii-art/convertImageDataToAsciiArt.d.ts +80 -0
- package/esm/src/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/avatars/avatarAnimationScheduler.ts +2 -1
- package/src/avatars/renderAvatarVisualAsciiArt.ts +138 -0
- package/src/avatars/visuals/octopus3d3AvatarVisual.ts +6 -2
- package/src/avatars/visuals/octopus3d4AvatarVisual.ts +14 -18
- package/src/book-components/Chat/Chat/insertDictationChunk.ts +3 -3
- package/src/book-components/Chat/Chat/learnDictationDictionary.ts +1 -1
- package/src/book-components/Chat/Chat/useChatInputAreaDictation.ts +133 -26
- package/src/cli/cli-commands/agents-server/buildAgentsServer.ts +3 -1
- package/src/cli/cli-commands/coder/boilerplateTemplates.ts +14 -21
- package/src/cli/cli-commands/coder/find-refactor-candidates.ts +9 -2
- package/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts +1 -4
- package/src/cli/cli-commands/coder/run.ts +3 -27
- package/src/cli/cli-commands/common/createPositiveIntegerOptionParser.ts +31 -0
- package/src/commitments/TEAM/TEAM.ts +5 -5
- package/src/other/templates/getTemplatesPipelineCollection.ts +770 -1169
- package/src/utils/ascii-art/$detectTerminalAnsiColorDepth.ts +45 -0
- package/src/utils/ascii-art/convertImageDataToAsciiArt.ts +396 -0
- package/src/version.ts +2 -2
- package/src/versions.txt +2 -0
- package/umd/index.umd.js +875 -60
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/find-refactor-candidates/find-refactor-candidates.d.ts +7 -0
- package/umd/scripts/find-refactor-candidates/selectMostImportantRefactorCandidates.d.ts +12 -0
- package/umd/scripts/run-codex-prompts/common/resolveCoderAgent.d.ts +20 -0
- package/umd/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +5 -0
- package/umd/scripts/run-codex-prompts/ui/buildCoderRunAgentVisual.d.ts +29 -0
- package/umd/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +4 -0
- package/umd/src/avatars/renderAvatarVisualAsciiArt.d.ts +75 -0
- package/umd/src/book-components/Chat/Chat/insertDictationChunk.d.ts +1 -1
- package/umd/src/book-components/Chat/Chat/insertDictationChunk.test.d.ts +1 -0
- package/umd/src/book-components/Chat/Chat/learnDictationDictionary.test.d.ts +1 -0
- package/umd/src/book-components/Chat/Chat/refineFinalDictationChunk.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/common/createPositiveIntegerOptionParser.d.ts +10 -0
- package/umd/src/utils/ascii-art/$detectTerminalAnsiColorDepth.d.ts +15 -0
- package/umd/src/utils/ascii-art/convertImageDataToAsciiArt.d.ts +80 -0
- package/umd/src/version.d.ts +1 -1
- package/esm/scripts/run-codex-prompts/common/resolveAgentSystemMessage.d.ts +0 -6
- package/umd/scripts/run-codex-prompts/common/resolveAgentSystemMessage.d.ts +0 -6
package/umd/index.umd.js
CHANGED
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
* @generated
|
|
64
64
|
* @see https://github.com/webgptorg/promptbook
|
|
65
65
|
*/
|
|
66
|
-
const PROMPTBOOK_ENGINE_VERSION = '0.113.0-
|
|
66
|
+
const PROMPTBOOK_ENGINE_VERSION = '0.113.0-8';
|
|
67
67
|
/**
|
|
68
68
|
* TODO: string_promptbook_version should be constrained to the all versions of Promptbook engine
|
|
69
69
|
* Note: [💞] Ignore a discrepancy between file name and entity name
|
|
@@ -4547,7 +4547,7 @@
|
|
|
4547
4547
|
const visibleOutputLines = buildVisibleOutputLines(options.agentOutputLines);
|
|
4548
4548
|
const controls = buildControlPills(pausePresentation.pauseControl, options.pendingEnterLabel).join(' ');
|
|
4549
4549
|
const frame = [
|
|
4550
|
-
...
|
|
4550
|
+
...buildFrameHeaderVisual(options, totalWidth, octopusAnimationFrame),
|
|
4551
4551
|
'',
|
|
4552
4552
|
...renderBox('Session', sessionLines, totalWidth, colors__default["default"].yellow.bold),
|
|
4553
4553
|
...renderBox(options.currentPromptLabel ? 'Current task' : 'Queue', currentTaskLines, totalWidth, colors__default["default"].magenta.bold),
|
|
@@ -4559,6 +4559,18 @@
|
|
|
4559
4559
|
frame.push(...renderBox('Controls', [controls], totalWidth, colors__default["default"].white.bold));
|
|
4560
4560
|
return frame;
|
|
4561
4561
|
}
|
|
4562
|
+
/**
|
|
4563
|
+
* Builds the header visual above the dashboard boxes.
|
|
4564
|
+
*
|
|
4565
|
+
* Shows the ASCII-art `--agent` avatar visual when one is available and
|
|
4566
|
+
* falls back to the default brand banner otherwise.
|
|
4567
|
+
*/
|
|
4568
|
+
function buildFrameHeaderVisual(options, totalWidth, octopusAnimationFrame) {
|
|
4569
|
+
if (options.agentVisualLines !== undefined && options.agentVisualLines.length > 0) {
|
|
4570
|
+
return options.agentVisualLines.map((agentVisualLine) => centerAnsiText(agentVisualLine, totalWidth));
|
|
4571
|
+
}
|
|
4572
|
+
return buildCoderRunOctopusVisual({ totalWidth, animationFrame: octopusAnimationFrame });
|
|
4573
|
+
}
|
|
4562
4574
|
/**
|
|
4563
4575
|
* Builds the structured session lines that combine state, runner, queue, and timing metadata.
|
|
4564
4576
|
*/
|
|
@@ -4859,6 +4871,13 @@
|
|
|
4859
4871
|
this.config = config;
|
|
4860
4872
|
this.emitChange();
|
|
4861
4873
|
}
|
|
4874
|
+
/**
|
|
4875
|
+
* Replaces the ASCII-art agent visual shown instead of the default brand banner.
|
|
4876
|
+
*/
|
|
4877
|
+
setAgentVisualLines(agentVisualLines) {
|
|
4878
|
+
this.agentVisualLines = agentVisualLines === undefined ? undefined : [...agentVisualLines];
|
|
4879
|
+
this.emitChange();
|
|
4880
|
+
}
|
|
4862
4881
|
/**
|
|
4863
4882
|
* Feeds new prompt statistics from the main loop so the progress bar updates.
|
|
4864
4883
|
*/
|
|
@@ -5194,6 +5213,7 @@
|
|
|
5194
5213
|
pauseState: getPauseState(),
|
|
5195
5214
|
pauseTargetLabel: getPauseTargetLabel(),
|
|
5196
5215
|
config: state.config,
|
|
5216
|
+
agentVisualLines: state.agentVisualLines,
|
|
5197
5217
|
phase: state.phase,
|
|
5198
5218
|
currentPromptLabel: state.currentPromptLabel,
|
|
5199
5219
|
currentScriptPaths: state.currentScriptPaths,
|
|
@@ -9835,12 +9855,150 @@
|
|
|
9835
9855
|
}
|
|
9836
9856
|
|
|
9837
9857
|
/* eslint-disable no-magic-numbers */
|
|
9858
|
+
// Note: [💞] Ignore a discrepancy between file name and entity name
|
|
9859
|
+
/**
|
|
9860
|
+
* Default square size used by avatar renderers.
|
|
9861
|
+
*
|
|
9862
|
+
* @private utility of the avatar rendering system
|
|
9863
|
+
*/
|
|
9864
|
+
const DEFAULT_AVATAR_SIZE = 192;
|
|
9865
|
+
/**
|
|
9866
|
+
* Default fallback hash used when no explicit hash is provided.
|
|
9867
|
+
*
|
|
9868
|
+
* @private utility of the avatar rendering system
|
|
9869
|
+
*/
|
|
9870
|
+
const DEFAULT_AVATAR_HASH = '0000000000000000000000000000000000000000000000000000000000000000';
|
|
9871
|
+
/**
|
|
9872
|
+
* Default fallback name used when no explicit name is provided.
|
|
9873
|
+
*
|
|
9874
|
+
* @private utility of the avatar rendering system
|
|
9875
|
+
*/
|
|
9876
|
+
const DEFAULT_AVATAR_NAME = 'Anonymous Agent';
|
|
9838
9877
|
/**
|
|
9839
9878
|
* Corner radius ratio used for the common rounded card frame.
|
|
9840
9879
|
*
|
|
9841
9880
|
* @private utility of the avatar rendering system
|
|
9842
9881
|
*/
|
|
9843
9882
|
const FRAME_RADIUS_RATIO = 0.18;
|
|
9883
|
+
/**
|
|
9884
|
+
* Normalizes arbitrary agent colors into a stable non-empty color list.
|
|
9885
|
+
*
|
|
9886
|
+
* @param colors Raw color list.
|
|
9887
|
+
* @returns Stable list of usable colors.
|
|
9888
|
+
*
|
|
9889
|
+
* @private utility of the avatar rendering system
|
|
9890
|
+
*/
|
|
9891
|
+
function normalizeAvatarColors(colors) {
|
|
9892
|
+
const normalizedColors = colors
|
|
9893
|
+
.map((color) => String(color).trim())
|
|
9894
|
+
.filter((color) => color !== '')
|
|
9895
|
+
.map((color) => Color.fromSafe(color).toHex());
|
|
9896
|
+
if (normalizedColors.length > 0) {
|
|
9897
|
+
return normalizedColors;
|
|
9898
|
+
}
|
|
9899
|
+
return [PROMPTBOOK_COLOR.toHex()];
|
|
9900
|
+
}
|
|
9901
|
+
/**
|
|
9902
|
+
* Normalizes the avatar input so visuals can rely on consistent data.
|
|
9903
|
+
*
|
|
9904
|
+
* @param avatarDefinition Raw avatar input.
|
|
9905
|
+
* @returns Normalized avatar definition.
|
|
9906
|
+
*
|
|
9907
|
+
* @private utility of the avatar rendering system
|
|
9908
|
+
*/
|
|
9909
|
+
function normalizeAvatarDefinition(avatarDefinition) {
|
|
9910
|
+
return {
|
|
9911
|
+
agentName: (avatarDefinition.agentName || DEFAULT_AVATAR_NAME).trim() || DEFAULT_AVATAR_NAME,
|
|
9912
|
+
agentHash: (avatarDefinition.agentHash || DEFAULT_AVATAR_HASH).trim() || DEFAULT_AVATAR_HASH,
|
|
9913
|
+
colors: normalizeAvatarColors(avatarDefinition.colors),
|
|
9914
|
+
};
|
|
9915
|
+
}
|
|
9916
|
+
/**
|
|
9917
|
+
* Extracts avatar colors from the flexible `META COLOR` agent field.
|
|
9918
|
+
*
|
|
9919
|
+
* @param colorValue Raw `META COLOR` value.
|
|
9920
|
+
* @returns Parsed avatar colors.
|
|
9921
|
+
*
|
|
9922
|
+
* @private utility of the avatar rendering system
|
|
9923
|
+
*/
|
|
9924
|
+
function parseAvatarColors(colorValue) {
|
|
9925
|
+
if (!colorValue) {
|
|
9926
|
+
return [];
|
|
9927
|
+
}
|
|
9928
|
+
const colors = [];
|
|
9929
|
+
let currentColor = '';
|
|
9930
|
+
let bracketDepth = 0;
|
|
9931
|
+
for (const character of colorValue) {
|
|
9932
|
+
if (character === '(') {
|
|
9933
|
+
bracketDepth++;
|
|
9934
|
+
currentColor += character;
|
|
9935
|
+
continue;
|
|
9936
|
+
}
|
|
9937
|
+
if (character === ')') {
|
|
9938
|
+
bracketDepth = Math.max(0, bracketDepth - 1);
|
|
9939
|
+
currentColor += character;
|
|
9940
|
+
continue;
|
|
9941
|
+
}
|
|
9942
|
+
if (bracketDepth === 0 && [',', ';', '|', '\n'].includes(character)) {
|
|
9943
|
+
const normalizedColor = currentColor.trim();
|
|
9944
|
+
if (normalizedColor !== '') {
|
|
9945
|
+
colors.push(normalizedColor);
|
|
9946
|
+
}
|
|
9947
|
+
currentColor = '';
|
|
9948
|
+
continue;
|
|
9949
|
+
}
|
|
9950
|
+
currentColor += character;
|
|
9951
|
+
}
|
|
9952
|
+
const lastColor = currentColor.trim();
|
|
9953
|
+
if (lastColor !== '') {
|
|
9954
|
+
colors.push(lastColor);
|
|
9955
|
+
}
|
|
9956
|
+
return colors;
|
|
9957
|
+
}
|
|
9958
|
+
/**
|
|
9959
|
+
* Creates a reusable avatar definition from parsed agent information.
|
|
9960
|
+
*
|
|
9961
|
+
* @param agentBasicInformation Parsed agent information.
|
|
9962
|
+
* @returns Avatar definition ready for canvas rendering.
|
|
9963
|
+
*
|
|
9964
|
+
* @private shared helper for app-level avatar previews
|
|
9965
|
+
*/
|
|
9966
|
+
function createAvatarDefinitionFromAgentBasicInformation(agentBasicInformation) {
|
|
9967
|
+
return normalizeAvatarDefinition({
|
|
9968
|
+
agentName: agentBasicInformation.agentName,
|
|
9969
|
+
agentHash: agentBasicInformation.agentHash,
|
|
9970
|
+
colors: parseAvatarColors(agentBasicInformation.meta.color),
|
|
9971
|
+
});
|
|
9972
|
+
}
|
|
9973
|
+
/**
|
|
9974
|
+
* Creates the shared derived palette used by every avatar visual.
|
|
9975
|
+
*
|
|
9976
|
+
* @param avatarDefinition Stable avatar definition.
|
|
9977
|
+
* @param surface Surface style used by the parent UI.
|
|
9978
|
+
* @returns Derived palette.
|
|
9979
|
+
*
|
|
9980
|
+
* @private utility of the avatar rendering system
|
|
9981
|
+
*/
|
|
9982
|
+
function createAvatarPalette(avatarDefinition, surface = 'framed') {
|
|
9983
|
+
const normalizedAvatarDefinition = normalizeAvatarDefinition(avatarDefinition);
|
|
9984
|
+
const primaryColor = Color.fromSafe(normalizedAvatarDefinition.colors[0] || PROMPTBOOK_COLOR);
|
|
9985
|
+
const secondaryColor = Color.fromSafe(normalizedAvatarDefinition.colors[1] || primaryColor.then(lighten(0.12)).then(saturate(0.16)));
|
|
9986
|
+
const accentColor = Color.fromSafe(normalizedAvatarDefinition.colors[2] || primaryColor.then(saturate(0.32)).then(lighten(0.22)));
|
|
9987
|
+
const backgroundColor = Color.fromSafe(primaryColor.then(darken(0.34)).then(saturate(-0.1)));
|
|
9988
|
+
const backgroundSecondaryColor = Color.fromSafe(secondaryColor.then(darken(0.42)).then(saturate(-0.16)).then(lighten(0.04)));
|
|
9989
|
+
const highlightColor = Color.fromSafe(accentColor.then(lighten(0.22)).then(saturate(0.08)));
|
|
9990
|
+
const shadowColor = Color.fromSafe(primaryColor.then(darken(0.46)).then(saturate(0.14)));
|
|
9991
|
+
return {
|
|
9992
|
+
background: surface === 'transparent' ? 'transparent' : backgroundColor.toHex(),
|
|
9993
|
+
backgroundSecondary: surface === 'transparent' ? 'transparent' : backgroundSecondaryColor.toHex(),
|
|
9994
|
+
primary: primaryColor.toHex(),
|
|
9995
|
+
secondary: secondaryColor.toHex(),
|
|
9996
|
+
accent: accentColor.toHex(),
|
|
9997
|
+
highlight: highlightColor.toHex(),
|
|
9998
|
+
shadow: shadowColor.toHex(),
|
|
9999
|
+
ink: createInkColor(primaryColor),
|
|
10000
|
+
};
|
|
10001
|
+
}
|
|
9844
10002
|
/**
|
|
9845
10003
|
* Draws the common rounded background frame used by most visuals.
|
|
9846
10004
|
*
|
|
@@ -9891,6 +10049,67 @@
|
|
|
9891
10049
|
context.arcTo(x, y, x + width, y, normalizedRadius);
|
|
9892
10050
|
context.closePath();
|
|
9893
10051
|
}
|
|
10052
|
+
/**
|
|
10053
|
+
* Creates a stable pseudo-random number generator from a string seed.
|
|
10054
|
+
*
|
|
10055
|
+
* @param seedSource String seed.
|
|
10056
|
+
* @returns Generator producing values in `[0, 1)`.
|
|
10057
|
+
*
|
|
10058
|
+
* @private utility of the avatar rendering system
|
|
10059
|
+
*/
|
|
10060
|
+
function createSeededRandom(seedSource) {
|
|
10061
|
+
let state = hashStringToUint32(seedSource) || 0x9e3779b9;
|
|
10062
|
+
return () => {
|
|
10063
|
+
state = (state + 0x6d2b79f5) >>> 0;
|
|
10064
|
+
let hash = Math.imul(state ^ (state >>> 15), 1 | state);
|
|
10065
|
+
hash ^= hash + Math.imul(hash ^ (hash >>> 7), 61 | hash);
|
|
10066
|
+
return ((hash ^ (hash >>> 14)) >>> 0) / 4294967296;
|
|
10067
|
+
};
|
|
10068
|
+
}
|
|
10069
|
+
/**
|
|
10070
|
+
* Creates a deterministic random factory scoped to the avatar definition.
|
|
10071
|
+
*
|
|
10072
|
+
* @param avatarDefinition Stable avatar definition.
|
|
10073
|
+
* @returns Random factory that can be re-seeded per visual part.
|
|
10074
|
+
*
|
|
10075
|
+
* @private utility of the avatar rendering system
|
|
10076
|
+
*/
|
|
10077
|
+
function createAvatarRandomFactory(avatarDefinition) {
|
|
10078
|
+
const normalizedAvatarDefinition = normalizeAvatarDefinition(avatarDefinition);
|
|
10079
|
+
const seedBase = `${normalizedAvatarDefinition.agentName}|${normalizedAvatarDefinition.agentHash}|${normalizedAvatarDefinition.colors.join('|')}`;
|
|
10080
|
+
return (salt) => createSeededRandom(`${seedBase}|${salt}`);
|
|
10081
|
+
}
|
|
10082
|
+
/**
|
|
10083
|
+
* Clears and scales the canvas for crisp avatar rendering on high DPI displays.
|
|
10084
|
+
*
|
|
10085
|
+
* @param canvas Canvas element to prepare.
|
|
10086
|
+
* @param context Canvas 2D context.
|
|
10087
|
+
* @param size Canvas size in CSS pixels.
|
|
10088
|
+
* @param devicePixelRatio Device pixel ratio.
|
|
10089
|
+
*
|
|
10090
|
+
* @private utility of the avatar rendering system
|
|
10091
|
+
*/
|
|
10092
|
+
function prepareAvatarCanvas(canvas, context, size, devicePixelRatio) {
|
|
10093
|
+
const normalizedDevicePixelRatio = Math.max(1, Math.round(devicePixelRatio * 100) / 100);
|
|
10094
|
+
const nextCanvasWidth = Math.round(size * normalizedDevicePixelRatio);
|
|
10095
|
+
const nextCanvasHeight = Math.round(size * normalizedDevicePixelRatio);
|
|
10096
|
+
const nextCanvasStyleWidth = `${size}px`;
|
|
10097
|
+
const nextCanvasStyleHeight = `${size}px`;
|
|
10098
|
+
if (canvas.width !== nextCanvasWidth) {
|
|
10099
|
+
canvas.width = nextCanvasWidth;
|
|
10100
|
+
}
|
|
10101
|
+
if (canvas.height !== nextCanvasHeight) {
|
|
10102
|
+
canvas.height = nextCanvasHeight;
|
|
10103
|
+
}
|
|
10104
|
+
if (canvas.style.width !== nextCanvasStyleWidth) {
|
|
10105
|
+
canvas.style.width = nextCanvasStyleWidth;
|
|
10106
|
+
}
|
|
10107
|
+
if (canvas.style.height !== nextCanvasStyleHeight) {
|
|
10108
|
+
canvas.style.height = nextCanvasStyleHeight;
|
|
10109
|
+
}
|
|
10110
|
+
context.setTransform(normalizedDevicePixelRatio, 0, 0, normalizedDevicePixelRatio, 0, 0);
|
|
10111
|
+
context.clearRect(0, 0, size, size);
|
|
10112
|
+
}
|
|
9894
10113
|
/**
|
|
9895
10114
|
* Picks one deterministic element from a non-empty collection.
|
|
9896
10115
|
*
|
|
@@ -9903,6 +10122,37 @@
|
|
|
9903
10122
|
function pickRandomItem(items, random) {
|
|
9904
10123
|
return items[Math.floor(random() * items.length)];
|
|
9905
10124
|
}
|
|
10125
|
+
/**
|
|
10126
|
+
* Creates a readable ink color from the given base color.
|
|
10127
|
+
*
|
|
10128
|
+
* @param color Base color.
|
|
10129
|
+
* @returns High-contrast ink color.
|
|
10130
|
+
*
|
|
10131
|
+
* @private utility of the avatar rendering system
|
|
10132
|
+
*/
|
|
10133
|
+
function createInkColor(color) {
|
|
10134
|
+
const perceivedBrightness = color.red * 0.299 + color.green * 0.587 + color.blue * 0.114;
|
|
10135
|
+
if (perceivedBrightness > 150) {
|
|
10136
|
+
return '#172033';
|
|
10137
|
+
}
|
|
10138
|
+
return '#f8fbff';
|
|
10139
|
+
}
|
|
10140
|
+
/**
|
|
10141
|
+
* Hashes an arbitrary string into a 32-bit unsigned integer.
|
|
10142
|
+
*
|
|
10143
|
+
* @param value Arbitrary input.
|
|
10144
|
+
* @returns 32-bit unsigned integer hash.
|
|
10145
|
+
*
|
|
10146
|
+
* @private utility of the avatar rendering system
|
|
10147
|
+
*/
|
|
10148
|
+
function hashStringToUint32(value) {
|
|
10149
|
+
let hash = 2166136261;
|
|
10150
|
+
for (const character of value) {
|
|
10151
|
+
hash ^= character.charCodeAt(0);
|
|
10152
|
+
hash = Math.imul(hash, 16777619);
|
|
10153
|
+
}
|
|
10154
|
+
return hash >>> 0;
|
|
10155
|
+
}
|
|
9906
10156
|
|
|
9907
10157
|
/* eslint-disable no-magic-numbers */
|
|
9908
10158
|
/**
|
|
@@ -14418,7 +14668,7 @@
|
|
|
14418
14668
|
isAnimated: true,
|
|
14419
14669
|
supportsPointerTracking: true,
|
|
14420
14670
|
render({ context, size, palette, createRandom, timeMs, interaction }) {
|
|
14421
|
-
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles, skinSpots } = getOctopus3d4StableState(createRandom);
|
|
14671
|
+
const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles, skinSpots, } = getOctopus3d4StableState(createRandom);
|
|
14422
14672
|
const sceneCenterX = size * 0.5;
|
|
14423
14673
|
const sceneCenterY = size * 0.535;
|
|
14424
14674
|
const bob = Math.sin(timeMs / 980 + animationPhase) * size * 0.013;
|
|
@@ -14766,10 +15016,7 @@
|
|
|
14766
15016
|
Math.max(0, Math.cos(effectiveLongitude)) * 0.12 +
|
|
14767
15017
|
lowerBlend * tentacleInfluence.core * (0.12 + tentacleInfluence.depthScale * 0.07) -
|
|
14768
15018
|
Math.max(0, -Math.cos(effectiveLongitude)) * 0.05;
|
|
14769
|
-
const tentacleTubeRadius = lowerBlend *
|
|
14770
|
-
tentacleInfluence.core *
|
|
14771
|
-
(0.12 + tipBlend * 0.07 + tentacleInfluence.widthScale * 0.028) *
|
|
14772
|
-
radiusX;
|
|
15019
|
+
const tentacleTubeRadius = lowerBlend * tentacleInfluence.core * (0.12 + tipBlend * 0.07 + tentacleInfluence.widthScale * 0.028) * radiusX;
|
|
14773
15020
|
const planarRadiusX = cosineLatitude * radiusX * horizontalScale + tentacleTubeRadius;
|
|
14774
15021
|
const planarRadiusZ = cosineLatitude * radiusZ * depthScale + tentacleTubeRadius * 0.74;
|
|
14775
15022
|
const lowerDrop = lowerBlend *
|
|
@@ -14781,9 +15028,7 @@
|
|
|
14781
15028
|
(morphologyProfile.tentacles.flowLengthScale - 1) * 0.1));
|
|
14782
15029
|
const combinedTentacleSway = (primaryTentacleWave + secondaryTentacleWave) * radiusX * (0.06 + tipBlend * 0.06);
|
|
14783
15030
|
return {
|
|
14784
|
-
x: Math.sin(effectiveLongitude) * planarRadiusX +
|
|
14785
|
-
combinedTentacleSway +
|
|
14786
|
-
tentacleCurl * radiusX * 0.18,
|
|
15031
|
+
x: Math.sin(effectiveLongitude) * planarRadiusX + combinedTentacleSway + tentacleCurl * radiusX * 0.18,
|
|
14787
15032
|
y: Math.sin(latitude) * radiusY * (1 + upperBlend * 0.14) -
|
|
14788
15033
|
upperBlend * radiusY * 0.12 +
|
|
14789
15034
|
lowerDrop +
|
|
@@ -15890,6 +16135,21 @@
|
|
|
15890
16135
|
.toLowerCase()
|
|
15891
16136
|
.replace(/[^a-z0-9]+/g, '');
|
|
15892
16137
|
}
|
|
16138
|
+
/**
|
|
16139
|
+
* Returns one avatar visual by its identifier.
|
|
16140
|
+
*
|
|
16141
|
+
* @param visualId Requested visual identifier.
|
|
16142
|
+
* @returns Matching visual definition.
|
|
16143
|
+
*
|
|
16144
|
+
* @private shared registry for the avatar rendering system
|
|
16145
|
+
*/
|
|
16146
|
+
function getAvatarVisualById(visualId) {
|
|
16147
|
+
const avatarVisual = AVATAR_VISUALS.find((candidateAvatarVisual) => candidateAvatarVisual.id === visualId);
|
|
16148
|
+
if (!avatarVisual) {
|
|
16149
|
+
throw new Error(`Unknown avatar visual "${visualId}".`);
|
|
16150
|
+
}
|
|
16151
|
+
return avatarVisual;
|
|
16152
|
+
}
|
|
15893
16153
|
/**
|
|
15894
16154
|
* Resolves a user-facing avatar visual value to a supported built-in visual id.
|
|
15895
16155
|
*
|
|
@@ -18027,10 +18287,10 @@
|
|
|
18027
18287
|
*
|
|
18028
18288
|
* @private
|
|
18029
18289
|
*/
|
|
18030
|
-
const
|
|
18031
|
-
|
|
18032
|
-
|
|
18033
|
-
|
|
18290
|
+
const TEAM_SYSTEM_MESSAGE_GUIDANCE = _spaceTrim.spaceTrim(`
|
|
18291
|
+
- If a teammate is relevant to the request, consult that teammate using the matching tool.
|
|
18292
|
+
- Do not ask the user for information that a listed teammate can provide directly.
|
|
18293
|
+
`);
|
|
18034
18294
|
/**
|
|
18035
18295
|
* Constant for remote agents by Url.
|
|
18036
18296
|
*/
|
|
@@ -18212,7 +18472,7 @@
|
|
|
18212
18472
|
`);
|
|
18213
18473
|
});
|
|
18214
18474
|
return _spaceTrim.spaceTrim((block) => `
|
|
18215
|
-
${block(
|
|
18475
|
+
${block(TEAM_SYSTEM_MESSAGE_GUIDANCE)}
|
|
18216
18476
|
|
|
18217
18477
|
${block(teammateSections.join('\n\n'))}
|
|
18218
18478
|
`);
|
|
@@ -28470,7 +28730,7 @@
|
|
|
28470
28730
|
const MODEL_ARGUMENT = options.model ? ` --model ${options.model}` : '';
|
|
28471
28731
|
const THINKING_LEVEL_ARGUMENT = options.thinkingLevel ? ` --effort ${options.thinkingLevel}` : '';
|
|
28472
28732
|
return spaceTrim((block) => `
|
|
28473
|
-
claude --allowedTools "Bash,Read,Edit,Write"${MODEL_ARGUMENT}${THINKING_LEVEL_ARGUMENT} --output-format json --print <<'${CLAUDE_PROMPT_DELIMITER}'
|
|
28733
|
+
claude --allowedTools "Bash,Read,Edit,Write"${MODEL_ARGUMENT}${THINKING_LEVEL_ARGUMENT} --output-format stream-json --verbose --include-partial-messages --print <<'${CLAUDE_PROMPT_DELIMITER}'
|
|
28474
28734
|
|
|
28475
28735
|
${block(options.prompt)}
|
|
28476
28736
|
|
|
@@ -40030,6 +40290,30 @@
|
|
|
40030
40290
|
}
|
|
40031
40291
|
// Note: [🟡] Code for repository script [RefactorCandidateLevel](scripts/find-refactor-candidates/RefactorCandidateLevel.ts) should never be published outside of `@promptbook/cli`
|
|
40032
40292
|
|
|
40293
|
+
/**
|
|
40294
|
+
* Creates a Commander argument parser that accepts only positive integers.
|
|
40295
|
+
*
|
|
40296
|
+
* The returned parser is meant to be passed as the coercion callback of `command.option(...)`.
|
|
40297
|
+
* It throws a branded `NotAllowed` error with a clear message referencing the given option name
|
|
40298
|
+
* when the provided value is not a positive integer.
|
|
40299
|
+
*
|
|
40300
|
+
* @private internal utility of `promptbookCli`
|
|
40301
|
+
*/
|
|
40302
|
+
function createPositiveIntegerOptionParser(optionName) {
|
|
40303
|
+
return (value) => {
|
|
40304
|
+
const parsedValue = Number(value);
|
|
40305
|
+
if (!Number.isInteger(parsedValue) || parsedValue <= 0) {
|
|
40306
|
+
throw new NotAllowed(_spaceTrim.spaceTrim(`
|
|
40307
|
+
Invalid value for \`${optionName}\`: \`${value}\`.
|
|
40308
|
+
|
|
40309
|
+
Use a positive integer.
|
|
40310
|
+
`));
|
|
40311
|
+
}
|
|
40312
|
+
return parsedValue;
|
|
40313
|
+
};
|
|
40314
|
+
}
|
|
40315
|
+
// Note: [🟡] Code for CLI option parser [createPositiveIntegerOptionParser](src/cli/cli-commands/common/createPositiveIntegerOptionParser.ts) should never be published outside of `@promptbook/cli`
|
|
40316
|
+
|
|
40033
40317
|
/**
|
|
40034
40318
|
* Initializes `coder find-refactor-candidates` command for Promptbook CLI utilities
|
|
40035
40319
|
*
|
|
@@ -40050,12 +40334,13 @@
|
|
|
40050
40334
|
command.addOption(new commander.Option('--level <level>', `Set scan aggressiveness (${REFACTOR_CANDIDATE_LEVEL_VALUES.join(', ')})`)
|
|
40051
40335
|
.choices([...REFACTOR_CANDIDATE_LEVEL_VALUES])
|
|
40052
40336
|
.default(DEFAULT_REFACTOR_CANDIDATE_LEVEL));
|
|
40337
|
+
command.option('--limit <candidate-count>', 'Create at most this many refactor prompts, keeping the most important candidates', createPositiveIntegerOptionParser('--limit'));
|
|
40053
40338
|
command.action(handleActionErrors(async (cliOptions) => {
|
|
40054
|
-
const { level = DEFAULT_REFACTOR_CANDIDATE_LEVEL } = cliOptions;
|
|
40339
|
+
const { level = DEFAULT_REFACTOR_CANDIDATE_LEVEL, limit } = cliOptions;
|
|
40055
40340
|
// Note: Import the function dynamically to avoid loading heavy dependencies until needed
|
|
40056
40341
|
const { findRefactorCandidates } = await Promise.resolve().then(function () { return findRefactorCandidates$1; });
|
|
40057
40342
|
try {
|
|
40058
|
-
await findRefactorCandidates({ level });
|
|
40343
|
+
await findRefactorCandidates({ level, limit });
|
|
40059
40344
|
}
|
|
40060
40345
|
catch (error) {
|
|
40061
40346
|
assertsError(error);
|
|
@@ -40139,26 +40424,26 @@
|
|
|
40139
40424
|
id: 'common',
|
|
40140
40425
|
relativeFilePath: path.join(PROMPTS_TEMPLATES_DIRECTORY_PATH, 'common.md'),
|
|
40141
40426
|
slugPrefix: null,
|
|
40142
|
-
content:
|
|
40143
|
-
|
|
40144
|
-
|
|
40145
|
-
|
|
40146
|
-
|
|
40147
|
-
|
|
40427
|
+
content: _spaceTrim.spaceTrim(`
|
|
40428
|
+
- @@@
|
|
40429
|
+
- Keep in mind the DRY _(don't repeat yourself)_ principle.
|
|
40430
|
+
- Do a proper analysis of the current functionality before you start implementing.
|
|
40431
|
+
- Add the changes into the [changelog](changelog/_current-preversion.md)
|
|
40432
|
+
`),
|
|
40148
40433
|
isDefaultProjectTemplate: true,
|
|
40149
40434
|
},
|
|
40150
40435
|
{
|
|
40151
40436
|
id: 'agents-server',
|
|
40152
40437
|
relativeFilePath: path.join(PROMPTS_TEMPLATES_DIRECTORY_PATH, 'agents-server.md'),
|
|
40153
40438
|
slugPrefix: 'agents-server',
|
|
40154
|
-
content:
|
|
40155
|
-
|
|
40156
|
-
|
|
40157
|
-
|
|
40158
|
-
|
|
40159
|
-
|
|
40160
|
-
|
|
40161
|
-
|
|
40439
|
+
content: _spaceTrim.spaceTrim(`
|
|
40440
|
+
- @@@
|
|
40441
|
+
- Keep in mind the DRY _(don't repeat yourself)_ principle.
|
|
40442
|
+
- Do a proper analysis of the current functionality before you start implementing.
|
|
40443
|
+
- You are working with the [Agents Server](apps/agents-server)
|
|
40444
|
+
- If you need to do the database migration, do it
|
|
40445
|
+
- Add the changes into the [changelog](changelog/_current-preversion.md)
|
|
40446
|
+
`),
|
|
40162
40447
|
isDefaultProjectTemplate: false,
|
|
40163
40448
|
},
|
|
40164
40449
|
];
|
|
@@ -40278,12 +40563,6 @@
|
|
|
40278
40563
|
function getDefaultCoderPromptTemplateDefinitionOrUndefined(template) {
|
|
40279
40564
|
return DEFAULT_CODER_PROMPT_TEMPLATE_DEFINITIONS.find((definition) => definition.id === template);
|
|
40280
40565
|
}
|
|
40281
|
-
/**
|
|
40282
|
-
* Builds stable markdown content for one coder prompt template without indentation drift.
|
|
40283
|
-
*/
|
|
40284
|
-
function buildCoderPromptTemplateContent(lines) {
|
|
40285
|
-
return lines.join('\n');
|
|
40286
|
-
}
|
|
40287
40566
|
/**
|
|
40288
40567
|
* Creates a fully resolved template payload from one built-in definition.
|
|
40289
40568
|
*/
|
|
@@ -41210,7 +41489,7 @@
|
|
|
41210
41489
|
command.option('--preserve-logs', 'Keep generated temp prompt/log artifacts after successful rounds for debugging and analytics', false);
|
|
41211
41490
|
addPromptRunnerExecutionOptions(command);
|
|
41212
41491
|
command.option('--priority <minimum-priority>', 'Filter prompts by minimum priority level', parseIntOption$1, 0);
|
|
41213
|
-
command.option('--limit <run-count>', 'Stop after processing this many prompt runs',
|
|
41492
|
+
command.option('--limit <run-count>', 'Stop after processing this many prompt runs', createPositiveIntegerOptionParser('--limit'));
|
|
41214
41493
|
command.option('--wait-after-prompt <duration>', _spaceTrim.spaceTrim(`
|
|
41215
41494
|
Wait this long after each prompt has been implemented, verified and committed before starting the next prompt.
|
|
41216
41495
|
Accepts durations like 1h, 30m, 5s. Defaults to 0 (no wait).
|
|
@@ -41297,22 +41576,6 @@
|
|
|
41297
41576
|
}
|
|
41298
41577
|
return parsed;
|
|
41299
41578
|
}
|
|
41300
|
-
/**
|
|
41301
|
-
* Parses a positive integer option value.
|
|
41302
|
-
*
|
|
41303
|
-
* @private internal utility of `coder run` command
|
|
41304
|
-
*/
|
|
41305
|
-
function parsePositiveIntegerOption(value) {
|
|
41306
|
-
const parsed = Number(value);
|
|
41307
|
-
if (!Number.isInteger(parsed) || parsed <= 0) {
|
|
41308
|
-
throw new NotAllowed(_spaceTrim.spaceTrim(`
|
|
41309
|
-
Invalid value for \`--limit\`: \`${value}\`.
|
|
41310
|
-
|
|
41311
|
-
Use a positive integer.
|
|
41312
|
-
`));
|
|
41313
|
-
}
|
|
41314
|
-
return parsed;
|
|
41315
|
-
}
|
|
41316
41579
|
/**
|
|
41317
41580
|
* Joins one Commander option that may be parsed either as a single string or a variadic token array.
|
|
41318
41581
|
*
|
|
@@ -69585,23 +69848,28 @@
|
|
|
69585
69848
|
const extension = path.extname(filePath).toLowerCase();
|
|
69586
69849
|
const relativePath = normalizeRefactorCandidatePath(path.relative(rootDir, filePath));
|
|
69587
69850
|
const reasons = [];
|
|
69851
|
+
let severityScore = 0;
|
|
69588
69852
|
if (!lineCountExemptPaths.has(normalizedAbsolutePath)) {
|
|
69589
69853
|
const lineCount = countLines(content);
|
|
69590
69854
|
const maxLines = getMaxLinesForExtension(extension, heuristics);
|
|
69591
69855
|
if (lineCount > maxLines) {
|
|
69592
69856
|
reasons.push(`lines ${lineCount}/${maxLines}`);
|
|
69857
|
+
severityScore += lineCount / maxLines;
|
|
69593
69858
|
}
|
|
69594
69859
|
}
|
|
69595
69860
|
if (STRUCTURAL_ANALYSIS_EXTENSIONS.includes(extension)) {
|
|
69596
69861
|
const structureSummary = summarizeSourceFileStructure(content, extension, filePath);
|
|
69597
69862
|
if (structureSummary.entityCount > heuristics.maxEntityCountPerFile) {
|
|
69598
69863
|
reasons.push(`entities ${structureSummary.entityCount}/${heuristics.maxEntityCountPerFile}`);
|
|
69864
|
+
severityScore += structureSummary.entityCount / heuristics.maxEntityCountPerFile;
|
|
69599
69865
|
}
|
|
69600
69866
|
if (structureSummary.functionCount > heuristics.maxFunctionCountPerFile) {
|
|
69601
69867
|
reasons.push(`functions ${structureSummary.functionCount}/${heuristics.maxFunctionCountPerFile}`);
|
|
69868
|
+
severityScore += structureSummary.functionCount / heuristics.maxFunctionCountPerFile;
|
|
69602
69869
|
}
|
|
69603
69870
|
if (structureSummary.maxFunctionComplexity > heuristics.maxFunctionComplexity) {
|
|
69604
69871
|
reasons.push(buildComplexityReason(structureSummary, heuristics.maxFunctionComplexity));
|
|
69872
|
+
severityScore += structureSummary.maxFunctionComplexity / heuristics.maxFunctionComplexity;
|
|
69605
69873
|
}
|
|
69606
69874
|
}
|
|
69607
69875
|
if (reasons.length === 0) {
|
|
@@ -69611,6 +69879,7 @@
|
|
|
69611
69879
|
absolutePath: filePath,
|
|
69612
69880
|
relativePath,
|
|
69613
69881
|
reasons,
|
|
69882
|
+
severityScore,
|
|
69614
69883
|
};
|
|
69615
69884
|
}
|
|
69616
69885
|
/**
|
|
@@ -70070,6 +70339,37 @@
|
|
|
70070
70339
|
}
|
|
70071
70340
|
// Note: [🟡] Code for repository script [resolveRefactorCandidateProject](scripts/find-refactor-candidates/resolveRefactorCandidateProject.ts) should never be published outside of `@promptbook/cli`
|
|
70072
70341
|
|
|
70342
|
+
/**
|
|
70343
|
+
* Keeps at most `limit` refactor candidates, preferring the most important ones.
|
|
70344
|
+
*
|
|
70345
|
+
* When there are more candidates than `limit`, only the highest-severity candidates are kept
|
|
70346
|
+
* (ties broken by relative path for determinism). When `limit` is `undefined` or there are fewer
|
|
70347
|
+
* candidates than the limit, every candidate is returned. The original input order is preserved
|
|
70348
|
+
* among the kept candidates, so `limit` acts purely as a filter and never reorders prompts.
|
|
70349
|
+
*
|
|
70350
|
+
* @private function of findRefactorCandidates
|
|
70351
|
+
*/
|
|
70352
|
+
function selectMostImportantRefactorCandidates(candidates, limit) {
|
|
70353
|
+
if (limit === undefined || candidates.length <= limit) {
|
|
70354
|
+
return candidates;
|
|
70355
|
+
}
|
|
70356
|
+
const candidatesRankedByImportance = [...candidates].sort(compareRefactorCandidatesByImportance);
|
|
70357
|
+
const keptRelativePaths = new Set(candidatesRankedByImportance.slice(0, limit).map((candidate) => candidate.relativePath));
|
|
70358
|
+
return candidates.filter((candidate) => keptRelativePaths.has(candidate.relativePath));
|
|
70359
|
+
}
|
|
70360
|
+
/**
|
|
70361
|
+
* Orders refactor candidates from most to least important.
|
|
70362
|
+
*
|
|
70363
|
+
* @private function of selectMostImportantRefactorCandidates
|
|
70364
|
+
*/
|
|
70365
|
+
function compareRefactorCandidatesByImportance(candidateA, candidateB) {
|
|
70366
|
+
if (candidateB.severityScore !== candidateA.severityScore) {
|
|
70367
|
+
return candidateB.severityScore - candidateA.severityScore;
|
|
70368
|
+
}
|
|
70369
|
+
return candidateA.relativePath.localeCompare(candidateB.relativePath);
|
|
70370
|
+
}
|
|
70371
|
+
// Note: [🟡] Code for repository script [selectMostImportantRefactorCandidates](scripts/find-refactor-candidates/selectMostImportantRefactorCandidates.ts) should never be published outside of `@promptbook/cli`
|
|
70372
|
+
|
|
70073
70373
|
/**
|
|
70074
70374
|
* Calculates the next available prompt numbering sequence for a month.
|
|
70075
70375
|
*/
|
|
@@ -70393,7 +70693,7 @@
|
|
|
70393
70693
|
* @public exported from `@promptbook/cli`
|
|
70394
70694
|
*/
|
|
70395
70695
|
async function findRefactorCandidates(options = {}) {
|
|
70396
|
-
const { level = DEFAULT_REFACTOR_CANDIDATE_LEVEL } = options;
|
|
70696
|
+
const { level = DEFAULT_REFACTOR_CANDIDATE_LEVEL, limit } = options;
|
|
70397
70697
|
const heuristics = getRefactorCandidateLevelConfiguration(level);
|
|
70398
70698
|
initializeFindRefactorCandidatesRun();
|
|
70399
70699
|
console.info(colors__default["default"].cyan('⚡🏭 Find refactor candidates'));
|
|
@@ -70417,8 +70717,10 @@
|
|
|
70417
70717
|
console.info(colors__default["default"].green('All candidates already have prompts.'));
|
|
70418
70718
|
return;
|
|
70419
70719
|
}
|
|
70720
|
+
const selectedCandidatesToWrite = selectMostImportantRefactorCandidates(candidatesToWrite, limit);
|
|
70721
|
+
const skippedByLimit = candidatesToWrite.length - selectedCandidatesToWrite.length;
|
|
70420
70722
|
const createdPrompts = await writeRefactorCandidatePrompts({
|
|
70421
|
-
candidates:
|
|
70723
|
+
candidates: selectedCandidatesToWrite,
|
|
70422
70724
|
rootDir,
|
|
70423
70725
|
promptsDir,
|
|
70424
70726
|
});
|
|
@@ -70426,6 +70728,9 @@
|
|
|
70426
70728
|
if (alreadyTracked > 0) {
|
|
70427
70729
|
console.info(colors__default["default"].gray(`Skipped ${alreadyTracked} candidate(s) with existing prompts.`));
|
|
70428
70730
|
}
|
|
70731
|
+
if (skippedByLimit > 0) {
|
|
70732
|
+
console.info(colors__default["default"].gray(`Skipped ${skippedByLimit} lower-priority candidate(s) because of \`--limit ${limit}\`.`));
|
|
70733
|
+
}
|
|
70429
70734
|
}
|
|
70430
70735
|
/**
|
|
70431
70736
|
* Prints discovered refactor candidates with their reasons.
|
|
@@ -71226,7 +71531,7 @@
|
|
|
71226
71531
|
*
|
|
71227
71532
|
* Returns `undefined` when no agent path is provided.
|
|
71228
71533
|
*/
|
|
71229
|
-
async function
|
|
71534
|
+
async function resolveCoderAgent(agentPath, currentWorkingDirectory) {
|
|
71230
71535
|
if (!agentPath) {
|
|
71231
71536
|
return undefined;
|
|
71232
71537
|
}
|
|
@@ -71241,7 +71546,10 @@
|
|
|
71241
71546
|
}
|
|
71242
71547
|
throw error;
|
|
71243
71548
|
});
|
|
71244
|
-
return
|
|
71549
|
+
return {
|
|
71550
|
+
agentSource: agentSource,
|
|
71551
|
+
systemMessage: await createAgentRunnerSystemMessage(agentSource),
|
|
71552
|
+
};
|
|
71245
71553
|
}
|
|
71246
71554
|
|
|
71247
71555
|
/**
|
|
@@ -71439,6 +71747,497 @@
|
|
|
71439
71747
|
await waitForEnter(colors__default["default"].bgWhite(`Press Enter to start the ${label}...`));
|
|
71440
71748
|
}
|
|
71441
71749
|
|
|
71750
|
+
/**
|
|
71751
|
+
* Default alpha channel value below which a half-cell is rendered as terminal background.
|
|
71752
|
+
*
|
|
71753
|
+
* @private within the repository
|
|
71754
|
+
*/
|
|
71755
|
+
const DEFAULT_ALPHA_THRESHOLD = 32;
|
|
71756
|
+
/**
|
|
71757
|
+
* Number of channels per pixel in an RGBA buffer.
|
|
71758
|
+
*
|
|
71759
|
+
* @private within the repository
|
|
71760
|
+
*/
|
|
71761
|
+
const RGBA_CHANNEL_COUNT = 4;
|
|
71762
|
+
/**
|
|
71763
|
+
* Upper half block character - foreground paints the top pixel, background paints the bottom pixel.
|
|
71764
|
+
*
|
|
71765
|
+
* @private within the repository
|
|
71766
|
+
*/
|
|
71767
|
+
const UPPER_HALF_BLOCK = '▀'; // <- ▀
|
|
71768
|
+
/**
|
|
71769
|
+
* Lower half block character - foreground paints the bottom pixel while the top pixel stays transparent.
|
|
71770
|
+
*
|
|
71771
|
+
* @private within the repository
|
|
71772
|
+
*/
|
|
71773
|
+
const LOWER_HALF_BLOCK = '▄'; // <- ▄
|
|
71774
|
+
/**
|
|
71775
|
+
* ANSI escape sequence that resets all colors and attributes.
|
|
71776
|
+
*
|
|
71777
|
+
* @private within the repository
|
|
71778
|
+
*/
|
|
71779
|
+
const ANSI_RESET = '\u001b[0m';
|
|
71780
|
+
/**
|
|
71781
|
+
* Maximum spread between RGB channels for a color to be treated as (nearly) achromatic gray.
|
|
71782
|
+
*
|
|
71783
|
+
* @private within the repository
|
|
71784
|
+
*/
|
|
71785
|
+
const ANSI_256_ACHROMATIC_CHANNEL_SPREAD = 12;
|
|
71786
|
+
/**
|
|
71787
|
+
* Gray level above which an achromatic color maps to the pure white color-cube entry.
|
|
71788
|
+
*
|
|
71789
|
+
* @private within the repository
|
|
71790
|
+
*/
|
|
71791
|
+
const ANSI_256_NEAR_WHITE_GRAY_LEVEL = 246;
|
|
71792
|
+
/**
|
|
71793
|
+
* Index of pure white inside the 6×6×6 ANSI color cube.
|
|
71794
|
+
*
|
|
71795
|
+
* @private within the repository
|
|
71796
|
+
*/
|
|
71797
|
+
const ANSI_256_WHITE_INDEX = 231;
|
|
71798
|
+
/**
|
|
71799
|
+
* Brightness of the lightest entry of the ANSI 256 grayscale ramp.
|
|
71800
|
+
*
|
|
71801
|
+
* @private within the repository
|
|
71802
|
+
*/
|
|
71803
|
+
const ANSI_256_GRAYSCALE_RAMP_MAX_LEVEL = 238;
|
|
71804
|
+
/**
|
|
71805
|
+
* Number of grayscale ramp steps above its first entry (ANSI indexes 232-255).
|
|
71806
|
+
*
|
|
71807
|
+
* @private within the repository
|
|
71808
|
+
*/
|
|
71809
|
+
const ANSI_256_GRAYSCALE_RAMP_INDEX_SPAN = 23;
|
|
71810
|
+
/**
|
|
71811
|
+
* Converts raw RGBA image pixels into colored ASCII art for ANSI terminals.
|
|
71812
|
+
*
|
|
71813
|
+
* This is the universal image-to-terminal technique used across the repository:
|
|
71814
|
+
* every output character cell covers a rectangular region of source pixels which is
|
|
71815
|
+
* split into a top and bottom half; each half is area-averaged and rendered with
|
|
71816
|
+
* half-block characters (`▀` / `▄`) so one character shows two "pixels" vertically.
|
|
71817
|
+
* Transparent halves keep the terminal background so non-rectangular images
|
|
71818
|
+
* (for example rounded avatar cards) compose naturally into any terminal UI.
|
|
71819
|
+
*
|
|
71820
|
+
* @param options Source pixels, output grid size, and ANSI color depth.
|
|
71821
|
+
* @returns One ANSI-colored string per output row, each ending with a color reset.
|
|
71822
|
+
*
|
|
71823
|
+
* @private within the repository
|
|
71824
|
+
*/
|
|
71825
|
+
function convertImageDataToAsciiArt(options) {
|
|
71826
|
+
const { imageData, columns, rows, colorDepth = 'TRUE_COLOR', alphaThreshold = DEFAULT_ALPHA_THRESHOLD } = options;
|
|
71827
|
+
if (!Number.isInteger(columns) || columns <= 0 || !Number.isInteger(rows) || rows <= 0) {
|
|
71828
|
+
throw new UnexpectedError(_spaceTrim.spaceTrim(`
|
|
71829
|
+
ASCII-art grid size is invalid.
|
|
71830
|
+
|
|
71831
|
+
Both \`columns\` and \`rows\` must be positive integers but \`${columns}\` × \`${rows}\` was requested.
|
|
71832
|
+
`));
|
|
71833
|
+
}
|
|
71834
|
+
if (imageData.width <= 0 ||
|
|
71835
|
+
imageData.height <= 0 ||
|
|
71836
|
+
imageData.data.length < imageData.width * imageData.height * RGBA_CHANNEL_COUNT) {
|
|
71837
|
+
throw new UnexpectedError(_spaceTrim.spaceTrim(`
|
|
71838
|
+
ASCII-art source image data is invalid.
|
|
71839
|
+
|
|
71840
|
+
Expected a RGBA buffer of at least \`${imageData.width} × ${imageData.height} × ${RGBA_CHANNEL_COUNT}\` bytes
|
|
71841
|
+
but got \`${imageData.data.length}\` bytes.
|
|
71842
|
+
`));
|
|
71843
|
+
}
|
|
71844
|
+
const halfCellRowCount = rows * 2;
|
|
71845
|
+
const asciiArtLines = [];
|
|
71846
|
+
for (let rowIndex = 0; rowIndex < rows; rowIndex++) {
|
|
71847
|
+
let line = '';
|
|
71848
|
+
let currentForegroundCode = undefined;
|
|
71849
|
+
let currentBackgroundCode = undefined;
|
|
71850
|
+
for (let columnIndex = 0; columnIndex < columns; columnIndex++) {
|
|
71851
|
+
const topHalfColor = computeHalfCellColor(imageData, columnIndex, rowIndex * 2, columns, halfCellRowCount, alphaThreshold);
|
|
71852
|
+
const bottomHalfColor = computeHalfCellColor(imageData, columnIndex, rowIndex * 2 + 1, columns, halfCellRowCount, alphaThreshold);
|
|
71853
|
+
let character;
|
|
71854
|
+
let nextForegroundCode;
|
|
71855
|
+
let nextBackgroundCode;
|
|
71856
|
+
if (topHalfColor.isOpaque && bottomHalfColor.isOpaque) {
|
|
71857
|
+
character = UPPER_HALF_BLOCK;
|
|
71858
|
+
nextForegroundCode = createForegroundColorCode(topHalfColor, colorDepth);
|
|
71859
|
+
nextBackgroundCode = createBackgroundColorCode(bottomHalfColor, colorDepth);
|
|
71860
|
+
}
|
|
71861
|
+
else if (topHalfColor.isOpaque) {
|
|
71862
|
+
character = UPPER_HALF_BLOCK;
|
|
71863
|
+
nextForegroundCode = createForegroundColorCode(topHalfColor, colorDepth);
|
|
71864
|
+
nextBackgroundCode = undefined;
|
|
71865
|
+
}
|
|
71866
|
+
else if (bottomHalfColor.isOpaque) {
|
|
71867
|
+
character = LOWER_HALF_BLOCK;
|
|
71868
|
+
nextForegroundCode = createForegroundColorCode(bottomHalfColor, colorDepth);
|
|
71869
|
+
nextBackgroundCode = undefined;
|
|
71870
|
+
}
|
|
71871
|
+
else {
|
|
71872
|
+
character = ' ';
|
|
71873
|
+
nextForegroundCode = undefined;
|
|
71874
|
+
nextBackgroundCode = undefined;
|
|
71875
|
+
}
|
|
71876
|
+
if (nextForegroundCode !== currentForegroundCode || nextBackgroundCode !== currentBackgroundCode) {
|
|
71877
|
+
// Note: A reset is required whenever a previously set color must be cleared,
|
|
71878
|
+
// otherwise stale background color would bleed into transparent cells.
|
|
71879
|
+
const isResetNeeded = (currentForegroundCode !== undefined && nextForegroundCode === undefined) ||
|
|
71880
|
+
(currentBackgroundCode !== undefined && nextBackgroundCode === undefined);
|
|
71881
|
+
if (isResetNeeded) {
|
|
71882
|
+
line += ANSI_RESET;
|
|
71883
|
+
currentForegroundCode = undefined;
|
|
71884
|
+
currentBackgroundCode = undefined;
|
|
71885
|
+
}
|
|
71886
|
+
if (nextForegroundCode !== undefined && nextForegroundCode !== currentForegroundCode) {
|
|
71887
|
+
line += nextForegroundCode;
|
|
71888
|
+
}
|
|
71889
|
+
if (nextBackgroundCode !== undefined && nextBackgroundCode !== currentBackgroundCode) {
|
|
71890
|
+
line += nextBackgroundCode;
|
|
71891
|
+
}
|
|
71892
|
+
currentForegroundCode = nextForegroundCode;
|
|
71893
|
+
currentBackgroundCode = nextBackgroundCode;
|
|
71894
|
+
}
|
|
71895
|
+
line += character;
|
|
71896
|
+
}
|
|
71897
|
+
if (currentForegroundCode !== undefined || currentBackgroundCode !== undefined) {
|
|
71898
|
+
line += ANSI_RESET;
|
|
71899
|
+
}
|
|
71900
|
+
asciiArtLines.push(line);
|
|
71901
|
+
}
|
|
71902
|
+
return asciiArtLines;
|
|
71903
|
+
}
|
|
71904
|
+
/**
|
|
71905
|
+
* Computes the area-averaged color of one half-cell of the output grid.
|
|
71906
|
+
*
|
|
71907
|
+
* Color channels are alpha-weighted so semi-transparent edge pixels do not darken towards black.
|
|
71908
|
+
*
|
|
71909
|
+
* @private helper of `convertImageDataToAsciiArt`
|
|
71910
|
+
*/
|
|
71911
|
+
function computeHalfCellColor(imageData, columnIndex, halfCellRowIndex, columns, halfCellRowCount, alphaThreshold) {
|
|
71912
|
+
const startX = Math.floor((columnIndex * imageData.width) / columns);
|
|
71913
|
+
const endX = Math.max(startX + 1, Math.floor(((columnIndex + 1) * imageData.width) / columns));
|
|
71914
|
+
const startY = Math.floor((halfCellRowIndex * imageData.height) / halfCellRowCount);
|
|
71915
|
+
const endY = Math.max(startY + 1, Math.floor(((halfCellRowIndex + 1) * imageData.height) / halfCellRowCount));
|
|
71916
|
+
let redSum = 0;
|
|
71917
|
+
let greenSum = 0;
|
|
71918
|
+
let blueSum = 0;
|
|
71919
|
+
let alphaSum = 0;
|
|
71920
|
+
let sampledPixelCount = 0;
|
|
71921
|
+
for (let y = startY; y < endY && y < imageData.height; y++) {
|
|
71922
|
+
for (let x = startX; x < endX && x < imageData.width; x++) {
|
|
71923
|
+
const pixelOffset = (y * imageData.width + x) * RGBA_CHANNEL_COUNT;
|
|
71924
|
+
const alpha = imageData.data[pixelOffset + 3];
|
|
71925
|
+
redSum += imageData.data[pixelOffset] * alpha;
|
|
71926
|
+
greenSum += imageData.data[pixelOffset + 1] * alpha;
|
|
71927
|
+
blueSum += imageData.data[pixelOffset + 2] * alpha;
|
|
71928
|
+
alphaSum += alpha;
|
|
71929
|
+
sampledPixelCount++;
|
|
71930
|
+
}
|
|
71931
|
+
}
|
|
71932
|
+
const averageAlpha = sampledPixelCount === 0 ? 0 : alphaSum / sampledPixelCount;
|
|
71933
|
+
if (averageAlpha < alphaThreshold || alphaSum === 0) {
|
|
71934
|
+
return { red: 0, green: 0, blue: 0, isOpaque: false };
|
|
71935
|
+
}
|
|
71936
|
+
return {
|
|
71937
|
+
red: Math.round(redSum / alphaSum),
|
|
71938
|
+
green: Math.round(greenSum / alphaSum),
|
|
71939
|
+
blue: Math.round(blueSum / alphaSum),
|
|
71940
|
+
isOpaque: true,
|
|
71941
|
+
};
|
|
71942
|
+
}
|
|
71943
|
+
/**
|
|
71944
|
+
* Creates the ANSI escape code that sets the foreground color of following characters.
|
|
71945
|
+
*
|
|
71946
|
+
* @private helper of `convertImageDataToAsciiArt`
|
|
71947
|
+
*/
|
|
71948
|
+
function createForegroundColorCode(color, colorDepth) {
|
|
71949
|
+
if (colorDepth === 'TRUE_COLOR') {
|
|
71950
|
+
return `\u001b[38;2;${color.red};${color.green};${color.blue}m`;
|
|
71951
|
+
}
|
|
71952
|
+
return `\u001b[38;5;${mapColorToAnsi256(color)}m`;
|
|
71953
|
+
}
|
|
71954
|
+
/**
|
|
71955
|
+
* Creates the ANSI escape code that sets the background color of following characters.
|
|
71956
|
+
*
|
|
71957
|
+
* @private helper of `convertImageDataToAsciiArt`
|
|
71958
|
+
*/
|
|
71959
|
+
function createBackgroundColorCode(color, colorDepth) {
|
|
71960
|
+
if (colorDepth === 'TRUE_COLOR') {
|
|
71961
|
+
return `\u001b[48;2;${color.red};${color.green};${color.blue}m`;
|
|
71962
|
+
}
|
|
71963
|
+
return `\u001b[48;5;${mapColorToAnsi256(color)}m`;
|
|
71964
|
+
}
|
|
71965
|
+
/**
|
|
71966
|
+
* Maps a 24-bit color onto the closest entry of the 256-color ANSI palette.
|
|
71967
|
+
*
|
|
71968
|
+
* Uses the 6×6×6 color cube (entries 16-231) and the grayscale ramp (entries 232-255).
|
|
71969
|
+
*
|
|
71970
|
+
* @private helper of `convertImageDataToAsciiArt`
|
|
71971
|
+
*/
|
|
71972
|
+
function mapColorToAnsi256(color) {
|
|
71973
|
+
const { red, green, blue } = color;
|
|
71974
|
+
// Note: Prefer the finer grayscale ramp when the color is (nearly) achromatic
|
|
71975
|
+
const maxChannel = Math.max(red, green, blue);
|
|
71976
|
+
const minChannel = Math.min(red, green, blue);
|
|
71977
|
+
if (maxChannel - minChannel < ANSI_256_ACHROMATIC_CHANNEL_SPREAD) {
|
|
71978
|
+
const gray = Math.round((red + green + blue) / 3);
|
|
71979
|
+
if (gray < 4) {
|
|
71980
|
+
return 16; // <- Note: Pure black lives in the color cube
|
|
71981
|
+
}
|
|
71982
|
+
if (gray > ANSI_256_NEAR_WHITE_GRAY_LEVEL) {
|
|
71983
|
+
return ANSI_256_WHITE_INDEX; // <- Note: Pure white lives in the color cube
|
|
71984
|
+
}
|
|
71985
|
+
return 232 + Math.round(((gray - 8) / ANSI_256_GRAYSCALE_RAMP_MAX_LEVEL) * ANSI_256_GRAYSCALE_RAMP_INDEX_SPAN);
|
|
71986
|
+
}
|
|
71987
|
+
const redIndex = Math.round((red / 255) * 5);
|
|
71988
|
+
const greenIndex = Math.round((green / 255) * 5);
|
|
71989
|
+
const blueIndex = Math.round((blue / 255) * 5);
|
|
71990
|
+
return 16 + 36 * redIndex + 6 * greenIndex + blueIndex;
|
|
71991
|
+
}
|
|
71992
|
+
|
|
71993
|
+
/**
|
|
71994
|
+
* Stable zeroed interaction state used by non-interactive render paths.
|
|
71995
|
+
*
|
|
71996
|
+
* @private utility of the avatar rendering system
|
|
71997
|
+
*/
|
|
71998
|
+
const IDLE_AVATAR_INTERACTION_STATE = {
|
|
71999
|
+
gazeX: 0,
|
|
72000
|
+
gazeY: 0,
|
|
72001
|
+
bodyOffsetX: 0,
|
|
72002
|
+
bodyOffsetY: 0,
|
|
72003
|
+
intensity: 0,
|
|
72004
|
+
isPointerActive: false,
|
|
72005
|
+
pointerType: 'idle',
|
|
72006
|
+
};
|
|
72007
|
+
/**
|
|
72008
|
+
* Returns the neutral interaction state used by static/server-side renders.
|
|
72009
|
+
*
|
|
72010
|
+
* @returns Zeroed interaction state.
|
|
72011
|
+
*
|
|
72012
|
+
* @private utility of the avatar rendering system
|
|
72013
|
+
*/
|
|
72014
|
+
function createIdleAvatarInteractionState() {
|
|
72015
|
+
return IDLE_AVATAR_INTERACTION_STATE;
|
|
72016
|
+
}
|
|
72017
|
+
|
|
72018
|
+
/**
|
|
72019
|
+
* Resolves the stable avatar render inputs reused across multiple frames.
|
|
72020
|
+
*
|
|
72021
|
+
* @param options Avatar identity and visual selection.
|
|
72022
|
+
* @returns Stable render data ready to be used by `renderAvatarVisual`.
|
|
72023
|
+
*
|
|
72024
|
+
* @private shared helper for canvas avatar rendering
|
|
72025
|
+
*/
|
|
72026
|
+
function resolveAvatarRenderDefinition(options) {
|
|
72027
|
+
const avatarDefinition = normalizeAvatarDefinition(options.avatarDefinition);
|
|
72028
|
+
const surface = options.surface || 'framed';
|
|
72029
|
+
return {
|
|
72030
|
+
avatarDefinition,
|
|
72031
|
+
avatarVisual: getAvatarVisualById(options.visualId),
|
|
72032
|
+
surface,
|
|
72033
|
+
palette: createAvatarPalette(avatarDefinition, surface),
|
|
72034
|
+
createRandom: createAvatarRandomFactory(avatarDefinition),
|
|
72035
|
+
};
|
|
72036
|
+
}
|
|
72037
|
+
/**
|
|
72038
|
+
* Renders one deterministic avatar frame into the provided canvas.
|
|
72039
|
+
*
|
|
72040
|
+
* @param options Rendering options.
|
|
72041
|
+
* @param resolvedAvatarRenderDefinition Optional stable render data reused between frames.
|
|
72042
|
+
*
|
|
72043
|
+
* @private shared helper for canvas avatar rendering
|
|
72044
|
+
*/
|
|
72045
|
+
function renderAvatarVisual(options, resolvedAvatarRenderDefinition) {
|
|
72046
|
+
const resolvedRenderDefinition = resolvedAvatarRenderDefinition ||
|
|
72047
|
+
resolveAvatarRenderDefinition({
|
|
72048
|
+
avatarDefinition: options.avatarDefinition,
|
|
72049
|
+
visualId: options.visualId,
|
|
72050
|
+
surface: options.surface,
|
|
72051
|
+
});
|
|
72052
|
+
const context = options.canvas.getContext('2d');
|
|
72053
|
+
if (!context) {
|
|
72054
|
+
throw new Error('2D canvas rendering context is unavailable.');
|
|
72055
|
+
}
|
|
72056
|
+
prepareAvatarCanvas(options.canvas, context, options.size, options.devicePixelRatio || 1);
|
|
72057
|
+
resolvedRenderDefinition.avatarVisual.render({
|
|
72058
|
+
canvas: options.canvas,
|
|
72059
|
+
context,
|
|
72060
|
+
size: options.size,
|
|
72061
|
+
devicePixelRatio: options.devicePixelRatio || 1,
|
|
72062
|
+
timeMs: options.timeMs,
|
|
72063
|
+
avatarDefinition: resolvedRenderDefinition.avatarDefinition,
|
|
72064
|
+
palette: resolvedRenderDefinition.palette,
|
|
72065
|
+
createRandom: resolvedRenderDefinition.createRandom,
|
|
72066
|
+
surface: resolvedRenderDefinition.surface,
|
|
72067
|
+
interaction: options.interaction || createIdleAvatarInteractionState(),
|
|
72068
|
+
});
|
|
72069
|
+
}
|
|
72070
|
+
|
|
72071
|
+
/**
|
|
72072
|
+
* Default output width of the ASCII avatar in terminal character cells.
|
|
72073
|
+
*
|
|
72074
|
+
* @private within the repository
|
|
72075
|
+
*/
|
|
72076
|
+
const DEFAULT_AVATAR_ASCII_ART_COLUMNS = 32;
|
|
72077
|
+
/**
|
|
72078
|
+
* Stable animation timestamp used when rasterizing animated avatar visuals into a static ASCII frame.
|
|
72079
|
+
*
|
|
72080
|
+
* @private within the repository
|
|
72081
|
+
*/
|
|
72082
|
+
const STATIC_AVATAR_ASCII_ART_FRAME_TIME_MS = 840;
|
|
72083
|
+
/**
|
|
72084
|
+
* Renders one built-in avatar visual into ANSI-colored ASCII art for terminal display.
|
|
72085
|
+
*
|
|
72086
|
+
* This is the universal bridge between the canvas avatar visuals shown on the website and
|
|
72087
|
+
* text-based terminal UIs: the visual is rasterized through the exact same `renderAvatarVisual`
|
|
72088
|
+
* pipeline the web uses, then the resulting pixels are converted into colored half-block
|
|
72089
|
+
* characters by `convertImageDataToAsciiArt`.
|
|
72090
|
+
*
|
|
72091
|
+
* @param options Avatar identity, visual selection, output grid size, and the platform canvas factory.
|
|
72092
|
+
* @returns One ANSI-colored string per output row.
|
|
72093
|
+
*
|
|
72094
|
+
* @private within the repository
|
|
72095
|
+
*/
|
|
72096
|
+
function renderAvatarVisualAsciiArt(options) {
|
|
72097
|
+
var _a, _b, _c;
|
|
72098
|
+
const columns = (_a = options.columns) !== null && _a !== void 0 ? _a : DEFAULT_AVATAR_ASCII_ART_COLUMNS;
|
|
72099
|
+
const rows = (_b = options.rows) !== null && _b !== void 0 ? _b : Math.round(columns / 2);
|
|
72100
|
+
const canvas = options.createCanvas(DEFAULT_AVATAR_SIZE, DEFAULT_AVATAR_SIZE);
|
|
72101
|
+
if (!canvas.style) {
|
|
72102
|
+
// Note: `renderAvatarVisual` expects a browser canvas shape; Node.js canvases only need this tiny compatibility shim.
|
|
72103
|
+
canvas.style = {};
|
|
72104
|
+
}
|
|
72105
|
+
renderAvatarVisual({
|
|
72106
|
+
canvas,
|
|
72107
|
+
avatarDefinition: options.avatarDefinition,
|
|
72108
|
+
visualId: options.visualId,
|
|
72109
|
+
size: DEFAULT_AVATAR_SIZE,
|
|
72110
|
+
timeMs: (_c = options.timeMs) !== null && _c !== void 0 ? _c : STATIC_AVATAR_ASCII_ART_FRAME_TIME_MS,
|
|
72111
|
+
devicePixelRatio: 1,
|
|
72112
|
+
});
|
|
72113
|
+
const context = canvas.getContext('2d');
|
|
72114
|
+
if (!context) {
|
|
72115
|
+
throw new EnvironmentMismatchError(_spaceTrim.spaceTrim(`
|
|
72116
|
+
2D canvas rendering context is unavailable while converting the avatar visual to ASCII art.
|
|
72117
|
+
|
|
72118
|
+
Provide a \`createCanvas\` factory whose canvases support \`getContext('2d')\`,
|
|
72119
|
+
for example \`createCanvas\` of \`@napi-rs/canvas\` in Node.js.
|
|
72120
|
+
`));
|
|
72121
|
+
}
|
|
72122
|
+
const imageData = context.getImageData(0, 0, DEFAULT_AVATAR_SIZE, DEFAULT_AVATAR_SIZE);
|
|
72123
|
+
return convertImageDataToAsciiArt({
|
|
72124
|
+
imageData,
|
|
72125
|
+
columns,
|
|
72126
|
+
rows,
|
|
72127
|
+
colorDepth: options.colorDepth,
|
|
72128
|
+
});
|
|
72129
|
+
}
|
|
72130
|
+
|
|
72131
|
+
/**
|
|
72132
|
+
* Default built-in avatar visual used when an agent does not define `META IMAGE`.
|
|
72133
|
+
*
|
|
72134
|
+
* @private shared avatar contract
|
|
72135
|
+
*/
|
|
72136
|
+
const DEFAULT_AGENT_AVATAR_VISUAL_ID = 'octopus3d4';
|
|
72137
|
+
/**
|
|
72138
|
+
* Resolves the avatar visual preferred by an agent, then falls back to a federated server default
|
|
72139
|
+
* and finally to the caller/server default.
|
|
72140
|
+
*
|
|
72141
|
+
* @param agent Agent metadata and optional remote-profile visual id.
|
|
72142
|
+
* @param defaultAvatarVisualId Optional metadata-resolved server default.
|
|
72143
|
+
* @returns Supported avatar visual id.
|
|
72144
|
+
*
|
|
72145
|
+
* @private shared avatar contract
|
|
72146
|
+
*/
|
|
72147
|
+
function resolveAgentAvatarVisualId(agent, defaultAvatarVisualId = DEFAULT_AGENT_AVATAR_VISUAL_ID) {
|
|
72148
|
+
var _a;
|
|
72149
|
+
return (resolveAvatarVisualId((_a = agent.meta) === null || _a === void 0 ? void 0 : _a.avatar) ||
|
|
72150
|
+
agent.avatarVisualId ||
|
|
72151
|
+
agent.defaultAgentAvatarVisualId ||
|
|
72152
|
+
defaultAvatarVisualId);
|
|
72153
|
+
}
|
|
72154
|
+
|
|
72155
|
+
/**
|
|
72156
|
+
* Detects the ANSI color depth supported by the current terminal.
|
|
72157
|
+
*
|
|
72158
|
+
* Prefers 24-bit true color when the environment advertises it (modern terminals such as
|
|
72159
|
+
* Windows Terminal, ConEmu, VS Code, mintty, iTerm2, and WezTerm) and falls back to the
|
|
72160
|
+
* portable 256-color palette otherwise.
|
|
72161
|
+
*
|
|
72162
|
+
* Note: `$` is used to indicate that this function is not a pure function - it reads the process environment
|
|
72163
|
+
*
|
|
72164
|
+
* @returns Color depth usable by `convertImageDataToAsciiArt`
|
|
72165
|
+
*
|
|
72166
|
+
* @private within the repository
|
|
72167
|
+
*/
|
|
72168
|
+
function $detectTerminalAnsiColorDepth() {
|
|
72169
|
+
if (typeof process === 'undefined' || !process.env) {
|
|
72170
|
+
return 'ANSI_256';
|
|
72171
|
+
}
|
|
72172
|
+
const colorTerm = (process.env.COLORTERM || '').toLowerCase();
|
|
72173
|
+
if (colorTerm.includes('truecolor') || colorTerm.includes('24bit')) {
|
|
72174
|
+
return 'TRUE_COLOR';
|
|
72175
|
+
}
|
|
72176
|
+
if (process.env.WT_SESSION !== undefined) {
|
|
72177
|
+
return 'TRUE_COLOR'; // <- Note: Windows Terminal always supports true color but does not set COLORTERM
|
|
72178
|
+
}
|
|
72179
|
+
if (process.env.ConEmuANSI === 'ON') {
|
|
72180
|
+
return 'TRUE_COLOR';
|
|
72181
|
+
}
|
|
72182
|
+
const termProgram = process.env.TERM_PROGRAM || '';
|
|
72183
|
+
if (['vscode', 'iTerm.app', 'WezTerm', 'ghostty', 'Hyper'].includes(termProgram)) {
|
|
72184
|
+
return 'TRUE_COLOR';
|
|
72185
|
+
}
|
|
72186
|
+
const term = (process.env.TERM || '').toLowerCase();
|
|
72187
|
+
if (term.includes('truecolor') || term.includes('24bit') || term.includes('direct')) {
|
|
72188
|
+
return 'TRUE_COLOR';
|
|
72189
|
+
}
|
|
72190
|
+
return 'ANSI_256';
|
|
72191
|
+
}
|
|
72192
|
+
|
|
72193
|
+
/**
|
|
72194
|
+
* Output width of the coder-run agent visual in terminal character cells.
|
|
72195
|
+
*
|
|
72196
|
+
* @private internal constant of coder run UI
|
|
72197
|
+
*/
|
|
72198
|
+
const CODER_RUN_AGENT_VISUAL_COLUMNS = 24;
|
|
72199
|
+
/**
|
|
72200
|
+
* Output height of the coder-run agent visual in terminal character cells.
|
|
72201
|
+
*
|
|
72202
|
+
* Half of the columns keeps the square avatar visually square in a common terminal font.
|
|
72203
|
+
*
|
|
72204
|
+
* @private internal constant of coder run UI
|
|
72205
|
+
*/
|
|
72206
|
+
const CODER_RUN_AGENT_VISUAL_ROWS = 12;
|
|
72207
|
+
/**
|
|
72208
|
+
* Builds the ANSI ASCII-art visual of the `--agent` book shown above the coder-run dashboard.
|
|
72209
|
+
*
|
|
72210
|
+
* The agent's avatar visual is resolved the same way as on the website - the `META AVATAR`
|
|
72211
|
+
* commitment wins, then the `META VISUAL` commitment, then the shared default visual - and is
|
|
72212
|
+
* rendered dynamically through the shared canvas avatar pipeline into terminal ASCII art.
|
|
72213
|
+
*
|
|
72214
|
+
* The visual is decorative, so any failure (for example when the optional `@napi-rs/canvas`
|
|
72215
|
+
* module is not installed) returns `null` and the caller keeps the default brand banner.
|
|
72216
|
+
*
|
|
72217
|
+
* @param agentSource Source of the `--agent` book file.
|
|
72218
|
+
* @returns ANSI-colored ASCII-art lines or `null` when the visual cannot be rendered.
|
|
72219
|
+
*/
|
|
72220
|
+
async function buildCoderRunAgentVisual(agentSource) {
|
|
72221
|
+
try {
|
|
72222
|
+
// Note: `@napi-rs/canvas` is an optional native module, so it is imported dynamically and lazily
|
|
72223
|
+
const { createCanvas } = await import('@napi-rs/canvas');
|
|
72224
|
+
const agentBasicInformation = parseAgentSource(agentSource);
|
|
72225
|
+
const avatarDefinition = createAvatarDefinitionFromAgentBasicInformation(agentBasicInformation);
|
|
72226
|
+
const avatarVisualId = resolveAgentAvatarVisualId(agentBasicInformation, resolveAvatarVisualId(agentBasicInformation.meta.visual) || DEFAULT_AGENT_AVATAR_VISUAL_ID);
|
|
72227
|
+
return renderAvatarVisualAsciiArt({
|
|
72228
|
+
avatarDefinition,
|
|
72229
|
+
visualId: avatarVisualId,
|
|
72230
|
+
columns: CODER_RUN_AGENT_VISUAL_COLUMNS,
|
|
72231
|
+
rows: CODER_RUN_AGENT_VISUAL_ROWS,
|
|
72232
|
+
colorDepth: $detectTerminalAnsiColorDepth(),
|
|
72233
|
+
createCanvas: (width, height) => createCanvas(width, height),
|
|
72234
|
+
});
|
|
72235
|
+
}
|
|
72236
|
+
catch (error) {
|
|
72237
|
+
return null;
|
|
72238
|
+
}
|
|
72239
|
+
}
|
|
72240
|
+
|
|
71442
72241
|
/**
|
|
71443
72242
|
* Formats commit message lines for console display.
|
|
71444
72243
|
*/
|
|
@@ -73355,13 +74154,15 @@
|
|
|
73355
74154
|
startPauseListenerIfNeeded(isRichUiEnabled);
|
|
73356
74155
|
try {
|
|
73357
74156
|
const resolvedCoderContext = await resolveCoderContext(options.context, process.cwd());
|
|
73358
|
-
const
|
|
74157
|
+
const resolvedCoderAgent = await resolveCoderAgent(options.agent, process.cwd());
|
|
74158
|
+
const resolvedAgentSystemMessage = resolvedCoderAgent === null || resolvedCoderAgent === void 0 ? void 0 : resolvedCoderAgent.systemMessage;
|
|
73359
74159
|
if (await runDryRunIfRequested(options)) {
|
|
73360
74160
|
return;
|
|
73361
74161
|
}
|
|
73362
74162
|
const { runner, actualRunnerModel, runnerMetadata } = resolvePromptRunner(options);
|
|
73363
74163
|
console.info(colors__default["default"].green(`Running prompts with ${runner.name}`));
|
|
73364
74164
|
initializeRunUi(uiHandle, runner.name, actualRunnerModel, options);
|
|
74165
|
+
await initializeRunUiAgentVisual(uiHandle, resolvedCoderAgent === null || resolvedCoderAgent === void 0 ? void 0 : resolvedCoderAgent.agentSource);
|
|
73365
74166
|
await seedCachedAveragePromptDuration({
|
|
73366
74167
|
options,
|
|
73367
74168
|
actualRunnerModel,
|
|
@@ -73599,6 +74400,20 @@
|
|
|
73599
74400
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setPhase('loading');
|
|
73600
74401
|
uiHandle === null || uiHandle === void 0 ? void 0 : uiHandle.state.setStatusMessage(`Running prompts with ${runnerName}`);
|
|
73601
74402
|
}
|
|
74403
|
+
/**
|
|
74404
|
+
* Renders the `--agent` book avatar as ASCII art and shows it instead of the default brand banner.
|
|
74405
|
+
*
|
|
74406
|
+
* Keeps the default banner when no agent is selected, the UI is disabled, or the visual cannot be rendered.
|
|
74407
|
+
*/
|
|
74408
|
+
async function initializeRunUiAgentVisual(uiHandle, agentSource) {
|
|
74409
|
+
if (!uiHandle || !agentSource) {
|
|
74410
|
+
return;
|
|
74411
|
+
}
|
|
74412
|
+
const agentVisualLines = await buildCoderRunAgentVisual(agentSource);
|
|
74413
|
+
if (agentVisualLines) {
|
|
74414
|
+
uiHandle.state.setAgentVisualLines(agentVisualLines);
|
|
74415
|
+
}
|
|
74416
|
+
}
|
|
73602
74417
|
/**
|
|
73603
74418
|
* Loads prompt files, updates progress displays, and selects the next runnable prompt.
|
|
73604
74419
|
*/
|