@promptbook/cli 0.114.0-0 → 0.114.0-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -15
- package/apps/agents-server/package.json +6 -4
- package/apps/agents-server/playwright.config.ts +28 -38
- package/apps/agents-server/scripts/build-agents-server.js +62 -0
- package/apps/agents-server/scripts/build-e2e.js +38 -0
- package/apps/agents-server/scripts/ensure-root-dependencies.js +86 -0
- package/apps/agents-server/scripts/prerender-homepage.js +1 -1
- package/apps/agents-server/scripts/run-e2e-tests.js +34 -0
- package/apps/agents-server/scripts/run-npm.js +42 -0
- package/apps/agents-server/src/app/admin/email-server/page.tsx +14 -6
- package/apps/agents-server/src/app/api/elevenlabs/tts/route.ts +3 -3
- package/apps/agents-server/src/app/api/onboarding/book/route.ts +7 -6
- package/apps/agents-server/src/app/superadmin/servers/ServersRegistryTable.tsx +105 -102
- package/apps/agents-server/src/app/superadmin/servers/useServersRegistryState.ts +15 -7
- package/apps/agents-server/src/components/AgentProjectDnsInstructions/AgentProjectDnsInstructions.tsx +11 -11
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/ManGoBookEditor.tsx +82 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/WizardShell.tsx +2 -2
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/steps/BookStep.tsx +13 -16
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/steps/ZadaniStep.tsx +4 -4
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/config/bookSections.ts +23 -16
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/lib/bookSource.ts +54 -0
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/bookService.ts +15 -8
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/createManGoAgentSource.ts +3 -37
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/createManGoOpenEditorRequest.ts +1 -1
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/state/OnboardingProvider.tsx +2 -2
- package/apps/agents-server/src/components/UsersList/CreateUserDialog.tsx +13 -22
- package/apps/agents-server/src/components/UsersList/PasswordGeneratorDialog.tsx +216 -0
- package/apps/agents-server/src/components/UsersList/UsersList.tsx +16 -11
- package/apps/agents-server/src/components/UsersList/generateSecurePassword.ts +112 -24
- package/apps/agents-server/src/components/UsersList/userDialogClassNames.ts +11 -0
- package/apps/agents-server/src/languages/ServerTranslationKeys.ts +11 -0
- package/apps/agents-server/src/languages/translations/czech.yaml +11 -0
- package/apps/agents-server/src/languages/translations/english.yaml +11 -0
- package/apps/agents-server/src/utils/agentProjects/agentProjectHrefs.ts +11 -0
- package/apps/agents-server/src/utils/agentProjects/createAgentProjectDnsRecords.ts +53 -7
- package/apps/agents-server/src/utils/agentProjects/createAgentProjectMarkdownReferences.ts +37 -27
- package/apps/agents-server/src/utils/manGoOnboarding/manGoOnboardingAgentBooks.ts +2 -13
- package/apps/agents-server/src/utils/manGoOnboarding/manGoOnboardingAgentRuntime.ts +21 -73
- package/apps/agents-server/src/utils/stalwart/createEmailDnsInstructions.ts +9 -5
- package/apps/agents-server/src/utils/stalwart/readStalwartEmailSnapshot.ts +23 -5
- package/apps/agents-server/src/utils/stalwart/stalwartBootstrap.ts +2 -1
- package/apps/agents-server/src/utils/stalwart/stalwartMailBridge.ts +7 -0
- package/apps/agents-server/tests/e2e/e2eEnvironment.cjs +49 -0
- package/esm/index.es.js +523 -169
- package/esm/index.es.js.map +1 -1
- package/esm/scripts/run-agent-chat/runCoderPing.d.ts +48 -0
- package/esm/scripts/run-codex-prompts/prompts/findNextTodoPrompt.d.ts +2 -1
- package/esm/scripts/run-codex-prompts/prompts/isPromptCompatibleWithRunner.d.ts +27 -0
- package/esm/scripts/run-codex-prompts/prompts/listRunnablePrompts.d.ts +2 -1
- package/esm/scripts/run-codex-prompts/prompts/listUpcomingTasks.d.ts +2 -1
- package/esm/scripts/run-codex-prompts/prompts/replacePromptTodoStatusLine.d.ts +7 -0
- package/esm/scripts/run-codex-prompts/testing/TestBeforeMode.d.ts +16 -0
- package/esm/scripts/run-codex-prompts/testing/createTestBeforeRepairPrompt.d.ts +9 -0
- package/esm/scripts/run-codex-prompts/testing/limitTestOutput.d.ts +4 -0
- package/esm/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +1 -2
- package/esm/scripts/run-codex-prompts/testing/runTestBefore.d.ts +24 -0
- package/esm/scripts/run-codex-prompts/ui/buildRunUiFrameShared.d.ts +1 -0
- package/esm/src/book-2.0/book-language-documentation/BookLanguageManualDictionary.d.ts +1 -15
- package/esm/src/book-2.0/book-language-documentation/getBookLanguageManualCommitmentGroups.d.ts +1 -1
- package/esm/src/book-2.0/book-language-documentation/renderCommitmentCatalogSection.d.ts +0 -4
- package/esm/src/book-components/Chat/utils/renderMarkdown.d.ts +7 -0
- package/esm/src/cli/cli-commands/coder/agentCodingFile.d.ts +2 -3
- package/esm/src/cli/cli-commands/coder/ping.d.ts +13 -0
- package/esm/src/cli/cli-commands/coder/ping.test.d.ts +1 -0
- package/esm/src/cli/cli-commands/coder.d.ts +1 -0
- package/package.json +1 -1
- package/src/book-2.0/book-language-documentation/BookLanguageManualDictionary.ts +1 -15
- package/src/book-2.0/book-language-documentation/bookLanguageDocumentationExamples.ts +1 -2
- package/src/book-2.0/book-language-documentation/createStandaloneBookLanguageMarkdown.ts +92 -32
- package/src/book-2.0/book-language-documentation/czechBookLanguageManualDictionary.ts +16 -39
- package/src/book-2.0/book-language-documentation/englishBookLanguageManualDictionary.ts +16 -36
- package/src/book-2.0/book-language-documentation/getBookLanguageManualCommitmentGroups.ts +9 -1
- package/src/book-2.0/book-language-documentation/renderCommitmentCatalogSection.ts +4 -51
- package/src/book-2.0/book-language-documentation/renderGroupedCommitmentDocumentationMarkdown.ts +291 -4
- package/src/book-components/Chat/utils/renderMarkdown.ts +133 -9
- package/src/cli/cli-commands/agents-server/startAgentsServer/createLocalAgentRunOptions.ts +1 -0
- package/src/cli/cli-commands/coder/agentCodingFile.ts +6 -129
- package/src/cli/cli-commands/coder/getDefaultCoderPackageJsonScripts.ts +1 -1
- package/src/cli/cli-commands/coder/initializeCoderProjectConfiguration.ts +1 -4
- package/src/cli/cli-commands/coder/ping.ts +94 -0
- package/src/cli/cli-commands/coder/run.ts +25 -2
- package/src/cli/cli-commands/coder.ts +4 -0
- package/src/other/templates/getTemplatesPipelineCollection.ts +805 -842
- package/src/utils/agent-message-runtime/resolveAgentMessageRuntimeActivity.ts +101 -0
- package/src/version.ts +1 -1
- package/src/versions.txt +1 -1
- package/umd/index.umd.js +525 -171
- package/umd/index.umd.js.map +1 -1
- package/umd/scripts/run-agent-chat/runCoderPing.d.ts +48 -0
- package/umd/scripts/run-codex-prompts/prompts/findNextTodoPrompt.d.ts +2 -1
- package/umd/scripts/run-codex-prompts/prompts/isPromptCompatibleWithRunner.d.ts +27 -0
- package/umd/scripts/run-codex-prompts/prompts/listRunnablePrompts.d.ts +2 -1
- package/umd/scripts/run-codex-prompts/prompts/listUpcomingTasks.d.ts +2 -1
- package/umd/scripts/run-codex-prompts/prompts/replacePromptTodoStatusLine.d.ts +7 -0
- package/umd/scripts/run-codex-prompts/testing/TestBeforeMode.d.ts +16 -0
- package/umd/scripts/run-codex-prompts/testing/createTestBeforeRepairPrompt.d.ts +9 -0
- package/umd/scripts/run-codex-prompts/testing/limitTestOutput.d.ts +4 -0
- package/umd/scripts/run-codex-prompts/testing/runPromptTestCommand.d.ts +1 -2
- package/umd/scripts/run-codex-prompts/testing/runTestBefore.d.ts +24 -0
- package/umd/scripts/run-codex-prompts/ui/buildRunUiFrameShared.d.ts +1 -0
- package/umd/src/book-2.0/book-language-documentation/BookLanguageManualDictionary.d.ts +1 -15
- package/umd/src/book-2.0/book-language-documentation/getBookLanguageManualCommitmentGroups.d.ts +1 -1
- package/umd/src/book-2.0/book-language-documentation/renderCommitmentCatalogSection.d.ts +0 -4
- package/umd/src/book-components/Chat/utils/renderMarkdown.d.ts +7 -0
- package/umd/src/cli/cli-commands/coder/agentCodingFile.d.ts +2 -3
- package/umd/src/cli/cli-commands/coder/ping.d.ts +13 -0
- package/umd/src/cli/cli-commands/coder/ping.test.d.ts +1 -0
- package/umd/src/cli/cli-commands/coder.d.ts +1 -0
- package/apps/agents-server/src/app/api/onboarding/draft/route.ts +0 -23
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/BookLanguagePanel.tsx +0 -125
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/MarkdownBookEditor.tsx +0 -154
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/components/MarkdownPreview.tsx +0 -188
- package/apps/agents-server/src/components/NewAgentDialog/ManGoNewAgentWizard/services/draftService.ts +0 -32
package/src/book-2.0/book-language-documentation/renderGroupedCommitmentDocumentationMarkdown.ts
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { spaceTrim } from 'spacetrim';
|
|
2
|
+
import { parseAgentSourceWithCommitments } from '../agent-source/parseAgentSourceWithCommitments';
|
|
3
|
+
import type { string_book } from '../agent-source/string_book';
|
|
4
|
+
import type { BookCommitment } from '../../commitments/_base/BookCommitment';
|
|
5
|
+
import { getAllCommitmentTypes } from '../../commitments/_common/getAllCommitmentTypes';
|
|
2
6
|
import { getCommitmentDefinition } from '../../commitments/_common/getCommitmentDefinition';
|
|
3
7
|
import type { string_markdown } from '../../types/string_markdown';
|
|
4
8
|
import { shiftMarkdownHeadingLevels } from '../../utils/markdown/shiftMarkdownHeadingLevels';
|
|
9
|
+
import { getSafeCodeBlock } from './getSafeCodeBlock';
|
|
5
10
|
|
|
6
11
|
/**
|
|
7
12
|
* Minimal commitment shape used by documentation renderers.
|
|
@@ -59,6 +64,23 @@ const CLOSED_COMMITMENT_TYPE = 'CLOSED';
|
|
|
59
64
|
*/
|
|
60
65
|
const COMMITMENT_DOCUMENTATION_SECTION_HEADING_LEVEL = 2;
|
|
61
66
|
|
|
67
|
+
/**
|
|
68
|
+
* Markdown code blocks whose Book source is shown as a commitment example.
|
|
69
|
+
*
|
|
70
|
+
* @private internal utility of `createStandaloneBookLanguageMarkdown`
|
|
71
|
+
*/
|
|
72
|
+
const BOOK_CODE_BLOCK_PATTERN = /(`{3,})book[^\n]*\n([\s\S]*?)\n\1/gu;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Recognized commitment types, ordered so compound keywords take priority over
|
|
76
|
+
* their shorter prefixes when reducing an example line by line.
|
|
77
|
+
*
|
|
78
|
+
* @private internal utility of `createStandaloneBookLanguageMarkdown`
|
|
79
|
+
*/
|
|
80
|
+
const COMMITMENT_TYPES_BY_LENGTH = [...getAllCommitmentTypes()].sort(
|
|
81
|
+
(firstType, secondType) => secondType.length - firstType.length,
|
|
82
|
+
);
|
|
83
|
+
|
|
62
84
|
/**
|
|
63
85
|
* Removes the top-level heading from one commitment documentation block.
|
|
64
86
|
*
|
|
@@ -76,12 +98,18 @@ function removeLeadingTopLevelHeading(markdown: string): string {
|
|
|
76
98
|
*
|
|
77
99
|
* @param title - Heading label for the subsection.
|
|
78
100
|
* @param documentation - Raw commitment documentation markdown.
|
|
101
|
+
* @param group - Commitment family represented by the documentation entry.
|
|
79
102
|
* @param headingLevelShift - How many levels the whole entry is nested by its host document.
|
|
80
103
|
* @returns Markdown subsection introducing one commitment of the family.
|
|
81
104
|
*
|
|
82
105
|
* @private internal utility of `createStandaloneBookLanguageMarkdown`
|
|
83
106
|
*/
|
|
84
|
-
function renderDocumentationSection(
|
|
107
|
+
function renderDocumentationSection(
|
|
108
|
+
title: string,
|
|
109
|
+
documentation: string,
|
|
110
|
+
group: GroupedCommitmentDocumentationSource,
|
|
111
|
+
headingLevelShift: number,
|
|
112
|
+
): string {
|
|
85
113
|
const headingPrefix = '#'.repeat(COMMITMENT_DOCUMENTATION_SECTION_HEADING_LEVEL + headingLevelShift);
|
|
86
114
|
|
|
87
115
|
return spaceTrim(
|
|
@@ -90,7 +118,9 @@ function renderDocumentationSection(title: string, documentation: string, headin
|
|
|
90
118
|
|
|
91
119
|
${block(
|
|
92
120
|
shiftMarkdownHeadingLevels(
|
|
93
|
-
removeLeadingTopLevelHeading(
|
|
121
|
+
removeLeadingTopLevelHeading(
|
|
122
|
+
renderFocusedCommitmentExamples(documentation, group),
|
|
123
|
+
) as string_markdown,
|
|
94
124
|
headingLevelShift + 1,
|
|
95
125
|
),
|
|
96
126
|
)}
|
|
@@ -116,7 +146,10 @@ export function renderGroupedCommitmentDocumentationMarkdown(
|
|
|
116
146
|
): string {
|
|
117
147
|
const commitmentTypes = new Set([group.primary.type, ...group.aliases]);
|
|
118
148
|
|
|
119
|
-
|
|
149
|
+
const isOpenClosedCommitmentFamily =
|
|
150
|
+
commitmentTypes.has(OPEN_COMMITMENT_TYPE) && commitmentTypes.has(CLOSED_COMMITMENT_TYPE);
|
|
151
|
+
|
|
152
|
+
if (isOpenClosedCommitmentFamily) {
|
|
120
153
|
const openCommitmentDefinition = getCommitmentDefinition(OPEN_COMMITMENT_TYPE);
|
|
121
154
|
const closedCommitmentDefinition = getCommitmentDefinition(CLOSED_COMMITMENT_TYPE);
|
|
122
155
|
|
|
@@ -127,6 +160,7 @@ export function renderGroupedCommitmentDocumentationMarkdown(
|
|
|
127
160
|
renderDocumentationSection(
|
|
128
161
|
OPEN_COMMITMENT_TYPE,
|
|
129
162
|
openCommitmentDefinition.documentation,
|
|
163
|
+
group,
|
|
130
164
|
headingLevelShift,
|
|
131
165
|
),
|
|
132
166
|
)}
|
|
@@ -135,6 +169,7 @@ export function renderGroupedCommitmentDocumentationMarkdown(
|
|
|
135
169
|
renderDocumentationSection(
|
|
136
170
|
CLOSED_COMMITMENT_TYPE,
|
|
137
171
|
closedCommitmentDefinition.documentation,
|
|
172
|
+
group,
|
|
138
173
|
headingLevelShift,
|
|
139
174
|
),
|
|
140
175
|
)}
|
|
@@ -144,7 +179,259 @@ export function renderGroupedCommitmentDocumentationMarkdown(
|
|
|
144
179
|
}
|
|
145
180
|
|
|
146
181
|
return shiftMarkdownHeadingLevels(
|
|
147
|
-
removeLeadingTopLevelHeading(
|
|
182
|
+
removeLeadingTopLevelHeading(
|
|
183
|
+
renderFocusedCommitmentExamples(group.primary.documentation, group),
|
|
184
|
+
) as string_markdown,
|
|
148
185
|
headingLevelShift,
|
|
149
186
|
);
|
|
150
187
|
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Rewrites Book examples in commitment documentation to show one canonical
|
|
191
|
+
* commitment in isolation, with only `GOAL` and `CLOSED` as supporting syntax.
|
|
192
|
+
*
|
|
193
|
+
* @param documentation - Raw commitment documentation markdown.
|
|
194
|
+
* @param group - Commitment family represented by the documentation entry.
|
|
195
|
+
* @returns Documentation whose Book examples use focused canonical syntax.
|
|
196
|
+
*
|
|
197
|
+
* @private internal utility of `createStandaloneBookLanguageMarkdown`
|
|
198
|
+
*/
|
|
199
|
+
function renderFocusedCommitmentExamples(
|
|
200
|
+
documentation: string,
|
|
201
|
+
group: GroupedCommitmentDocumentationSource,
|
|
202
|
+
): string {
|
|
203
|
+
return documentation.replace(BOOK_CODE_BLOCK_PATTERN, (codeBlock, _fence, source: string) => {
|
|
204
|
+
const focusedSource = createFocusedCommitmentExampleSource(source, group);
|
|
205
|
+
return focusedSource ? getSafeCodeBlock(focusedSource, 'book') : codeBlock;
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Creates a focused Book source example for one commitment documentation entry.
|
|
211
|
+
*
|
|
212
|
+
* @param source - Original Book source from the commitment documentation.
|
|
213
|
+
* @param group - Commitment family represented by the documentation entry.
|
|
214
|
+
* @returns Focused source, or `null` when the source cannot be safely reduced.
|
|
215
|
+
*
|
|
216
|
+
* @private internal utility of `createStandaloneBookLanguageMarkdown`
|
|
217
|
+
*/
|
|
218
|
+
function createFocusedCommitmentExampleSource(
|
|
219
|
+
source: string,
|
|
220
|
+
group: GroupedCommitmentDocumentationSource,
|
|
221
|
+
): string | null {
|
|
222
|
+
const parsedSource = parseAgentSourceWithCommitments(source as string_book);
|
|
223
|
+
const commitmentTypes = new Set([group.primary.type, ...group.aliases]);
|
|
224
|
+
const isOpenClosedCommitmentFamily =
|
|
225
|
+
commitmentTypes.has(OPEN_COMMITMENT_TYPE) && commitmentTypes.has(CLOSED_COMMITMENT_TYPE);
|
|
226
|
+
const allowedCommitmentTypes = new Set([
|
|
227
|
+
group.primary.type,
|
|
228
|
+
...group.aliases,
|
|
229
|
+
'GOAL',
|
|
230
|
+
CLOSED_COMMITMENT_TYPE,
|
|
231
|
+
]);
|
|
232
|
+
const canonicalTypeByCommitmentType = createCanonicalCommitmentTypeByCommitmentType(
|
|
233
|
+
group,
|
|
234
|
+
isOpenClosedCommitmentFamily,
|
|
235
|
+
);
|
|
236
|
+
const focusedCommitments = parsedSource.commitments
|
|
237
|
+
.filter((commitment) => allowedCommitmentTypes.has(commitment.type))
|
|
238
|
+
.map((commitment) => {
|
|
239
|
+
const type = canonicalTypeByCommitmentType.get(commitment.type) || commitment.type;
|
|
240
|
+
return `${type}${commitment.content ? ` ${commitment.content}` : ''}`;
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
if (focusedCommitments.length > 0) {
|
|
244
|
+
return finalizeFocusedCommitmentExampleSource(
|
|
245
|
+
getFocusedExampleAgentName(parsedSource.agentName),
|
|
246
|
+
focusedCommitments,
|
|
247
|
+
);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
return createLineFocusedCommitmentExampleSource(source, group, isOpenClosedCommitmentFamily);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Creates a focused example when the Book parser cannot recognize the target
|
|
255
|
+
* commitment because it appears as the first source line or has a shared prefix.
|
|
256
|
+
*
|
|
257
|
+
* @param source - Original Book source from the documentation code block.
|
|
258
|
+
* @param group - Commitment family represented by the documentation entry.
|
|
259
|
+
* @param isOpenClosedCommitmentFamily - Whether the family contains both switch commitments.
|
|
260
|
+
* @returns Focused source, or `null` when the source does not use this commitment family.
|
|
261
|
+
*
|
|
262
|
+
* @private internal utility of `createStandaloneBookLanguageMarkdown`
|
|
263
|
+
*/
|
|
264
|
+
function createLineFocusedCommitmentExampleSource(
|
|
265
|
+
source: string,
|
|
266
|
+
group: GroupedCommitmentDocumentationSource,
|
|
267
|
+
isOpenClosedCommitmentFamily: boolean,
|
|
268
|
+
): string | null {
|
|
269
|
+
const sourceLines = source.split(/\r?\n/u);
|
|
270
|
+
const allowedCommitmentTypes = new Set([group.primary.type, ...group.aliases, 'GOAL', CLOSED_COMMITMENT_TYPE]);
|
|
271
|
+
const canonicalTypeByCommitmentType = createCanonicalCommitmentTypeByCommitmentType(
|
|
272
|
+
group,
|
|
273
|
+
isOpenClosedCommitmentFamily,
|
|
274
|
+
);
|
|
275
|
+
const focusedCommitments: Array<string> = [];
|
|
276
|
+
const firstSourceLine = sourceLines.find((line) => line.trim().length > 0) || null;
|
|
277
|
+
const firstCommitmentType = firstSourceLine ? getCommitmentTypeAtLine(firstSourceLine) : null;
|
|
278
|
+
const agentName = firstSourceLine && !firstCommitmentType ? firstSourceLine.trim() : null;
|
|
279
|
+
let activeFocusedCommitmentIndex: number | null = null;
|
|
280
|
+
let isInsideCodeBlock = false;
|
|
281
|
+
|
|
282
|
+
for (const sourceLine of sourceLines) {
|
|
283
|
+
const trimmedSourceLine = sourceLine.trim();
|
|
284
|
+
|
|
285
|
+
if (trimmedSourceLine.startsWith('```')) {
|
|
286
|
+
appendLineToActiveCommitment(focusedCommitments, activeFocusedCommitmentIndex, sourceLine);
|
|
287
|
+
isInsideCodeBlock = !isInsideCodeBlock;
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (isInsideCodeBlock) {
|
|
292
|
+
appendLineToActiveCommitment(focusedCommitments, activeFocusedCommitmentIndex, sourceLine);
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const commitmentType = getCommitmentTypeAtLine(sourceLine);
|
|
297
|
+
|
|
298
|
+
if (!commitmentType) {
|
|
299
|
+
appendLineToActiveCommitment(focusedCommitments, activeFocusedCommitmentIndex, sourceLine);
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
if (!allowedCommitmentTypes.has(commitmentType)) {
|
|
304
|
+
activeFocusedCommitmentIndex = null;
|
|
305
|
+
continue;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const canonicalType = canonicalTypeByCommitmentType.get(commitmentType) || commitmentType;
|
|
309
|
+
const content = trimmedSourceLine.slice(commitmentType.length).trimStart();
|
|
310
|
+
focusedCommitments.push(`${canonicalType}${content ? ` ${content}` : ''}`);
|
|
311
|
+
activeFocusedCommitmentIndex = focusedCommitments.length - 1;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return finalizeFocusedCommitmentExampleSource(agentName, focusedCommitments);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Finds the longest supported commitment keyword at the start of a source line.
|
|
319
|
+
*
|
|
320
|
+
* @param sourceLine - One Book source line to inspect.
|
|
321
|
+
* @returns Matching commitment type, or `null` when the line is ordinary content.
|
|
322
|
+
*
|
|
323
|
+
* @private internal utility of `createStandaloneBookLanguageMarkdown`
|
|
324
|
+
*/
|
|
325
|
+
function getCommitmentTypeAtLine(sourceLine: string): BookCommitment | null {
|
|
326
|
+
const trimmedSourceLine = sourceLine.trim();
|
|
327
|
+
|
|
328
|
+
return (
|
|
329
|
+
COMMITMENT_TYPES_BY_LENGTH.find(
|
|
330
|
+
(commitmentType) =>
|
|
331
|
+
trimmedSourceLine === commitmentType || trimmedSourceLine.startsWith(`${commitmentType} `),
|
|
332
|
+
) || null
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Appends a source line only when a focused commitment currently owns it.
|
|
338
|
+
*
|
|
339
|
+
* @param focusedCommitments - Focused commitments assembled from the example.
|
|
340
|
+
* @param activeFocusedCommitmentIndex - Index of the commitment receiving continuation lines.
|
|
341
|
+
* @param sourceLine - Source line to append.
|
|
342
|
+
*
|
|
343
|
+
* @private internal utility of `createStandaloneBookLanguageMarkdown`
|
|
344
|
+
*/
|
|
345
|
+
function appendLineToActiveCommitment(
|
|
346
|
+
focusedCommitments: Array<string>,
|
|
347
|
+
activeFocusedCommitmentIndex: number | null,
|
|
348
|
+
sourceLine: string,
|
|
349
|
+
): void {
|
|
350
|
+
if (activeFocusedCommitmentIndex === null) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
focusedCommitments[activeFocusedCommitmentIndex] += `\n${sourceLine}`;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Adds the standard closing marker and formats one reduced Book example.
|
|
359
|
+
*
|
|
360
|
+
* @param agentName - Optional human-readable title retained from the original example.
|
|
361
|
+
* @param focusedCommitments - Canonical commitment blocks kept in the example.
|
|
362
|
+
* @returns Focused source, or `null` when no relevant commitment was found.
|
|
363
|
+
*
|
|
364
|
+
* @private internal utility of `createStandaloneBookLanguageMarkdown`
|
|
365
|
+
*/
|
|
366
|
+
function finalizeFocusedCommitmentExampleSource(
|
|
367
|
+
agentName: string | null,
|
|
368
|
+
focusedCommitments: Array<string>,
|
|
369
|
+
): string | null {
|
|
370
|
+
const normalizedFocusedCommitments = focusedCommitments.map((commitment) => commitment.trim());
|
|
371
|
+
|
|
372
|
+
if (normalizedFocusedCommitments.length === 0) {
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const isClosedCommitmentIncluded = normalizedFocusedCommitments.some((commitment) =>
|
|
377
|
+
commitment.startsWith(CLOSED_COMMITMENT_TYPE),
|
|
378
|
+
);
|
|
379
|
+
const isOpenCommitmentIncluded = normalizedFocusedCommitments.some((commitment) =>
|
|
380
|
+
commitment.startsWith(OPEN_COMMITMENT_TYPE),
|
|
381
|
+
);
|
|
382
|
+
|
|
383
|
+
if (!isClosedCommitmentIncluded && !isOpenCommitmentIncluded) {
|
|
384
|
+
normalizedFocusedCommitments.push(CLOSED_COMMITMENT_TYPE);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
return [agentName, ...normalizedFocusedCommitments]
|
|
388
|
+
.filter((line): line is string => Boolean(line))
|
|
389
|
+
.join('\n\n');
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Keeps an example title unless the parser interpreted a commitment-only
|
|
394
|
+
* example's first line as its mandatory agent name.
|
|
395
|
+
*
|
|
396
|
+
* @param agentName - Parsed agent name from the original example.
|
|
397
|
+
* @returns Agent title suitable for a focused example, or `null` when absent.
|
|
398
|
+
*
|
|
399
|
+
* @private internal utility of `createStandaloneBookLanguageMarkdown`
|
|
400
|
+
*/
|
|
401
|
+
function getFocusedExampleAgentName(agentName: string | null): string | null {
|
|
402
|
+
if (!agentName || getCommitmentDefinition(agentName as BookCommitment)) {
|
|
403
|
+
return null;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return agentName;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Maps aliases to the canonical keyword shown by a commitment example.
|
|
411
|
+
*
|
|
412
|
+
* `OPEN` and `CLOSED` share one documentation entry, but each remains a
|
|
413
|
+
* distinct keyword and must therefore retain its own spelling.
|
|
414
|
+
*
|
|
415
|
+
* @param group - Commitment family represented by the documentation entry.
|
|
416
|
+
* @param isOpenClosedCommitmentFamily - Whether the family contains both switch commitments.
|
|
417
|
+
* @returns Canonical keyword by accepted source keyword.
|
|
418
|
+
*
|
|
419
|
+
* @private internal utility of `createStandaloneBookLanguageMarkdown`
|
|
420
|
+
*/
|
|
421
|
+
function createCanonicalCommitmentTypeByCommitmentType(
|
|
422
|
+
group: GroupedCommitmentDocumentationSource,
|
|
423
|
+
isOpenClosedCommitmentFamily: boolean,
|
|
424
|
+
): ReadonlyMap<string, string> {
|
|
425
|
+
const canonicalTypeByCommitmentType = new Map<string, string>();
|
|
426
|
+
|
|
427
|
+
canonicalTypeByCommitmentType.set(group.primary.type, group.primary.type);
|
|
428
|
+
|
|
429
|
+
for (const alias of group.aliases) {
|
|
430
|
+
canonicalTypeByCommitmentType.set(
|
|
431
|
+
alias,
|
|
432
|
+
isOpenClosedCommitmentFamily ? alias : group.primary.type,
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return canonicalTypeByCommitmentType;
|
|
437
|
+
}
|
|
@@ -272,6 +272,16 @@ const DETAILS_PLACEHOLDER_WRAPPED_REGEX = new RegExp(`<p>\\s*(${DETAILS_PLACEHOL
|
|
|
272
272
|
*/
|
|
273
273
|
const INLINE_REFERENCE_REGEX = /\[\[([^\]\r\n]+?)\]\]/g;
|
|
274
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Pattern matching ordinary markdown links that can be promoted to inline reference chips.
|
|
277
|
+
*
|
|
278
|
+
* Images are intentionally captured separately and left unchanged by the replacement helper.
|
|
279
|
+
*
|
|
280
|
+
* @private utility of `renderMarkdown`
|
|
281
|
+
*/
|
|
282
|
+
const MARKDOWN_INLINE_REFERENCE_LINK_REGEX =
|
|
283
|
+
/(!?)\[([^\]\r\n]*)\]\(\s*(<[^>\r\n]+>|[^)\s]+)(?:\s+(?:"[^"\r\n]*"|'[^'\r\n]*'|\([^)]*\)))?\s*\)/g;
|
|
284
|
+
|
|
275
285
|
/**
|
|
276
286
|
* Markdown patterns that are strong enough to identify content as markdown.
|
|
277
287
|
*/
|
|
@@ -339,6 +349,14 @@ export type MarkdownInlineReference = {
|
|
|
339
349
|
*/
|
|
340
350
|
readonly href: string;
|
|
341
351
|
|
|
352
|
+
/**
|
|
353
|
+
* Markdown link destination prefixes that should render as this reference as well.
|
|
354
|
+
*
|
|
355
|
+
* This supports legacy links such as an Agents Server project file URL while keeping
|
|
356
|
+
* `reference` as the canonical `[[project]]` token.
|
|
357
|
+
*/
|
|
358
|
+
readonly sourceHrefPrefixes?: ReadonlyArray<string>;
|
|
359
|
+
|
|
342
360
|
/**
|
|
343
361
|
* Optional hover title for the rendered reference.
|
|
344
362
|
*/
|
|
@@ -699,11 +717,12 @@ const CHAT_MARKDOWN_CONVERTER = createChatMarkdownConverter();
|
|
|
699
717
|
* outer `<details>` and optional `<summary>` markup untouched.
|
|
700
718
|
*
|
|
701
719
|
* @param detailsBlock - Raw `<details>...</details>` HTML captured from markdown.
|
|
720
|
+
* @param options - Markdown rendering options to reuse for the details body.
|
|
702
721
|
* @returns `<details>` HTML whose body has been converted from markdown to HTML.
|
|
703
722
|
*
|
|
704
723
|
* @private utility of `renderMarkdown`
|
|
705
724
|
*/
|
|
706
|
-
function renderDetailsBlock(detailsBlock: string): string_html {
|
|
725
|
+
function renderDetailsBlock(detailsBlock: string, options?: RenderMarkdownOptions): string_html {
|
|
707
726
|
const openTagMatch = detailsBlock.match(/^<details\b[^>]*>/i);
|
|
708
727
|
const closeTagMatch = detailsBlock.match(/<\/details\s*>$/i);
|
|
709
728
|
|
|
@@ -717,7 +736,7 @@ function renderDetailsBlock(detailsBlock: string): string_html {
|
|
|
717
736
|
const summaryMatch = innerContent.match(/^(\s*<summary\b[^>]*>[\s\S]*?<\/summary\s*>)([\s\S]*)$/i);
|
|
718
737
|
const summaryHtml = summaryMatch?.[1] ?? '';
|
|
719
738
|
const bodyMarkdown = (summaryMatch?.[2] ?? innerContent) as string_markdown;
|
|
720
|
-
const renderedBody = renderMarkdown(bodyMarkdown);
|
|
739
|
+
const renderedBody = renderMarkdown(bodyMarkdown, options);
|
|
721
740
|
|
|
722
741
|
return `${openTag}${summaryHtml}${renderedBody}${closeTag}` as string_html;
|
|
723
742
|
}
|
|
@@ -761,17 +780,18 @@ function maskMarkdownCodeSegments(markdown: string_markdown): MaskedCodeSegments
|
|
|
761
780
|
* processes their content.
|
|
762
781
|
*
|
|
763
782
|
* @param markdown - Markdown text that may contain raw HTML `<details>` blocks.
|
|
783
|
+
* @param options - Markdown rendering options to reuse for the details body.
|
|
764
784
|
* @returns Masked markdown and a restore helper that returns `string_html`.
|
|
765
785
|
*
|
|
766
786
|
* @private utility of `renderMarkdown`
|
|
767
787
|
*/
|
|
768
|
-
function maskDetailsBlocks(markdown: string_markdown): MaskedDetailsBlocksResult {
|
|
788
|
+
function maskDetailsBlocks(markdown: string_markdown, options?: RenderMarkdownOptions): MaskedDetailsBlocksResult {
|
|
769
789
|
const blocks: string_html[] = [];
|
|
770
790
|
|
|
771
791
|
DETAILS_BLOCK_REGEX.lastIndex = 0;
|
|
772
792
|
const masked = markdown.replace(DETAILS_BLOCK_REGEX, (match) => {
|
|
773
793
|
const placeholder = `${DETAILS_PLACEHOLDER_PREFIX}${blocks.length}__`;
|
|
774
|
-
blocks.push(renderDetailsBlock(match));
|
|
794
|
+
blocks.push(renderDetailsBlock(match, options));
|
|
775
795
|
return placeholder;
|
|
776
796
|
}) as string_markdown;
|
|
777
797
|
|
|
@@ -885,6 +905,93 @@ function createMarkdownInlineReferenceByKey(
|
|
|
885
905
|
return referenceByKey;
|
|
886
906
|
}
|
|
887
907
|
|
|
908
|
+
/**
|
|
909
|
+
* Returns whether a href starts with a configured source href prefix.
|
|
910
|
+
*
|
|
911
|
+
* @param href - Markdown link destination.
|
|
912
|
+
* @param sourceHrefPrefix - Configured source href prefix.
|
|
913
|
+
* @returns Whether the href belongs to the source prefix.
|
|
914
|
+
*
|
|
915
|
+
* @private utility of `renderMarkdown`
|
|
916
|
+
*/
|
|
917
|
+
function doesHrefStartWithSourceHrefPrefix(href: string, sourceHrefPrefix: string): boolean {
|
|
918
|
+
if (href === sourceHrefPrefix) {
|
|
919
|
+
return true;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
const normalizedSourceHrefPrefix = sourceHrefPrefix.endsWith('/') ? sourceHrefPrefix : `${sourceHrefPrefix}/`;
|
|
923
|
+
|
|
924
|
+
return href.startsWith(normalizedSourceHrefPrefix);
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
/**
|
|
928
|
+
* Returns a comparable path for an absolute href when the configured source prefix is relative.
|
|
929
|
+
*
|
|
930
|
+
* @param href - Href to normalize.
|
|
931
|
+
* @returns Absolute URL pathname or the original href when it is relative/invalid.
|
|
932
|
+
*
|
|
933
|
+
* @private utility of `renderMarkdown`
|
|
934
|
+
*/
|
|
935
|
+
function resolveAbsoluteHrefPath(href: string): string {
|
|
936
|
+
try {
|
|
937
|
+
return new URL(href).pathname;
|
|
938
|
+
} catch {
|
|
939
|
+
return href;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* Returns whether one markdown link destination belongs to one inline reference.
|
|
945
|
+
*
|
|
946
|
+
* Relative project paths also match absolute URLs on the current server, which keeps
|
|
947
|
+
* server-generated relative links and model-generated absolute links consistent.
|
|
948
|
+
*
|
|
949
|
+
* @param reference - Candidate inline reference.
|
|
950
|
+
* @param href - Markdown link destination.
|
|
951
|
+
* @returns Whether the href should render as the reference chip.
|
|
952
|
+
*
|
|
953
|
+
* @private utility of `renderMarkdown`
|
|
954
|
+
*/
|
|
955
|
+
function doesMarkdownInlineReferenceMatchHref(reference: MarkdownInlineReference, href: string): boolean {
|
|
956
|
+
const normalizedHref = href.trim();
|
|
957
|
+
|
|
958
|
+
return (reference.sourceHrefPrefixes || []).some((sourceHrefPrefix) => {
|
|
959
|
+
const normalizedSourceHrefPrefix = sourceHrefPrefix.trim();
|
|
960
|
+
if (!normalizedSourceHrefPrefix) {
|
|
961
|
+
return false;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
if (doesHrefStartWithSourceHrefPrefix(normalizedHref, normalizedSourceHrefPrefix)) {
|
|
965
|
+
return true;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
const isRelativeSourceHrefPrefix = !/^[a-z][a-z0-9+.-]*:/i.test(normalizedSourceHrefPrefix);
|
|
969
|
+
const isAbsoluteHref = /^[a-z][a-z0-9+.-]*:/i.test(normalizedHref);
|
|
970
|
+
|
|
971
|
+
return (
|
|
972
|
+
isRelativeSourceHrefPrefix &&
|
|
973
|
+
isAbsoluteHref &&
|
|
974
|
+
doesHrefStartWithSourceHrefPrefix(resolveAbsoluteHrefPath(normalizedHref), normalizedSourceHrefPrefix)
|
|
975
|
+
);
|
|
976
|
+
});
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
/**
|
|
980
|
+
* Finds the inline reference represented by a markdown link destination.
|
|
981
|
+
*
|
|
982
|
+
* @param references - Inline references available to the markdown renderer.
|
|
983
|
+
* @param href - Markdown link destination.
|
|
984
|
+
* @returns Matching reference or `undefined` when the href is unrelated.
|
|
985
|
+
*
|
|
986
|
+
* @private utility of `renderMarkdown`
|
|
987
|
+
*/
|
|
988
|
+
function findMarkdownInlineReferenceByHref(
|
|
989
|
+
references: ReadonlyArray<MarkdownInlineReference>,
|
|
990
|
+
href: string,
|
|
991
|
+
): MarkdownInlineReference | undefined {
|
|
992
|
+
return references.find((reference) => doesMarkdownInlineReferenceMatchHref(reference, href));
|
|
993
|
+
}
|
|
994
|
+
|
|
888
995
|
/**
|
|
889
996
|
* Renders one inline reference as raw HTML that is sanitized by the shared markdown sanitizer.
|
|
890
997
|
*
|
|
@@ -977,11 +1084,28 @@ function applyMarkdownInlineReferences(markdown: string_markdown, options?: Rend
|
|
|
977
1084
|
return markdown;
|
|
978
1085
|
}
|
|
979
1086
|
|
|
980
|
-
|
|
981
|
-
|
|
1087
|
+
const markdownWithInlineReferenceTokens = markdown.replace(
|
|
1088
|
+
INLINE_REFERENCE_REGEX,
|
|
1089
|
+
(match, rawReference: string) => {
|
|
1090
|
+
const reference = referenceByKey.get(normalizeMarkdownInlineReferenceKey(rawReference));
|
|
982
1091
|
|
|
983
|
-
|
|
984
|
-
|
|
1092
|
+
return reference ? renderMarkdownInlineReferenceHtml(reference, className) : match;
|
|
1093
|
+
},
|
|
1094
|
+
);
|
|
1095
|
+
|
|
1096
|
+
return markdownWithInlineReferenceTokens.replace(
|
|
1097
|
+
MARKDOWN_INLINE_REFERENCE_LINK_REGEX,
|
|
1098
|
+
(match, imageMarker: string, _linkLabel: string, rawHref: string) => {
|
|
1099
|
+
if (imageMarker) {
|
|
1100
|
+
return match;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
const href = rawHref.replace(/^<|>$/g, '');
|
|
1104
|
+
const reference = findMarkdownInlineReferenceByHref(references, href);
|
|
1105
|
+
|
|
1106
|
+
return reference ? renderMarkdownInlineReferenceHtml(reference, className) : match;
|
|
1107
|
+
},
|
|
1108
|
+
) as string_markdown;
|
|
985
1109
|
}
|
|
986
1110
|
|
|
987
1111
|
/**
|
|
@@ -1026,7 +1150,7 @@ export function renderMarkdown(markdown: string_markdown, options?: RenderMarkdo
|
|
|
1026
1150
|
|
|
1027
1151
|
try {
|
|
1028
1152
|
const normalizedMarkdown = normalizeMarkdownSublists(markdown);
|
|
1029
|
-
const { masked: maskedMarkdown, restore: restoreDetails } = maskDetailsBlocks(normalizedMarkdown);
|
|
1153
|
+
const { masked: maskedMarkdown, restore: restoreDetails } = maskDetailsBlocks(normalizedMarkdown, options);
|
|
1030
1154
|
const { masked: codeMaskedMarkdown, restore: restoreCode } = maskMarkdownCodeSegments(maskedMarkdown);
|
|
1031
1155
|
const referencedMarkdown = applyMarkdownInlineReferences(codeMaskedMarkdown, options);
|
|
1032
1156
|
const inlineReferenceMarkdown = restoreCode(referencedMarkdown);
|