@norman-else/dsh-claude 0.1.35 → 0.1.37
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/INSTALL.md +55 -55
- package/LICENSE +21 -21
- package/README.md +196 -195
- package/cordis.patch.yml +12 -12
- package/legacy-preset/agent.cordis.yml +11 -11
- package/legacy-preset/preset.yml +4 -4
- package/lib/bin.mjs +1 -1
- package/lib/bin.mjs.map +1 -1
- package/lib/client.d.ts +13 -0
- package/lib/client.js +1176 -810
- package/lib/client.js.map +1 -1
- package/lib/{events-Doid-tq7.mjs → events-OhBoFNKO.mjs} +7 -2
- package/lib/events-OhBoFNKO.mjs.map +1 -0
- package/lib/index.d.mts +5 -0
- package/lib/index.mjs +256 -48
- package/lib/index.mjs.map +1 -1
- package/lib/{presenters-CXtE8qve.mjs → presenters-BBoM1Ju1.mjs} +2 -2
- package/lib/presenters-BBoM1Ju1.mjs.map +1 -0
- package/lib/{preset-installer-BMyKr5eQ.mjs → preset-installer-loenwnLS.mjs} +2 -2
- package/lib/preset-installer-loenwnLS.mjs.map +1 -0
- package/lib/preset-route.mjs +2 -2
- package/lib/preset-route.mjs.map +1 -1
- package/package.json +195 -189
- package/preset/claude/agent.cordis.yml +11 -11
- package/preset/claude/preset.yml +4 -4
- package/lib/events-Doid-tq7.mjs.map +0 -1
- package/lib/presenters-CXtE8qve.mjs.map +0 -1
- package/lib/preset-installer-BMyKr5eQ.mjs.map +0 -1
package/lib/client.js
CHANGED
|
@@ -30,6 +30,10 @@ window.__ModuleLoader__.load({
|
|
|
30
30
|
function isClaudeRenderMode(value) {
|
|
31
31
|
return value === "plugin" || value === "native";
|
|
32
32
|
}
|
|
33
|
+
const DEFAULT_CLAUDE_PROSE_MODE = "plain";
|
|
34
|
+
function isClaudeProseMode(value) {
|
|
35
|
+
return value === "plain" || value === "enhanced";
|
|
36
|
+
}
|
|
33
37
|
//#endregion
|
|
34
38
|
//#region src/client/task-projection.ts
|
|
35
39
|
/** Tasks UI is reserved for detached work and genuine Claude subagents. */
|
|
@@ -270,6 +274,62 @@ window.__ModuleLoader__.load({
|
|
|
270
274
|
}
|
|
271
275
|
return failed ? `Failed to ${failedAction}` : completed;
|
|
272
276
|
}
|
|
277
|
+
/** The call id a task's own lifecycle pings were dispatched from. */
|
|
278
|
+
function taskParentToolUseId(activities, taskId) {
|
|
279
|
+
for (const activity of activities) {
|
|
280
|
+
if (activity.taskId !== taskId) continue;
|
|
281
|
+
const id = inputRecord(activity.detail)?.tool_use_id;
|
|
282
|
+
if (typeof id === "string" && id.length > 0) return id;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* The tools one task ran, in the shape the transcript's tool cards take.
|
|
287
|
+
*
|
|
288
|
+
* The task's own activities are lifecycle pings whose detail is the raw
|
|
289
|
+
* protocol message -- useful to nobody reading a panel. The work is in the
|
|
290
|
+
* activities addressed to the call that dispatched the task: a subagent's
|
|
291
|
+
* nested calls carry it as `parentToolUseId`, and a backgrounded command IS
|
|
292
|
+
* that call. Both are folded here the way {@link transcriptItemsForStep} folds
|
|
293
|
+
* a step, so one card renderer serves the transcript and the task panel.
|
|
294
|
+
*/
|
|
295
|
+
function taskTools(activities, taskId) {
|
|
296
|
+
const parent = taskParentToolUseId(activities, taskId);
|
|
297
|
+
if (parent === void 0) return [];
|
|
298
|
+
const tools = /* @__PURE__ */ new Map();
|
|
299
|
+
const ordered = [...activities].sort((left, right) => left.ordinal - right.ordinal);
|
|
300
|
+
for (const activity of ordered) {
|
|
301
|
+
const own = activity.parentToolUseId === parent;
|
|
302
|
+
const isRoot = activity.parentToolUseId === void 0 && activity.toolUseId === parent;
|
|
303
|
+
if (!own && !isRoot) continue;
|
|
304
|
+
const toolUseId = activity.toolUseId;
|
|
305
|
+
if (toolUseId === void 0) continue;
|
|
306
|
+
const previous = tools.get(toolUseId);
|
|
307
|
+
if (previous === void 0) {
|
|
308
|
+
if (activity.toolName === void 0) continue;
|
|
309
|
+
const input = inputRecord(activity.detail);
|
|
310
|
+
tools.set(toolUseId, {
|
|
311
|
+
toolUseId,
|
|
312
|
+
toolName: activity.toolName,
|
|
313
|
+
description: toolDescription(activity.toolName, input),
|
|
314
|
+
...activity.summary === void 0 ? {} : { summary: activity.summary },
|
|
315
|
+
...activity.detail === void 0 ? {} : { input: activity.detail },
|
|
316
|
+
...activity.phase === void 0 ? {} : { phase: activity.phase },
|
|
317
|
+
...activity.isError === void 0 ? {} : { isError: activity.isError },
|
|
318
|
+
subcalls: []
|
|
319
|
+
});
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
const failed = activity.isError === true || activity.phase === "failed";
|
|
323
|
+
tools.set(toolUseId, {
|
|
324
|
+
...previous,
|
|
325
|
+
description: toolDescription(previous.toolName, inputRecord(previous.input), failed),
|
|
326
|
+
...activity.detail === void 0 ? {} : { output: activity.detail },
|
|
327
|
+
...activity.phase === void 0 ? {} : { phase: activity.phase },
|
|
328
|
+
...activity.isError === void 0 ? {} : { isError: activity.isError }
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
return [...tools.values()];
|
|
332
|
+
}
|
|
273
333
|
/** Whether the Host drew this step with DSH's own renderer.
|
|
274
334
|
*
|
|
275
335
|
* The stamp rides on the records themselves rather than on a Client-side copy
|
|
@@ -342,6 +402,15 @@ window.__ModuleLoader__.load({
|
|
|
342
402
|
});
|
|
343
403
|
continue;
|
|
344
404
|
}
|
|
405
|
+
if (activity.kind === "usage" && activity.usage !== void 0) {
|
|
406
|
+
flushGroup();
|
|
407
|
+
items.push({
|
|
408
|
+
kind: "usage",
|
|
409
|
+
ordinal: activity.ordinal,
|
|
410
|
+
usage: activity.usage
|
|
411
|
+
});
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
345
414
|
if (activity.kind === "tool-call" && activity.toolUseId !== void 0 && activity.toolName !== void 0) {
|
|
346
415
|
group ??= {
|
|
347
416
|
ordinal: activity.ordinal,
|
|
@@ -1106,6 +1175,14 @@ window.__ModuleLoader__.load({
|
|
|
1106
1175
|
cursor: "pointer"
|
|
1107
1176
|
};
|
|
1108
1177
|
const taskActivitySection = { margin: "7px 0 0 27px" };
|
|
1178
|
+
/** The task's tool cards. No inset panel of their own: each card already
|
|
1179
|
+
* carries its own surface, and nesting two would read as a box in a box. */
|
|
1180
|
+
const taskToolList = {
|
|
1181
|
+
display: "flex",
|
|
1182
|
+
flexDirection: "column",
|
|
1183
|
+
gap: 2,
|
|
1184
|
+
marginTop: 7
|
|
1185
|
+
};
|
|
1109
1186
|
const taskActivityList = {
|
|
1110
1187
|
display: "flex",
|
|
1111
1188
|
flexDirection: "column",
|
|
@@ -3352,626 +3429,265 @@ window.__ModuleLoader__.load({
|
|
|
3352
3429
|
lineHeight: "20px"
|
|
3353
3430
|
};
|
|
3354
3431
|
//#endregion
|
|
3355
|
-
//#region src/client/
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3432
|
+
//#region src/client/markdown-theme.ts
|
|
3433
|
+
/** Claude Code's code presentation over the Host's Markdown renderer.
|
|
3434
|
+
*
|
|
3435
|
+
* This package renders no Markdown of its own — prose, fenced blocks and the
|
|
3436
|
+
* copy affordance all come from the Host's `MarkdownText` primitive. What it
|
|
3437
|
+
* can own is what that primitive reads: the palette (custom properties) and
|
|
3438
|
+
* the block's chrome (CSS over the primitive's own markup).
|
|
3439
|
+
*
|
|
3440
|
+
* PARITY IS PARTIAL BY CONSTRUCTION. Both renderers highlight with shiki, but
|
|
3441
|
+
* Claude Code's desktop build loads a full TextMate theme (Pierre Dark /
|
|
3442
|
+
* Pierre Light Soft: 248 tokenColor rules over 424 scopes) and bakes the
|
|
3443
|
+
* resolved colour into every span, while the Host loads shiki's legacy
|
|
3444
|
+
* `css-variables` theme, which collapses every scope into the eleven buckets
|
|
3445
|
+
* below. Those eleven carry the colours that dominate a code block —
|
|
3446
|
+
* keywords, strings, comments, functions, numbers — and nothing here can
|
|
3447
|
+
* recover the rest: `constant.numeric` and `constant` are two different
|
|
3448
|
+
* colours in Pierre and one bucket here, and Pierre's string-coloured string
|
|
3449
|
+
* delimiters share this sheet's single punctuation bucket. Matching the rest
|
|
3450
|
+
* means this package running its own shiki, which is a different decision
|
|
3451
|
+
* with a different cost.
|
|
3452
|
+
*
|
|
3453
|
+
* Every rule fails open the way `host-chrome` does: the palette is
|
|
3454
|
+
* declarations on this package's own wrapper, and the chrome rules match the
|
|
3455
|
+
* primitive's CSS Module local names, so a Host that renames either simply
|
|
3456
|
+
* stops matching and its stock presentation comes back.
|
|
3457
|
+
*/
|
|
3458
|
+
/** Wrapper class carrying the palette and scoping the chrome rules.
|
|
3459
|
+
* `display:contents` so the extra element generates no box — custom
|
|
3460
|
+
* properties inherit through it regardless. */
|
|
3461
|
+
const CLAUDE_MARKDOWN_SCOPE = "dsh-claude-markdown";
|
|
3462
|
+
/** Pierre mapped onto the Host's eleven buckets. Each entry names the theme
|
|
3463
|
+
* scope the value was taken from, because the mapping — not the colour — is
|
|
3464
|
+
* the part a reader has to check. */
|
|
3465
|
+
const PIERRE_DARK = [
|
|
3466
|
+
[
|
|
3467
|
+
"--shiki-background",
|
|
3468
|
+
"#1a1a19",
|
|
3469
|
+
"UI surface (--cds-surface-2)"
|
|
3470
|
+
],
|
|
3471
|
+
[
|
|
3472
|
+
"--shiki-foreground",
|
|
3473
|
+
"#fafafa",
|
|
3474
|
+
"editor.foreground"
|
|
3475
|
+
],
|
|
3476
|
+
[
|
|
3477
|
+
"--shiki-token-comment",
|
|
3478
|
+
"#737373",
|
|
3479
|
+
"comment"
|
|
3480
|
+
],
|
|
3481
|
+
[
|
|
3482
|
+
"--shiki-token-keyword",
|
|
3483
|
+
"#ff678d",
|
|
3484
|
+
"keyword, storage.type"
|
|
3485
|
+
],
|
|
3486
|
+
[
|
|
3487
|
+
"--shiki-token-string",
|
|
3488
|
+
"#5ecc71",
|
|
3489
|
+
"string"
|
|
3490
|
+
],
|
|
3491
|
+
[
|
|
3492
|
+
"--shiki-token-string-expression",
|
|
3493
|
+
"#ffa359",
|
|
3494
|
+
"punctuation.section.embedded"
|
|
3495
|
+
],
|
|
3496
|
+
[
|
|
3497
|
+
"--shiki-token-function",
|
|
3498
|
+
"#9d6afb",
|
|
3499
|
+
"entity.name.function"
|
|
3500
|
+
],
|
|
3501
|
+
[
|
|
3502
|
+
"--shiki-token-constant",
|
|
3503
|
+
"#68cdf2",
|
|
3504
|
+
"constant.numeric, constant.language"
|
|
3505
|
+
],
|
|
3506
|
+
[
|
|
3507
|
+
"--shiki-token-parameter",
|
|
3508
|
+
"#a3a3a3",
|
|
3509
|
+
"variable.parameter"
|
|
3510
|
+
],
|
|
3511
|
+
[
|
|
3512
|
+
"--shiki-token-punctuation",
|
|
3513
|
+
"#636363",
|
|
3514
|
+
"punctuation"
|
|
3515
|
+
],
|
|
3516
|
+
[
|
|
3517
|
+
"--shiki-token-link",
|
|
3518
|
+
"#ff678d",
|
|
3519
|
+
"markup.underline.link.markdown"
|
|
3520
|
+
]
|
|
3521
|
+
];
|
|
3522
|
+
const PIERRE_LIGHT = [
|
|
3523
|
+
[
|
|
3524
|
+
"--shiki-background",
|
|
3525
|
+
"#ffffff",
|
|
3526
|
+
"UI surface (--cds-surface-2)"
|
|
3527
|
+
],
|
|
3528
|
+
[
|
|
3529
|
+
"--shiki-foreground",
|
|
3530
|
+
"#525252",
|
|
3531
|
+
"editor.foreground"
|
|
3532
|
+
],
|
|
3533
|
+
[
|
|
3534
|
+
"--shiki-token-comment",
|
|
3535
|
+
"#8a8a8a",
|
|
3536
|
+
"comment"
|
|
3537
|
+
],
|
|
3538
|
+
[
|
|
3539
|
+
"--shiki-token-keyword",
|
|
3540
|
+
"#ff678d",
|
|
3541
|
+
"keyword, storage.type"
|
|
3542
|
+
],
|
|
3543
|
+
[
|
|
3544
|
+
"--shiki-token-string",
|
|
3545
|
+
"#0dbe4e",
|
|
3546
|
+
"string"
|
|
3547
|
+
],
|
|
3548
|
+
[
|
|
3549
|
+
"--shiki-token-string-expression",
|
|
3550
|
+
"#fe8c2c",
|
|
3551
|
+
"punctuation.section.embedded"
|
|
3552
|
+
],
|
|
3553
|
+
[
|
|
3554
|
+
"--shiki-token-function",
|
|
3555
|
+
"#9d6afb",
|
|
3556
|
+
"entity.name.function"
|
|
3557
|
+
],
|
|
3558
|
+
[
|
|
3559
|
+
"--shiki-token-constant",
|
|
3560
|
+
"#08c0ef",
|
|
3561
|
+
"constant.numeric, constant.language"
|
|
3562
|
+
],
|
|
3563
|
+
[
|
|
3564
|
+
"--shiki-token-parameter",
|
|
3565
|
+
"#737373",
|
|
3566
|
+
"variable.parameter"
|
|
3567
|
+
],
|
|
3568
|
+
[
|
|
3569
|
+
"--shiki-token-punctuation",
|
|
3570
|
+
"#737373",
|
|
3571
|
+
"punctuation"
|
|
3572
|
+
],
|
|
3573
|
+
[
|
|
3574
|
+
"--shiki-token-link",
|
|
3575
|
+
"#ff678d",
|
|
3576
|
+
"markup.underline.link.markdown"
|
|
3577
|
+
]
|
|
3578
|
+
];
|
|
3579
|
+
/** Claude's brand clay (`--cds-hsl-clay`), its inline-code TEXT colour; the
|
|
3580
|
+
* emphasized ramp is the light-theme variant. The chip's fill is deliberately
|
|
3581
|
+
* NOT tinted with it — see {@link INLINE_FILL_DARK}. */
|
|
3582
|
+
const CLAY = "#d97757";
|
|
3583
|
+
const CLAY_EMPHASIZED = "#c8603f";
|
|
3584
|
+
/** Prose colours for the body of a Claude answer.
|
|
3585
|
+
*
|
|
3586
|
+
* These are NOT Pierre: the palette above exists to match Claude's desktop
|
|
3587
|
+
* build inside code blocks, and Claude paints prose in plain body text. This
|
|
3588
|
+
* block is a deliberate departure — headings, emphasis and links get their
|
|
3589
|
+
* own hues so a long answer is scannable, the way a Markdown-highlighting
|
|
3590
|
+
* editor shows it. Values are theme-independent by design (the same six read
|
|
3591
|
+
* acceptably on both surfaces); split them if the light theme ever needs its
|
|
3592
|
+
* own ramp.
|
|
3593
|
+
*
|
|
3594
|
+
* The inline-code entry REPLACES {@link CLAY} rather than sitting beside it:
|
|
3595
|
+
* two colours on the same chip is not a choice a stylesheet can make. */
|
|
3596
|
+
const PROSE = {
|
|
3597
|
+
heading: "#7C9EFF",
|
|
3598
|
+
bold: "#FFB454",
|
|
3599
|
+
italic: "#5BD6C0",
|
|
3600
|
+
inlineCode: "#FF7A93",
|
|
3601
|
+
listMarker: "#F2C94C",
|
|
3602
|
+
quote: "#9AA3B2",
|
|
3603
|
+
link: "#4DA3FF",
|
|
3604
|
+
codeBackground: "#0F1218",
|
|
3605
|
+
codeBorder: "#2E3546"
|
|
3369
3606
|
};
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3607
|
+
/** The inline-code chip fill: a neutral 4% wash (Claude's `--t1`), not a tint
|
|
3608
|
+
* of the text colour. A clay-tinted fill reads as a coloured box around every
|
|
3609
|
+
* identifier; the neutral one disappears into the surface and lets the text
|
|
3610
|
+
* carry the accent, which is what the chip is for. */
|
|
3611
|
+
const INLINE_FILL_DARK = "hsl(0 0% 100% / .04)";
|
|
3612
|
+
const INLINE_FILL_LIGHT = "hsl(0 0% 4.3% / .04)";
|
|
3613
|
+
/** Block corner radius (Claude's `--r6`), against the Host's own 12px. */
|
|
3614
|
+
const BLOCK_RADIUS = "8px";
|
|
3615
|
+
/** @param banner - equal to `surface` on purpose: the bar is floated out of
|
|
3616
|
+
* the way below, so this colour is only reached if those chrome selectors
|
|
3617
|
+
* miss, and a bar that matches the block is the neutral fallback. */
|
|
3618
|
+
function palette(entries, surface, banner, inlineFill) {
|
|
3619
|
+
return [
|
|
3620
|
+
...entries.map(([name, value]) => `${name}:${value};`),
|
|
3621
|
+
`--dsw-alias-markdown-code-block:${surface};`,
|
|
3622
|
+
`--dsw-alias-markdown-code-block-banner:${banner};`,
|
|
3623
|
+
`--dsw-alias-markdown-inline-code:${inlineFill}`
|
|
3624
|
+
].join("");
|
|
3376
3625
|
}
|
|
3377
|
-
|
|
3378
|
-
|
|
3626
|
+
const CLAUDE_MARKDOWN_THEME_CSS = [
|
|
3627
|
+
`.${CLAUDE_MARKDOWN_SCOPE}{display:contents;`,
|
|
3628
|
+
palette(PIERRE_LIGHT, "#ffffff", "#ffffff", INLINE_FILL_LIGHT),
|
|
3629
|
+
"}",
|
|
3630
|
+
`body[data-ds-dark-theme] .${CLAUDE_MARKDOWN_SCOPE}{`,
|
|
3631
|
+
palette(PIERRE_DARK, "#1a1a19", "#1a1a19", INLINE_FILL_DARK),
|
|
3632
|
+
"}",
|
|
3633
|
+
`.${CLAUDE_MARKDOWN_SCOPE} :not(pre)>code{color:${CLAY_EMPHASIZED};border-radius:4px;padding:1px 2px;font-size:1.05em!important}`,
|
|
3634
|
+
`body[data-ds-dark-theme] .${CLAUDE_MARKDOWN_SCOPE} :not(pre)>code{color:${CLAY}}`,
|
|
3635
|
+
`.${CLAUDE_MARKDOWN_SCOPE} [class*="bannerWrap"]{position:absolute;top:0;right:0;z-index:7;background:transparent;border-radius:0}`,
|
|
3636
|
+
`.${CLAUDE_MARKDOWN_SCOPE} [class*="banner"]:not([class*="bannerWrap"]){background:transparent;padding:6px 8px}`,
|
|
3637
|
+
`.${CLAUDE_MARKDOWN_SCOPE} [class*="infostring"]{display:none}`,
|
|
3638
|
+
`.${CLAUDE_MARKDOWN_SCOPE} pre{white-space:pre;word-break:normal;overflow-x:auto}`,
|
|
3639
|
+
`.${CLAUDE_MARKDOWN_SCOPE} [class*="block"]{--dsl-code-block-border-radius:${BLOCK_RADIUS}}`
|
|
3640
|
+
].join("");
|
|
3641
|
+
/** The class the review-comment card puts on a rendered comment body. Declared
|
|
3642
|
+
* here rather than imported because it is a literal inside `styles.ts`'s CSS
|
|
3643
|
+
* string, not a constant; a rename there makes these rules miss and the
|
|
3644
|
+
* comment keeps its stock colours, which is the same fail-open the chrome
|
|
3645
|
+
* rules above rely on. */
|
|
3646
|
+
const COMMENT_BODY_SCOPE = "dshClaudeDiffCommentBody";
|
|
3647
|
+
/** Everything the `prose: 'enhanced'` setting adds, and nothing the base sheet
|
|
3648
|
+
* needs. Appended AFTER the base sheet so its rules win ties on source order —
|
|
3649
|
+
* see the note on the inline-code selector below. */
|
|
3650
|
+
const CLAUDE_MARKDOWN_ENHANCED_CSS = [
|
|
3651
|
+
`.${CLAUDE_MARKDOWN_SCOPE} :is(h1,h2,h3,h4,h5,h6){color:${PROSE.heading}}`,
|
|
3652
|
+
`.${CLAUDE_MARKDOWN_SCOPE} strong{color:${PROSE.bold}}`,
|
|
3653
|
+
`.${CLAUDE_MARKDOWN_SCOPE} em{color:${PROSE.italic}}`,
|
|
3654
|
+
`.${CLAUDE_MARKDOWN_SCOPE} li::marker{color:${PROSE.listMarker}}`,
|
|
3655
|
+
`.${CLAUDE_MARKDOWN_SCOPE} blockquote{border-left-color:${PROSE.quote};color:${PROSE.quote}}`,
|
|
3656
|
+
`.${CLAUDE_MARKDOWN_SCOPE} a{color:${PROSE.link}}`,
|
|
3657
|
+
`.${CLAUDE_MARKDOWN_SCOPE} :not(pre)>code,body[data-ds-dark-theme] .${CLAUDE_MARKDOWN_SCOPE} :not(pre)>code{color:${PROSE.inlineCode}}`,
|
|
3658
|
+
`.${CLAUDE_MARKDOWN_SCOPE} [class*="block"]{background:${PROSE.codeBackground};box-shadow:0 0 0 1px ${PROSE.codeBorder}}`,
|
|
3659
|
+
`.${CLAUDE_MARKDOWN_SCOPE} pre{background:${PROSE.codeBackground}}`,
|
|
3660
|
+
`.${COMMENT_BODY_SCOPE} :is(h1,h2,h3,h4,h5,h6){color:${PROSE.heading}}`,
|
|
3661
|
+
`.${COMMENT_BODY_SCOPE} strong{color:${PROSE.bold}}`,
|
|
3662
|
+
`.${COMMENT_BODY_SCOPE} em{color:${PROSE.italic}}`,
|
|
3663
|
+
`.${COMMENT_BODY_SCOPE} li::marker{color:${PROSE.listMarker}}`,
|
|
3664
|
+
`.${COMMENT_BODY_SCOPE} blockquote{border-left-color:${PROSE.quote};color:${PROSE.quote}}`,
|
|
3665
|
+
`.${COMMENT_BODY_SCOPE} a{color:${PROSE.link}}`,
|
|
3666
|
+
`.${COMMENT_BODY_SCOPE} :not(pre)>code{color:${PROSE.inlineCode}}`
|
|
3667
|
+
].join("");
|
|
3668
|
+
/** Live reference to this package's sheet, and the mode it currently holds.
|
|
3669
|
+
* The mode is remembered so `ensureClaudeMarkdownTheme` — called on every
|
|
3670
|
+
* Markdown render — cannot undo a choice boot or the settings panel made. */
|
|
3671
|
+
let styleTag = null;
|
|
3672
|
+
let mode = DEFAULT_CLAUDE_PROSE_MODE;
|
|
3673
|
+
function write() {
|
|
3674
|
+
if (typeof document === "undefined") return;
|
|
3675
|
+
if (styleTag === null || styleTag.parentNode === null) {
|
|
3676
|
+
styleTag = document.createElement("style");
|
|
3677
|
+
styleTag.dataset.dshClaudeMarkdownTheme = "";
|
|
3678
|
+
document.head.appendChild(styleTag);
|
|
3679
|
+
}
|
|
3680
|
+
styleTag.textContent = mode === "enhanced" ? CLAUDE_MARKDOWN_THEME_CSS + CLAUDE_MARKDOWN_ENHANCED_CSS : CLAUDE_MARKDOWN_THEME_CSS;
|
|
3379
3681
|
}
|
|
3380
|
-
|
|
3381
|
-
|
|
3682
|
+
/** Attach the sheet, keeping whatever mode is already set. Idempotent. */
|
|
3683
|
+
function ensureClaudeMarkdownTheme() {
|
|
3684
|
+
write();
|
|
3382
3685
|
}
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
return {
|
|
3389
|
-
state: running > 0 ? "running" : failed > 0 ? "failed" : "completed",
|
|
3390
|
-
count: tasks.length,
|
|
3391
|
-
running,
|
|
3392
|
-
failed,
|
|
3393
|
-
completed
|
|
3394
|
-
};
|
|
3395
|
-
}
|
|
3396
|
-
function statusGlyph(status) {
|
|
3397
|
-
if (status === "running") return "●";
|
|
3398
|
-
if (status === "completed") return "✓";
|
|
3399
|
-
if (status === "stopped") return "–";
|
|
3400
|
-
return "×";
|
|
3401
|
-
}
|
|
3402
|
-
function formatDuration(ms) {
|
|
3403
|
-
if (ms < 1e3) return String(Math.max(1, Math.round(ms))) + "ms";
|
|
3404
|
-
const seconds = Math.round(ms / 1e3);
|
|
3405
|
-
if (seconds < 60) return String(seconds) + "s";
|
|
3406
|
-
const minutes = Math.floor(seconds / 60);
|
|
3407
|
-
return String(minutes) + "m " + String(seconds % 60) + "s";
|
|
3408
|
-
}
|
|
3409
|
-
function taskMeta(task, t) {
|
|
3410
|
-
const parts = [];
|
|
3411
|
-
if (task.subagentType !== void 0) parts.push(task.subagentType);
|
|
3412
|
-
else if (task.taskType !== void 0) parts.push(task.taskType);
|
|
3413
|
-
if (task.usage?.durationMs !== void 0) parts.push(formatDuration(task.usage.durationMs));
|
|
3414
|
-
if (task.usage?.totalTokens !== void 0) parts.push(t("tokens", { count: formatTokenCount(task.usage.totalTokens) }));
|
|
3415
|
-
if (task.usage?.toolUses !== void 0) parts.push(t("tasksToolUses", { count: task.usage.toolUses }));
|
|
3416
|
-
if (task.lastToolName !== void 0) parts.push(t("tasksLastTool", { tool: task.lastToolName }));
|
|
3417
|
-
return parts;
|
|
3418
|
-
}
|
|
3419
|
-
function TaskActivity({ activity, t }) {
|
|
3420
|
-
return /* @__PURE__ */ jsxs("li", {
|
|
3421
|
-
style: taskActivityItem,
|
|
3422
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
3423
|
-
style: taskActivityGlyph,
|
|
3424
|
-
"aria-hidden": "true",
|
|
3425
|
-
children: activity.isError === true ? "×" : "›"
|
|
3426
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
3427
|
-
style: taskActivityBody,
|
|
3428
|
-
children: [
|
|
3429
|
-
/* @__PURE__ */ jsx("p", {
|
|
3430
|
-
style: taskActivityTitle,
|
|
3431
|
-
children: activity.title ?? activity.kind
|
|
3432
|
-
}),
|
|
3433
|
-
activity.summary === void 0 ? null : /* @__PURE__ */ jsx("p", {
|
|
3434
|
-
style: taskActivitySummary,
|
|
3435
|
-
children: activity.summary
|
|
3436
|
-
}),
|
|
3437
|
-
activity.detail === void 0 ? null : /* @__PURE__ */ jsxs("details", {
|
|
3438
|
-
style: taskActivityDetail,
|
|
3439
|
-
children: [/* @__PURE__ */ jsx("summary", {
|
|
3440
|
-
style: taskActivityDetailSummary,
|
|
3441
|
-
children: t("detail")
|
|
3442
|
-
}), /* @__PURE__ */ jsx("pre", {
|
|
3443
|
-
style: detailCode,
|
|
3444
|
-
children: activity.detail
|
|
3445
|
-
})]
|
|
3446
|
-
})
|
|
3447
|
-
]
|
|
3448
|
-
})]
|
|
3449
|
-
});
|
|
3450
|
-
}
|
|
3451
|
-
function TaskCard(props) {
|
|
3452
|
-
const { task, activities, t } = props;
|
|
3453
|
-
const [activityOpen, setActivityOpen] = useState(false);
|
|
3454
|
-
const running = task.status === "running";
|
|
3455
|
-
const failed = task.status === "failed" || task.status === "killed";
|
|
3456
|
-
const meta = taskMeta(task, t);
|
|
3457
|
-
return /* @__PURE__ */ jsxs("article", {
|
|
3458
|
-
style: {
|
|
3459
|
-
...taskCard,
|
|
3460
|
-
...running ? taskCardRunning : {}
|
|
3461
|
-
},
|
|
3462
|
-
children: [
|
|
3463
|
-
/* @__PURE__ */ jsxs("div", {
|
|
3464
|
-
style: taskCardTop,
|
|
3465
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
3466
|
-
className: running ? "dsh-claude-act-running" : void 0,
|
|
3467
|
-
style: {
|
|
3468
|
-
...taskCardGlyph,
|
|
3469
|
-
...running ? iconChipRunning : {},
|
|
3470
|
-
...failed ? iconChipError : {}
|
|
3471
|
-
},
|
|
3472
|
-
"aria-hidden": "true",
|
|
3473
|
-
children: statusGlyph(task.status)
|
|
3474
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
3475
|
-
style: taskCardBody,
|
|
3476
|
-
children: [/* @__PURE__ */ jsx("p", {
|
|
3477
|
-
style: {
|
|
3478
|
-
...taskTitle,
|
|
3479
|
-
...failed ? { color: "var(--dsw-alias-state-error-primary)" } : {}
|
|
3480
|
-
},
|
|
3481
|
-
children: task.description
|
|
3482
|
-
}), /* @__PURE__ */ jsxs("p", {
|
|
3483
|
-
style: taskStatusLine,
|
|
3484
|
-
children: [/* @__PURE__ */ jsx("span", { children: t(STATUS_LABEL[task.status] ?? "tasksRunning") }), task.backgrounded === true ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
|
|
3485
|
-
"aria-hidden": "true",
|
|
3486
|
-
children: " · "
|
|
3487
|
-
}), /* @__PURE__ */ jsx("span", { children: t("tasksBackground") })] }) : null]
|
|
3488
|
-
})]
|
|
3489
|
-
})]
|
|
3490
|
-
}),
|
|
3491
|
-
meta.length === 0 ? null : /* @__PURE__ */ jsx("p", {
|
|
3492
|
-
style: taskMeta$1,
|
|
3493
|
-
children: meta.join(" · ")
|
|
3494
|
-
}),
|
|
3495
|
-
task.summary === void 0 || running ? null : /* @__PURE__ */ jsx("p", {
|
|
3496
|
-
style: taskSummary,
|
|
3497
|
-
children: task.summary
|
|
3498
|
-
}),
|
|
3499
|
-
activities.length === 0 ? null : /* @__PURE__ */ jsxs("div", {
|
|
3500
|
-
style: taskActivitySection,
|
|
3501
|
-
children: [/* @__PURE__ */ jsx("button", {
|
|
3502
|
-
type: "button",
|
|
3503
|
-
style: taskTextButton,
|
|
3504
|
-
"aria-expanded": activityOpen,
|
|
3505
|
-
onClick: () => setActivityOpen((value) => !value),
|
|
3506
|
-
children: activityOpen ? t("tasksHideActivity") : t("tasksViewActivity")
|
|
3507
|
-
}), activityOpen ? /* @__PURE__ */ jsx("ul", {
|
|
3508
|
-
style: taskActivityList,
|
|
3509
|
-
children: activities.map((activity) => /* @__PURE__ */ jsx(TaskActivity, {
|
|
3510
|
-
activity,
|
|
3511
|
-
t
|
|
3512
|
-
}, `${activity.turn}:${activity.step}:${activity.ordinal}`))
|
|
3513
|
-
}) : null]
|
|
3514
|
-
})
|
|
3515
|
-
]
|
|
3516
|
-
});
|
|
3517
|
-
}
|
|
3518
|
-
function GroupHeading(props) {
|
|
3519
|
-
const { label, count, collapsed, onToggle, action } = props;
|
|
3520
|
-
const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsx("span", {
|
|
3521
|
-
style: tasksGroupCount,
|
|
3522
|
-
children: count
|
|
3523
|
-
})] });
|
|
3524
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
3525
|
-
style: tasksGroupHeading,
|
|
3526
|
-
children: [onToggle === void 0 ? /* @__PURE__ */ jsx("div", {
|
|
3527
|
-
style: tasksGroupTitle,
|
|
3528
|
-
children: content
|
|
3529
|
-
}) : /* @__PURE__ */ jsxs("button", {
|
|
3530
|
-
type: "button",
|
|
3531
|
-
style: tasksGroupToggle,
|
|
3532
|
-
"aria-expanded": !collapsed,
|
|
3533
|
-
onClick: onToggle,
|
|
3534
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
3535
|
-
style: {
|
|
3536
|
-
...chevron,
|
|
3537
|
-
...collapsed === true ? {} : chevronOpen
|
|
3538
|
-
},
|
|
3539
|
-
children: "›"
|
|
3540
|
-
}), content]
|
|
3541
|
-
}), action === void 0 ? null : /* @__PURE__ */ jsx("button", {
|
|
3542
|
-
type: "button",
|
|
3543
|
-
style: taskTextButton,
|
|
3544
|
-
onClick: action.onClick,
|
|
3545
|
-
children: action.label
|
|
3546
|
-
})]
|
|
3547
|
-
});
|
|
3548
|
-
}
|
|
3549
|
-
function ClaudeTasksPanel({ useClaudeProjection, t, closeDetails, turn }) {
|
|
3550
|
-
const projection = useClaudeProjection((value) => value);
|
|
3551
|
-
const tasks = useMemo(() => tasksForTurn(projection.tasks?.tasks ?? [], turn), [projection.tasks, turn]);
|
|
3552
|
-
useEffect(() => {
|
|
3553
|
-
if (!projection.owned || tasks.length === 0) closeDetails();
|
|
3554
|
-
}, [
|
|
3555
|
-
closeDetails,
|
|
3556
|
-
projection.owned,
|
|
3557
|
-
tasks.length
|
|
3558
|
-
]);
|
|
3559
|
-
const [finishedCollapsed, setFinishedCollapsed] = useState(false);
|
|
3560
|
-
const [dismissedSettledIds, setDismissedSettledIds] = useState(() => /* @__PURE__ */ new Set());
|
|
3561
|
-
const groups = useMemo(() => visibleTaskGroups(tasks, dismissedSettledIds), [tasks, dismissedSettledIds]);
|
|
3562
|
-
const taskActivities = useMemo(() => new Map(tasks.map((task) => [task.taskId, activitiesForTask(projection.activities, task.taskId)])), [projection.activities, tasks]);
|
|
3563
|
-
const clearFinished = () => setDismissedSettledIds((previous) => /* @__PURE__ */ new Set([...previous, ...tasks.filter((task) => task.status !== "running").map((task) => task.taskId)]));
|
|
3564
|
-
if (!projection.owned) return null;
|
|
3565
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
3566
|
-
className: detailsCardClass,
|
|
3567
|
-
style: tasksPanel,
|
|
3568
|
-
children: [
|
|
3569
|
-
/* @__PURE__ */ jsxs("style", {
|
|
3570
|
-
"data-dsh-claude-panel-icon-styles": true,
|
|
3571
|
-
children: [detailsCardCss, panelIconButtonCss]
|
|
3572
|
-
}),
|
|
3573
|
-
/* @__PURE__ */ jsxs("div", {
|
|
3574
|
-
style: tasksHeader,
|
|
3575
|
-
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("span", {
|
|
3576
|
-
style: tasksHeading,
|
|
3577
|
-
children: t("tasksPanelTurn")
|
|
3578
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
3579
|
-
style: tasksTurnMeta,
|
|
3580
|
-
children: t("tasksTurnNumber", { turn })
|
|
3581
|
-
})] }), /* @__PURE__ */ jsx("button", {
|
|
3582
|
-
type: "button",
|
|
3583
|
-
className: panelIconButtonClass,
|
|
3584
|
-
"aria-label": t("tasksClose"),
|
|
3585
|
-
onClick: closeDetails,
|
|
3586
|
-
children: /* @__PURE__ */ jsx(IconCloseOutline16, {})
|
|
3587
|
-
})]
|
|
3588
|
-
}),
|
|
3589
|
-
/* @__PURE__ */ jsxs("div", {
|
|
3590
|
-
style: tasksBody,
|
|
3591
|
-
children: [/* @__PURE__ */ jsxs("section", {
|
|
3592
|
-
"aria-label": t("tasksRunning"),
|
|
3593
|
-
children: [/* @__PURE__ */ jsx(GroupHeading, {
|
|
3594
|
-
label: t("tasksRunning"),
|
|
3595
|
-
count: groups.running.length
|
|
3596
|
-
}), groups.running.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
3597
|
-
style: tasksGroupEmpty,
|
|
3598
|
-
children: t("tasksNoneRunning")
|
|
3599
|
-
}) : /* @__PURE__ */ jsx("div", {
|
|
3600
|
-
style: taskCardList,
|
|
3601
|
-
children: groups.running.map((task) => /* @__PURE__ */ jsx(TaskCard, {
|
|
3602
|
-
task,
|
|
3603
|
-
activities: taskActivities.get(task.taskId) ?? [],
|
|
3604
|
-
t
|
|
3605
|
-
}, task.taskId))
|
|
3606
|
-
})]
|
|
3607
|
-
}), /* @__PURE__ */ jsxs("section", {
|
|
3608
|
-
"aria-label": t("tasksSettled"),
|
|
3609
|
-
style: tasksFinishedSection,
|
|
3610
|
-
children: [/* @__PURE__ */ jsx(GroupHeading, {
|
|
3611
|
-
label: t("tasksSettled"),
|
|
3612
|
-
count: groups.finished.length,
|
|
3613
|
-
collapsed: finishedCollapsed,
|
|
3614
|
-
onToggle: () => setFinishedCollapsed((value) => !value),
|
|
3615
|
-
...groups.finished.length === 0 ? {} : { action: {
|
|
3616
|
-
label: t("tasksClear"),
|
|
3617
|
-
onClick: clearFinished
|
|
3618
|
-
} }
|
|
3619
|
-
}), finishedCollapsed || groups.finished.length === 0 ? null : /* @__PURE__ */ jsx("div", {
|
|
3620
|
-
style: taskCardList,
|
|
3621
|
-
children: groups.finished.map((task) => /* @__PURE__ */ jsx(TaskCard, {
|
|
3622
|
-
task,
|
|
3623
|
-
activities: taskActivities.get(task.taskId) ?? [],
|
|
3624
|
-
t
|
|
3625
|
-
}, task.taskId))
|
|
3626
|
-
})]
|
|
3627
|
-
})]
|
|
3628
|
-
})
|
|
3629
|
-
]
|
|
3630
|
-
});
|
|
3631
|
-
}
|
|
3632
|
-
//#endregion
|
|
3633
|
-
//#region src/client/ClaudeActivityTail.tsx
|
|
3634
|
-
const MAX_HOVER_TASKS = 6;
|
|
3635
|
-
function taskGlyph(status) {
|
|
3636
|
-
if (status === "failed") return {
|
|
3637
|
-
glyph: "×",
|
|
3638
|
-
style: tasksHoverGlyphError
|
|
3639
|
-
};
|
|
3640
|
-
if (status === "completed") return {
|
|
3641
|
-
glyph: "✓",
|
|
3642
|
-
style: tasksHoverGlyphDone
|
|
3643
|
-
};
|
|
3644
|
-
return {
|
|
3645
|
-
glyph: "●",
|
|
3646
|
-
style: tasksHoverGlyphRunning
|
|
3647
|
-
};
|
|
3648
|
-
}
|
|
3649
|
-
function ClaudeTaskLauncher({ turn, tasks, t, openTasks }) {
|
|
3650
|
-
const [hovered, setHovered] = useState(false);
|
|
3651
|
-
const closeTimer = useRef();
|
|
3652
|
-
const turnTasks = useMemo(() => tasksForTurn(tasks, turn), [tasks, turn]);
|
|
3653
|
-
const summary = useMemo(() => summarizeTurnTasks(turnTasks), [turnTasks]);
|
|
3654
|
-
const open = () => {
|
|
3655
|
-
if (closeTimer.current !== void 0) clearTimeout(closeTimer.current);
|
|
3656
|
-
closeTimer.current = void 0;
|
|
3657
|
-
setHovered(true);
|
|
3658
|
-
};
|
|
3659
|
-
const scheduleClose = () => {
|
|
3660
|
-
if (closeTimer.current !== void 0) clearTimeout(closeTimer.current);
|
|
3661
|
-
closeTimer.current = setTimeout(() => {
|
|
3662
|
-
closeTimer.current = void 0;
|
|
3663
|
-
setHovered(false);
|
|
3664
|
-
}, 350);
|
|
3665
|
-
};
|
|
3666
|
-
useEffect(() => () => {
|
|
3667
|
-
if (closeTimer.current !== void 0) clearTimeout(closeTimer.current);
|
|
3668
|
-
}, []);
|
|
3669
|
-
if (summary === void 0) return null;
|
|
3670
|
-
const label = summary.state === "running" ? t("tasksTurnRunning", { count: summary.running }) : summary.state === "failed" ? t("tasksTurnFailed", {
|
|
3671
|
-
failed: summary.failed,
|
|
3672
|
-
completed: summary.completed
|
|
3673
|
-
}) : t("tasksTurnCompleted", { count: summary.completed });
|
|
3674
|
-
const stateStyle = summary.state === "completed" ? tasksBadgeDone : {};
|
|
3675
|
-
const dotStyle = summary.state === "failed" ? tasksBadgeDotError : summary.state === "completed" ? tasksBadgeDotDone : {};
|
|
3676
|
-
return /* @__PURE__ */ jsx("div", {
|
|
3677
|
-
"data-claude-task-launcher": turn,
|
|
3678
|
-
style: tasksBadgeWrap,
|
|
3679
|
-
children: /* @__PURE__ */ jsxs("span", {
|
|
3680
|
-
style: tasksBadgeSeat,
|
|
3681
|
-
onMouseEnter: open,
|
|
3682
|
-
onMouseLeave: scheduleClose,
|
|
3683
|
-
onFocus: open,
|
|
3684
|
-
onBlur: (event) => {
|
|
3685
|
-
if (!event.currentTarget.contains(event.relatedTarget)) scheduleClose();
|
|
3686
|
-
},
|
|
3687
|
-
children: [hovered ? /* @__PURE__ */ jsxs("span", {
|
|
3688
|
-
role: "tooltip",
|
|
3689
|
-
style: tasksHoverCard,
|
|
3690
|
-
onMouseEnter: open,
|
|
3691
|
-
onMouseLeave: scheduleClose,
|
|
3692
|
-
children: [
|
|
3693
|
-
/* @__PURE__ */ jsx("span", {
|
|
3694
|
-
style: tasksHoverHeader,
|
|
3695
|
-
children: label
|
|
3696
|
-
}),
|
|
3697
|
-
turnTasks.slice(0, MAX_HOVER_TASKS).map((task) => {
|
|
3698
|
-
const { glyph, style } = taskGlyph(task.status);
|
|
3699
|
-
return /* @__PURE__ */ jsxs("span", {
|
|
3700
|
-
style: tasksHoverRow,
|
|
3701
|
-
children: [
|
|
3702
|
-
/* @__PURE__ */ jsx("span", {
|
|
3703
|
-
className: task.status === "running" ? "dsh-claude-act-running" : void 0,
|
|
3704
|
-
style: {
|
|
3705
|
-
...tasksHoverGlyph,
|
|
3706
|
-
...style
|
|
3707
|
-
},
|
|
3708
|
-
"aria-hidden": "true",
|
|
3709
|
-
children: glyph
|
|
3710
|
-
}),
|
|
3711
|
-
/* @__PURE__ */ jsx("span", {
|
|
3712
|
-
style: tasksHoverDesc,
|
|
3713
|
-
title: task.description,
|
|
3714
|
-
children: task.description
|
|
3715
|
-
}),
|
|
3716
|
-
task.subagentType === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
3717
|
-
style: tasksHoverType,
|
|
3718
|
-
children: task.subagentType
|
|
3719
|
-
})
|
|
3720
|
-
]
|
|
3721
|
-
}, task.taskId);
|
|
3722
|
-
}),
|
|
3723
|
-
turnTasks.length > MAX_HOVER_TASKS ? /* @__PURE__ */ jsxs("span", {
|
|
3724
|
-
style: tasksHoverMore,
|
|
3725
|
-
children: ["+", turnTasks.length - MAX_HOVER_TASKS]
|
|
3726
|
-
}) : null,
|
|
3727
|
-
/* @__PURE__ */ jsx("span", {
|
|
3728
|
-
style: tasksHoverHint,
|
|
3729
|
-
children: t("tasksOpen")
|
|
3730
|
-
})
|
|
3731
|
-
]
|
|
3732
|
-
}) : null, /* @__PURE__ */ jsxs("button", {
|
|
3733
|
-
type: "button",
|
|
3734
|
-
className: "dsh-claude-task-launcher",
|
|
3735
|
-
style: {
|
|
3736
|
-
...tasksTurnBadge,
|
|
3737
|
-
...stateStyle,
|
|
3738
|
-
...hovered ? tasksBadgeHovered : {}
|
|
3739
|
-
},
|
|
3740
|
-
"aria-label": `${label} — ${t("tasksOpen")}`,
|
|
3741
|
-
onClick: () => openTasks(turn),
|
|
3742
|
-
children: [/* @__PURE__ */ jsx("span", {
|
|
3743
|
-
className: summary.state === "running" ? "dsh-claude-act-running" : void 0,
|
|
3744
|
-
style: {
|
|
3745
|
-
...tasksBadgeDot,
|
|
3746
|
-
...dotStyle
|
|
3747
|
-
},
|
|
3748
|
-
"aria-hidden": "true"
|
|
3749
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
3750
|
-
style: tasksBadgeLabel,
|
|
3751
|
-
children: label
|
|
3752
|
-
})]
|
|
3753
|
-
})]
|
|
3754
|
-
})
|
|
3755
|
-
});
|
|
3756
|
-
}
|
|
3757
|
-
function ClaudeActivityTail({ matched, useClaudeProjection, t, openTasks }) {
|
|
3758
|
-
const tasks = useClaudeProjection((value) => value.tasks?.tasks ?? []);
|
|
3759
|
-
return /* @__PURE__ */ jsx(ClaudeTaskLauncher, {
|
|
3760
|
-
turn: matched.turn,
|
|
3761
|
-
tasks,
|
|
3762
|
-
t,
|
|
3763
|
-
openTasks
|
|
3764
|
-
});
|
|
3765
|
-
}
|
|
3766
|
-
//#endregion
|
|
3767
|
-
//#region src/client/ClaudeActiveTasksNode.tsx
|
|
3768
|
-
const EMPTY_TASKS$1 = [];
|
|
3769
|
-
/** Render the task launcher while the owning DSH turn is still open. */
|
|
3770
|
-
function ClaudeActiveTasksNode({ node, useClaudeProjection, t, openTasks }) {
|
|
3771
|
-
const tasks = useClaudeProjection((value) => value.tasks?.tasks ?? EMPTY_TASKS$1);
|
|
3772
|
-
return /* @__PURE__ */ jsx(ClaudeTaskLauncher, {
|
|
3773
|
-
turn: node.data.turn,
|
|
3774
|
-
tasks,
|
|
3775
|
-
t,
|
|
3776
|
-
openTasks
|
|
3777
|
-
});
|
|
3778
|
-
}
|
|
3779
|
-
//#endregion
|
|
3780
|
-
//#region src/client/markdown-theme.ts
|
|
3781
|
-
/** Claude Code's code presentation over the Host's Markdown renderer.
|
|
3782
|
-
*
|
|
3783
|
-
* This package renders no Markdown of its own — prose, fenced blocks and the
|
|
3784
|
-
* copy affordance all come from the Host's `MarkdownText` primitive. What it
|
|
3785
|
-
* can own is what that primitive reads: the palette (custom properties) and
|
|
3786
|
-
* the block's chrome (CSS over the primitive's own markup).
|
|
3787
|
-
*
|
|
3788
|
-
* PARITY IS PARTIAL BY CONSTRUCTION. Both renderers highlight with shiki, but
|
|
3789
|
-
* Claude Code's desktop build loads a full TextMate theme (Pierre Dark /
|
|
3790
|
-
* Pierre Light Soft: 248 tokenColor rules over 424 scopes) and bakes the
|
|
3791
|
-
* resolved colour into every span, while the Host loads shiki's legacy
|
|
3792
|
-
* `css-variables` theme, which collapses every scope into the eleven buckets
|
|
3793
|
-
* below. Those eleven carry the colours that dominate a code block —
|
|
3794
|
-
* keywords, strings, comments, functions, numbers — and nothing here can
|
|
3795
|
-
* recover the rest: `constant.numeric` and `constant` are two different
|
|
3796
|
-
* colours in Pierre and one bucket here, and Pierre's string-coloured string
|
|
3797
|
-
* delimiters share this sheet's single punctuation bucket. Matching the rest
|
|
3798
|
-
* means this package running its own shiki, which is a different decision
|
|
3799
|
-
* with a different cost.
|
|
3800
|
-
*
|
|
3801
|
-
* Every rule fails open the way `host-chrome` does: the palette is
|
|
3802
|
-
* declarations on this package's own wrapper, and the chrome rules match the
|
|
3803
|
-
* primitive's CSS Module local names, so a Host that renames either simply
|
|
3804
|
-
* stops matching and its stock presentation comes back.
|
|
3805
|
-
*/
|
|
3806
|
-
/** Wrapper class carrying the palette and scoping the chrome rules.
|
|
3807
|
-
* `display:contents` so the extra element generates no box — custom
|
|
3808
|
-
* properties inherit through it regardless. */
|
|
3809
|
-
const CLAUDE_MARKDOWN_SCOPE = "dsh-claude-markdown";
|
|
3810
|
-
/** Pierre mapped onto the Host's eleven buckets. Each entry names the theme
|
|
3811
|
-
* scope the value was taken from, because the mapping — not the colour — is
|
|
3812
|
-
* the part a reader has to check. */
|
|
3813
|
-
const PIERRE_DARK = [
|
|
3814
|
-
[
|
|
3815
|
-
"--shiki-background",
|
|
3816
|
-
"#1a1a19",
|
|
3817
|
-
"UI surface (--cds-surface-2)"
|
|
3818
|
-
],
|
|
3819
|
-
[
|
|
3820
|
-
"--shiki-foreground",
|
|
3821
|
-
"#fafafa",
|
|
3822
|
-
"editor.foreground"
|
|
3823
|
-
],
|
|
3824
|
-
[
|
|
3825
|
-
"--shiki-token-comment",
|
|
3826
|
-
"#737373",
|
|
3827
|
-
"comment"
|
|
3828
|
-
],
|
|
3829
|
-
[
|
|
3830
|
-
"--shiki-token-keyword",
|
|
3831
|
-
"#ff678d",
|
|
3832
|
-
"keyword, storage.type"
|
|
3833
|
-
],
|
|
3834
|
-
[
|
|
3835
|
-
"--shiki-token-string",
|
|
3836
|
-
"#5ecc71",
|
|
3837
|
-
"string"
|
|
3838
|
-
],
|
|
3839
|
-
[
|
|
3840
|
-
"--shiki-token-string-expression",
|
|
3841
|
-
"#ffa359",
|
|
3842
|
-
"punctuation.section.embedded"
|
|
3843
|
-
],
|
|
3844
|
-
[
|
|
3845
|
-
"--shiki-token-function",
|
|
3846
|
-
"#9d6afb",
|
|
3847
|
-
"entity.name.function"
|
|
3848
|
-
],
|
|
3849
|
-
[
|
|
3850
|
-
"--shiki-token-constant",
|
|
3851
|
-
"#68cdf2",
|
|
3852
|
-
"constant.numeric, constant.language"
|
|
3853
|
-
],
|
|
3854
|
-
[
|
|
3855
|
-
"--shiki-token-parameter",
|
|
3856
|
-
"#a3a3a3",
|
|
3857
|
-
"variable.parameter"
|
|
3858
|
-
],
|
|
3859
|
-
[
|
|
3860
|
-
"--shiki-token-punctuation",
|
|
3861
|
-
"#636363",
|
|
3862
|
-
"punctuation"
|
|
3863
|
-
],
|
|
3864
|
-
[
|
|
3865
|
-
"--shiki-token-link",
|
|
3866
|
-
"#ff678d",
|
|
3867
|
-
"markup.underline.link.markdown"
|
|
3868
|
-
]
|
|
3869
|
-
];
|
|
3870
|
-
const PIERRE_LIGHT = [
|
|
3871
|
-
[
|
|
3872
|
-
"--shiki-background",
|
|
3873
|
-
"#ffffff",
|
|
3874
|
-
"UI surface (--cds-surface-2)"
|
|
3875
|
-
],
|
|
3876
|
-
[
|
|
3877
|
-
"--shiki-foreground",
|
|
3878
|
-
"#525252",
|
|
3879
|
-
"editor.foreground"
|
|
3880
|
-
],
|
|
3881
|
-
[
|
|
3882
|
-
"--shiki-token-comment",
|
|
3883
|
-
"#8a8a8a",
|
|
3884
|
-
"comment"
|
|
3885
|
-
],
|
|
3886
|
-
[
|
|
3887
|
-
"--shiki-token-keyword",
|
|
3888
|
-
"#ff678d",
|
|
3889
|
-
"keyword, storage.type"
|
|
3890
|
-
],
|
|
3891
|
-
[
|
|
3892
|
-
"--shiki-token-string",
|
|
3893
|
-
"#0dbe4e",
|
|
3894
|
-
"string"
|
|
3895
|
-
],
|
|
3896
|
-
[
|
|
3897
|
-
"--shiki-token-string-expression",
|
|
3898
|
-
"#fe8c2c",
|
|
3899
|
-
"punctuation.section.embedded"
|
|
3900
|
-
],
|
|
3901
|
-
[
|
|
3902
|
-
"--shiki-token-function",
|
|
3903
|
-
"#9d6afb",
|
|
3904
|
-
"entity.name.function"
|
|
3905
|
-
],
|
|
3906
|
-
[
|
|
3907
|
-
"--shiki-token-constant",
|
|
3908
|
-
"#08c0ef",
|
|
3909
|
-
"constant.numeric, constant.language"
|
|
3910
|
-
],
|
|
3911
|
-
[
|
|
3912
|
-
"--shiki-token-parameter",
|
|
3913
|
-
"#737373",
|
|
3914
|
-
"variable.parameter"
|
|
3915
|
-
],
|
|
3916
|
-
[
|
|
3917
|
-
"--shiki-token-punctuation",
|
|
3918
|
-
"#737373",
|
|
3919
|
-
"punctuation"
|
|
3920
|
-
],
|
|
3921
|
-
[
|
|
3922
|
-
"--shiki-token-link",
|
|
3923
|
-
"#ff678d",
|
|
3924
|
-
"markup.underline.link.markdown"
|
|
3925
|
-
]
|
|
3926
|
-
];
|
|
3927
|
-
/** Claude's brand clay (`--cds-hsl-clay`), its inline-code TEXT colour; the
|
|
3928
|
-
* emphasized ramp is the light-theme variant. The chip's fill is deliberately
|
|
3929
|
-
* NOT tinted with it — see {@link INLINE_FILL_DARK}. */
|
|
3930
|
-
const CLAY = "#d97757";
|
|
3931
|
-
const CLAY_EMPHASIZED = "#c8603f";
|
|
3932
|
-
/** The inline-code chip fill: a neutral 4% wash (Claude's `--t1`), not a tint
|
|
3933
|
-
* of the text colour. A clay-tinted fill reads as a coloured box around every
|
|
3934
|
-
* identifier; the neutral one disappears into the surface and lets the text
|
|
3935
|
-
* carry the accent, which is what the chip is for. */
|
|
3936
|
-
const INLINE_FILL_DARK = "hsl(0 0% 100% / .04)";
|
|
3937
|
-
const INLINE_FILL_LIGHT = "hsl(0 0% 4.3% / .04)";
|
|
3938
|
-
/** Block corner radius (Claude's `--r6`), against the Host's own 12px. */
|
|
3939
|
-
const BLOCK_RADIUS = "8px";
|
|
3940
|
-
/** @param banner - equal to `surface` on purpose: the bar is floated out of
|
|
3941
|
-
* the way below, so this colour is only reached if those chrome selectors
|
|
3942
|
-
* miss, and a bar that matches the block is the neutral fallback. */
|
|
3943
|
-
function palette(entries, surface, banner, inlineFill) {
|
|
3944
|
-
return [
|
|
3945
|
-
...entries.map(([name, value]) => `${name}:${value};`),
|
|
3946
|
-
`--dsw-alias-markdown-code-block:${surface};`,
|
|
3947
|
-
`--dsw-alias-markdown-code-block-banner:${banner};`,
|
|
3948
|
-
`--dsw-alias-markdown-inline-code:${inlineFill}`
|
|
3949
|
-
].join("");
|
|
3950
|
-
}
|
|
3951
|
-
const CLAUDE_MARKDOWN_THEME_CSS = [
|
|
3952
|
-
`.${CLAUDE_MARKDOWN_SCOPE}{display:contents;`,
|
|
3953
|
-
palette(PIERRE_LIGHT, "#ffffff", "#ffffff", INLINE_FILL_LIGHT),
|
|
3954
|
-
"}",
|
|
3955
|
-
`body[data-ds-dark-theme] .${CLAUDE_MARKDOWN_SCOPE}{`,
|
|
3956
|
-
palette(PIERRE_DARK, "#1a1a19", "#1a1a19", INLINE_FILL_DARK),
|
|
3957
|
-
"}",
|
|
3958
|
-
`.${CLAUDE_MARKDOWN_SCOPE} :not(pre)>code{color:${CLAY_EMPHASIZED};border-radius:4px;padding:1px 2px}`,
|
|
3959
|
-
`body[data-ds-dark-theme] .${CLAUDE_MARKDOWN_SCOPE} :not(pre)>code{color:${CLAY}}`,
|
|
3960
|
-
`.${CLAUDE_MARKDOWN_SCOPE} [class*="bannerWrap"]{position:absolute;top:0;right:0;z-index:7;background:transparent;border-radius:0}`,
|
|
3961
|
-
`.${CLAUDE_MARKDOWN_SCOPE} [class*="banner"]:not([class*="bannerWrap"]){background:transparent;padding:6px 8px}`,
|
|
3962
|
-
`.${CLAUDE_MARKDOWN_SCOPE} [class*="infostring"]{display:none}`,
|
|
3963
|
-
`.${CLAUDE_MARKDOWN_SCOPE} pre{white-space:pre;word-break:normal;overflow-x:auto}`,
|
|
3964
|
-
`.${CLAUDE_MARKDOWN_SCOPE} [class*="block"]{--dsl-code-block-border-radius:${BLOCK_RADIUS}}`
|
|
3965
|
-
].join("");
|
|
3966
|
-
let injected = false;
|
|
3967
|
-
/** Attach the sheet once per page. */
|
|
3968
|
-
function ensureClaudeMarkdownTheme() {
|
|
3969
|
-
if (injected || typeof document === "undefined") return;
|
|
3970
|
-
injected = true;
|
|
3971
|
-
const element = document.createElement("style");
|
|
3972
|
-
element.dataset.dshClaudeMarkdownTheme = "";
|
|
3973
|
-
element.textContent = CLAUDE_MARKDOWN_THEME_CSS;
|
|
3974
|
-
document.head.appendChild(element);
|
|
3686
|
+
/** Switch the prose palette. Rewriting one global sheet repaints every mounted
|
|
3687
|
+
* Markdown block at once, so no render state has to carry the setting. */
|
|
3688
|
+
function applyClaudeMarkdownTheme(next) {
|
|
3689
|
+
mode = next;
|
|
3690
|
+
write();
|
|
3975
3691
|
}
|
|
3976
3692
|
//#endregion
|
|
3977
3693
|
//#region src/client/markdown-labels.tsx
|
|
@@ -4848,13 +4564,21 @@ window.__ModuleLoader__.load({
|
|
|
4848
4564
|
}
|
|
4849
4565
|
};
|
|
4850
4566
|
//#endregion
|
|
4567
|
+
//#region src/client/token-format.ts
|
|
4568
|
+
function formatTokenCount(tokens) {
|
|
4569
|
+
if (tokens >= 1e6) return `${Number((tokens / 1e6).toFixed(tokens >= 1e7 ? 0 : 1))}M`;
|
|
4570
|
+
if (tokens >= 1e3) return `${Number((tokens / 1e3).toFixed(tokens >= 1e5 ? 0 : 1))}K`;
|
|
4571
|
+
return String(tokens);
|
|
4572
|
+
}
|
|
4573
|
+
//#endregion
|
|
4851
4574
|
//#region src/client/ClaudeActivityNode.tsx
|
|
4852
|
-
const EMPTY_TASKS = [];
|
|
4575
|
+
const EMPTY_TASKS$1 = [];
|
|
4853
4576
|
const ACTIVITY_CSS = [
|
|
4854
4577
|
".dsh-claude-flow{display:flex;flex-direction:column;gap:10px}",
|
|
4855
4578
|
".dsh-claude-transcript-text{color:var(--dsw-alias-label-primary);font-size:15px;line-height:24px;overflow-wrap:anywhere}",
|
|
4856
4579
|
".dsh-claude-tool-group-native{overflow:visible}",
|
|
4857
4580
|
".dsh-claude-tool-group-native>.dsh-claude-flow-row{padding:0}",
|
|
4581
|
+
".dsh-claude-flow-row .dsh-claude-tool-stats{margin-left:8px}",
|
|
4858
4582
|
".dsh-claude-tool-list{max-height:min(420px,calc(100vh - 320px));overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;margin-top:4px;border:1px solid var(--dsw-alias-border-l1, color-mix(in srgb, currentColor 12%, transparent));border-radius:10px;scrollbar-gutter:stable}",
|
|
4859
4583
|
".dsh-claude-tool-item{border-top:1px solid var(--dsw-alias-border-l1, color-mix(in srgb, currentColor 12%, transparent))}",
|
|
4860
4584
|
".dsh-claude-tool-item:first-child{border-top:0}",
|
|
@@ -4882,6 +4606,13 @@ window.__ModuleLoader__.load({
|
|
|
4882
4606
|
".dsh-claude-diff-delete{color:var(--dsw-alias-state-error-primary)}",
|
|
4883
4607
|
".dsh-claude-tool-name{font-size:14px;line-height:22px;color:var(--dsw-alias-label-primary)}",
|
|
4884
4608
|
".dsh-claude-tool-summary{margin-left:8px;color:var(--dsw-alias-label-tertiary)}",
|
|
4609
|
+
".dsh-claude-turn-usage{display:flex;flex-wrap:wrap;align-items:center;gap:5px;margin-top:10px;",
|
|
4610
|
+
"color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:18px}",
|
|
4611
|
+
".dsh-claude-turn-usage-label{color:var(--dsw-alias-label-caption)}",
|
|
4612
|
+
".dsh-claude-tool-terminal{display:flex;gap:8px;margin:6px 0 0;padding:8px 10px;max-height:220px;overflow:auto;",
|
|
4613
|
+
"border-radius:8px;background:var(--dsw-alias-markdown-code-block);font:var(--dsw-font-markdown-code-block-small)}",
|
|
4614
|
+
".dsh-claude-tool-prompt{flex:none;user-select:none;color:var(--dsw-alias-label-caption)}",
|
|
4615
|
+
".dsh-claude-tool-command{min-width:0;margin:0;color:var(--dsw-alias-label-primary);white-space:pre-wrap;overflow-wrap:anywhere}",
|
|
4885
4616
|
".dsh-claude-tool-detail{margin:6px 0 0;padding:8px 10px;max-height:220px;overflow:auto;border-radius:8px;background:var(--dsw-alias-markdown-code-block);font:var(--dsw-font-markdown-code-block-small);white-space:pre-wrap;overflow-wrap:anywhere}",
|
|
4886
4617
|
".dsh-claude-flow-row{position:relative;overflow:hidden}",
|
|
4887
4618
|
".dsh-claude-flow-leading{flex-shrink:0}",
|
|
@@ -5057,6 +4788,21 @@ window.__ModuleLoader__.load({
|
|
|
5057
4788
|
}, index))
|
|
5058
4789
|
});
|
|
5059
4790
|
}
|
|
4791
|
+
/** The command as a shell prompt rather than a labelled field: it was typed
|
|
4792
|
+
* at one, and the prompt is what tells a reader that at a glance. */
|
|
4793
|
+
function Terminal({ command }) {
|
|
4794
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4795
|
+
className: "dsh-claude-tool-terminal",
|
|
4796
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
4797
|
+
className: "dsh-claude-tool-prompt",
|
|
4798
|
+
"aria-hidden": "true",
|
|
4799
|
+
children: "$"
|
|
4800
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
4801
|
+
className: "dsh-claude-tool-command",
|
|
4802
|
+
children: command
|
|
4803
|
+
})]
|
|
4804
|
+
});
|
|
4805
|
+
}
|
|
5060
4806
|
function TextDetail({ title, value }) {
|
|
5061
4807
|
if (value === void 0 || value.length === 0) return null;
|
|
5062
4808
|
return /* @__PURE__ */ jsx(Section, {
|
|
@@ -5071,13 +4817,36 @@ window.__ModuleLoader__.load({
|
|
|
5071
4817
|
if (!Array.isArray(value)) return [];
|
|
5072
4818
|
return value.filter((item) => typeof item === "string");
|
|
5073
4819
|
}
|
|
4820
|
+
/** The diff card's chrome, which primitives 0.1.2 moved onto the caller.
|
|
4821
|
+
*
|
|
4822
|
+
* The card reads `labels.copy` while it builds, so omitting them throws
|
|
4823
|
+
* mid-render -- and React answers by tearing down the whole conversation, not
|
|
4824
|
+
* the one tool row.
|
|
4825
|
+
*
|
|
4826
|
+
* The aria strings deliberately repeat the visible ones: both already say
|
|
4827
|
+
* exactly what the control does. */
|
|
4828
|
+
function diffBlockLabels(t) {
|
|
4829
|
+
const expand = (hidden) => t("diffCardExpand", { count: hidden });
|
|
4830
|
+
return {
|
|
4831
|
+
copy: t("markdownCopy"),
|
|
4832
|
+
copied: t("markdownCopied"),
|
|
4833
|
+
collapse: t("diffCardCollapse"),
|
|
4834
|
+
collapseAria: t("diffCardCollapse"),
|
|
4835
|
+
expand,
|
|
4836
|
+
expandAria: expand,
|
|
4837
|
+
files: (count) => t("diffCardFiles", { count })
|
|
4838
|
+
};
|
|
4839
|
+
}
|
|
5074
4840
|
function ToolPresentation({ tool, t }) {
|
|
5075
4841
|
const inputValue = parsedValue(tool.input);
|
|
5076
4842
|
const outputValue = parsedValue(tool.output);
|
|
5077
4843
|
const input = record$6(inputValue);
|
|
5078
4844
|
const output = record$6(outputValue);
|
|
5079
4845
|
const outputTitle = tool.isError === true ? t("toolError") : t("toolOutput");
|
|
5080
|
-
if (tool.diffs !== void 0) return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DiffBlock, {
|
|
4846
|
+
if (tool.diffs !== void 0) return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DiffBlock, {
|
|
4847
|
+
diffs: [...tool.diffs],
|
|
4848
|
+
labels: diffBlockLabels(t)
|
|
4849
|
+
}), /* @__PURE__ */ jsx(TextDetail, {
|
|
5081
4850
|
title: outputTitle,
|
|
5082
4851
|
value: typeof outputValue === "string" ? outputValue : void 0
|
|
5083
4852
|
})] });
|
|
@@ -5101,180 +4870,660 @@ window.__ModuleLoader__.load({
|
|
|
5101
4870
|
omit: ["file_path"]
|
|
5102
4871
|
})
|
|
5103
4872
|
}),
|
|
5104
|
-
content === void 0 ? null : /* @__PURE__ */ jsx(Section, {
|
|
5105
|
-
title: outputTitle,
|
|
5106
|
-
children: /* @__PURE__ */ jsx(Source, {
|
|
5107
|
-
content,
|
|
5108
|
-
start: offset
|
|
5109
|
-
})
|
|
5110
|
-
})
|
|
5111
|
-
] });
|
|
5112
|
-
}
|
|
5113
|
-
if (tool.toolName === "Grep" || tool.toolName === "Glob") {
|
|
5114
|
-
const filenames = filenameList(output?.filenames);
|
|
5115
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [input === void 0 ? /* @__PURE__ */ jsx(TextDetail, {
|
|
5116
|
-
title: t("toolInput"),
|
|
5117
|
-
value: typeof inputValue === "string" ? inputValue : void 0
|
|
5118
|
-
}) : /* @__PURE__ */ jsx(Section, {
|
|
5119
|
-
title: t("toolInput"),
|
|
5120
|
-
children: /* @__PURE__ */ jsx(Fields, { value: input })
|
|
5121
|
-
}), filenames.length === 0 ? /* @__PURE__ */ jsx(TextDetail, {
|
|
5122
|
-
title: outputTitle,
|
|
5123
|
-
value: typeof outputValue === "string" ? outputValue : output === void 0 ? void 0 : displayValue(output)
|
|
5124
|
-
}) : /* @__PURE__ */ jsx(Section, {
|
|
5125
|
-
title: outputTitle,
|
|
5126
|
-
children: /* @__PURE__ */ jsx(Paths, { paths: filenames })
|
|
5127
|
-
})] });
|
|
5128
|
-
}
|
|
5129
|
-
if (tool.toolName === "Bash" || tool.toolName === "PowerShell") {
|
|
5130
|
-
const command = text$1(input?.command);
|
|
5131
|
-
const terminal = [text$1(output?.stdout), text$1(output?.stderr)].filter((value) => value !== void 0).join("\n");
|
|
5132
|
-
|
|
5133
|
-
|
|
5134
|
-
|
|
5135
|
-
|
|
4873
|
+
content === void 0 ? null : /* @__PURE__ */ jsx(Section, {
|
|
4874
|
+
title: outputTitle,
|
|
4875
|
+
children: /* @__PURE__ */ jsx(Source, {
|
|
4876
|
+
content,
|
|
4877
|
+
start: offset
|
|
4878
|
+
})
|
|
4879
|
+
})
|
|
4880
|
+
] });
|
|
4881
|
+
}
|
|
4882
|
+
if (tool.toolName === "Grep" || tool.toolName === "Glob") {
|
|
4883
|
+
const filenames = filenameList(output?.filenames);
|
|
4884
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [input === void 0 ? /* @__PURE__ */ jsx(TextDetail, {
|
|
4885
|
+
title: t("toolInput"),
|
|
4886
|
+
value: typeof inputValue === "string" ? inputValue : void 0
|
|
4887
|
+
}) : /* @__PURE__ */ jsx(Section, {
|
|
4888
|
+
title: t("toolInput"),
|
|
4889
|
+
children: /* @__PURE__ */ jsx(Fields, { value: input })
|
|
4890
|
+
}), filenames.length === 0 ? /* @__PURE__ */ jsx(TextDetail, {
|
|
4891
|
+
title: outputTitle,
|
|
4892
|
+
value: typeof outputValue === "string" ? outputValue : output === void 0 ? void 0 : displayValue(output)
|
|
4893
|
+
}) : /* @__PURE__ */ jsx(Section, {
|
|
4894
|
+
title: outputTitle,
|
|
4895
|
+
children: /* @__PURE__ */ jsx(Paths, { paths: filenames })
|
|
4896
|
+
})] });
|
|
4897
|
+
}
|
|
4898
|
+
if (tool.toolName === "Bash" || tool.toolName === "PowerShell") {
|
|
4899
|
+
const command = text$1(input?.command);
|
|
4900
|
+
const terminal = [text$1(output?.stdout), text$1(output?.stderr)].filter((value) => value !== void 0).join("\n");
|
|
4901
|
+
const typed = command ?? (typeof inputValue === "string" ? inputValue : void 0);
|
|
4902
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
4903
|
+
typed === void 0 ? null : /* @__PURE__ */ jsx(Terminal, { command: typed }),
|
|
4904
|
+
input === void 0 ? null : /* @__PURE__ */ jsx(Section, {
|
|
4905
|
+
title: t("toolInput"),
|
|
4906
|
+
children: /* @__PURE__ */ jsx(Fields, {
|
|
4907
|
+
value: input,
|
|
4908
|
+
omit: ["command", "description"]
|
|
4909
|
+
})
|
|
4910
|
+
}),
|
|
4911
|
+
/* @__PURE__ */ jsx(TextDetail, {
|
|
4912
|
+
title: outputTitle,
|
|
4913
|
+
value: terminal || (typeof outputValue === "string" ? outputValue : void 0)
|
|
4914
|
+
})
|
|
4915
|
+
] });
|
|
4916
|
+
}
|
|
4917
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [input === void 0 ? /* @__PURE__ */ jsx(TextDetail, {
|
|
4918
|
+
title: t("toolInput"),
|
|
4919
|
+
value: typeof inputValue === "string" ? inputValue : void 0
|
|
4920
|
+
}) : /* @__PURE__ */ jsx(Section, {
|
|
4921
|
+
title: t("toolInput"),
|
|
4922
|
+
children: /* @__PURE__ */ jsx(Fields, { value: input })
|
|
4923
|
+
}), output === void 0 ? /* @__PURE__ */ jsx(TextDetail, {
|
|
4924
|
+
title: outputTitle,
|
|
4925
|
+
value: typeof outputValue === "string" ? outputValue : void 0
|
|
4926
|
+
}) : /* @__PURE__ */ jsx(Section, {
|
|
4927
|
+
title: outputTitle,
|
|
4928
|
+
children: /* @__PURE__ */ jsx(Fields, { value: output })
|
|
4929
|
+
})] });
|
|
4930
|
+
}
|
|
4931
|
+
function ClaudeTranscriptToolItem({ tool, t }) {
|
|
4932
|
+
return /* @__PURE__ */ jsxs("details", {
|
|
4933
|
+
className: "dsh-claude-tool-item",
|
|
4934
|
+
children: [/* @__PURE__ */ jsxs("summary", {
|
|
4935
|
+
className: "dsh-claude-tool-summary-row",
|
|
4936
|
+
children: [
|
|
4937
|
+
/* @__PURE__ */ jsx("span", {
|
|
4938
|
+
className: "dsh-claude-tool-label",
|
|
4939
|
+
children: tool.toolName
|
|
4940
|
+
}),
|
|
4941
|
+
/* @__PURE__ */ jsx("span", {
|
|
4942
|
+
className: "dsh-claude-tool-description",
|
|
4943
|
+
children: tool.description
|
|
4944
|
+
}),
|
|
4945
|
+
tool.additions === void 0 && tool.deletions === void 0 ? null : /* @__PURE__ */ jsxs("span", {
|
|
4946
|
+
className: "dsh-claude-tool-stats",
|
|
4947
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
4948
|
+
className: "dsh-claude-diff-add",
|
|
4949
|
+
children: ["+", tool.additions ?? 0]
|
|
4950
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
4951
|
+
className: "dsh-claude-diff-delete",
|
|
4952
|
+
children: ["−", tool.deletions ?? 0]
|
|
4953
|
+
})]
|
|
4954
|
+
})
|
|
4955
|
+
]
|
|
4956
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
4957
|
+
className: "dsh-claude-tool-content",
|
|
4958
|
+
children: [tool.subcalls.length === 0 ? null : /* @__PURE__ */ jsx("div", {
|
|
4959
|
+
className: "dsh-claude-flow-subcalls",
|
|
4960
|
+
children: tool.subcalls.map((subcall) => /* @__PURE__ */ jsxs("div", { children: [
|
|
4961
|
+
subcallGlyph(subcall),
|
|
4962
|
+
" ",
|
|
4963
|
+
subcall.toolName ?? t("subagent"),
|
|
4964
|
+
subcall.summary === void 0 ? "" : ` · ${subcall.summary}`
|
|
4965
|
+
] }, subcall.toolUseId))
|
|
4966
|
+
}), /* @__PURE__ */ jsx(ToolPresentation, {
|
|
4967
|
+
tool,
|
|
4968
|
+
t
|
|
4969
|
+
})]
|
|
4970
|
+
})]
|
|
4971
|
+
});
|
|
4972
|
+
}
|
|
4973
|
+
function ClaudeTranscriptToolGroup({ tools, additions, deletions, files: _files, t }) {
|
|
4974
|
+
const [open, setOpen] = useState(false);
|
|
4975
|
+
const failed = tools.some((tool) => tool.isError === true || tool.phase === "failed");
|
|
4976
|
+
const running = tools.some((tool) => tool.phase === "started" || tool.phase === "updated");
|
|
4977
|
+
const summary = tools.length === 1 ? t("usedTool") : t("usedTools", { count: tools.length });
|
|
4978
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
4979
|
+
className: "dsh-claude-tool-group-native",
|
|
4980
|
+
children: [/* @__PURE__ */ jsx(DisclosureRow, {
|
|
4981
|
+
rowClassName: "dsh-claude-flow-row",
|
|
4982
|
+
leadingClassName: "dsh-claude-flow-leading",
|
|
4983
|
+
titleClassName: "dsh-claude-flow-title",
|
|
4984
|
+
chevronClassName: "dsh-claude-flow-chevron",
|
|
4985
|
+
icon: failed ? /* @__PURE__ */ jsx(StateDot, { state: "error" }) : running ? /* @__PURE__ */ jsx(StateDot, { state: "ongoing" }) : /* @__PURE__ */ jsx(IconApiOutline14, { size: 14 }),
|
|
4986
|
+
title: summary,
|
|
4987
|
+
open,
|
|
4988
|
+
expandable: true,
|
|
4989
|
+
expandOnRowClick: true,
|
|
4990
|
+
keepContentWhenOpen: true,
|
|
4991
|
+
onToggle: () => setOpen((value) => !value),
|
|
4992
|
+
collapsedContent: additions !== void 0 || deletions !== void 0 ? /* @__PURE__ */ jsxs("span", {
|
|
4993
|
+
className: "dsh-claude-tool-stats",
|
|
4994
|
+
children: [/* @__PURE__ */ jsxs("span", {
|
|
4995
|
+
className: "dsh-claude-diff-add",
|
|
4996
|
+
children: ["+", additions ?? 0]
|
|
4997
|
+
}), /* @__PURE__ */ jsxs("span", {
|
|
4998
|
+
className: "dsh-claude-diff-delete",
|
|
4999
|
+
children: ["−", deletions ?? 0]
|
|
5000
|
+
})]
|
|
5001
|
+
}) : void 0
|
|
5002
|
+
}), open ? /* @__PURE__ */ jsx("div", {
|
|
5003
|
+
className: "dsh-claude-tool-list",
|
|
5004
|
+
children: tools.map((tool) => /* @__PURE__ */ jsx(ClaudeTranscriptToolItem, {
|
|
5005
|
+
tool,
|
|
5006
|
+
t
|
|
5007
|
+
}, tool.toolUseId))
|
|
5008
|
+
}) : null]
|
|
5009
|
+
});
|
|
5010
|
+
}
|
|
5011
|
+
/** Round a duration the way a reader reads one: no more precision than the
|
|
5012
|
+
* number deserves. */
|
|
5013
|
+
function formatTurnDuration(ms) {
|
|
5014
|
+
if (ms < 1e3) return `${Math.max(1, Math.round(ms))}ms`;
|
|
5015
|
+
const seconds = ms / 1e3;
|
|
5016
|
+
if (seconds < 60) return `${seconds < 10 ? seconds.toFixed(1) : String(Math.round(seconds))}s`;
|
|
5017
|
+
const whole = Math.round(seconds);
|
|
5018
|
+
return `${Math.floor(whole / 60)}m ${String(whole % 60).padStart(2, "0")}s`;
|
|
5019
|
+
}
|
|
5020
|
+
/** Share of the prompt that was served from cache.
|
|
5021
|
+
*
|
|
5022
|
+
* Cache reads are counted against everything the prompt cost to assemble --
|
|
5023
|
+
* fresh input and cache writes included -- so a turn that read nothing scores
|
|
5024
|
+
* zero rather than dividing by nothing. */
|
|
5025
|
+
function cacheHitRate(usage) {
|
|
5026
|
+
const read = usage.cacheReadTokens ?? 0;
|
|
5027
|
+
const total = read + (usage.cacheCreationTokens ?? 0) + (usage.inputTokens ?? 0);
|
|
5028
|
+
return total === 0 ? void 0 : read / total;
|
|
5029
|
+
}
|
|
5030
|
+
/** The turn's accounting, in the order a reader wants it: size, then cost of
|
|
5031
|
+
* assembling it, then how long it took, then money. */
|
|
5032
|
+
function turnUsageParts(usage, t) {
|
|
5033
|
+
const tokens = (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0) + (usage.cacheReadTokens ?? 0) + (usage.cacheCreationTokens ?? 0);
|
|
5034
|
+
const cached = cacheHitRate(usage);
|
|
5035
|
+
const parts = [];
|
|
5036
|
+
if (tokens > 0) parts.push(t("turnUsageTokens", { count: formatTokenCount(tokens) }));
|
|
5037
|
+
if (cached !== void 0) parts.push(t("turnUsageCache", { percent: (cached * 100).toFixed(1) }));
|
|
5038
|
+
if (usage.durationMs !== void 0) parts.push(formatTurnDuration(usage.durationMs));
|
|
5039
|
+
if (usage.ttftMs !== void 0) parts.push(t("turnUsageTtft", { duration: formatTurnDuration(usage.ttftMs) }));
|
|
5040
|
+
if (usage.cumulativeCostUsd !== void 0) parts.push(t("turnUsageCost", { cost: usage.cumulativeCostUsd.toFixed(2) }));
|
|
5041
|
+
return parts;
|
|
5042
|
+
}
|
|
5043
|
+
/** The footer the Host draws under its own assistant message, drawn here for
|
|
5044
|
+
* the steps the Host never had a message for. */
|
|
5045
|
+
function ClaudeTurnUsage({ usage, t }) {
|
|
5046
|
+
const parts = turnUsageParts(usage, t);
|
|
5047
|
+
if (parts.length === 0) return null;
|
|
5048
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
5049
|
+
className: "dsh-claude-turn-usage",
|
|
5050
|
+
children: [
|
|
5051
|
+
/* @__PURE__ */ jsx("span", {
|
|
5052
|
+
className: "dsh-claude-turn-usage-label",
|
|
5053
|
+
children: t("turnUsage")
|
|
5054
|
+
}),
|
|
5055
|
+
/* @__PURE__ */ jsx("span", {
|
|
5056
|
+
"aria-hidden": "true",
|
|
5057
|
+
children: "·"
|
|
5058
|
+
}),
|
|
5059
|
+
/* @__PURE__ */ jsx("span", { children: parts.join(" · ") })
|
|
5060
|
+
]
|
|
5061
|
+
});
|
|
5062
|
+
}
|
|
5063
|
+
function ClaudeActivityNode({ node, useClaudeProjection, t }) {
|
|
5064
|
+
ensureCss$3();
|
|
5065
|
+
const marker = node.data;
|
|
5066
|
+
const activities = useClaudeProjection((value) => selectStepActivities(value, marker.turn, marker.step));
|
|
5067
|
+
const tasks = useClaudeProjection((value) => value.tasks?.tasks ?? EMPTY_TASKS$1);
|
|
5068
|
+
const items = useMemo(() => transcriptItemsForStep(activities, marker.turn, marker.step, tasks), [
|
|
5069
|
+
activities,
|
|
5070
|
+
marker.step,
|
|
5071
|
+
marker.turn,
|
|
5072
|
+
tasks
|
|
5073
|
+
]);
|
|
5074
|
+
const markdownLabels = useClaudeMarkdownLabels(t);
|
|
5075
|
+
if (items.length === 0) return null;
|
|
5076
|
+
return /* @__PURE__ */ jsx("div", {
|
|
5077
|
+
className: "dsh-claude-flow",
|
|
5078
|
+
children: items.map((item) => item.kind === "text" ? /* @__PURE__ */ jsx("div", {
|
|
5079
|
+
className: "dsh-claude-transcript-text",
|
|
5080
|
+
children: /* @__PURE__ */ jsx(ClaudeMarkdown, {
|
|
5081
|
+
text: item.text,
|
|
5082
|
+
labels: markdownLabels
|
|
5083
|
+
})
|
|
5084
|
+
}, `text:${item.ordinal}`) : item.kind === "compaction" ? /* @__PURE__ */ jsx(ClaudeCompactionDivider, {
|
|
5085
|
+
compaction: item.compaction,
|
|
5086
|
+
t
|
|
5087
|
+
}, `compaction:${item.ordinal}`) : item.kind === "usage" ? /* @__PURE__ */ jsx(ClaudeTurnUsage, {
|
|
5088
|
+
usage: item.usage,
|
|
5089
|
+
t
|
|
5090
|
+
}, `usage:${item.ordinal}`) : item.kind === "tools" ? /* @__PURE__ */ jsx(ClaudeTranscriptToolGroup, {
|
|
5091
|
+
tools: item.tools,
|
|
5092
|
+
...item.additions === void 0 ? {} : { additions: item.additions },
|
|
5093
|
+
...item.deletions === void 0 ? {} : { deletions: item.deletions },
|
|
5094
|
+
...item.files === void 0 ? {} : { files: item.files },
|
|
5095
|
+
t
|
|
5096
|
+
}, `tools:${item.ordinal}`) : /* @__PURE__ */ jsx(ActivityRow, {
|
|
5097
|
+
row: item.row,
|
|
5098
|
+
t
|
|
5099
|
+
}, `activity:${item.ordinal}`))
|
|
5100
|
+
});
|
|
5101
|
+
}
|
|
5102
|
+
//#endregion
|
|
5103
|
+
//#region src/client/ClaudeTasksPanel.tsx
|
|
5104
|
+
const STATUS_LABEL = {
|
|
5105
|
+
running: "tasksRunning",
|
|
5106
|
+
completed: "tasksCompleted",
|
|
5107
|
+
failed: "tasksFailed",
|
|
5108
|
+
stopped: "tasksStopped",
|
|
5109
|
+
killed: "tasksKilled"
|
|
5110
|
+
};
|
|
5111
|
+
function visibleTaskGroups(tasks, dismissedSettledIds) {
|
|
5112
|
+
const projected = tasks.filter(isProjectedTask);
|
|
5113
|
+
return {
|
|
5114
|
+
running: projected.filter((task) => task.status === "running"),
|
|
5115
|
+
finished: projected.filter((task) => task.status !== "running" && !dismissedSettledIds.has(task.taskId))
|
|
5116
|
+
};
|
|
5117
|
+
}
|
|
5118
|
+
function activitiesForTask(activities, taskId) {
|
|
5119
|
+
return activities.filter((activity) => activity.taskId === taskId);
|
|
5120
|
+
}
|
|
5121
|
+
function tasksForTurn(tasks, turn) {
|
|
5122
|
+
return tasks.filter((task) => task.originTurn === turn && isProjectedTask(task));
|
|
5123
|
+
}
|
|
5124
|
+
function summarizeTurnTasks(tasks) {
|
|
5125
|
+
if (tasks.length === 0) return void 0;
|
|
5126
|
+
const running = tasks.filter((task) => task.status === "running").length;
|
|
5127
|
+
const failed = tasks.filter((task) => task.status === "failed" || task.status === "stopped" || task.status === "killed").length;
|
|
5128
|
+
const completed = tasks.filter((task) => task.status === "completed").length;
|
|
5129
|
+
return {
|
|
5130
|
+
state: running > 0 ? "running" : failed > 0 ? "failed" : "completed",
|
|
5131
|
+
count: tasks.length,
|
|
5132
|
+
running,
|
|
5133
|
+
failed,
|
|
5134
|
+
completed
|
|
5135
|
+
};
|
|
5136
|
+
}
|
|
5137
|
+
function statusGlyph(status) {
|
|
5138
|
+
if (status === "running") return "●";
|
|
5139
|
+
if (status === "completed") return "✓";
|
|
5140
|
+
if (status === "stopped") return "–";
|
|
5141
|
+
return "×";
|
|
5142
|
+
}
|
|
5143
|
+
function formatDuration(ms) {
|
|
5144
|
+
if (ms < 1e3) return String(Math.max(1, Math.round(ms))) + "ms";
|
|
5145
|
+
const seconds = Math.round(ms / 1e3);
|
|
5146
|
+
if (seconds < 60) return String(seconds) + "s";
|
|
5147
|
+
const minutes = Math.floor(seconds / 60);
|
|
5148
|
+
return String(minutes) + "m " + String(seconds % 60) + "s";
|
|
5149
|
+
}
|
|
5150
|
+
function taskMeta(task, t) {
|
|
5151
|
+
const parts = [];
|
|
5152
|
+
if (task.subagentType !== void 0) parts.push(task.subagentType);
|
|
5153
|
+
else if (task.taskType !== void 0) parts.push(task.taskType);
|
|
5154
|
+
if (task.usage?.durationMs !== void 0) parts.push(formatDuration(task.usage.durationMs));
|
|
5155
|
+
if (task.usage?.totalTokens !== void 0) parts.push(t("tokens", { count: formatTokenCount(task.usage.totalTokens) }));
|
|
5156
|
+
if (task.usage?.toolUses !== void 0) parts.push(t("tasksToolUses", { count: task.usage.toolUses }));
|
|
5157
|
+
if (task.lastToolName !== void 0) parts.push(t("tasksLastTool", { tool: task.lastToolName }));
|
|
5158
|
+
return parts;
|
|
5159
|
+
}
|
|
5160
|
+
function TaskActivity({ activity, t }) {
|
|
5161
|
+
return /* @__PURE__ */ jsxs("li", {
|
|
5162
|
+
style: taskActivityItem,
|
|
5163
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
5164
|
+
style: taskActivityGlyph,
|
|
5165
|
+
"aria-hidden": "true",
|
|
5166
|
+
children: activity.isError === true ? "×" : "›"
|
|
5167
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
5168
|
+
style: taskActivityBody,
|
|
5169
|
+
children: [
|
|
5170
|
+
/* @__PURE__ */ jsx("p", {
|
|
5171
|
+
style: taskActivityTitle,
|
|
5172
|
+
children: activity.title ?? activity.kind
|
|
5173
|
+
}),
|
|
5174
|
+
activity.summary === void 0 ? null : /* @__PURE__ */ jsx("p", {
|
|
5175
|
+
style: taskActivitySummary,
|
|
5176
|
+
children: activity.summary
|
|
5177
|
+
}),
|
|
5178
|
+
activity.detail === void 0 ? null : /* @__PURE__ */ jsxs("details", {
|
|
5179
|
+
style: taskActivityDetail,
|
|
5180
|
+
children: [/* @__PURE__ */ jsx("summary", {
|
|
5181
|
+
style: taskActivityDetailSummary,
|
|
5182
|
+
children: t("detail")
|
|
5183
|
+
}), /* @__PURE__ */ jsx("pre", {
|
|
5184
|
+
style: detailCode,
|
|
5185
|
+
children: activity.detail
|
|
5186
|
+
})]
|
|
5187
|
+
})
|
|
5188
|
+
]
|
|
5189
|
+
})]
|
|
5190
|
+
});
|
|
5191
|
+
}
|
|
5192
|
+
function TaskCard(props) {
|
|
5193
|
+
const { task, activities, allActivities, t } = props;
|
|
5194
|
+
const tools = useMemo(() => taskTools(allActivities, task.taskId), [allActivities, task.taskId]);
|
|
5195
|
+
const [activityOpen, setActivityOpen] = useState(false);
|
|
5196
|
+
const running = task.status === "running";
|
|
5197
|
+
const failed = task.status === "failed" || task.status === "killed";
|
|
5198
|
+
const meta = taskMeta(task, t);
|
|
5199
|
+
return /* @__PURE__ */ jsxs("article", {
|
|
5200
|
+
style: {
|
|
5201
|
+
...taskCard,
|
|
5202
|
+
...running ? taskCardRunning : {}
|
|
5203
|
+
},
|
|
5204
|
+
children: [
|
|
5205
|
+
/* @__PURE__ */ jsxs("div", {
|
|
5206
|
+
style: taskCardTop,
|
|
5207
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
5208
|
+
className: running ? "dsh-claude-act-running" : void 0,
|
|
5209
|
+
style: {
|
|
5210
|
+
...taskCardGlyph,
|
|
5211
|
+
...running ? iconChipRunning : {},
|
|
5212
|
+
...failed ? iconChipError : {}
|
|
5213
|
+
},
|
|
5214
|
+
"aria-hidden": "true",
|
|
5215
|
+
children: statusGlyph(task.status)
|
|
5216
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
5217
|
+
style: taskCardBody,
|
|
5218
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
5219
|
+
style: {
|
|
5220
|
+
...taskTitle,
|
|
5221
|
+
...failed ? { color: "var(--dsw-alias-state-error-primary)" } : {}
|
|
5222
|
+
},
|
|
5223
|
+
children: task.description
|
|
5224
|
+
}), /* @__PURE__ */ jsxs("p", {
|
|
5225
|
+
style: taskStatusLine,
|
|
5226
|
+
children: [/* @__PURE__ */ jsx("span", { children: t(STATUS_LABEL[task.status] ?? "tasksRunning") }), task.backgrounded === true ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
|
|
5227
|
+
"aria-hidden": "true",
|
|
5228
|
+
children: " · "
|
|
5229
|
+
}), /* @__PURE__ */ jsx("span", { children: t("tasksBackground") })] }) : null]
|
|
5230
|
+
})]
|
|
5231
|
+
})]
|
|
5232
|
+
}),
|
|
5233
|
+
meta.length === 0 ? null : /* @__PURE__ */ jsx("p", {
|
|
5234
|
+
style: taskMeta$1,
|
|
5235
|
+
children: meta.join(" · ")
|
|
5136
5236
|
}),
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
children:
|
|
5140
|
-
value: input,
|
|
5141
|
-
omit: ["command"]
|
|
5142
|
-
})
|
|
5237
|
+
task.summary === void 0 || running ? null : /* @__PURE__ */ jsx("p", {
|
|
5238
|
+
style: taskSummary,
|
|
5239
|
+
children: task.summary
|
|
5143
5240
|
}),
|
|
5144
|
-
/* @__PURE__ */
|
|
5145
|
-
|
|
5146
|
-
|
|
5241
|
+
activities.length === 0 && tools.length === 0 ? null : /* @__PURE__ */ jsxs("div", {
|
|
5242
|
+
style: taskActivitySection,
|
|
5243
|
+
children: [/* @__PURE__ */ jsx("button", {
|
|
5244
|
+
type: "button",
|
|
5245
|
+
style: taskTextButton,
|
|
5246
|
+
"aria-expanded": activityOpen,
|
|
5247
|
+
onClick: () => setActivityOpen((value) => !value),
|
|
5248
|
+
children: activityOpen ? t("tasksHideActivity") : t("tasksViewActivity")
|
|
5249
|
+
}), !activityOpen ? null : tools.length > 0 ? /* @__PURE__ */ jsx("div", {
|
|
5250
|
+
style: taskToolList,
|
|
5251
|
+
children: tools.map((tool) => /* @__PURE__ */ jsx(ClaudeTranscriptToolItem, {
|
|
5252
|
+
tool,
|
|
5253
|
+
t
|
|
5254
|
+
}, tool.toolUseId))
|
|
5255
|
+
}) : /* @__PURE__ */ jsx("ul", {
|
|
5256
|
+
style: taskActivityList,
|
|
5257
|
+
children: activities.map((activity) => /* @__PURE__ */ jsx(TaskActivity, {
|
|
5258
|
+
activity,
|
|
5259
|
+
t
|
|
5260
|
+
}, `${activity.turn}:${activity.step}:${activity.ordinal}`))
|
|
5261
|
+
})]
|
|
5147
5262
|
})
|
|
5148
|
-
]
|
|
5149
|
-
}
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
children:
|
|
5156
|
-
}), output === void 0 ? /* @__PURE__ */ jsx(TextDetail, {
|
|
5157
|
-
title: outputTitle,
|
|
5158
|
-
value: typeof outputValue === "string" ? outputValue : void 0
|
|
5159
|
-
}) : /* @__PURE__ */ jsx(Section, {
|
|
5160
|
-
title: outputTitle,
|
|
5161
|
-
children: /* @__PURE__ */ jsx(Fields, { value: output })
|
|
5263
|
+
]
|
|
5264
|
+
});
|
|
5265
|
+
}
|
|
5266
|
+
function GroupHeading(props) {
|
|
5267
|
+
const { label, count, collapsed, onToggle, action } = props;
|
|
5268
|
+
const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", { children: label }), /* @__PURE__ */ jsx("span", {
|
|
5269
|
+
style: tasksGroupCount,
|
|
5270
|
+
children: count
|
|
5162
5271
|
})] });
|
|
5272
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
5273
|
+
style: tasksGroupHeading,
|
|
5274
|
+
children: [onToggle === void 0 ? /* @__PURE__ */ jsx("div", {
|
|
5275
|
+
style: tasksGroupTitle,
|
|
5276
|
+
children: content
|
|
5277
|
+
}) : /* @__PURE__ */ jsxs("button", {
|
|
5278
|
+
type: "button",
|
|
5279
|
+
style: tasksGroupToggle,
|
|
5280
|
+
"aria-expanded": !collapsed,
|
|
5281
|
+
onClick: onToggle,
|
|
5282
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
5283
|
+
style: {
|
|
5284
|
+
...chevron,
|
|
5285
|
+
...collapsed === true ? {} : chevronOpen
|
|
5286
|
+
},
|
|
5287
|
+
children: "›"
|
|
5288
|
+
}), content]
|
|
5289
|
+
}), action === void 0 ? null : /* @__PURE__ */ jsx("button", {
|
|
5290
|
+
type: "button",
|
|
5291
|
+
style: taskTextButton,
|
|
5292
|
+
onClick: action.onClick,
|
|
5293
|
+
children: action.label
|
|
5294
|
+
})]
|
|
5295
|
+
});
|
|
5163
5296
|
}
|
|
5164
|
-
function
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
|
|
5177
|
-
|
|
5178
|
-
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5297
|
+
function ClaudeTasksPanel({ useClaudeProjection, t, closeDetails, turn }) {
|
|
5298
|
+
const projection = useClaudeProjection((value) => value);
|
|
5299
|
+
const tasks = useMemo(() => tasksForTurn(projection.tasks?.tasks ?? [], turn), [projection.tasks, turn]);
|
|
5300
|
+
useEffect(() => {
|
|
5301
|
+
if (!projection.owned || tasks.length === 0) closeDetails();
|
|
5302
|
+
}, [
|
|
5303
|
+
closeDetails,
|
|
5304
|
+
projection.owned,
|
|
5305
|
+
tasks.length
|
|
5306
|
+
]);
|
|
5307
|
+
const [finishedCollapsed, setFinishedCollapsed] = useState(false);
|
|
5308
|
+
const [dismissedSettledIds, setDismissedSettledIds] = useState(() => /* @__PURE__ */ new Set());
|
|
5309
|
+
const groups = useMemo(() => visibleTaskGroups(tasks, dismissedSettledIds), [tasks, dismissedSettledIds]);
|
|
5310
|
+
const taskActivities = useMemo(() => new Map(tasks.map((task) => [task.taskId, activitiesForTask(projection.activities, task.taskId)])), [projection.activities, tasks]);
|
|
5311
|
+
const clearFinished = () => setDismissedSettledIds((previous) => /* @__PURE__ */ new Set([...previous, ...tasks.filter((task) => task.status !== "running").map((task) => task.taskId)]));
|
|
5312
|
+
if (!projection.owned) return null;
|
|
5313
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
5314
|
+
className: detailsCardClass,
|
|
5315
|
+
style: tasksPanel,
|
|
5316
|
+
children: [
|
|
5317
|
+
/* @__PURE__ */ jsxs("style", {
|
|
5318
|
+
"data-dsh-claude-panel-icon-styles": true,
|
|
5319
|
+
children: [detailsCardCss, panelIconButtonCss]
|
|
5320
|
+
}),
|
|
5321
|
+
/* @__PURE__ */ jsxs("div", {
|
|
5322
|
+
style: tasksHeader,
|
|
5323
|
+
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("span", {
|
|
5324
|
+
style: tasksHeading,
|
|
5325
|
+
children: t("tasksPanelTurn")
|
|
5326
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
5327
|
+
style: tasksTurnMeta,
|
|
5328
|
+
children: t("tasksTurnNumber", { turn })
|
|
5329
|
+
})] }), /* @__PURE__ */ jsx("button", {
|
|
5330
|
+
type: "button",
|
|
5331
|
+
className: panelIconButtonClass,
|
|
5332
|
+
"aria-label": t("tasksClose"),
|
|
5333
|
+
onClick: closeDetails,
|
|
5334
|
+
children: /* @__PURE__ */ jsx(IconCloseOutline16, {})
|
|
5335
|
+
})]
|
|
5336
|
+
}),
|
|
5337
|
+
/* @__PURE__ */ jsxs("div", {
|
|
5338
|
+
style: tasksBody,
|
|
5339
|
+
children: [/* @__PURE__ */ jsxs("section", {
|
|
5340
|
+
"aria-label": t("tasksRunning"),
|
|
5341
|
+
children: [/* @__PURE__ */ jsx(GroupHeading, {
|
|
5342
|
+
label: t("tasksRunning"),
|
|
5343
|
+
count: groups.running.length
|
|
5344
|
+
}), groups.running.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
5345
|
+
style: tasksGroupEmpty,
|
|
5346
|
+
children: t("tasksNoneRunning")
|
|
5347
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
5348
|
+
style: taskCardList,
|
|
5349
|
+
children: groups.running.map((task) => /* @__PURE__ */ jsx(TaskCard, {
|
|
5350
|
+
task,
|
|
5351
|
+
activities: taskActivities.get(task.taskId) ?? [],
|
|
5352
|
+
allActivities: projection.activities,
|
|
5353
|
+
t
|
|
5354
|
+
}, task.taskId))
|
|
5355
|
+
})]
|
|
5356
|
+
}), /* @__PURE__ */ jsxs("section", {
|
|
5357
|
+
"aria-label": t("tasksSettled"),
|
|
5358
|
+
style: tasksFinishedSection,
|
|
5359
|
+
children: [/* @__PURE__ */ jsx(GroupHeading, {
|
|
5360
|
+
label: t("tasksSettled"),
|
|
5361
|
+
count: groups.finished.length,
|
|
5362
|
+
collapsed: finishedCollapsed,
|
|
5363
|
+
onToggle: () => setFinishedCollapsed((value) => !value),
|
|
5364
|
+
...groups.finished.length === 0 ? {} : { action: {
|
|
5365
|
+
label: t("tasksClear"),
|
|
5366
|
+
onClick: clearFinished
|
|
5367
|
+
} }
|
|
5368
|
+
}), finishedCollapsed || groups.finished.length === 0 ? null : /* @__PURE__ */ jsx("div", {
|
|
5369
|
+
style: taskCardList,
|
|
5370
|
+
children: groups.finished.map((task) => /* @__PURE__ */ jsx(TaskCard, {
|
|
5371
|
+
task,
|
|
5372
|
+
activities: taskActivities.get(task.taskId) ?? [],
|
|
5373
|
+
allActivities: projection.activities,
|
|
5374
|
+
t
|
|
5375
|
+
}, task.taskId))
|
|
5186
5376
|
})]
|
|
5187
|
-
})
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
className: "dsh-claude-tool-content",
|
|
5191
|
-
children: [tool.subcalls.length === 0 ? null : /* @__PURE__ */ jsx("div", {
|
|
5192
|
-
className: "dsh-claude-flow-subcalls",
|
|
5193
|
-
children: tool.subcalls.map((subcall) => /* @__PURE__ */ jsxs("div", { children: [
|
|
5194
|
-
subcallGlyph(subcall),
|
|
5195
|
-
" ",
|
|
5196
|
-
subcall.toolName ?? t("subagent"),
|
|
5197
|
-
subcall.summary === void 0 ? "" : ` · ${subcall.summary}`
|
|
5198
|
-
] }, subcall.toolUseId))
|
|
5199
|
-
}), /* @__PURE__ */ jsx(ToolPresentation, {
|
|
5200
|
-
tool,
|
|
5201
|
-
t
|
|
5202
|
-
})]
|
|
5203
|
-
})]
|
|
5377
|
+
})]
|
|
5378
|
+
})
|
|
5379
|
+
]
|
|
5204
5380
|
});
|
|
5205
5381
|
}
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5382
|
+
//#endregion
|
|
5383
|
+
//#region src/client/ClaudeActivityTail.tsx
|
|
5384
|
+
const MAX_HOVER_TASKS = 6;
|
|
5385
|
+
function taskGlyph(status) {
|
|
5386
|
+
if (status === "failed") return {
|
|
5387
|
+
glyph: "×",
|
|
5388
|
+
style: tasksHoverGlyphError
|
|
5389
|
+
};
|
|
5390
|
+
if (status === "completed") return {
|
|
5391
|
+
glyph: "✓",
|
|
5392
|
+
style: tasksHoverGlyphDone
|
|
5393
|
+
};
|
|
5394
|
+
return {
|
|
5395
|
+
glyph: "●",
|
|
5396
|
+
style: tasksHoverGlyphRunning
|
|
5397
|
+
};
|
|
5398
|
+
}
|
|
5399
|
+
function ClaudeTaskLauncher({ turn, tasks, t, openTasks }) {
|
|
5400
|
+
const [hovered, setHovered] = useState(false);
|
|
5401
|
+
const closeTimer = useRef();
|
|
5402
|
+
const turnTasks = useMemo(() => tasksForTurn(tasks, turn), [tasks, turn]);
|
|
5403
|
+
const summary = useMemo(() => summarizeTurnTasks(turnTasks), [turnTasks]);
|
|
5404
|
+
const open = () => {
|
|
5405
|
+
if (closeTimer.current !== void 0) clearTimeout(closeTimer.current);
|
|
5406
|
+
closeTimer.current = void 0;
|
|
5407
|
+
setHovered(true);
|
|
5408
|
+
};
|
|
5409
|
+
const scheduleClose = () => {
|
|
5410
|
+
if (closeTimer.current !== void 0) clearTimeout(closeTimer.current);
|
|
5411
|
+
closeTimer.current = setTimeout(() => {
|
|
5412
|
+
closeTimer.current = void 0;
|
|
5413
|
+
setHovered(false);
|
|
5414
|
+
}, 350);
|
|
5415
|
+
};
|
|
5416
|
+
useEffect(() => () => {
|
|
5417
|
+
if (closeTimer.current !== void 0) clearTimeout(closeTimer.current);
|
|
5418
|
+
}, []);
|
|
5419
|
+
if (summary === void 0) return null;
|
|
5420
|
+
const label = summary.state === "running" ? t("tasksTurnRunning", { count: summary.running }) : summary.state === "failed" ? t("tasksTurnFailed", {
|
|
5421
|
+
failed: summary.failed,
|
|
5422
|
+
completed: summary.completed
|
|
5423
|
+
}) : t("tasksTurnCompleted", { count: summary.completed });
|
|
5424
|
+
const stateStyle = summary.state === "completed" ? tasksBadgeDone : {};
|
|
5425
|
+
const dotStyle = summary.state === "failed" ? tasksBadgeDotError : summary.state === "completed" ? tasksBadgeDotDone : {};
|
|
5426
|
+
return /* @__PURE__ */ jsx("div", {
|
|
5427
|
+
"data-claude-task-launcher": turn,
|
|
5428
|
+
style: tasksBadgeWrap,
|
|
5429
|
+
children: /* @__PURE__ */ jsxs("span", {
|
|
5430
|
+
style: tasksBadgeSeat,
|
|
5431
|
+
onMouseEnter: open,
|
|
5432
|
+
onMouseLeave: scheduleClose,
|
|
5433
|
+
onFocus: open,
|
|
5434
|
+
onBlur: (event) => {
|
|
5435
|
+
if (!event.currentTarget.contains(event.relatedTarget)) scheduleClose();
|
|
5436
|
+
},
|
|
5437
|
+
children: [hovered ? /* @__PURE__ */ jsxs("span", {
|
|
5438
|
+
role: "tooltip",
|
|
5439
|
+
style: tasksHoverCard,
|
|
5440
|
+
onMouseEnter: open,
|
|
5441
|
+
onMouseLeave: scheduleClose,
|
|
5442
|
+
children: [
|
|
5443
|
+
/* @__PURE__ */ jsx("span", {
|
|
5444
|
+
style: tasksHoverHeader,
|
|
5445
|
+
children: label
|
|
5446
|
+
}),
|
|
5447
|
+
turnTasks.slice(0, MAX_HOVER_TASKS).map((task) => {
|
|
5448
|
+
const { glyph, style } = taskGlyph(task.status);
|
|
5449
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
5450
|
+
style: tasksHoverRow,
|
|
5451
|
+
children: [
|
|
5452
|
+
/* @__PURE__ */ jsx("span", {
|
|
5453
|
+
className: task.status === "running" ? "dsh-claude-act-running" : void 0,
|
|
5454
|
+
style: {
|
|
5455
|
+
...tasksHoverGlyph,
|
|
5456
|
+
...style
|
|
5457
|
+
},
|
|
5458
|
+
"aria-hidden": "true",
|
|
5459
|
+
children: glyph
|
|
5460
|
+
}),
|
|
5461
|
+
/* @__PURE__ */ jsx("span", {
|
|
5462
|
+
style: tasksHoverDesc,
|
|
5463
|
+
title: task.description,
|
|
5464
|
+
children: task.description
|
|
5465
|
+
}),
|
|
5466
|
+
task.subagentType === void 0 ? null : /* @__PURE__ */ jsx("span", {
|
|
5467
|
+
style: tasksHoverType,
|
|
5468
|
+
children: task.subagentType
|
|
5469
|
+
})
|
|
5470
|
+
]
|
|
5471
|
+
}, task.taskId);
|
|
5472
|
+
}),
|
|
5473
|
+
turnTasks.length > MAX_HOVER_TASKS ? /* @__PURE__ */ jsxs("span", {
|
|
5474
|
+
style: tasksHoverMore,
|
|
5475
|
+
children: ["+", turnTasks.length - MAX_HOVER_TASKS]
|
|
5476
|
+
}) : null,
|
|
5477
|
+
/* @__PURE__ */ jsx("span", {
|
|
5478
|
+
style: tasksHoverHint,
|
|
5479
|
+
children: t("tasksOpen")
|
|
5480
|
+
})
|
|
5481
|
+
]
|
|
5482
|
+
}) : null, /* @__PURE__ */ jsxs("button", {
|
|
5483
|
+
type: "button",
|
|
5484
|
+
className: "dsh-claude-task-launcher",
|
|
5485
|
+
style: {
|
|
5486
|
+
...tasksTurnBadge,
|
|
5487
|
+
...stateStyle,
|
|
5488
|
+
...hovered ? tasksBadgeHovered : {}
|
|
5489
|
+
},
|
|
5490
|
+
"aria-label": `${label} — ${t("tasksOpen")}`,
|
|
5491
|
+
onClick: () => openTasks(turn),
|
|
5492
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
5493
|
+
className: summary.state === "running" ? "dsh-claude-act-running" : void 0,
|
|
5494
|
+
style: {
|
|
5495
|
+
...tasksBadgeDot,
|
|
5496
|
+
...dotStyle
|
|
5497
|
+
},
|
|
5498
|
+
"aria-hidden": "true"
|
|
5499
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
5500
|
+
style: tasksBadgeLabel,
|
|
5501
|
+
children: label
|
|
5233
5502
|
})]
|
|
5234
|
-
})
|
|
5235
|
-
})
|
|
5236
|
-
className: "dsh-claude-tool-list",
|
|
5237
|
-
children: tools.map((tool) => /* @__PURE__ */ jsx(ClaudeTranscriptToolItem, {
|
|
5238
|
-
tool,
|
|
5239
|
-
t
|
|
5240
|
-
}, tool.toolUseId))
|
|
5241
|
-
}) : null]
|
|
5503
|
+
})]
|
|
5504
|
+
})
|
|
5242
5505
|
});
|
|
5243
5506
|
}
|
|
5244
|
-
function
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5507
|
+
function ClaudeActivityTail({ matched, useClaudeProjection, t, openTasks }) {
|
|
5508
|
+
const tasks = useClaudeProjection((value) => value.tasks?.tasks ?? []);
|
|
5509
|
+
return /* @__PURE__ */ jsx(ClaudeTaskLauncher, {
|
|
5510
|
+
turn: matched.turn,
|
|
5511
|
+
tasks,
|
|
5512
|
+
t,
|
|
5513
|
+
openTasks
|
|
5514
|
+
});
|
|
5515
|
+
}
|
|
5516
|
+
//#endregion
|
|
5517
|
+
//#region src/client/ClaudeActiveTasksNode.tsx
|
|
5518
|
+
const EMPTY_TASKS = [];
|
|
5519
|
+
/** Render the task launcher while the owning DSH turn is still open. */
|
|
5520
|
+
function ClaudeActiveTasksNode({ node, useClaudeProjection, t, openTasks }) {
|
|
5248
5521
|
const tasks = useClaudeProjection((value) => value.tasks?.tasks ?? EMPTY_TASKS);
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
]);
|
|
5255
|
-
const markdownLabels = useClaudeMarkdownLabels(t);
|
|
5256
|
-
if (items.length === 0) return null;
|
|
5257
|
-
return /* @__PURE__ */ jsx("div", {
|
|
5258
|
-
className: "dsh-claude-flow",
|
|
5259
|
-
children: items.map((item) => item.kind === "text" ? /* @__PURE__ */ jsx("div", {
|
|
5260
|
-
className: "dsh-claude-transcript-text",
|
|
5261
|
-
children: /* @__PURE__ */ jsx(ClaudeMarkdown, {
|
|
5262
|
-
text: item.text,
|
|
5263
|
-
labels: markdownLabels
|
|
5264
|
-
})
|
|
5265
|
-
}, `text:${item.ordinal}`) : item.kind === "compaction" ? /* @__PURE__ */ jsx(ClaudeCompactionDivider, {
|
|
5266
|
-
compaction: item.compaction,
|
|
5267
|
-
t
|
|
5268
|
-
}, `compaction:${item.ordinal}`) : item.kind === "tools" ? /* @__PURE__ */ jsx(ClaudeTranscriptToolGroup, {
|
|
5269
|
-
tools: item.tools,
|
|
5270
|
-
...item.additions === void 0 ? {} : { additions: item.additions },
|
|
5271
|
-
...item.deletions === void 0 ? {} : { deletions: item.deletions },
|
|
5272
|
-
...item.files === void 0 ? {} : { files: item.files },
|
|
5273
|
-
t
|
|
5274
|
-
}, `tools:${item.ordinal}`) : /* @__PURE__ */ jsx(ActivityRow, {
|
|
5275
|
-
row: item.row,
|
|
5276
|
-
t
|
|
5277
|
-
}, `activity:${item.ordinal}`))
|
|
5522
|
+
return /* @__PURE__ */ jsx(ClaudeTaskLauncher, {
|
|
5523
|
+
turn: node.data.turn,
|
|
5524
|
+
tasks,
|
|
5525
|
+
t,
|
|
5526
|
+
openTasks
|
|
5278
5527
|
});
|
|
5279
5528
|
}
|
|
5280
5529
|
//#endregion
|
|
@@ -5394,6 +5643,7 @@ window.__ModuleLoader__.load({
|
|
|
5394
5643
|
if (typeof setting !== "object" || setting === null || Array.isArray(setting)) return false;
|
|
5395
5644
|
const item = setting;
|
|
5396
5645
|
if (typeof item.key !== "string" || typeof item.value !== "string" || ![
|
|
5646
|
+
"immediate",
|
|
5397
5647
|
"new-session",
|
|
5398
5648
|
"next-turn",
|
|
5399
5649
|
"next-worktree",
|
|
@@ -5584,6 +5834,23 @@ window.__ModuleLoader__.load({
|
|
|
5584
5834
|
"seven_day_opus",
|
|
5585
5835
|
"seven_day_sonnet"
|
|
5586
5836
|
]);
|
|
5837
|
+
/** The prose mode a settings payload carries, or the default when it carries
|
|
5838
|
+
* none — an older Host, or a response this Client does not fully understand,
|
|
5839
|
+
* leaves the palette alone rather than guessing. */
|
|
5840
|
+
function proseModeOf(settings) {
|
|
5841
|
+
const value = settings.find((setting) => setting.key === "prose")?.value;
|
|
5842
|
+
return isClaudeProseMode(value) ? value : DEFAULT_CLAUDE_PROSE_MODE;
|
|
5843
|
+
}
|
|
5844
|
+
/** Settings whose row only makes sense under a particular value of another.
|
|
5845
|
+
* Filtering here rather than server-side keeps the descriptor list flat: the
|
|
5846
|
+
* server has no view of what the Client can paint. Fails OPEN — a payload
|
|
5847
|
+
* missing the setting a row depends on shows the row rather than hiding it,
|
|
5848
|
+
* so an older Host cannot make a setting unreachable. */
|
|
5849
|
+
function visibleGlobalSettings(settings) {
|
|
5850
|
+
const renderer = settings.find((setting) => setting.key === "renderer");
|
|
5851
|
+
if (renderer === void 0 || renderer.value !== "native") return settings;
|
|
5852
|
+
return settings.filter((setting) => setting.key !== "prose");
|
|
5853
|
+
}
|
|
5587
5854
|
/** Per-setting label and the effect note that used to sit as a standalone
|
|
5588
5855
|
* paragraph under the card; it now hangs off the label as a hover hint. */
|
|
5589
5856
|
const SETTING_COPY = {
|
|
@@ -5595,6 +5862,10 @@ window.__ModuleLoader__.load({
|
|
|
5595
5862
|
label: "renderer",
|
|
5596
5863
|
hint: "rendererEffect"
|
|
5597
5864
|
},
|
|
5865
|
+
prose: {
|
|
5866
|
+
label: "prose",
|
|
5867
|
+
hint: "proseEffect"
|
|
5868
|
+
},
|
|
5598
5869
|
worktreeBranchPrefix: {
|
|
5599
5870
|
label: "worktreeBranchPrefix",
|
|
5600
5871
|
hint: "worktreeBranchPrefixEffect"
|
|
@@ -5613,7 +5884,9 @@ window.__ModuleLoader__.load({
|
|
|
5613
5884
|
* names) carry no entry and keep the label the route reported. */
|
|
5614
5885
|
const SETTING_OPTION_COPY = {
|
|
5615
5886
|
"renderer:plugin": "rendererPlugin",
|
|
5616
|
-
"renderer:native": "rendererNative"
|
|
5887
|
+
"renderer:native": "rendererNative",
|
|
5888
|
+
"prose:plain": "prosePlain",
|
|
5889
|
+
"prose:enhanced": "proseEnhanced"
|
|
5617
5890
|
};
|
|
5618
5891
|
function settingOptionLabel(settingKey, option, t) {
|
|
5619
5892
|
const key = SETTING_OPTION_COPY[`${settingKey}:${option.value}`];
|
|
@@ -5852,6 +6125,7 @@ window.__ModuleLoader__.load({
|
|
|
5852
6125
|
});
|
|
5853
6126
|
if (!isGlobalSettingsView(payload)) throw new Error("Invalid global settings response");
|
|
5854
6127
|
setGlobalSettings(payload);
|
|
6128
|
+
applyClaudeMarkdownTheme(proseModeOf(payload.settings));
|
|
5855
6129
|
} catch (cause) {
|
|
5856
6130
|
setGlobalSettingsError(cardFailure(cause));
|
|
5857
6131
|
} finally {
|
|
@@ -5962,7 +6236,7 @@ window.__ModuleLoader__.load({
|
|
|
5962
6236
|
globalSettings === void 0 ? /* @__PURE__ */ jsx("p", {
|
|
5963
6237
|
style: notice,
|
|
5964
6238
|
children: t("globalSettingsLoading")
|
|
5965
|
-
}) : globalSettings.settings.map((setting) => {
|
|
6239
|
+
}) : visibleGlobalSettings(globalSettings.settings).map((setting) => {
|
|
5966
6240
|
const copy = SETTING_COPY[setting.key];
|
|
5967
6241
|
return /* @__PURE__ */ jsxs("div", {
|
|
5968
6242
|
style: diagnosticGrid,
|
|
@@ -6305,10 +6579,14 @@ window.__ModuleLoader__.load({
|
|
|
6305
6579
|
const HOST_STAGES = /* @__PURE__ */ new Set([
|
|
6306
6580
|
"inspecting",
|
|
6307
6581
|
"fetching",
|
|
6582
|
+
"summarizing",
|
|
6308
6583
|
"creating-worktree",
|
|
6309
6584
|
"saving-worktree",
|
|
6310
6585
|
"switching-branch"
|
|
6311
6586
|
]);
|
|
6587
|
+
/** The draft only has to describe the work; the host truncates it again before
|
|
6588
|
+
* summarizing, and the setup route caps the whole body at 16 KiB. */
|
|
6589
|
+
const MAX_INTENT_CHARS = 2e3;
|
|
6312
6590
|
function record$3(value) {
|
|
6313
6591
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
6314
6592
|
}
|
|
@@ -6344,7 +6622,7 @@ window.__ModuleLoader__.load({
|
|
|
6344
6622
|
throw error;
|
|
6345
6623
|
}
|
|
6346
6624
|
}
|
|
6347
|
-
async function prepareRepository(cwd, branch, worktree, branchName, onProgress = () => {}) {
|
|
6625
|
+
async function prepareRepository(cwd, branch, worktree, branchName, onProgress = () => {}, intent) {
|
|
6348
6626
|
const carrier = new AbortController();
|
|
6349
6627
|
try {
|
|
6350
6628
|
const reader = await pluginNdjson(CLAUDE_REPOSITORY_SETUP_PATH, carrier.signal, {
|
|
@@ -6353,7 +6631,8 @@ window.__ModuleLoader__.load({
|
|
|
6353
6631
|
cwd,
|
|
6354
6632
|
branch,
|
|
6355
6633
|
worktree,
|
|
6356
|
-
...branchName === void 0 ? {} : { branchName }
|
|
6634
|
+
...branchName === void 0 ? {} : { branchName },
|
|
6635
|
+
...intent === void 0 || intent.trim().length === 0 ? {} : { intent: intent.slice(0, MAX_INTENT_CHARS) }
|
|
6357
6636
|
}
|
|
6358
6637
|
});
|
|
6359
6638
|
const decoder = new TextDecoder();
|
|
@@ -6642,10 +6921,40 @@ window.__ModuleLoader__.load({
|
|
|
6642
6921
|
const CLAUDE_SCOPED_CSS_VARIABLES = ["--dsh-composer-card-max-width"];
|
|
6643
6922
|
/** Marks the bar the scoped-property probe measures. */
|
|
6644
6923
|
const CLAUDE_COMPOSER_BAR_ATTRIBUTE = "data-dsh-claude-composer-bar";
|
|
6645
|
-
/**
|
|
6646
|
-
|
|
6924
|
+
/** Methods this plugin calls on the Host services it injects.
|
|
6925
|
+
*
|
|
6926
|
+
* A service that still resolves but has lost a method is the drift the
|
|
6927
|
+
* service list above cannot see: Desktop 0.1.2 moved `connectWorkspace` off
|
|
6928
|
+
* `workspaces` onto a new service, and the worktree flow went on registering
|
|
6929
|
+
* itself and only broke once a user ran it. Naming the methods here turns
|
|
6930
|
+
* that into a boot-time line. Methods with a runtime fallback stay out. */
|
|
6931
|
+
const CLAUDE_REQUIRED_SERVICE_METHODS = {
|
|
6932
|
+
sessions: [
|
|
6933
|
+
"scope",
|
|
6934
|
+
"open",
|
|
6935
|
+
"binding"
|
|
6936
|
+
],
|
|
6937
|
+
workspaces: [
|
|
6938
|
+
"create",
|
|
6939
|
+
"delete",
|
|
6940
|
+
"archiveSession"
|
|
6941
|
+
],
|
|
6942
|
+
uiConversation: ["binding"],
|
|
6943
|
+
uiSession: ["provide"],
|
|
6944
|
+
inputTriggers: ["registerSource"]
|
|
6945
|
+
};
|
|
6946
|
+
/** One line per service the Host no longer provides, or provides without a
|
|
6947
|
+
* method this plugin calls on it; empty when everything resolves. */
|
|
6948
|
+
function claudeBootCheckFindings(input, methods = CLAUDE_REQUIRED_SERVICE_METHODS) {
|
|
6647
6949
|
const findings = [];
|
|
6648
|
-
for (const name of input.services)
|
|
6950
|
+
for (const name of input.services) {
|
|
6951
|
+
const service = input.resolve(name);
|
|
6952
|
+
if (service === void 0) {
|
|
6953
|
+
findings.push(`service "${name}" is declared in inject but the Host does not provide it`);
|
|
6954
|
+
continue;
|
|
6955
|
+
}
|
|
6956
|
+
for (const method of methods[name] ?? []) if (typeof service[method] !== "function") findings.push(`service "${name}" no longer provides ${method}(); the features calling it are broken`);
|
|
6957
|
+
}
|
|
6649
6958
|
return findings;
|
|
6650
6959
|
}
|
|
6651
6960
|
/** One line per scoped custom property the measured element cannot see.
|
|
@@ -7578,9 +7887,15 @@ window.__ModuleLoader__.load({
|
|
|
7578
7887
|
style: repositoryRemote,
|
|
7579
7888
|
children: repositoryName$1(repository.remote)
|
|
7580
7889
|
}),
|
|
7581
|
-
/* @__PURE__ */ jsx(
|
|
7582
|
-
|
|
7583
|
-
|
|
7890
|
+
/* @__PURE__ */ jsx(Tooltip, {
|
|
7891
|
+
label: branch,
|
|
7892
|
+
side: "top",
|
|
7893
|
+
delayMs: 250,
|
|
7894
|
+
maxWidth: 420,
|
|
7895
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
7896
|
+
style: repositoryBranch,
|
|
7897
|
+
children: branch
|
|
7898
|
+
})
|
|
7584
7899
|
}),
|
|
7585
7900
|
repository.worktree === true ? /* @__PURE__ */ jsx("span", {
|
|
7586
7901
|
style: repositoryWorktree,
|
|
@@ -7772,7 +8087,9 @@ window.__ModuleLoader__.load({
|
|
|
7772
8087
|
children: comment.text
|
|
7773
8088
|
})]
|
|
7774
8089
|
}),
|
|
7775
|
-
openDelayMs: 250
|
|
8090
|
+
openDelayMs: 250,
|
|
8091
|
+
copyLabel: t("markdownCopy"),
|
|
8092
|
+
copiedLabel: t("markdownCopied")
|
|
7776
8093
|
});
|
|
7777
8094
|
}
|
|
7778
8095
|
/** Pending review comments docked above the composer; drained by the next user turn. */
|
|
@@ -13841,7 +14158,7 @@ window.__ModuleLoader__.load({
|
|
|
13841
14158
|
* @returns the preset id, or undefined when neither source carries one.
|
|
13842
14159
|
*/
|
|
13843
14160
|
function sessionRowPreset(row) {
|
|
13844
|
-
return row?.agentPreset ?? row?.projectionValues?.agentPreset;
|
|
14161
|
+
return row?.agentPreset ?? row?.projectionValues?.agentPreset ?? void 0;
|
|
13845
14162
|
}
|
|
13846
14163
|
//#endregion
|
|
13847
14164
|
//#region src/client/ClaudePullRequestsPanel.tsx
|
|
@@ -15072,10 +15389,15 @@ window.__ModuleLoader__.load({
|
|
|
15072
15389
|
}
|
|
15073
15390
|
//#endregion
|
|
15074
15391
|
//#region src/client/ClaudeHeroRepositoryControls.tsx
|
|
15392
|
+
/** The host composer was a textarea through rc.8 and is a Lexical
|
|
15393
|
+
* contenteditable from 0.1.2 on, so match the composer seat rather than the
|
|
15394
|
+
* element type: an element-type check silently stops intercepting Enter, and
|
|
15395
|
+
* the capsule's branch and Worktree choices go nowhere. */
|
|
15075
15396
|
function shouldInterceptKey(event) {
|
|
15076
15397
|
if (event.key !== "Enter" || event.shiftKey || event.repeat || event.isComposing) return false;
|
|
15077
15398
|
const target = event.target;
|
|
15078
|
-
|
|
15399
|
+
if (!(target instanceof Element)) return false;
|
|
15400
|
+
return target.closest("textarea, [data-composer-input]") !== null && target.closest("[data-phase=\"hero\"]") !== null;
|
|
15079
15401
|
}
|
|
15080
15402
|
function shouldInterceptClick(event) {
|
|
15081
15403
|
const target = event.target;
|
|
@@ -15111,6 +15433,7 @@ window.__ModuleLoader__.load({
|
|
|
15111
15433
|
const WORKTREE_PROGRESS_STAGES = [
|
|
15112
15434
|
"inspecting",
|
|
15113
15435
|
"fetching",
|
|
15436
|
+
"summarizing",
|
|
15114
15437
|
"creating-worktree",
|
|
15115
15438
|
"saving-worktree",
|
|
15116
15439
|
"creating-workspace",
|
|
@@ -15121,6 +15444,7 @@ window.__ModuleLoader__.load({
|
|
|
15121
15444
|
const PROGRESS_LABEL_KEYS = {
|
|
15122
15445
|
inspecting: "repositoryProgress_inspecting",
|
|
15123
15446
|
fetching: "repositoryProgress_fetching",
|
|
15447
|
+
summarizing: "repositoryProgress_summarizing",
|
|
15124
15448
|
"creating-worktree": "repositoryProgress_creating-worktree",
|
|
15125
15449
|
"saving-worktree": "repositoryProgress_saving-worktree",
|
|
15126
15450
|
"switching-branch": "repositoryProgress_switching-branch",
|
|
@@ -16702,6 +17026,10 @@ window.__ModuleLoader__.load({
|
|
|
16702
17026
|
rendererPlugin: "插件渲染器",
|
|
16703
17027
|
rendererNative: "DSH 原生渲染器",
|
|
16704
17028
|
rendererEffect: "插件渲染器沿用本插件自带的转录视图:交错的正文、成组的工具卡片与活动行。DSH 原生渲染器改由 DSH 自身绘制:正文作为普通助手文本块,思考作为推理块,Claude 的顶层工具会镜像成原生工具卡片。修改从下一个回合起生效;已经产生的回合仍按记录时的渲染器显示,不会重绘。",
|
|
17029
|
+
prose: "Markdown 彩色高亮",
|
|
17030
|
+
prosePlain: "关闭",
|
|
17031
|
+
proseEnhanced: "开启",
|
|
17032
|
+
proseEffect: "开启后,正文的标题、加粗、斜体、行内代码、列表符号、引用与链接各自着色,代码块换成深色描边底。这会覆盖本插件默认对齐 Claude 桌面版的配色。仅在使用插件渲染器时有效,改动立即生效,无需等待下一回合。",
|
|
16705
17033
|
worktreeBranchPrefix: "Worktree 分支前缀",
|
|
16706
17034
|
worktreeBranchPrefixEffect: "分支前缀修改会应用于之后自动创建的 Worktree 分支;显式指定的完整分支名不会被修改。",
|
|
16707
17035
|
maxProcessesSetting: "Claude 进程上限",
|
|
@@ -16796,6 +17124,7 @@ window.__ModuleLoader__.load({
|
|
|
16796
17124
|
repositoryProgressDismiss: "关闭 Worktree 进度",
|
|
16797
17125
|
repositoryProgress_inspecting: "检查仓库和分支",
|
|
16798
17126
|
repositoryProgress_fetching: "刷新远程引用",
|
|
17127
|
+
repositoryProgress_summarizing: "总结需求生成分支名",
|
|
16799
17128
|
"repositoryProgress_creating-worktree": "创建分支和 Worktree",
|
|
16800
17129
|
"repositoryProgress_saving-worktree": "保存 Worktree 状态",
|
|
16801
17130
|
"repositoryProgress_switching-branch": "切换本地分支",
|
|
@@ -16853,6 +17182,9 @@ window.__ModuleLoader__.load({
|
|
|
16853
17182
|
diffCommentNext: "下一条评论",
|
|
16854
17183
|
diffCommentPosition: "第 {index} 条,共 {total} 条",
|
|
16855
17184
|
diffCommentCounter: "{index}/{total}",
|
|
17185
|
+
diffCardExpand: "展开其余 {count} 行",
|
|
17186
|
+
diffCardCollapse: "收起",
|
|
17187
|
+
diffCardFiles: "{count} 个文件",
|
|
16856
17188
|
diffExpandAll: "展开全部文件",
|
|
16857
17189
|
diffCollapseAll: "收起全部文件",
|
|
16858
17190
|
diffRestore: "还原 Diff 面板",
|
|
@@ -17014,7 +17346,12 @@ window.__ModuleLoader__.load({
|
|
|
17014
17346
|
rewindSubmitting: "回退中…",
|
|
17015
17347
|
rewindFailed: "回退失败({code})。",
|
|
17016
17348
|
rewindBusy: "这个会话正在运行,请等本轮结束后再回退。",
|
|
17017
|
-
rewindStale: "宿主进程里的插件还是旧版本(没有回退接口)。重启 DSH 后再试。"
|
|
17349
|
+
rewindStale: "宿主进程里的插件还是旧版本(没有回退接口)。重启 DSH 后再试。",
|
|
17350
|
+
turnUsage: "本回合用量",
|
|
17351
|
+
turnUsageTokens: "{count} tok",
|
|
17352
|
+
turnUsageCache: "缓存命中 {percent}%",
|
|
17353
|
+
turnUsageTtft: "首字 {duration}",
|
|
17354
|
+
turnUsageCost: "累计 ${cost}"
|
|
17018
17355
|
};
|
|
17019
17356
|
const en = {
|
|
17020
17357
|
nav: "Claude Code",
|
|
@@ -17066,6 +17403,10 @@ window.__ModuleLoader__.load({
|
|
|
17066
17403
|
rendererPlugin: "Plugin renderer",
|
|
17067
17404
|
rendererNative: "DSH native renderer",
|
|
17068
17405
|
rendererEffect: "The plugin renderer keeps this package’s own transcript: interleaved prose, grouped tool cards, and activity rows. The DSH native renderer hands the same turn to DSH itself — prose as ordinary assistant text blocks, thinking as reasoning blocks, and root Claude tools mirrored into native tool cards. A change applies from the next turn; turns already recorded keep the renderer they were recorded with and are not redrawn.",
|
|
17406
|
+
prose: "Markdown colour highlighting",
|
|
17407
|
+
prosePlain: "Off",
|
|
17408
|
+
proseEnhanced: "On",
|
|
17409
|
+
proseEffect: "Gives headings, bold, italics, inline code, list markers, quotes and links their own colours, and paints the code block on a dark outlined surface. This overrides the Claude-desktop palette this package matches by default. Only applies under the plugin renderer, and takes effect immediately rather than on the next turn.",
|
|
17069
17410
|
worktreeBranchPrefix: "Worktree branch prefix",
|
|
17070
17411
|
worktreeBranchPrefixEffect: "Prefix changes apply to subsequently generated Worktree branches. Explicit full branch names remain unchanged.",
|
|
17071
17412
|
maxProcessesSetting: "Claude process limit",
|
|
@@ -17160,6 +17501,7 @@ window.__ModuleLoader__.load({
|
|
|
17160
17501
|
repositoryProgressDismiss: "Dismiss Worktree progress",
|
|
17161
17502
|
repositoryProgress_inspecting: "Checking repository and branch",
|
|
17162
17503
|
repositoryProgress_fetching: "Refreshing remote references",
|
|
17504
|
+
repositoryProgress_summarizing: "Naming the branch after the request",
|
|
17163
17505
|
"repositoryProgress_creating-worktree": "Creating branch and Worktree",
|
|
17164
17506
|
"repositoryProgress_saving-worktree": "Saving Worktree state",
|
|
17165
17507
|
"repositoryProgress_switching-branch": "Switching local branch",
|
|
@@ -17217,6 +17559,9 @@ window.__ModuleLoader__.load({
|
|
|
17217
17559
|
diffCommentNext: "Next comment",
|
|
17218
17560
|
diffCommentPosition: "Comment {index} of {total}",
|
|
17219
17561
|
diffCommentCounter: "{index}/{total}",
|
|
17562
|
+
diffCardExpand: "Show {count} more lines",
|
|
17563
|
+
diffCardCollapse: "Show less",
|
|
17564
|
+
diffCardFiles: "{count} files",
|
|
17220
17565
|
diffExpandAll: "Expand all files",
|
|
17221
17566
|
diffCollapseAll: "Collapse all files",
|
|
17222
17567
|
diffRestore: "Restore diff panel",
|
|
@@ -17378,7 +17723,12 @@ window.__ModuleLoader__.load({
|
|
|
17378
17723
|
rewindSubmitting: "Rewinding…",
|
|
17379
17724
|
rewindFailed: "The rewind failed ({code}).",
|
|
17380
17725
|
rewindBusy: "This session is running; wait for the turn to finish before rewinding.",
|
|
17381
|
-
rewindStale: "The Host process is still running the previous plugin build, which has no rewind route. Restart DSH and try again."
|
|
17726
|
+
rewindStale: "The Host process is still running the previous plugin build, which has no rewind route. Restart DSH and try again.",
|
|
17727
|
+
turnUsage: "Turn usage",
|
|
17728
|
+
turnUsageTokens: "{count} tok",
|
|
17729
|
+
turnUsageCache: "Cache hit {percent}%",
|
|
17730
|
+
turnUsageTtft: "TTFT {duration}",
|
|
17731
|
+
turnUsageCost: "${cost} total"
|
|
17382
17732
|
};
|
|
17383
17733
|
//#endregion
|
|
17384
17734
|
//#region src/client/index.tsx
|
|
@@ -17412,6 +17762,17 @@ window.__ModuleLoader__.load({
|
|
|
17412
17762
|
"conversation",
|
|
17413
17763
|
"connection"
|
|
17414
17764
|
];
|
|
17765
|
+
/** Resolve one session's composer facade.
|
|
17766
|
+
*
|
|
17767
|
+
* `sessions.scope()` returns the client runtime's AgentContext, and the
|
|
17768
|
+
* conversation package -- a release ahead of the runtime in the graph the Host
|
|
17769
|
+
* itself ships -- types `input.for` against a Context whose `remote` has since
|
|
17770
|
+
* gained `$stream` and `$host`. It is the same object at runtime; only the two
|
|
17771
|
+
* declarations disagree, and they disagree inside the Host too, so the cast
|
|
17772
|
+
* lives here once instead of at all nine call sites. */
|
|
17773
|
+
function sessionInput(conversation, scope) {
|
|
17774
|
+
return conversation.input.for(scope);
|
|
17775
|
+
}
|
|
17415
17776
|
function apply(ctx) {
|
|
17416
17777
|
const namespace = "settings.claude-code";
|
|
17417
17778
|
const diagnostics = createClaudeDiagnosticsReporter();
|
|
@@ -17428,12 +17789,17 @@ window.__ModuleLoader__.load({
|
|
|
17428
17789
|
}), "dsh-claude: client copy");
|
|
17429
17790
|
const t = ctx.locale.bind(namespace);
|
|
17430
17791
|
ctx.effect(() => restyleHostChrome(), "dsh-claude: Host chrome restyling");
|
|
17792
|
+
pluginRead(CLAUDE_GLOBAL_SETTINGS_PATH, "fast").then((payload) => {
|
|
17793
|
+
if (isGlobalSettingsView(payload)) applyClaudeMarkdownTheme(proseModeOf(payload.settings));
|
|
17794
|
+
}).catch(() => {});
|
|
17431
17795
|
const projections = new ClaudeProjectionStore({ report: (kind, detail) => {
|
|
17432
17796
|
diagnostics.report(kind, detail);
|
|
17433
17797
|
} });
|
|
17434
17798
|
ctx.effect(() => ctx.inputTriggers.registerSource(createClaudeCommandSource(ctx, projections)), "dsh-claude: Claude slash source");
|
|
17435
17799
|
const sessions = ctx.get("sessions");
|
|
17436
17800
|
const workspaces = ctx.get("workspaces");
|
|
17801
|
+
const uiWorkspace = ctx.get("uiWorkspace");
|
|
17802
|
+
const connectWorkspace = uiWorkspace?.connectWorkspace?.bind(uiWorkspace) ?? (typeof workspaces?.connectWorkspace === "function" ? workspaces.connectWorkspace.bind(workspaces) : void 0);
|
|
17437
17803
|
const conversation = ctx.get("conversation");
|
|
17438
17804
|
const connection = ctx.get("connection");
|
|
17439
17805
|
const remote = ctx.get("remote");
|
|
@@ -17445,7 +17811,7 @@ window.__ModuleLoader__.load({
|
|
|
17445
17811
|
return (draft, mode = "append") => {
|
|
17446
17812
|
const scope = sessions.scope(sessionId);
|
|
17447
17813
|
if (scope === void 0) return false;
|
|
17448
|
-
const input = conversation
|
|
17814
|
+
const input = sessionInput(conversation, scope);
|
|
17449
17815
|
const current = input.state.getSnapshot().draft;
|
|
17450
17816
|
if (current.trim() === "") input.setDraft(draft);
|
|
17451
17817
|
else if (mode === "append") input.setDraft(`${current}\n\n${draft}`);
|
|
@@ -17691,7 +18057,7 @@ window.__ModuleLoader__.load({
|
|
|
17691
18057
|
...sessions === void 0 || conversation === void 0 ? {} : { submitWith: (fallbackDraft) => {
|
|
17692
18058
|
const scope = sessions.scope(sessionId);
|
|
17693
18059
|
if (scope === void 0) return;
|
|
17694
|
-
const input = conversation
|
|
18060
|
+
const input = sessionInput(conversation, scope);
|
|
17695
18061
|
if (input.state.getSnapshot().draft.trim() === "") input.setDraft(fallbackDraft);
|
|
17696
18062
|
input.submit();
|
|
17697
18063
|
} }
|
|
@@ -17729,7 +18095,7 @@ window.__ModuleLoader__.load({
|
|
|
17729
18095
|
...sessions === void 0 || conversation === void 0 ? {} : { insertIntoChat: (sessionId, text) => {
|
|
17730
18096
|
const scope = sessions.scope(sessionId);
|
|
17731
18097
|
if (scope === void 0) return;
|
|
17732
|
-
const input = conversation
|
|
18098
|
+
const input = sessionInput(conversation, scope);
|
|
17733
18099
|
const current = input.state.getSnapshot().draft;
|
|
17734
18100
|
input.setDraft(current.trim() === "" ? text : `${current}\n\n${text}`);
|
|
17735
18101
|
} }
|
|
@@ -17791,7 +18157,7 @@ window.__ModuleLoader__.load({
|
|
|
17791
18157
|
...conversation === void 0 ? {} : { setDraft: (sessionId, text) => {
|
|
17792
18158
|
const scope = sessions.scope(sessionId);
|
|
17793
18159
|
if (scope === void 0) return;
|
|
17794
|
-
conversation
|
|
18160
|
+
sessionInput(conversation, scope).setDraft(text);
|
|
17795
18161
|
} }
|
|
17796
18162
|
};
|
|
17797
18163
|
ctx.slots.inject("shell.overlay", () => ctx.slots.register({
|
|
@@ -17813,12 +18179,12 @@ window.__ModuleLoader__.load({
|
|
|
17813
18179
|
t,
|
|
17814
18180
|
updateQueue: (itemId, action) => target.updateQueue(itemId, action),
|
|
17815
18181
|
notify: (level, text) => {
|
|
17816
|
-
if (scope !== void 0) conversation
|
|
18182
|
+
if (scope !== void 0) sessionInput(conversation, scope).notify(level, text);
|
|
17817
18183
|
}
|
|
17818
18184
|
};
|
|
17819
18185
|
}
|
|
17820
18186
|
}, ClaudeQueueDock));
|
|
17821
|
-
if (sessions !== void 0 && workspaces !== void 0 && conversation !== void 0 && connection !== void 0 && remote !== void 0) {
|
|
18187
|
+
if (sessions !== void 0 && workspaces !== void 0 && connectWorkspace !== void 0 && conversation !== void 0 && connection !== void 0 && remote !== void 0) {
|
|
17822
18188
|
/** Attach a prepared worktree to its session without blocking the flow. */
|
|
17823
18189
|
const bindLease = (leaseId, targetSessionId) => {
|
|
17824
18190
|
if (leaseId === void 0) return;
|
|
@@ -17836,11 +18202,11 @@ window.__ModuleLoader__.load({
|
|
|
17836
18202
|
prepare: async (cwd, branch, useWorktree, onProgress, ticket) => {
|
|
17837
18203
|
const sourceScope = sessions.scope(sourceSessionId);
|
|
17838
18204
|
if (sourceScope === void 0) throw new Error(t("repositorySessionUnavailable"));
|
|
17839
|
-
const sourceInput = conversation
|
|
18205
|
+
const sourceInput = sessionInput(conversation, sourceScope);
|
|
17840
18206
|
const rawDraft = sourceInput.state.getSnapshot().draft;
|
|
17841
18207
|
const draft = ticket === void 0 ? rawDraft : rawDraft.trim() === "" ? ticketPrompt(ticket) : `${rawDraft.trimEnd()}\n\n${ticketContext(ticket)}`;
|
|
17842
18208
|
const imageIds = sourceInput.state.getSnapshot().imageIds;
|
|
17843
|
-
const prepared = await prepareRepository(cwd, branch, useWorktree, ticket?.key, onProgress);
|
|
18209
|
+
const prepared = await prepareRepository(cwd, branch, useWorktree, ticket?.key, onProgress, ticket === void 0 ? draft : void 0);
|
|
17844
18210
|
if (ticket !== void 0) assignJiraTicket(ticket.key).catch((reason) => {
|
|
17845
18211
|
console.warn(`dsh-claude: could not assign ${ticket.key}: ${reason instanceof Error ? reason.message : String(reason)}`);
|
|
17846
18212
|
});
|
|
@@ -17852,13 +18218,13 @@ window.__ModuleLoader__.load({
|
|
|
17852
18218
|
onProgress("creating-workspace");
|
|
17853
18219
|
const workspace = await workspaces.create({ path: prepared.path });
|
|
17854
18220
|
onProgress("starting-session");
|
|
17855
|
-
const targetSessionId = await
|
|
18221
|
+
const targetSessionId = await connectWorkspace(workspace.workspaceId);
|
|
17856
18222
|
const targetScope = sessions.scope(targetSessionId);
|
|
17857
18223
|
if (targetScope === void 0) throw new Error(t("repositorySessionUnavailable"));
|
|
17858
18224
|
const presetResponse = await remote.agentPresets.select(targetSessionId, "claude");
|
|
17859
18225
|
if (!presetResponse.ok) throw new Error(presetResponse.error.message);
|
|
17860
|
-
sessions.noteAgentPreset(targetSessionId, presetResponse.value);
|
|
17861
|
-
const targetInput = conversation
|
|
18226
|
+
sessions.noteAgentPreset?.(targetSessionId, presetResponse.value);
|
|
18227
|
+
const targetInput = sessionInput(conversation, targetScope);
|
|
17862
18228
|
onProgress("transferring-draft");
|
|
17863
18229
|
if (imageIds.length > 0 && !targetInput.addImages(imageIds)) throw new Error(t("repositoryDraftTransferFailed"));
|
|
17864
18230
|
if (draft !== "") targetInput.setDraft(draft);
|
|
@@ -17872,7 +18238,7 @@ window.__ModuleLoader__.load({
|
|
|
17872
18238
|
prepareMany: async (cwd, branch, tickets, onProgress) => {
|
|
17873
18239
|
const sourceScope = sessions.scope(sourceSessionId);
|
|
17874
18240
|
if (sourceScope === void 0) throw new Error(t("repositorySessionUnavailable"));
|
|
17875
|
-
const sourceInput = conversation
|
|
18241
|
+
const sourceInput = sessionInput(conversation, sourceScope);
|
|
17876
18242
|
const rawDraft = sourceInput.state.getSnapshot().draft;
|
|
17877
18243
|
const failures = [];
|
|
17878
18244
|
for (const [index, ticket] of tickets.entries()) {
|
|
@@ -17893,13 +18259,13 @@ window.__ModuleLoader__.load({
|
|
|
17893
18259
|
report("creating-workspace");
|
|
17894
18260
|
const workspace = await workspaces.create({ path: prepared.path });
|
|
17895
18261
|
report("starting-session");
|
|
17896
|
-
const targetSessionId = await
|
|
18262
|
+
const targetSessionId = await connectWorkspace(workspace.workspaceId);
|
|
17897
18263
|
const targetScope = sessions.scope(targetSessionId);
|
|
17898
18264
|
if (targetScope === void 0) throw new Error(t("repositorySessionUnavailable"));
|
|
17899
18265
|
const presetResponse = await remote.agentPresets.select(targetSessionId, "claude");
|
|
17900
18266
|
if (!presetResponse.ok) throw new Error(presetResponse.error.message);
|
|
17901
|
-
sessions.noteAgentPreset(targetSessionId, presetResponse.value);
|
|
17902
|
-
const targetInput = conversation
|
|
18267
|
+
sessions.noteAgentPreset?.(targetSessionId, presetResponse.value);
|
|
18268
|
+
const targetInput = sessionInput(conversation, targetScope);
|
|
17903
18269
|
report("transferring-draft");
|
|
17904
18270
|
targetInput.setDraft(rawDraft.trim() === "" ? ticketPrompt(ticket) : `${rawDraft.trimEnd()}\n\n${ticketContext(ticket)}`);
|
|
17905
18271
|
bindLease(prepared.leaseId, targetSessionId);
|