scream-code 0.9.2 → 0.9.4
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 +12 -12
- package/dist/{app-Ir0w8ElF.mjs → app-D7S2yEaM.mjs} +336 -426
- package/dist/main.mjs +1 -1
- package/icon.ico +0 -0
- package/package.json +1 -2
|
@@ -46,9 +46,9 @@ import { lookup } from "node:dns/promises";
|
|
|
46
46
|
import { isIP } from "node:net";
|
|
47
47
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
48
48
|
import { Command, Option } from "commander";
|
|
49
|
-
import { CombinedAutocompleteProvider, Container, Editor, Image, Input, Key, Markdown, ProcessTerminal, Spacer, TUI, Text, decodeKittyPrintable, deleteAllKittyImages, fuzzyFilter, fuzzyMatch, getCapabilities, getImageDimensions, isKeyRelease, matchesKey, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
50
|
-
import chalk, { chalkStderr } from "chalk";
|
|
51
49
|
import { createInterface } from "node:readline/promises";
|
|
50
|
+
import chalk, { chalkStderr } from "chalk";
|
|
51
|
+
import { CombinedAutocompleteProvider, Container, Editor, Image, Input, Key, Markdown, ProcessTerminal, Spacer, TUI, Text, decodeKittyPrintable, deleteAllKittyImages, fuzzyFilter, fuzzyMatch, getCapabilities, getImageDimensions, isKeyRelease, matchesKey, truncateToWidth, visibleWidth, wrapTextWithAnsi } from "@earendil-works/pi-tui";
|
|
52
52
|
import { highlight, supportsLanguage } from "cli-highlight";
|
|
53
53
|
import { diffWords } from "diff";
|
|
54
54
|
import { promisify } from "node:util";
|
|
@@ -81345,10 +81345,10 @@ function blockDecision(event, results) {
|
|
|
81345
81345
|
}
|
|
81346
81346
|
function toHookInputData(input) {
|
|
81347
81347
|
const result = {};
|
|
81348
|
-
for (const [key, value] of Object.entries(input)) result[camelToSnake$
|
|
81348
|
+
for (const [key, value] of Object.entries(input)) result[camelToSnake$1(key)] = value;
|
|
81349
81349
|
return result;
|
|
81350
81350
|
}
|
|
81351
|
-
function camelToSnake$
|
|
81351
|
+
function camelToSnake$1(value) {
|
|
81352
81352
|
return value.replaceAll(/[A-Z]/g, (ch) => `_${ch.toLowerCase()}`);
|
|
81353
81353
|
}
|
|
81354
81354
|
//#endregion
|
|
@@ -99668,7 +99668,7 @@ function rawThinking(config) {
|
|
|
99668
99668
|
function snakeToCamel(str) {
|
|
99669
99669
|
return str.replaceAll(/_([a-z])/g, (_, ch) => ch.toUpperCase());
|
|
99670
99670
|
}
|
|
99671
|
-
function camelToSnake
|
|
99671
|
+
function camelToSnake(str) {
|
|
99672
99672
|
return str.replaceAll(/[A-Z]/g, (ch) => `_${ch.toLowerCase()}`);
|
|
99673
99673
|
}
|
|
99674
99674
|
const DEFAULT_CONFIG_FILE_TEXT = `# ~/.scream-code/config.toml
|
|
@@ -99835,7 +99835,7 @@ function configToTomlData(config) {
|
|
|
99835
99835
|
"defaultPlanMode",
|
|
99836
99836
|
"mergeAllAvailableSkills",
|
|
99837
99837
|
"extraSkillDirs"
|
|
99838
|
-
]) setDefined(out, camelToSnake
|
|
99838
|
+
]) setDefined(out, camelToSnake(key), config[key]);
|
|
99839
99839
|
setRecordSection(out, "providers", config.providers, providerToToml);
|
|
99840
99840
|
setRecordSection(out, "models", config.models, modelToToml);
|
|
99841
99841
|
setSection(out, "thinking", config.thinking, thinkingToToml);
|
|
@@ -99868,20 +99868,20 @@ function setSection(out, snakeKey, value, toToml) {
|
|
|
99868
99868
|
}
|
|
99869
99869
|
function providerToToml(provider, rawProvider) {
|
|
99870
99870
|
const out = cloneRecord(rawProvider);
|
|
99871
|
-
for (const [key, value] of Object.entries(provider)) if (key === "oauth" && value !== void 0) out[camelToSnake
|
|
99872
|
-
else if ((key === "env" || key === "customHeaders") && value !== void 0) out[camelToSnake
|
|
99873
|
-
else setDefined(out, camelToSnake
|
|
99871
|
+
for (const [key, value] of Object.entries(provider)) if (key === "oauth" && value !== void 0) out[camelToSnake(key)] = oauthToToml(value);
|
|
99872
|
+
else if ((key === "env" || key === "customHeaders") && value !== void 0) out[camelToSnake(key)] = cloneUnknown(value);
|
|
99873
|
+
else setDefined(out, camelToSnake(key), value);
|
|
99874
99874
|
return out;
|
|
99875
99875
|
}
|
|
99876
99876
|
function modelToToml(model, rawModel) {
|
|
99877
99877
|
const out = cloneRecord(rawModel);
|
|
99878
|
-
for (const [key, value] of Object.entries(model)) if (key === "capabilities" && Array.isArray(value)) out[camelToSnake
|
|
99879
|
-
else setDefined(out, camelToSnake
|
|
99878
|
+
for (const [key, value] of Object.entries(model)) if (key === "capabilities" && Array.isArray(value)) out[camelToSnake(key)] = [...value];
|
|
99879
|
+
else setDefined(out, camelToSnake(key), value);
|
|
99880
99880
|
return out;
|
|
99881
99881
|
}
|
|
99882
99882
|
function thinkingToToml(thinking, rawThinking) {
|
|
99883
99883
|
const out = cloneRecord(rawThinking);
|
|
99884
|
-
for (const [key, value] of Object.entries(thinking)) setDefined(out, camelToSnake
|
|
99884
|
+
for (const [key, value] of Object.entries(thinking)) setDefined(out, camelToSnake(key), value);
|
|
99885
99885
|
return out;
|
|
99886
99886
|
}
|
|
99887
99887
|
function permissionToToml(permission, rawPermission) {
|
|
@@ -99895,7 +99895,7 @@ function permissionToToml(permission, rawPermission) {
|
|
|
99895
99895
|
}
|
|
99896
99896
|
function permissionRuleToToml(rule) {
|
|
99897
99897
|
const out = {};
|
|
99898
|
-
for (const [key, value] of Object.entries(rule)) setDefined(out, camelToSnake
|
|
99898
|
+
for (const [key, value] of Object.entries(rule)) setDefined(out, camelToSnake(key), value);
|
|
99899
99899
|
return out;
|
|
99900
99900
|
}
|
|
99901
99901
|
function servicesToToml(services, rawServices) {
|
|
@@ -99908,19 +99908,19 @@ function servicesToToml(services, rawServices) {
|
|
|
99908
99908
|
}
|
|
99909
99909
|
function serviceToToml(service) {
|
|
99910
99910
|
const out = {};
|
|
99911
|
-
for (const [key, value] of Object.entries(service)) if (key === "oauth" && value !== void 0) out[camelToSnake
|
|
99912
|
-
else if (key === "customHeaders" && value !== void 0) out[camelToSnake
|
|
99913
|
-
else setDefined(out, camelToSnake
|
|
99911
|
+
for (const [key, value] of Object.entries(service)) if (key === "oauth" && value !== void 0) out[camelToSnake(key)] = oauthToToml(value);
|
|
99912
|
+
else if (key === "customHeaders" && value !== void 0) out[camelToSnake(key)] = cloneUnknown(value);
|
|
99913
|
+
else setDefined(out, camelToSnake(key), value);
|
|
99914
99914
|
return out;
|
|
99915
99915
|
}
|
|
99916
99916
|
function loopControlToToml(loopControl, rawLoopControl) {
|
|
99917
99917
|
const out = cloneRecord(rawLoopControl);
|
|
99918
|
-
for (const [key, value] of Object.entries(loopControl)) setDefined(out, camelToSnake
|
|
99918
|
+
for (const [key, value] of Object.entries(loopControl)) setDefined(out, camelToSnake(key), value);
|
|
99919
99919
|
return out;
|
|
99920
99920
|
}
|
|
99921
99921
|
function backgroundToToml(background, rawBackground) {
|
|
99922
99922
|
const out = cloneRecord(rawBackground);
|
|
99923
|
-
for (const [key, value] of Object.entries(background)) setDefined(out, camelToSnake
|
|
99923
|
+
for (const [key, value] of Object.entries(background)) setDefined(out, camelToSnake(key), value);
|
|
99924
99924
|
return out;
|
|
99925
99925
|
}
|
|
99926
99926
|
function setHooks(out, hooks) {
|
|
@@ -99932,12 +99932,12 @@ function setHooks(out, hooks) {
|
|
|
99932
99932
|
}
|
|
99933
99933
|
function hookToToml(hook) {
|
|
99934
99934
|
const out = {};
|
|
99935
|
-
for (const [key, value] of Object.entries(hook)) setDefined(out, camelToSnake
|
|
99935
|
+
for (const [key, value] of Object.entries(hook)) setDefined(out, camelToSnake(key), value);
|
|
99936
99936
|
return out;
|
|
99937
99937
|
}
|
|
99938
99938
|
function oauthToToml(oauth) {
|
|
99939
99939
|
const out = {};
|
|
99940
|
-
for (const [key, value] of Object.entries(oauth)) out[camelToSnake
|
|
99940
|
+
for (const [key, value] of Object.entries(oauth)) out[camelToSnake(key)] = value;
|
|
99941
99941
|
return out;
|
|
99942
99942
|
}
|
|
99943
99943
|
function isPlainObject$1(value) {
|
|
@@ -119240,25 +119240,6 @@ const SessionSummaryStateSchema = z.object({
|
|
|
119240
119240
|
title: z.string().optional(),
|
|
119241
119241
|
custom: z.record(z.string(), z.unknown()).optional()
|
|
119242
119242
|
});
|
|
119243
|
-
const CcConnectHistoryEntrySchema = z.object({
|
|
119244
|
-
role: z.string(),
|
|
119245
|
-
content: z.string(),
|
|
119246
|
-
timestamp: z.string().optional()
|
|
119247
|
-
});
|
|
119248
|
-
const CcConnectSessionSchema = z.object({
|
|
119249
|
-
id: z.string(),
|
|
119250
|
-
name: z.string().optional(),
|
|
119251
|
-
agent_session_id: z.string().optional(),
|
|
119252
|
-
agent_type: z.string().optional(),
|
|
119253
|
-
history: z.array(CcConnectHistoryEntrySchema).nullable().optional(),
|
|
119254
|
-
created_at: z.string().optional(),
|
|
119255
|
-
updated_at: z.string().optional()
|
|
119256
|
-
});
|
|
119257
|
-
const CcConnectSnapshotSchema = z.object({
|
|
119258
|
-
sessions: z.record(z.string(), CcConnectSessionSchema).optional(),
|
|
119259
|
-
active_session: z.record(z.string(), z.string()).optional(),
|
|
119260
|
-
version: z.number().optional()
|
|
119261
|
-
});
|
|
119262
119243
|
var SessionStore = class {
|
|
119263
119244
|
homeDir;
|
|
119264
119245
|
sessionsDir;
|
|
@@ -119403,17 +119384,11 @@ var SessionStore = class {
|
|
|
119403
119384
|
async listAll() {
|
|
119404
119385
|
const index = await readSessionIndex(this.homeDir, this.sessionsDir);
|
|
119405
119386
|
const sessions = [];
|
|
119406
|
-
const seenAgentIds = /* @__PURE__ */ new Set();
|
|
119407
119387
|
for (const entry of index.values()) {
|
|
119408
119388
|
if (!await isDirectory(entry.sessionDir)) continue;
|
|
119409
119389
|
const summary = await this.summaryFromDir(entry.sessionId, entry.sessionDir, entry.workDir);
|
|
119410
119390
|
sessions.push(summary);
|
|
119411
|
-
seenAgentIds.add(entry.sessionId);
|
|
119412
119391
|
}
|
|
119413
|
-
try {
|
|
119414
|
-
const ccSessions = await listCcConnectSessions(seenAgentIds);
|
|
119415
|
-
sessions.push(...ccSessions);
|
|
119416
|
-
} catch {}
|
|
119417
119392
|
sessions.sort(compareSessionSummary);
|
|
119418
119393
|
return sessions;
|
|
119419
119394
|
}
|
|
@@ -119587,90 +119562,6 @@ function compareSessionSummary(a, b) {
|
|
|
119587
119562
|
if (a.id > b.id) return 1;
|
|
119588
119563
|
return 0;
|
|
119589
119564
|
}
|
|
119590
|
-
const CC_CONNECT_SESSIONS_DIR = join$1(homedir(), ".cc-connect", "sessions");
|
|
119591
|
-
/**
|
|
119592
|
-
* Scan `~/.cc-connect/sessions/*.json` and return ScreamCode-compatible
|
|
119593
|
-
* SessionSummary entries for every cc-connect session that has a
|
|
119594
|
-
* non-empty agent_session_id (i.e. can actually be resumed).
|
|
119595
|
-
*
|
|
119596
|
-
* Sessions whose `agent_session_id` already appears in `seenAgentIds` are
|
|
119597
|
-
* skipped — the native ScreamCode session takes precedence.
|
|
119598
|
-
*/
|
|
119599
|
-
async function listCcConnectSessions(seenAgentIds) {
|
|
119600
|
-
let entries;
|
|
119601
|
-
try {
|
|
119602
|
-
entries = await readdir(CC_CONNECT_SESSIONS_DIR);
|
|
119603
|
-
} catch {
|
|
119604
|
-
return [];
|
|
119605
|
-
}
|
|
119606
|
-
const results = [];
|
|
119607
|
-
for (const name of entries) {
|
|
119608
|
-
if (!name.endsWith(".json")) continue;
|
|
119609
|
-
const projectName = name.slice(0, -5);
|
|
119610
|
-
const parsed = await readCcConnectSnapshot(join$1(CC_CONNECT_SESSIONS_DIR, name));
|
|
119611
|
-
if (parsed === void 0) continue;
|
|
119612
|
-
for (const [, ccSession] of Object.entries(parsed.sessions ?? {})) {
|
|
119613
|
-
const agentId = ccSession.agent_session_id?.trim();
|
|
119614
|
-
if (!agentId || agentId.length === 0) continue;
|
|
119615
|
-
if (seenAgentIds.has(agentId)) continue;
|
|
119616
|
-
const summary = ccSessionToSummary(ccSession, agentId, projectName);
|
|
119617
|
-
if (summary !== void 0) {
|
|
119618
|
-
results.push(summary);
|
|
119619
|
-
seenAgentIds.add(agentId);
|
|
119620
|
-
}
|
|
119621
|
-
}
|
|
119622
|
-
}
|
|
119623
|
-
return results;
|
|
119624
|
-
}
|
|
119625
|
-
async function readCcConnectSnapshot(filePath) {
|
|
119626
|
-
try {
|
|
119627
|
-
const raw = await readFile(filePath, "utf-8");
|
|
119628
|
-
const parsed = JSON.parse(raw);
|
|
119629
|
-
const result = CcConnectSnapshotSchema.safeParse(parsed);
|
|
119630
|
-
return result.success ? result.data : void 0;
|
|
119631
|
-
} catch {
|
|
119632
|
-
return;
|
|
119633
|
-
}
|
|
119634
|
-
}
|
|
119635
|
-
/** Extract the last user-message content for a preview in the picker. */
|
|
119636
|
-
function lastPromptFromCcHistory(history) {
|
|
119637
|
-
if (!history || history.length === 0) return void 0;
|
|
119638
|
-
for (let i = history.length - 1; i >= 0; i--) {
|
|
119639
|
-
const entry = history[i];
|
|
119640
|
-
if (entry && entry.role === "user" && entry.content?.trim().length > 0) return entry.content.trim();
|
|
119641
|
-
}
|
|
119642
|
-
}
|
|
119643
|
-
function ccSessionToSummary(cc, agentSessionId, projectName) {
|
|
119644
|
-
const id = `cc:${projectName}/${cc.id}`;
|
|
119645
|
-
const createdAt = parseCcTimestamp(cc.created_at);
|
|
119646
|
-
const updatedAt = parseCcTimestamp(cc.updated_at) ?? createdAt;
|
|
119647
|
-
if (createdAt === void 0 && updatedAt === void 0) return void 0;
|
|
119648
|
-
const title = cc.name?.trim() ?? cc.id;
|
|
119649
|
-
const lastPrompt = lastPromptFromCcHistory(cc.history);
|
|
119650
|
-
const metadata = {
|
|
119651
|
-
source: "cc-connect",
|
|
119652
|
-
agentSessionId,
|
|
119653
|
-
ccProject: projectName,
|
|
119654
|
-
ccSessionId: cc.id
|
|
119655
|
-
};
|
|
119656
|
-
if (cc.agent_type) metadata["agentType"] = cc.agent_type;
|
|
119657
|
-
return {
|
|
119658
|
-
id,
|
|
119659
|
-
workDir: homedir(),
|
|
119660
|
-
sessionDir: "",
|
|
119661
|
-
createdAt: createdAt ?? updatedAt,
|
|
119662
|
-
updatedAt: updatedAt ?? createdAt,
|
|
119663
|
-
title: title.length > 0 ? title : void 0,
|
|
119664
|
-
lastPrompt,
|
|
119665
|
-
metadata
|
|
119666
|
-
};
|
|
119667
|
-
}
|
|
119668
|
-
/** Parse an ISO-8601 timestamp with optional timezone offset to epoch ms. */
|
|
119669
|
-
function parseCcTimestamp(value) {
|
|
119670
|
-
if (!value) return void 0;
|
|
119671
|
-
const ms = Date.parse(value);
|
|
119672
|
-
return Number.isFinite(ms) ? ms : void 0;
|
|
119673
|
-
}
|
|
119674
119565
|
//#endregion
|
|
119675
119566
|
//#region ../../packages/jian/src/errors.ts
|
|
119676
119567
|
/**
|
|
@@ -121652,6 +121543,7 @@ const dictionaries = {
|
|
|
121652
121543
|
"session.title": "会话",
|
|
121653
121544
|
"session.loading": "正在加载会话...",
|
|
121654
121545
|
"session_picker.empty": "未找到会话。按 Escape 关闭。",
|
|
121546
|
+
"session_picker.cc_restricted": "CC专属会话不支持切换或删除,请点击或复制下方文件路径进入手动管理",
|
|
121655
121547
|
"session.picker_title": "会话 ",
|
|
121656
121548
|
"session.delete_confirm": "⚠️ 按 Enter 确认删除,Esc 取消",
|
|
121657
121549
|
"session.picker_hint": "(↑↓ 导航,Enter 选择,d 删除,Esc 取消)",
|
|
@@ -121767,7 +121659,7 @@ const dictionaries = {
|
|
|
121767
121659
|
"skill.skill_removed": "该 Skill 及其子 Skill 已从当前会话中移除。",
|
|
121768
121660
|
"skill.delete_failed": "删除失败。",
|
|
121769
121661
|
"skill.delete_failed_msg": "删除失败: {msg}",
|
|
121770
|
-
"skill.confirm_uninstall": "确认卸载",
|
|
121662
|
+
"skill.confirm_uninstall": "确认卸载 \"{label}\"?",
|
|
121771
121663
|
"skill.uninstall_reversible": "卸载后可在 Skill 中心重新安装",
|
|
121772
121664
|
"skill.uninstall_yes": "是,卸载",
|
|
121773
121665
|
"toolcall.bg_agent_lost": "后台 agent 丢失(会话在完成前已重启)",
|
|
@@ -122139,8 +122031,6 @@ const dictionaries = {
|
|
|
122139
122031
|
"market.design_card_desc": "14 种设计卡片生成(封面/图文/社交分享/长篇排版),Parchment × Swiss 双风格体系",
|
|
122140
122032
|
"market.superpowers_name": "Superpowers 开发技能包",
|
|
122141
122033
|
"market.superpowers_desc": "14 个开发方法论技能:TDD、系统调试、代码审查、子代理驱动开发、并行代理、头脑风暴等",
|
|
122142
|
-
"market.audio_name": "Audio Skill 录音分析",
|
|
122143
|
-
"market.audio_desc": "本地录音分析自动化,含 RAG 知识库。适用于销售录音复盘、会议纪要、质量评分等",
|
|
122144
122034
|
"market.scrapling_name": "Scrapling 网页爬取",
|
|
122145
122035
|
"market.scrapling_desc": "基于 Scrapling 的智能爬虫技能,支持 Cloudflare/WAF 绕过、登录会话、自动抓取解析",
|
|
122146
122036
|
"market.astock_name": "A 股数据分析",
|
|
@@ -122728,6 +122618,7 @@ const dictionaries = {
|
|
|
122728
122618
|
"session.title": "Sessions",
|
|
122729
122619
|
"session.loading": "Loading sessions...",
|
|
122730
122620
|
"session_picker.empty": "No sessions found. Press Escape to close.",
|
|
122621
|
+
"session_picker.cc_restricted": "CC sessions cannot be switched or deleted. Use the file path below to manage manually",
|
|
122731
122622
|
"session.picker_title": "Sessions ",
|
|
122732
122623
|
"session.delete_confirm": "⚠️ Press Enter to confirm delete, Esc to cancel",
|
|
122733
122624
|
"session.picker_hint": "(↑↓ Navigate, Enter Select, d Delete, Esc Cancel)",
|
|
@@ -122843,7 +122734,7 @@ const dictionaries = {
|
|
|
122843
122734
|
"skill.skill_removed": "This skill and its sub-skills have been removed from the current session.",
|
|
122844
122735
|
"skill.delete_failed": "Delete failed.",
|
|
122845
122736
|
"skill.delete_failed_msg": "Delete failed: {msg}",
|
|
122846
|
-
"skill.confirm_uninstall": "
|
|
122737
|
+
"skill.confirm_uninstall": "Uninstall \"{label}\"?",
|
|
122847
122738
|
"skill.uninstall_reversible": "You can reinstall from the Skill center later",
|
|
122848
122739
|
"skill.uninstall_yes": "Yes, uninstall",
|
|
122849
122740
|
"toolcall.bg_agent_lost": "Background agent lost (session restarted before completion)",
|
|
@@ -123215,8 +123106,6 @@ const dictionaries = {
|
|
|
123215
123106
|
"market.design_card_desc": "14 design card generators (cover/photo/social/long-form), Parchment × Swiss dual-style system",
|
|
123216
123107
|
"market.superpowers_name": "Superpowers Dev Skill Pack",
|
|
123217
123108
|
"market.superpowers_desc": "14 dev methodology skills: TDD, system debugging, code review, subagent-driven dev, parallel agents, brainstorming, etc.",
|
|
123218
|
-
"market.audio_name": "Audio Skill Recording Analysis",
|
|
123219
|
-
"market.audio_desc": "Local recording analysis automation with RAG knowledge base. For sales review, meeting minutes, quality scoring, etc.",
|
|
123220
123109
|
"market.scrapling_name": "Scrapling Web Scraper",
|
|
123221
123110
|
"market.scrapling_desc": "Smart scraper based on Scrapling, supports Cloudflare/WAF bypass, login sessions, auto-extraction",
|
|
123222
123111
|
"market.astock_name": "A-Share Data Analysis",
|
|
@@ -124742,66 +124631,6 @@ const DEFAULT_OAUTH_PROVIDER_NAME = "managed:scream-code";
|
|
|
124742
124631
|
ErrorCodes.AUTH_LOGIN_REQUIRED;
|
|
124743
124632
|
const SCREAM_CODE_PLUGIN_MARKETPLACE_URL_ENV = "SCREAM_CODE_PLUGIN_MARKETPLACE_URL";
|
|
124744
124633
|
//#endregion
|
|
124745
|
-
//#region src/migration/command.ts
|
|
124746
|
-
function registerMigrateCommand(parent, _onMigrate) {
|
|
124747
|
-
parent.command("migrate").description("将旧版 scream-cli 安装的数据迁移到 scream-code。(已停用)").action(() => {
|
|
124748
|
-
process.stdout.write("迁移功能已取消,不再支持从 scream-cli 导入数据。\n");
|
|
124749
|
-
process.exit(0);
|
|
124750
|
-
});
|
|
124751
|
-
}
|
|
124752
|
-
//#endregion
|
|
124753
|
-
//#region src/migration/badge.ts
|
|
124754
|
-
/**
|
|
124755
|
-
* Pure helpers for composing session labels in the session picker.
|
|
124756
|
-
*
|
|
124757
|
-
* Detection rule for the `[imported]` badge: `metadata.imported_from_scream_cli`
|
|
124758
|
-
* is strictly the boolean `true`. This mirrors the value written by
|
|
124759
|
-
* `migration-legacy` into the session's `state.json` `custom` block.
|
|
124760
|
-
*/
|
|
124761
|
-
const IMPORTED_BADGE = "[已导入]";
|
|
124762
|
-
const IMPORTED_FLAG_KEY = "imported_from_scream_cli";
|
|
124763
|
-
function isImportedSession(metadata) {
|
|
124764
|
-
if (metadata === void 0) return false;
|
|
124765
|
-
return metadata[IMPORTED_FLAG_KEY] === true;
|
|
124766
|
-
}
|
|
124767
|
-
function formatSessionLabel(input) {
|
|
124768
|
-
return `${isImportedSession(input.metadata) ? `${IMPORTED_BADGE} ` : ""}${input.title}`;
|
|
124769
|
-
}
|
|
124770
|
-
//#endregion
|
|
124771
|
-
//#region ../../packages/migration-legacy/src/scream-cli-schema.ts
|
|
124772
|
-
const OldWorkDirMetaSchema = z.object({
|
|
124773
|
-
path: z.string(),
|
|
124774
|
-
jian: z.string().default("local"),
|
|
124775
|
-
last_session_id: z.string().nullable().optional()
|
|
124776
|
-
});
|
|
124777
|
-
z.object({ work_dirs: z.array(OldWorkDirMetaSchema).default([]) });
|
|
124778
|
-
z.object({
|
|
124779
|
-
version: z.number().optional(),
|
|
124780
|
-
approval: z.object({
|
|
124781
|
-
yolo: z.boolean().optional(),
|
|
124782
|
-
afk: z.boolean().optional(),
|
|
124783
|
-
auto_approve_actions: z.array(z.string()).optional()
|
|
124784
|
-
}).partial().optional(),
|
|
124785
|
-
additional_dirs: z.array(z.string()).optional(),
|
|
124786
|
-
custom_title: z.string().nullable().optional(),
|
|
124787
|
-
title_generated: z.boolean().optional(),
|
|
124788
|
-
title_generate_attempts: z.number().optional(),
|
|
124789
|
-
plan_mode: z.boolean().optional(),
|
|
124790
|
-
plan_session_id: z.string().nullable().optional(),
|
|
124791
|
-
plan_slug: z.string().nullable().optional(),
|
|
124792
|
-
wire_mtime: z.number().nullable().optional(),
|
|
124793
|
-
archived: z.boolean().optional(),
|
|
124794
|
-
archived_at: z.number().nullable().optional(),
|
|
124795
|
-
auto_archive_exempt: z.boolean().optional(),
|
|
124796
|
-
todos: z.array(z.unknown()).optional()
|
|
124797
|
-
}).passthrough();
|
|
124798
|
-
//#endregion
|
|
124799
|
-
//#region ../../packages/migration-legacy/src/steps/config.ts
|
|
124800
|
-
function camelToSnake(s) {
|
|
124801
|
-
return s.replaceAll(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
|
|
124802
|
-
}
|
|
124803
|
-
new Set(Object.keys(ScreamConfigSchema.shape).filter((k) => k !== "raw" && k !== "providers" && k !== "models" && k !== "hooks").map(camelToSnake));
|
|
124804
|
-
//#endregion
|
|
124805
124634
|
//#region src/cli/update/types.ts
|
|
124806
124635
|
function emptyUpdateCache() {
|
|
124807
124636
|
return {
|
|
@@ -124874,7 +124703,7 @@ function optionalBuildString(value) {
|
|
|
124874
124703
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
124875
124704
|
}
|
|
124876
124705
|
const SCREAM_BUILD_INFO = {
|
|
124877
|
-
version: optionalBuildString("0.9.
|
|
124706
|
+
version: optionalBuildString("0.9.4"),
|
|
124878
124707
|
channel: optionalBuildString(""),
|
|
124879
124708
|
commit: optionalBuildString(""),
|
|
124880
124709
|
buildTarget: optionalBuildString("darwin-arm64")
|
|
@@ -125031,19 +124860,24 @@ function errorMessage(error) {
|
|
|
125031
124860
|
}
|
|
125032
124861
|
//#endregion
|
|
125033
124862
|
//#region src/cli/commands.ts
|
|
125034
|
-
function createProgram(version, onMain,
|
|
124863
|
+
function createProgram(version, onMain, onPluginNodeRunner = () => {}, onStreamJson = () => {}, onChannelSetup = () => {}) {
|
|
125035
124864
|
const program = new Command(CLI_COMMAND_NAME).description("下一代智能体的起点").version(version, "-V, --version").allowUnknownOption(false).configureHelp({ helpWidth: 100 }).helpOption("-h, --help", "显示帮助。").addHelpText("after", "\n文档: https://scream-cli.github.io/scream-code/\n");
|
|
125036
124865
|
program.addOption(new Option("-S, --session [id]", "恢复会话。带 ID:恢复该会话。不带 ID:交互式选择。").argParser((val) => val === true ? "" : val)).addOption(new Option("-r, --resume [id]").hideHelp().argParser((val) => val === true ? "" : val)).option("-C, --continue", "继续当前工作目录的上一个会话。", false).option("-y, --yolo", "自动批准所有操作。", false).option("--auto", "以自动权限模式启动。", false).addOption(new Option("-m, --model <model>", "本次调用使用的 LLM 模型别名。默认使用 config.toml 中的 default_model。")).addOption(new Option("-p, --prompt <prompt>", "非交互式运行一条提示并打印响应。")).addOption(new Option("--output-format <format>", "提示模式的输出格式。默认为 text。").choices(["text", "stream-json"])).addOption(new Option("--skills-dir <dir>", "从该目录加载技能,而不是自动发现的用户和项目目录。可多次指定。").argParser((value, previous) => [...previous ?? [], value]).default([])).addOption(new Option("--yes").hideHelp().default(false)).addOption(new Option("--auto-approve").hideHelp().default(false)).option("--plan", "以计划模式启动。", false).option("--wolfpack", "启动时默认开启 WolfPack 批量并发模式。", false);
|
|
125037
124866
|
registerExportCommand(program);
|
|
125038
|
-
|
|
125039
|
-
program.command("stream-json", { hidden: true }).option("--input-format <fmt>", "stream-json").option("--output-format <fmt>", "stream-json").option("--resume <id>", "resume a previous session").option("--model <model>", "model to use").option("--permission-mode <mode>", "permission mode").option("--permission-prompt-tool <mode>", "(ignored, cc-connect compat)").option("--replay-user-messages", "(ignored, cc-connect compat)").option("--verbose", "(ignored, cc-connect compat)").option("--system-prompt <text>", "(ignored, cc-connect compat)").option("--append-system-prompt <text>", "(passed through to agent)").option("--append-system-prompt-file <path>", "(passed through to agent; file contents are read and merged)").option("--allowedTools <list>", "(ignored, cc-connect compat)").option("--disallowedTools <list>", "(ignored, cc-connect compat)").option("--effort <value>", "(ignored, cc-connect compat)").option("--max-context-tokens <N>", "(ignored, cc-connect compat)").option("--skills-dir <dir>", "additional skills directory (repeatable)", (value, previous) => [...previous ?? [], value], []).option("--plugin-dir <dir>", "(ignored, cc-connect compat; repeatable)", (value, previous) => [...previous ?? [], value], []).action((subOpts) => {
|
|
124867
|
+
program.command("stream-json", { hidden: true }).option("--input-format <fmt>", "stream-json").option("--output-format <fmt>", "stream-json").option("--resume <id>", "resume a previous session").option("--model <model>", "model to use").option("--permission-mode <mode>", "permission mode").option("--permission-prompt-tool <mode>", "(ignored, cc-connect compat)").option("--replay-user-messages", "(ignored, cc-connect compat)").option("--verbose", "(ignored, cc-connect compat)").option("--system-prompt <text>", "(passed through to agent system prompt)").option("--append-system-prompt <text>", "(passed through to agent)").option("--append-system-prompt-file <path>", "(passed through to agent; file contents are read and merged)").option("--allowedTools <list>", "(comma-separated tool whitelist)").option("--disallowedTools <list>", "(comma-separated tool blacklist)").option("--effort <value>", "(reasoning effort: low/medium/high/max)").option("--max-context-tokens <N>", "(ignored, cc-connect compat)").option("--skills-dir <dir>", "additional skills directory (repeatable)", (value, previous) => [...previous ?? [], value], []).option("--plugin-dir <dir>", "(ignored, cc-connect compat; repeatable)", (value, previous) => [...previous ?? [], value], []).action((subOpts) => {
|
|
125040
124868
|
onStreamJson({
|
|
125041
124869
|
resume: subOpts["resume"],
|
|
125042
124870
|
model: subOpts["model"],
|
|
125043
124871
|
permissionMode: subOpts["permissionMode"],
|
|
125044
124872
|
skillsDirs: subOpts["skillsDir"] ?? [],
|
|
125045
124873
|
appendSystemPrompt: subOpts["appendSystemPrompt"],
|
|
125046
|
-
appendSystemPromptFile: subOpts["appendSystemPromptFile"]
|
|
124874
|
+
appendSystemPromptFile: subOpts["appendSystemPromptFile"],
|
|
124875
|
+
systemPrompt: subOpts["systemPrompt"],
|
|
124876
|
+
allowedTools: subOpts["allowedTools"],
|
|
124877
|
+
disallowedTools: subOpts["disallowedTools"],
|
|
124878
|
+
effort: subOpts["effort"],
|
|
124879
|
+
maxContextTokens: subOpts["maxContextTokens"],
|
|
124880
|
+
pluginDirs: subOpts["pluginDir"] ?? []
|
|
125047
124881
|
});
|
|
125048
124882
|
});
|
|
125049
124883
|
program.command("channel").description("管理 cc-connect 消息平台通道").command("setup").description("配置 cc-connect 并选择要连接的平台").action(() => {
|
|
@@ -125111,7 +124945,6 @@ function validateOptions(opts) {
|
|
|
125111
124945
|
* Agent/runtime settings live in core's `config.toml`; this file owns only
|
|
125112
124946
|
* terminal UI preferences for the scream-code client.
|
|
125113
124947
|
*/
|
|
125114
|
-
const INVALID_TUI_CONFIG_MESSAGE = t("tui.invalid_config");
|
|
125115
124948
|
const TuiThemeSchema = z.enum([
|
|
125116
124949
|
"dark",
|
|
125117
124950
|
"light",
|
|
@@ -125179,7 +125012,7 @@ var TuiConfigParseError = class extends Error {
|
|
|
125179
125012
|
name = "TuiConfigParseError";
|
|
125180
125013
|
fallback;
|
|
125181
125014
|
constructor(fallback) {
|
|
125182
|
-
super(
|
|
125015
|
+
super(t("tui.invalid_config"));
|
|
125183
125016
|
this.fallback = fallback;
|
|
125184
125017
|
}
|
|
125185
125018
|
};
|
|
@@ -135236,7 +135069,7 @@ function generateConfig$1(platform) {
|
|
|
135236
135069
|
"type = \"claudecode\"",
|
|
135237
135070
|
"",
|
|
135238
135071
|
"[projects.agent.options]",
|
|
135239
|
-
`
|
|
135072
|
+
`cmd = '${escapeSingleQuotes(detectScreamPath$1())}'`,
|
|
135240
135073
|
`work_dir = '${escapeSingleQuotes(process.cwd())}'`,
|
|
135241
135074
|
"mode = \"default\"",
|
|
135242
135075
|
"",
|
|
@@ -135580,134 +135413,130 @@ var MoonLoader = class extends Text {
|
|
|
135580
135413
|
*
|
|
135581
135414
|
* Used when the remote marketplace cannot be fetched at runtime.
|
|
135582
135415
|
*/
|
|
135583
|
-
|
|
135584
|
-
|
|
135585
|
-
|
|
135586
|
-
|
|
135587
|
-
|
|
135588
|
-
|
|
135589
|
-
|
|
135590
|
-
|
|
135591
|
-
|
|
135592
|
-
|
|
135593
|
-
|
|
135594
|
-
|
|
135595
|
-
|
|
135596
|
-
|
|
135597
|
-
|
|
135598
|
-
|
|
135599
|
-
|
|
135600
|
-
|
|
135601
|
-
|
|
135602
|
-
|
|
135603
|
-
|
|
135604
|
-
|
|
135605
|
-
|
|
135606
|
-
|
|
135607
|
-
|
|
135608
|
-
|
|
135609
|
-
|
|
135610
|
-
|
|
135611
|
-
|
|
135612
|
-
|
|
135613
|
-
|
|
135614
|
-
|
|
135615
|
-
|
|
135616
|
-
|
|
135617
|
-
|
|
135618
|
-
|
|
135619
|
-
|
|
135620
|
-
|
|
135621
|
-
|
|
135622
|
-
|
|
135623
|
-
|
|
135624
|
-
|
|
135625
|
-
|
|
135626
|
-
|
|
135627
|
-
|
|
135628
|
-
|
|
135629
|
-
|
|
135630
|
-
|
|
135631
|
-
|
|
135632
|
-
|
|
135633
|
-
|
|
135634
|
-
|
|
135635
|
-
|
|
135636
|
-
|
|
135637
|
-
|
|
135638
|
-
|
|
135639
|
-
|
|
135640
|
-
|
|
135641
|
-
|
|
135642
|
-
|
|
135643
|
-
|
|
135644
|
-
|
|
135645
|
-
|
|
135646
|
-
|
|
135647
|
-
|
|
135648
|
-
|
|
135649
|
-
|
|
135650
|
-
|
|
135651
|
-
|
|
135652
|
-
|
|
135653
|
-
|
|
135654
|
-
|
|
135655
|
-
|
|
135656
|
-
|
|
135657
|
-
|
|
135658
|
-
|
|
135659
|
-
|
|
135660
|
-
|
|
135661
|
-
|
|
135662
|
-
|
|
135663
|
-
|
|
135664
|
-
|
|
135665
|
-
|
|
135666
|
-
|
|
135667
|
-
|
|
135668
|
-
|
|
135669
|
-
|
|
135670
|
-
|
|
135671
|
-
|
|
135672
|
-
|
|
135673
|
-
|
|
135674
|
-
|
|
135675
|
-
|
|
135676
|
-
|
|
135677
|
-
|
|
135678
|
-
|
|
135679
|
-
|
|
135680
|
-
|
|
135681
|
-
|
|
135682
|
-
|
|
135683
|
-
|
|
135684
|
-
|
|
135685
|
-
|
|
135686
|
-
|
|
135687
|
-
|
|
135688
|
-
|
|
135689
|
-
|
|
135690
|
-
|
|
135691
|
-
|
|
135692
|
-
|
|
135693
|
-
|
|
135694
|
-
|
|
135695
|
-
|
|
135696
|
-
|
|
135697
|
-
|
|
135698
|
-
|
|
135699
|
-
|
|
135700
|
-
|
|
135701
|
-
|
|
135702
|
-
|
|
135703
|
-
|
|
135704
|
-
|
|
135705
|
-
|
|
135706
|
-
|
|
135707
|
-
description: t("market.guizang_desc"),
|
|
135708
|
-
source: "https://github.com/op7418/guizang-social-card-skill"
|
|
135709
|
-
}
|
|
135710
|
-
];
|
|
135416
|
+
function getFallbackSkillMarketplace() {
|
|
135417
|
+
return [
|
|
135418
|
+
{
|
|
135419
|
+
id: "gsap-skills",
|
|
135420
|
+
displayName: t("market.gsap_name"),
|
|
135421
|
+
description: t("market.gsap_desc"),
|
|
135422
|
+
source: "https://github.com/greensock/gsap-skills"
|
|
135423
|
+
},
|
|
135424
|
+
{
|
|
135425
|
+
id: "claude-design-card",
|
|
135426
|
+
displayName: t("market.design_card_name"),
|
|
135427
|
+
description: t("market.design_card_desc"),
|
|
135428
|
+
source: "https://github.com/geekjourneyx/claude-design-card"
|
|
135429
|
+
},
|
|
135430
|
+
{
|
|
135431
|
+
id: "superpowers",
|
|
135432
|
+
displayName: t("market.superpowers_name"),
|
|
135433
|
+
description: t("market.superpowers_desc"),
|
|
135434
|
+
source: "https://github.com/obra/superpowers"
|
|
135435
|
+
},
|
|
135436
|
+
{
|
|
135437
|
+
id: "scrapling-skill",
|
|
135438
|
+
displayName: t("market.scrapling_name"),
|
|
135439
|
+
description: t("market.scrapling_desc"),
|
|
135440
|
+
source: "https://github.com/Cedriccmh/claude-code-skill-scrapling"
|
|
135441
|
+
},
|
|
135442
|
+
{
|
|
135443
|
+
id: "a-stock-data",
|
|
135444
|
+
displayName: t("market.astock_name"),
|
|
135445
|
+
description: t("market.astock_desc"),
|
|
135446
|
+
source: "https://github.com/simonlin1212/a-stock-data"
|
|
135447
|
+
},
|
|
135448
|
+
{
|
|
135449
|
+
id: "humanizer",
|
|
135450
|
+
displayName: t("market.humanizer_name"),
|
|
135451
|
+
description: t("market.humanizer_desc"),
|
|
135452
|
+
source: "https://github.com/blader/humanizer"
|
|
135453
|
+
},
|
|
135454
|
+
{
|
|
135455
|
+
id: "patent-disclosure-skill",
|
|
135456
|
+
displayName: t("market.patent_name"),
|
|
135457
|
+
description: t("market.patent_desc"),
|
|
135458
|
+
source: "https://github.com/handsomestWei/patent-disclosure-skill"
|
|
135459
|
+
},
|
|
135460
|
+
{
|
|
135461
|
+
id: "contract-review-pro",
|
|
135462
|
+
displayName: t("market.contract_name"),
|
|
135463
|
+
description: t("market.contract_desc"),
|
|
135464
|
+
source: "https://github.com/CSlawyer1985/contract-review-pro"
|
|
135465
|
+
},
|
|
135466
|
+
{
|
|
135467
|
+
id: "academic-research-skills",
|
|
135468
|
+
displayName: t("market.academic_name"),
|
|
135469
|
+
description: t("market.academic_desc"),
|
|
135470
|
+
source: "https://github.com/Imbad0202/academic-research-skills"
|
|
135471
|
+
},
|
|
135472
|
+
{
|
|
135473
|
+
id: "headroom",
|
|
135474
|
+
displayName: t("market.headroom_name"),
|
|
135475
|
+
description: t("market.headroom_desc"),
|
|
135476
|
+
source: "https://github.com/chopratejas/headroom"
|
|
135477
|
+
},
|
|
135478
|
+
{
|
|
135479
|
+
id: "xiaohu-wechat-format",
|
|
135480
|
+
displayName: t("market.xiaohu_wechat_name"),
|
|
135481
|
+
description: t("market.xiaohu_wechat_desc"),
|
|
135482
|
+
source: "https://github.com/xiaohuailabs/xiaohu-wechat-format"
|
|
135483
|
+
},
|
|
135484
|
+
{
|
|
135485
|
+
id: "huashu-design",
|
|
135486
|
+
displayName: t("market.huashu_name"),
|
|
135487
|
+
description: t("market.huashu_desc"),
|
|
135488
|
+
source: "https://github.com/alchaincyf/huashu-design"
|
|
135489
|
+
},
|
|
135490
|
+
{
|
|
135491
|
+
id: "html-video",
|
|
135492
|
+
displayName: t("market.html_video_name"),
|
|
135493
|
+
description: t("market.html_video_desc"),
|
|
135494
|
+
source: "https://github.com/nexu-io/html-video"
|
|
135495
|
+
},
|
|
135496
|
+
{
|
|
135497
|
+
id: "xiaohu-video-translate",
|
|
135498
|
+
displayName: t("market.xiaohu_translate_name"),
|
|
135499
|
+
description: t("market.xiaohu_translate_desc"),
|
|
135500
|
+
source: "https://github.com/xiaohuailabs/xiaohu-video-translate"
|
|
135501
|
+
},
|
|
135502
|
+
{
|
|
135503
|
+
id: "videocut-skills",
|
|
135504
|
+
displayName: t("market.videocut_name"),
|
|
135505
|
+
description: t("market.videocut_desc"),
|
|
135506
|
+
source: "https://github.com/Ceeon/videocut-skills"
|
|
135507
|
+
},
|
|
135508
|
+
{
|
|
135509
|
+
id: "taste-skill",
|
|
135510
|
+
displayName: t("market.taste_name"),
|
|
135511
|
+
description: t("market.taste_desc"),
|
|
135512
|
+
source: "https://github.com/Leonxlnx/taste-skill"
|
|
135513
|
+
},
|
|
135514
|
+
{
|
|
135515
|
+
id: "vtake-skills",
|
|
135516
|
+
displayName: t("market.vtake_name"),
|
|
135517
|
+
description: t("market.vtake_desc"),
|
|
135518
|
+
source: "https://github.com/notedit/vtake-skills"
|
|
135519
|
+
},
|
|
135520
|
+
{
|
|
135521
|
+
id: "remotion-skills",
|
|
135522
|
+
displayName: t("market.remotion_name"),
|
|
135523
|
+
description: t("market.remotion_desc"),
|
|
135524
|
+
source: "https://github.com/remotion-dev/skills"
|
|
135525
|
+
},
|
|
135526
|
+
{
|
|
135527
|
+
id: "html-anything",
|
|
135528
|
+
displayName: t("market.html_anything_name"),
|
|
135529
|
+
description: t("market.html_anything_desc"),
|
|
135530
|
+
source: "https://github.com/nexu-io/html-anything"
|
|
135531
|
+
},
|
|
135532
|
+
{
|
|
135533
|
+
id: "guizang-social-card-skill",
|
|
135534
|
+
displayName: t("market.guizang_name"),
|
|
135535
|
+
description: t("market.guizang_desc"),
|
|
135536
|
+
source: "https://github.com/op7418/guizang-social-card-skill"
|
|
135537
|
+
}
|
|
135538
|
+
];
|
|
135539
|
+
}
|
|
135711
135540
|
//#endregion
|
|
135712
135541
|
//#region src/tui/commands/skill-center.ts
|
|
135713
135542
|
const SKILL_DESC_MAX = 60;
|
|
@@ -135807,7 +135636,7 @@ async function loadMarketplace(host) {
|
|
|
135807
135636
|
const { plugins } = await loadPluginMarketplace({ workDir: host.state.appState.workDir });
|
|
135808
135637
|
return plugins;
|
|
135809
135638
|
} catch {
|
|
135810
|
-
return [...
|
|
135639
|
+
return [...getFallbackSkillMarketplace()];
|
|
135811
135640
|
}
|
|
135812
135641
|
}
|
|
135813
135642
|
function buildOptions(host, skills, plugins, marketplace) {
|
|
@@ -136006,7 +135835,7 @@ async function uninstallManualSkill(host, skill) {
|
|
|
136006
135835
|
async function confirmUninstall(host, label, description) {
|
|
136007
135836
|
return new Promise((resolve) => {
|
|
136008
135837
|
const picker = new ChoicePickerComponent({
|
|
136009
|
-
title:
|
|
135838
|
+
title: t("skill.confirm_uninstall", { label }),
|
|
136010
135839
|
hint: t("skill.uninstall_reversible"),
|
|
136011
135840
|
options: [{
|
|
136012
135841
|
value: "no",
|
|
@@ -136837,7 +136666,7 @@ function resize(){
|
|
|
136837
136666
|
ctx.setTransform(DPR,0,0,DPR,0,0);
|
|
136838
136667
|
}
|
|
136839
136668
|
resize();
|
|
136840
|
-
window.addEventListener('resize',resize);
|
|
136669
|
+
window.addEventListener('resize',function(){resize();markDirty()});
|
|
136841
136670
|
|
|
136842
136671
|
// 相机
|
|
136843
136672
|
var camRotX=0.25,camRotY=0.4;
|
|
@@ -136855,33 +136684,6 @@ var graphData;
|
|
|
136855
136684
|
var nodePositions={};
|
|
136856
136685
|
var nodeData=[];
|
|
136857
136686
|
|
|
136858
|
-
// 节点漂浮参数:每个节点独立相位,渲染时叠加微小偏移
|
|
136859
|
-
var floatParams={};
|
|
136860
|
-
var frameTime=0;
|
|
136861
|
-
function ensureFloat(id){
|
|
136862
|
-
if(floatParams[id])return;
|
|
136863
|
-
floatParams[id]={
|
|
136864
|
-
phaseX:Math.random()*Math.PI*2,
|
|
136865
|
-
phaseY:Math.random()*Math.PI*2,
|
|
136866
|
-
phaseZ:Math.random()*Math.PI*2,
|
|
136867
|
-
ampX:1.5+Math.random()*2.5,
|
|
136868
|
-
ampY:1.5+Math.random()*2.5,
|
|
136869
|
-
ampZ:1+Math.random()*2,
|
|
136870
|
-
speed:0.0004+Math.random()*0.0004
|
|
136871
|
-
};
|
|
136872
|
-
}
|
|
136873
|
-
// 返回某节点当前帧的漂浮后位置(不修改原 nodePositions,避免拾取错位)
|
|
136874
|
-
function floatingPos(id,t){
|
|
136875
|
-
var p=nodePositions[id];if(!p)return p;
|
|
136876
|
-
var f=floatParams[id];if(!f)return p;
|
|
136877
|
-
if(t===undefined)t=frameTime;
|
|
136878
|
-
return{
|
|
136879
|
-
x:p.x+Math.sin(t*f.speed+f.phaseX)*f.ampX,
|
|
136880
|
-
y:p.y+Math.cos(t*f.speed*1.1+f.phaseY)*f.ampY,
|
|
136881
|
-
z:p.z+Math.sin(t*f.speed*0.8+f.phaseZ)*f.ampZ
|
|
136882
|
-
};
|
|
136883
|
-
}
|
|
136884
|
-
|
|
136885
136687
|
// ─── 3D 投影 ──────────────────────────────────────────
|
|
136886
136688
|
function project(p){
|
|
136887
136689
|
var cosY=Math.cos(camRotY),sinY=Math.sin(camRotY);
|
|
@@ -136985,10 +136787,6 @@ function buildNebulae(){
|
|
|
136985
136787
|
baseX:p.x+r*Math.sin(phi)*Math.cos(theta),
|
|
136986
136788
|
baseY:p.y+r*Math.sin(phi)*Math.sin(theta),
|
|
136987
136789
|
baseZ:p.z+r*Math.cos(phi),
|
|
136988
|
-
phase:Math.random()*Math.PI*2,
|
|
136989
|
-
ampX:2+Math.random()*4,
|
|
136990
|
-
ampY:2+Math.random()*4,
|
|
136991
|
-
ampZ:1+Math.random()*3,
|
|
136992
136790
|
size:0.5+Math.random()*0.8,
|
|
136993
136791
|
op:0.15+Math.random()*0.2
|
|
136994
136792
|
});
|
|
@@ -136996,19 +136794,14 @@ function buildNebulae(){
|
|
|
136996
136794
|
});
|
|
136997
136795
|
}
|
|
136998
136796
|
|
|
136999
|
-
function drawNebulae(
|
|
136797
|
+
function drawNebulae(){
|
|
137000
136798
|
ctx.save();
|
|
137001
136799
|
for(var i=0;i<nebulaDots.length;i++){
|
|
137002
136800
|
var d=nebulaDots[i];
|
|
137003
|
-
|
|
137004
|
-
var x=d.baseX+Math.sin(t*0.0003+d.phase)*d.ampX;
|
|
137005
|
-
var y=d.baseY+Math.cos(t*0.0004+d.phase*1.3)*d.ampY;
|
|
137006
|
-
var z=d.baseZ+Math.sin(t*0.0002+d.phase*0.7)*d.ampZ;
|
|
137007
|
-
var p=project({x:x,y:y,z:z});
|
|
136801
|
+
var p=project({x:d.baseX,y:d.baseY,z:d.baseZ});
|
|
137008
136802
|
if(p.z<=0)continue;
|
|
137009
136803
|
var r=Math.max(0.3,d.size*p.scale*0.5);
|
|
137010
136804
|
if(r<0.4)continue;
|
|
137011
|
-
// 远处淡,近处稍清晰
|
|
137012
136805
|
var alpha=d.op*Math.min(1,p.scale*1.5);
|
|
137013
136806
|
ctx.fillStyle='rgba(0,0,0,'+alpha.toFixed(3)+')';
|
|
137014
136807
|
ctx.beginPath();
|
|
@@ -137185,7 +136978,7 @@ function computeProjMap(){
|
|
|
137185
136978
|
vis.events.forEach(function(id){visAll.add(id)});
|
|
137186
136979
|
var map={allIds:visAll};
|
|
137187
136980
|
visAll.forEach(function(id){
|
|
137188
|
-
var p=
|
|
136981
|
+
var p=nodePositions[id];
|
|
137189
136982
|
if(p)map[id]=project(p);
|
|
137190
136983
|
});
|
|
137191
136984
|
return map;
|
|
@@ -137217,6 +137010,7 @@ function startInertia(){
|
|
|
137217
137010
|
camRotY+=velRotY;
|
|
137218
137011
|
camRotX=Math.max(-1.2,Math.min(1.2,camRotX+velRotX));
|
|
137219
137012
|
velRotX*=0.94;velRotY*=0.94;
|
|
137013
|
+
markDirty();
|
|
137220
137014
|
inertiaRAF=requestAnimationFrame(step);
|
|
137221
137015
|
}
|
|
137222
137016
|
inertiaRAF=requestAnimationFrame(step);
|
|
@@ -137255,7 +137049,7 @@ function pickNode(sx,sy){
|
|
|
137255
137049
|
vis.events.forEach(function(id){visAll.add(id)});
|
|
137256
137050
|
var best=null,bestDist=Infinity;
|
|
137257
137051
|
visAll.forEach(function(id){
|
|
137258
|
-
var p=
|
|
137052
|
+
var p=nodePositions[id];if(!p)return;
|
|
137259
137053
|
var sp=project(p);
|
|
137260
137054
|
if(sp.z<=0)return;
|
|
137261
137055
|
var data=nodeData.find(function(n){return n.id===id});
|
|
@@ -137294,14 +137088,16 @@ canvas.addEventListener('mousemove',function(e){
|
|
|
137294
137088
|
velRotY=(e.clientX-lastMoveX)/dt*0.005;
|
|
137295
137089
|
velRotX=(e.clientY-lastMoveY)/dt*0.005;
|
|
137296
137090
|
lastMoveTime=now;lastMoveX=e.clientX;lastMoveY=e.clientY;
|
|
137091
|
+
markDirty();
|
|
137297
137092
|
}else if(isPanning){
|
|
137298
137093
|
var pdx=e.clientX-dragStart.x,pdy=e.clientY-dragStart.y;
|
|
137299
137094
|
var scale=fov/camDist;
|
|
137300
137095
|
camTargetX=dragStart.panX - pdx*scale;
|
|
137301
137096
|
camTargetY=dragStart.panY + pdy*scale;
|
|
137097
|
+
markDirty();
|
|
137302
137098
|
}else{
|
|
137303
137099
|
var id=pickNode(e.clientX,e.clientY);
|
|
137304
|
-
if(id!==hoveredId){hoveredId=id;canvas.style.cursor=id?'pointer':'grab';}
|
|
137100
|
+
if(id!==hoveredId){hoveredId=id;canvas.style.cursor=id?'pointer':'grab';markDirty();}
|
|
137305
137101
|
if(id)showTooltip(e.clientX,e.clientY,id);
|
|
137306
137102
|
else hideTooltip();
|
|
137307
137103
|
}
|
|
@@ -137325,10 +137121,10 @@ canvas.addEventListener('mouseup',function(e){
|
|
|
137325
137121
|
if(data.kind==='event'&&!expEv.has(id))expEv.add(id);
|
|
137326
137122
|
}
|
|
137327
137123
|
selId=id;navStack=[];
|
|
137328
|
-
focusOn(id);rebuildLabels();
|
|
137124
|
+
focusOn(id);rebuildLabels();markDirty();
|
|
137329
137125
|
},250);
|
|
137330
137126
|
}else{
|
|
137331
|
-
selId=null;rebuildLabels();closeModal();
|
|
137127
|
+
selId=null;rebuildLabels();closeModal();markDirty();
|
|
137332
137128
|
}
|
|
137333
137129
|
});
|
|
137334
137130
|
|
|
@@ -137344,13 +137140,13 @@ canvas.addEventListener('dblclick',function(e){
|
|
|
137344
137140
|
if(data){
|
|
137345
137141
|
if(!expEnt.has(id)&&!expEv.has(id)){expEnt.add(id);}
|
|
137346
137142
|
selId=id;navStack=[];
|
|
137347
|
-
focusOn(id);rebuildLabels();
|
|
137143
|
+
focusOn(id);rebuildLabels();markDirty();
|
|
137348
137144
|
showModal(id,data.kind);
|
|
137349
137145
|
}
|
|
137350
137146
|
}else{
|
|
137351
137147
|
expEnt.clear();expEv.clear();selId=null;
|
|
137352
137148
|
if(graphData)graphData.entities.forEach(function(en){expEnt.add(en.id)});
|
|
137353
|
-
closeModal();rebuildLabels();fitView();
|
|
137149
|
+
closeModal();rebuildLabels();fitView();markDirty();
|
|
137354
137150
|
}
|
|
137355
137151
|
});
|
|
137356
137152
|
|
|
@@ -137368,6 +137164,7 @@ canvas.addEventListener('wheel',function(e){
|
|
|
137368
137164
|
var scaleAfter=fov/camDist;
|
|
137369
137165
|
camTargetX=worldX - (mx-W/2)/scaleAfter;
|
|
137370
137166
|
camTargetY=worldY + (my-H/2)/scaleAfter;
|
|
137167
|
+
markDirty();
|
|
137371
137168
|
},{passive:false});
|
|
137372
137169
|
|
|
137373
137170
|
function focusOn(id){
|
|
@@ -137387,6 +137184,7 @@ function focusOn(id){
|
|
|
137387
137184
|
camTargetY=startTy+(endTy-startTy)*e;
|
|
137388
137185
|
camTargetZ=startTz+(endTz-startTz)*e;
|
|
137389
137186
|
camDist=startDist+(endDist-startDist)*e;
|
|
137187
|
+
markDirty();
|
|
137390
137188
|
if(t<1)focusAnim=requestAnimationFrame(step);
|
|
137391
137189
|
}
|
|
137392
137190
|
focusAnim=requestAnimationFrame(step);
|
|
@@ -137397,7 +137195,7 @@ function fitView(){
|
|
|
137397
137195
|
var ids=[];
|
|
137398
137196
|
vis.entities.forEach(function(id){ids.push(id)});
|
|
137399
137197
|
vis.events.forEach(function(id){ids.push(id)});
|
|
137400
|
-
if(!ids.length){camTargetX=0;camTargetY=0;camTargetZ=0;camDist=700;return}
|
|
137198
|
+
if(!ids.length){camTargetX=0;camTargetY=0;camTargetZ=0;camDist=700;markDirty();return}
|
|
137401
137199
|
var x0=Infinity,x1=-Infinity,y0=Infinity,y1=-Infinity,z0=Infinity,z1=-Infinity;
|
|
137402
137200
|
ids.forEach(function(id){var p=nodePositions[id];if(!p)return;if(p.x<x0)x0=p.x;if(p.x>x1)x1=p.x;if(p.y<y0)y0=p.y;if(p.y>y1)y1=p.y;if(p.z<z0)z0=p.z;if(p.z>z1)z1=p.z});
|
|
137403
137201
|
var cx=(x0+x1)/2,cy=(y0+y1)/2,cz=(z0+z1)/2;
|
|
@@ -137418,6 +137216,7 @@ function fitView(){
|
|
|
137418
137216
|
camDist=startDist+(endDist-startDist)*e;
|
|
137419
137217
|
camRotX=startRotX+(endRotX-startRotX)*e;
|
|
137420
137218
|
camRotY=startRotY+(endRotY-startRotY)*e;
|
|
137219
|
+
markDirty();
|
|
137421
137220
|
if(t<1)focusAnim=requestAnimationFrame(step);
|
|
137422
137221
|
}
|
|
137423
137222
|
focusAnim=requestAnimationFrame(step);
|
|
@@ -137432,6 +137231,7 @@ function startAutoRotate(){
|
|
|
137432
137231
|
var t=Math.min(1,elapsed/duration);
|
|
137433
137232
|
var fade=1-t;
|
|
137434
137233
|
camRotY+=speed*fade;
|
|
137234
|
+
markDirty();
|
|
137435
137235
|
if(t<1)autoRotRAF=requestAnimationFrame(step);
|
|
137436
137236
|
}
|
|
137437
137237
|
autoRotRAF=requestAnimationFrame(step);
|
|
@@ -137494,14 +137294,14 @@ function esc(s){if(!s)return'';return String(s).replace(/&/g,'&').replace(/<
|
|
|
137494
137294
|
document.getElementById('btn-reset').onclick=function(){
|
|
137495
137295
|
expEnt.clear();expEv.clear();selId=null;
|
|
137496
137296
|
if(graphData)graphData.entities.forEach(function(e){expEnt.add(e.id)});
|
|
137497
|
-
closeModal();rebuildLabels();fitView();
|
|
137297
|
+
closeModal();rebuildLabels();fitView();markDirty();
|
|
137498
137298
|
};
|
|
137499
137299
|
document.getElementById('btn-expand').onclick=function(){
|
|
137500
137300
|
if(graphData){
|
|
137501
137301
|
graphData.entities.forEach(function(e){expEnt.add(e.id)});
|
|
137502
137302
|
graphData.events.forEach(function(e){expEv.add(e.id)});
|
|
137503
137303
|
}
|
|
137504
|
-
selId=null;closeModal();rebuildLabels();fitView();
|
|
137304
|
+
selId=null;closeModal();rebuildLabels();fitView();markDirty();
|
|
137505
137305
|
};
|
|
137506
137306
|
document.getElementById('btn-close').onclick=closeModal;
|
|
137507
137307
|
document.getElementById('modal-mask').addEventListener('click',closeModal);
|
|
@@ -137543,11 +137343,12 @@ window.addEventListener('keydown',function(e){
|
|
|
137543
137343
|
if(e.key==='Escape'){
|
|
137544
137344
|
if(document.getElementById('modal').classList.contains('open'))closeModal();
|
|
137545
137345
|
else{selId=null;rebuildLabels()}
|
|
137346
|
+
markDirty();
|
|
137546
137347
|
}else if(e.key===' '){
|
|
137547
137348
|
e.preventDefault();
|
|
137548
137349
|
expEnt.clear();expEv.clear();selId=null;
|
|
137549
137350
|
if(graphData)graphData.entities.forEach(function(en){expEnt.add(en.id)});
|
|
137550
|
-
closeModal();rebuildLabels();fitView();
|
|
137351
|
+
closeModal();rebuildLabels();fitView();markDirty();
|
|
137551
137352
|
}else if(e.key==='ArrowRight'||e.key==='ArrowDown'){e.preventDefault();navigateRelated('next');}
|
|
137552
137353
|
else if(e.key==='ArrowLeft'||e.key==='ArrowUp'){e.preventDefault();navigateRelated('prev');}
|
|
137553
137354
|
});
|
|
@@ -137557,7 +137358,7 @@ var searchInput=document.getElementById('search-input');
|
|
|
137557
137358
|
var searchQuery='',searchMatches=null;
|
|
137558
137359
|
searchInput.addEventListener('input',function(){
|
|
137559
137360
|
searchQuery=searchInput.value.trim().toLowerCase();
|
|
137560
|
-
if(!searchQuery){searchMatches=null;rebuildLabels();return}
|
|
137361
|
+
if(!searchQuery){searchMatches=null;rebuildLabels();markDirty();return}
|
|
137561
137362
|
searchMatches=new Set();
|
|
137562
137363
|
var firstMatch=null;
|
|
137563
137364
|
if(graphData){
|
|
@@ -137588,9 +137389,10 @@ searchInput.addEventListener('input',function(){
|
|
|
137588
137389
|
});
|
|
137589
137390
|
selId=firstMatch;focusOn(firstMatch);rebuildLabels();
|
|
137590
137391
|
}
|
|
137392
|
+
markDirty();
|
|
137591
137393
|
});
|
|
137592
137394
|
searchInput.addEventListener('keydown',function(e){
|
|
137593
|
-
if(e.key==='Escape'){searchInput.value='';searchQuery='';searchMatches=null;rebuildLabels();searchInput.blur();}
|
|
137395
|
+
if(e.key==='Escape'){searchInput.value='';searchQuery='';searchMatches=null;rebuildLabels();searchInput.blur();markDirty();}
|
|
137594
137396
|
else if(e.key==='Enter'&&searchMatches&&searchMatches.size>0){
|
|
137595
137397
|
var first=Array.from(searchMatches)[0];
|
|
137596
137398
|
var data=nodeData.find(function(n){return n.id===first});
|
|
@@ -137670,20 +137472,24 @@ miniCanvas.addEventListener('click',function(e){
|
|
|
137670
137472
|
var e=t<.5?2*t*t:1-Math.pow(-2*t+2,2)/2;
|
|
137671
137473
|
camTargetX=startTx+(worldX-startTx)*e;
|
|
137672
137474
|
camTargetZ=startTz+(worldZ-startTz)*e;
|
|
137475
|
+
markDirty();
|
|
137673
137476
|
if(t<1)focusAnim=requestAnimationFrame(step);
|
|
137674
137477
|
}
|
|
137675
137478
|
focusAnim=requestAnimationFrame(step);
|
|
137676
137479
|
});
|
|
137677
137480
|
|
|
137678
137481
|
// ─── 主渲染循环 ──────────────────────────────────────
|
|
137482
|
+
var dirty=true;
|
|
137483
|
+
function markDirty(){dirty=true}
|
|
137679
137484
|
function animate(){
|
|
137680
137485
|
requestAnimationFrame(animate);
|
|
137681
137486
|
if(!graphData)return;
|
|
137682
|
-
|
|
137487
|
+
if(!dirty)return;
|
|
137488
|
+
dirty=false;
|
|
137683
137489
|
ctx.clearRect(0,0,W,H);
|
|
137684
137490
|
ctx.fillStyle='#fafafa';
|
|
137685
137491
|
ctx.fillRect(0,0,W,H);
|
|
137686
|
-
drawNebulae(
|
|
137492
|
+
drawNebulae();
|
|
137687
137493
|
var projMap=computeProjMap();
|
|
137688
137494
|
var connSet=computeConnSet(projMap.allIds);
|
|
137689
137495
|
drawEdges(projMap,connSet);
|
|
@@ -137736,11 +137542,11 @@ fetch('/api/graph').then(function(r){return r.json()}).then(function(data){
|
|
|
137736
137542
|
});
|
|
137737
137543
|
forceLayout3D();
|
|
137738
137544
|
buildNebulae();
|
|
137739
|
-
nodeData.forEach(function(n){ensureFloat(n.id)});
|
|
137740
137545
|
rebuildLabels();
|
|
137741
137546
|
fitView();
|
|
137742
137547
|
animate();
|
|
137743
137548
|
startAutoRotate();
|
|
137549
|
+
new EventSource('/api/heartbeat');
|
|
137744
137550
|
}).catch(function(err){
|
|
137745
137551
|
document.getElementById('loading').style.display='none';
|
|
137746
137552
|
errorMsg.style.display='block';
|
|
@@ -137864,6 +137670,22 @@ async function handleWeb(host) {
|
|
|
137864
137670
|
serveGraphJSON(store, res);
|
|
137865
137671
|
return;
|
|
137866
137672
|
}
|
|
137673
|
+
if (req.url === "/api/heartbeat") {
|
|
137674
|
+
res.writeHead(200, {
|
|
137675
|
+
"Content-Type": "text/event-stream",
|
|
137676
|
+
"Cache-Control": "no-store",
|
|
137677
|
+
Connection: "keep-alive"
|
|
137678
|
+
});
|
|
137679
|
+
const timer = setInterval(() => {
|
|
137680
|
+
res.write(": ping\n\n");
|
|
137681
|
+
}, 15e3);
|
|
137682
|
+
res.on("close", () => {
|
|
137683
|
+
clearInterval(timer);
|
|
137684
|
+
server.close();
|
|
137685
|
+
});
|
|
137686
|
+
res.write(": ok\n\n");
|
|
137687
|
+
return;
|
|
137688
|
+
}
|
|
137867
137689
|
serveHTML(res, getLocale());
|
|
137868
137690
|
});
|
|
137869
137691
|
registerServer(server);
|
|
@@ -146316,6 +146138,7 @@ function sessionRowsForPicker(sessions, currentSessionId, currentSessionHasConte
|
|
|
146316
146138
|
title: session.title ?? null,
|
|
146317
146139
|
last_prompt: session.lastPrompt ?? null,
|
|
146318
146140
|
work_dir: session.workDir,
|
|
146141
|
+
session_dir: session.sessionDir ?? "",
|
|
146319
146142
|
updated_at: session.updatedAt ?? session.createdAt ?? 0,
|
|
146320
146143
|
metadata: session.metadata
|
|
146321
146144
|
}));
|
|
@@ -147856,6 +147679,24 @@ var MemoryPickerComponent = class extends Container {
|
|
|
147856
147679
|
}
|
|
147857
147680
|
};
|
|
147858
147681
|
//#endregion
|
|
147682
|
+
//#region src/tui/utils/session-label.ts
|
|
147683
|
+
/**
|
|
147684
|
+
* Helpers for composing session labels in the session picker.
|
|
147685
|
+
*
|
|
147686
|
+
* Detection rule for the `[imported]` badge: `metadata.imported_from_scream_cli`
|
|
147687
|
+
* is strictly the boolean `true`. This mirrors the value written by
|
|
147688
|
+
* the old migration-legacy package into the session's `state.json` `custom` block.
|
|
147689
|
+
*/
|
|
147690
|
+
const IMPORTED_BADGE = "[已导入]";
|
|
147691
|
+
const IMPORTED_FLAG_KEY = "imported_from_scream_cli";
|
|
147692
|
+
function isImportedSession(metadata) {
|
|
147693
|
+
if (metadata === void 0) return false;
|
|
147694
|
+
return metadata[IMPORTED_FLAG_KEY] === true;
|
|
147695
|
+
}
|
|
147696
|
+
function formatSessionLabel(input) {
|
|
147697
|
+
return `${isImportedSession(input.metadata) ? `${IMPORTED_BADGE} ` : ""}${input.title}`;
|
|
147698
|
+
}
|
|
147699
|
+
//#endregion
|
|
147859
147700
|
//#region src/tui/components/dialogs/session-picker.ts
|
|
147860
147701
|
/**
|
|
147861
147702
|
* SessionPicker — pi-tui version of the session selection dialog.
|
|
@@ -147906,6 +147747,7 @@ var SessionPickerComponent = class extends Container {
|
|
|
147906
147747
|
onSelect;
|
|
147907
147748
|
onCancel;
|
|
147908
147749
|
onDelete;
|
|
147750
|
+
onStatus;
|
|
147909
147751
|
maxVisibleSessions;
|
|
147910
147752
|
loading;
|
|
147911
147753
|
focused = false;
|
|
@@ -147920,6 +147762,7 @@ var SessionPickerComponent = class extends Container {
|
|
|
147920
147762
|
this.onSelect = opts.onSelect;
|
|
147921
147763
|
this.onCancel = opts.onCancel;
|
|
147922
147764
|
this.onDelete = opts.onDelete;
|
|
147765
|
+
this.onStatus = opts.onStatus;
|
|
147923
147766
|
this.maxVisibleSessions = opts.maxVisibleSessions ?? 4;
|
|
147924
147767
|
}
|
|
147925
147768
|
handleInput(data) {
|
|
@@ -147936,9 +147779,17 @@ var SessionPickerComponent = class extends Container {
|
|
|
147936
147779
|
if (!session) return;
|
|
147937
147780
|
if (this.confirmingDelete) {
|
|
147938
147781
|
this.confirmingDelete = false;
|
|
147782
|
+
if (session.metadata?.["source"] === "cc-connect") {
|
|
147783
|
+
this.onStatus(t("session_picker.cc_restricted"));
|
|
147784
|
+
return;
|
|
147785
|
+
}
|
|
147939
147786
|
this.onDelete?.(session.id);
|
|
147940
147787
|
return;
|
|
147941
147788
|
}
|
|
147789
|
+
if (session.metadata?.["source"] === "cc-connect") {
|
|
147790
|
+
this.onStatus(t("session_picker.cc_restricted"));
|
|
147791
|
+
return;
|
|
147792
|
+
}
|
|
147942
147793
|
this.onSelect(session.id);
|
|
147943
147794
|
return;
|
|
147944
147795
|
}
|
|
@@ -147955,7 +147806,12 @@ var SessionPickerComponent = class extends Container {
|
|
|
147955
147806
|
const k = printableChar(data);
|
|
147956
147807
|
if ((k === "d" || k === "D") && !this.confirmingDelete && this.sessions.length > 0) {
|
|
147957
147808
|
const session = this.sessions[this.selectedIndex];
|
|
147958
|
-
if (session
|
|
147809
|
+
if (!session) return;
|
|
147810
|
+
if (session.metadata?.["source"] === "cc-connect") {
|
|
147811
|
+
this.onStatus(t("session_picker.cc_restricted"));
|
|
147812
|
+
return;
|
|
147813
|
+
}
|
|
147814
|
+
if (session.id !== this.currentSessionId) this.confirmingDelete = true;
|
|
147959
147815
|
}
|
|
147960
147816
|
}
|
|
147961
147817
|
render(width) {
|
|
@@ -148026,12 +147882,12 @@ var SessionPickerComponent = class extends Container {
|
|
|
148026
147882
|
const metaGap = " ";
|
|
148027
147883
|
const metaGapWidth = visibleWidth(metaGap);
|
|
148028
147884
|
const idLineWidth = indentWidth + idWidth;
|
|
148029
|
-
const
|
|
148030
|
-
const dirWidth = visibleWidth(
|
|
148031
|
-
if (idLineWidth + metaGapWidth + dirWidth <= width) card.push(indent + chalk.hex(colors.textMuted)(fullId) + chalk.hex(colors.textDim)(metaGap) + chalk.hex(colors.textMuted)(
|
|
147885
|
+
const displayDir = session.session_dir ? homeAlias(session.session_dir) : homeAlias(session.work_dir);
|
|
147886
|
+
const dirWidth = visibleWidth(displayDir);
|
|
147887
|
+
if (idLineWidth + metaGapWidth + dirWidth <= width) card.push(indent + chalk.hex(colors.textMuted)(fullId) + chalk.hex(colors.textDim)(metaGap) + chalk.hex(colors.textMuted)(displayDir));
|
|
148032
147888
|
else {
|
|
148033
147889
|
card.push(indent + chalk.hex(colors.textMuted)(truncateToWidth(fullId, Math.max(idWidth, width - indentWidth), ELLIPSIS)));
|
|
148034
|
-
const dir = truncatePathLeft(
|
|
147890
|
+
const dir = truncatePathLeft(displayDir, Math.max(8, width - indentWidth));
|
|
148035
147891
|
card.push(indent + chalk.hex(colors.textMuted)(dir));
|
|
148036
147892
|
}
|
|
148037
147893
|
const rawPrompt = session.last_prompt?.trim();
|
|
@@ -148693,6 +148549,9 @@ var DialogManager = class {
|
|
|
148693
148549
|
loading: this.host.getIsLoadingSessions(),
|
|
148694
148550
|
currentSessionId: this.host.getCurrentSessionId(),
|
|
148695
148551
|
colors: this.host.state.theme.colors,
|
|
148552
|
+
onStatus: (message) => {
|
|
148553
|
+
this.host.showStatus(message);
|
|
148554
|
+
},
|
|
148696
148555
|
onSelect: (pickerId) => {
|
|
148697
148556
|
const row = this.host.getSessions().find((s) => s.id === pickerId);
|
|
148698
148557
|
const isCc = row?.metadata?.["source"] === "cc-connect";
|
|
@@ -149940,7 +149799,7 @@ function generateConfig(cliPath, platformType) {
|
|
|
149940
149799
|
"type = \"claudecode\"",
|
|
149941
149800
|
"",
|
|
149942
149801
|
"[projects.agent.options]",
|
|
149943
|
-
`
|
|
149802
|
+
`cmd = '${cliPath}'`,
|
|
149944
149803
|
`work_dir = '${workDir}'`,
|
|
149945
149804
|
"mode = \"default\"",
|
|
149946
149805
|
"",
|
|
@@ -150087,13 +149946,15 @@ var ClaudeStreamJsonWriter = class {
|
|
|
150087
149946
|
this.currentModel = model;
|
|
150088
149947
|
}
|
|
150089
149948
|
/** Emit the `system` / `init` event. Called once after session creation. */
|
|
150090
|
-
emitSystem(sessionId) {
|
|
149949
|
+
emitSystem(sessionId, model) {
|
|
150091
149950
|
this.sessionId = sessionId;
|
|
150092
|
-
|
|
149951
|
+
const event = {
|
|
150093
149952
|
type: "system",
|
|
150094
149953
|
subtype: "init",
|
|
150095
149954
|
session_id: sessionId
|
|
150096
|
-
}
|
|
149955
|
+
};
|
|
149956
|
+
if (model) event["model"] = model;
|
|
149957
|
+
this.writeLine(JSON.stringify(event));
|
|
150097
149958
|
}
|
|
150098
149959
|
/** Accumulate assistant text delta. Flush buffered thinking first. */
|
|
150099
149960
|
writeAssistantDelta(delta) {
|
|
@@ -150204,14 +150065,16 @@ var ClaudeStreamJsonWriter = class {
|
|
|
150204
150065
|
content: `Resume this session: scream -r ${sessionId}`
|
|
150205
150066
|
});
|
|
150206
150067
|
}
|
|
150207
|
-
/** Emit a `control_request` event for cc-connect permission flow.
|
|
150068
|
+
/** Emit a `control_request` event for cc-connect permission flow.
|
|
150069
|
+
* Format matches cc-connect's handleControlRequest which expects
|
|
150070
|
+
* `request.subtype = "can_use_tool"`, `request.tool_name`, `request.input`. */
|
|
150208
150071
|
emitControlRequest(requestId, toolCallId, toolName, input) {
|
|
150209
150072
|
this.writeJson({
|
|
150210
150073
|
type: "control_request",
|
|
150211
150074
|
request_id: requestId,
|
|
150212
|
-
|
|
150213
|
-
|
|
150214
|
-
|
|
150075
|
+
request: {
|
|
150076
|
+
subtype: "can_use_tool",
|
|
150077
|
+
tool_name: toolName,
|
|
150215
150078
|
input
|
|
150216
150079
|
}
|
|
150217
150080
|
});
|
|
@@ -150263,7 +150126,7 @@ async function* readStdinMessages() {
|
|
|
150263
150126
|
log.warn("stream-json: failed to parse stdin line", { line: trimmed.slice(0, 200) });
|
|
150264
150127
|
continue;
|
|
150265
150128
|
}
|
|
150266
|
-
if (msg.type === "user" || msg.type === "control_response") yield msg;
|
|
150129
|
+
if (msg.type === "user" || msg.type === "control_response" || msg.type === "control_cancel_request") yield msg;
|
|
150267
150130
|
else log.debug("stream-json: ignoring unknown stdin message type", { type: msg.type });
|
|
150268
150131
|
}
|
|
150269
150132
|
}
|
|
@@ -150351,7 +150214,8 @@ async function runStreamJson(opts) {
|
|
|
150351
150214
|
error: String(error)
|
|
150352
150215
|
});
|
|
150353
150216
|
}
|
|
150354
|
-
|
|
150217
|
+
const hasSystemPrompt = opts.systemPrompt && opts.systemPrompt.trim().length > 0;
|
|
150218
|
+
if (hasSystemPrompt || appendPrompt) {
|
|
150355
150219
|
try {
|
|
150356
150220
|
originalAgentsMd = await readFile(agentsMdPath, "utf-8");
|
|
150357
150221
|
} catch {}
|
|
@@ -150360,10 +150224,13 @@ async function runStreamJson(opts) {
|
|
|
150360
150224
|
cc-connect send --image /absolute/path/to/image.png
|
|
150361
150225
|
cc-connect send --file /absolute/path/to/file.pdf
|
|
150362
150226
|
当用户要求你发送文件、截图、生成的图片时,使用 Bash 工具执行上述命令即可。
|
|
150363
|
-
\n${appendPrompt}`;
|
|
150227
|
+
\n${hasSystemPrompt ? `# System Prompt (from --system-prompt)\n\n${opts.systemPrompt}\n` : ""}\n${appendPrompt ? appendPrompt : ""}`;
|
|
150364
150228
|
await writeFile(agentsMdPath, originalAgentsMd ? `${ccPrompt}\n\n${originalAgentsMd}` : ccPrompt, "utf-8");
|
|
150365
150229
|
injectedAgentsMd = true;
|
|
150366
|
-
log.info("stream-json: injected cc-connect system prompt into AGENTS.md"
|
|
150230
|
+
log.info("stream-json: injected cc-connect system prompt into AGENTS.md", {
|
|
150231
|
+
hasSystemPrompt,
|
|
150232
|
+
hasAppendPrompt: appendPrompt.length > 0
|
|
150233
|
+
});
|
|
150367
150234
|
}
|
|
150368
150235
|
try {
|
|
150369
150236
|
await harness.ensureConfigFile();
|
|
@@ -150382,6 +150249,17 @@ async function runStreamJson(opts) {
|
|
|
150382
150249
|
} else log.warn("stream-json: control_response for unknown request_id", { requestId: msg.response.request_id });
|
|
150383
150250
|
continue;
|
|
150384
150251
|
}
|
|
150252
|
+
if (msg.type === "control_cancel_request") {
|
|
150253
|
+
const pending = pendingApprovals.get(msg.request_id);
|
|
150254
|
+
if (pending) {
|
|
150255
|
+
pendingApprovals.delete(msg.request_id);
|
|
150256
|
+
pending.resolve({
|
|
150257
|
+
decision: "rejected",
|
|
150258
|
+
feedback: "Permission request cancelled"
|
|
150259
|
+
});
|
|
150260
|
+
}
|
|
150261
|
+
continue;
|
|
150262
|
+
}
|
|
150385
150263
|
const userText = extractUserText(msg);
|
|
150386
150264
|
if (!userText) {
|
|
150387
150265
|
log.warn("stream-json: empty user message, skipping");
|
|
@@ -150414,7 +150292,12 @@ async function runStreamJson(opts) {
|
|
|
150414
150292
|
workDir,
|
|
150415
150293
|
model,
|
|
150416
150294
|
permission: mappedPermission,
|
|
150417
|
-
planMode: mappedPlanMode
|
|
150295
|
+
planMode: mappedPlanMode,
|
|
150296
|
+
thinking: opts.effort,
|
|
150297
|
+
metadata: {
|
|
150298
|
+
source: "cc-connect",
|
|
150299
|
+
agentType: "scream-code"
|
|
150300
|
+
}
|
|
150418
150301
|
});
|
|
150419
150302
|
log.info("stream-json: recreated session", { sessionId: session.id });
|
|
150420
150303
|
}
|
|
@@ -150425,14 +150308,19 @@ async function runStreamJson(opts) {
|
|
|
150425
150308
|
workDir,
|
|
150426
150309
|
model,
|
|
150427
150310
|
permission: mappedPermission,
|
|
150428
|
-
planMode: mappedPlanMode
|
|
150311
|
+
planMode: mappedPlanMode,
|
|
150312
|
+
thinking: opts.effort,
|
|
150313
|
+
metadata: {
|
|
150314
|
+
source: "cc-connect",
|
|
150315
|
+
agentType: "scream-code"
|
|
150316
|
+
}
|
|
150429
150317
|
});
|
|
150430
150318
|
log.info("stream-json: created session", { sessionId: session.id });
|
|
150431
150319
|
}
|
|
150432
150320
|
currentSessionId = session.id;
|
|
150433
150321
|
writer.setSessionId(session.id);
|
|
150434
150322
|
writer.setModel(opts.model ?? config.defaultModel ?? "");
|
|
150435
|
-
writer.emitSystem(sessionKey);
|
|
150323
|
+
writer.emitSystem(sessionKey, opts.model ?? config.defaultModel);
|
|
150436
150324
|
function sendControlRequest(request) {
|
|
150437
150325
|
let resolve;
|
|
150438
150326
|
const promise = new Promise((res) => {
|
|
@@ -150443,25 +150331,55 @@ async function runStreamJson(opts) {
|
|
|
150443
150331
|
writer.emitControlRequest(reqId, request.toolCallId, request.toolName, request.display);
|
|
150444
150332
|
return promise;
|
|
150445
150333
|
}
|
|
150334
|
+
const allowedSet = opts.allowedTools ? new Set(opts.allowedTools.split(",").map((t) => t.trim()).filter(Boolean)) : void 0;
|
|
150335
|
+
const disallowedSet = opts.disallowedTools ? new Set(opts.disallowedTools.split(",").map((t) => t.trim()).filter(Boolean)) : void 0;
|
|
150336
|
+
function isToolBlocked(toolName) {
|
|
150337
|
+
if (disallowedSet?.has(toolName)) return true;
|
|
150338
|
+
if (allowedSet && allowedSet.size > 0 && !allowedSet.has(toolName)) return true;
|
|
150339
|
+
return false;
|
|
150340
|
+
}
|
|
150446
150341
|
switch (opts.permissionMode) {
|
|
150447
150342
|
case "yolo":
|
|
150448
150343
|
case "bypassPermissions":
|
|
150449
|
-
session.setApprovalHandler(() =>
|
|
150344
|
+
session.setApprovalHandler((request) => {
|
|
150345
|
+
if (isToolBlocked(request.toolName)) return {
|
|
150346
|
+
decision: "rejected",
|
|
150347
|
+
feedback: `Tool ${request.toolName} is disallowed`
|
|
150348
|
+
};
|
|
150349
|
+
return { decision: "approved" };
|
|
150350
|
+
});
|
|
150450
150351
|
break;
|
|
150451
150352
|
case "dontAsk":
|
|
150452
|
-
session.setApprovalHandler(() =>
|
|
150453
|
-
|
|
150454
|
-
|
|
150455
|
-
|
|
150353
|
+
session.setApprovalHandler((request) => {
|
|
150354
|
+
if (disallowedSet?.has(request.toolName)) return {
|
|
150355
|
+
decision: "rejected",
|
|
150356
|
+
feedback: `Tool ${request.toolName} is disallowed`
|
|
150357
|
+
};
|
|
150358
|
+
if (allowedSet?.has(request.toolName)) return { decision: "approved" };
|
|
150359
|
+
return {
|
|
150360
|
+
decision: "rejected",
|
|
150361
|
+
feedback: "dontAsk mode: tool call auto-denied"
|
|
150362
|
+
};
|
|
150363
|
+
});
|
|
150456
150364
|
break;
|
|
150457
150365
|
case "acceptEdits":
|
|
150458
150366
|
session.setApprovalHandler((request) => {
|
|
150367
|
+
if (isToolBlocked(request.toolName)) return {
|
|
150368
|
+
decision: "rejected",
|
|
150369
|
+
feedback: `Tool ${request.toolName} is disallowed`
|
|
150370
|
+
};
|
|
150459
150371
|
if (["Edit", "Write"].includes(request.toolName)) return { decision: "approved" };
|
|
150460
150372
|
return sendControlRequest(request);
|
|
150461
150373
|
});
|
|
150462
150374
|
break;
|
|
150463
150375
|
default:
|
|
150464
|
-
session.setApprovalHandler((request) =>
|
|
150376
|
+
session.setApprovalHandler((request) => {
|
|
150377
|
+
if (isToolBlocked(request.toolName)) return {
|
|
150378
|
+
decision: "rejected",
|
|
150379
|
+
feedback: `Tool ${request.toolName} is disallowed`
|
|
150380
|
+
};
|
|
150381
|
+
return sendControlRequest(request);
|
|
150382
|
+
});
|
|
150465
150383
|
break;
|
|
150466
150384
|
}
|
|
150467
150385
|
session.setQuestionHandler(() => null);
|
|
@@ -150526,6 +150444,10 @@ async function runStreamJson(opts) {
|
|
|
150526
150444
|
if (type === "turn.step.started" || type === "turn.step.interrupted") writer.flushAssistant();
|
|
150527
150445
|
else if (type === "turn.step.retrying") writer.discardAssistant();
|
|
150528
150446
|
else if (type === "assistant.delta") writer.writeAssistantDelta(event.delta);
|
|
150447
|
+
else if (type === "thinking.delta") writer.writeThinkingDelta(event.delta);
|
|
150448
|
+
else if (type === "tool.call.started") writer.writeToolCall(event.toolCallId, event.name, event.args);
|
|
150449
|
+
else if (type === "tool.call.delta") writer.writeToolCallDelta(event.toolCallId, event.name, event.argumentsPart);
|
|
150450
|
+
else if (type === "tool.result") writer.writeToolResult(event.toolCallId, event.output, event.isError);
|
|
150529
150451
|
else if (type === "turn.step.completed") {
|
|
150530
150452
|
if (event.usage) {
|
|
150531
150453
|
const inputTotal = (event.usage.inputOther ?? 0) + (event.usage.inputCacheRead ?? 0) + (event.usage.inputCacheCreation ?? 0);
|
|
@@ -150658,11 +150580,6 @@ async function handleMainCommand(opts, version) {
|
|
|
150658
150580
|
}
|
|
150659
150581
|
await runShell(validated.options, version);
|
|
150660
150582
|
}
|
|
150661
|
-
/** `scream migrate` — permanently disabled. */
|
|
150662
|
-
async function handleMigrateCommand() {
|
|
150663
|
-
process.stdout.write("迁移功能已取消,不再支持从 scream-cli 导入数据。\n");
|
|
150664
|
-
process.exit(0);
|
|
150665
|
-
}
|
|
150666
150583
|
function main() {
|
|
150667
150584
|
initProcessName();
|
|
150668
150585
|
const version = getVersion();
|
|
@@ -150674,13 +150591,6 @@ function main() {
|
|
|
150674
150591
|
process.stderr.write(`查看日志:${resolveGlobalLogPath(resolveScreamHome())}\n`);
|
|
150675
150592
|
process.exit(1);
|
|
150676
150593
|
});
|
|
150677
|
-
}, () => {
|
|
150678
|
-
handleMigrateCommand().catch(async (error) => {
|
|
150679
|
-
await logStartupFailure("运行迁移", error);
|
|
150680
|
-
process.stderr.write(formatStartupError(error, { operation: "运行迁移" }));
|
|
150681
|
-
process.stderr.write(`查看日志:${resolveGlobalLogPath(resolveScreamHome())}\n`);
|
|
150682
|
-
process.exit(1);
|
|
150683
|
-
});
|
|
150684
150594
|
}, (entry, args) => {
|
|
150685
150595
|
runPluginNodeEntry(entry, args).catch(async (error) => {
|
|
150686
150596
|
await logStartupFailure("运行插件节点入口", error);
|