@couralabs/claudin 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/claudin.js +744 -132
- package/package.json +1 -1
package/claudin.js
CHANGED
|
@@ -5928,6 +5928,12 @@ var backgroundColorSchema = object({
|
|
|
5928
5928
|
a: channelSchema
|
|
5929
5929
|
});
|
|
5930
5930
|
var TRANSPARENT_BACKGROUND = { r: 0, g: 0, b: 0, a: 0 };
|
|
5931
|
+
// packages/events/src/models/customTools.ts
|
|
5932
|
+
var CUSTOM_SERVER_NAME = "claudin";
|
|
5933
|
+
var BATCH_EDIT_BASE_NAME = "BatchEdit";
|
|
5934
|
+
var BATCH_EDIT_TOOL_NAME = `mcp__${CUSTOM_SERVER_NAME}__${BATCH_EDIT_BASE_NAME}`;
|
|
5935
|
+
var CUSTOM_PREFIX = `mcp__${CUSTOM_SERVER_NAME}__`;
|
|
5936
|
+
var stripCustomPrefix = (toolName) => toolName.startsWith(CUSTOM_PREFIX) ? toolName.slice(CUSTOM_PREFIX.length) : toolName;
|
|
5931
5937
|
// packages/events/src/models/fileDiff.ts
|
|
5932
5938
|
var fileDiffSchema = object({
|
|
5933
5939
|
path: string2(),
|
|
@@ -6064,6 +6070,7 @@ function appendEntry(state, entry) {
|
|
|
6064
6070
|
};
|
|
6065
6071
|
}
|
|
6066
6072
|
var appendNotice = (state, text) => appendEntry(state, { kind: "notice", text });
|
|
6073
|
+
var appendMarkdownNotice = (state, text) => appendEntry(state, { kind: "notice", text, markdown: true });
|
|
6067
6074
|
|
|
6068
6075
|
// packages/events/src/reducers/reduceHistory.ts
|
|
6069
6076
|
var NO_MATCH_NOTICE = "No earlier prompt matches";
|
|
@@ -6111,6 +6118,7 @@ var agentSessionId = string2();
|
|
|
6111
6118
|
var content = sdkValue();
|
|
6112
6119
|
var agentOptions = sdkValue().optional();
|
|
6113
6120
|
var effortLevelSchema = _enum(["low", "medium", "high", "xhigh", "max"]);
|
|
6121
|
+
var DEFAULT_EFFORT = "high";
|
|
6114
6122
|
var permissionModeSchema = _enum(["auto", "acceptEdits", "bypassPermissions", "dontAsk"]);
|
|
6115
6123
|
var DEFAULT_PERMISSION_MODE = "bypassPermissions";
|
|
6116
6124
|
var PERMISSION_MODE_LABELS = {
|
|
@@ -6145,9 +6153,8 @@ var agentRequestSchemas = [
|
|
|
6145
6153
|
options: agentOptions
|
|
6146
6154
|
}),
|
|
6147
6155
|
object({ type: literal("agent.prompt.requested"), agentSessionId, content }),
|
|
6148
|
-
object({ type: literal("agent.prompt.queue.requested"), agentSessionId, content }),
|
|
6149
|
-
object({ type: literal("agent.prompt.steer.requested"), agentSessionId, content }),
|
|
6150
6156
|
object({ type: literal("agent.prompt.cancel.requested"), agentSessionId }),
|
|
6157
|
+
object({ type: literal("agent.task.stop.requested"), agentSessionId, taskId: string2() }),
|
|
6151
6158
|
object({
|
|
6152
6159
|
type: literal("agent.tool.approval.answered"),
|
|
6153
6160
|
agentSessionId,
|
|
@@ -6217,6 +6224,8 @@ var createSessionState = (sessionId) => ({
|
|
|
6217
6224
|
models: [],
|
|
6218
6225
|
sessionList: [],
|
|
6219
6226
|
queuedTurns: 0,
|
|
6227
|
+
queuedPrompts: [],
|
|
6228
|
+
tasks: [],
|
|
6220
6229
|
transcript: [],
|
|
6221
6230
|
entryCounter: 0,
|
|
6222
6231
|
now: Date.now(),
|
|
@@ -6315,10 +6324,11 @@ function describeSystemMessage(message) {
|
|
|
6315
6324
|
var OPEN_STATUSES = new Set(["running", "awaiting_approval", "awaiting_answer"]);
|
|
6316
6325
|
var isToolsEntry = (entry) => entry.kind === "tools";
|
|
6317
6326
|
var listToolCalls = (state) => state.transcript.filter(isToolsEntry).flatMap((entry) => entry.calls);
|
|
6318
|
-
var EDIT_TOOLS = new Set(["Write", "Edit", "MultiEdit", "
|
|
6319
|
-
var
|
|
6327
|
+
var EDIT_TOOLS = new Set(["Write", "Edit", "MultiEdit", "mcp__claudin__BatchEdit"]);
|
|
6328
|
+
var listBatchEditPaths = (input) => Array.isArray(input.edits) ? input.edits.map((edit) => edit?.file_path) : [];
|
|
6329
|
+
var readEditedPaths = (call) => call.name === BATCH_EDIT_TOOL_NAME ? listBatchEditPaths(call.input) : EDIT_TOOLS.has(call.name) ? [call.input.file_path ?? call.input.notebook_path] : [];
|
|
6320
6330
|
var listEditedFiles = (state) => [
|
|
6321
|
-
...new Set(listToolCalls(state).filter((call) =>
|
|
6331
|
+
...new Set(listToolCalls(state).filter((call) => call.status === "completed").flatMap(readEditedPaths).filter((path) => typeof path === "string"))
|
|
6322
6332
|
];
|
|
6323
6333
|
function countTurnTools(state) {
|
|
6324
6334
|
const lastUser = state.transcript.findLastIndex((entry) => entry.kind === "user");
|
|
@@ -6517,6 +6527,43 @@ function reduceStreamEvent(state, event) {
|
|
|
6517
6527
|
}
|
|
6518
6528
|
}
|
|
6519
6529
|
|
|
6530
|
+
// packages/events/src/reducers/reduceTaskModel.ts
|
|
6531
|
+
var readMessageModel = (message) => {
|
|
6532
|
+
if (message.type === "assistant")
|
|
6533
|
+
return message.message.model;
|
|
6534
|
+
if (message.type !== "stream_event")
|
|
6535
|
+
return;
|
|
6536
|
+
const event = message.event;
|
|
6537
|
+
return event.type === "message_start" ? event.message?.model : undefined;
|
|
6538
|
+
};
|
|
6539
|
+
var readRequestedModel = (state, toolUseId) => {
|
|
6540
|
+
const model = listToolCalls(state).find((call) => call.id === toolUseId)?.input.model;
|
|
6541
|
+
return typeof model === "string" ? model : undefined;
|
|
6542
|
+
};
|
|
6543
|
+
function reduceTaskModel(state, message) {
|
|
6544
|
+
if (message.type !== "assistant" && message.type !== "stream_event")
|
|
6545
|
+
return state;
|
|
6546
|
+
const model = readMessageModel(message);
|
|
6547
|
+
const parentId = message.parent_tool_use_id;
|
|
6548
|
+
const stale = (task) => task.toolUseId === parentId && task.model !== model;
|
|
6549
|
+
if (!model || !parentId || !state.tasks.some(stale))
|
|
6550
|
+
return state;
|
|
6551
|
+
const tasks = state.tasks.map((task) => stale(task) ? { ...task, model } : task);
|
|
6552
|
+
return { ...state, tasks };
|
|
6553
|
+
}
|
|
6554
|
+
|
|
6555
|
+
// packages/events/src/reducers/reduceTaskToolUse.ts
|
|
6556
|
+
function reduceTaskToolUse(state, message) {
|
|
6557
|
+
if (message.type !== "assistant" || !message.parent_tool_use_id)
|
|
6558
|
+
return state;
|
|
6559
|
+
const call = message.message.content.findLast((block) => block.type === "tool_use");
|
|
6560
|
+
if (call?.type !== "tool_use")
|
|
6561
|
+
return state;
|
|
6562
|
+
const lastToolCall = { name: call.name, input: call.input ?? {} };
|
|
6563
|
+
const tasks = state.tasks.map((task) => task.toolUseId === message.parent_tool_use_id ? { ...task, lastToolCall } : task);
|
|
6564
|
+
return { ...state, tasks };
|
|
6565
|
+
}
|
|
6566
|
+
|
|
6520
6567
|
// packages/events/src/reducers/reduceTaskProgress.ts
|
|
6521
6568
|
function reduceTaskProgress(state, message) {
|
|
6522
6569
|
const { tool_use_id: toolUseId, summary } = message;
|
|
@@ -6525,6 +6572,58 @@ function reduceTaskProgress(state, message) {
|
|
|
6525
6572
|
return updateToolCall(state, toolUseId, (call) => ({ ...call, progress: summary }));
|
|
6526
6573
|
}
|
|
6527
6574
|
|
|
6575
|
+
// packages/events/src/reducers/reduceTasks.ts
|
|
6576
|
+
var FINISHED_STATUSES = ["completed", "failed", "killed"];
|
|
6577
|
+
var isTaskMessage = (message) => message.type === "system" && ["task_started", "task_progress", "task_updated", "task_notification"].includes(message.subtype);
|
|
6578
|
+
var patchTask = (tasks, id, patch) => tasks.map((task) => task.id === id ? patch(task) : task);
|
|
6579
|
+
var startTask = (state, message) => {
|
|
6580
|
+
if (message.ambient || message.skip_transcript)
|
|
6581
|
+
return state.tasks;
|
|
6582
|
+
const task = {
|
|
6583
|
+
id: message.task_id,
|
|
6584
|
+
kind: message.subagent_type ?? message.task_type ?? "task",
|
|
6585
|
+
description: message.description,
|
|
6586
|
+
startedAt: state.now,
|
|
6587
|
+
toolUseId: message.tool_use_id,
|
|
6588
|
+
model: readRequestedModel(state, message.tool_use_id),
|
|
6589
|
+
tokens: 0,
|
|
6590
|
+
paused: false
|
|
6591
|
+
};
|
|
6592
|
+
return [...state.tasks.filter(({ id }) => id !== task.id), task];
|
|
6593
|
+
};
|
|
6594
|
+
var updateTask = (tasks, message) => {
|
|
6595
|
+
const { status, description } = message.patch;
|
|
6596
|
+
if (status && FINISHED_STATUSES.includes(status)) {
|
|
6597
|
+
return tasks.filter(({ id }) => id !== message.task_id);
|
|
6598
|
+
}
|
|
6599
|
+
return patchTask(tasks, message.task_id, (task) => ({
|
|
6600
|
+
...task,
|
|
6601
|
+
description: description ?? task.description,
|
|
6602
|
+
paused: status ? status === "paused" : task.paused
|
|
6603
|
+
}));
|
|
6604
|
+
};
|
|
6605
|
+
var readTasks = (state, message) => {
|
|
6606
|
+
switch (message.subtype) {
|
|
6607
|
+
case "task_started":
|
|
6608
|
+
return startTask(state, message);
|
|
6609
|
+
case "task_progress":
|
|
6610
|
+
return patchTask(state.tasks, message.task_id, (task) => ({
|
|
6611
|
+
...task,
|
|
6612
|
+
lastToolName: message.last_tool_name ?? task.lastToolName,
|
|
6613
|
+
summary: message.summary ?? task.summary,
|
|
6614
|
+
tokens: message.usage.total_tokens
|
|
6615
|
+
}));
|
|
6616
|
+
case "task_updated":
|
|
6617
|
+
return updateTask(state.tasks, message);
|
|
6618
|
+
case "task_notification":
|
|
6619
|
+
return state.tasks.filter(({ id }) => id !== message.task_id);
|
|
6620
|
+
}
|
|
6621
|
+
};
|
|
6622
|
+
var reduceTasks = (state, message) => ({
|
|
6623
|
+
...state,
|
|
6624
|
+
tasks: readTasks(state, message)
|
|
6625
|
+
});
|
|
6626
|
+
|
|
6528
6627
|
// packages/events/src/reducers/reduceToolResults.ts
|
|
6529
6628
|
function applyResult(state, block) {
|
|
6530
6629
|
if (block.type !== "tool_result" || !block.tool_use_id)
|
|
@@ -6542,10 +6641,10 @@ function reduceToolResults(state, message) {
|
|
|
6542
6641
|
|
|
6543
6642
|
// packages/events/src/reducers/reduceAgentMessage.ts
|
|
6544
6643
|
function reduceAgentMessage(state, message) {
|
|
6644
|
+
if (isTaskMessage(message))
|
|
6645
|
+
return reduceTaskMessage(reduceTasks(state, message), message);
|
|
6545
6646
|
switch (message.type) {
|
|
6546
6647
|
case "system":
|
|
6547
|
-
if (message.subtype === "task_progress")
|
|
6548
|
-
return reduceTaskProgress(state, message);
|
|
6549
6648
|
if (message.subtype !== "init")
|
|
6550
6649
|
return reduceNoticeMessage(state, message);
|
|
6551
6650
|
return {
|
|
@@ -6557,9 +6656,12 @@ function reduceAgentMessage(state, message) {
|
|
|
6557
6656
|
};
|
|
6558
6657
|
case "stream_event":
|
|
6559
6658
|
if (message.parent_tool_use_id)
|
|
6560
|
-
return state;
|
|
6659
|
+
return reduceTaskModel(state, message);
|
|
6561
6660
|
return reduceStreamEvent(state, message.event);
|
|
6562
6661
|
case "assistant":
|
|
6662
|
+
if (message.parent_tool_use_id) {
|
|
6663
|
+
return reduceTaskToolUse(reduceTaskModel(state, message), message);
|
|
6664
|
+
}
|
|
6563
6665
|
return reduceAssistant(state, message);
|
|
6564
6666
|
case "user":
|
|
6565
6667
|
return isPromptEcho(message) ? reduceCheckpoint(state, message) : reduceToolResults(state, message);
|
|
@@ -6571,6 +6673,16 @@ function reduceAgentMessage(state, message) {
|
|
|
6571
6673
|
return reduceNoticeMessage(state, message);
|
|
6572
6674
|
}
|
|
6573
6675
|
}
|
|
6676
|
+
function reduceTaskMessage(state, message) {
|
|
6677
|
+
if (message.type === "system" && message.subtype === "task_progress") {
|
|
6678
|
+
return reduceTaskProgress(state, message);
|
|
6679
|
+
}
|
|
6680
|
+
if (message.type === "system" && message.subtype === "task_notification") {
|
|
6681
|
+
const text = describeSystemMessage(message);
|
|
6682
|
+
return text ? appendMarkdownNotice(state, text) : state;
|
|
6683
|
+
}
|
|
6684
|
+
return state;
|
|
6685
|
+
}
|
|
6574
6686
|
function reduceNoticeMessage(state, message) {
|
|
6575
6687
|
const text = describeSystemMessage(message);
|
|
6576
6688
|
return text ? appendNotice(state, text) : state;
|
|
@@ -6751,6 +6863,23 @@ function changeQuestionCustom(state, text) {
|
|
|
6751
6863
|
return question ? withDraft(state, { ...question, custom: text }) : state;
|
|
6752
6864
|
}
|
|
6753
6865
|
|
|
6866
|
+
// packages/events/src/reducers/reduceTheme.ts
|
|
6867
|
+
var applyLoadedTheme = (state, theme = state.theme) => ({
|
|
6868
|
+
...state,
|
|
6869
|
+
theme
|
|
6870
|
+
});
|
|
6871
|
+
var applySavedTheme = (state, theme) => appendNotice({ ...state, theme }, `Theme set to ${theme}`);
|
|
6872
|
+
|
|
6873
|
+
// packages/events/src/reducers/reducePromptQueue.ts
|
|
6874
|
+
var queuePrompt = (state, content) => ({
|
|
6875
|
+
...state,
|
|
6876
|
+
queuedPrompts: [...state.queuedPrompts, content]
|
|
6877
|
+
});
|
|
6878
|
+
var dequeuePrompt = (state) => ({
|
|
6879
|
+
...state,
|
|
6880
|
+
queuedPrompts: state.queuedPrompts.slice(1)
|
|
6881
|
+
});
|
|
6882
|
+
|
|
6754
6883
|
// packages/events/src/reducers/reduceToast.ts
|
|
6755
6884
|
var withToast = (state, toast) => ({
|
|
6756
6885
|
...state,
|
|
@@ -6778,6 +6907,8 @@ var pickerSize = (state, kind) => {
|
|
|
6778
6907
|
return state.models.length;
|
|
6779
6908
|
if (kind === "theme")
|
|
6780
6909
|
return THEME_NAMES.length;
|
|
6910
|
+
if (kind === "effort")
|
|
6911
|
+
return effortLevelSchema.options.length;
|
|
6781
6912
|
if (kind === "rewind")
|
|
6782
6913
|
return listCheckpoints(state).length;
|
|
6783
6914
|
return state.sessionList.length;
|
|
@@ -6796,6 +6927,11 @@ var openThemePicker = (state) => {
|
|
|
6796
6927
|
const selected = Math.max(THEME_NAMES.indexOf(state.theme), 0);
|
|
6797
6928
|
return { ...state, ui: { ...state.ui, picker: { kind: "theme", selected } } };
|
|
6798
6929
|
};
|
|
6930
|
+
var openEffortPicker = (state) => {
|
|
6931
|
+
const current = state.effort || DEFAULT_EFFORT;
|
|
6932
|
+
const selected = Math.max(effortLevelSchema.options.findIndex((level) => level === current), 0);
|
|
6933
|
+
return { ...state, ui: { ...state.ui, picker: { kind: "effort", selected } } };
|
|
6934
|
+
};
|
|
6799
6935
|
function openRewindPicker(state) {
|
|
6800
6936
|
const size = listCheckpoints(state).length;
|
|
6801
6937
|
if (size === 0)
|
|
@@ -6820,8 +6956,12 @@ function reduceUi(state, event) {
|
|
|
6820
6956
|
return { ...state, ui: { ...state.ui, picker: null } };
|
|
6821
6957
|
case "ui.theme.picker.opened":
|
|
6822
6958
|
return openThemePicker(state);
|
|
6823
|
-
case "ui.
|
|
6824
|
-
return
|
|
6959
|
+
case "ui.effort.picker.opened":
|
|
6960
|
+
return openEffortPicker(state);
|
|
6961
|
+
case "ui.prompt.queued":
|
|
6962
|
+
return queuePrompt(state, event.content);
|
|
6963
|
+
case "ui.prompt.dequeued":
|
|
6964
|
+
return dequeuePrompt(state);
|
|
6825
6965
|
case "ui.rewind.picker.opened":
|
|
6826
6966
|
return openRewindPicker(state);
|
|
6827
6967
|
case "ui.history.moved":
|
|
@@ -6855,6 +6995,7 @@ function reduceUi(state, event) {
|
|
|
6855
6995
|
case "ui.question.recorded":
|
|
6856
6996
|
return recordQuestionAnswer(state, event);
|
|
6857
6997
|
case "ui.exit.requested":
|
|
6998
|
+
case "ui.title.set":
|
|
6858
6999
|
return state;
|
|
6859
7000
|
case "ui.notice.posted":
|
|
6860
7001
|
return appendNotice(state, event.text);
|
|
@@ -6899,9 +7040,6 @@ var reduceTimedEvent = (state, event, at) => reduceSessionState({ ...state, now:
|
|
|
6899
7040
|
function reduceSessionState(state, event) {
|
|
6900
7041
|
switch (event.type) {
|
|
6901
7042
|
case "agent.prompt.requested":
|
|
6902
|
-
return reducePrompt(state, event.content, false);
|
|
6903
|
-
case "agent.prompt.queue.requested":
|
|
6904
|
-
case "agent.prompt.steer.requested":
|
|
6905
7043
|
return reducePrompt(state, event.content, state.status !== "idle");
|
|
6906
7044
|
case "agent.message.received":
|
|
6907
7045
|
return reduceAgentMessage(state, event.message);
|
|
@@ -6978,9 +7116,11 @@ function reduceSessionState(state, event) {
|
|
|
6978
7116
|
case "workspace.info.received":
|
|
6979
7117
|
return { ...state, cwd: event.cwd, gitBranch: event.gitBranch, gitStats: event.gitStats };
|
|
6980
7118
|
case "options.loaded":
|
|
6981
|
-
return applyLoadedBackground(state, event.background);
|
|
7119
|
+
return applyLoadedTheme(applyLoadedBackground(state, event.background), event.theme);
|
|
6982
7120
|
case "options.background.saved":
|
|
6983
7121
|
return applySavedBackground(state, event.color);
|
|
7122
|
+
case "options.theme.saved":
|
|
7123
|
+
return applySavedTheme(state, event.theme);
|
|
6984
7124
|
case "workspace.files.received":
|
|
6985
7125
|
return updateFileMatches(state, event.query, event.matches);
|
|
6986
7126
|
default:
|
|
@@ -6993,13 +7133,22 @@ var optionsRequestSchemas = [
|
|
|
6993
7133
|
object({
|
|
6994
7134
|
type: literal("options.background.save.requested"),
|
|
6995
7135
|
color: backgroundColorSchema
|
|
6996
|
-
})
|
|
7136
|
+
}),
|
|
7137
|
+
object({ type: literal("options.theme.save.requested"), theme: themeNameSchema })
|
|
6997
7138
|
];
|
|
6998
7139
|
var optionsResponseSchemas = [
|
|
6999
|
-
object({
|
|
7000
|
-
|
|
7140
|
+
object({
|
|
7141
|
+
type: literal("options.loaded"),
|
|
7142
|
+
background: backgroundColorSchema.optional(),
|
|
7143
|
+
theme: themeNameSchema.optional()
|
|
7144
|
+
}),
|
|
7145
|
+
object({ type: literal("options.background.saved"), color: backgroundColorSchema }),
|
|
7146
|
+
object({ type: literal("options.theme.saved"), theme: themeNameSchema })
|
|
7001
7147
|
];
|
|
7002
|
-
var optionsFileSchema = looseObject({
|
|
7148
|
+
var optionsFileSchema = looseObject({
|
|
7149
|
+
background: backgroundColorSchema.optional(),
|
|
7150
|
+
theme: themeNameSchema.optional()
|
|
7151
|
+
});
|
|
7003
7152
|
// packages/events/src/requests/sessionRequestEvents.ts
|
|
7004
7153
|
var sessionRequestSchemas = [
|
|
7005
7154
|
object({ type: literal("session.create.requested") }),
|
|
@@ -7060,7 +7209,6 @@ var agentResponseSchemas = [
|
|
|
7060
7209
|
}),
|
|
7061
7210
|
object({ type: literal("agent.session.created"), agentSessionId: agentSessionId2 }),
|
|
7062
7211
|
object({ type: literal("agent.message.received"), message: unknown() }),
|
|
7063
|
-
object({ type: literal("agent.prompt.accepted"), agentSessionId: agentSessionId2 }),
|
|
7064
7212
|
object({ type: literal("agent.prompt.cancelled"), agentSessionId: agentSessionId2 }),
|
|
7065
7213
|
object({
|
|
7066
7214
|
type: literal("agent.tool.approval.required"),
|
|
@@ -7470,11 +7618,10 @@ var sdkRuntime = {
|
|
|
7470
7618
|
};
|
|
7471
7619
|
// packages/agent/src/runtime/buildUserMessage.ts
|
|
7472
7620
|
var isSlashCommand = (content) => readPromptText(content).trimStart().startsWith("/");
|
|
7473
|
-
var buildUserMessage = (content
|
|
7621
|
+
var buildUserMessage = (content) => ({
|
|
7474
7622
|
type: "user",
|
|
7475
7623
|
message: { role: "user", content },
|
|
7476
7624
|
parent_tool_use_id: null,
|
|
7477
|
-
priority,
|
|
7478
7625
|
client_composed: isSlashCommand(content) ? undefined : true
|
|
7479
7626
|
});
|
|
7480
7627
|
// node_modules/.bun/p-defer@4.0.1/node_modules/p-defer/index.js
|
|
@@ -8699,6 +8846,110 @@ class PermissionGate {
|
|
|
8699
8846
|
}
|
|
8700
8847
|
}
|
|
8701
8848
|
|
|
8849
|
+
// packages/agent/src/tools/customToolsServer.ts
|
|
8850
|
+
import { createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
|
|
8851
|
+
|
|
8852
|
+
// packages/agent/src/tools/batchEdit/batchEditTool.ts
|
|
8853
|
+
import { tool } from "@anthropic-ai/claude-agent-sdk";
|
|
8854
|
+
|
|
8855
|
+
// packages/agent/src/tools/batchEdit/batchEditSchema.ts
|
|
8856
|
+
var textEditSchema = object({
|
|
8857
|
+
file_path: string2().describe("Absolute path of the file to modify"),
|
|
8858
|
+
old_string: string2().describe("Exact text to replace; empty only to create a new file with new_string"),
|
|
8859
|
+
new_string: string2().describe("Replacement text; must differ from old_string"),
|
|
8860
|
+
replace_all: boolean2().optional().describe("Replace every occurrence of old_string")
|
|
8861
|
+
});
|
|
8862
|
+
var batchEditShape = {
|
|
8863
|
+
edits: array(textEditSchema).min(1).describe("Edits applied in order; edits to one file see the result of earlier ones")
|
|
8864
|
+
};
|
|
8865
|
+
|
|
8866
|
+
// packages/agent/src/tools/batchEdit/stageEdits.ts
|
|
8867
|
+
import { isAbsolute, resolve } from "path";
|
|
8868
|
+
|
|
8869
|
+
// packages/agent/src/tools/batchEdit/applyTextEdit.ts
|
|
8870
|
+
var failEdit = (reason) => ({ ok: false, reason });
|
|
8871
|
+
function applyTextEdit(content, edit) {
|
|
8872
|
+
const { old_string: oldText, new_string: newText, replace_all: replaceAll } = edit;
|
|
8873
|
+
if (oldText === newText)
|
|
8874
|
+
return failEdit("old_string and new_string are identical");
|
|
8875
|
+
if (oldText === "") {
|
|
8876
|
+
return content === "" ? { ok: true, content: newText, replacements: 1 } : failEdit("old_string is empty but the file already has content");
|
|
8877
|
+
}
|
|
8878
|
+
const parts = content.split(oldText);
|
|
8879
|
+
const matches = parts.length - 1;
|
|
8880
|
+
if (matches === 0)
|
|
8881
|
+
return failEdit("old_string was not found in the file");
|
|
8882
|
+
if (matches > 1 && !replaceAll) {
|
|
8883
|
+
return failEdit(`old_string matches ${matches} times; add context or set replace_all`);
|
|
8884
|
+
}
|
|
8885
|
+
return { ok: true, content: parts.join(newText), replacements: matches };
|
|
8886
|
+
}
|
|
8887
|
+
|
|
8888
|
+
// packages/agent/src/tools/batchEdit/stageEdits.ts
|
|
8889
|
+
var failStage = (index, edit, reason) => ({
|
|
8890
|
+
ok: false,
|
|
8891
|
+
message: `Edit ${index + 1} (${edit.file_path}): ${reason}`
|
|
8892
|
+
});
|
|
8893
|
+
async function stageEdits(edits, readFile) {
|
|
8894
|
+
const files = new Map;
|
|
8895
|
+
for (const [index, edit] of edits.entries()) {
|
|
8896
|
+
if (!isAbsolute(edit.file_path))
|
|
8897
|
+
return failStage(index, edit, "file_path must be absolute");
|
|
8898
|
+
const path = resolve(edit.file_path);
|
|
8899
|
+
const current = files.get(path)?.content ?? await readFile(path);
|
|
8900
|
+
if (current === undefined && edit.old_string !== "") {
|
|
8901
|
+
return failStage(index, edit, "the file does not exist");
|
|
8902
|
+
}
|
|
8903
|
+
const outcome = applyTextEdit(current ?? "", edit);
|
|
8904
|
+
if (!outcome.ok)
|
|
8905
|
+
return failStage(index, edit, outcome.reason);
|
|
8906
|
+
const replacements = (files.get(path)?.replacements ?? 0) + outcome.replacements;
|
|
8907
|
+
files.set(path, { content: outcome.content, replacements });
|
|
8908
|
+
}
|
|
8909
|
+
return { ok: true, files };
|
|
8910
|
+
}
|
|
8911
|
+
|
|
8912
|
+
// packages/agent/src/tools/batchEdit/runBatchEdit.ts
|
|
8913
|
+
var readFileText = async (path) => {
|
|
8914
|
+
const file = Bun.file(path);
|
|
8915
|
+
return await file.exists() ? file.text() : undefined;
|
|
8916
|
+
};
|
|
8917
|
+
var describeFiles = (files) => [...files].map(([path, { replacements }]) => `- ${path}: ${replacements} replacement(s)`).join(`
|
|
8918
|
+
`);
|
|
8919
|
+
async function runBatchEdit(edits, readFile = readFileText) {
|
|
8920
|
+
const staged = await stageEdits(edits, readFile);
|
|
8921
|
+
if (!staged.ok) {
|
|
8922
|
+
return { isError: true, text: `${staged.message}
|
|
8923
|
+
No files were changed.` };
|
|
8924
|
+
}
|
|
8925
|
+
try {
|
|
8926
|
+
await Promise.all([...staged.files].map(([path, { content }]) => Bun.write(path, content)));
|
|
8927
|
+
} catch (error) {
|
|
8928
|
+
return { isError: true, text: `Writing failed, files may be partly changed: ${error}` };
|
|
8929
|
+
}
|
|
8930
|
+
return {
|
|
8931
|
+
isError: false,
|
|
8932
|
+
text: `Applied ${edits.length} edit(s) to ${staged.files.size} file(s):
|
|
8933
|
+
${describeFiles(staged.files)}`
|
|
8934
|
+
};
|
|
8935
|
+
}
|
|
8936
|
+
|
|
8937
|
+
// packages/agent/src/tools/batchEdit/batchEditTool.ts
|
|
8938
|
+
var DESCRIPTION = `Apply many exact-string edits across one or more files in a single call. Each edit works like Edit (file_path, old_string, new_string, replace_all). Edits run in order, and edits to the same file build on each other. The batch is all-or-nothing: if any edit fails validation, no file is changed.`;
|
|
8939
|
+
var batchEditTool = tool(BATCH_EDIT_BASE_NAME, DESCRIPTION, batchEditShape, async ({ edits }) => {
|
|
8940
|
+
const { isError, text } = await runBatchEdit(edits);
|
|
8941
|
+
return { isError, content: [{ type: "text", text }] };
|
|
8942
|
+
});
|
|
8943
|
+
|
|
8944
|
+
// packages/agent/src/tools/customToolsServer.ts
|
|
8945
|
+
var CUSTOM_MCP_SERVERS = {
|
|
8946
|
+
[CUSTOM_SERVER_NAME]: createSdkMcpServer({
|
|
8947
|
+
name: CUSTOM_SERVER_NAME,
|
|
8948
|
+
tools: [batchEditTool],
|
|
8949
|
+
alwaysLoad: true
|
|
8950
|
+
})
|
|
8951
|
+
};
|
|
8952
|
+
|
|
8702
8953
|
// packages/agent/src/profile/adhdSystemPrompt.ts
|
|
8703
8954
|
var ADHD_SYSTEM_PROMPT = `For the rest of this session, shape every response for a reader with ADHD. The output is not just brief; it is shaped so an ADHD brain can act on it.
|
|
8704
8955
|
|
|
@@ -8813,8 +9064,7 @@ var AGENT_TOOLS = [
|
|
|
8813
9064
|
"TodoWrite",
|
|
8814
9065
|
"AskUserQuestion",
|
|
8815
9066
|
"Write",
|
|
8816
|
-
"Edit"
|
|
8817
|
-
"NotebookEdit"
|
|
9067
|
+
"Edit"
|
|
8818
9068
|
];
|
|
8819
9069
|
var AGENT_DISALLOWED_TOOLS = [
|
|
8820
9070
|
"Agent(Explore)",
|
|
@@ -8841,11 +9091,12 @@ var TOOL_USAGE = {
|
|
|
8841
9091
|
AskUserQuestion: "ask the user",
|
|
8842
9092
|
Write: "create new files with content",
|
|
8843
9093
|
Edit: "update files",
|
|
8844
|
-
|
|
9094
|
+
mcp__claudin__BatchEdit: "update files mutiples files or multiple replaces in same file"
|
|
8845
9095
|
};
|
|
8846
9096
|
var TOOL_GUIDANCE = `Always use the dedicated tool, never a workaround:
|
|
8847
9097
|
${AGENT_TOOLS.map((tool) => `- Use *${tool}* to ${TOOL_USAGE[tool]}`).join(`
|
|
8848
|
-
`)}
|
|
9098
|
+
`)}
|
|
9099
|
+
- Use *${BATCH_EDIT_TOOL_NAME}* instead of repeated *Edit* calls to make several edits, across one or many files, in one call`;
|
|
8849
9100
|
|
|
8850
9101
|
// packages/agent/src/profile/agentSystemPrompt.ts
|
|
8851
9102
|
var AGENT_SYSTEM_PROMPT = [ADHD_SYSTEM_PROMPT, TOOL_GUIDANCE, SUBAGENT_GUIDANCE].join(`
|
|
@@ -8855,6 +9106,8 @@ var AGENT_SYSTEM_PROMPT = [ADHD_SYSTEM_PROMPT, TOOL_GUIDANCE, SUBAGENT_GUIDANCE]
|
|
|
8855
9106
|
// packages/agent/src/profile/agentProfile.ts
|
|
8856
9107
|
var AGENT_PROFILE_OPTIONS = {
|
|
8857
9108
|
tools: AGENT_TOOLS,
|
|
9109
|
+
mcpServers: CUSTOM_MCP_SERVERS,
|
|
9110
|
+
toolAliases: { [BATCH_EDIT_BASE_NAME]: BATCH_EDIT_TOOL_NAME },
|
|
8858
9111
|
disallowedTools: AGENT_DISALLOWED_TOOLS,
|
|
8859
9112
|
systemPrompt: AGENT_SYSTEM_PROMPT,
|
|
8860
9113
|
agents: AGENT_SUBAGENTS,
|
|
@@ -8889,6 +9142,27 @@ var AGENT_PROFILE_OPTIONS = {
|
|
|
8889
9142
|
includeHookEvents: true
|
|
8890
9143
|
};
|
|
8891
9144
|
|
|
9145
|
+
// packages/agent/src/session/readLiveTaskIds.ts
|
|
9146
|
+
var FINISHED_STATUSES2 = ["completed", "failed", "killed"];
|
|
9147
|
+
var withTask = (current, id) => new Set([...current, id]);
|
|
9148
|
+
var withoutTask = (current, id) => new Set([...current].filter((taskId) => taskId !== id));
|
|
9149
|
+
function readLiveTaskIds(message, current) {
|
|
9150
|
+
if (message.type !== "system")
|
|
9151
|
+
return current;
|
|
9152
|
+
switch (message.subtype) {
|
|
9153
|
+
case "background_tasks_changed":
|
|
9154
|
+
return new Set(message.tasks.filter((task) => !task.ambient).map((task) => task.task_id));
|
|
9155
|
+
case "task_started":
|
|
9156
|
+
return message.ambient ? current : withTask(current, message.task_id);
|
|
9157
|
+
case "task_updated":
|
|
9158
|
+
return FINISHED_STATUSES2.includes(message.patch.status ?? "") ? withoutTask(current, message.task_id) : current;
|
|
9159
|
+
case "task_notification":
|
|
9160
|
+
return withoutTask(current, message.task_id);
|
|
9161
|
+
default:
|
|
9162
|
+
return current;
|
|
9163
|
+
}
|
|
9164
|
+
}
|
|
9165
|
+
|
|
8892
9166
|
// packages/agent/src/session/agentSession.ts
|
|
8893
9167
|
function requireRewind(result) {
|
|
8894
9168
|
if (!result.canRewind)
|
|
@@ -8903,6 +9177,7 @@ class AgentSession {
|
|
|
8903
9177
|
elicitations;
|
|
8904
9178
|
query;
|
|
8905
9179
|
pendingTurns = 0;
|
|
9180
|
+
liveTaskIds = new Set;
|
|
8906
9181
|
pumping = false;
|
|
8907
9182
|
constructor(agentSessionId, baseOptions, runtime) {
|
|
8908
9183
|
this.baseOptions = baseOptions;
|
|
@@ -8918,13 +9193,13 @@ class AgentSession {
|
|
|
8918
9193
|
}
|
|
8919
9194
|
});
|
|
8920
9195
|
}
|
|
8921
|
-
prompt(content
|
|
8922
|
-
this.send(content
|
|
9196
|
+
prompt(content) {
|
|
9197
|
+
this.send(content);
|
|
8923
9198
|
return this.streamTurn();
|
|
8924
9199
|
}
|
|
8925
|
-
send(content
|
|
9200
|
+
send(content) {
|
|
8926
9201
|
this.pendingTurns += 1;
|
|
8927
|
-
this.input.push(buildUserMessage(content
|
|
9202
|
+
this.input.push(buildUserMessage(content));
|
|
8928
9203
|
}
|
|
8929
9204
|
async* streamTurn() {
|
|
8930
9205
|
if (this.pumping)
|
|
@@ -8951,6 +9226,9 @@ class AgentSession {
|
|
|
8951
9226
|
this.rejectAllPrompts();
|
|
8952
9227
|
await this.query.interrupt();
|
|
8953
9228
|
}
|
|
9229
|
+
stopTask(taskId) {
|
|
9230
|
+
return this.query.stopTask(taskId);
|
|
9231
|
+
}
|
|
8954
9232
|
async setModel(model) {
|
|
8955
9233
|
await this.query.setModel(model);
|
|
8956
9234
|
this.baseOptions = { ...this.baseOptions, model };
|
|
@@ -9021,10 +9299,11 @@ class AgentSession {
|
|
|
9021
9299
|
if (done)
|
|
9022
9300
|
break;
|
|
9023
9301
|
sink.push({ type: "agent.message.received", message: value });
|
|
9302
|
+
this.liveTaskIds = readLiveTaskIds(value, this.liveTaskIds);
|
|
9024
9303
|
if (value.type !== "result")
|
|
9025
9304
|
continue;
|
|
9026
9305
|
this.pendingTurns = Math.max(this.pendingTurns - 1, 0);
|
|
9027
|
-
if (this.pendingTurns === 0)
|
|
9306
|
+
if (this.pendingTurns === 0 && this.liveTaskIds.size === 0)
|
|
9028
9307
|
break;
|
|
9029
9308
|
}
|
|
9030
9309
|
sink.end();
|
|
@@ -9091,19 +9370,21 @@ async function readOptions2(path) {
|
|
|
9091
9370
|
const parsed = optionsFileSchema.safeParse(stored);
|
|
9092
9371
|
return parsed.success ? parsed.data : {};
|
|
9093
9372
|
}
|
|
9094
|
-
async
|
|
9095
|
-
await Bun.write(path, JSON.stringify({ ...await readOptions2(path),
|
|
9096
|
-
}
|
|
9373
|
+
var saveOption = async (path, option) => {
|
|
9374
|
+
await Bun.write(path, JSON.stringify({ ...await readOptions2(path), ...option }, null, 2));
|
|
9375
|
+
};
|
|
9376
|
+
var saveBackground = (path, background) => saveOption(path, { background });
|
|
9377
|
+
var saveTheme = (path, theme) => saveOption(path, { theme });
|
|
9097
9378
|
|
|
9098
9379
|
// packages/daemon/src/workspace/resolvePath.ts
|
|
9099
9380
|
import { stat } from "fs/promises";
|
|
9100
9381
|
import { homedir as homedir2 } from "os";
|
|
9101
|
-
import { join as join3, resolve } from "path";
|
|
9382
|
+
import { join as join3, resolve as resolve2 } from "path";
|
|
9102
9383
|
var isDirectory = async (path) => (await stat(path).catch(() => {
|
|
9103
9384
|
return;
|
|
9104
9385
|
}))?.isDirectory() ?? false;
|
|
9105
9386
|
var expandHome = (path) => path === "~" || path.startsWith("~/") ? join3(homedir2(), path.slice(1)) : path;
|
|
9106
|
-
var resolveUserPath = (base, path) =>
|
|
9387
|
+
var resolveUserPath = (base, path) => resolve2(base, expandHome(path.trim()));
|
|
9107
9388
|
|
|
9108
9389
|
// packages/daemon/src/server/daemonContext.ts
|
|
9109
9390
|
var SESSIONS_DIRECTORY = join4(homedir3(), ".claudin", "sessions");
|
|
@@ -9171,11 +9452,7 @@ async function createDaemonContext(store = new FileSessionStore(SESSIONS_DIRECTO
|
|
|
9171
9452
|
// packages/daemon/src/client/replayClient.ts
|
|
9172
9453
|
var MAX_GAP_MS = 1500;
|
|
9173
9454
|
var READ_ONLY_REASON = "Replay is read-only";
|
|
9174
|
-
var PROMPT_TYPES = new Set([
|
|
9175
|
-
"agent.prompt.requested",
|
|
9176
|
-
"agent.prompt.queue.requested",
|
|
9177
|
-
"agent.prompt.steer.requested"
|
|
9178
|
-
]);
|
|
9455
|
+
var PROMPT_TYPES = new Set(["agent.prompt.requested"]);
|
|
9179
9456
|
|
|
9180
9457
|
class ReplayClient {
|
|
9181
9458
|
stored;
|
|
@@ -9288,20 +9565,13 @@ var agentHandlers = {
|
|
|
9288
9565
|
async* "agent.prompt.requested"({ agents }, request) {
|
|
9289
9566
|
yield* agents.requireSession(request.agentSessionId).prompt(request.content);
|
|
9290
9567
|
},
|
|
9291
|
-
async* "agent.prompt.queue.requested"({ agents }, request) {
|
|
9292
|
-
const turn = agents.requireSession(request.agentSessionId).prompt(request.content, "later");
|
|
9293
|
-
yield { type: "agent.prompt.accepted", agentSessionId: request.agentSessionId };
|
|
9294
|
-
yield* turn;
|
|
9295
|
-
},
|
|
9296
|
-
async* "agent.prompt.steer.requested"({ agents }, request) {
|
|
9297
|
-
const turn = agents.requireSession(request.agentSessionId).prompt(request.content, "now");
|
|
9298
|
-
yield { type: "agent.prompt.accepted", agentSessionId: request.agentSessionId };
|
|
9299
|
-
yield* turn;
|
|
9300
|
-
},
|
|
9301
9568
|
async* "agent.prompt.cancel.requested"({ agents }, request) {
|
|
9302
9569
|
await agents.requireSession(request.agentSessionId).cancel();
|
|
9303
9570
|
yield { type: "agent.prompt.cancelled", agentSessionId: request.agentSessionId };
|
|
9304
9571
|
},
|
|
9572
|
+
async* "agent.task.stop.requested"({ agents }, request) {
|
|
9573
|
+
await agents.requireSession(request.agentSessionId).stopTask(request.taskId);
|
|
9574
|
+
},
|
|
9305
9575
|
async* "agent.tool.approval.answered"({ agents }, request) {
|
|
9306
9576
|
agents.requireSession(request.agentSessionId).answerApproval(request.toolUseId, request.decision);
|
|
9307
9577
|
},
|
|
@@ -9378,12 +9648,16 @@ var agentHandlers = {
|
|
|
9378
9648
|
// packages/daemon/src/handlers/optionsHandlers.ts
|
|
9379
9649
|
var optionsHandlers = {
|
|
9380
9650
|
async* "options.load.requested"({ optionsPath }) {
|
|
9381
|
-
const { background } = await readOptions2(optionsPath);
|
|
9382
|
-
yield { type: "options.loaded", background };
|
|
9651
|
+
const { background, theme } = await readOptions2(optionsPath);
|
|
9652
|
+
yield { type: "options.loaded", background, theme };
|
|
9383
9653
|
},
|
|
9384
9654
|
async* "options.background.save.requested"({ optionsPath }, request) {
|
|
9385
9655
|
await saveBackground(optionsPath, request.color);
|
|
9386
9656
|
yield { type: "options.background.saved", color: request.color };
|
|
9657
|
+
},
|
|
9658
|
+
async* "options.theme.save.requested"({ optionsPath }, request) {
|
|
9659
|
+
await saveTheme(optionsPath, request.theme);
|
|
9660
|
+
yield { type: "options.theme.saved", theme: request.theme };
|
|
9387
9661
|
}
|
|
9388
9662
|
};
|
|
9389
9663
|
|
|
@@ -9419,14 +9693,14 @@ var sessionHandlers = {
|
|
|
9419
9693
|
};
|
|
9420
9694
|
|
|
9421
9695
|
// packages/daemon/src/workspace/readFileDiffs.ts
|
|
9422
|
-
import { relative, resolve as
|
|
9696
|
+
import { relative, resolve as resolve3 } from "path";
|
|
9423
9697
|
var isTracked = async (cwd, path) => (await Bun.$`git ls-files --error-unmatch -- ${path}`.cwd(cwd).quiet().nothrow()).exitCode === 0;
|
|
9424
9698
|
async function readPatch(cwd, path) {
|
|
9425
9699
|
const command = await isTracked(cwd, path) ? Bun.$`git diff --no-color HEAD -- ${path}` : Bun.$`git diff --no-color --no-index -- /dev/null ${path}`;
|
|
9426
9700
|
return (await command.cwd(cwd).quiet().nothrow()).text();
|
|
9427
9701
|
}
|
|
9428
9702
|
async function readFileDiff(cwd, path) {
|
|
9429
|
-
const absolute =
|
|
9703
|
+
const absolute = resolve3(cwd, path);
|
|
9430
9704
|
const patch = await readPatch(cwd, absolute);
|
|
9431
9705
|
return {
|
|
9432
9706
|
path: relative(cwd, absolute) || path,
|
|
@@ -11134,7 +11408,7 @@ async function startDaemon(port = DEFAULT_PORT, context) {
|
|
|
11134
11408
|
}
|
|
11135
11409
|
// apps/tui/src/startTui.ts
|
|
11136
11410
|
import {
|
|
11137
|
-
BoxRenderable as
|
|
11411
|
+
BoxRenderable as BoxRenderable19,
|
|
11138
11412
|
createCliRenderer,
|
|
11139
11413
|
createHostClipboard
|
|
11140
11414
|
} from "@opentui/core";
|
|
@@ -11176,7 +11450,7 @@ function buildPalette(colors, background = TRANSPARENT_BACKGROUND) {
|
|
|
11176
11450
|
},
|
|
11177
11451
|
fg: {
|
|
11178
11452
|
primary: hex("text"),
|
|
11179
|
-
secondary: rgbToHex2(tint(color("text"), color("textMuted"), SECONDARY_TEXT_WEIGHT)),
|
|
11453
|
+
secondary: hex("secondary") ?? rgbToHex2(tint(color("text"), color("textMuted"), SECONDARY_TEXT_WEIGHT)),
|
|
11180
11454
|
muted: hex("textMuted")
|
|
11181
11455
|
},
|
|
11182
11456
|
border: { subtle: hex("borderSubtle"), focus: hex("borderActive"), separator: hex("border") },
|
|
@@ -11187,7 +11461,38 @@ function buildPalette(colors, background = TRANSPARENT_BACKGROUND) {
|
|
|
11187
11461
|
warning: hex("warning"),
|
|
11188
11462
|
info: hex("info")
|
|
11189
11463
|
},
|
|
11190
|
-
diff: {
|
|
11464
|
+
diff: {
|
|
11465
|
+
addedBg: hex("diffAddedBg"),
|
|
11466
|
+
removedBg: hex("diffRemovedBg"),
|
|
11467
|
+
contextBg: hex("diffContextBg"),
|
|
11468
|
+
addedText: hex("diffAdded"),
|
|
11469
|
+
removedText: hex("diffRemoved"),
|
|
11470
|
+
contextText: hex("diffContext"),
|
|
11471
|
+
lineNumber: hex("diffLineNumber"),
|
|
11472
|
+
addedLineNumberBg: hex("diffAddedLineNumberBg"),
|
|
11473
|
+
removedLineNumberBg: hex("diffRemovedLineNumberBg")
|
|
11474
|
+
},
|
|
11475
|
+
syntax: {
|
|
11476
|
+
comment: hex("syntaxComment"),
|
|
11477
|
+
keyword: hex("syntaxKeyword"),
|
|
11478
|
+
function: hex("syntaxFunction"),
|
|
11479
|
+
variable: hex("syntaxVariable"),
|
|
11480
|
+
string: hex("syntaxString"),
|
|
11481
|
+
number: hex("syntaxNumber"),
|
|
11482
|
+
type: hex("syntaxType"),
|
|
11483
|
+
operator: hex("syntaxOperator"),
|
|
11484
|
+
punctuation: hex("syntaxPunctuation")
|
|
11485
|
+
},
|
|
11486
|
+
markdown: {
|
|
11487
|
+
heading: hex("markdownHeading"),
|
|
11488
|
+
strong: hex("markdownStrong"),
|
|
11489
|
+
emphasis: hex("markdownEmph"),
|
|
11490
|
+
listItem: hex("markdownListItem"),
|
|
11491
|
+
blockQuote: hex("markdownBlockQuote"),
|
|
11492
|
+
code: hex("markdownCode"),
|
|
11493
|
+
link: hex("markdownLink"),
|
|
11494
|
+
linkText: hex("markdownLinkText")
|
|
11495
|
+
}
|
|
11191
11496
|
};
|
|
11192
11497
|
}
|
|
11193
11498
|
// apps/tui/src/theme/assets/aura.json
|
|
@@ -18656,10 +18961,16 @@ var createDiffView = (renderer, syntaxStyle, patch, filetype) => new DiffRendera
|
|
|
18656
18961
|
syntaxStyle,
|
|
18657
18962
|
view: "unified",
|
|
18658
18963
|
showLineNumbers: true,
|
|
18964
|
+
fg: Theme.fg.primary,
|
|
18659
18965
|
addedBg: Theme.diff.addedBg,
|
|
18660
18966
|
removedBg: Theme.diff.removedBg,
|
|
18661
|
-
|
|
18662
|
-
|
|
18967
|
+
contextBg: Theme.diff.contextBg,
|
|
18968
|
+
lineNumberFg: Theme.diff.lineNumber,
|
|
18969
|
+
lineNumberBg: Theme.diff.contextBg,
|
|
18970
|
+
addedLineNumberBg: Theme.diff.addedLineNumberBg,
|
|
18971
|
+
removedLineNumberBg: Theme.diff.removedLineNumberBg,
|
|
18972
|
+
addedSignColor: Theme.diff.addedText,
|
|
18973
|
+
removedSignColor: Theme.diff.removedText,
|
|
18663
18974
|
flexShrink: 0
|
|
18664
18975
|
});
|
|
18665
18976
|
|
|
@@ -18948,11 +19259,11 @@ var buildImageBlock = (mediaType, bytes) => ({
|
|
|
18948
19259
|
// apps/tui/src/prompt/pastedPaths.ts
|
|
18949
19260
|
import { statSync } from "fs";
|
|
18950
19261
|
import { homedir as homedir6 } from "os";
|
|
18951
|
-
import { isAbsolute } from "path";
|
|
19262
|
+
import { isAbsolute as isAbsolute2 } from "path";
|
|
18952
19263
|
var unwrapPath = (raw) => raw.trim().replace(/^(['"])(.*)\1$/, "$2").replace(/^file:\/\//, "").replace(/^~(?=\/)/, homedir6()).replace(/\\(.)/g, "$1");
|
|
18953
19264
|
var isExistingFile = (path) => {
|
|
18954
19265
|
try {
|
|
18955
|
-
return
|
|
19266
|
+
return isAbsolute2(path) && statSync(path).isFile();
|
|
18956
19267
|
} catch {
|
|
18957
19268
|
return false;
|
|
18958
19269
|
}
|
|
@@ -18998,7 +19309,7 @@ function planPaste(event, attachments) {
|
|
|
18998
19309
|
|
|
18999
19310
|
// apps/tui/src/components/promptInput.ts
|
|
19000
19311
|
var MAX_INPUT_LINES = 8;
|
|
19001
|
-
var
|
|
19312
|
+
var BUSY_PLACEHOLDER = "Enter (steer) Ctrl+Q (queue)";
|
|
19002
19313
|
var ATTACHMENT_STYLE = "attachment";
|
|
19003
19314
|
var PLACEHOLDER = "Type your prompt, /slash command, or @file reference...";
|
|
19004
19315
|
var KEY_BINDINGS = [
|
|
@@ -19020,12 +19331,11 @@ class PromptInput {
|
|
|
19020
19331
|
constructor(renderer, handlers) {
|
|
19021
19332
|
this.renderable = new BoxRenderable5(renderer, {
|
|
19022
19333
|
border: ["top", "bottom"],
|
|
19334
|
+
borderColor: Theme.fg.muted,
|
|
19023
19335
|
borderStyle: "rounded",
|
|
19024
|
-
bottomTitleAlignment: "right",
|
|
19025
19336
|
flexDirection: "row",
|
|
19026
19337
|
height: 3,
|
|
19027
|
-
flexShrink: 0
|
|
19028
|
-
paddingLeft: 1
|
|
19338
|
+
flexShrink: 0
|
|
19029
19339
|
});
|
|
19030
19340
|
this.attachmentStyle = SyntaxStyle.create(renderer.nativeScene);
|
|
19031
19341
|
this.textarea = new TextareaRenderable(renderer, {
|
|
@@ -19086,16 +19396,15 @@ class PromptInput {
|
|
|
19086
19396
|
this.textarea.blur();
|
|
19087
19397
|
}
|
|
19088
19398
|
setBusy(busy) {
|
|
19089
|
-
const
|
|
19090
|
-
if (this.
|
|
19091
|
-
this.
|
|
19399
|
+
const placeholder = busy ? BUSY_PLACEHOLDER : PLACEHOLDER;
|
|
19400
|
+
if (this.textarea.placeholder !== placeholder)
|
|
19401
|
+
this.textarea.placeholder = placeholder;
|
|
19092
19402
|
}
|
|
19093
19403
|
setBorderColor(color) {
|
|
19094
19404
|
this.renderable.borderColor = color;
|
|
19095
19405
|
}
|
|
19096
19406
|
applyColors() {
|
|
19097
|
-
this.
|
|
19098
|
-
this.chevron.fg = Theme.accent.brand;
|
|
19407
|
+
this.chevron.fg = Theme.fg.muted;
|
|
19099
19408
|
this.textarea.placeholderColor = Theme.fg.muted;
|
|
19100
19409
|
this.textarea.textColor = Theme.fg.primary;
|
|
19101
19410
|
this.textarea.focusedTextColor = Theme.fg.primary;
|
|
@@ -19197,6 +19506,25 @@ class AssistantMessageView {
|
|
|
19197
19506
|
}
|
|
19198
19507
|
}
|
|
19199
19508
|
|
|
19509
|
+
// apps/tui/src/components/markdownNoticeView.ts
|
|
19510
|
+
import { MarkdownRenderable as MarkdownRenderable2 } from "@opentui/core";
|
|
19511
|
+
|
|
19512
|
+
class MarkdownNoticeView {
|
|
19513
|
+
renderable;
|
|
19514
|
+
constructor(renderer, mutedSyntaxStyle) {
|
|
19515
|
+
this.renderable = new MarkdownRenderable2(renderer, {
|
|
19516
|
+
content: "",
|
|
19517
|
+
syntaxStyle: mutedSyntaxStyle,
|
|
19518
|
+
marginTop: 1,
|
|
19519
|
+
flexShrink: 0
|
|
19520
|
+
});
|
|
19521
|
+
}
|
|
19522
|
+
update(entry) {
|
|
19523
|
+
if (this.renderable.content !== entry.text)
|
|
19524
|
+
this.renderable.content = entry.text;
|
|
19525
|
+
}
|
|
19526
|
+
}
|
|
19527
|
+
|
|
19200
19528
|
// apps/tui/src/components/noticeView.ts
|
|
19201
19529
|
import { fg as fg7, StyledText as StyledText6, TextRenderable as TextRenderable7 } from "@opentui/core";
|
|
19202
19530
|
class NoticeView {
|
|
@@ -19851,7 +20179,9 @@ var clipLines = (text, maxLines) => {
|
|
|
19851
20179
|
// apps/tui/src/format/toolInputText.ts
|
|
19852
20180
|
var VALUE_LENGTH = 200;
|
|
19853
20181
|
var formatInputValue = (value) => truncateText(typeof value === "string" ? value : JSON.stringify(value), VALUE_LENGTH);
|
|
19854
|
-
var
|
|
20182
|
+
var formatBatchEdit = ({ input }) => listBatchEditPaths(input).map((path, index) => `${index + 1}. ${formatInputValue(path)}`).join(`
|
|
20183
|
+
`);
|
|
20184
|
+
var formatToolInput = (call) => call.name === BATCH_EDIT_TOOL_NAME ? formatBatchEdit(call) : Object.entries(call.input).map(([key, value]) => `${key}: ${formatInputValue(value)}`).join(`
|
|
19855
20185
|
`);
|
|
19856
20186
|
|
|
19857
20187
|
// apps/tui/src/format/toolSummary.ts
|
|
@@ -19859,9 +20189,15 @@ var SUMMARY_LENGTH = 80;
|
|
|
19859
20189
|
var SUMMARY_KEYS = ["file_path", "path", "command", "pattern", "query", "url", "description"];
|
|
19860
20190
|
var SEARCH_TOOLS = new Set(["Glob", "Grep"]);
|
|
19861
20191
|
var summarizeSearch = ({ pattern, path }) => typeof path === "string" ? `${pattern} in ${path}` : String(pattern);
|
|
20192
|
+
var summarizeBatchEdit = (input) => {
|
|
20193
|
+
const paths = listBatchEditPaths(input);
|
|
20194
|
+
return `${paths.length} edits in ${new Set(paths).size} files`;
|
|
20195
|
+
};
|
|
19862
20196
|
function summarizeToolCall({ name, input, status, progress }) {
|
|
19863
20197
|
if (status === "running" && progress)
|
|
19864
20198
|
return truncateText(progress, SUMMARY_LENGTH);
|
|
20199
|
+
if (name === BATCH_EDIT_TOOL_NAME)
|
|
20200
|
+
return summarizeBatchEdit(input);
|
|
19865
20201
|
if (SEARCH_TOOLS.has(name) && typeof input.pattern === "string") {
|
|
19866
20202
|
return truncateText(summarizeSearch(input), SUMMARY_LENGTH);
|
|
19867
20203
|
}
|
|
@@ -19870,6 +20206,8 @@ function summarizeToolCall({ name, input, status, progress }) {
|
|
|
19870
20206
|
return truncateText(value, SUMMARY_LENGTH);
|
|
19871
20207
|
}
|
|
19872
20208
|
var describeApproval = ({ name, input }) => {
|
|
20209
|
+
if (name === BATCH_EDIT_TOOL_NAME)
|
|
20210
|
+
return `Apply ${summarizeBatchEdit(input)} with BatchEdit?`;
|
|
19873
20211
|
if (name === "Bash")
|
|
19874
20212
|
return `Run command \`${truncateText(String(input.command ?? ""), 60)}\`?`;
|
|
19875
20213
|
const path = input.file_path ?? input.notebook_path;
|
|
@@ -20114,8 +20452,8 @@ class ToolCallView {
|
|
|
20114
20452
|
const glyph = call.expanded ? COLLAPSE_GLYPHS.expanded : COLLAPSE_GLYPHS.collapsed;
|
|
20115
20453
|
const accent = this.hovered ? Theme.accent.brand : undefined;
|
|
20116
20454
|
this.title.content = new StyledText10([
|
|
20117
|
-
fg11(accent ?? toolColor(call.status))(
|
|
20118
|
-
bold6(fg11(accent ?? Theme.fg.primary)(call.name)),
|
|
20455
|
+
fg11(accent ?? toolColor(call.status))(glyph),
|
|
20456
|
+
bold6(fg11(accent ?? Theme.fg.primary)(stripCustomPrefix(call.name))),
|
|
20119
20457
|
fg11(Theme.fg.secondary)(` ${summarizeToolCall(call)}`),
|
|
20120
20458
|
fg11(Theme.fg.muted)(stats)
|
|
20121
20459
|
]);
|
|
@@ -20222,7 +20560,6 @@ class UserMessageView {
|
|
|
20222
20560
|
return;
|
|
20223
20561
|
this.entry = entry;
|
|
20224
20562
|
this.text.content = new StyledText11([
|
|
20225
|
-
bold7(fg12(Theme.accent.brand)("\u276F ")),
|
|
20226
20563
|
bold7(fg12(Theme.fg.primary)(clipLines(entry.text, USER_LINES)))
|
|
20227
20564
|
]);
|
|
20228
20565
|
this.clock.content = new StyledText11([fg12(Theme.fg.muted)(formatClock(entry.at))]);
|
|
@@ -20276,9 +20613,9 @@ class ScrollbackView {
|
|
|
20276
20613
|
else if (below > 0)
|
|
20277
20614
|
this.renderable.scrollBy(Math.min(below, above));
|
|
20278
20615
|
}
|
|
20279
|
-
reset(syntaxStyle) {
|
|
20616
|
+
reset(syntaxStyle, mutedSyntaxStyle) {
|
|
20280
20617
|
this.dropViews(() => true);
|
|
20281
|
-
this.options = { syntaxStyle, hooks: { ...this.options.hooks, syntaxStyle } };
|
|
20618
|
+
this.options = { syntaxStyle, mutedSyntaxStyle, hooks: { ...this.options.hooks, syntaxStyle } };
|
|
20282
20619
|
}
|
|
20283
20620
|
dropRemovedViews(state) {
|
|
20284
20621
|
const live = new Set(state.transcript.map((entry) => entry.id));
|
|
@@ -20300,14 +20637,14 @@ class ScrollbackView {
|
|
|
20300
20637
|
return view;
|
|
20301
20638
|
}
|
|
20302
20639
|
createView(entry) {
|
|
20303
|
-
const { syntaxStyle, hooks } = this.options;
|
|
20640
|
+
const { syntaxStyle, mutedSyntaxStyle, hooks } = this.options;
|
|
20304
20641
|
switch (entry.kind) {
|
|
20305
20642
|
case "user":
|
|
20306
20643
|
return new UserMessageView(this.renderer);
|
|
20307
20644
|
case "assistant":
|
|
20308
20645
|
return new AssistantMessageView(this.renderer, syntaxStyle);
|
|
20309
20646
|
case "notice":
|
|
20310
|
-
return new NoticeView(this.renderer);
|
|
20647
|
+
return entry.markdown ? new MarkdownNoticeView(this.renderer, mutedSyntaxStyle) : new NoticeView(this.renderer);
|
|
20311
20648
|
case "thought":
|
|
20312
20649
|
return new ThoughtView(this.renderer);
|
|
20313
20650
|
case "tools":
|
|
@@ -20386,15 +20723,14 @@ class SessionInfoBar {
|
|
|
20386
20723
|
limits;
|
|
20387
20724
|
constructor(renderer) {
|
|
20388
20725
|
this.renderable = new BoxRenderable13(renderer, {
|
|
20389
|
-
marginBottom: 1,
|
|
20390
20726
|
flexShrink: 0,
|
|
20391
20727
|
flexDirection: "row",
|
|
20392
20728
|
flexWrap: "wrap",
|
|
20393
20729
|
rowGap: 1,
|
|
20394
20730
|
columnGap: 0,
|
|
20395
20731
|
justifyContent: "space-between",
|
|
20396
|
-
paddingLeft:
|
|
20397
|
-
paddingRight:
|
|
20732
|
+
paddingLeft: 2,
|
|
20733
|
+
paddingRight: 2
|
|
20398
20734
|
});
|
|
20399
20735
|
this.info = new TextRenderable13(renderer, { content: "", wrapMode: "none", flexShrink: 0 });
|
|
20400
20736
|
this.limits = new TextRenderable13(renderer, {
|
|
@@ -20450,12 +20786,14 @@ class StatusLine {
|
|
|
20450
20786
|
constructor(renderer, onStop) {
|
|
20451
20787
|
this.renderable = new BoxRenderable14(renderer, {
|
|
20452
20788
|
height: 2,
|
|
20453
|
-
paddingTop: 1,
|
|
20454
20789
|
flexShrink: 0,
|
|
20455
20790
|
flexDirection: "row",
|
|
20456
20791
|
justifyContent: "space-between",
|
|
20792
|
+
border: ["top"],
|
|
20793
|
+
borderColor: Theme.border.subtle,
|
|
20457
20794
|
paddingLeft: 2,
|
|
20458
|
-
paddingRight: 2
|
|
20795
|
+
paddingRight: 2,
|
|
20796
|
+
visible: false
|
|
20459
20797
|
});
|
|
20460
20798
|
this.label = new TextRenderable14(renderer, { content: "", wrapMode: "none" });
|
|
20461
20799
|
this.stats = new TextRenderable14(renderer, {
|
|
@@ -20471,9 +20809,11 @@ class StatusLine {
|
|
|
20471
20809
|
update(state) {
|
|
20472
20810
|
if (state.status === "idle") {
|
|
20473
20811
|
this.label.content = state.lastRun ? new StyledText13(buildLastRunChunks(state.lastRun, readLastPrompt(state))) : "";
|
|
20812
|
+
this.renderable.visible = state.lastRun !== undefined;
|
|
20474
20813
|
this.stats.content = "";
|
|
20475
20814
|
return;
|
|
20476
20815
|
}
|
|
20816
|
+
this.renderable.visible = true;
|
|
20477
20817
|
const label = agentLabel(state.status);
|
|
20478
20818
|
const busy = label.icon === undefined;
|
|
20479
20819
|
const frame = SPINNER_FRAMES[Math.floor(state.now / SPINNER_STEP_MS) % SPINNER_FRAMES.length];
|
|
@@ -20490,8 +20830,198 @@ class StatusLine {
|
|
|
20490
20830
|
}
|
|
20491
20831
|
}
|
|
20492
20832
|
|
|
20833
|
+
// apps/tui/src/components/promptQueueView.ts
|
|
20834
|
+
import {
|
|
20835
|
+
BoxRenderable as BoxRenderable15,
|
|
20836
|
+
bold as bold9,
|
|
20837
|
+
dim as dim7,
|
|
20838
|
+
fg as fg16,
|
|
20839
|
+
StyledText as StyledText14,
|
|
20840
|
+
TextRenderable as TextRenderable15
|
|
20841
|
+
} from "@opentui/core";
|
|
20842
|
+
|
|
20843
|
+
// apps/tui/src/format/promptQueueRows.ts
|
|
20844
|
+
var MAX_QUEUE_ROWS = 5;
|
|
20845
|
+
var QUEUE_TEXT_LENGTH = 80;
|
|
20846
|
+
var buildQueueRows = (queued) => queued.slice(0, MAX_QUEUE_ROWS).map((content, index) => `${index + 1}. ${truncateText(readPromptText(content), QUEUE_TEXT_LENGTH)}`);
|
|
20847
|
+
var buildQueueHeader = (queued) => `Queued${SEPARATOR}${queued.length} waiting`;
|
|
20848
|
+
var countHiddenQueued = (queued) => Math.max(queued.length - MAX_QUEUE_ROWS, 0);
|
|
20849
|
+
|
|
20850
|
+
// apps/tui/src/components/promptQueueView.ts
|
|
20851
|
+
class PromptQueueView {
|
|
20852
|
+
renderable;
|
|
20853
|
+
header;
|
|
20854
|
+
rows;
|
|
20855
|
+
overflow;
|
|
20856
|
+
constructor(renderer) {
|
|
20857
|
+
this.renderable = new BoxRenderable15(renderer, {
|
|
20858
|
+
flexShrink: 0,
|
|
20859
|
+
paddingLeft: 2,
|
|
20860
|
+
paddingRight: 2,
|
|
20861
|
+
visible: false
|
|
20862
|
+
});
|
|
20863
|
+
this.header = new TextRenderable15(renderer, { content: "", wrapMode: "none" });
|
|
20864
|
+
this.overflow = new TextRenderable15(renderer, { content: "", wrapMode: "none" });
|
|
20865
|
+
this.rows = Array.from({ length: MAX_QUEUE_ROWS }, () => new TextRenderable15(renderer, { content: "", wrapMode: "none" }));
|
|
20866
|
+
this.renderable.add(this.header);
|
|
20867
|
+
for (const row of this.rows)
|
|
20868
|
+
this.renderable.add(row);
|
|
20869
|
+
this.renderable.add(this.overflow);
|
|
20870
|
+
}
|
|
20871
|
+
update({ queuedPrompts }) {
|
|
20872
|
+
this.renderable.visible = queuedPrompts.length > 0;
|
|
20873
|
+
if (queuedPrompts.length === 0)
|
|
20874
|
+
return;
|
|
20875
|
+
this.header.content = new StyledText14([
|
|
20876
|
+
bold9(fg16(Theme.fg.secondary)(buildQueueHeader(queuedPrompts)))
|
|
20877
|
+
]);
|
|
20878
|
+
const lines = buildQueueRows(queuedPrompts);
|
|
20879
|
+
this.rows.forEach((row, index) => {
|
|
20880
|
+
row.content = new StyledText14([fg16(Theme.fg.primary)(lines[index] ?? "")]);
|
|
20881
|
+
});
|
|
20882
|
+
const hidden = countHiddenQueued(queuedPrompts);
|
|
20883
|
+
this.overflow.content = hidden ? new StyledText14([dim7(fg16(Theme.fg.muted)(` +${hidden} more`))]) : "";
|
|
20884
|
+
}
|
|
20885
|
+
}
|
|
20886
|
+
|
|
20887
|
+
// apps/tui/src/components/taskPanel.ts
|
|
20888
|
+
import {
|
|
20889
|
+
BoxRenderable as BoxRenderable17,
|
|
20890
|
+
bold as bold11,
|
|
20891
|
+
dim as dim9,
|
|
20892
|
+
fg as fg18,
|
|
20893
|
+
StyledText as StyledText16,
|
|
20894
|
+
TextRenderable as TextRenderable17
|
|
20895
|
+
} from "@opentui/core";
|
|
20896
|
+
|
|
20897
|
+
// apps/tui/src/format/taskRows.ts
|
|
20898
|
+
var MAX_TASK_ROWS = 5;
|
|
20899
|
+
var KIND_LABELS = { "general-purpose": "Agent", local_bash: "Bash" };
|
|
20900
|
+
var describeLastTool = ({ lastToolCall, lastToolName }) => {
|
|
20901
|
+
if (!lastToolCall)
|
|
20902
|
+
return lastToolName;
|
|
20903
|
+
const { name, input } = lastToolCall;
|
|
20904
|
+
const summary = summarizeToolCall({
|
|
20905
|
+
id: "",
|
|
20906
|
+
name,
|
|
20907
|
+
input,
|
|
20908
|
+
status: "running",
|
|
20909
|
+
expanded: false,
|
|
20910
|
+
startedAt: 0
|
|
20911
|
+
});
|
|
20912
|
+
return `${name} ${summary}`;
|
|
20913
|
+
};
|
|
20914
|
+
var readDetail = (task) => {
|
|
20915
|
+
if (task.paused)
|
|
20916
|
+
return "Paused";
|
|
20917
|
+
return task.summary ?? describeLastTool(task) ?? "Starting...";
|
|
20918
|
+
};
|
|
20919
|
+
var buildTaskRow = (task, now) => ({
|
|
20920
|
+
taskId: task.id,
|
|
20921
|
+
kind: KIND_LABELS[task.kind] ?? task.kind,
|
|
20922
|
+
model: task.model ?? "",
|
|
20923
|
+
title: task.description,
|
|
20924
|
+
stats: [formatDuration(Math.max(now - task.startedAt, 0)), `\u2193${formatTokenCount(task.tokens)}`].join(SEPARATOR).trim(),
|
|
20925
|
+
detail: readDetail(task)
|
|
20926
|
+
});
|
|
20927
|
+
var buildTaskRows = (tasks, now) => tasks.slice(0, MAX_TASK_ROWS).map((task) => buildTaskRow(task, now));
|
|
20928
|
+
var buildTaskHeader = (tasks) => `Tasks${SEPARATOR}${tasks.length} running`;
|
|
20929
|
+
var countHiddenTasks = (tasks) => Math.max(tasks.length - MAX_TASK_ROWS, 0);
|
|
20930
|
+
|
|
20931
|
+
// apps/tui/src/components/taskRowView.ts
|
|
20932
|
+
import {
|
|
20933
|
+
BoxRenderable as BoxRenderable16,
|
|
20934
|
+
bold as bold10,
|
|
20935
|
+
dim as dim8,
|
|
20936
|
+
fg as fg17,
|
|
20937
|
+
StyledText as StyledText15,
|
|
20938
|
+
TextRenderable as TextRenderable16
|
|
20939
|
+
} from "@opentui/core";
|
|
20940
|
+
var SPINNER_STEP_MS2 = 100;
|
|
20941
|
+
|
|
20942
|
+
class TaskRowView {
|
|
20943
|
+
renderable;
|
|
20944
|
+
title;
|
|
20945
|
+
stop;
|
|
20946
|
+
detail;
|
|
20947
|
+
taskId = "";
|
|
20948
|
+
constructor(renderer, onStop) {
|
|
20949
|
+
this.renderable = new BoxRenderable16(renderer, { flexShrink: 0, visible: false });
|
|
20950
|
+
const line = new BoxRenderable16(renderer, {
|
|
20951
|
+
flexDirection: "row",
|
|
20952
|
+
justifyContent: "space-between"
|
|
20953
|
+
});
|
|
20954
|
+
this.title = new TextRenderable16(renderer, { content: "", wrapMode: "none" });
|
|
20955
|
+
this.stop = new TextRenderable16(renderer, {
|
|
20956
|
+
content: "",
|
|
20957
|
+
wrapMode: "none",
|
|
20958
|
+
flexShrink: 0,
|
|
20959
|
+
selectable: false,
|
|
20960
|
+
onMouseDown: () => onStop(this.taskId)
|
|
20961
|
+
});
|
|
20962
|
+
this.detail = new TextRenderable16(renderer, { content: "", wrapMode: "none" });
|
|
20963
|
+
line.add(this.title);
|
|
20964
|
+
line.add(this.stop);
|
|
20965
|
+
this.renderable.add(line);
|
|
20966
|
+
this.renderable.add(this.detail);
|
|
20967
|
+
}
|
|
20968
|
+
update(row, now) {
|
|
20969
|
+
this.renderable.visible = row !== undefined;
|
|
20970
|
+
if (!row)
|
|
20971
|
+
return;
|
|
20972
|
+
this.taskId = row.taskId;
|
|
20973
|
+
const frame = SPINNER_FRAMES[Math.floor(now / SPINNER_STEP_MS2) % SPINNER_FRAMES.length];
|
|
20974
|
+
this.title.content = new StyledText15([
|
|
20975
|
+
fg17(Theme.status.success)(`${frame} `),
|
|
20976
|
+
bold10(fg17(Theme.fg.primary)(row.kind)),
|
|
20977
|
+
fg17(Theme.fg.muted)(row.model ? ` (${row.model})` : ""),
|
|
20978
|
+
fg17(Theme.fg.secondary)(` ${row.title}`)
|
|
20979
|
+
]);
|
|
20980
|
+
this.stop.content = new StyledText15([
|
|
20981
|
+
fg17(Theme.fg.muted)(`${row.stats} `),
|
|
20982
|
+
bold10(fg17(Theme.fg.secondary)("[stop]"))
|
|
20983
|
+
]);
|
|
20984
|
+
this.detail.content = new StyledText15([dim8(fg17(Theme.fg.muted)(` \u2514 ${row.detail}`))]);
|
|
20985
|
+
}
|
|
20986
|
+
}
|
|
20987
|
+
|
|
20988
|
+
// apps/tui/src/components/taskPanel.ts
|
|
20989
|
+
class TaskPanel {
|
|
20990
|
+
renderable;
|
|
20991
|
+
header;
|
|
20992
|
+
rows;
|
|
20993
|
+
overflow;
|
|
20994
|
+
constructor(renderer, onStop) {
|
|
20995
|
+
this.renderable = new BoxRenderable17(renderer, {
|
|
20996
|
+
flexShrink: 0,
|
|
20997
|
+
paddingLeft: 2,
|
|
20998
|
+
paddingRight: 2,
|
|
20999
|
+
border: ["top"],
|
|
21000
|
+
borderColor: Theme.border.subtle,
|
|
21001
|
+
visible: false
|
|
21002
|
+
});
|
|
21003
|
+
this.header = new TextRenderable17(renderer, { content: "", wrapMode: "none" });
|
|
21004
|
+
this.overflow = new TextRenderable17(renderer, { content: "", wrapMode: "none" });
|
|
21005
|
+
this.rows = Array.from({ length: MAX_TASK_ROWS }, () => new TaskRowView(renderer, onStop));
|
|
21006
|
+
this.renderable.add(this.header);
|
|
21007
|
+
for (const row of this.rows)
|
|
21008
|
+
this.renderable.add(row.renderable);
|
|
21009
|
+
this.renderable.add(this.overflow);
|
|
21010
|
+
}
|
|
21011
|
+
update({ tasks, now }) {
|
|
21012
|
+
this.renderable.visible = tasks.length > 0;
|
|
21013
|
+
if (tasks.length === 0)
|
|
21014
|
+
return;
|
|
21015
|
+
const rows = buildTaskRows(tasks, now);
|
|
21016
|
+
this.header.content = new StyledText16([bold11(fg18(Theme.fg.primary)(buildTaskHeader(tasks)))]);
|
|
21017
|
+
this.rows.forEach((view, index) => view.update(rows[index], now));
|
|
21018
|
+
const hidden = countHiddenTasks(tasks);
|
|
21019
|
+
this.overflow.content = hidden ? new StyledText16([dim9(fg18(Theme.fg.muted)(` +${hidden} more`))]) : "";
|
|
21020
|
+
}
|
|
21021
|
+
}
|
|
21022
|
+
|
|
20493
21023
|
// apps/tui/src/components/toastView.ts
|
|
20494
|
-
import { BoxRenderable as
|
|
21024
|
+
import { BoxRenderable as BoxRenderable18, fg as fg19, StyledText as StyledText17, TextRenderable as TextRenderable18 } from "@opentui/core";
|
|
20495
21025
|
var TOAST_ICON = "\u25CF";
|
|
20496
21026
|
|
|
20497
21027
|
class ToastView {
|
|
@@ -20499,7 +21029,7 @@ class ToastView {
|
|
|
20499
21029
|
text;
|
|
20500
21030
|
toastId;
|
|
20501
21031
|
constructor(renderer) {
|
|
20502
|
-
this.renderable = new
|
|
21032
|
+
this.renderable = new BoxRenderable18(renderer, {
|
|
20503
21033
|
position: "absolute",
|
|
20504
21034
|
top: 1,
|
|
20505
21035
|
right: 2,
|
|
@@ -20510,7 +21040,7 @@ class ToastView {
|
|
|
20510
21040
|
borderStyle: "rounded",
|
|
20511
21041
|
visible: false
|
|
20512
21042
|
});
|
|
20513
|
-
this.text = new
|
|
21043
|
+
this.text = new TextRenderable18(renderer, { content: "", wrapMode: "none", selectable: false });
|
|
20514
21044
|
this.renderable.add(this.text);
|
|
20515
21045
|
}
|
|
20516
21046
|
update({ ui }) {
|
|
@@ -20521,9 +21051,9 @@ class ToastView {
|
|
|
20521
21051
|
this.toastId = toast.id;
|
|
20522
21052
|
this.renderable.borderColor = Theme.border.focus;
|
|
20523
21053
|
this.renderable.backgroundColor = Theme.bg.surface;
|
|
20524
|
-
this.text.content = new
|
|
20525
|
-
|
|
20526
|
-
|
|
21054
|
+
this.text.content = new StyledText17([
|
|
21055
|
+
fg19(Theme.status.success)(`${TOAST_ICON} `),
|
|
21056
|
+
fg19(Theme.fg.primary)(toast.text)
|
|
20527
21057
|
]);
|
|
20528
21058
|
}
|
|
20529
21059
|
}
|
|
@@ -20552,6 +21082,9 @@ function requestAgent(store, request, onMissing = "notify") {
|
|
|
20552
21082
|
return true;
|
|
20553
21083
|
}
|
|
20554
21084
|
|
|
21085
|
+
// apps/tui/src/input/themeActions.ts
|
|
21086
|
+
var saveTheme2 = (store, theme) => store.request({ type: "options.theme.save.requested", theme });
|
|
21087
|
+
|
|
20555
21088
|
// apps/tui/src/input/workflowCommands.ts
|
|
20556
21089
|
var postNotice = (store, text) => store.emit({ type: "ui.notice.posted", text });
|
|
20557
21090
|
var WORKFLOW_COMMANDS = {
|
|
@@ -20651,7 +21184,7 @@ var SLASH_COMMANDS = {
|
|
|
20651
21184
|
return store.emit({ type: "ui.theme.picker.opened" });
|
|
20652
21185
|
const parsed = themeNameSchema.safeParse(argument);
|
|
20653
21186
|
if (parsed.success)
|
|
20654
|
-
return store
|
|
21187
|
+
return saveTheme2(store, parsed.data);
|
|
20655
21188
|
store.emit({ type: "ui.notice.posted", text: `Unknown theme: ${argument}` });
|
|
20656
21189
|
}
|
|
20657
21190
|
},
|
|
@@ -20680,8 +21213,10 @@ var SLASH_COMMANDS = {
|
|
|
20680
21213
|
}
|
|
20681
21214
|
},
|
|
20682
21215
|
"/effort": {
|
|
20683
|
-
description: "
|
|
21216
|
+
description: "Pick a reasoning effort, or set one with /effort <level>",
|
|
20684
21217
|
run(store, level) {
|
|
21218
|
+
if (!level)
|
|
21219
|
+
return store.emit({ type: "ui.effort.picker.opened" });
|
|
20685
21220
|
const parsed = effortLevelSchema.safeParse(level);
|
|
20686
21221
|
if (parsed.success) {
|
|
20687
21222
|
return void requestAgent(store, {
|
|
@@ -20753,6 +21288,14 @@ function buildPickerView(state) {
|
|
|
20753
21288
|
}));
|
|
20754
21289
|
return { title: "Select a theme", rows, selected: picker.selected };
|
|
20755
21290
|
}
|
|
21291
|
+
if (picker.kind === "effort") {
|
|
21292
|
+
const current = state.effort || DEFAULT_EFFORT;
|
|
21293
|
+
const rows = effortLevelSchema.options.map((level) => ({
|
|
21294
|
+
name: `${level === current ? "\u25CF " : " "}${level}`,
|
|
21295
|
+
description: ""
|
|
21296
|
+
}));
|
|
21297
|
+
return { title: "Select an effort level", rows, selected: picker.selected };
|
|
21298
|
+
}
|
|
20756
21299
|
if (picker.kind === "rewind") {
|
|
20757
21300
|
const rows = listCheckpoints(state).map((entry) => ({
|
|
20758
21301
|
name: truncateText(entry.text.replace(/\s+/g, " "), CHECKPOINT_TEXT_LENGTH),
|
|
@@ -20770,7 +21313,6 @@ function buildPickerView(state) {
|
|
|
20770
21313
|
var buildListView = (state) => buildPickerView(state) ?? buildAutocompleteView(state);
|
|
20771
21314
|
|
|
20772
21315
|
// apps/tui/src/input/agentSessionActions.ts
|
|
20773
|
-
var DEFAULT_EFFORT = "high";
|
|
20774
21316
|
var DEFAULT_MODEL = "claude-haiku-5-5";
|
|
20775
21317
|
var buildSessionOptions = (store) => ({
|
|
20776
21318
|
model: store.state.model || DEFAULT_MODEL,
|
|
@@ -20949,23 +21491,22 @@ function runSlashCommand(store, line) {
|
|
|
20949
21491
|
}
|
|
20950
21492
|
|
|
20951
21493
|
// apps/tui/src/input/promptActions.ts
|
|
20952
|
-
var DELIVERY_REQUESTS = {
|
|
20953
|
-
send: "agent.prompt.requested",
|
|
20954
|
-
queue: "agent.prompt.queue.requested",
|
|
20955
|
-
steer: "agent.prompt.steer.requested"
|
|
20956
|
-
};
|
|
20957
|
-
var BUSY_NOTICE = "Agent is busy: Ctrl+Q queues, Ctrl+W steers, Esc Esc interrupts the turn";
|
|
20958
21494
|
var buildContent = (text, images) => images.length > 0 ? [{ type: "text", text }, ...images] : text;
|
|
20959
21495
|
function deliverPrompt(store, content, delivery, images) {
|
|
20960
|
-
const
|
|
20961
|
-
if (
|
|
20962
|
-
store.emit({ type: "ui.
|
|
20963
|
-
return
|
|
21496
|
+
const body = buildContent(content, images);
|
|
21497
|
+
if (delivery === "queue" && isAgentBusy(store)) {
|
|
21498
|
+
store.emit({ type: "ui.prompt.queued", content: body });
|
|
21499
|
+
return true;
|
|
20964
21500
|
}
|
|
20965
|
-
return requestAgent(store, {
|
|
20966
|
-
|
|
20967
|
-
|
|
20968
|
-
|
|
21501
|
+
return requestAgent(store, { type: "agent.prompt.requested", content: body });
|
|
21502
|
+
}
|
|
21503
|
+
function sendNextQueuedPrompt(store) {
|
|
21504
|
+
const [next] = store.state.queuedPrompts;
|
|
21505
|
+
if (next === undefined || store.state.status !== "idle")
|
|
21506
|
+
return;
|
|
21507
|
+
const sent = requestAgent(store, { type: "agent.prompt.requested", content: next }, "ignore");
|
|
21508
|
+
if (sent)
|
|
21509
|
+
store.emit({ type: "ui.prompt.dequeued" });
|
|
20969
21510
|
}
|
|
20970
21511
|
function submitPrompt(store, text, delivery = "send", images = []) {
|
|
20971
21512
|
const content = text.trim();
|
|
@@ -20982,6 +21523,9 @@ function answerApproval(store, decision, toolUseId) {
|
|
|
20982
21523
|
if (target)
|
|
20983
21524
|
requestAgent(store, { type: "agent.tool.approval.answered", toolUseId: target, decision });
|
|
20984
21525
|
}
|
|
21526
|
+
function stopTask(store, taskId) {
|
|
21527
|
+
requestAgent(store, { type: "agent.task.stop.requested", taskId });
|
|
21528
|
+
}
|
|
20985
21529
|
function cancelTurn(store) {
|
|
20986
21530
|
requestAgent(store, { type: "agent.prompt.cancel.requested" });
|
|
20987
21531
|
}
|
|
@@ -21046,7 +21590,12 @@ var PICKER_CONFIRMS = {
|
|
|
21046
21590
|
theme(store, _state, selected) {
|
|
21047
21591
|
const theme = THEME_NAMES[selected];
|
|
21048
21592
|
if (theme)
|
|
21049
|
-
store
|
|
21593
|
+
saveTheme2(store, theme);
|
|
21594
|
+
},
|
|
21595
|
+
effort(store, _state, selected) {
|
|
21596
|
+
const effort = effortLevelSchema.options[selected];
|
|
21597
|
+
if (effort)
|
|
21598
|
+
requestAgent(store, { type: "agent.effort.set.requested", effort });
|
|
21050
21599
|
},
|
|
21051
21600
|
rewind(store, state, selected) {
|
|
21052
21601
|
const userMessageId = listCheckpoints(state)[selected]?.checkpointId;
|
|
@@ -21094,7 +21643,7 @@ var dismissQuestion = (store) => sendAnswers(store, {});
|
|
|
21094
21643
|
|
|
21095
21644
|
// apps/tui/src/input/routeKeys.ts
|
|
21096
21645
|
var createKeyPresses = () => ({ escapeAt: 0, ctrlCAt: 0 });
|
|
21097
|
-
var DELIVERY_KEYS = { q: "queue"
|
|
21646
|
+
var DELIVERY_KEYS = { q: "queue" };
|
|
21098
21647
|
var DOUBLE_ESCAPE_MS = 500;
|
|
21099
21648
|
var EXIT_CONFIRM_MS = 3000;
|
|
21100
21649
|
var EXIT_NOTICE = "Press Ctrl + C again to exit";
|
|
@@ -21439,21 +21988,70 @@ class AppStore {
|
|
|
21439
21988
|
|
|
21440
21989
|
// apps/tui/src/theme/syntaxStyle.ts
|
|
21441
21990
|
import { SyntaxStyle as SyntaxStyle2 } from "@opentui/core";
|
|
21442
|
-
|
|
21443
|
-
|
|
21444
|
-
|
|
21445
|
-
|
|
21446
|
-
|
|
21447
|
-
|
|
21448
|
-
|
|
21449
|
-
|
|
21450
|
-
|
|
21451
|
-
|
|
21452
|
-
|
|
21453
|
-
|
|
21454
|
-
|
|
21455
|
-
|
|
21456
|
-
|
|
21991
|
+
|
|
21992
|
+
// apps/tui/src/theme/syntaxRules.ts
|
|
21993
|
+
var rule = (scope, foreground, style = {}) => ({
|
|
21994
|
+
scope,
|
|
21995
|
+
style: { foreground, ...style }
|
|
21996
|
+
});
|
|
21997
|
+
var buildMutedSyntaxRules = (palette) => buildSyntaxRules(palette).map(({ scope, style }) => ({
|
|
21998
|
+
scope,
|
|
21999
|
+
style: { ...style, foreground: palette.fg.muted }
|
|
22000
|
+
}));
|
|
22001
|
+
var buildSyntaxRules = ({ fg, status, syntax, markdown, diff, bg }) => [
|
|
22002
|
+
rule(["default"], fg.primary),
|
|
22003
|
+
rule(["comment", "comment.documentation"], syntax.comment, { italic: true }),
|
|
22004
|
+
rule(["string", "symbol", "character.special", "character"], syntax.string),
|
|
22005
|
+
rule(["number", "boolean", "constant", "float"], syntax.number),
|
|
22006
|
+
rule(["keyword.return", "keyword.conditional", "keyword.repeat", "keyword.coroutine"], syntax.keyword, {
|
|
22007
|
+
italic: true
|
|
22008
|
+
}),
|
|
22009
|
+
rule(["keyword.type"], syntax.type, { bold: true, italic: true }),
|
|
22010
|
+
rule(["keyword.function", "function.method"], syntax.function),
|
|
22011
|
+
rule(["keyword"], syntax.keyword, { italic: true }),
|
|
22012
|
+
rule(["keyword.import", "string.escape", "string.regexp", "tag.attribute", "keyword.export"], syntax.keyword),
|
|
22013
|
+
rule(["operator", "keyword.operator", "punctuation.delimiter", "keyword.conditional.ternary"], syntax.operator),
|
|
22014
|
+
rule(["variable", "variable.parameter", "function.method.call", "function.call", "property", "parameter", "field"], syntax.variable),
|
|
22015
|
+
rule(["variable.member", "function", "constructor"], syntax.function),
|
|
22016
|
+
rule(["type", "module", "class", "namespace"], syntax.type),
|
|
22017
|
+
rule(["type.definition"], syntax.type, { bold: true }),
|
|
22018
|
+
rule(["punctuation", "punctuation.bracket"], syntax.punctuation),
|
|
22019
|
+
rule(["variable.builtin", "type.builtin", "function.builtin", "module.builtin", "constant.builtin", "variable.super"], status.danger),
|
|
22020
|
+
rule(["keyword.directive", "keyword.modifier", "keyword.exception"], syntax.keyword, { italic: true }),
|
|
22021
|
+
rule(["punctuation.special", "tag.delimiter"], syntax.operator),
|
|
22022
|
+
rule(["markup.heading", "markup.heading.2", "markup.heading.3", "markup.heading.4", "markup.heading.5", "markup.heading.6"], markdown.heading, { bold: true }),
|
|
22023
|
+
rule(["markup.heading.1"], markdown.heading, { bold: true, underline: true }),
|
|
22024
|
+
rule(["markup.bold", "markup.strong"], markdown.strong, { bold: true }),
|
|
22025
|
+
rule(["markup.italic"], markdown.emphasis, { italic: true }),
|
|
22026
|
+
rule(["markup.list"], markdown.listItem),
|
|
22027
|
+
rule(["markup.quote"], markdown.blockQuote, { italic: true }),
|
|
22028
|
+
rule(["markup.raw", "markup.raw.block"], markdown.code),
|
|
22029
|
+
rule(["markup.raw.inline"], markdown.code, { background: bg.surface }),
|
|
22030
|
+
rule(["markup.link", "markup.link.url", "string.special", "string.special.url"], markdown.link, {
|
|
22031
|
+
underline: true
|
|
22032
|
+
}),
|
|
22033
|
+
rule(["markup.link.label"], markdown.linkText, { underline: true }),
|
|
22034
|
+
rule(["label"], markdown.linkText),
|
|
22035
|
+
rule(["spell", "nospell"], fg.primary),
|
|
22036
|
+
rule(["markup.underline"], fg.primary, { underline: true }),
|
|
22037
|
+
rule(["comment.error"], status.danger, { italic: true, bold: true }),
|
|
22038
|
+
rule(["comment.warning"], status.warning, { italic: true, bold: true }),
|
|
22039
|
+
rule(["comment.todo", "comment.note"], status.info, { italic: true, bold: true }),
|
|
22040
|
+
rule(["attribute", "annotation"], status.warning),
|
|
22041
|
+
rule(["tag"], status.danger),
|
|
22042
|
+
rule(["markup.strikethrough", "markup.list.unchecked", "debug"], fg.muted),
|
|
22043
|
+
rule(["markup.list.checked"], status.success),
|
|
22044
|
+
rule(["diff.plus"], diff.addedText, { background: diff.addedBg }),
|
|
22045
|
+
rule(["diff.minus"], diff.removedText, { background: diff.removedBg }),
|
|
22046
|
+
rule(["diff.delta"], diff.contextText, { background: diff.contextBg }),
|
|
22047
|
+
rule(["error"], status.danger, { bold: true }),
|
|
22048
|
+
rule(["warning"], status.warning, { bold: true }),
|
|
22049
|
+
rule(["info"], status.info)
|
|
22050
|
+
];
|
|
22051
|
+
|
|
22052
|
+
// apps/tui/src/theme/syntaxStyle.ts
|
|
22053
|
+
var createSyntaxStyle = (renderer) => SyntaxStyle2.fromTheme(buildSyntaxRules(Theme), renderer.nativeScene);
|
|
22054
|
+
var createMutedSyntaxStyle = (renderer) => SyntaxStyle2.fromTheme(buildMutedSyntaxRules(Theme), renderer.nativeScene);
|
|
21457
22055
|
|
|
21458
22056
|
// apps/tui/src/startTui.ts
|
|
21459
22057
|
var CLOCK_INTERVAL_MS = 100;
|
|
@@ -21463,10 +22061,10 @@ var readShownTheme = ({ theme, ui }) => (ui.picker?.kind === "theme" ? THEME_NAM
|
|
|
21463
22061
|
var readShownBackground = ({ background, ui }) => ui.backgroundEditor?.color ?? background;
|
|
21464
22062
|
async function startTui(client, options = {}) {
|
|
21465
22063
|
const activeRenderer = options.renderer ?? await createCliRenderer({ exitOnCtrlC: false, useMouse: true });
|
|
21466
|
-
activeRenderer.setTerminalTitle("Claudin");
|
|
21467
22064
|
const store = new AppStore(client);
|
|
21468
22065
|
const clipboard = options.clipboard ?? createHostClipboard();
|
|
21469
22066
|
let syntaxStyle = createSyntaxStyle(activeRenderer);
|
|
22067
|
+
let mutedSyntaxStyle = createMutedSyntaxStyle(activeRenderer);
|
|
21470
22068
|
let appliedTheme = readShownTheme(store.state);
|
|
21471
22069
|
let appliedBackground = readShownBackground(store.state);
|
|
21472
22070
|
const header = new HeaderBar(activeRenderer);
|
|
@@ -21475,8 +22073,11 @@ async function startTui(client, options = {}) {
|
|
|
21475
22073
|
const backgroundPanel = new BackgroundPanel(activeRenderer);
|
|
21476
22074
|
const toastView = new ToastView(activeRenderer);
|
|
21477
22075
|
const statusLine = new StatusLine(activeRenderer, () => cancelTurn(store));
|
|
22076
|
+
const taskPanel = new TaskPanel(activeRenderer, (taskId) => stopTask(store, taskId));
|
|
22077
|
+
const promptQueue = new PromptQueueView(activeRenderer);
|
|
21478
22078
|
const scrollback = new ScrollbackView(activeRenderer, {
|
|
21479
22079
|
syntaxStyle,
|
|
22080
|
+
mutedSyntaxStyle,
|
|
21480
22081
|
hooks: {
|
|
21481
22082
|
syntaxStyle,
|
|
21482
22083
|
onDecision: (decision, id) => answerApproval(store, decision, id),
|
|
@@ -21509,7 +22110,7 @@ async function startTui(client, options = {}) {
|
|
|
21509
22110
|
saveDraft(text);
|
|
21510
22111
|
}
|
|
21511
22112
|
});
|
|
21512
|
-
const root = new
|
|
22113
|
+
const root = new BoxRenderable19(activeRenderer, {
|
|
21513
22114
|
width: "100%",
|
|
21514
22115
|
height: "100%",
|
|
21515
22116
|
flexDirection: "column",
|
|
@@ -21520,10 +22121,12 @@ async function startTui(client, options = {}) {
|
|
|
21520
22121
|
scrollback,
|
|
21521
22122
|
diffViewer,
|
|
21522
22123
|
statusLine,
|
|
22124
|
+
promptQueue,
|
|
21523
22125
|
popover,
|
|
21524
22126
|
backgroundPanel,
|
|
21525
22127
|
input,
|
|
21526
|
-
infoBar
|
|
22128
|
+
infoBar,
|
|
22129
|
+
taskPanel
|
|
21527
22130
|
];
|
|
21528
22131
|
for (const part of parts)
|
|
21529
22132
|
root.add(part.renderable);
|
|
@@ -21532,7 +22135,7 @@ async function startTui(client, options = {}) {
|
|
|
21532
22135
|
activeRenderer.on("selection", (selection) => {
|
|
21533
22136
|
copySelection(store, activeRenderer, clipboard, selection);
|
|
21534
22137
|
});
|
|
21535
|
-
for (const part of [header, statusLine, popover, backgroundPanel, input, infoBar]) {
|
|
22138
|
+
for (const part of [header, statusLine, taskPanel, popover, backgroundPanel, input, infoBar]) {
|
|
21536
22139
|
part.renderable.onMouseScroll = ({ scroll }) => {
|
|
21537
22140
|
if (scroll?.direction === "up")
|
|
21538
22141
|
scrollback.scrollByLines(-1);
|
|
@@ -21550,11 +22153,13 @@ async function startTui(client, options = {}) {
|
|
|
21550
22153
|
appliedBackground = shownBackground;
|
|
21551
22154
|
applyTheme(shownTheme, shownBackground);
|
|
21552
22155
|
if (themeChanged) {
|
|
21553
|
-
const previous = syntaxStyle;
|
|
22156
|
+
const previous = [syntaxStyle, mutedSyntaxStyle];
|
|
21554
22157
|
syntaxStyle = createSyntaxStyle(activeRenderer);
|
|
21555
|
-
|
|
22158
|
+
mutedSyntaxStyle = createMutedSyntaxStyle(activeRenderer);
|
|
22159
|
+
scrollback.reset(syntaxStyle, mutedSyntaxStyle);
|
|
21556
22160
|
diffViewer.reset(syntaxStyle);
|
|
21557
|
-
previous
|
|
22161
|
+
for (const style of previous)
|
|
22162
|
+
style.destroy();
|
|
21558
22163
|
}
|
|
21559
22164
|
root.backgroundColor = Theme.bg.default;
|
|
21560
22165
|
input.applyColors();
|
|
@@ -21564,6 +22169,8 @@ async function startTui(client, options = {}) {
|
|
|
21564
22169
|
syncTheme(state);
|
|
21565
22170
|
header.update(state);
|
|
21566
22171
|
statusLine.update(state);
|
|
22172
|
+
taskPanel.update(state);
|
|
22173
|
+
promptQueue.update(state);
|
|
21567
22174
|
toastView.update(state);
|
|
21568
22175
|
infoBar.update(state);
|
|
21569
22176
|
scrollback.update(state);
|
|
@@ -21575,7 +22182,7 @@ async function startTui(client, options = {}) {
|
|
|
21575
22182
|
input.setFocused(inputFocused);
|
|
21576
22183
|
scrollback.setFocused(!inputFocused);
|
|
21577
22184
|
input.setBusy(isStatusBusy(state.status));
|
|
21578
|
-
input.setBorderColor(inputFocused ? Theme.
|
|
22185
|
+
input.setBorderColor(inputFocused ? Theme.fg.muted : Theme.border.separator);
|
|
21579
22186
|
const awaitingId = (findAwaitingCalls(state)[0] ?? findQuestionCalls(state)[0])?.id;
|
|
21580
22187
|
if (awaitingId && awaitingId !== revealedCallId) {
|
|
21581
22188
|
scrollback.revealEntry(findGroupId(state, awaitingId) ?? "");
|
|
@@ -21583,13 +22190,17 @@ async function startTui(client, options = {}) {
|
|
|
21583
22190
|
revealedCallId = awaitingId;
|
|
21584
22191
|
};
|
|
21585
22192
|
store.subscribe(render);
|
|
22193
|
+
store.subscribe(() => sendNextQueuedPrompt(store));
|
|
21586
22194
|
const notifier = new TurnNotifier(activeRenderer);
|
|
21587
22195
|
store.subscribeOwnEvents((event) => {
|
|
21588
22196
|
reactToEvent(store, event);
|
|
21589
22197
|
notifier.notify(event);
|
|
21590
22198
|
if (event.type === "ui.exit.requested")
|
|
21591
22199
|
activeRenderer.destroy();
|
|
22200
|
+
if (event.type === "ui.title.set")
|
|
22201
|
+
activeRenderer.setTerminalTitle(event.title);
|
|
21592
22202
|
});
|
|
22203
|
+
store.emit({ type: "ui.title.set", title: "Claudin" });
|
|
21593
22204
|
const editor = {
|
|
21594
22205
|
read: () => input.text,
|
|
21595
22206
|
replace: (text) => input.replaceText(text, text.length)
|
|
@@ -21611,7 +22222,8 @@ async function startTui(client, options = {}) {
|
|
|
21611
22222
|
key.preventDefault();
|
|
21612
22223
|
});
|
|
21613
22224
|
const clock = setInterval(() => {
|
|
21614
|
-
|
|
22225
|
+
const { status, tasks } = store.state;
|
|
22226
|
+
if (status !== "idle" || tasks.length > 0)
|
|
21615
22227
|
store.emit({ type: "ui.clock.ticked", now: Date.now() });
|
|
21616
22228
|
}, CLOCK_INTERVAL_MS);
|
|
21617
22229
|
let lastRateLimitAt = Date.now();
|