@promptbook/cli 0.113.0-4 → 0.113.0-6

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.
Files changed (54) hide show
  1. package/apps/agents-server/src/app/agents/[agentName]/api/book/route.ts +13 -1
  2. package/apps/agents-server/src/search/createDefaultServerSearchProviders/loadLocalOrganizationSearchDataset.ts +12 -1
  3. package/apps/agents-server/src/utils/agentOrganization/loadAgentOrganizationState.ts +13 -1
  4. package/apps/agents-server/src/utils/createLocalAgentSourceImporter.ts +159 -0
  5. package/apps/agents-server/src/utils/createMissingImportedAgentFallback.ts +60 -0
  6. package/apps/agents-server/src/utils/customDomainRouting.ts +157 -12
  7. package/apps/agents-server/src/utils/externalChatRunner/processExternalUserChatJob.ts +1 -1
  8. package/apps/agents-server/src/utils/importAgentWithFallback.ts +1 -58
  9. package/apps/agents-server/src/utils/localAgentRouteReferences.ts +167 -0
  10. package/apps/agents-server/src/utils/localChatRunner/processLocalUserChatJob.ts +1 -1
  11. package/apps/agents-server/src/utils/managementApi/managementApiAgents.ts +17 -3
  12. package/apps/agents-server/src/utils/resolveAgentStateFromSource.ts +7 -1
  13. package/apps/agents-server/src/utils/resolveInheritedAgentSource.ts +54 -5
  14. package/apps/agents-server/src/utils/resolveServerAgentContext.ts +12 -1
  15. package/apps/agents-server/src/utils/resolveStoredAgentState.ts +2 -1
  16. package/apps/agents-server/src/utils/userChat/userChatMessageLifecycle.ts +39 -9
  17. package/apps/agents-server/tests/e2e/support/ChatHistoryNavigationSupport.ts +5 -0
  18. package/esm/index.es.js +803 -39
  19. package/esm/index.es.js.map +1 -1
  20. package/esm/scripts/run-codex-prompts/common/resolveCoderAgent.d.ts +20 -0
  21. package/esm/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +5 -0
  22. package/esm/scripts/run-codex-prompts/ui/buildCoderRunAgentVisual.d.ts +29 -0
  23. package/esm/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +4 -0
  24. package/esm/src/avatars/renderAvatarVisualAsciiArt.d.ts +75 -0
  25. package/esm/src/utils/ascii-art/$detectTerminalAnsiColorDepth.d.ts +15 -0
  26. package/esm/src/utils/ascii-art/convertImageDataToAsciiArt.d.ts +80 -0
  27. package/esm/src/version.d.ts +1 -1
  28. package/package.json +1 -1
  29. package/src/avatars/avatarAnimationScheduler.ts +2 -1
  30. package/src/avatars/renderAvatarVisualAsciiArt.ts +138 -0
  31. package/src/avatars/visuals/octopus3d3AvatarVisual.ts +6 -2
  32. package/src/avatars/visuals/octopus3d4AvatarVisual.ts +14 -18
  33. package/src/cli/cli-commands/agents-server/buildAgentsServer.ts +3 -1
  34. package/src/cli/cli-commands/coder/boilerplateTemplates.ts +14 -21
  35. package/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts +1 -4
  36. package/src/cli/cli-commands/coder/run.ts +2 -9
  37. package/src/commitments/TEAM/TEAM.ts +5 -5
  38. package/src/other/templates/getTemplatesPipelineCollection.ts +781 -943
  39. package/src/utils/ascii-art/$detectTerminalAnsiColorDepth.ts +45 -0
  40. package/src/utils/ascii-art/convertImageDataToAsciiArt.ts +396 -0
  41. package/src/version.ts +2 -2
  42. package/src/versions.txt +2 -0
  43. package/umd/index.umd.js +803 -39
  44. package/umd/index.umd.js.map +1 -1
  45. package/umd/scripts/run-codex-prompts/common/resolveCoderAgent.d.ts +20 -0
  46. package/umd/scripts/run-codex-prompts/ui/CoderRunUiState.d.ts +5 -0
  47. package/umd/scripts/run-codex-prompts/ui/buildCoderRunAgentVisual.d.ts +29 -0
  48. package/umd/scripts/run-codex-prompts/ui/buildCoderRunUiFrame.d.ts +4 -0
  49. package/umd/src/avatars/renderAvatarVisualAsciiArt.d.ts +75 -0
  50. package/umd/src/utils/ascii-art/$detectTerminalAnsiColorDepth.d.ts +15 -0
  51. package/umd/src/utils/ascii-art/convertImageDataToAsciiArt.d.ts +80 -0
  52. package/umd/src/version.d.ts +1 -1
  53. package/esm/scripts/run-codex-prompts/common/resolveAgentSystemMessage.d.ts +0 -6
  54. package/umd/scripts/run-codex-prompts/common/resolveAgentSystemMessage.d.ts +0 -6
@@ -0,0 +1,20 @@
1
+ import type { string_book } from '../../../src/book-2.0/agent-source/string_book';
2
+ /**
3
+ * Agent data resolved from the optional `--agent` book file.
4
+ */
5
+ export type ResolvedCoderAgent = {
6
+ /**
7
+ * Raw source of the agent `.book` file.
8
+ */
9
+ readonly agentSource: string_book;
10
+ /**
11
+ * Compiled system message injected into each coding prompt.
12
+ */
13
+ readonly systemMessage: string;
14
+ };
15
+ /**
16
+ * Reads an optional agent `.book` file and compiles its system message for injection into coder prompts.
17
+ *
18
+ * Returns `undefined` when no agent path is provided.
19
+ */
20
+ export declare function resolveCoderAgent(agentPath: string | undefined, currentWorkingDirectory: string): Promise<ResolvedCoderAgent | undefined>;
@@ -41,6 +41,7 @@ export type { CoderRunProgressSnapshot };
41
41
  */
42
42
  export declare class CoderRunUiState extends EventEmitter {
43
43
  config: CoderRunConfig;
44
+ agentVisualLines: string[] | undefined;
44
45
  currentPromptLabel: string;
45
46
  currentScriptPaths: string[];
46
47
  currentAttempt: number;
@@ -72,6 +73,10 @@ export declare class CoderRunUiState extends EventEmitter {
72
73
  * Replaces the configuration shown in the UI header.
73
74
  */
74
75
  setConfig(config: CoderRunConfig): void;
76
+ /**
77
+ * Replaces the ASCII-art agent visual shown instead of the default brand banner.
78
+ */
79
+ setAgentVisualLines(agentVisualLines: ReadonlyArray<string> | undefined): void;
75
80
  /**
76
81
  * Feeds new prompt statistics from the main loop so the progress bar updates.
77
82
  */
@@ -0,0 +1,29 @@
1
+ import type { string_book } from '../../../src/book-2.0/agent-source/string_book';
2
+ /**
3
+ * Output width of the coder-run agent visual in terminal character cells.
4
+ *
5
+ * @private internal constant of coder run UI
6
+ */
7
+ export declare const CODER_RUN_AGENT_VISUAL_COLUMNS = 24;
8
+ /**
9
+ * Output height of the coder-run agent visual in terminal character cells.
10
+ *
11
+ * Half of the columns keeps the square avatar visually square in a common terminal font.
12
+ *
13
+ * @private internal constant of coder run UI
14
+ */
15
+ export declare const CODER_RUN_AGENT_VISUAL_ROWS = 12;
16
+ /**
17
+ * Builds the ANSI ASCII-art visual of the `--agent` book shown above the coder-run dashboard.
18
+ *
19
+ * The agent's avatar visual is resolved the same way as on the website - the `META AVATAR`
20
+ * commitment wins, then the `META VISUAL` commitment, then the shared default visual - and is
21
+ * rendered dynamically through the shared canvas avatar pipeline into terminal ASCII art.
22
+ *
23
+ * The visual is decorative, so any failure (for example when the optional `@napi-rs/canvas`
24
+ * module is not installed) returns `null` and the caller keeps the default brand banner.
25
+ *
26
+ * @param agentSource Source of the `--agent` book file.
27
+ * @returns ANSI-colored ASCII-art lines or `null` when the visual cannot be rendered.
28
+ */
29
+ export declare function buildCoderRunAgentVisual(agentSource: string_book): Promise<ReadonlyArray<string> | null>;
@@ -11,6 +11,10 @@ export type BuildCoderRunUiFrameOptions = {
11
11
  readonly terminalWidth: number;
12
12
  readonly animationFrame: number;
13
13
  readonly spinner: string;
14
+ /**
15
+ * ANSI ASCII-art lines of the `--agent` avatar visual shown instead of the default brand banner.
16
+ */
17
+ readonly agentVisualLines?: readonly string[];
14
18
  readonly pauseState: CoderRunPauseState;
15
19
  readonly pauseTargetLabel: string;
16
20
  readonly config: CoderRunConfig;
@@ -0,0 +1,75 @@
1
+ import type { AsciiArtColorDepth } from '../utils/ascii-art/convertImageDataToAsciiArt';
2
+ import type { AvatarDefinition } from './types/AvatarDefinition';
3
+ import type { AvatarVisualId } from './types/AvatarVisualDefinition';
4
+ /**
5
+ * Default output width of the ASCII avatar in terminal character cells.
6
+ *
7
+ * @private within the repository
8
+ */
9
+ export declare const DEFAULT_AVATAR_ASCII_ART_COLUMNS = 32;
10
+ /**
11
+ * Factory creating a drawable canvas of the requested pixel size.
12
+ *
13
+ * In browsers this is typically `document.createElement('canvas')` (with width/height set),
14
+ * in Node.js an adapter around `createCanvas` of `@napi-rs/canvas` or a compatible library.
15
+ *
16
+ * @private within the repository
17
+ */
18
+ export type CreateCanvasForAsciiArt = (width: number, height: number) => HTMLCanvasElement;
19
+ /**
20
+ * Options for `renderAvatarVisualAsciiArt`.
21
+ *
22
+ * @private within the repository
23
+ */
24
+ export type RenderAvatarVisualAsciiArtOptions = {
25
+ /**
26
+ * Stable visual identity of the rendered agent avatar.
27
+ */
28
+ readonly avatarDefinition: AvatarDefinition;
29
+ /**
30
+ * Built-in avatar visual to render, the same one used on the website.
31
+ */
32
+ readonly visualId: AvatarVisualId;
33
+ /**
34
+ * Output width in terminal character cells.
35
+ *
36
+ * @default `DEFAULT_AVATAR_ASCII_ART_COLUMNS`
37
+ */
38
+ readonly columns?: number;
39
+ /**
40
+ * Output height in terminal character cells.
41
+ *
42
+ * @default `columns / 2` so the square avatar stays visually square in a common terminal font
43
+ */
44
+ readonly rows?: number;
45
+ /**
46
+ * Color depth of the emitted ANSI escape codes.
47
+ *
48
+ * @default 'TRUE_COLOR'
49
+ */
50
+ readonly colorDepth?: AsciiArtColorDepth;
51
+ /**
52
+ * Animation timestamp for animated visuals.
53
+ *
54
+ * @default `STATIC_AVATAR_ASCII_ART_FRAME_TIME_MS`
55
+ */
56
+ readonly timeMs?: number;
57
+ /**
58
+ * Platform-specific canvas factory used to rasterize the visual.
59
+ */
60
+ readonly createCanvas: CreateCanvasForAsciiArt;
61
+ };
62
+ /**
63
+ * Renders one built-in avatar visual into ANSI-colored ASCII art for terminal display.
64
+ *
65
+ * This is the universal bridge between the canvas avatar visuals shown on the website and
66
+ * text-based terminal UIs: the visual is rasterized through the exact same `renderAvatarVisual`
67
+ * pipeline the web uses, then the resulting pixels are converted into colored half-block
68
+ * characters by `convertImageDataToAsciiArt`.
69
+ *
70
+ * @param options Avatar identity, visual selection, output grid size, and the platform canvas factory.
71
+ * @returns One ANSI-colored string per output row.
72
+ *
73
+ * @private within the repository
74
+ */
75
+ export declare function renderAvatarVisualAsciiArt(options: RenderAvatarVisualAsciiArtOptions): ReadonlyArray<string>;
@@ -0,0 +1,15 @@
1
+ import type { AsciiArtColorDepth } from './convertImageDataToAsciiArt';
2
+ /**
3
+ * Detects the ANSI color depth supported by the current terminal.
4
+ *
5
+ * Prefers 24-bit true color when the environment advertises it (modern terminals such as
6
+ * Windows Terminal, ConEmu, VS Code, mintty, iTerm2, and WezTerm) and falls back to the
7
+ * portable 256-color palette otherwise.
8
+ *
9
+ * Note: `$` is used to indicate that this function is not a pure function - it reads the process environment
10
+ *
11
+ * @returns Color depth usable by `convertImageDataToAsciiArt`
12
+ *
13
+ * @private within the repository
14
+ */
15
+ export declare function $detectTerminalAnsiColorDepth(): AsciiArtColorDepth;
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Color depth of the ANSI escape codes emitted by the ASCII-art conversion.
3
+ *
4
+ * - `TRUE_COLOR` emits 24-bit `38;2;r;g;b` / `48;2;r;g;b` sequences
5
+ * - `ANSI_256` approximates colors on the 256-color ANSI cube for older terminals
6
+ *
7
+ * @private within the repository
8
+ */
9
+ export type AsciiArtColorDepth = 'TRUE_COLOR' | 'ANSI_256';
10
+ /**
11
+ * Minimal structural subset of the DOM `ImageData` accepted by the ASCII-art conversion.
12
+ *
13
+ * Works with browser canvas `ImageData`, `@napi-rs/canvas` image data, or any raw RGBA buffer.
14
+ *
15
+ * @private within the repository
16
+ */
17
+ export type AsciiArtImageData = {
18
+ /**
19
+ * Source image width in pixels.
20
+ */
21
+ readonly width: number;
22
+ /**
23
+ * Source image height in pixels.
24
+ */
25
+ readonly height: number;
26
+ /**
27
+ * Flat RGBA pixel buffer with 4 bytes per pixel.
28
+ */
29
+ readonly data: ArrayLike<number>;
30
+ };
31
+ /**
32
+ * Options for `convertImageDataToAsciiArt`.
33
+ *
34
+ * @private within the repository
35
+ */
36
+ export type ConvertImageDataToAsciiArtOptions = {
37
+ /**
38
+ * Source pixels to convert.
39
+ */
40
+ readonly imageData: AsciiArtImageData;
41
+ /**
42
+ * Output width in terminal character cells.
43
+ */
44
+ readonly columns: number;
45
+ /**
46
+ * Output height in terminal character cells.
47
+ *
48
+ * Each character cell renders two vertically stacked pixels, so `rows = columns / 2`
49
+ * keeps a square image visually square in a common terminal font.
50
+ */
51
+ readonly rows: number;
52
+ /**
53
+ * Color depth of the emitted ANSI escape codes.
54
+ *
55
+ * @default 'TRUE_COLOR'
56
+ */
57
+ readonly colorDepth?: AsciiArtColorDepth;
58
+ /**
59
+ * Alpha channel value (0-255) below which an averaged half-cell is treated as fully transparent.
60
+ *
61
+ * @default 32
62
+ */
63
+ readonly alphaThreshold?: number;
64
+ };
65
+ /**
66
+ * Converts raw RGBA image pixels into colored ASCII art for ANSI terminals.
67
+ *
68
+ * This is the universal image-to-terminal technique used across the repository:
69
+ * every output character cell covers a rectangular region of source pixels which is
70
+ * split into a top and bottom half; each half is area-averaged and rendered with
71
+ * half-block characters (`▀` / `▄`) so one character shows two "pixels" vertically.
72
+ * Transparent halves keep the terminal background so non-rectangular images
73
+ * (for example rounded avatar cards) compose naturally into any terminal UI.
74
+ *
75
+ * @param options Source pixels, output grid size, and ANSI color depth.
76
+ * @returns One ANSI-colored string per output row, each ending with a color reset.
77
+ *
78
+ * @private within the repository
79
+ */
80
+ export declare function convertImageDataToAsciiArt(options: ConvertImageDataToAsciiArtOptions): ReadonlyArray<string>;
@@ -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.113.0-3`).
18
+ * It follows semantic versioning (e.g., `0.113.0-5`).
19
19
  *
20
20
  * @generated
21
21
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@promptbook/cli",
3
- "version": "0.113.0-4",
3
+ "version": "0.113.0-6",
4
4
  "description": "Promptbook: Create persistent AI agents that turn your company's scattered knowledge into action",
5
5
  "private": false,
6
6
  "sideEffects": false,
@@ -133,7 +133,8 @@ function ensureAvatarAnimationLoop(): void {
133
133
  // Run the most stale listeners first so each avatar keeps its target FPS even when
134
134
  // total work exceeds the per-frame budget.
135
135
  dueListenerEntries.sort(
136
- (firstListenerEntry, secondListenerEntry) => firstListenerEntry.lastRunAtMs - secondListenerEntry.lastRunAtMs,
136
+ (firstListenerEntry, secondListenerEntry) =>
137
+ firstListenerEntry.lastRunAtMs - secondListenerEntry.lastRunAtMs,
137
138
  );
138
139
 
139
140
  const listenersToRunCount = Math.min(dueListenerEntries.length, MAX_AVATAR_LISTENERS_PER_FRAME);
@@ -0,0 +1,138 @@
1
+ import { spaceTrim } from 'spacetrim';
2
+ import { EnvironmentMismatchError } from '../errors/EnvironmentMismatchError';
3
+ import type { AsciiArtColorDepth } from '../utils/ascii-art/convertImageDataToAsciiArt';
4
+ import { convertImageDataToAsciiArt } from '../utils/ascii-art/convertImageDataToAsciiArt';
5
+ import { DEFAULT_AVATAR_SIZE } from './avatarRenderingUtils';
6
+ import { renderAvatarVisual } from './renderAvatarVisual';
7
+ import type { AvatarDefinition } from './types/AvatarDefinition';
8
+ import type { AvatarVisualId } from './types/AvatarVisualDefinition';
9
+
10
+ /**
11
+ * Default output width of the ASCII avatar in terminal character cells.
12
+ *
13
+ * @private within the repository
14
+ */
15
+ export const DEFAULT_AVATAR_ASCII_ART_COLUMNS = 32;
16
+
17
+ /**
18
+ * Stable animation timestamp used when rasterizing animated avatar visuals into a static ASCII frame.
19
+ *
20
+ * @private within the repository
21
+ */
22
+ const STATIC_AVATAR_ASCII_ART_FRAME_TIME_MS = 840;
23
+
24
+ /**
25
+ * Factory creating a drawable canvas of the requested pixel size.
26
+ *
27
+ * In browsers this is typically `document.createElement('canvas')` (with width/height set),
28
+ * in Node.js an adapter around `createCanvas` of `@napi-rs/canvas` or a compatible library.
29
+ *
30
+ * @private within the repository
31
+ */
32
+ export type CreateCanvasForAsciiArt = (width: number, height: number) => HTMLCanvasElement;
33
+
34
+ /**
35
+ * Options for `renderAvatarVisualAsciiArt`.
36
+ *
37
+ * @private within the repository
38
+ */
39
+ export type RenderAvatarVisualAsciiArtOptions = {
40
+ /**
41
+ * Stable visual identity of the rendered agent avatar.
42
+ */
43
+ readonly avatarDefinition: AvatarDefinition;
44
+
45
+ /**
46
+ * Built-in avatar visual to render, the same one used on the website.
47
+ */
48
+ readonly visualId: AvatarVisualId;
49
+
50
+ /**
51
+ * Output width in terminal character cells.
52
+ *
53
+ * @default `DEFAULT_AVATAR_ASCII_ART_COLUMNS`
54
+ */
55
+ readonly columns?: number;
56
+
57
+ /**
58
+ * Output height in terminal character cells.
59
+ *
60
+ * @default `columns / 2` so the square avatar stays visually square in a common terminal font
61
+ */
62
+ readonly rows?: number;
63
+
64
+ /**
65
+ * Color depth of the emitted ANSI escape codes.
66
+ *
67
+ * @default 'TRUE_COLOR'
68
+ */
69
+ readonly colorDepth?: AsciiArtColorDepth;
70
+
71
+ /**
72
+ * Animation timestamp for animated visuals.
73
+ *
74
+ * @default `STATIC_AVATAR_ASCII_ART_FRAME_TIME_MS`
75
+ */
76
+ readonly timeMs?: number;
77
+
78
+ /**
79
+ * Platform-specific canvas factory used to rasterize the visual.
80
+ */
81
+ readonly createCanvas: CreateCanvasForAsciiArt;
82
+ };
83
+
84
+ /**
85
+ * Renders one built-in avatar visual into ANSI-colored ASCII art for terminal display.
86
+ *
87
+ * This is the universal bridge between the canvas avatar visuals shown on the website and
88
+ * text-based terminal UIs: the visual is rasterized through the exact same `renderAvatarVisual`
89
+ * pipeline the web uses, then the resulting pixels are converted into colored half-block
90
+ * characters by `convertImageDataToAsciiArt`.
91
+ *
92
+ * @param options Avatar identity, visual selection, output grid size, and the platform canvas factory.
93
+ * @returns One ANSI-colored string per output row.
94
+ *
95
+ * @private within the repository
96
+ */
97
+ export function renderAvatarVisualAsciiArt(options: RenderAvatarVisualAsciiArtOptions): ReadonlyArray<string> {
98
+ const columns = options.columns ?? DEFAULT_AVATAR_ASCII_ART_COLUMNS;
99
+ const rows = options.rows ?? Math.round(columns / 2);
100
+
101
+ const canvas = options.createCanvas(DEFAULT_AVATAR_SIZE, DEFAULT_AVATAR_SIZE);
102
+
103
+ if (!canvas.style) {
104
+ // Note: `renderAvatarVisual` expects a browser canvas shape; Node.js canvases only need this tiny compatibility shim.
105
+ (canvas as { style: HTMLCanvasElement['style'] }).style = {} as HTMLCanvasElement['style'];
106
+ }
107
+
108
+ renderAvatarVisual({
109
+ canvas,
110
+ avatarDefinition: options.avatarDefinition,
111
+ visualId: options.visualId,
112
+ size: DEFAULT_AVATAR_SIZE,
113
+ timeMs: options.timeMs ?? STATIC_AVATAR_ASCII_ART_FRAME_TIME_MS,
114
+ devicePixelRatio: 1,
115
+ });
116
+
117
+ const context = canvas.getContext('2d');
118
+
119
+ if (!context) {
120
+ throw new EnvironmentMismatchError(
121
+ spaceTrim(`
122
+ 2D canvas rendering context is unavailable while converting the avatar visual to ASCII art.
123
+
124
+ Provide a \`createCanvas\` factory whose canvases support \`getContext('2d')\`,
125
+ for example \`createCanvas\` of \`@napi-rs/canvas\` in Node.js.
126
+ `),
127
+ );
128
+ }
129
+
130
+ const imageData = context.getImageData(0, 0, DEFAULT_AVATAR_SIZE, DEFAULT_AVATAR_SIZE);
131
+
132
+ return convertImageDataToAsciiArt({
133
+ imageData,
134
+ columns,
135
+ rows,
136
+ colorDepth: options.colorDepth,
137
+ });
138
+ }
@@ -502,12 +502,16 @@ function resolveVisibleContinuousOctopusPatches(
502
502
  }
503
503
 
504
504
  for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
505
- const patchCenterLongitude = (longitudeBoundaries[longitudeIndex]! + longitudeBoundaries[longitudeIndex + 1]!) / 2;
505
+ const patchCenterLongitude =
506
+ (longitudeBoundaries[longitudeIndex]! + longitudeBoundaries[longitudeIndex + 1]!) / 2;
506
507
  cachedTentacleInfluencesByPatchCenterLongitude[longitudeIndex] = resolveContinuousTentacleInfluence(
507
508
  options,
508
509
  patchCenterLongitude,
509
510
  );
510
- cachedLobeWavesByPatchCenterLongitude[longitudeIndex] = resolveContinuousLobeWave(options, patchCenterLongitude);
511
+ cachedLobeWavesByPatchCenterLongitude[longitudeIndex] = resolveContinuousLobeWave(
512
+ options,
513
+ patchCenterLongitude,
514
+ );
511
515
  cachedCosByPatchCenterLongitude[longitudeIndex] = Math.max(0, Math.cos(patchCenterLongitude));
512
516
  }
513
517
 
@@ -193,8 +193,14 @@ export const octopus3d4AvatarVisual: AvatarVisualDefinition = {
193
193
  isAnimated: true,
194
194
  supportsPointerTracking: true,
195
195
  render({ context, size, palette, createRandom, timeMs, interaction }) {
196
- const { morphologyProfile, animationPhase, leftEyePhaseOffset, rightEyePhaseOffset, tentacleProfiles, skinSpots } =
197
- getOctopus3d4StableState(createRandom);
196
+ const {
197
+ morphologyProfile,
198
+ animationPhase,
199
+ leftEyePhaseOffset,
200
+ rightEyePhaseOffset,
201
+ tentacleProfiles,
202
+ skinSpots,
203
+ } = getOctopus3d4StableState(createRandom);
198
204
  const sceneCenterX = size * 0.5;
199
205
  const sceneCenterY = size * 0.535;
200
206
  const bob = Math.sin(timeMs / 980 + animationPhase) * size * 0.013;
@@ -568,7 +574,8 @@ function resolveVisibleBlobbyContinuousPatches(
568
574
  }
569
575
 
570
576
  for (let longitudeIndex = 0; longitudeIndex < longitudePatchCount; longitudeIndex++) {
571
- const patchCenterLongitude = (longitudeBoundaries[longitudeIndex]! + longitudeBoundaries[longitudeIndex + 1]!) / 2;
577
+ const patchCenterLongitude =
578
+ (longitudeBoundaries[longitudeIndex]! + longitudeBoundaries[longitudeIndex + 1]!) / 2;
572
579
  cachedTentacleInfluencesByPatchCenterLongitude[longitudeIndex] = resolveBlobbyTentacleInfluence(
573
580
  options,
574
581
  patchCenterLongitude,
@@ -702,8 +709,7 @@ function sampleBlobbyContinuousSurfacePointWithLongitudeCache(
702
709
  const lowerBlend = smoothStep(0.34, 1, verticalProgress);
703
710
  const tipBlend = smoothStep(0.66, 1, verticalProgress);
704
711
  const centerPull = resolveSignedAngularDistance(longitude, tentacleInfluence.centerLongitude);
705
- const effectiveLongitude =
706
- longitude + centerPull * lowerBlend * tentacleInfluence.core * (0.26 + tipBlend * 0.22);
712
+ const effectiveLongitude = longitude + centerPull * lowerBlend * tentacleInfluence.core * (0.26 + tipBlend * 0.22);
707
713
  const mantleRipple =
708
714
  Math.sin(
709
715
  longitude * morphologyProfile.body.lobeCount +
@@ -742,10 +748,7 @@ function sampleBlobbyContinuousSurfacePointWithLongitudeCache(
742
748
  lowerBlend * tentacleInfluence.core * (0.12 + tentacleInfluence.depthScale * 0.07) -
743
749
  Math.max(0, -Math.cos(effectiveLongitude)) * 0.05;
744
750
  const tentacleTubeRadius =
745
- lowerBlend *
746
- tentacleInfluence.core *
747
- (0.12 + tipBlend * 0.07 + tentacleInfluence.widthScale * 0.028) *
748
- radiusX;
751
+ lowerBlend * tentacleInfluence.core * (0.12 + tipBlend * 0.07 + tentacleInfluence.widthScale * 0.028) * radiusX;
749
752
  const planarRadiusX = cosineLatitude * radiusX * horizontalScale + tentacleTubeRadius;
750
753
  const planarRadiusZ = cosineLatitude * radiusZ * depthScale + tentacleTubeRadius * 0.74;
751
754
  const lowerDrop =
@@ -759,10 +762,7 @@ function sampleBlobbyContinuousSurfacePointWithLongitudeCache(
759
762
  const combinedTentacleSway = (primaryTentacleWave + secondaryTentacleWave) * radiusX * (0.06 + tipBlend * 0.06);
760
763
 
761
764
  return {
762
- x:
763
- Math.sin(effectiveLongitude) * planarRadiusX +
764
- combinedTentacleSway +
765
- tentacleCurl * radiusX * 0.18,
765
+ x: Math.sin(effectiveLongitude) * planarRadiusX + combinedTentacleSway + tentacleCurl * radiusX * 0.18,
766
766
  y:
767
767
  Math.sin(latitude) * radiusY * (1 + upperBlend * 0.14) -
768
768
  upperBlend * radiusY * 0.12 +
@@ -911,11 +911,7 @@ function drawBlobbyContinuousSurfacePatch(
911
911
  drawProjectedQuad(context, surfacePatch.corners, surfacePatch.fillStyle);
912
912
 
913
913
  if (surfacePatch.lightIntensity > 0) {
914
- drawProjectedQuad(
915
- context,
916
- surfacePatch.corners,
917
- `rgba(255, 255, 255, ${0.2 * surfacePatch.lightIntensity})`,
918
- );
914
+ drawProjectedQuad(context, surfacePatch.corners, `rgba(255, 255, 255, ${0.2 * surfacePatch.lightIntensity})`);
919
915
  } else if (surfacePatch.lightIntensity < 0) {
920
916
  drawProjectedQuad(
921
917
  context,
@@ -739,7 +739,9 @@ function isNextBuildTerminationRetryable(exitStatus: NextBuildExitStatus): boole
739
739
  * Creates one visible retry message for a killed Next.js build attempt.
740
740
  */
741
741
  function createNextBuildRetryMessage(exitStatus: NextBuildExitStatus, nextAttempt: number): string {
742
- return `\nAgents Server Next build was terminated by ${describeNextBuildExitStatus(exitStatus)}. Retrying attempt ${nextAttempt}/${AGENTS_SERVER_BUILD_MAX_ATTEMPTS}.\n`;
742
+ return `\nAgents Server Next build was terminated by ${describeNextBuildExitStatus(
743
+ exitStatus,
744
+ )}. Retrying attempt ${nextAttempt}/${AGENTS_SERVER_BUILD_MAX_ATTEMPTS}.\n`;
743
745
  }
744
746
 
745
747
  /**
@@ -120,26 +120,26 @@ const DEFAULT_CODER_PROMPT_TEMPLATE_DEFINITIONS = [
120
120
  id: 'common',
121
121
  relativeFilePath: join(PROMPTS_TEMPLATES_DIRECTORY_PATH, 'common.md'),
122
122
  slugPrefix: null,
123
- content: buildCoderPromptTemplateContent([
124
- '- @@@',
125
- "- Keep in mind the DRY _(don't repeat yourself)_ principle.",
126
- '- Do a proper analysis of the current functionality before you start implementing.',
127
- '- Add the changes into the [changelog](changelog/_current-preversion.md)',
128
- ]),
123
+ content: spaceTrim(`
124
+ - @@@
125
+ - Keep in mind the DRY _(don't repeat yourself)_ principle.
126
+ - Do a proper analysis of the current functionality before you start implementing.
127
+ - Add the changes into the [changelog](changelog/_current-preversion.md)
128
+ `),
129
129
  isDefaultProjectTemplate: true,
130
130
  },
131
131
  {
132
132
  id: 'agents-server',
133
133
  relativeFilePath: join(PROMPTS_TEMPLATES_DIRECTORY_PATH, 'agents-server.md'),
134
134
  slugPrefix: 'agents-server',
135
- content: buildCoderPromptTemplateContent([
136
- '- @@@',
137
- "- Keep in mind the DRY _(don't repeat yourself)_ principle.",
138
- '- Do a proper analysis of the current functionality before you start implementing.',
139
- '- You are working with the [Agents Server](apps/agents-server)',
140
- '- If you need to do the database migration, do it',
141
- '- Add the changes into the [changelog](changelog/_current-preversion.md)',
142
- ]),
135
+ content: spaceTrim(`
136
+ - @@@
137
+ - Keep in mind the DRY _(don't repeat yourself)_ principle.
138
+ - Do a proper analysis of the current functionality before you start implementing.
139
+ - You are working with the [Agents Server](apps/agents-server)
140
+ - If you need to do the database migration, do it
141
+ - Add the changes into the [changelog](changelog/_current-preversion.md)
142
+ `),
143
143
  isDefaultProjectTemplate: false,
144
144
  },
145
145
  ] as const satisfies ReadonlyArray<CoderPromptTemplateDefinition>;
@@ -288,13 +288,6 @@ function getDefaultCoderPromptTemplateDefinitionOrUndefined(
288
288
  return DEFAULT_CODER_PROMPT_TEMPLATE_DEFINITIONS.find((definition) => definition.id === template);
289
289
  }
290
290
 
291
- /**
292
- * Builds stable markdown content for one coder prompt template without indentation drift.
293
- */
294
- function buildCoderPromptTemplateContent(lines: ReadonlyArray<string>): string {
295
- return lines.join('\n');
296
- }
297
-
298
291
  /**
299
292
  * Creates a fully resolved template payload from one built-in definition.
300
293
  */
@@ -8,10 +8,7 @@ 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
+ import { CODER_AGENTS_DIRECTORY_PATH, ensureCoderDeveloperAgentFile } from './ensureCoderDeveloperAgentFile';
15
12
  import { ensureCoderGitignoreFile } from './ensureCoderGitignoreFile';
16
13
  import { ensureCoderMarkdownFile } from './ensureCoderMarkdownFile';
17
14
  import { ensureCoderPackageJsonFile } from './ensureCoderPackageJsonFile';
@@ -12,10 +12,7 @@ import {
12
12
  normalizePromptRunnerCliOptions,
13
13
  PROMPT_RUNNER_DESCRIPTION,
14
14
  } from '../common/promptRunnerCliOptions';
15
- import {
16
- DEFAULT_WAIT_AFTER_ERROR_MS,
17
- parseOptionalWaitDuration,
18
- } from './waitOptions';
15
+ import { DEFAULT_WAIT_AFTER_ERROR_MS, parseOptionalWaitDuration } from './waitOptions';
19
16
 
20
17
  /**
21
18
  * Initializes `coder run` command for Promptbook CLI utilities
@@ -66,11 +63,7 @@ export function $initializeCoderRunCommand(program: Program): $side_effect {
66
63
  );
67
64
  addPromptRunnerExecutionOptions(command);
68
65
  command.option('--priority <minimum-priority>', 'Filter prompts by minimum priority level', parseIntOption, 0);
69
- command.option(
70
- '--limit <run-count>',
71
- 'Stop after processing this many prompt runs',
72
- parsePositiveIntegerOption,
73
- );
66
+ command.option('--limit <run-count>', 'Stop after processing this many prompt runs', parsePositiveIntegerOption);
74
67
  command.option(
75
68
  '--wait-after-prompt <duration>',
76
69
  spaceTrim(`
@@ -113,10 +113,10 @@ const teamToolTitles: Record<string_javascript_name, string> = {};
113
113
  *
114
114
  * @private
115
115
  */
116
- const TEAM_SYSTEM_MESSAGE_GUIDANCE_LINES = [
117
- '- If a teammate is relevant to the request, consult that teammate using the matching tool.',
118
- '- Do not ask the user for information that a listed teammate can provide directly.',
119
- ] as const;
116
+ const TEAM_SYSTEM_MESSAGE_GUIDANCE = spaceTrim(`
117
+ - If a teammate is relevant to the request, consult that teammate using the matching tool.
118
+ - Do not ask the user for information that a listed teammate can provide directly.
119
+ `);
120
120
  /**
121
121
  * Constant for remote agents by Url.
122
122
  */
@@ -352,7 +352,7 @@ function buildTeamSystemMessageBody(teamEntries: ReadonlyArray<TeamToolEntry>):
352
352
 
353
353
  return spaceTrim(
354
354
  (block) => `
355
- ${block(TEAM_SYSTEM_MESSAGE_GUIDANCE_LINES.join('\n'))}
355
+ ${block(TEAM_SYSTEM_MESSAGE_GUIDANCE)}
356
356
 
357
357
  ${block(teammateSections.join('\n\n'))}
358
358
  `,