feat: add task notification mode and skip review builtin option

- Add TASK_NOTIFICATION_TAG to distinguish task notifications from regular prompts
- Add SKIP_REVIEW_BUILTIN=1 env var to skip review builtin generation
  during dev/build for faster startup

Co-Authored-By: claude-sonnet-4-6 <noreply@anthropic.com>
This commit is contained in:
DoSun 2026-05-15 09:10:07 +08:00
parent e93a60264c
commit 196ff5ba21
3 changed files with 64 additions and 41 deletions

View File

@ -8,15 +8,19 @@ const outdir = 'dist'
const { rmSync } = await import('fs') const { rmSync } = await import('fs')
rmSync(outdir, { recursive: true, force: true }) rmSync(outdir, { recursive: true, force: true })
// Step 1.5: Generate review builtin files // Step 1.5: Generate review builtin files (skip with SKIP_REVIEW_BUILTIN=1)
console.log('Generating review builtin files...') if (process.env.SKIP_REVIEW_BUILTIN) {
const { spawnSync: genSpawnSync } = await import('child_process') console.log('Skipping review builtin generation (SKIP_REVIEW_BUILTIN is set)')
const genResult = genSpawnSync('bun', ['run', 'scripts/generate-review-builtin.ts'], { } else {
stdio: 'inherit', console.log('Generating review builtin files...')
cwd: process.cwd(), const { spawnSync: genSpawnSync } = await import('child_process')
}) const genResult = genSpawnSync('bun', ['run', 'scripts/generate-review-builtin.ts'], {
if (genResult.status !== 0) { stdio: 'inherit',
console.warn('Warning: generate-review-builtin.ts failed, using existing files') cwd: process.cwd(),
})
if (genResult.status !== 0) {
console.warn('Warning: generate-review-builtin.ts failed, using existing files')
}
} }
// Default features that match the official CLI build. // Default features that match the official CLI build.

View File

@ -73,14 +73,18 @@ const inspectArgs = process.env.BUN_INSPECT
// npm, etc.) and on all platforms. // npm, etc.) and on all platforms.
const bunCmd = process.execPath; const bunCmd = process.execPath;
// Generate review builtin files before dev launch // Generate review builtin files before dev launch (skip with SKIP_REVIEW_BUILTIN=1)
console.log('[dev] Generating review builtin files...'); if (process.env.SKIP_REVIEW_BUILTIN) {
const genResult = Bun.spawnSync(['bun', 'run', 'scripts/generate-review-builtin.ts'], { console.log('[dev] Skipping review builtin generation (SKIP_REVIEW_BUILTIN is set)');
stdio: ["inherit", "inherit", "inherit"], } else {
cwd: projectRoot, console.log('[dev] Generating review builtin files...');
}); const genResult = Bun.spawnSync(['bun', 'run', 'scripts/generate-review-builtin.ts'], {
if (!genResult.success) { stdio: ["inherit", "inherit", "inherit"],
console.warn('[dev] Warning: generate-review-builtin.ts failed, using existing files'); cwd: projectRoot,
});
if (!genResult.success) {
console.warn('[dev] Warning: generate-review-builtin.ts failed, using existing files');
}
} }
const args = [bunCmd, ...inspectArgs, "run", ...defineArgs, ...featureArgs, cliPath, ...process.argv.slice(2)]; const args = [bunCmd, ...inspectArgs, "run", ...defineArgs, ...featureArgs, cliPath, ...process.argv.slice(2)];

View File

@ -161,7 +161,7 @@ import {
DEFAULT_OUTPUT_STYLE_NAME, DEFAULT_OUTPUT_STYLE_NAME,
getAllOutputStyles, getAllOutputStyles,
} from 'src/constants/outputStyles.js' } from 'src/constants/outputStyles.js'
import { TEAMMATE_MESSAGE_TAG, TICK_TAG } from 'src/constants/xml.js' import { TASK_NOTIFICATION_TAG, TEAMMATE_MESSAGE_TAG, TICK_TAG } from 'src/constants/xml.js'
import { import {
getSettings_DEPRECATED, getSettings_DEPRECATED,
getSettingsWithSources, getSettingsWithSources,
@ -4360,29 +4360,44 @@ function runHeadlessStreaming(
trackReceivedMessageUuid(userMsg.uuid as UUID) trackReceivedMessageUuid(userMsg.uuid as UUID)
} }
enqueue({ const rawContent = typeof userMsg.content === 'string' ? userMsg.content : ''
mode: 'prompt' as const, const isTaskNotification = rawContent.trimStart().startsWith(
// file_attachments rides the protobuf catchall from the web composer. `<${TASK_NOTIFICATION_TAG}>`,
// Same-ref no-op when absent (no 'file_attachments' key). )
value: await resolveAndPrepend(
userMsg, if (isTaskNotification) {
(userMsg.message as { content: ContentBlockParam[] }).content, enqueue({
), mode: 'task-notification' as const,
uuid: userMsg.uuid as `${string}-${string}-${string}-${string}-${string}`, value: rawContent,
priority: (userMsg as { priority?: string }) uuid: userMsg.uuid as `${string}-${string}-${string}-${string}-${string}`,
.priority as import('src/types/textInputTypes.js').QueuePriority, priority: (userMsg as { priority?: string })
}) .priority as import('src/types/textInputTypes.js').QueuePriority,
// Increment prompt count for attribution tracking and save snapshot })
// The snapshot persists promptCount so it survives compaction } else {
if (feature('COMMIT_ATTRIBUTION')) { enqueue({
setAppState(prev => ({ mode: 'prompt' as const,
...prev, // file_attachments rides the protobuf catchall from the web composer.
attribution: incrementPromptCount(prev.attribution, snapshot => { // Same-ref no-op when absent (no 'file_attachments' key).
void recordAttributionSnapshot(snapshot).catch(error => { value: await resolveAndPrepend(
logForDebugging(`Attribution: Failed to save snapshot: ${error}`) userMsg,
}) (userMsg.message as { content: ContentBlockParam[] }).content,
}), ),
})) uuid: userMsg.uuid as `${string}-${string}-${string}-${string}-${string}`,
priority: (userMsg as { priority?: string })
.priority as import('src/types/textInputTypes.js').QueuePriority,
})
// Increment prompt count for attribution tracking and save snapshot
// The snapshot persists promptCount so it survives compaction
if (feature('COMMIT_ATTRIBUTION')) {
setAppState(prev => ({
...prev,
attribution: incrementPromptCount(prev.attribution, snapshot => {
void recordAttributionSnapshot(snapshot).catch(error => {
logForDebugging(`Attribution: Failed to save snapshot: ${error}`)
})
}),
}))
}
} }
void run() void run()
} }