tau-all-agent 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/extensions/answer.ts +111 -118
- package/package.json +5 -1
- package/skills/oracle/scripts/oracle-bundle +82 -34
- package/themes/tau-dark.json +85 -0
package/README.md
CHANGED
package/extensions/answer.ts
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { complete, type Model, type Api, type UserMessage } from "@mariozechner/pi-ai";
|
|
14
|
-
import type { ExtensionAPI
|
|
14
|
+
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
|
15
15
|
import { BorderedLoader } from "@mariozechner/pi-coding-agent";
|
|
16
16
|
import {
|
|
17
17
|
type Component,
|
|
@@ -464,138 +464,131 @@ class QnAComponent implements Component {
|
|
|
464
464
|
}
|
|
465
465
|
|
|
466
466
|
export default function (pi: ExtensionAPI) {
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
467
|
+
pi.registerCommand("answer", {
|
|
468
|
+
description: "Extract questions from last assistant message into interactive Q&A",
|
|
469
|
+
handler: async (_args, ctx) => {
|
|
470
|
+
if (!ctx.hasUI) {
|
|
471
|
+
ctx.ui.notify("answer requires interactive mode", "error");
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
472
474
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
475
|
+
if (!ctx.model) {
|
|
476
|
+
ctx.ui.notify("No model selected", "error");
|
|
477
|
+
return;
|
|
478
|
+
}
|
|
477
479
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
480
|
+
// Find the last assistant message on the current branch
|
|
481
|
+
const branch = ctx.sessionManager.getBranch();
|
|
482
|
+
let lastAssistantText: string | undefined;
|
|
483
|
+
|
|
484
|
+
for (let i = branch.length - 1; i >= 0; i--) {
|
|
485
|
+
const entry = branch[i];
|
|
486
|
+
if (entry.type === "message") {
|
|
487
|
+
const msg = entry.message;
|
|
488
|
+
if ("role" in msg && msg.role === "assistant") {
|
|
489
|
+
if (msg.stopReason !== "stop") {
|
|
490
|
+
ctx.ui.notify(`Last assistant message incomplete (${msg.stopReason})`, "error");
|
|
491
|
+
return;
|
|
492
|
+
}
|
|
493
|
+
const textParts = msg.content
|
|
494
|
+
.filter((c): c is { type: "text"; text: string } => c.type === "text")
|
|
495
|
+
.map((c) => c.text);
|
|
496
|
+
if (textParts.length > 0) {
|
|
497
|
+
lastAssistantText = textParts.join("\n");
|
|
498
|
+
break;
|
|
499
|
+
}
|
|
497
500
|
}
|
|
498
501
|
}
|
|
499
502
|
}
|
|
500
|
-
}
|
|
501
503
|
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
// Select the best model for extraction (prefer a fast model in the current family).
|
|
508
|
-
const extractionSelection = await selectExtractionModel(ctx.model, ctx.modelRegistry);
|
|
509
|
-
if (!extractionSelection) {
|
|
510
|
-
ctx.ui.notify("No configured Pi model is available for question extraction", "error");
|
|
511
|
-
return;
|
|
512
|
-
}
|
|
504
|
+
if (!lastAssistantText) {
|
|
505
|
+
ctx.ui.notify("No assistant messages found", "error");
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
513
508
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
(
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
`Extracting questions using ${extractionSelection.model.id}...`,
|
|
521
|
-
);
|
|
522
|
-
loader.onAbort = () => done(null);
|
|
523
|
-
|
|
524
|
-
const doExtract = async () => {
|
|
525
|
-
const userMessage: UserMessage = {
|
|
526
|
-
role: "user",
|
|
527
|
-
content: [{ type: "text", text: lastAssistantText! }],
|
|
528
|
-
timestamp: Date.now(),
|
|
529
|
-
};
|
|
509
|
+
// Select the best model for extraction (prefer a fast model in the current family).
|
|
510
|
+
const extractionSelection = await selectExtractionModel(ctx.model, ctx.modelRegistry);
|
|
511
|
+
if (!extractionSelection) {
|
|
512
|
+
ctx.ui.notify("No configured Pi model is available for question extraction", "error");
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
530
515
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
},
|
|
516
|
+
// Run extraction with loader UI
|
|
517
|
+
const extractionResult = await ctx.ui.custom<ExtractionResult | null>(
|
|
518
|
+
(tui, theme, _kb, done) => {
|
|
519
|
+
const loader = new BorderedLoader(
|
|
520
|
+
tui,
|
|
521
|
+
theme,
|
|
522
|
+
`Extracting questions using ${extractionSelection.model.id}...`,
|
|
539
523
|
);
|
|
524
|
+
loader.onAbort = () => done(null);
|
|
525
|
+
|
|
526
|
+
const doExtract = async () => {
|
|
527
|
+
const userMessage: UserMessage = {
|
|
528
|
+
role: "user",
|
|
529
|
+
content: [{ type: "text", text: lastAssistantText! }],
|
|
530
|
+
timestamp: Date.now(),
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
const response = await complete(
|
|
534
|
+
extractionSelection.model,
|
|
535
|
+
{ systemPrompt: SYSTEM_PROMPT, messages: [userMessage] },
|
|
536
|
+
{
|
|
537
|
+
apiKey: extractionSelection.apiKey,
|
|
538
|
+
headers: extractionSelection.headers,
|
|
539
|
+
signal: loader.signal,
|
|
540
|
+
},
|
|
541
|
+
);
|
|
542
|
+
|
|
543
|
+
if (response.stopReason === "aborted") {
|
|
544
|
+
return null;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
const responseText = response.content
|
|
548
|
+
.filter((c): c is { type: "text"; text: string } => c.type === "text")
|
|
549
|
+
.map((c) => c.text)
|
|
550
|
+
.join("\n");
|
|
551
|
+
|
|
552
|
+
return parseExtractionResult(responseText);
|
|
553
|
+
};
|
|
540
554
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
const responseText = response.content
|
|
546
|
-
.filter((c): c is { type: "text"; text: string } => c.type === "text")
|
|
547
|
-
.map((c) => c.text)
|
|
548
|
-
.join("\n");
|
|
549
|
-
|
|
550
|
-
return parseExtractionResult(responseText);
|
|
551
|
-
};
|
|
552
|
-
|
|
553
|
-
doExtract()
|
|
554
|
-
.then(done)
|
|
555
|
-
.catch(() => done(null));
|
|
556
|
-
|
|
557
|
-
return loader;
|
|
558
|
-
},
|
|
559
|
-
);
|
|
560
|
-
|
|
561
|
-
if (extractionResult === null) {
|
|
562
|
-
ctx.ui.notify("Cancelled", "info");
|
|
563
|
-
return;
|
|
564
|
-
}
|
|
555
|
+
doExtract()
|
|
556
|
+
.then(done)
|
|
557
|
+
.catch(() => done(null));
|
|
565
558
|
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
}
|
|
559
|
+
return loader;
|
|
560
|
+
},
|
|
561
|
+
);
|
|
570
562
|
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
563
|
+
if (extractionResult === null) {
|
|
564
|
+
ctx.ui.notify("Cancelled", "info");
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
575
567
|
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
568
|
+
if (extractionResult.questions.length === 0) {
|
|
569
|
+
ctx.ui.notify("No questions found in the last message", "info");
|
|
570
|
+
return;
|
|
571
|
+
}
|
|
580
572
|
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
content: "Here are my answers to your questions:\n\n" + answersResult,
|
|
586
|
-
display: true,
|
|
587
|
-
},
|
|
588
|
-
{ triggerTurn: true },
|
|
589
|
-
);
|
|
590
|
-
};
|
|
573
|
+
// Show the Q&A component
|
|
574
|
+
const answersResult = await ctx.ui.custom<string | null>((tui, _theme, _kb, done) => {
|
|
575
|
+
return new QnAComponent(extractionResult.questions, tui, done);
|
|
576
|
+
});
|
|
591
577
|
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
578
|
+
if (answersResult === null) {
|
|
579
|
+
ctx.ui.notify("Cancelled", "info");
|
|
580
|
+
return;
|
|
581
|
+
}
|
|
596
582
|
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
583
|
+
// Send the answers directly as a message and trigger a turn
|
|
584
|
+
pi.sendMessage(
|
|
585
|
+
{
|
|
586
|
+
customType: "answers",
|
|
587
|
+
content: "Here are my answers to your questions:\n\n" + answersResult,
|
|
588
|
+
display: true,
|
|
589
|
+
},
|
|
590
|
+
{ triggerTurn: true },
|
|
591
|
+
);
|
|
592
|
+
},
|
|
600
593
|
});
|
|
601
594
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tau-all-agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Full Tau distribution for Pi",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-extension",
|
|
@@ -65,11 +65,15 @@
|
|
|
65
65
|
"skills/web-design",
|
|
66
66
|
"skills/homeassistant-ops",
|
|
67
67
|
"skills/openscad"
|
|
68
|
+
],
|
|
69
|
+
"themes": [
|
|
70
|
+
"themes/tau-dark.json"
|
|
68
71
|
]
|
|
69
72
|
},
|
|
70
73
|
"files": [
|
|
71
74
|
"extensions",
|
|
72
75
|
"skills",
|
|
76
|
+
"themes",
|
|
73
77
|
"README.md",
|
|
74
78
|
"LICENSE"
|
|
75
79
|
]
|
|
@@ -130,10 +130,31 @@ done
|
|
|
130
130
|
|
|
131
131
|
include_patterns=()
|
|
132
132
|
exclude_patterns=()
|
|
133
|
+
explicit_files=()
|
|
134
|
+
|
|
135
|
+
add_pattern() {
|
|
136
|
+
local is_exclude="$1"
|
|
137
|
+
local pattern="$2"
|
|
138
|
+
if [[ "$is_exclude" -eq 1 ]]; then
|
|
139
|
+
exclude_patterns+=("$pattern")
|
|
140
|
+
else
|
|
141
|
+
include_patterns+=("$pattern")
|
|
142
|
+
fi
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
add_exact_file() {
|
|
146
|
+
local is_exclude="$1"
|
|
147
|
+
local file="$2"
|
|
148
|
+
if [[ "$is_exclude" -eq 1 ]]; then
|
|
149
|
+
exclude_patterns+=("$file")
|
|
150
|
+
else
|
|
151
|
+
explicit_files+=("$file")
|
|
152
|
+
fi
|
|
153
|
+
}
|
|
133
154
|
|
|
134
155
|
for sel in "${selectors[@]}"; do
|
|
135
156
|
is_exclude=0
|
|
136
|
-
if [[ "$sel" ==
|
|
157
|
+
if [[ "${sel:0:1}" == "!" ]]; then
|
|
137
158
|
is_exclude=1
|
|
138
159
|
sel="${sel:1}"
|
|
139
160
|
fi
|
|
@@ -148,69 +169,96 @@ for sel in "${selectors[@]}"; do
|
|
|
148
169
|
if [[ "$sel" == "${ROOT_DIR}/"* ]]; then
|
|
149
170
|
sel="${sel#"${ROOT_DIR}/"}"
|
|
150
171
|
else
|
|
151
|
-
|
|
152
|
-
|
|
172
|
+
if [[ "$is_exclude" -eq 1 ]]; then
|
|
173
|
+
add_pattern "$is_exclude" "$sel"
|
|
174
|
+
continue
|
|
175
|
+
fi
|
|
176
|
+
if [[ ! -f "$sel" ]]; then
|
|
177
|
+
echo "error: absolute paths outside repo must name an existing file: ${sel}" >&2
|
|
178
|
+
exit 2
|
|
179
|
+
fi
|
|
180
|
+
add_exact_file "$is_exclude" "$sel"
|
|
181
|
+
continue
|
|
153
182
|
fi
|
|
154
183
|
fi
|
|
155
184
|
|
|
156
|
-
|
|
157
|
-
|
|
185
|
+
sel="${sel#./}"
|
|
186
|
+
|
|
187
|
+
if [[ -f "$sel" ]]; then
|
|
188
|
+
add_exact_file "$is_exclude" "$sel"
|
|
189
|
+
continue
|
|
158
190
|
fi
|
|
159
191
|
|
|
160
|
-
if [[
|
|
161
|
-
|
|
162
|
-
else
|
|
163
|
-
include_patterns+=("$sel")
|
|
192
|
+
if [[ -d "$sel" ]] && ! has_glob_chars "$sel"; then
|
|
193
|
+
sel="${sel}/**"
|
|
164
194
|
fi
|
|
195
|
+
|
|
196
|
+
add_pattern "$is_exclude" "$sel"
|
|
165
197
|
done
|
|
166
198
|
|
|
167
|
-
if [[ "${#include_patterns[@]}" -eq 0 ]]; then
|
|
199
|
+
if [[ "${#include_patterns[@]}" -eq 0 && "${#explicit_files[@]}" -eq 0 ]]; then
|
|
168
200
|
echo "error: no include patterns provided (need at least one non-! --file)" >&2
|
|
169
201
|
exit 2
|
|
170
202
|
fi
|
|
171
203
|
|
|
172
204
|
all_files=()
|
|
173
|
-
if
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
205
|
+
if [[ "${#include_patterns[@]}" -gt 0 ]]; then
|
|
206
|
+
if git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
207
|
+
while IFS= read -r f; do
|
|
208
|
+
[[ -n "$f" ]] && all_files+=("$f")
|
|
209
|
+
done < <(git ls-files -co --exclude-standard)
|
|
210
|
+
else
|
|
211
|
+
while IFS= read -r f; do
|
|
212
|
+
f="${f#./}"
|
|
213
|
+
[[ -n "$f" ]] && all_files+=("$f")
|
|
214
|
+
done < <(find . -type f -print)
|
|
215
|
+
fi
|
|
182
216
|
fi
|
|
183
217
|
|
|
184
218
|
selected=()
|
|
185
219
|
skipped=()
|
|
186
220
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
221
|
+
select_file() {
|
|
222
|
+
local file="$1"
|
|
223
|
+
local size=""
|
|
190
224
|
|
|
191
|
-
|
|
192
|
-
continue
|
|
193
|
-
fi
|
|
225
|
+
[[ -z "$file" ]] && return 0
|
|
194
226
|
|
|
195
|
-
if [[ "${#exclude_patterns[@]}" -gt 0 ]] && matches_any_pattern "$
|
|
196
|
-
|
|
227
|
+
if [[ "${#exclude_patterns[@]}" -gt 0 ]] && matches_any_pattern "$file" "${exclude_patterns[@]}"; then
|
|
228
|
+
return 0
|
|
197
229
|
fi
|
|
198
230
|
|
|
199
|
-
if [[ ! -f "$
|
|
200
|
-
|
|
231
|
+
if [[ ! -f "$file" ]]; then
|
|
232
|
+
return 0
|
|
201
233
|
fi
|
|
202
234
|
|
|
203
|
-
size="$(file_size_bytes "$
|
|
235
|
+
size="$(file_size_bytes "$file")"
|
|
204
236
|
if [[ "$size" -gt "$MAX_BYTES" ]]; then
|
|
205
|
-
skipped+=("${
|
|
237
|
+
skipped+=("${file} (too large: ${size} bytes)")
|
|
238
|
+
return 0
|
|
239
|
+
fi
|
|
240
|
+
|
|
241
|
+
selected+=("$file")
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
for file in "${explicit_files[@]}"; do
|
|
245
|
+
select_file "$file"
|
|
246
|
+
done
|
|
247
|
+
|
|
248
|
+
for rel in "${all_files[@]}"; do
|
|
249
|
+
[[ -z "$rel" ]] && continue
|
|
250
|
+
|
|
251
|
+
path_has_ignored_dir "$rel" && continue
|
|
252
|
+
|
|
253
|
+
if ! matches_any_pattern "$rel" "${include_patterns[@]}"; then
|
|
206
254
|
continue
|
|
207
255
|
fi
|
|
208
256
|
|
|
209
|
-
|
|
257
|
+
select_file "$rel"
|
|
210
258
|
done
|
|
211
259
|
|
|
212
260
|
if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
213
|
-
printf '%s\n' "${selected[@]}" | LC_ALL=C sort
|
|
261
|
+
printf '%s\n' "${selected[@]}" | LC_ALL=C sort -u
|
|
214
262
|
if [[ "${#skipped[@]}" -gt 0 ]]; then
|
|
215
263
|
printf '\nSkipped:\n' >&2
|
|
216
264
|
printf '%s\n' "${skipped[@]}" >&2
|
|
@@ -219,7 +267,7 @@ if [[ "$DRY_RUN" -eq 1 ]]; then
|
|
|
219
267
|
fi
|
|
220
268
|
|
|
221
269
|
printf '# Task\n\n%s\n\n# Files\n' "$(trim "$PROMPT")"
|
|
222
|
-
printf '%s\n' "${selected[@]}" | LC_ALL=C sort | while IFS= read -r rel; do
|
|
270
|
+
printf '%s\n' "${selected[@]}" | LC_ALL=C sort -u | while IFS= read -r rel; do
|
|
223
271
|
[[ -z "$rel" ]] && continue
|
|
224
272
|
printf '\n## %s\n\n```\n' "$rel"
|
|
225
273
|
cat "$rel"
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://raw.githubusercontent.com/badlogic/pi-mono/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
|
|
3
|
+
"name": "tau-dark",
|
|
4
|
+
"vars": {
|
|
5
|
+
"accent": "#8abeb7",
|
|
6
|
+
"blue": "#5f87af",
|
|
7
|
+
"green": "#b5bd68",
|
|
8
|
+
"red": "#cc6666",
|
|
9
|
+
"yellow": "#f0c674",
|
|
10
|
+
"gray": "#808080",
|
|
11
|
+
"dimGray": "#666666",
|
|
12
|
+
"darkGray": "#505050",
|
|
13
|
+
"heading": "#DCDCAA",
|
|
14
|
+
"selectedBg": "#3a3a4a",
|
|
15
|
+
"userMsgBg": "#343541",
|
|
16
|
+
"toolPendingBg": "#282832",
|
|
17
|
+
"toolSuccessBg": "#283228",
|
|
18
|
+
"toolErrorBg": "#3c2828",
|
|
19
|
+
"customMsgBg": "#2d2838"
|
|
20
|
+
},
|
|
21
|
+
"colors": {
|
|
22
|
+
"accent": "accent",
|
|
23
|
+
"border": "blue",
|
|
24
|
+
"borderAccent": "accent",
|
|
25
|
+
"borderMuted": "darkGray",
|
|
26
|
+
"success": "green",
|
|
27
|
+
"error": "red",
|
|
28
|
+
"warning": "yellow",
|
|
29
|
+
"muted": "gray",
|
|
30
|
+
"dim": "dimGray",
|
|
31
|
+
"text": "",
|
|
32
|
+
"thinkingText": "gray",
|
|
33
|
+
|
|
34
|
+
"selectedBg": "selectedBg",
|
|
35
|
+
"userMessageBg": "userMsgBg",
|
|
36
|
+
"userMessageText": "",
|
|
37
|
+
"customMessageBg": "customMsgBg",
|
|
38
|
+
"customMessageText": "",
|
|
39
|
+
"customMessageLabel": "#9575cd",
|
|
40
|
+
"toolPendingBg": "toolPendingBg",
|
|
41
|
+
"toolSuccessBg": "toolSuccessBg",
|
|
42
|
+
"toolErrorBg": "toolErrorBg",
|
|
43
|
+
"toolTitle": "",
|
|
44
|
+
"toolOutput": "gray",
|
|
45
|
+
|
|
46
|
+
"mdHeading": "heading",
|
|
47
|
+
"mdLink": "#81a2be",
|
|
48
|
+
"mdLinkUrl": "dimGray",
|
|
49
|
+
"mdCode": "accent",
|
|
50
|
+
"mdCodeBlock": "green",
|
|
51
|
+
"mdCodeBlockBorder": "gray",
|
|
52
|
+
"mdQuote": "gray",
|
|
53
|
+
"mdQuoteBorder": "gray",
|
|
54
|
+
"mdHr": "gray",
|
|
55
|
+
"mdListBullet": "accent",
|
|
56
|
+
|
|
57
|
+
"toolDiffAdded": "green",
|
|
58
|
+
"toolDiffRemoved": "red",
|
|
59
|
+
"toolDiffContext": "gray",
|
|
60
|
+
|
|
61
|
+
"syntaxComment": "#6A9955",
|
|
62
|
+
"syntaxKeyword": "#569CD6",
|
|
63
|
+
"syntaxFunction": "#DCDCAA",
|
|
64
|
+
"syntaxVariable": "#9CDCFE",
|
|
65
|
+
"syntaxString": "#CE9178",
|
|
66
|
+
"syntaxNumber": "#B5CEA8",
|
|
67
|
+
"syntaxType": "#4EC9B0",
|
|
68
|
+
"syntaxOperator": "#D4D4D4",
|
|
69
|
+
"syntaxPunctuation": "#D4D4D4",
|
|
70
|
+
|
|
71
|
+
"thinkingOff": "darkGray",
|
|
72
|
+
"thinkingMinimal": "dimGray",
|
|
73
|
+
"thinkingLow": "#657B83",
|
|
74
|
+
"thinkingMedium": "#6f9bb3",
|
|
75
|
+
"thinkingHigh": "#78a8a1",
|
|
76
|
+
"thinkingXhigh": "accent",
|
|
77
|
+
|
|
78
|
+
"bashMode": "green"
|
|
79
|
+
},
|
|
80
|
+
"export": {
|
|
81
|
+
"pageBg": "#18181e",
|
|
82
|
+
"cardBg": "#1e1e24",
|
|
83
|
+
"infoBg": "#3c3728"
|
|
84
|
+
}
|
|
85
|
+
}
|