scream-code 0.4.0 → 0.4.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/dist/main.mjs +290 -60
- package/package.json +1 -1
package/dist/main.mjs
CHANGED
|
@@ -1042,6 +1042,16 @@ var APIContextOverflowError = class extends APIStatusError {
|
|
|
1042
1042
|
}
|
|
1043
1043
|
};
|
|
1044
1044
|
/**
|
|
1045
|
+
* HTTP status error that specifically means the provider rate-limited the
|
|
1046
|
+
* request.
|
|
1047
|
+
*/
|
|
1048
|
+
var APIProviderRateLimitError = class extends APIStatusError {
|
|
1049
|
+
constructor(message, requestId) {
|
|
1050
|
+
super(429, message, requestId);
|
|
1051
|
+
this.name = "APIProviderRateLimitError";
|
|
1052
|
+
}
|
|
1053
|
+
};
|
|
1054
|
+
/**
|
|
1045
1055
|
* The API returned an empty response (no content, no tool calls).
|
|
1046
1056
|
*/
|
|
1047
1057
|
var APIEmptyResponseError = class extends ChatProviderError {
|
|
@@ -1075,6 +1085,7 @@ function isContextOverflowErrorCode(code) {
|
|
|
1075
1085
|
return code === "context_length_exceeded";
|
|
1076
1086
|
}
|
|
1077
1087
|
function normalizeAPIStatusError(statusCode, message, requestId) {
|
|
1088
|
+
if (statusCode === 429) return new APIProviderRateLimitError(message, requestId);
|
|
1078
1089
|
if (isContextOverflowStatusError(statusCode, message)) return new APIContextOverflowError(statusCode, message, requestId);
|
|
1079
1090
|
return new APIStatusError(statusCode, message, requestId);
|
|
1080
1091
|
}
|
|
@@ -1084,6 +1095,94 @@ function isContextOverflowStatusError(statusCode, message) {
|
|
|
1084
1095
|
return CONTEXT_OVERFLOW_MESSAGE_PATTERNS.some((pattern) => pattern.test(lowerMessage));
|
|
1085
1096
|
}
|
|
1086
1097
|
//#endregion
|
|
1098
|
+
//#region ../../packages/ltod/src/providers/tool-call-id.ts
|
|
1099
|
+
const EMPTY_TOOL_CALL_ID = "tool_call";
|
|
1100
|
+
const TOOL_CALL_ID_SAFE_CHARS = /[^a-zA-Z0-9_-]/g;
|
|
1101
|
+
function sanitizeToolCallId(id, maxLength) {
|
|
1102
|
+
const sanitized = id.replace(TOOL_CALL_ID_SAFE_CHARS, "_");
|
|
1103
|
+
return maxLength === void 0 ? sanitized : sanitized.slice(0, maxLength);
|
|
1104
|
+
}
|
|
1105
|
+
function sanitizeOpenAIResponsesCallId(id, maxLength) {
|
|
1106
|
+
const [callId] = id.split("|", 1);
|
|
1107
|
+
return sanitizeToolCallId(callId ?? id, maxLength);
|
|
1108
|
+
}
|
|
1109
|
+
function normalizeToolCallIdsForProvider(messages, policy) {
|
|
1110
|
+
const rawIds = collectToolCallIds(messages);
|
|
1111
|
+
if (rawIds.length === 0) return messages;
|
|
1112
|
+
const mappedIds = buildToolCallIdMap(rawIds, policy);
|
|
1113
|
+
let changed = false;
|
|
1114
|
+
const normalizedMessages = messages.map((message) => {
|
|
1115
|
+
let messageChanged = false;
|
|
1116
|
+
let toolCalls = message.toolCalls;
|
|
1117
|
+
if (message.toolCalls.length > 0) toolCalls = message.toolCalls.map((toolCall) => {
|
|
1118
|
+
const mappedId = mappedIds.get(toolCall.id);
|
|
1119
|
+
if (mappedId === void 0 || mappedId === toolCall.id) return toolCall;
|
|
1120
|
+
messageChanged = true;
|
|
1121
|
+
return {
|
|
1122
|
+
...toolCall,
|
|
1123
|
+
id: mappedId
|
|
1124
|
+
};
|
|
1125
|
+
});
|
|
1126
|
+
const mappedToolCallId = (message.toolCallId === void 0 ? void 0 : mappedIds.get(message.toolCallId)) ?? message.toolCallId;
|
|
1127
|
+
if (mappedToolCallId !== message.toolCallId) messageChanged = true;
|
|
1128
|
+
if (!messageChanged) return message;
|
|
1129
|
+
changed = true;
|
|
1130
|
+
return {
|
|
1131
|
+
...message,
|
|
1132
|
+
toolCalls,
|
|
1133
|
+
toolCallId: mappedToolCallId
|
|
1134
|
+
};
|
|
1135
|
+
});
|
|
1136
|
+
return changed ? normalizedMessages : messages;
|
|
1137
|
+
}
|
|
1138
|
+
function collectToolCallIds(messages) {
|
|
1139
|
+
const ids = [];
|
|
1140
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1141
|
+
const append = (id) => {
|
|
1142
|
+
if (seen.has(id)) return;
|
|
1143
|
+
seen.add(id);
|
|
1144
|
+
ids.push(id);
|
|
1145
|
+
};
|
|
1146
|
+
for (const message of messages) {
|
|
1147
|
+
for (const toolCall of message.toolCalls) append(toolCall.id);
|
|
1148
|
+
if (message.toolCallId !== void 0) append(message.toolCallId);
|
|
1149
|
+
}
|
|
1150
|
+
return ids;
|
|
1151
|
+
}
|
|
1152
|
+
function buildToolCallIdMap(rawIds, policy) {
|
|
1153
|
+
const mappedIds = /* @__PURE__ */ new Map();
|
|
1154
|
+
const usedIds = /* @__PURE__ */ new Set();
|
|
1155
|
+
for (const rawId of rawIds) {
|
|
1156
|
+
const normalized = policy.normalize(rawId);
|
|
1157
|
+
if (normalized === rawId && normalized.length > 0) {
|
|
1158
|
+
mappedIds.set(rawId, normalized);
|
|
1159
|
+
usedIds.add(normalized);
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
for (const rawId of rawIds) {
|
|
1163
|
+
if (mappedIds.has(rawId)) continue;
|
|
1164
|
+
const unique = makeUniqueToolCallId(policy.normalize(rawId), usedIds, policy.maxLength);
|
|
1165
|
+
mappedIds.set(rawId, unique);
|
|
1166
|
+
usedIds.add(unique);
|
|
1167
|
+
}
|
|
1168
|
+
return mappedIds;
|
|
1169
|
+
}
|
|
1170
|
+
function makeUniqueToolCallId(normalized, usedIds, maxLength) {
|
|
1171
|
+
const base = normalized.length > 0 ? normalized : EMPTY_TOOL_CALL_ID;
|
|
1172
|
+
const candidate = truncateToolCallId(base, maxLength, "");
|
|
1173
|
+
if (!usedIds.has(candidate)) return candidate;
|
|
1174
|
+
for (let i = 2;; i++) {
|
|
1175
|
+
const suffixed = truncateToolCallId(base, maxLength, `_${i}`);
|
|
1176
|
+
if (!usedIds.has(suffixed)) return suffixed;
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
function truncateToolCallId(base, maxLength, suffix) {
|
|
1180
|
+
if (maxLength === void 0) return `${base}${suffix}`;
|
|
1181
|
+
const baseLength = maxLength - suffix.length;
|
|
1182
|
+
if (baseLength <= 0) throw new Error(`Tool call id maxLength ${maxLength} is too small for suffix ${suffix}.`);
|
|
1183
|
+
return `${base.slice(0, baseLength)}${suffix}`;
|
|
1184
|
+
}
|
|
1185
|
+
//#endregion
|
|
1087
1186
|
//#region ../../node_modules/.pnpm/@anthropic-ai+sdk@0.95.2_zod@4.4.3/node_modules/@anthropic-ai/sdk/internal/tslib.mjs
|
|
1088
1187
|
function __classPrivateFieldSet$1(receiver, state, value, kind, f) {
|
|
1089
1188
|
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
@@ -8946,6 +9045,10 @@ function budgetTokensForEffort(effort) {
|
|
|
8946
9045
|
}
|
|
8947
9046
|
throw new Error(`Unknown thinking effort: ${String(effort)}`);
|
|
8948
9047
|
}
|
|
9048
|
+
const ANTHROPIC_TOOL_CALL_ID_POLICY = {
|
|
9049
|
+
normalize: (id) => sanitizeToolCallId(id, 64),
|
|
9050
|
+
maxLength: 64
|
|
9051
|
+
};
|
|
8949
9052
|
const CACHE_CONTROL = { type: "ephemeral" };
|
|
8950
9053
|
/**
|
|
8951
9054
|
* Content block types that support cache_control injection.
|
|
@@ -9347,8 +9450,9 @@ var AnthropicChatProvider = class {
|
|
|
9347
9450
|
text: systemPrompt,
|
|
9348
9451
|
cache_control: CACHE_CONTROL
|
|
9349
9452
|
}] : void 0;
|
|
9453
|
+
const normalizedHistory = normalizeToolCallIdsForProvider(history, ANTHROPIC_TOOL_CALL_ID_POLICY);
|
|
9350
9454
|
const messages = [];
|
|
9351
|
-
for (const msg of
|
|
9455
|
+
for (const msg of normalizedHistory) {
|
|
9352
9456
|
const converted = convertMessage$3(msg);
|
|
9353
9457
|
const last = messages.at(-1);
|
|
9354
9458
|
if (last !== void 0 && isToolResultOnly(last) && isToolResultOnly(converted)) last.content = [...last.content, ...converted.content];
|
|
@@ -48884,6 +48988,10 @@ const KNOWN_REASONING_KEYS = [
|
|
|
48884
48988
|
"reasoning"
|
|
48885
48989
|
];
|
|
48886
48990
|
const DEFAULT_OUTBOUND_REASONING_KEY = KNOWN_REASONING_KEYS[0];
|
|
48991
|
+
const OPENAI_CHAT_TOOL_CALL_ID_POLICY = {
|
|
48992
|
+
normalize: (id) => sanitizeToolCallId(id, 64),
|
|
48993
|
+
maxLength: 64
|
|
48994
|
+
};
|
|
48887
48995
|
function extractReasoningContent(source, explicitKey) {
|
|
48888
48996
|
if (typeof source !== "object" || source === null) return void 0;
|
|
48889
48997
|
const record = source;
|
|
@@ -49060,7 +49168,8 @@ var OpenAILegacyChatProvider = class {
|
|
|
49060
49168
|
role: "system",
|
|
49061
49169
|
content: systemPrompt
|
|
49062
49170
|
});
|
|
49063
|
-
|
|
49171
|
+
const normalizedHistory = normalizeToolCallIdsForProvider(history, OPENAI_CHAT_TOOL_CALL_ID_POLICY);
|
|
49172
|
+
for (const msg of normalizedHistory) messages.push(convertMessage$1(msg, this._reasoningKey, this._toolMessageConversion));
|
|
49064
49173
|
const kwargs = { ...this._generationKwargs };
|
|
49065
49174
|
let reasoningEffort = this._reasoningEffort;
|
|
49066
49175
|
if (reasoningEffort === void 0 && kwargs["reasoning_effort"] === void 0) {
|
|
@@ -49161,6 +49270,10 @@ function normalizeResponsesFinishReason(status, incompleteReason) {
|
|
|
49161
49270
|
rawFinishReason: null
|
|
49162
49271
|
};
|
|
49163
49272
|
}
|
|
49273
|
+
const OPENAI_RESPONSES_TOOL_CALL_ID_POLICY = {
|
|
49274
|
+
normalize: (id) => sanitizeOpenAIResponsesCallId(id, 64),
|
|
49275
|
+
maxLength: 64
|
|
49276
|
+
};
|
|
49164
49277
|
function asRawObject(value) {
|
|
49165
49278
|
if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
|
|
49166
49279
|
return value;
|
|
@@ -49685,7 +49798,8 @@ var OpenAIResponsesChatProvider = class {
|
|
|
49685
49798
|
if (usesOpenAIResponsesDeveloperRole(this._model)) sysItem["role"] = "developer";
|
|
49686
49799
|
input.push(sysItem);
|
|
49687
49800
|
}
|
|
49688
|
-
|
|
49801
|
+
const normalizedHistory = normalizeToolCallIdsForProvider(history, OPENAI_RESPONSES_TOOL_CALL_ID_POLICY);
|
|
49802
|
+
for (const msg of normalizedHistory) input.push(...convertMessage(msg, this._model, this._toolMessageConversion));
|
|
49689
49803
|
const kwargs = { ...this._generationKwargs };
|
|
49690
49804
|
const reasoningEffort = kwargs["reasoning_effort"];
|
|
49691
49805
|
delete kwargs["reasoning_effort"];
|
|
@@ -72232,9 +72346,11 @@ function maybeStatusCode(error) {
|
|
|
72232
72346
|
//#endregion
|
|
72233
72347
|
//#region ../../packages/agent-core/src/agent/context/projector.ts
|
|
72234
72348
|
function project(history) {
|
|
72235
|
-
|
|
72349
|
+
const usable = history.filter((message) => {
|
|
72236
72350
|
return message.partial !== true && !(message.role === "assistant" && message.content.length === 0 && message.toolCalls.length === 0);
|
|
72237
|
-
})
|
|
72351
|
+
});
|
|
72352
|
+
const last = usable.at(-1);
|
|
72353
|
+
return mergeAdjacentUserMessages(last?.role === "assistant" && last.toolCalls.length > 0 ? usable.slice(0, -1) : usable);
|
|
72238
72354
|
}
|
|
72239
72355
|
function mergeAdjacentUserMessages(history) {
|
|
72240
72356
|
const out = [];
|
|
@@ -85499,7 +85615,7 @@ async function finalizePendingToolResult(step, pendingResult) {
|
|
|
85499
85615
|
async function executeTool(step, execution, toolCall, toolName, metadata) {
|
|
85500
85616
|
const { dispatchEvent, signal, turnId } = step;
|
|
85501
85617
|
signal.throwIfAborted();
|
|
85502
|
-
return
|
|
85618
|
+
return raceExecuteWithGraceTimeout(execution.execute({
|
|
85503
85619
|
turnId,
|
|
85504
85620
|
toolCallId: toolCall.id,
|
|
85505
85621
|
metadata,
|
|
@@ -85514,10 +85630,8 @@ async function executeTool(step, execution, toolCall, toolName, metadata) {
|
|
|
85514
85630
|
}
|
|
85515
85631
|
}), signal, toolName);
|
|
85516
85632
|
}
|
|
85517
|
-
|
|
85518
|
-
async function raceExecuteWithGraceAndHardTimeout(executePromise, signal, toolName) {
|
|
85633
|
+
async function raceExecuteWithGraceTimeout(executePromise, signal, toolName) {
|
|
85519
85634
|
let graceTimer;
|
|
85520
|
-
let hardTimer;
|
|
85521
85635
|
let onAbort;
|
|
85522
85636
|
const graceSentinel = new Promise((resolve) => {
|
|
85523
85637
|
const armTimer = () => {
|
|
@@ -85534,23 +85648,10 @@ async function raceExecuteWithGraceAndHardTimeout(executePromise, signal, toolNa
|
|
|
85534
85648
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
85535
85649
|
}
|
|
85536
85650
|
});
|
|
85537
|
-
const hardSentinel = new Promise((resolve) => {
|
|
85538
|
-
hardTimer = setTimeout(() => {
|
|
85539
|
-
resolve({
|
|
85540
|
-
output: `Tool "${toolName}" exceeded hard timeout (${String(HARD_TIMEOUT_MS)}ms)`,
|
|
85541
|
-
isError: true
|
|
85542
|
-
});
|
|
85543
|
-
}, HARD_TIMEOUT_MS);
|
|
85544
|
-
});
|
|
85545
85651
|
try {
|
|
85546
|
-
return await Promise.race([
|
|
85547
|
-
executePromise,
|
|
85548
|
-
graceSentinel,
|
|
85549
|
-
hardSentinel
|
|
85550
|
-
]);
|
|
85652
|
+
return await Promise.race([executePromise, graceSentinel]);
|
|
85551
85653
|
} finally {
|
|
85552
85654
|
if (graceTimer !== void 0) clearTimeout(graceTimer);
|
|
85553
|
-
if (hardTimer !== void 0) clearTimeout(hardTimer);
|
|
85554
85655
|
if (onAbort !== void 0) try {
|
|
85555
85656
|
signal.removeEventListener("abort", onAbort);
|
|
85556
85657
|
} catch {}
|
|
@@ -97111,6 +97212,16 @@ async function parseManifest(pluginRoot) {
|
|
|
97111
97212
|
manifestPath: skillMdPath,
|
|
97112
97213
|
diagnostics: []
|
|
97113
97214
|
};
|
|
97215
|
+
const discoveredSkillDirs = await discoverSkillDirs(pluginRoot, 3);
|
|
97216
|
+
if (discoveredSkillDirs.length > 0) return {
|
|
97217
|
+
manifest: {
|
|
97218
|
+
name: path.basename(pluginRoot),
|
|
97219
|
+
skills: discoveredSkillDirs
|
|
97220
|
+
},
|
|
97221
|
+
manifestKind: "bare-skill",
|
|
97222
|
+
manifestPath: path.join(discoveredSkillDirs[0], BARE_SKILL_PATH),
|
|
97223
|
+
diagnostics: []
|
|
97224
|
+
};
|
|
97114
97225
|
return { diagnostics: [{
|
|
97115
97226
|
severity: "error",
|
|
97116
97227
|
message: `No manifest at ${SCREAM_PLUGIN_ROOT_PATH}, ${SCREAM_PLUGIN_DIR_PATH}, or ${CLAUDE_PLUGIN_DIR_PATH}`
|
|
@@ -97409,6 +97520,34 @@ function isWithin$1(child, parent) {
|
|
|
97409
97520
|
const relative = path.relative(parent, child);
|
|
97410
97521
|
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
97411
97522
|
}
|
|
97523
|
+
/**
|
|
97524
|
+
* Recursively scan for `SKILL.md` files up to `maxDepth` levels below `root`.
|
|
97525
|
+
* Returns the unique parent directories, deduplicated so that a nested skill
|
|
97526
|
+
* dir is not listed if its ancestor is already a skill root.
|
|
97527
|
+
*/
|
|
97528
|
+
async function discoverSkillDirs(root, maxDepth) {
|
|
97529
|
+
const found = [];
|
|
97530
|
+
async function walk(dir, depth) {
|
|
97531
|
+
if (depth > maxDepth) return;
|
|
97532
|
+
let entries;
|
|
97533
|
+
try {
|
|
97534
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
97535
|
+
} catch {
|
|
97536
|
+
return;
|
|
97537
|
+
}
|
|
97538
|
+
for (const entry of entries) {
|
|
97539
|
+
if (!entry.isDirectory()) continue;
|
|
97540
|
+
const child = path.join(dir, entry.name);
|
|
97541
|
+
if (await isFile$1(path.join(child, BARE_SKILL_PATH))) found.push(child);
|
|
97542
|
+
await walk(child, depth + 1);
|
|
97543
|
+
}
|
|
97544
|
+
}
|
|
97545
|
+
await walk(root, 1);
|
|
97546
|
+
const sorted = found.sort((a, b) => a.length - b.length);
|
|
97547
|
+
const result = [];
|
|
97548
|
+
for (const dir of sorted) if (!result.some((parent) => dir.startsWith(parent + path.sep))) result.push(dir);
|
|
97549
|
+
return result;
|
|
97550
|
+
}
|
|
97412
97551
|
async function isFile$1(p) {
|
|
97413
97552
|
try {
|
|
97414
97553
|
return (await stat(p)).isFile();
|
|
@@ -112953,12 +113092,15 @@ var SessionStore = class {
|
|
|
112953
113092
|
async create(input) {
|
|
112954
113093
|
assertSafeSessionId(input.id);
|
|
112955
113094
|
const workDir = normalizeWorkDir(input.workDir);
|
|
112956
|
-
if (await this.findSessionEntry(input.id) !== void 0) throw new ScreamError(ErrorCodes.SESSION_ALREADY_EXISTS, `Session "${input.id}" already exists`);
|
|
112957
113095
|
const dir = this.sessionDirFor({
|
|
112958
113096
|
id: input.id,
|
|
112959
113097
|
workDir
|
|
112960
113098
|
});
|
|
112961
|
-
if (await
|
|
113099
|
+
if (await this.findSessionEntry(input.id) !== void 0) await this.delete(input.id);
|
|
113100
|
+
else if (await isDirectory(dir)) await rm(dir, {
|
|
113101
|
+
recursive: true,
|
|
113102
|
+
force: true
|
|
113103
|
+
});
|
|
112962
113104
|
await mkdir(dir, {
|
|
112963
113105
|
recursive: true,
|
|
112964
113106
|
mode: 448
|
|
@@ -113029,11 +113171,12 @@ var SessionStore = class {
|
|
|
113029
113171
|
}
|
|
113030
113172
|
async delete(id) {
|
|
113031
113173
|
assertSafeSessionId(id);
|
|
113032
|
-
|
|
113174
|
+
const entry = await this.findSessionEntry(id);
|
|
113175
|
+
if (entry !== void 0) await rm(entry.sessionDir, {
|
|
113033
113176
|
recursive: true,
|
|
113034
113177
|
force: true
|
|
113035
|
-
});
|
|
113036
|
-
await removeSessionIndexEntry(this.homeDir, id);
|
|
113178
|
+
}).catch(() => {});
|
|
113179
|
+
await removeSessionIndexEntry(this.homeDir, id).catch(() => {});
|
|
113037
113180
|
}
|
|
113038
113181
|
async list(options = {}) {
|
|
113039
113182
|
const workDir = options.workDir === void 0 ? void 0 : normalizeRequiredWorkDir(options.workDir);
|
|
@@ -125364,12 +125507,6 @@ const BUILTIN_REGISTRY = [
|
|
|
125364
125507
|
description: "GreenSock 动画平台全套参考手册,含核心 API、Timeline、ScrollTrigger、插件、React 集成等 8 个技能",
|
|
125365
125508
|
source: "https://github.com/greensock/gsap-skills"
|
|
125366
125509
|
},
|
|
125367
|
-
{
|
|
125368
|
-
id: "gorden-ppt-skill",
|
|
125369
|
-
displayName: "Gorden PPT 助手",
|
|
125370
|
-
description: "17 套精修中文 PPT 模板,支持 python-pptx 编辑生成,适配国企/互联网大厂风格",
|
|
125371
|
-
source: "https://github.com/GordenSun/GordenPPTSkill"
|
|
125372
|
-
},
|
|
125373
125510
|
{
|
|
125374
125511
|
id: "claude-design-card",
|
|
125375
125512
|
displayName: "Claude Design Card",
|
|
@@ -125412,18 +125549,6 @@ const BUILTIN_REGISTRY = [
|
|
|
125412
125549
|
description: "专利交底书自动生成:专利点挖掘 → 国知局查新 → 脱敏成文 → 自检闭环,Mermaid 附图,输出 .docx",
|
|
125413
125550
|
source: "https://github.com/handsomestWei/patent-disclosure-skill"
|
|
125414
125551
|
},
|
|
125415
|
-
{
|
|
125416
|
-
id: "html-ppt-skill",
|
|
125417
|
-
displayName: "HTML PPT Studio 演示文稿",
|
|
125418
|
-
description: "AI 驱动 HTML 幻灯片:36 套主题 × 31 种布局 × 47 种动画,纯静态 HTML/CSS/JS,支持演讲者模式",
|
|
125419
|
-
source: "https://github.com/lewislulu/html-ppt-skill"
|
|
125420
|
-
},
|
|
125421
|
-
{
|
|
125422
|
-
id: "uzi-skill",
|
|
125423
|
-
displayName: "UZI Skill 股票分析引擎",
|
|
125424
|
-
description: "A股/港股/美股深度分析:22 数据维度 × 180 量化规则 × 17 机构分析法 × 51 投资大师人格模拟,输出 Bloomberg 风格 HTML 报告",
|
|
125425
|
-
source: "https://github.com/wbh604/UZI-Skill"
|
|
125426
|
-
},
|
|
125427
125552
|
{
|
|
125428
125553
|
id: "contract-review-pro",
|
|
125429
125554
|
displayName: "Contract Review Pro 合同审查",
|
|
@@ -125441,6 +125566,66 @@ const BUILTIN_REGISTRY = [
|
|
|
125441
125566
|
displayName: "Headroom 压缩优化",
|
|
125442
125567
|
description: "在内容送达 LLM 前压缩工具输出、日志、文件和 RAG 块,节省 60-95% Token,答案质量不变",
|
|
125443
125568
|
source: "https://github.com/chopratejas/headroom"
|
|
125569
|
+
},
|
|
125570
|
+
{
|
|
125571
|
+
id: "xiaohu-wechat-format",
|
|
125572
|
+
displayName: "小壶公众号排版",
|
|
125573
|
+
description: "Markdown → 微信兼容 HTML → 推送草稿箱,30 套主题 + 可视化画廊,一键排版发布",
|
|
125574
|
+
source: "https://github.com/xiaohuailabs/xiaohu-wechat-format"
|
|
125575
|
+
},
|
|
125576
|
+
{
|
|
125577
|
+
id: "huashu-design",
|
|
125578
|
+
displayName: "花束设计",
|
|
125579
|
+
description: "HTML 原生设计技能:高保真原型 / 幻灯片 / 动画 + 20 设计哲学 + 5 维评审 + MP4 导出",
|
|
125580
|
+
source: "https://github.com/alchaincyf/huashu-design"
|
|
125581
|
+
},
|
|
125582
|
+
{
|
|
125583
|
+
id: "html-video",
|
|
125584
|
+
displayName: "HTML Video 视频生成",
|
|
125585
|
+
description: "HTML 转 MP4:可插拔渲染引擎 + 21 套模板 + AI 配乐,全程本地,零渲染费用",
|
|
125586
|
+
source: "https://github.com/nexu-io/html-video"
|
|
125587
|
+
},
|
|
125588
|
+
{
|
|
125589
|
+
id: "xiaohu-video-translate",
|
|
125590
|
+
displayName: "小壶视频翻译",
|
|
125591
|
+
description: "外语视频自动配中文字幕:下载 / 转写 / 翻译 / 润色 / 烧录一条龙,全程本地",
|
|
125592
|
+
source: "https://github.com/xiaohuailabs/xiaohu-video-translate"
|
|
125593
|
+
},
|
|
125594
|
+
{
|
|
125595
|
+
id: "videocut-skills",
|
|
125596
|
+
displayName: "视频剪辑 Agent",
|
|
125597
|
+
description: "Claude Code Skills 驱动的视频剪辑 Agent:口播剪辑 / 字幕导入 / 画质高清化",
|
|
125598
|
+
source: "https://github.com/Ceeon/videocut-skills"
|
|
125599
|
+
},
|
|
125600
|
+
{
|
|
125601
|
+
id: "taste-skill",
|
|
125602
|
+
displayName: "Taste Skill 设计品味",
|
|
125603
|
+
description: "给 AI 好品味:阻止生成无聊通用的设计,输出有质感的方案",
|
|
125604
|
+
source: "https://github.com/Leonxlnx/taste-skill"
|
|
125605
|
+
},
|
|
125606
|
+
{
|
|
125607
|
+
id: "vtake-skills",
|
|
125608
|
+
displayName: "VTake 视频剪辑",
|
|
125609
|
+
description: "Agent Skills 驱动的视频剪辑工具",
|
|
125610
|
+
source: "https://github.com/notedit/vtake-skills"
|
|
125611
|
+
},
|
|
125612
|
+
{
|
|
125613
|
+
id: "remotion-skills",
|
|
125614
|
+
displayName: "Remotion 视频技能",
|
|
125615
|
+
description: "Remotion(React 视频框架)官方技能包",
|
|
125616
|
+
source: "https://github.com/remotion-dev/skills"
|
|
125617
|
+
},
|
|
125618
|
+
{
|
|
125619
|
+
id: "html-anything",
|
|
125620
|
+
displayName: "HTML Anything 全能设计",
|
|
125621
|
+
description: "75 个技能 × 9 种场景:杂志 / 幻灯片 / 海报 / 小红书 / 数据报告 / 原型,零 API 密钥",
|
|
125622
|
+
source: "https://github.com/nexu-io/html-anything"
|
|
125623
|
+
},
|
|
125624
|
+
{
|
|
125625
|
+
id: "guizang-social-card-skill",
|
|
125626
|
+
displayName: "归藏社交卡片",
|
|
125627
|
+
description: "小红书轮播图 + 公众号封面:28 种布局 × 10 套主题,Editorial × Swiss 视觉体系,单文件 HTML → PNG",
|
|
125628
|
+
source: "https://github.com/op7418/guizang-social-card-skill"
|
|
125444
125629
|
}
|
|
125445
125630
|
];
|
|
125446
125631
|
async function handlePluginCommand(host, _args) {
|
|
@@ -125542,10 +125727,33 @@ async function loadInstalled(host) {
|
|
|
125542
125727
|
return [];
|
|
125543
125728
|
}
|
|
125544
125729
|
}
|
|
125730
|
+
/**
|
|
125731
|
+
* Normalize a GitHub URL to `{owner}/{repo}` for fuzzy matching.
|
|
125732
|
+
* Returns `null` for non-GitHub URLs (caller falls back to exact match).
|
|
125733
|
+
*/
|
|
125734
|
+
function normalizeGithubSource(url) {
|
|
125735
|
+
try {
|
|
125736
|
+
const u = new URL(url.trim());
|
|
125737
|
+
if (u.hostname !== "github.com" && u.hostname !== "www.github.com") return null;
|
|
125738
|
+
const segments = u.pathname.split("/").filter((s) => s.length > 0);
|
|
125739
|
+
if (segments.length < 2) return null;
|
|
125740
|
+
return `${segments[0]}/${segments[1].replace(/\.git$/, "")}`.toLowerCase();
|
|
125741
|
+
} catch {
|
|
125742
|
+
return null;
|
|
125743
|
+
}
|
|
125744
|
+
}
|
|
125745
|
+
function isInstalled(marketplaceId, marketplaceSource, installed) {
|
|
125746
|
+
if (installed.some((p) => p.id === marketplaceId)) return true;
|
|
125747
|
+
const normalizedSource = normalizeGithubSource(marketplaceSource);
|
|
125748
|
+
if (normalizedSource === null) return false;
|
|
125749
|
+
return installed.some((p) => {
|
|
125750
|
+
const norm = normalizeGithubSource(p.originalSource ?? "");
|
|
125751
|
+
return norm !== null && norm === normalizedSource;
|
|
125752
|
+
});
|
|
125753
|
+
}
|
|
125545
125754
|
function buildOptions(marketplace, installed) {
|
|
125546
125755
|
const options = [];
|
|
125547
|
-
const
|
|
125548
|
-
const newPlugins = marketplace.filter((p) => !installedIds.has(p.id));
|
|
125756
|
+
const newPlugins = marketplace.filter((p) => !isInstalled(p.id, p.source, installed));
|
|
125549
125757
|
if (newPlugins.length > 0) {
|
|
125550
125758
|
options.push({
|
|
125551
125759
|
value: "__section__marketplace",
|
|
@@ -134733,6 +134941,7 @@ var ScreamTUI = class {
|
|
|
134733
134941
|
return this.state.loadingSessions;
|
|
134734
134942
|
}
|
|
134735
134943
|
async deleteSession(sessionId) {
|
|
134944
|
+
if (sessionId === this.session?.id) await this.sessionManager.closeSession("session deleted");
|
|
134736
134945
|
await this.harness.deleteSession(sessionId);
|
|
134737
134946
|
}
|
|
134738
134947
|
async getStartupMcpMs() {
|
|
@@ -135169,6 +135378,7 @@ var ScreamTUI = class {
|
|
|
135169
135378
|
//#region src/tui/components/chrome/loading.ts
|
|
135170
135379
|
const { stdout } = process$1;
|
|
135171
135380
|
const BRIGHT = "\x1B[38;2;255;255;255m";
|
|
135381
|
+
const RESET = "\x1B[0m";
|
|
135172
135382
|
const THEME_GREEN = {
|
|
135173
135383
|
dark: "\x1B[38;2;78;200;126m",
|
|
135174
135384
|
light: "\x1B[38;2;14;122;56m"
|
|
@@ -135280,17 +135490,17 @@ function supportsAnsi() {
|
|
|
135280
135490
|
ansiSupported = false;
|
|
135281
135491
|
return false;
|
|
135282
135492
|
}
|
|
135283
|
-
if (process$1.env
|
|
135493
|
+
if (process$1.env["NO_COLOR"]) {
|
|
135284
135494
|
ansiSupported = false;
|
|
135285
135495
|
return false;
|
|
135286
135496
|
}
|
|
135287
|
-
if (process$1.env
|
|
135497
|
+
if (process$1.env["FORCE_COLOR"]) {
|
|
135288
135498
|
ansiSupported = true;
|
|
135289
135499
|
return true;
|
|
135290
135500
|
}
|
|
135291
135501
|
if (process$1.platform === "win32") {
|
|
135292
|
-
const term = (process$1.env
|
|
135293
|
-
const session = (process$1.env
|
|
135502
|
+
const term = (process$1.env["TERM"] ?? "").toLowerCase();
|
|
135503
|
+
const session = (process$1.env["TERM_PROGRAM"] ?? "").toLowerCase();
|
|
135294
135504
|
if (term.includes("xterm") || term.includes("vt100") || term.includes("256color")) {
|
|
135295
135505
|
ansiSupported = true;
|
|
135296
135506
|
return true;
|
|
@@ -135299,14 +135509,14 @@ function supportsAnsi() {
|
|
|
135299
135509
|
ansiSupported = true;
|
|
135300
135510
|
return true;
|
|
135301
135511
|
}
|
|
135302
|
-
if (process$1.env
|
|
135512
|
+
if (process$1.env["CI"]) {
|
|
135303
135513
|
ansiSupported = true;
|
|
135304
135514
|
return true;
|
|
135305
135515
|
}
|
|
135306
135516
|
ansiSupported = true;
|
|
135307
135517
|
return true;
|
|
135308
135518
|
}
|
|
135309
|
-
if (process$1.env
|
|
135519
|
+
if (process$1.env["TERM"] && process$1.env["TERM"] !== "dumb") {
|
|
135310
135520
|
ansiSupported = true;
|
|
135311
135521
|
return true;
|
|
135312
135522
|
}
|
|
@@ -135319,11 +135529,23 @@ function plainFrame(frameIndex, green) {
|
|
|
135319
135529
|
for (const l of f.content) out += color(l, green) + (l || " ") + "\x1B[0m\n";
|
|
135320
135530
|
return out;
|
|
135321
135531
|
}
|
|
135532
|
+
const LOADING_STAGES = [
|
|
135533
|
+
"正在整理记忆区域....",
|
|
135534
|
+
"正在加载用户喜好....",
|
|
135535
|
+
"正在确认模型配置....",
|
|
135536
|
+
"正在加载scream code...."
|
|
135537
|
+
];
|
|
135538
|
+
const STAGE_DELAYS_MS = [
|
|
135539
|
+
450,
|
|
135540
|
+
350,
|
|
135541
|
+
650,
|
|
135542
|
+
350
|
|
135543
|
+
];
|
|
135322
135544
|
function runLoadingAnimation(theme = "dark") {
|
|
135323
135545
|
const green = THEME_GREEN[theme];
|
|
135324
135546
|
if (!supportsAnsi()) {
|
|
135325
135547
|
stdout.write(plainFrame(FRAMES.length - 1, green));
|
|
135326
|
-
stdout.write("\
|
|
135548
|
+
for (const stage of LOADING_STAGES) stdout.write(green + stage + "\x1B[0m\n");
|
|
135327
135549
|
return Promise.resolve();
|
|
135328
135550
|
}
|
|
135329
135551
|
return new Promise((resolve) => {
|
|
@@ -135332,14 +135554,22 @@ function runLoadingAnimation(theme = "dark") {
|
|
|
135332
135554
|
function draw(i) {
|
|
135333
135555
|
stdout.write("\x1B[H" + plainFrame(i, green));
|
|
135334
135556
|
}
|
|
135557
|
+
function showStages(stages, index) {
|
|
135558
|
+
if (index >= stages.length) {
|
|
135559
|
+
setTimeout(() => {
|
|
135560
|
+
stdout.write("\x1B[2J\x1B[H\x1B[?25h");
|
|
135561
|
+
resolve();
|
|
135562
|
+
}, 400);
|
|
135563
|
+
return;
|
|
135564
|
+
}
|
|
135565
|
+
stdout.write("\n" + green + stages[index] + RESET);
|
|
135566
|
+
const delay = STAGE_DELAYS_MS[index] ?? 350;
|
|
135567
|
+
setTimeout(() => showStages(stages, index + 1), delay);
|
|
135568
|
+
}
|
|
135335
135569
|
function tick() {
|
|
135336
135570
|
if (frame >= last) {
|
|
135337
135571
|
setTimeout(() => {
|
|
135338
|
-
|
|
135339
|
-
setTimeout(() => {
|
|
135340
|
-
stdout.write("\x1B[2J\x1B[H\x1B[?25h");
|
|
135341
|
-
resolve();
|
|
135342
|
-
}, 400);
|
|
135572
|
+
showStages(LOADING_STAGES, 0);
|
|
135343
135573
|
}, 600);
|
|
135344
135574
|
return;
|
|
135345
135575
|
}
|