@gendive/chatllm 0.15.1 → 0.15.3
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/react/index.d.mts +6 -2
- package/dist/react/index.d.ts +6 -2
- package/dist/react/index.js +73 -16
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +73 -16
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react/index.d.mts
CHANGED
|
@@ -328,6 +328,10 @@ interface ChatToolDefinition {
|
|
|
328
328
|
name: string;
|
|
329
329
|
description: string;
|
|
330
330
|
parameters: Record<string, ChatToolParameter>;
|
|
331
|
+
/** @Todo vibecode - UI 표시용 라벨 (미제공 시 name 사용) */
|
|
332
|
+
label?: string;
|
|
333
|
+
/** @Todo vibecode - UI 표시용 아이콘 ('image', 'search', 'code', 'file') */
|
|
334
|
+
icon?: string;
|
|
331
335
|
}
|
|
332
336
|
interface ChatMessage {
|
|
333
337
|
id: string;
|
|
@@ -1531,11 +1535,11 @@ declare const FileContentCard: React$1.FC<FileContentCardProps>;
|
|
|
1531
1535
|
|
|
1532
1536
|
/**
|
|
1533
1537
|
* @description 도구 정의 배열을 스킬 레코드로 변환
|
|
1534
|
-
* @Todo vibecode - 각 tool을 trigger: '
|
|
1538
|
+
* @Todo vibecode - 각 tool을 trigger: 'both' SkillConfig로 변환
|
|
1535
1539
|
*
|
|
1536
1540
|
* 변환 규칙:
|
|
1537
1541
|
* - skill name = tool.name (접두사 없음)
|
|
1538
|
-
* - trigger: '
|
|
1542
|
+
* - trigger: 'both' (AI 자동 호출 + '+' 메뉴에서 수동 선택)
|
|
1539
1543
|
* - execute: onToolCall 호출 → SkillExecutionResult 반환
|
|
1540
1544
|
* - metadata.__toolResult__: true (도구 결과 식별용)
|
|
1541
1545
|
*/
|
package/dist/react/index.d.ts
CHANGED
|
@@ -328,6 +328,10 @@ interface ChatToolDefinition {
|
|
|
328
328
|
name: string;
|
|
329
329
|
description: string;
|
|
330
330
|
parameters: Record<string, ChatToolParameter>;
|
|
331
|
+
/** @Todo vibecode - UI 표시용 라벨 (미제공 시 name 사용) */
|
|
332
|
+
label?: string;
|
|
333
|
+
/** @Todo vibecode - UI 표시용 아이콘 ('image', 'search', 'code', 'file') */
|
|
334
|
+
icon?: string;
|
|
331
335
|
}
|
|
332
336
|
interface ChatMessage {
|
|
333
337
|
id: string;
|
|
@@ -1531,11 +1535,11 @@ declare const FileContentCard: React$1.FC<FileContentCardProps>;
|
|
|
1531
1535
|
|
|
1532
1536
|
/**
|
|
1533
1537
|
* @description 도구 정의 배열을 스킬 레코드로 변환
|
|
1534
|
-
* @Todo vibecode - 각 tool을 trigger: '
|
|
1538
|
+
* @Todo vibecode - 각 tool을 trigger: 'both' SkillConfig로 변환
|
|
1535
1539
|
*
|
|
1536
1540
|
* 변환 규칙:
|
|
1537
1541
|
* - skill name = tool.name (접두사 없음)
|
|
1538
|
-
* - trigger: '
|
|
1542
|
+
* - trigger: 'both' (AI 자동 호출 + '+' 메뉴에서 수동 선택)
|
|
1539
1543
|
* - execute: onToolCall 호출 → SkillExecutionResult 반환
|
|
1540
1544
|
* - metadata.__toolResult__: true (도구 결과 식별용)
|
|
1541
1545
|
*/
|
package/dist/react/index.js
CHANGED
|
@@ -979,21 +979,53 @@ var useSkills = (options) => {
|
|
|
979
979
|
);
|
|
980
980
|
if (autoSkills.length === 0) return "";
|
|
981
981
|
const skillDescriptions = autoSkills.map(([name, config]) => {
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
982
|
+
let desc = `### ${name}
|
|
983
|
+
${config.description}`;
|
|
984
|
+
if (config.parameters?.properties) {
|
|
985
|
+
desc += "\n\uD30C\uB77C\uBBF8\uD130:";
|
|
986
|
+
const props = config.parameters.properties;
|
|
987
|
+
const requiredList = config.parameters.required || [];
|
|
988
|
+
Object.entries(props).forEach(([key, prop]) => {
|
|
989
|
+
const isRequired = requiredList.includes(key);
|
|
990
|
+
const tag = isRequired ? "(\uD544\uC218)" : "(\uC120\uD0DD)";
|
|
991
|
+
let line = `
|
|
992
|
+
- ${key} ${tag}: ${prop.description || prop.type}`;
|
|
993
|
+
if (prop.enum) {
|
|
994
|
+
line += ` [\uAC00\uB2A5\uD55C \uAC12: ${prop.enum.join(", ")}]`;
|
|
995
|
+
}
|
|
996
|
+
desc += line;
|
|
997
|
+
});
|
|
998
|
+
const exampleParams = {};
|
|
999
|
+
Object.entries(props).forEach(([key, prop]) => {
|
|
1000
|
+
if (prop.enum) {
|
|
1001
|
+
exampleParams[key] = prop.enum[0];
|
|
1002
|
+
} else if (prop.description) {
|
|
1003
|
+
exampleParams[key] = `${prop.description}`;
|
|
1004
|
+
} else {
|
|
1005
|
+
exampleParams[key] = key;
|
|
1006
|
+
}
|
|
1007
|
+
});
|
|
1008
|
+
desc += `
|
|
1009
|
+
\uC608\uC2DC: <skill_use name="${name}">${JSON.stringify(exampleParams)}</skill_use>`;
|
|
1010
|
+
}
|
|
1011
|
+
return desc;
|
|
1012
|
+
}).join("\n\n");
|
|
1013
|
+
return `## \uC0AC\uC6A9 \uAC00\uB2A5\uD55C \uB3C4\uAD6C
|
|
1014
|
+
|
|
1015
|
+
\uC544\uB798 \uB3C4\uAD6C\uB97C \uC801\uADF9\uC801\uC73C\uB85C \uC0AC\uC6A9\uD558\uC138\uC694. \uC0AC\uC6A9\uC790\uC758 \uC694\uCCAD\uC5D0 \uB9DE\uB294 \uB3C4\uAD6C\uAC00 \uC788\uC73C\uBA74 \uBC18\uB4DC\uC2DC \uD638\uCD9C\uD574\uC57C \uD569\uB2C8\uB2E4.
|
|
986
1016
|
|
|
987
|
-
\
|
|
988
|
-
|
|
1017
|
+
\uD638\uCD9C \uD615\uC2DD:
|
|
1018
|
+
<skill_use name="\uB3C4\uAD6C\uC774\uB984">{"\uD30C\uB77C\uBBF8\uD130": "\uAC12"}</skill_use>
|
|
989
1019
|
|
|
990
1020
|
${skillDescriptions}
|
|
991
1021
|
|
|
992
|
-
|
|
993
|
-
- \
|
|
994
|
-
- \
|
|
995
|
-
- \
|
|
996
|
-
- \
|
|
1022
|
+
**\uADDC\uCE59:**
|
|
1023
|
+
- \uC774\uBBF8\uC9C0 \uC0DD\uC131/\uADF8\uB9BC/\uC77C\uB7EC\uC2A4\uD2B8 \uC694\uCCAD \u2192 \uBC18\uB4DC\uC2DC generate_image \uB3C4\uAD6C \uD638\uCD9C
|
|
1024
|
+
- \uCD5C\uC2E0 \uC815\uBCF4/\uAC80\uC0C9/\uB274\uC2A4 \uC694\uCCAD \u2192 \uBC18\uB4DC\uC2DC web_search \uB3C4\uAD6C \uD638\uCD9C
|
|
1025
|
+
- \uB3C4\uAD6C \uD638\uCD9C \uC2DC \uC9E7\uC740 \uC548\uB0B4 \uBA54\uC2DC\uC9C0\uB97C \uBA3C\uC800 \uC791\uC131\uD558\uACE0, \uADF8 \uB4A4\uC5D0 skill_use \uD0DC\uADF8\uB97C \uD3EC\uD568\uD558\uC138\uC694
|
|
1026
|
+
- \uD55C \uBC88\uC5D0 \uD558\uB098\uC758 \uB3C4\uAD6C\uB9CC \uD638\uCD9C\uD558\uC138\uC694
|
|
1027
|
+
- \uB3C4\uAD6C \uC5C6\uC774 \uD14D\uC2A4\uD2B8\uB85C\uB9CC \uB2F5\uBCC0\uD558\uC9C0 \uB9C8\uC138\uC694 (\uD574\uB2F9 \uB3C4\uAD6C\uAC00 \uC788\uB294 \uACBD\uC6B0)
|
|
1028
|
+
- \uB3C4\uAD6C\uAC00 \uC2E4\uD589\uB418\uBA74 \uACB0\uACFC\uAC00 \uC790\uB3D9\uC73C\uB85C \uC804\uB2EC\uB429\uB2C8\uB2E4`;
|
|
997
1029
|
}, [resolvedSkills]);
|
|
998
1030
|
const handleSkillCall = (0, import_react3.useCallback)(
|
|
999
1031
|
async (content, callbacks) => {
|
|
@@ -1221,8 +1253,9 @@ var convertToolsToSkills = (tools, onToolCall) => {
|
|
|
1221
1253
|
for (const tool of tools) {
|
|
1222
1254
|
skillMap[tool.name] = {
|
|
1223
1255
|
description: tool.description,
|
|
1224
|
-
trigger: "
|
|
1225
|
-
label: tool.name,
|
|
1256
|
+
trigger: "both",
|
|
1257
|
+
label: tool.label || tool.name,
|
|
1258
|
+
icon: tool.icon,
|
|
1226
1259
|
parameters: {
|
|
1227
1260
|
type: "object",
|
|
1228
1261
|
properties: Object.fromEntries(
|
|
@@ -2096,6 +2129,7 @@ ${currentContextSummary}` },
|
|
|
2096
2129
|
const decoder = new TextDecoder();
|
|
2097
2130
|
let buffer = "";
|
|
2098
2131
|
let accumulatedContent = "";
|
|
2132
|
+
let skillTagDetected = false;
|
|
2099
2133
|
while (true) {
|
|
2100
2134
|
const { done, value } = await reader.read();
|
|
2101
2135
|
if (done) break;
|
|
@@ -2115,6 +2149,12 @@ ${currentContextSummary}` },
|
|
|
2115
2149
|
const thinking = parsed.message?.thinking || "";
|
|
2116
2150
|
if (content2 || thinking) {
|
|
2117
2151
|
if (content2) accumulatedContent += content2;
|
|
2152
|
+
if (!skipNextSkillParsingRef.current && accumulatedContent.includes("</skill_use>")) {
|
|
2153
|
+
const endIdx = accumulatedContent.indexOf("</skill_use>");
|
|
2154
|
+
accumulatedContent = accumulatedContent.substring(0, endIdx + "</skill_use>".length);
|
|
2155
|
+
skillTagDetected = true;
|
|
2156
|
+
}
|
|
2157
|
+
const displayContent = skillTagDetected ? accumulatedContent : null;
|
|
2118
2158
|
setSessions(
|
|
2119
2159
|
(prev) => prev.map((s) => {
|
|
2120
2160
|
if (s.id === capturedSessionId) {
|
|
@@ -2122,6 +2162,9 @@ ${currentContextSummary}` },
|
|
|
2122
2162
|
...s,
|
|
2123
2163
|
messages: s.messages.map((m) => {
|
|
2124
2164
|
if (m.id !== assistantMessageId) return m;
|
|
2165
|
+
if (displayContent) {
|
|
2166
|
+
return { ...m, content: displayContent };
|
|
2167
|
+
}
|
|
2125
2168
|
let newContent = m.content;
|
|
2126
2169
|
if (thinking) {
|
|
2127
2170
|
if (!newContent.includes("<thinking>")) {
|
|
@@ -2143,10 +2186,12 @@ ${currentContextSummary}` },
|
|
|
2143
2186
|
return s;
|
|
2144
2187
|
})
|
|
2145
2188
|
);
|
|
2189
|
+
if (skillTagDetected) break;
|
|
2146
2190
|
}
|
|
2147
2191
|
} catch {
|
|
2148
2192
|
}
|
|
2149
2193
|
}
|
|
2194
|
+
if (skillTagDetected) break;
|
|
2150
2195
|
}
|
|
2151
2196
|
if (buffer.trim()) {
|
|
2152
2197
|
try {
|
|
@@ -2938,11 +2983,23 @@ ${currentSession.contextSummary}` },
|
|
|
2938
2983
|
*/
|
|
2939
2984
|
manualSkills,
|
|
2940
2985
|
/**
|
|
2941
|
-
* @description manual
|
|
2942
|
-
* @Todo vibecode -
|
|
2986
|
+
* @description manual 스킬/도구 선택 핸들러
|
|
2987
|
+
* @Todo vibecode - 도구 스킬은 selectedAction으로 변환, 일반 스킬은 즉시 실행
|
|
2943
2988
|
*/
|
|
2944
2989
|
executeManualSkill: (skillName) => {
|
|
2945
|
-
|
|
2990
|
+
const isToolSkill = tools?.some((t) => t.name === skillName);
|
|
2991
|
+
if (isToolSkill) {
|
|
2992
|
+
const toolConfig = tools.find((t) => t.name === skillName);
|
|
2993
|
+
setSelectedAction({
|
|
2994
|
+
id: `tool_${skillName}`,
|
|
2995
|
+
label: toolConfig.label || toolConfig.name,
|
|
2996
|
+
icon: toolConfig.icon || "sparkling",
|
|
2997
|
+
description: toolConfig.description,
|
|
2998
|
+
systemPrompt: `\uC0AC\uC6A9\uC790\uAC00 "${toolConfig.label || skillName}" \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD558\uB824\uACE0 \uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uC758 \uBA54\uC2DC\uC9C0\uB97C \uBC14\uD0D5\uC73C\uB85C \uBC18\uB4DC\uC2DC <skill_use name="${skillName}"> \uD0DC\uADF8\uB97C \uC0AC\uC6A9\uD558\uC5EC \uC774 \uB3C4\uAD6C\uB97C \uD638\uCD9C\uD558\uC138\uC694. \uB3C4\uAD6C\uB97C \uC0AC\uC6A9\uD558\uC9C0 \uC54A\uACE0 \uD14D\uC2A4\uD2B8\uB85C\uB9CC \uB2F5\uBCC0\uD558\uC9C0 \uB9C8\uC138\uC694.`
|
|
2999
|
+
});
|
|
3000
|
+
} else {
|
|
3001
|
+
executeManualSkill(skillName, { query: input });
|
|
3002
|
+
}
|
|
2946
3003
|
}
|
|
2947
3004
|
};
|
|
2948
3005
|
};
|