| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126 |
- // Copyright (c) 未来飞马
- //
- // This Source Code Form is subject to the terms of the Mozilla Public
- // License, v. 2.0. If a copy of the MPL was not distributed with this
- // file, You can obtain one at https://mozilla.org/MPL/2.0/.
- //
- // Trademark Notice:
- // The MPL-2.0 license grants copyright permissions for source code only.
- // It does NOT grant any rights to use trademarks including "未来飞马",
- // "Harness Loop", "RSI", and associated slogan "让AI进化提前发生,让AI落地快人一步".
- // Any use of these trademarks requires separate written permission.
- /**
- * skill-deliverable SDK — 交付物上报核心
- *
- * 零依赖(使用 Node ≥ 18 内置 fetch + fs)
- * 所有凭据从 env → config 文件 → 兜底,按高兼容链解析
- */
- import { readFileSync, existsSync, constants } from 'fs';
- import { homedir, hostname } from 'os';
- import { join } from 'path';
- import { env } from 'process';
- const HOME = homedir();
- const GATEWAY = env.FMODE_API || 'https://server.fmode.cn';
- const FN_ID = env.FN_DELIVERABLES || 'lfYlgU7SkK';
- // ============================================================
- // Agent 身份高兼容解析
- // ============================================================
- export function resolveAgentId() {
- // 1. env
- if (env.FMODE_AGENT_ID) return env.FMODE_AGENT_ID;
- if (env.AGENT_ID) return env.AGENT_ID;
- // 2. ~/.fmode/config.json
- const homeCfg = tryReadJSON(join(HOME, '.fmode', 'config.json'));
- if (homeCfg?.agentId) return homeCfg.agentId;
- // 3. ./.fmode/config.json (cwd)
- const cwdCfg = tryReadJSON(join(process.cwd(), '.fmode', 'config.json'));
- if (cwdCfg?.agentId) return cwdCfg.agentId;
- // 4. 兜底 hostname(仅 warn)
- const hn = hostname();
- console.warn(`[warn] 未找到语义 agentId,回退到 hostname "${hn}"(可能不是注册名)`);
- return hn;
- }
- // ============================================================
- // Session Token 高兼容解析
- // ============================================================
- export function resolveSessionToken() {
- // 1. env
- if (env.FMODE_SESSION_TOKEN) return env.FMODE_SESSION_TOKEN;
- // 2. ~/.fmode/config/user.json
- const userCfg = tryReadJSON(join(HOME, '.fmode', 'config', 'user.json'));
- if (userCfg?.sessionToken) return userCfg.sessionToken;
- // 3. ~/.fmode/config.json
- const homeCfg = tryReadJSON(join(HOME, '.fmode', 'config.json'));
- if (homeCfg?.sessionToken) return homeCfg.sessionToken;
- // 4. ./.fmode/config.json (cwd)
- const cwdCfg = tryReadJSON(join(process.cwd(), '.fmode', 'config.json'));
- if (cwdCfg?.sessionToken) return cwdCfg.sessionToken;
- return null;
- }
- // ============================================================
- // 云函数调用
- // ============================================================
- export async function callFn(params) {
- const token = resolveSessionToken();
- if (!token) throw new Error('无 sessionToken:无法调用云函数。设置 FMODE_SESSION_TOKEN 环境变量或 ~/.fmode/config/user.json');
- const resp = await fetch(`${GATEWAY}/api/functions`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ token, id: FN_ID, params }),
- });
- return resp.json();
- }
- // ============================================================
- // 上报交付物
- // ============================================================
- export async function report({ agentId, agentObjectId, title, summary, project, artifacts, tags }) {
- if (!title) throw new Error('title 必填');
- const resolvedAgentId = agentId || resolveAgentId();
- if (!resolvedAgentId) throw new Error('agentId 必填');
-
- return callFn({
- action: 'report',
- agentId: resolvedAgentId,
- agentObjectId: agentObjectId || '',
- title,
- summary: summary || '',
- project: project || '',
- artifacts: artifacts || [],
- tags: tags || [],
- });
- }
- // ============================================================
- // 查询交付物
- // ============================================================
- export async function list({ limit = 5, agentId } = {}) {
- const r = await callFn({ action: 'list', agentId: agentId || resolveAgentId(), limit });
- return r.deliverables || [];
- }
- // ============================================================
- // 工具
- // ============================================================
- function tryReadJSON(p) {
- try {
- if (!existsSync(p)) return null;
- return JSON.parse(readFileSync(p, 'utf-8'));
- } catch {
- return null;
- }
- }
- export default { resolveAgentId, resolveSessionToken, report, list, callFn };
|