@hcmai/sdk 0.1.0 → 0.2.0
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/index.d.ts +63 -8
- package/dist/index.js +145 -6
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -310,10 +310,20 @@ interface AttachmentMeta {
|
|
|
310
310
|
}
|
|
311
311
|
declare function guessMimeType(filePath: string): string;
|
|
312
312
|
/**
|
|
313
|
-
* 上传本地文件到 HCM
|
|
314
|
-
*
|
|
313
|
+
* 上传本地文件到 HCM 文档存储,返回可直接携带的附件元数据。
|
|
314
|
+
* 类型限制跟随服务端校验。
|
|
315
|
+
*
|
|
316
|
+
* @param storageCategory 存储分类。**必须是目标环境里真实存在的分类**——
|
|
317
|
+
* 它是服务端数据而非枚举,不同环境的分类表可以不同。
|
|
318
|
+
* 聊天附件传 {@link CHAT_ATTACHMENT_CATEGORY};报表模板一类传 `flex-report`。
|
|
319
|
+
*
|
|
320
|
+
* <p>🔴 此前这里硬编码 `'ai-conversation'`,于是 `hcm upload <任意文件>` 在
|
|
321
|
+
* 没有该分类的环境上**一律失败**,而错误被包成
|
|
322
|
+
* `BUSINESS_RULE_VIOLATION: Request failed with status code 404`——看不出真因是
|
|
323
|
+
* 「分类不存在」。2026-08-26 按交付技能跑弹性报表端到端时,Step 4「上传模板」
|
|
324
|
+
* 卡在这里;模板是报表的必需件,这条不通整条链就断了。
|
|
315
325
|
*/
|
|
316
|
-
declare function uploadDocument(http: AxiosInstance, filePath: string): Promise<AttachmentMeta>;
|
|
326
|
+
declare function uploadDocument(http: AxiosInstance, filePath: string, storageCategory?: string): Promise<AttachmentMeta>;
|
|
317
327
|
/** 默认产物落盘目录(对标 Claude Code 工具产物本地直接访问)。 */
|
|
318
328
|
declare function defaultDownloadDir(): string;
|
|
319
329
|
/**
|
|
@@ -1685,8 +1695,13 @@ declare function createHttpClient(opts: HttpClientOptions): AxiosInstance;
|
|
|
1685
1695
|
* 必须先装技能才能建租户。所以本模块只需要 endpoint,不碰 identity/token。
|
|
1686
1696
|
*
|
|
1687
1697
|
* 后端契约(ChironController):
|
|
1688
|
-
* - `GET /skills.json`
|
|
1689
|
-
* - `GET /skills/{id}.md`
|
|
1698
|
+
* - `GET {base}/skills.json` 目录 manifest
|
|
1699
|
+
* - `GET {base}/skills/{id}.md` 技能原文
|
|
1700
|
+
* - `GET {base}/skills/{id}/references/{path}` 技能自带的参考文件
|
|
1701
|
+
*
|
|
1702
|
+
* 🔴 `{base}` 是 `'/api'` 或 `''`,由 {@link resolveChironBase} 探出来。真实部署只把
|
|
1703
|
+
* `/api/**` 路由给后端,根路径归前端 SPA——`GET /skills.json` 在客户环境上拿回来的是
|
|
1704
|
+
* 一段 HTML。而老版本后端只有根路径。两种都要能连上,所以先探再用,不写死。
|
|
1690
1705
|
*/
|
|
1691
1706
|
interface ChironSkill {
|
|
1692
1707
|
id: string;
|
|
@@ -1697,8 +1712,15 @@ interface ChironSkill {
|
|
|
1697
1712
|
description: string;
|
|
1698
1713
|
/** 交付生命周期阶段(多值)——一个技能天然跨阶段 */
|
|
1699
1714
|
stages: string[];
|
|
1715
|
+
/** 安装本技能前必须同时安装的其他 Chiron 技能 id;旧服务端缺省时视为空。 */
|
|
1716
|
+
requires?: string[];
|
|
1700
1717
|
bytes: number;
|
|
1701
1718
|
markdownUrl: string;
|
|
1719
|
+
/**
|
|
1720
|
+
* 技能自带的参考文件相对路径(相对 `<skill>/references/`)。SKILL.md 正文用
|
|
1721
|
+
* `[x](references/x.md)` 引它们——不跟着装下来就是一堆死链。旧服务端缺省时视为空。
|
|
1722
|
+
*/
|
|
1723
|
+
references?: string[];
|
|
1702
1724
|
}
|
|
1703
1725
|
interface ChironStage {
|
|
1704
1726
|
key: string;
|
|
@@ -1721,9 +1743,42 @@ interface ChironManifest {
|
|
|
1721
1743
|
stages: ChironStage[];
|
|
1722
1744
|
categories: ChironCategory[];
|
|
1723
1745
|
}
|
|
1724
|
-
|
|
1725
|
-
|
|
1746
|
+
/**
|
|
1747
|
+
* 探出本环境技能库的前缀。
|
|
1748
|
+
*
|
|
1749
|
+
* 为什么不能写死任何一个:
|
|
1750
|
+
* - 真实部署(反代把 `/api/**` 给后端、其余给前端)下根路径返回的是前端 SPA 的 HTML,
|
|
1751
|
+
* HTTP 200 但根本不是 manifest —— 所以判据必须看**内容**,不能看状态码;
|
|
1752
|
+
* - 还没升级到带 `/api` 别名那一版的后端,只有根路径可用。
|
|
1753
|
+
*
|
|
1754
|
+
* 两条都探不到时抛出可执行的错误,而不是把一段 HTML 当目录解析出满屏乱码。
|
|
1755
|
+
*/
|
|
1756
|
+
declare function resolveChironBase(http: AxiosInstance): Promise<string>;
|
|
1757
|
+
declare function fetchSkillCatalog(http: AxiosInstance, base: string): Promise<ChironManifest>;
|
|
1758
|
+
declare function fetchSkillMarkdown(http: AxiosInstance, id: string, base: string): Promise<string>;
|
|
1759
|
+
/** 取技能自带的参考文件原文。`relativePath` 相对 `<skill>/references/`。 */
|
|
1760
|
+
declare function fetchSkillReference(http: AxiosInstance, id: string, relativePath: string, base: string): Promise<string>;
|
|
1761
|
+
/**
|
|
1762
|
+
* 参考文件相对路径约束——与后端 `ChironCatalogService.SAFE_REFERENCE_PATH` 同形。
|
|
1763
|
+
*
|
|
1764
|
+
* 🔴 服务端返回什么,本地就按什么建目录,所以这里是**写文件前**的闸:`..` 段会让
|
|
1765
|
+
* 安装写出技能目录之外。不要因为「服务端已经校验过」就省掉——CLI 可以指向任何 endpoint。
|
|
1766
|
+
*/
|
|
1767
|
+
declare function assertSafeReferencePath(relativePath: string): void;
|
|
1768
|
+
/** 归一 references 字段:旧服务端缺省时视为空,逐条过白名单。 */
|
|
1769
|
+
declare function normalizeReferences(raw: unknown, skillId: string): string[];
|
|
1726
1770
|
declare function flattenSkills(manifest: ChironManifest): ChironSkill[];
|
|
1771
|
+
/**
|
|
1772
|
+
* 计算技能安装闭包,返回稳定的「依赖在前、目标在后」顺序。
|
|
1773
|
+
*
|
|
1774
|
+
* 这是纯函数:远程安装与测试共用,不在这里发请求或写文件。旧目录没有 requires 时
|
|
1775
|
+
* 自然退化为只安装目标技能。
|
|
1776
|
+
*/
|
|
1777
|
+
declare function resolveSkillInstallOrder(manifest: ChironManifest, targetId: string): ChironSkill[];
|
|
1778
|
+
/** 从一份 SKILL.md 读取本地安装所需的 requires,不接受正文中的近似语法。 */
|
|
1779
|
+
declare function parseSkillRequirements(markdown: string, skillId: string): string[];
|
|
1780
|
+
/** Chiron 与公开端点共用的小写安全 id 约束。 */
|
|
1781
|
+
declare function assertSafeSkillId(id: string): void;
|
|
1727
1782
|
/** 按交付生命周期阶段筛选。 */
|
|
1728
1783
|
declare function filterByStage(skills: ChironSkill[], stage?: string): ChironSkill[];
|
|
1729
1784
|
/** 关键词匹配 id / 标题 / 描述 / 分类,全部小写包含。 */
|
|
@@ -1772,4 +1827,4 @@ declare function resetSettingItem(http: AxiosInstance, domain: string, namespace
|
|
|
1772
1827
|
*/
|
|
1773
1828
|
declare function parseSettingAssignment(raw: string): SettingWrite;
|
|
1774
1829
|
|
|
1775
|
-
export { type ActionHttpMethod, type ActionInput, type ActionMeta, type ActionResult, type ActionScope, type AnyStreamEvent, type ApprovalConfirmPayload, type ApprovalRejectPayload, type AttachmentMeta, type AuthScheme, type BootstrapReconcileResult, type BootstrapTenantRequest, type BootstrapTenantResult, type CacheClearResult, type CacheStats, type ChangePasswordInput, type ChironCategory, type ChironManifest, type ChironSkill, type ChironStage, type ClearMetaCacheOpts, CliError, CliErrorCode, type CliErrorInit, type ClientAuthContext, type ClientCredentialsInput, type ConnectionMessage, type ControlChannelEnvelope, type ConversationListItem, type ConversationListResult, type ConversationState, type CreateResult, type CreatedConversation, DEFAULT_AGENT_ID, DEFAULT_SESSION_TTL_SECONDS, type DescribeOpts, type EnvConfig, ExitCode, type FieldMeta, type Fixture, type FormatOptions, type GlobalConfig, HcmClient, type HcmClientOpts, type HttpClientOptions, type IdentityMeta, type ImportClient, type ImportOptions, type ImportResult, type InteractionAnswerPayload, type InteractionRequest, type InteractionResolved, type ListTenantMetaOpts, type LoginOutcome, MINI_CONTEXT_FILE, MINI_CONTEXT_KIND, MINI_CONTEXT_VERSION, MINI_PULL_MANIFEST_FILE, MINI_REMOTE_ROOT, MINI_STATE_DIR, type MessageClass, type MessageCreatePayload, type MessageStreamHandle, type MigrationSummary, type MiniFileSnapshot, type MiniInitArgs, type MiniLocalFile, type MiniLocalStatus, type MiniPreviewTarget, type MiniProjectContext, type MiniPullArgs, type MiniPullManifest, type MiniPullResult, type MiniPushArgs, type MiniPushConflict, type MiniPushOperation, type MiniPushPlanItem, type MiniPushResult, type MiniSmokeCheckArgs, type MiniSmokeFetch, type MiniSmokeFetchResponse, type MiniSmokeResult, type MiniSmokeTargetKind, type MiniSmokeTargetResult, type MiniStatusEntry, type MiniSurface, type MiniTemplateArgs, type MiniTemplateKind, type MiniValidationResult, type MiniVerifyAgentReport, type MiniVerifyBrowserAcceptance, type MiniVerifyChangedFile, type MiniVerifyNextAction, type MiniVerifyPlan, type MiniVerifyPreviewUrl, type MiniVerifyReport, type MiniVerifySummary, type MiniWritableTemplateConfig, type ModelDescription, type ModelQueryDsl, type OneShotOpts, type OneShotResult, type OneShotToolCall, type OutputFormat, PASSWORD_CHANGE_REQUIRED, PROACTIVE_REFRESH_MARGIN_SECONDS, type PairingLoginInput, type ParsedPlaceholder, type PasswordChangeChallenge, type PasswordLoginInput, type PatLoginInput, type Principal, type ProfileConfig, type QueryResult, RefStore, type RefreshInput, type RelationMeta, type RemoveResult, type ResponseCompletedPayload, type ResponseFailedPayload, type ResponsePartDeltaPayload, type ResponseStartedPayload, type ResumeSummary, type ResumeTurn, type RowResult, type RowStatus, SDK_VERSION, type SaveMetaResult, type SendMessageOpts, type SettingItem, type SettingWrite, type StreamCancelPayload, type StreamCommand, type StreamCommandEnvelope, type StreamCommandType, type StreamEventEnvelope, type StreamEventType, type TaskProgressPayload, type TenantMetaEntry, type TimelineItemLite, type TokenRecord, TokenStore, type ToolCallFailedPayload, type ToolCallResultPayload, type ToolCallStartedPayload, type V4RenderSink, type V4StreamEventType, type WorkspaceFileContent, type WorkspaceFileItem, type WorkspaceFileListResult, WsClient, type WsClientOpts, absoluteDownloadUrl, archiveDir, bootstrapTenant, buildAnswer, buildConfirm, buildInterrupt, buildMiniAppTemplateFiles, buildMiniPreviewTargets, buildMiniVerifyAgentReport, buildReject, buildResumeSummary, buildSteer, camelizeKeys, changePassword, classifyMessage, clearMetaCache, clearModelCache, conversationStateFile, create, createConversation, createHttpClient, createV4Reducer, createWorkspaceFile, credentialsFile, defaultDownloadDir, defaultMiniRequiredScopes, deleteEnv, deleteIdentity, deleteTenantMeta, deleteWorkspaceFile, deriveNamelessToolLabel, describePrincipal, detectDelegationPause, detectDirectInteractionPending, detectPasswordChangeChallenge, displayWidth, downloadDocument, ensureSessionFresh, envDir, envFile, envsDir, exitCodeFor, extractNextSteps, fetchConversationTimeline, fetchConversationTimelineStrict, fetchRecentConversations, fetchSkillCatalog, fetchSkillMarkdown, filterByStage, findLastAssistantSeq, flattenSkills, formatMiniVerifyReport, formatObject, formatRows, fromAxiosError, getCacheStats, getMiniStatus, getSettingDomain, getTenantMeta, globalConfigFile, guessMimeType, hcmConfigDir, identitiesDir, identityDir, identityMetaFile, inferEnvName, inferMiniWritableTemplateOptionsFromModel, initMiniAppProject, isDelegationToolName, isServerSlidingSession, listEnvs, listIdentities, listProfiles, listTenantMeta, listWorkspaceFiles, loadConversationState, loadEnv, loadGlobalConfig, loadIdentity, loadProfile, loadWorkspaceFileContent, loginClientCredentials, loginPairing, loginPassword, loginPat, matchSkills, migrateLegacyProfiles, needsRefresh, oneShot, parseConfirmToolName, parseFixture, parseInteractionRequest, parseInteractionResolved, parsePlaceholder, parseSettingAssignment, patchSettingDomain, profileDir, profileFile, pullMiniAppProject, pushMiniAppProject, readMiniContext, readPullManifest, refreshToken, remove, replHistoryFile, resetSettingItem, resolveActiveEnv, resolveActiveIdentity, resolveActiveProfile, resolveRefs, runImport, runMiniSmokeChecks, saveConversationState, saveEnv, saveGlobalConfig, saveIdentity, saveProfile, saveTenantMeta, saveWorkspaceFileContent, sendMessageAndStream, snakeToCamel, toJson, toOrigin, toPrincipal, toTable, toYaml, truncateDisplay, update, uploadDocument, validateMiniProject };
|
|
1830
|
+
export { type ActionHttpMethod, type ActionInput, type ActionMeta, type ActionResult, type ActionScope, type AnyStreamEvent, type ApprovalConfirmPayload, type ApprovalRejectPayload, type AttachmentMeta, type AuthScheme, type BootstrapReconcileResult, type BootstrapTenantRequest, type BootstrapTenantResult, type CacheClearResult, type CacheStats, type ChangePasswordInput, type ChironCategory, type ChironManifest, type ChironSkill, type ChironStage, type ClearMetaCacheOpts, CliError, CliErrorCode, type CliErrorInit, type ClientAuthContext, type ClientCredentialsInput, type ConnectionMessage, type ControlChannelEnvelope, type ConversationListItem, type ConversationListResult, type ConversationState, type CreateResult, type CreatedConversation, DEFAULT_AGENT_ID, DEFAULT_SESSION_TTL_SECONDS, type DescribeOpts, type EnvConfig, ExitCode, type FieldMeta, type Fixture, type FormatOptions, type GlobalConfig, HcmClient, type HcmClientOpts, type HttpClientOptions, type IdentityMeta, type ImportClient, type ImportOptions, type ImportResult, type InteractionAnswerPayload, type InteractionRequest, type InteractionResolved, type ListTenantMetaOpts, type LoginOutcome, MINI_CONTEXT_FILE, MINI_CONTEXT_KIND, MINI_CONTEXT_VERSION, MINI_PULL_MANIFEST_FILE, MINI_REMOTE_ROOT, MINI_STATE_DIR, type MessageClass, type MessageCreatePayload, type MessageStreamHandle, type MigrationSummary, type MiniFileSnapshot, type MiniInitArgs, type MiniLocalFile, type MiniLocalStatus, type MiniPreviewTarget, type MiniProjectContext, type MiniPullArgs, type MiniPullManifest, type MiniPullResult, type MiniPushArgs, type MiniPushConflict, type MiniPushOperation, type MiniPushPlanItem, type MiniPushResult, type MiniSmokeCheckArgs, type MiniSmokeFetch, type MiniSmokeFetchResponse, type MiniSmokeResult, type MiniSmokeTargetKind, type MiniSmokeTargetResult, type MiniStatusEntry, type MiniSurface, type MiniTemplateArgs, type MiniTemplateKind, type MiniValidationResult, type MiniVerifyAgentReport, type MiniVerifyBrowserAcceptance, type MiniVerifyChangedFile, type MiniVerifyNextAction, type MiniVerifyPlan, type MiniVerifyPreviewUrl, type MiniVerifyReport, type MiniVerifySummary, type MiniWritableTemplateConfig, type ModelDescription, type ModelQueryDsl, type OneShotOpts, type OneShotResult, type OneShotToolCall, type OutputFormat, PASSWORD_CHANGE_REQUIRED, PROACTIVE_REFRESH_MARGIN_SECONDS, type PairingLoginInput, type ParsedPlaceholder, type PasswordChangeChallenge, type PasswordLoginInput, type PatLoginInput, type Principal, type ProfileConfig, type QueryResult, RefStore, type RefreshInput, type RelationMeta, type RemoveResult, type ResponseCompletedPayload, type ResponseFailedPayload, type ResponsePartDeltaPayload, type ResponseStartedPayload, type ResumeSummary, type ResumeTurn, type RowResult, type RowStatus, SDK_VERSION, type SaveMetaResult, type SendMessageOpts, type SettingItem, type SettingWrite, type StreamCancelPayload, type StreamCommand, type StreamCommandEnvelope, type StreamCommandType, type StreamEventEnvelope, type StreamEventType, type TaskProgressPayload, type TenantMetaEntry, type TimelineItemLite, type TokenRecord, TokenStore, type ToolCallFailedPayload, type ToolCallResultPayload, type ToolCallStartedPayload, type V4RenderSink, type V4StreamEventType, type WorkspaceFileContent, type WorkspaceFileItem, type WorkspaceFileListResult, WsClient, type WsClientOpts, absoluteDownloadUrl, archiveDir, assertSafeReferencePath, assertSafeSkillId, bootstrapTenant, buildAnswer, buildConfirm, buildInterrupt, buildMiniAppTemplateFiles, buildMiniPreviewTargets, buildMiniVerifyAgentReport, buildReject, buildResumeSummary, buildSteer, camelizeKeys, changePassword, classifyMessage, clearMetaCache, clearModelCache, conversationStateFile, create, createConversation, createHttpClient, createV4Reducer, createWorkspaceFile, credentialsFile, defaultDownloadDir, defaultMiniRequiredScopes, deleteEnv, deleteIdentity, deleteTenantMeta, deleteWorkspaceFile, deriveNamelessToolLabel, describePrincipal, detectDelegationPause, detectDirectInteractionPending, detectPasswordChangeChallenge, displayWidth, downloadDocument, ensureSessionFresh, envDir, envFile, envsDir, exitCodeFor, extractNextSteps, fetchConversationTimeline, fetchConversationTimelineStrict, fetchRecentConversations, fetchSkillCatalog, fetchSkillMarkdown, fetchSkillReference, filterByStage, findLastAssistantSeq, flattenSkills, formatMiniVerifyReport, formatObject, formatRows, fromAxiosError, getCacheStats, getMiniStatus, getSettingDomain, getTenantMeta, globalConfigFile, guessMimeType, hcmConfigDir, identitiesDir, identityDir, identityMetaFile, inferEnvName, inferMiniWritableTemplateOptionsFromModel, initMiniAppProject, isDelegationToolName, isServerSlidingSession, listEnvs, listIdentities, listProfiles, listTenantMeta, listWorkspaceFiles, loadConversationState, loadEnv, loadGlobalConfig, loadIdentity, loadProfile, loadWorkspaceFileContent, loginClientCredentials, loginPairing, loginPassword, loginPat, matchSkills, migrateLegacyProfiles, needsRefresh, normalizeReferences, oneShot, parseConfirmToolName, parseFixture, parseInteractionRequest, parseInteractionResolved, parsePlaceholder, parseSettingAssignment, parseSkillRequirements, patchSettingDomain, profileDir, profileFile, pullMiniAppProject, pushMiniAppProject, readMiniContext, readPullManifest, refreshToken, remove, replHistoryFile, resetSettingItem, resolveActiveEnv, resolveActiveIdentity, resolveActiveProfile, resolveChironBase, resolveRefs, resolveSkillInstallOrder, runImport, runMiniSmokeChecks, saveConversationState, saveEnv, saveGlobalConfig, saveIdentity, saveProfile, saveTenantMeta, saveWorkspaceFileContent, sendMessageAndStream, snakeToCamel, toJson, toOrigin, toPrincipal, toTable, toYaml, truncateDisplay, update, uploadDocument, validateMiniProject };
|
package/dist/index.js
CHANGED
|
@@ -1403,13 +1403,14 @@ var MIME_BY_EXT = {
|
|
|
1403
1403
|
function guessMimeType(filePath) {
|
|
1404
1404
|
return MIME_BY_EXT[path4.extname(filePath).toLowerCase()] ?? "application/octet-stream";
|
|
1405
1405
|
}
|
|
1406
|
-
|
|
1406
|
+
var CHAT_ATTACHMENT_CATEGORY = "ai-conversation";
|
|
1407
|
+
async function uploadDocument(http, filePath, storageCategory = CHAT_ATTACHMENT_CATEGORY) {
|
|
1407
1408
|
const abs = expandHome(filePath);
|
|
1408
1409
|
const buf = await fsp.readFile(abs);
|
|
1409
1410
|
const fileName = path4.basename(abs);
|
|
1410
1411
|
const form = new FormData();
|
|
1411
1412
|
form.append("file", new Blob([buf], { type: guessMimeType(abs) }), fileName);
|
|
1412
|
-
form.append("storageCategory",
|
|
1413
|
+
form.append("storageCategory", storageCategory);
|
|
1413
1414
|
form.append("allowEmptyFormId", "true");
|
|
1414
1415
|
const resp = await http.post("/api/documents/upload", form);
|
|
1415
1416
|
const meta = resp.data?.data ?? resp.data;
|
|
@@ -5002,20 +5003,151 @@ async function deleteTenantMeta(http, path6) {
|
|
|
5002
5003
|
}
|
|
5003
5004
|
|
|
5004
5005
|
// src/skills.ts
|
|
5005
|
-
|
|
5006
|
-
|
|
5006
|
+
import yaml7, { JSON_SCHEMA as JSON_SCHEMA2 } from "js-yaml";
|
|
5007
|
+
var CHIRON_BASE_CANDIDATES = ["/api", ""];
|
|
5008
|
+
function looksLikeManifest(data) {
|
|
5009
|
+
if (!data || typeof data !== "object") return false;
|
|
5010
|
+
const m = data;
|
|
5011
|
+
return m.name === "chiron" && Array.isArray(m.categories);
|
|
5012
|
+
}
|
|
5013
|
+
async function resolveChironBase(http) {
|
|
5014
|
+
const tried = [];
|
|
5015
|
+
for (const base of CHIRON_BASE_CANDIDATES) {
|
|
5016
|
+
const url = `${base}/skills.json`;
|
|
5017
|
+
tried.push(url);
|
|
5018
|
+
try {
|
|
5019
|
+
const resp = await http.get(url);
|
|
5020
|
+
const data = resp.data?.data ?? resp.data;
|
|
5021
|
+
if (looksLikeManifest(data)) return base;
|
|
5022
|
+
} catch {
|
|
5023
|
+
}
|
|
5024
|
+
}
|
|
5025
|
+
throw new CliError({
|
|
5026
|
+
code: "INVALID_ARGUMENT" /* INVALID_ARGUMENT */,
|
|
5027
|
+
message: `\u8FD9\u4E2A\u73AF\u5883\u4E0A\u627E\u4E0D\u5230\u777F\u620E\u6280\u80FD\u5E93\uFF08\u8BD5\u8FC7 ${tried.join(" \u548C ")}\uFF09\u3002\u5E38\u89C1\u539F\u56E0\uFF1A\u2460 \u540E\u7AEF\u7248\u672C\u8FD8\u6CA1\u6709 /api/skills \u7AEF\u70B9\uFF0C\u5347\u7EA7\u540E\u7AEF\u5373\u53EF\uFF1B\u2461 endpoint \u586B\u7684\u662F\u524D\u7AEF\u5730\u5740\u4E14\u672A\u53CD\u4EE3\u5230\u540E\u7AEF\uFF1B\u2462 \u5730\u5740\u6216\u7F51\u7EDC\u4E0D\u901A\u3002`
|
|
5028
|
+
});
|
|
5029
|
+
}
|
|
5030
|
+
async function fetchSkillCatalog(http, base) {
|
|
5031
|
+
const resp = await http.get(`${base}/skills.json`);
|
|
5007
5032
|
return resp.data?.data ?? resp.data;
|
|
5008
5033
|
}
|
|
5009
|
-
async function fetchSkillMarkdown(http, id) {
|
|
5010
|
-
const resp = await http.get(
|
|
5034
|
+
async function fetchSkillMarkdown(http, id, base) {
|
|
5035
|
+
const resp = await http.get(`${base}/skills/${encodeURIComponent(id)}.md`, {
|
|
5036
|
+
responseType: "text",
|
|
5037
|
+
transformResponse: [(d) => d]
|
|
5038
|
+
});
|
|
5039
|
+
return String(resp.data ?? "");
|
|
5040
|
+
}
|
|
5041
|
+
async function fetchSkillReference(http, id, relativePath, base) {
|
|
5042
|
+
assertSafeReferencePath(relativePath);
|
|
5043
|
+
const encoded = relativePath.split("/").map(encodeURIComponent).join("/");
|
|
5044
|
+
const resp = await http.get(`${base}/skills/${encodeURIComponent(id)}/references/${encoded}`, {
|
|
5011
5045
|
responseType: "text",
|
|
5012
5046
|
transformResponse: [(d) => d]
|
|
5013
5047
|
});
|
|
5014
5048
|
return String(resp.data ?? "");
|
|
5015
5049
|
}
|
|
5050
|
+
function assertSafeReferencePath(relativePath) {
|
|
5051
|
+
const ok = /^[A-Za-z0-9_][A-Za-z0-9._-]{0,63}(\/[A-Za-z0-9_][A-Za-z0-9._-]{0,63}){0,2}$/.test(relativePath);
|
|
5052
|
+
if (!ok) {
|
|
5053
|
+
throw invalid(`\u53C2\u8003\u6587\u4EF6\u8DEF\u5F84\u4E0D\u5408\u6CD5\uFF1A${JSON.stringify(relativePath)}`);
|
|
5054
|
+
}
|
|
5055
|
+
}
|
|
5056
|
+
function normalizeReferences(raw, skillId) {
|
|
5057
|
+
if (raw === void 0 || raw === null) return [];
|
|
5058
|
+
if (!Array.isArray(raw)) throw invalid(`\u6280\u80FD ${skillId} \u7684 references \u53EA\u80FD\u662F\u5B57\u7B26\u4E32\u6570\u7EC4`);
|
|
5059
|
+
const out = [];
|
|
5060
|
+
for (const value of raw) {
|
|
5061
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
5062
|
+
throw invalid(`\u6280\u80FD ${skillId} \u7684 references \u53EA\u80FD\u662F\u975E\u7A7A\u5B57\u7B26\u4E32\u6570\u7EC4`);
|
|
5063
|
+
}
|
|
5064
|
+
const rel = value.trim();
|
|
5065
|
+
assertSafeReferencePath(rel);
|
|
5066
|
+
if (!out.includes(rel)) out.push(rel);
|
|
5067
|
+
}
|
|
5068
|
+
return out;
|
|
5069
|
+
}
|
|
5016
5070
|
function flattenSkills(manifest2) {
|
|
5017
5071
|
return (manifest2.categories ?? []).flatMap((c) => c.skills ?? []);
|
|
5018
5072
|
}
|
|
5073
|
+
function resolveSkillInstallOrder(manifest2, targetId) {
|
|
5074
|
+
const byId = /* @__PURE__ */ new Map();
|
|
5075
|
+
for (const skill of flattenSkills(manifest2)) {
|
|
5076
|
+
if (byId.has(skill.id)) {
|
|
5077
|
+
throw invalid(`\u6280\u80FD\u76EE\u5F55\u5B58\u5728\u91CD\u590D id: ${skill.id}`);
|
|
5078
|
+
}
|
|
5079
|
+
byId.set(skill.id, skill);
|
|
5080
|
+
}
|
|
5081
|
+
if (!byId.has(targetId)) {
|
|
5082
|
+
throw invalid(`\u6280\u80FD\u76EE\u5F55\u4E2D\u4E0D\u5B58\u5728 ${targetId}`);
|
|
5083
|
+
}
|
|
5084
|
+
const state = /* @__PURE__ */ new Map();
|
|
5085
|
+
const path6 = [];
|
|
5086
|
+
const order = [];
|
|
5087
|
+
const visit = (id, requiredBy) => {
|
|
5088
|
+
const current = state.get(id);
|
|
5089
|
+
if (current === "done") return;
|
|
5090
|
+
if (current === "visiting") {
|
|
5091
|
+
const cycleStart = path6.indexOf(id);
|
|
5092
|
+
const cycle = [...path6.slice(Math.max(0, cycleStart)), id];
|
|
5093
|
+
throw invalid(`\u6280\u80FD\u4F9D\u8D56\u5B58\u5728\u73AF: ${cycle.join(" -> ")}`);
|
|
5094
|
+
}
|
|
5095
|
+
const skill = byId.get(id);
|
|
5096
|
+
if (!skill) {
|
|
5097
|
+
throw invalid(`\u6280\u80FD ${requiredBy ?? targetId} \u4F9D\u8D56\u4E0D\u5B58\u5728: ${id}`);
|
|
5098
|
+
}
|
|
5099
|
+
assertSafeSkillId(skill.id);
|
|
5100
|
+
state.set(id, "visiting");
|
|
5101
|
+
path6.push(id);
|
|
5102
|
+
for (const required of normalizeRequirements(skill.requires, skill.id)) {
|
|
5103
|
+
visit(required, skill.id);
|
|
5104
|
+
}
|
|
5105
|
+
path6.pop();
|
|
5106
|
+
state.set(id, "done");
|
|
5107
|
+
order.push(skill);
|
|
5108
|
+
};
|
|
5109
|
+
visit(targetId);
|
|
5110
|
+
return order;
|
|
5111
|
+
}
|
|
5112
|
+
function parseSkillRequirements(markdown, skillId) {
|
|
5113
|
+
const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(markdown);
|
|
5114
|
+
if (!match) return [];
|
|
5115
|
+
let frontmatter;
|
|
5116
|
+
try {
|
|
5117
|
+
frontmatter = yaml7.load(match[1] ?? "", { schema: JSON_SCHEMA2 });
|
|
5118
|
+
} catch (cause) {
|
|
5119
|
+
throw new CliError({
|
|
5120
|
+
code: "INVALID_ARGUMENT" /* INVALID_ARGUMENT */,
|
|
5121
|
+
message: `\u6280\u80FD ${skillId} \u7684 frontmatter \u4E0D\u662F\u5408\u6CD5 YAML`,
|
|
5122
|
+
cause
|
|
5123
|
+
});
|
|
5124
|
+
}
|
|
5125
|
+
if (!frontmatter || typeof frontmatter !== "object" || Array.isArray(frontmatter)) return [];
|
|
5126
|
+
const raw = frontmatter.requires;
|
|
5127
|
+
return normalizeRequirements(raw, skillId);
|
|
5128
|
+
}
|
|
5129
|
+
function assertSafeSkillId(id) {
|
|
5130
|
+
if (!/^[a-z0-9][a-z0-9-]{0,63}$/.test(id)) {
|
|
5131
|
+
throw invalid(`\u6280\u80FD id \u53EA\u80FD\u662F\u5C0F\u5199\u5B57\u6BCD/\u6570\u5B57/\u8FDE\u5B57\u7B26\uFF0C\u6536\u5230 "${id}"`);
|
|
5132
|
+
}
|
|
5133
|
+
}
|
|
5134
|
+
function normalizeRequirements(raw, skillId) {
|
|
5135
|
+
if (raw === void 0 || raw === null) return [];
|
|
5136
|
+
const values = Array.isArray(raw) ? raw : [raw];
|
|
5137
|
+
const normalized = [];
|
|
5138
|
+
for (const value of values) {
|
|
5139
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
5140
|
+
throw invalid(`\u6280\u80FD ${skillId} \u7684 requires \u53EA\u80FD\u662F\u975E\u7A7A\u6280\u80FD id \u6570\u7EC4`);
|
|
5141
|
+
}
|
|
5142
|
+
const id = value.trim();
|
|
5143
|
+
assertSafeSkillId(id);
|
|
5144
|
+
if (!normalized.includes(id)) normalized.push(id);
|
|
5145
|
+
}
|
|
5146
|
+
return normalized;
|
|
5147
|
+
}
|
|
5148
|
+
function invalid(message) {
|
|
5149
|
+
return new CliError({ code: "INVALID_ARGUMENT" /* INVALID_ARGUMENT */, message });
|
|
5150
|
+
}
|
|
5019
5151
|
function filterByStage(skills, stage) {
|
|
5020
5152
|
if (!stage) return skills;
|
|
5021
5153
|
return skills.filter((s) => (s.stages ?? []).includes(stage));
|
|
@@ -5076,6 +5208,8 @@ export {
|
|
|
5076
5208
|
WsClient,
|
|
5077
5209
|
absoluteDownloadUrl,
|
|
5078
5210
|
archiveDir,
|
|
5211
|
+
assertSafeReferencePath,
|
|
5212
|
+
assertSafeSkillId,
|
|
5079
5213
|
bootstrapTenant,
|
|
5080
5214
|
buildAnswer,
|
|
5081
5215
|
buildConfirm,
|
|
@@ -5122,6 +5256,7 @@ export {
|
|
|
5122
5256
|
fetchRecentConversations,
|
|
5123
5257
|
fetchSkillCatalog,
|
|
5124
5258
|
fetchSkillMarkdown,
|
|
5259
|
+
fetchSkillReference,
|
|
5125
5260
|
filterByStage,
|
|
5126
5261
|
findLastAssistantSeq,
|
|
5127
5262
|
flattenSkills,
|
|
@@ -5162,6 +5297,7 @@ export {
|
|
|
5162
5297
|
matchSkills,
|
|
5163
5298
|
migrateLegacyProfiles,
|
|
5164
5299
|
needsRefresh,
|
|
5300
|
+
normalizeReferences,
|
|
5165
5301
|
oneShot,
|
|
5166
5302
|
parseConfirmToolName,
|
|
5167
5303
|
parseFixture,
|
|
@@ -5169,6 +5305,7 @@ export {
|
|
|
5169
5305
|
parseInteractionResolved,
|
|
5170
5306
|
parsePlaceholder,
|
|
5171
5307
|
parseSettingAssignment,
|
|
5308
|
+
parseSkillRequirements,
|
|
5172
5309
|
patchSettingDomain,
|
|
5173
5310
|
profileDir,
|
|
5174
5311
|
profileFile,
|
|
@@ -5183,7 +5320,9 @@ export {
|
|
|
5183
5320
|
resolveActiveEnv,
|
|
5184
5321
|
resolveActiveIdentity,
|
|
5185
5322
|
resolveActiveProfile,
|
|
5323
|
+
resolveChironBase,
|
|
5186
5324
|
resolveRefs,
|
|
5325
|
+
resolveSkillInstallOrder,
|
|
5187
5326
|
runImport,
|
|
5188
5327
|
runMiniSmokeChecks,
|
|
5189
5328
|
saveConversationState,
|