@gitruck/cli 1.0.3 → 1.0.5
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/AGENT.md +31 -0
- package/LICENSE +21 -21
- package/README.en.md +627 -626
- package/README.md +625 -624
- package/contracts/README.md +14 -14
- package/contracts/handoff-contracts.json +10 -10
- package/dist/index.js +286 -1
- package/package.json +66 -66
- package/skills/gtrk-cover/SKILL.md +93 -93
- package/skills/gtrk-cover/assets/workbench-template.html +955 -955
- package/skills/gtrk-cover/references/checklist.md +81 -81
- package/skills/gtrk-cover/references/layout-recipes.md +337 -337
- package/skills/gtrk-cover/references/prompt-templates.md +119 -119
- package/skills/gtrk-cover/references/workbench-guide.md +99 -99
- package/skills/gtrk-music-visualizer/SKILL.md +76 -76
- package/skills/gtrk-splitter/references/example-visual-split.json +638 -638
- package/skills/gtrk-splitter/references/example-visual-split.md +439 -439
- package/skills/gtrk-style-maker/references/ammo.md +16 -16
- package/skills/gtrk-style-maker/references/contracts-ref.md +9 -9
- package/skills/gtrk-style-maker/references/seeds/README.md +4 -4
- package/skills/gtrk-style-maker/references/seeds/seed-ecom-home-goods.md +37 -37
- package/skills/gtrk-style-maker/references/seeds/seed-psych-humanities.md +35 -35
- package/skills/gtrk-transcript/agents/openai.yaml +4 -4
- package/skills/gtrk-travel-recap/SKILL.md +212 -212
package/contracts/README.md
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
# 框架契约库(handoff contracts)
|
|
2
|
-
|
|
3
|
-
同合云管线的 handoff 契约**正本**,随 `@gitruck/cli` npm 包分发。创作 skill 以「契约名 + 版本」引用(如 `gsap-emit v1`);`handoff-contracts.json` 是「handoff 类型 → 契约」映射表,消费方查表、不硬编码。
|
|
4
|
-
|
|
5
|
-
## 收录双轴边界(handoff-contract-library spec,扩项须走 change 过审)
|
|
6
|
-
|
|
7
|
-
- **轴一(管线性,审美零预设)**:契约只约束**机器可判定的管线消费属性**(封装/注册/确定性/依赖可达/产物格式)。**不得**规定颜色、字体、构图、红点数量等任何视觉取值或栏目词表词条;凡涉视觉取值处一律参数化/中性占位。「全片最多一个红点」这类审美铁律属栏目 skill 侧,**不入库**。
|
|
8
|
-
- **轴二(脱敏)**:只收**自有管线**的合规契约——渲染引擎合规、`.gtrk` 契约、派单格式(封闭列举)。外部供应商/外部平台适配内容(AI 视频平台差异、文生图平台参数等)**永不收录**,那属于用户自己的 skill。
|
|
9
|
-
|
|
10
|
-
## 现有契约
|
|
11
|
-
|
|
12
|
-
| 契约 | 版本 | 适用 handoff | 文档 |
|
|
13
|
-
|---|---|---|---|
|
|
14
|
-
| gsap-emit(HTML 动画颗粒逐帧 seek 合规) | v1 | MG(去品牌化前 RRV_MG,消费方查表前归一) | [gsap-emit-v1.md](gsap-emit-v1.md) |
|
|
1
|
+
# 框架契约库(handoff contracts)
|
|
2
|
+
|
|
3
|
+
同合云管线的 handoff 契约**正本**,随 `@gitruck/cli` npm 包分发。创作 skill 以「契约名 + 版本」引用(如 `gsap-emit v1`);`handoff-contracts.json` 是「handoff 类型 → 契约」映射表,消费方查表、不硬编码。
|
|
4
|
+
|
|
5
|
+
## 收录双轴边界(handoff-contract-library spec,扩项须走 change 过审)
|
|
6
|
+
|
|
7
|
+
- **轴一(管线性,审美零预设)**:契约只约束**机器可判定的管线消费属性**(封装/注册/确定性/依赖可达/产物格式)。**不得**规定颜色、字体、构图、红点数量等任何视觉取值或栏目词表词条;凡涉视觉取值处一律参数化/中性占位。「全片最多一个红点」这类审美铁律属栏目 skill 侧,**不入库**。
|
|
8
|
+
- **轴二(脱敏)**:只收**自有管线**的合规契约——渲染引擎合规、`.gtrk` 契约、派单格式(封闭列举)。外部供应商/外部平台适配内容(AI 视频平台差异、文生图平台参数等)**永不收录**,那属于用户自己的 skill。
|
|
9
|
+
|
|
10
|
+
## 现有契约
|
|
11
|
+
|
|
12
|
+
| 契约 | 版本 | 适用 handoff | 文档 |
|
|
13
|
+
|---|---|---|---|
|
|
14
|
+
| gsap-emit(HTML 动画颗粒逐帧 seek 合规) | v1 | MG(去品牌化前 RRV_MG,消费方查表前归一) | [gsap-emit-v1.md](gsap-emit-v1.md) |
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 1,
|
|
3
|
-
"comment": "handoff 类型 → 契约映射表(handoff-contract-library spec)。消费方(含 gtrk-style-maker)查此表,不得硬编码映射;消费方查表前先将遗留品牌值(如 RRV_MG)归一为中性名(MG)。null = 暂无契约(产线可用,无合规绑定要求)。注册集当前 = 现行四车道(P2 注册表化前的过渡事实)。",
|
|
4
|
-
"mappings": {
|
|
5
|
-
"A_ROLL": null,
|
|
6
|
-
"MG": { "contract": "gsap-emit", "version": "v1", "doc": "gsap-emit-v1.md" },
|
|
7
|
-
"AI_DRAMA": null,
|
|
8
|
-
"FILM_BROLL": null
|
|
9
|
-
}
|
|
10
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"comment": "handoff 类型 → 契约映射表(handoff-contract-library spec)。消费方(含 gtrk-style-maker)查此表,不得硬编码映射;消费方查表前先将遗留品牌值(如 RRV_MG)归一为中性名(MG)。null = 暂无契约(产线可用,无合规绑定要求)。注册集当前 = 现行四车道(P2 注册表化前的过渡事实)。",
|
|
4
|
+
"mappings": {
|
|
5
|
+
"A_ROLL": null,
|
|
6
|
+
"MG": { "contract": "gsap-emit", "version": "v1", "doc": "gsap-emit-v1.md" },
|
|
7
|
+
"AI_DRAMA": null,
|
|
8
|
+
"FILM_BROLL": null
|
|
9
|
+
}
|
|
10
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -8159,7 +8159,7 @@ function layBrollTracks(opts) {
|
|
|
8159
8159
|
contract_version: "v1",
|
|
8160
8160
|
generated_at: opts.generatedAt,
|
|
8161
8161
|
plan_path: opts.planPath,
|
|
8162
|
-
lay_tracks: blackTrack === null ? registeredIndices : [...registeredIndices, blackTrack],
|
|
8162
|
+
lay_tracks: (blackTrack === null ? registeredIndices : [...registeredIndices, blackTrack]).slice().sort((a, b) => a - b),
|
|
8163
8163
|
track_layers: trackLayers,
|
|
8164
8164
|
black_track: blackTrack,
|
|
8165
8165
|
confirmed: false,
|
|
@@ -21869,6 +21869,290 @@ function registerSubtitle(program2) {
|
|
|
21869
21869
|
});
|
|
21870
21870
|
}
|
|
21871
21871
|
|
|
21872
|
+
// src/commands/feedback.ts
|
|
21873
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
21874
|
+
import { release } from "node:os";
|
|
21875
|
+
var CATEGORIES = [
|
|
21876
|
+
"complaint",
|
|
21877
|
+
"env_unstable",
|
|
21878
|
+
"confused",
|
|
21879
|
+
"blocked",
|
|
21880
|
+
"agent_self_detected",
|
|
21881
|
+
"feature_request",
|
|
21882
|
+
"other"
|
|
21883
|
+
];
|
|
21884
|
+
var CATEGORY_LABELS = {
|
|
21885
|
+
complaint: "抱怨吐槽",
|
|
21886
|
+
env_unstable: "环境不稳",
|
|
21887
|
+
confused: "用法困惑",
|
|
21888
|
+
blocked: "使用受阻",
|
|
21889
|
+
agent_self_detected: "助手自查",
|
|
21890
|
+
feature_request: "功能诉求",
|
|
21891
|
+
other: "其他"
|
|
21892
|
+
};
|
|
21893
|
+
var PLATFORM_LABELS = {
|
|
21894
|
+
win32: "Windows",
|
|
21895
|
+
darwin: "macOS",
|
|
21896
|
+
linux: "Linux"
|
|
21897
|
+
};
|
|
21898
|
+
var SUMMARY_MAX_CHARS = 512;
|
|
21899
|
+
var USER_QUOTE_MAX_CHARS = 2000;
|
|
21900
|
+
var CONTEXT_WHITELIST = {
|
|
21901
|
+
os: { type: "string", pattern: /^(win32|darwin|linux)$/ },
|
|
21902
|
+
os_release: { type: "string", pattern: /^[0-9][0-9A-Za-z.\-]{0,31}$/ },
|
|
21903
|
+
arch: { type: "string", pattern: /^(x64|arm64|ia32|arm)$/ },
|
|
21904
|
+
locale: { type: "string", pattern: /^[a-z]{2}(-[A-Za-z]{2})?$/ },
|
|
21905
|
+
command: { type: "string", pattern: /^[a-z][a-z0-9-]{0,31}( [a-z][a-z0-9-]{0,31}){0,2}$/ },
|
|
21906
|
+
exit_code: { type: "int", min: -256, max: 256 },
|
|
21907
|
+
duration_ms: { type: "int", min: 0, max: 86400000 },
|
|
21908
|
+
route: { type: "string", pattern: /^[a-z][a-z0-9/_-]{0,63}$/ },
|
|
21909
|
+
webview_version: { type: "string", pattern: /^[0-9][0-9A-Za-z.\-]{0,31}$/ },
|
|
21910
|
+
task_type: { type: "string", pattern: /^[a-z][a-z0-9_]{0,63}$/ },
|
|
21911
|
+
error_code: { type: "int", min: 0, max: 65535 },
|
|
21912
|
+
project_id: { type: "string", pattern: /^[0-9a-fA-F-]{8,64}$/ },
|
|
21913
|
+
column_key: { type: "string", pattern: /^[a-z][a-z0-9_-]{0,63}$/ }
|
|
21914
|
+
};
|
|
21915
|
+
var USER_SETTABLE_KEYS = [
|
|
21916
|
+
"exit_code",
|
|
21917
|
+
"duration_ms",
|
|
21918
|
+
"task_type",
|
|
21919
|
+
"error_code",
|
|
21920
|
+
"project_id",
|
|
21921
|
+
"column_key"
|
|
21922
|
+
];
|
|
21923
|
+
var REDACTION_RULES = [
|
|
21924
|
+
{ re: /\bbearer\s+\S+/gi, to: "<凭据已隐去>" },
|
|
21925
|
+
{
|
|
21926
|
+
re: /\b(?:api[_-]?key|secret|token|password|passwd|authorization)\b\s*[:=]\s*\S+/gi,
|
|
21927
|
+
to: "<凭据已隐去>"
|
|
21928
|
+
},
|
|
21929
|
+
{ re: /\bgc_[A-Za-z0-9_-]{16,}\b/g, to: "<凭据已隐去>" },
|
|
21930
|
+
{ re: /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}(?:\.[A-Za-z0-9_-]+)?/g, to: "<凭据已隐去>" },
|
|
21931
|
+
{ re: /(?:(?<![A-Za-z])[A-Za-z]:[\\/]|\\\\)[^\s"'<>|]+/g, to: "<路径已隐去>" },
|
|
21932
|
+
{ re: /(?:~|\/(?:home|Users|root|mnt|media))\/[^\s"'<>|]*/g, to: "<路径已隐去>" },
|
|
21933
|
+
{ re: /(https?:\/\/[^\s"'<>]*?)\?[^\s"'<>]*/g, to: "$1" },
|
|
21934
|
+
{ re: /[\p{L}\p{N}_.+-]+@[\p{L}\p{N}_-]+\.[\p{L}\p{N}_.]+/gu, to: "<邮箱已隐去>" },
|
|
21935
|
+
{ re: /(?<!\d)1[3-9]\d{9}(?!\d)/g, to: "<手机号已隐去>" },
|
|
21936
|
+
{ re: /(?<!\d)\d{17}[\dXx](?!\d)/g, to: "<证件号已隐去>" },
|
|
21937
|
+
{ re: /\b[0-9a-fA-F]{32,}\b/g, to: "<凭据已隐去>" },
|
|
21938
|
+
{ re: /\b[A-Za-z0-9+/]{40,}={0,2}\b/g, to: "<凭据已隐去>" }
|
|
21939
|
+
];
|
|
21940
|
+
function redactText(text) {
|
|
21941
|
+
if (text == null)
|
|
21942
|
+
return;
|
|
21943
|
+
let out = String(text);
|
|
21944
|
+
for (const { re, to } of REDACTION_RULES) {
|
|
21945
|
+
re.lastIndex = 0;
|
|
21946
|
+
out = out.replace(re, to);
|
|
21947
|
+
}
|
|
21948
|
+
return out;
|
|
21949
|
+
}
|
|
21950
|
+
function parseContextPairs(pairs) {
|
|
21951
|
+
const context = {};
|
|
21952
|
+
for (const raw of pairs ?? []) {
|
|
21953
|
+
const eq = raw.indexOf("=");
|
|
21954
|
+
if (eq <= 0) {
|
|
21955
|
+
return { context, error: `--context 需要 k=v 形式,收到「${raw}」` };
|
|
21956
|
+
}
|
|
21957
|
+
const key = raw.slice(0, eq).trim();
|
|
21958
|
+
const value = raw.slice(eq + 1).trim();
|
|
21959
|
+
const entry = CONTEXT_WHITELIST[key];
|
|
21960
|
+
if (!entry || !USER_SETTABLE_KEYS.includes(key)) {
|
|
21961
|
+
return {
|
|
21962
|
+
context,
|
|
21963
|
+
error: `--context 不认识「${key}」。可用:${USER_SETTABLE_KEYS.join(" / ")}`
|
|
21964
|
+
};
|
|
21965
|
+
}
|
|
21966
|
+
if (entry.type === "int") {
|
|
21967
|
+
if (!/^-?\d+$/.test(value)) {
|
|
21968
|
+
return { context, error: `--context ${key} 需要整数,收到「${value}」` };
|
|
21969
|
+
}
|
|
21970
|
+
const n = Number(value);
|
|
21971
|
+
if (entry.min != null && n < entry.min || entry.max != null && n > entry.max) {
|
|
21972
|
+
return { context, error: `--context ${key} 超出取值范围(${entry.min} ~ ${entry.max})` };
|
|
21973
|
+
}
|
|
21974
|
+
context[key] = n;
|
|
21975
|
+
continue;
|
|
21976
|
+
}
|
|
21977
|
+
if (entry.pattern && !entry.pattern.test(value)) {
|
|
21978
|
+
return { context, error: `--context ${key} 的写法不符合要求,收到「${value}」` };
|
|
21979
|
+
}
|
|
21980
|
+
context[key] = value;
|
|
21981
|
+
}
|
|
21982
|
+
return { context };
|
|
21983
|
+
}
|
|
21984
|
+
function collectEnvContext() {
|
|
21985
|
+
const out = {};
|
|
21986
|
+
const put = (key, value) => {
|
|
21987
|
+
const entry = CONTEXT_WHITELIST[key];
|
|
21988
|
+
if (entry?.pattern?.test(value))
|
|
21989
|
+
out[key] = value;
|
|
21990
|
+
};
|
|
21991
|
+
put("os", process.platform);
|
|
21992
|
+
put("arch", process.arch);
|
|
21993
|
+
put("os_release", release());
|
|
21994
|
+
try {
|
|
21995
|
+
put("locale", new Intl.DateTimeFormat().resolvedOptions().locale);
|
|
21996
|
+
} catch {}
|
|
21997
|
+
return out;
|
|
21998
|
+
}
|
|
21999
|
+
function buildFeedbackPayload(message, opts, deps = {}) {
|
|
22000
|
+
const summaryRaw = (message ?? "").trim();
|
|
22001
|
+
if (!summaryRaw)
|
|
22002
|
+
return { error: "请把要反馈的内容写清楚(第一个参数)" };
|
|
22003
|
+
const command = (opts.command ?? "").trim();
|
|
22004
|
+
if (!command) {
|
|
22005
|
+
return { error: '请用 --command 说明这条反馈发生在哪个命令上,例如 --command "matrix search"' };
|
|
22006
|
+
}
|
|
22007
|
+
if (!CONTEXT_WHITELIST.command.pattern?.test(command)) {
|
|
22008
|
+
return {
|
|
22009
|
+
error: `--command 只填命令名(可带至多两级子命令),不要带参数。收到「${command}」,` + `应写成 --command "matrix search"`
|
|
22010
|
+
};
|
|
22011
|
+
}
|
|
22012
|
+
const category = opts.category ?? "other";
|
|
22013
|
+
if (!CATEGORIES.includes(category)) {
|
|
22014
|
+
return { error: `--category 只能是:${CATEGORIES.join(" / ")}` };
|
|
22015
|
+
}
|
|
22016
|
+
const parsed = parseContextPairs(opts.context);
|
|
22017
|
+
if (parsed.error)
|
|
22018
|
+
return { error: parsed.error };
|
|
22019
|
+
let taskId;
|
|
22020
|
+
if (opts.taskId != null && String(opts.taskId).trim() !== "") {
|
|
22021
|
+
if (!/^\d+$/.test(String(opts.taskId).trim())) {
|
|
22022
|
+
return { error: `--task-id 需要纯数字,收到「${opts.taskId}」` };
|
|
22023
|
+
}
|
|
22024
|
+
taskId = Number(String(opts.taskId).trim());
|
|
22025
|
+
}
|
|
22026
|
+
const summary = redactText(summaryRaw);
|
|
22027
|
+
const quoteRaw = opts.quote?.trim();
|
|
22028
|
+
const userQuote = quoteRaw ? redactText(quoteRaw) : undefined;
|
|
22029
|
+
if ([...summary].length > SUMMARY_MAX_CHARS) {
|
|
22030
|
+
return { error: `反馈内容过长(上限 ${SUMMARY_MAX_CHARS} 字),请精简后重试` };
|
|
22031
|
+
}
|
|
22032
|
+
if (userQuote && [...userQuote].length > USER_QUOTE_MAX_CHARS) {
|
|
22033
|
+
return { error: `--quote 过长(上限 ${USER_QUOTE_MAX_CHARS} 字),请精简后重试` };
|
|
22034
|
+
}
|
|
22035
|
+
const payload = {
|
|
22036
|
+
event_id: (deps.randomToken ?? (() => randomUUID2().replace(/-/g, "")))(),
|
|
22037
|
+
source: opts.disclosed ? "agent" : "cli",
|
|
22038
|
+
disclosure: opts.disclosed ? "agent_disclosed" : "user_submitted",
|
|
22039
|
+
category,
|
|
22040
|
+
summary,
|
|
22041
|
+
...userQuote ? { user_quote: userQuote } : {},
|
|
22042
|
+
context: { ...collectEnvContext(), ...parsed.context, command },
|
|
22043
|
+
...taskId != null ? { task_id: taskId } : {},
|
|
22044
|
+
reporter_version: currentVersion()
|
|
22045
|
+
};
|
|
22046
|
+
return { payload };
|
|
22047
|
+
}
|
|
22048
|
+
function renderDisclosureNotice(payload) {
|
|
22049
|
+
const bits = [];
|
|
22050
|
+
if (payload.context.command)
|
|
22051
|
+
bits.push(`命令 ${payload.context.command}`);
|
|
22052
|
+
bits.push(`版本 ${payload.reporter_version}`);
|
|
22053
|
+
const platform = payload.context.os ? PLATFORM_LABELS[String(payload.context.os)] : undefined;
|
|
22054
|
+
if (platform)
|
|
22055
|
+
bits.push(`系统 ${platform}${payload.context.arch ? ` ${payload.context.arch}` : ""}`);
|
|
22056
|
+
if (payload.task_id != null)
|
|
22057
|
+
bits.push(`任务 ${payload.task_id}`);
|
|
22058
|
+
const lines = [
|
|
22059
|
+
`类型:${CATEGORY_LABELS[payload.category]}`,
|
|
22060
|
+
`摘要:${payload.summary}`,
|
|
22061
|
+
...payload.user_quote ? [`你的原话:${payload.user_quote}`] : [],
|
|
22062
|
+
`随附信息:${bits.join(" | ")}`
|
|
22063
|
+
];
|
|
22064
|
+
return ["────────", ...lines, "────────"].join(`
|
|
22065
|
+
`);
|
|
22066
|
+
}
|
|
22067
|
+
function renderRefusalNotice(payload) {
|
|
22068
|
+
return [
|
|
22069
|
+
"⚠️ 这条反馈还没有经过用户确认,本次未发送。",
|
|
22070
|
+
" 请把下面这段原样念给用户,得到同意后,在原命令上加 --disclosed 重跑:",
|
|
22071
|
+
renderDisclosureNotice(payload)
|
|
22072
|
+
].join(`
|
|
22073
|
+
`);
|
|
22074
|
+
}
|
|
22075
|
+
var TIMEOUT_MS = 15000;
|
|
22076
|
+
async function postFeedback(cfg, payload, fetchFn = fetch) {
|
|
22077
|
+
noticeOnce();
|
|
22078
|
+
let lastNetworkError;
|
|
22079
|
+
for (let attempt = 0;attempt < 2; attempt++) {
|
|
22080
|
+
try {
|
|
22081
|
+
const res = await fetchFn(`${cfg.base}/feedback/report`, {
|
|
22082
|
+
method: "POST",
|
|
22083
|
+
headers: { Authorization: cfg.apiKey, "Content-Type": "application/json" },
|
|
22084
|
+
body: JSON.stringify(payload),
|
|
22085
|
+
signal: AbortSignal.timeout(TIMEOUT_MS)
|
|
22086
|
+
});
|
|
22087
|
+
const r = await parseJson(res);
|
|
22088
|
+
if (r.code === 200) {
|
|
22089
|
+
const data = r.data ?? {};
|
|
22090
|
+
return { duplicated: data.duplicated === true, retried: attempt > 0 };
|
|
22091
|
+
}
|
|
22092
|
+
throw new CloudError(r.code, `反馈提交失败 (code=${r.code ?? "?"}):${r.msg ?? "未知错误"}`);
|
|
22093
|
+
} catch (e) {
|
|
22094
|
+
if (e instanceof CloudError)
|
|
22095
|
+
throw e;
|
|
22096
|
+
lastNetworkError = e;
|
|
22097
|
+
}
|
|
22098
|
+
}
|
|
22099
|
+
throw lastNetworkError instanceof Error ? lastNetworkError : new Error(String(lastNetworkError));
|
|
22100
|
+
}
|
|
22101
|
+
async function runFeedback(message, opts, deps = {}) {
|
|
22102
|
+
if (opts.json)
|
|
22103
|
+
routeLogsToStderr();
|
|
22104
|
+
const write = deps.write ?? ((chunk2) => void process.stderr.write(chunk2));
|
|
22105
|
+
const isTty = deps.isTty ?? (() => process.stdout.isTTY === true);
|
|
22106
|
+
const built = buildFeedbackPayload(message, opts, deps);
|
|
22107
|
+
if (built.error || !built.payload)
|
|
22108
|
+
throw new Error(built.error ?? "反馈内容不完整");
|
|
22109
|
+
const payload = built.payload;
|
|
22110
|
+
if (!opts.disclosed) {
|
|
22111
|
+
if (!isTty()) {
|
|
22112
|
+
const notice = renderRefusalNotice(payload);
|
|
22113
|
+
write(`${notice}
|
|
22114
|
+
`);
|
|
22115
|
+
return {
|
|
22116
|
+
ok: false,
|
|
22117
|
+
submitted: false,
|
|
22118
|
+
code: "needs_user_confirmation",
|
|
22119
|
+
notice,
|
|
22120
|
+
exitCode: 1
|
|
22121
|
+
};
|
|
22122
|
+
}
|
|
22123
|
+
write(`${renderDisclosureNotice(payload)}
|
|
22124
|
+
`);
|
|
22125
|
+
if (!opts.yes) {
|
|
22126
|
+
const agreed = await (deps.confirm ?? promptConfirm)("确认发送?");
|
|
22127
|
+
if (!agreed) {
|
|
22128
|
+
return { ok: true, submitted: false, code: "cancelled_by_user", exitCode: 0 };
|
|
22129
|
+
}
|
|
22130
|
+
}
|
|
22131
|
+
}
|
|
22132
|
+
const cfg = deps.cfg ?? loadConfig();
|
|
22133
|
+
const { duplicated, retried } = await postFeedback(cfg, payload, deps.fetchFn);
|
|
22134
|
+
if (duplicated && !retried) {
|
|
22135
|
+
log.warn("这条内容刚刚已经报过了,本次未重复记录");
|
|
22136
|
+
}
|
|
22137
|
+
return { ok: true, submitted: true, duplicated, category: payload.category, exitCode: 0 };
|
|
22138
|
+
}
|
|
22139
|
+
function registerFeedback(program2) {
|
|
22140
|
+
program2.command("feedback <message>").description("把使用中的不顺手反馈给同合云(告知式提交:助手代提时必须先把内容念给你听、得到同意)").option("--command <name>", '这条反馈发生在哪个命令上,如 "matrix search"(必填,不要带参数)').option("--category <c>", `类别:${CATEGORIES.join(" / ")}(默认 other)`).option("--quote <text>", "你的原话(可选)").option("--task-id <id>", "关联的任务 ID(可选)").option("--context <k=v>", "附加信息,可重复", (v, acc) => [...acc, v], []).option("--disclosed", "声明「已把完整内容念给用户并获得同意」——助手代提时必须带").option("-y, --yes", "跳过终端里的确认等待(注意:它不能替代上面那条声明)").option("--json", "机读模式:人读日志转 stderr,stdout 只输出结果 JSON").action(async (message, opts) => {
|
|
22141
|
+
const result = await runFeedback(message, opts);
|
|
22142
|
+
if (opts.json) {
|
|
22143
|
+
const { exitCode: _exit, ...body } = result;
|
|
22144
|
+
process.stdout.write(`${JSON.stringify(body)}
|
|
22145
|
+
`);
|
|
22146
|
+
} else if (result.submitted) {
|
|
22147
|
+
log.ok("已记录并反馈给同合云");
|
|
22148
|
+
} else if (result.code === "cancelled_by_user") {
|
|
22149
|
+
log.info("已取消,未发送");
|
|
22150
|
+
}
|
|
22151
|
+
if (result.exitCode !== 0)
|
|
22152
|
+
process.exitCode = result.exitCode;
|
|
22153
|
+
});
|
|
22154
|
+
}
|
|
22155
|
+
|
|
21872
22156
|
// src/index.ts
|
|
21873
22157
|
try {
|
|
21874
22158
|
process.loadEnvFile?.();
|
|
@@ -21900,6 +22184,7 @@ registerDeps(program2);
|
|
|
21900
22184
|
registerProject(program2);
|
|
21901
22185
|
registerAudio(program2);
|
|
21902
22186
|
registerSubtitle(program2);
|
|
22187
|
+
registerFeedback(program2);
|
|
21903
22188
|
program2.parseAsync(process.argv).catch((e) => {
|
|
21904
22189
|
console.error(`
|
|
21905
22190
|
❌ ${e instanceof Error ? e.message : String(e)}`);
|
package/package.json
CHANGED
|
@@ -1,66 +1,66 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@gitruck/cli",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "同合云成片流水线 CLI —— agent 驱动云端任务、产物拉回本地、三方工程文件(客户端/剪映/PR)互通。",
|
|
5
|
-
"license": "MIT",
|
|
6
|
-
"author": "Gitruck (同合云)",
|
|
7
|
-
"repository": {
|
|
8
|
-
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/Gitruck/cli.git"
|
|
10
|
-
},
|
|
11
|
-
"homepage": "https://github.com/Gitruck/cli#readme",
|
|
12
|
-
"bugs": {
|
|
13
|
-
"url": "https://github.com/Gitruck/cli/issues"
|
|
14
|
-
},
|
|
15
|
-
"type": "module",
|
|
16
|
-
"bin": {
|
|
17
|
-
"gtrk": "dist/index.js"
|
|
18
|
-
},
|
|
19
|
-
"files": [
|
|
20
|
-
"dist",
|
|
21
|
-
"assets",
|
|
22
|
-
"skills",
|
|
23
|
-
"contracts",
|
|
24
|
-
"AGENT.md",
|
|
25
|
-
"README.md",
|
|
26
|
-
"README.en.md",
|
|
27
|
-
"LICENSE"
|
|
28
|
-
],
|
|
29
|
-
"engines": {
|
|
30
|
-
"node": ">=20.6"
|
|
31
|
-
},
|
|
32
|
-
"publishConfig": {
|
|
33
|
-
"access": "public",
|
|
34
|
-
"registry": "https://registry.npmjs.org/"
|
|
35
|
-
},
|
|
36
|
-
"keywords": [
|
|
37
|
-
"gitruck",
|
|
38
|
-
"同合云",
|
|
39
|
-
"video",
|
|
40
|
-
"oral-cut",
|
|
41
|
-
"口播剪辑",
|
|
42
|
-
"cli",
|
|
43
|
-
"jianying",
|
|
44
|
-
"剪映",
|
|
45
|
-
"agent"
|
|
46
|
-
],
|
|
47
|
-
"scripts": {
|
|
48
|
-
"gtrk": "bun run src/index.ts",
|
|
49
|
-
"build": "bun build ./src/index.ts --target=node --outfile dist/index.js",
|
|
50
|
-
"typecheck": "tsc --noEmit",
|
|
51
|
-
"prepublishOnly": "npm run typecheck && npm test && bun run build",
|
|
52
|
-
"test": "esbuild src/lib/compliance-notice.ts src/lib/first-run-tutorial.ts src/lib/desktop-client-hint.ts src/lib/chunk-upload.ts src/lib/upload-cache.ts src/lib/upload-submit.ts src/lib/render.ts src/lib/cloud.ts src/lib/materialize.ts src/lib/jianying.ts src/lib/clip-brief.ts src/lib/media.ts src/lib/projection.ts src/lib/reproject.ts src/lib/splitdoc.ts src/lib/gtrk-writeback.ts src/lib/column-config.ts src/lib/matrix.ts src/lib/matrix-material.ts src/lib/matrix-lay.ts src/lib/embed-client.ts src/lib/describe.ts src/lib/local-index.ts src/lib/local-search.ts src/lib/qc.ts src/lib/image-move.ts src/lib/cloud-render-guard.ts src/lib/material-integrity.ts src/lib/solid-png.ts src/lib/mg-lint.ts src/lib/mg-lay.ts src/lib/tool-descriptors.ts src/lib/tool-runner.ts src/lib/tool-pricing.ts src/lib/transcript.ts src/lib/runtime-assets.ts src/lib/subtitle-lay.ts --bundle --platform=node --format=esm --external:bun:sqlite --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/split.ts --bundle --platform=node --format=esm --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/matrix.ts --bundle --platform=node --format=esm --external:bun:sqlite --outfile=.test-build/matrix-cmd.mjs && esbuild src/commands/mg.ts --bundle --platform=node --format=esm --outfile=.test-build/mg-cmd.mjs && esbuild src/commands/tool.ts --bundle --platform=node --format=esm --outfile=.test-build/tool-cmd.mjs && esbuild src/commands/transcript.ts --bundle --platform=node --format=esm --outfile=.test-build/transcript-cmd.mjs && esbuild src/commands/project.ts --bundle --platform=node --format=esm --outfile=.test-build/project-cmd.mjs && esbuild src/commands/audio.ts --bundle --platform=node --format=esm --outfile=.test-build/audio-cmd.mjs && esbuild src/commands/subtitle.ts --bundle --platform=node --format=esm --outfile=.test-build/subtitle-cmd.mjs && esbuild src/commands/music-visualizer.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/music-visualizer-cmd.mjs && esbuild src/commands/long2short.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/long2short-cmd.mjs && esbuild src/commands/skills.ts --bundle --platform=node --format=esm --outfile=.test-build/skills-cmd.mjs && esbuild src/commands/qc.ts --bundle --platform=node --format=esm --external:commander --external:bun:sqlite --outfile=.test-build/qc-cmd.mjs && esbuild src/lib/convert/ir_to_jsx.ts src/lib/convert/ir_to_am.ts src/lib/convert/ir_to_nv.ts src/lib/convert/am_parse.ts src/lib/convert/nv_parse.ts src/lib/convert/parse.ts src/lib/convert/download.ts src/lib/convert/bake_ops.ts --bundle --platform=node --format=esm --outdir=.test-build/convert --out-extension:.js=.mjs && esbuild src/lib/mad/selector.ts src/lib/mad/beat.ts src/lib/mad/scan.ts src/lib/mad/data.ts src/lib/mad/pool.ts src/lib/mad/cloud-beat.ts src/lib/mad/mad.ts --bundle --platform=node --format=esm --outdir=.test-build/mad --out-extension:.js=.mjs && node --import ./test/helpers/test-home.mjs --test \"test/*.test.mjs\"",
|
|
53
|
-
"openspec:gate": "node openspec/gate.mjs"
|
|
54
|
-
},
|
|
55
|
-
"devDependencies": {
|
|
56
|
-
"@xmldom/xmldom": "^0.9.6",
|
|
57
|
-
"bun-types": "^1.1.0",
|
|
58
|
-
"commander": "^12.1.0",
|
|
59
|
-
"esbuild": "^0.28.1",
|
|
60
|
-
"typescript": "^5.6.0"
|
|
61
|
-
},
|
|
62
|
-
"dependencies": {
|
|
63
|
-
"hash-wasm": "^4.12.0",
|
|
64
|
-
"jszip": "^3.10.1"
|
|
65
|
-
}
|
|
66
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@gitruck/cli",
|
|
3
|
+
"version": "1.0.5",
|
|
4
|
+
"description": "同合云成片流水线 CLI —— agent 驱动云端任务、产物拉回本地、三方工程文件(客户端/剪映/PR)互通。",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Gitruck (同合云)",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Gitruck/cli.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/Gitruck/cli#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Gitruck/cli/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"bin": {
|
|
17
|
+
"gtrk": "dist/index.js"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"assets",
|
|
22
|
+
"skills",
|
|
23
|
+
"contracts",
|
|
24
|
+
"AGENT.md",
|
|
25
|
+
"README.md",
|
|
26
|
+
"README.en.md",
|
|
27
|
+
"LICENSE"
|
|
28
|
+
],
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=20.6"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public",
|
|
34
|
+
"registry": "https://registry.npmjs.org/"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"gitruck",
|
|
38
|
+
"同合云",
|
|
39
|
+
"video",
|
|
40
|
+
"oral-cut",
|
|
41
|
+
"口播剪辑",
|
|
42
|
+
"cli",
|
|
43
|
+
"jianying",
|
|
44
|
+
"剪映",
|
|
45
|
+
"agent"
|
|
46
|
+
],
|
|
47
|
+
"scripts": {
|
|
48
|
+
"gtrk": "bun run src/index.ts",
|
|
49
|
+
"build": "bun build ./src/index.ts --target=node --outfile dist/index.js",
|
|
50
|
+
"typecheck": "tsc --noEmit",
|
|
51
|
+
"prepublishOnly": "npm run typecheck && npm test && bun run build",
|
|
52
|
+
"test": "esbuild src/lib/compliance-notice.ts src/lib/first-run-tutorial.ts src/lib/desktop-client-hint.ts src/lib/chunk-upload.ts src/lib/upload-cache.ts src/lib/upload-submit.ts src/lib/render.ts src/lib/cloud.ts src/lib/materialize.ts src/lib/jianying.ts src/lib/clip-brief.ts src/lib/media.ts src/lib/projection.ts src/lib/reproject.ts src/lib/splitdoc.ts src/lib/gtrk-writeback.ts src/lib/column-config.ts src/lib/matrix.ts src/lib/matrix-material.ts src/lib/matrix-lay.ts src/lib/embed-client.ts src/lib/describe.ts src/lib/local-index.ts src/lib/local-search.ts src/lib/qc.ts src/lib/image-move.ts src/lib/cloud-render-guard.ts src/lib/material-integrity.ts src/lib/solid-png.ts src/lib/mg-lint.ts src/lib/mg-lay.ts src/lib/tool-descriptors.ts src/lib/tool-runner.ts src/lib/tool-pricing.ts src/lib/transcript.ts src/lib/runtime-assets.ts src/lib/subtitle-lay.ts --bundle --platform=node --format=esm --external:bun:sqlite --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/split.ts --bundle --platform=node --format=esm --outdir=.test-build --out-extension:.js=.mjs && esbuild src/commands/matrix.ts --bundle --platform=node --format=esm --external:bun:sqlite --outfile=.test-build/matrix-cmd.mjs && esbuild src/commands/mg.ts --bundle --platform=node --format=esm --outfile=.test-build/mg-cmd.mjs && esbuild src/commands/tool.ts --bundle --platform=node --format=esm --outfile=.test-build/tool-cmd.mjs && esbuild src/commands/transcript.ts --bundle --platform=node --format=esm --outfile=.test-build/transcript-cmd.mjs && esbuild src/commands/project.ts --bundle --platform=node --format=esm --outfile=.test-build/project-cmd.mjs && esbuild src/commands/audio.ts --bundle --platform=node --format=esm --outfile=.test-build/audio-cmd.mjs && esbuild src/commands/subtitle.ts --bundle --platform=node --format=esm --outfile=.test-build/subtitle-cmd.mjs && esbuild src/commands/feedback.ts --bundle --platform=node --format=esm --outfile=.test-build/feedback-cmd.mjs && esbuild src/commands/music-visualizer.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/music-visualizer-cmd.mjs && esbuild src/commands/long2short.ts --bundle --platform=node --format=esm --external:commander --outfile=.test-build/long2short-cmd.mjs && esbuild src/commands/skills.ts --bundle --platform=node --format=esm --outfile=.test-build/skills-cmd.mjs && esbuild src/commands/qc.ts --bundle --platform=node --format=esm --external:commander --external:bun:sqlite --outfile=.test-build/qc-cmd.mjs && esbuild src/lib/convert/ir_to_jsx.ts src/lib/convert/ir_to_am.ts src/lib/convert/ir_to_nv.ts src/lib/convert/am_parse.ts src/lib/convert/nv_parse.ts src/lib/convert/parse.ts src/lib/convert/download.ts src/lib/convert/bake_ops.ts --bundle --platform=node --format=esm --outdir=.test-build/convert --out-extension:.js=.mjs && esbuild src/lib/mad/selector.ts src/lib/mad/beat.ts src/lib/mad/scan.ts src/lib/mad/data.ts src/lib/mad/pool.ts src/lib/mad/cloud-beat.ts src/lib/mad/mad.ts --bundle --platform=node --format=esm --outdir=.test-build/mad --out-extension:.js=.mjs && node --import ./test/helpers/test-home.mjs --test \"test/*.test.mjs\"",
|
|
53
|
+
"openspec:gate": "node openspec/gate.mjs"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@xmldom/xmldom": "^0.9.6",
|
|
57
|
+
"bun-types": "^1.1.0",
|
|
58
|
+
"commander": "^12.1.0",
|
|
59
|
+
"esbuild": "^0.28.1",
|
|
60
|
+
"typescript": "^5.6.0"
|
|
61
|
+
},
|
|
62
|
+
"dependencies": {
|
|
63
|
+
"hash-wasm": "^4.12.0",
|
|
64
|
+
"jszip": "^3.10.1"
|
|
65
|
+
}
|
|
66
|
+
}
|