chainlesschain 0.162.65 → 0.162.66
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/package.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-DjJf_QIn.js → AIOps-BeJlvHR1.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BT45g-KL.js → ActionButton-B93fwcal.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-CRaTHble.js → Analytics-B-Lc0FRK.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-72r5TM1u.js → AppLayout-nv2C8TdH.js} +5 -5
- package/src/assets/web-panel/assets/{Audit-BNlvJ3Yc.js → Audit-B4pwb1Oe.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-Kuj0-vBg.js → Backup-B4HFWkJA.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-_pKOPRf4.js → BaseInput-BQk1ONWO.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CMNhGWK5.js → Chat-B2IobFfI.js} +5 -5
- package/src/assets/web-panel/assets/ChatBubbleRenderer-jJL-hGlG.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-B5R2TdAI.js → Checkbox-BHCU5kit.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-69RAQ0Gi.js → Codegen-Bqgq9-0q.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DlbssQEY.js → Col-BqDf398Z.js} +1 -1
- package/src/assets/web-panel/assets/{Community-DU3SAZIS.js → Community-Cd58ltip.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BqdNnAZv.js → Compact-CWa3CY1X.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-D9a9-ihS.js → Compliance-BNJWsGi0.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DWBtOBbU.js → Cowork-ChOCC2KD.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-ClSuf90k.js → Cron-BpWtgfDE.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BFjRKvpa.js → Crosschain-Csy7U94a.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BwBGRlMm.js → DID-CIh7lr9T.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-CHrXGmQ3.js → Dashboard-DYJUc9Jy.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-C24B5sk2.js → Dropdown-GnUptPAU.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DaXTSK5p.js → EmailListRenderer-sE9mvxjT.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-65d89G5t.js → FamilyGuardDashboard-Dg7-GHSu.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CkWdqmVs.js → Federation-BiH_O7jy.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BV4W2nrT.js → FormItemContext-C1AZ_qE-.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-D60KJ0_b.js → GenericCardRenderer-WpsC5meD.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BIKuoGvW.js → Git-L4XGb5Qj.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CKnJpq5X.js → Governance-CJ9Gn_A9.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-C7G3YGeg.js → Inference-Dlc9Ey87.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-D7fCUd4B.js → KnowledgeGraph-CfndHiBW.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-C0unjcbC.js → Logs-CSOLZERs.js} +2 -2
- package/src/assets/web-panel/assets/{Marketplace-BzLlnyI8.js → Marketplace-Cjiz9wPY.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DSKFRB1-.js → McpTools-C8UNhnTj.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-C_QrLAnt.js → Memory-BhOoGXRL.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DBeaFERD.js → MobileBridge-rKKcGEvg.js} +2 -2
- package/src/assets/web-panel/assets/{MobileProjects-C2L_RttC.js → MobileProjects-KvGFVl79.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-B3Tdh6-l.js → Mtc-jyA3mXYt.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-B3O_EUvt.js → MtcAudit-BYi6sulR.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig--60rVmDj.js → Multisig-CWZGD6_3.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-D60vxATf.js → NLProgramming-bOIPDOh5.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-D2gj2uFI.js → Notes-_I6Hs_bJ.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-D0DWHNlF.js → NotificationSettings-Bj9Bcy2A.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-CNi1B7fH.js → OrderTableRenderer-C5zZeOhJ.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BRcdFgAd.js → Organization-B-SfOynT.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-C3_Oap7v.js → Overflow-CG7JBYts.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DEbZ93QW.js → P2P-vpebJYvr.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-CPeKixo2.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-CPj3C9o2.js → Permissions-CpflO2Ac.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BZGupZzh.js → PersonalDataHub-D6CjgWDH.js} +2 -2
- package/src/assets/web-panel/assets/{Pipeline-SMLW1BG7.js → Pipeline-CgC59gHt.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-o24SJ2no.js → Privacy-CoZn6LrI.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-DxjAXD8f.js → ProjectInit-BmNYdFPv.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-DipynlqL.js → ProjectSettings-C13HHOUG.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-CZ9egQ8r.js → Projects-BSHYaYKU.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-x3p-wcab.js → Providers-Dh6ys5NR.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CZ7beKFC.js → QuickAsk-Cljz9ZIS.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-VJCd2i9_.js → Recommend-CEAVAYGZ.js} +1 -1
- package/src/assets/web-panel/assets/{Reputation-pl12NmBF.js → Reputation-C7AxH6cu.js} +1 -1
- package/src/assets/web-panel/assets/{Row-NkSeo4Tb.js → Row-D5Jgzbof.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-B17vp67R.js → RssFeed-V6vBnNBE.js} +2 -2
- package/src/assets/web-panel/assets/{Search-Dij0_m6W.js → Search-dfDC6aHa.js} +1 -1
- package/src/assets/web-panel/assets/{Security-n9CSBX-9.js → Security-BOSRXul6.js} +3 -3
- package/src/assets/web-panel/assets/{Services-bZOzqHdK.js → Services-dsNT3Tra.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-B23D5vJ-.js → Skeleton-_rXFZqCe.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-IXh-0mk0.js → Skills-WWvbl-N6.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-QEofxmdK.js → Sla-BZT_pwjV.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-u68R59ft.js → SpeechSettings-BSVqkQ0F.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-B3tc986U.js → SyncSettings-TLHuQW_s.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-Cp2QxGrr.js → Tasks-8-jiv3Dt.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CMWiWxiH.js → Templates-D7qs_H3G.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-M8aPJ3C7.js → Tenant-B4hRLxlc.js} +1 -1
- package/src/assets/web-panel/assets/Terminal-lrlEETgH.js +3 -0
- package/src/assets/web-panel/assets/{TimelineRenderer-DF6aIS-d.js → TimelineRenderer-Do8UQaNj.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BcfMMw_e.js → Tokens-wyuwl9gS.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-jIbNmxvm.js → Trigger-Ck4j8Emr.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-ChLil6CZ.js → Trust-Z07lGZvX.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-B1WzYAon.js → UkeySign-5rI48ojV.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Dwm0LyCc.js → VideoEditing-Dm8PV-Ss.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DVyxsX-O.js → Wallet-BwWYuV0j.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-WYPNy2Q7.js → WebAuthn-CavU3f2i.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-Br3dCsmv.js → WorkflowEditor-jj1aB37x.js} +1 -1
- package/src/assets/web-panel/assets/{chat-fAKHY2HK.js → chat-BpRqPqbA.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BXqS-Bwi.js → colors-BBJU99fO.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BgCQhtW3.js → compact-item-t2Elz5Kg.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-weZBwqHy.js → createContext-B_D6Nida.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CmJstpP_.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-Dx68UNFL.js → hasIn-D5k1KNpe.js} +1 -1
- package/src/assets/web-panel/assets/{index-BjsidvP5.js → index-1lcpLp-e.js} +1 -1
- package/src/assets/web-panel/assets/{index-DXuz90bX.js → index-2KvtrQkP.js} +1 -1
- package/src/assets/web-panel/assets/{index-Co5cQnlv.js → index-33FQbw3H.js} +1 -1
- package/src/assets/web-panel/assets/{index-CfqzwaAV.js → index-3TymUGUQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DNF3aCJF.js → index-6iwQSswx.js} +1 -1
- package/src/assets/web-panel/assets/{index-LxcdLeFj.js → index-B2cxsdFe.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8zNZ_oH.js → index-BCpJT0on.js} +1 -1
- package/src/assets/web-panel/assets/{index-DgUC575c.js → index-BH_HjIO6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BqcH_mKR.js → index-BVEb-kUY.js} +1 -1
- package/src/assets/web-panel/assets/{index-ohVNy7ua.js → index-BaS1rfcr.js} +1 -1
- package/src/assets/web-panel/assets/{index-ChdeuOni.js → index-BfKFGtsC.js} +1 -1
- package/src/assets/web-panel/assets/{index-BSQEQCft.js → index-Bo72gKe8.js} +1 -1
- package/src/assets/web-panel/assets/{index-HIN85jl7.js → index-C-271Q6Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-5e-OAZOb.js → index-C3alXfss.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bwv_UrNF.js → index-CB1AFQiL.js} +1 -1
- package/src/assets/web-panel/assets/{index-BawcE_zG.js → index-CHyyhgQ3.js} +1 -1
- package/src/assets/web-panel/assets/{index-qUBHSW_3.js → index-CP2Nz1mx.js} +3 -3
- package/src/assets/web-panel/assets/{index-Cxsfc5Ou.js → index-CT_-tscA.js} +1 -1
- package/src/assets/web-panel/assets/{index-ClfP1Yax.js → index-CWwjhqgi.js} +1 -1
- package/src/assets/web-panel/assets/{index-DG2KCc8h.js → index-CYdBeNTv.js} +1 -1
- package/src/assets/web-panel/assets/{index-BC-4la9j.js → index-CgCeon6Z.js} +1 -1
- package/src/assets/web-panel/assets/{index-CEjLe8FJ.js → index-Ctt8xM0M.js} +1 -1
- package/src/assets/web-panel/assets/{index-G_wPnPoA.js → index-CwAKqpJd.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9NeNwHP.js → index-CwEJnamf.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dbv5btEU.js → index-D8LnFSKZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-loaP_41H.js → index-DGtbeySv.js} +1 -1
- package/src/assets/web-panel/assets/{index-CJXZDwkf.js → index-DHHTczBZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bo4UTTla.js → index-DIgtJB5J.js} +1 -1
- package/src/assets/web-panel/assets/{index-CX9cxRnU.js → index-DLfAmDGs.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0rgvjX8.js → index-DRh9m8hf.js} +1 -1
- package/src/assets/web-panel/assets/index-Dric_1LC.js +1 -0
- package/src/assets/web-panel/assets/{index-u2U9t07r.js → index-DzIq7BlR.js} +1 -1
- package/src/assets/web-panel/assets/{index-B8-2rQdr.js → index-E4x-hzLB.js} +1 -1
- package/src/assets/web-panel/assets/{index-BehvfmYd.js → index-GSUbdu-w.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bazltj8w.js → index-GSpv5udU.js} +1 -1
- package/src/assets/web-panel/assets/{index-CxfVwfub.js → index-NMj4bTp1.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCYJDUab.js → index-OmJk1MzD.js} +1 -1
- package/src/assets/web-panel/assets/index-eFol7ymc.js +1 -0
- package/src/assets/web-panel/assets/{index-C0ZjD3Ac.js → index-eVBDpynR.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-M7xH4eUK.js → initDefaultProps-CuryY55W.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BrJP4mFE.js → motion-IVsWxV-s.js} +1 -1
- package/src/assets/web-panel/assets/{move-BufxEuU9.js → move-DNKsQLrH.js} +1 -1
- package/src/assets/web-panel/assets/{omit-s6dtQtFP.js → omit-gXu4NluL.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BcYdIZqz.js → pickAttrs-CVb4Ykex.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Ds-3Hw3n.js → placementArrow-BarpAJK0.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BRtrRTxl.js → responsiveObserve-eaDhQlY1.js} +1 -1
- package/src/assets/web-panel/assets/{slide-RJzqMQM4.js → slide-C8oU8Wlo.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-BuBhJXvr.js → statusUtils-DrBdj2xb.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-so8acGHq.js → styleChecker-_Rycq1-Q.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-BpkV467K.js → useFlexGapSupport-BagU5XLY.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-lES1RctZ.js → useFs-DZYMOaAQ.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DdCNi4bA.js → usePersonalDataHub-CDMZ5QvU.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-nAeEg_3h.js → vnode-Bg7MuEf5.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-BWjRAfRy.js → zoom-oJIwomWy.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/insights.js +137 -0
- package/src/commands/review.js +392 -48
- package/src/index.js +2 -0
- package/src/lib/personal-data-hub-wiring.js +20 -0
- package/src/lib/session-insights.js +145 -0
- package/src/lib/skill-loader.js +18 -3
- package/src/repl/agent-repl.js +1 -3
- package/src/skills-bundled/run/SKILL.md +49 -0
- package/src/skills-bundled/verify/SKILL.md +49 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-DxJmwLv8.js +0 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-DN_pmo2N.js +0 -7
- package/src/assets/web-panel/assets/Terminal-CK3zKjIE.js +0 -3
- package/src/assets/web-panel/assets/devWarning-BpXdFCJ4.js +0 -1
- package/src/assets/web-panel/assets/index-BrPKR2RZ.js +0 -1
- package/src/assets/web-panel/assets/index-CMEfvACO.js +0 -1
package/src/commands/review.js
CHANGED
|
@@ -63,7 +63,9 @@ function gitCli(args, { cwd } = {}) {
|
|
|
63
63
|
|
|
64
64
|
function isGitRepo(cwd, git = gitCli) {
|
|
65
65
|
try {
|
|
66
|
-
return
|
|
66
|
+
return (
|
|
67
|
+
git(["rev-parse", "--is-inside-work-tree"], { cwd }).trim() === "true"
|
|
68
|
+
);
|
|
67
69
|
} catch {
|
|
68
70
|
return false;
|
|
69
71
|
}
|
|
@@ -174,26 +176,43 @@ export function buildReviewPrompt(o = {}) {
|
|
|
174
176
|
effort = "medium",
|
|
175
177
|
mode = "default",
|
|
176
178
|
fix = false,
|
|
179
|
+
comment = false,
|
|
177
180
|
label = "working tree vs HEAD",
|
|
178
181
|
untrackedBlocks = "",
|
|
179
182
|
truncated = false,
|
|
180
183
|
} = o;
|
|
181
184
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
: "
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
185
|
+
// comment mode → machine-readable findings so each maps to a PR inline comment.
|
|
186
|
+
const commentTail =
|
|
187
|
+
"Output ONLY a JSON array of findings and nothing else — no prose, no " +
|
|
188
|
+
"markdown fence. Each element: " +
|
|
189
|
+
'{"path": "<repo-relative file path exactly as in the diff>", ' +
|
|
190
|
+
'"line": <integer line number in the NEW version of the file, which MUST ' +
|
|
191
|
+
"appear in the diff>, " +
|
|
192
|
+
'"severity": "Critical"|"High"|"Medium"|"Low", ' +
|
|
193
|
+
'"title": "<one-line summary>", ' +
|
|
194
|
+
'"body": "<why it matters + a concrete suggested fix>"}. ' +
|
|
195
|
+
"Only report lines that are present in the diff (added/context lines on the " +
|
|
196
|
+
"new side). Do NOT modify any files. If there is nothing worth raising, " +
|
|
197
|
+
"output exactly [].";
|
|
198
|
+
|
|
199
|
+
const tail = comment
|
|
200
|
+
? commentTail
|
|
201
|
+
: fix
|
|
202
|
+
? "First identify the issues as above. Then APPLY the fixes directly with " +
|
|
203
|
+
"your edit tools — make the smallest change that resolves each issue and " +
|
|
204
|
+
"match the surrounding code's style. Every file edit is automatically " +
|
|
205
|
+
"checkpointed and reversible, so edit confidently. Stay within the " +
|
|
206
|
+
"reviewed change and its immediate dependencies — do not refactor " +
|
|
207
|
+
"unrelated code. Do NOT run destructive shell commands. When done, output " +
|
|
208
|
+
"a Markdown summary: what you changed (with `path:line`) and any issue you " +
|
|
209
|
+
"deliberately did NOT fix, each with a one-line reason."
|
|
210
|
+
: "Output a Markdown report. For each finding give: a severity " +
|
|
211
|
+
"(Critical / High / Medium / Low), the `path:line`, a one-line title, " +
|
|
212
|
+
"why it matters, and a concrete suggested fix (a short code snippet when " +
|
|
213
|
+
"it helps). Group findings by severity, most severe first. If nothing is " +
|
|
214
|
+
"worth raising, say so plainly. Do NOT modify any files — this is a " +
|
|
215
|
+
"review only.";
|
|
197
216
|
|
|
198
217
|
return [
|
|
199
218
|
`You are an expert code reviewer. ${LENS[mode]}`,
|
|
@@ -208,7 +227,8 @@ export function buildReviewPrompt(o = {}) {
|
|
|
208
227
|
"Unified diff:",
|
|
209
228
|
"```diff",
|
|
210
229
|
truncated
|
|
211
|
-
? diff +
|
|
230
|
+
? diff +
|
|
231
|
+
"\n\n[... diff truncated — review what is shown; note the cutoff]"
|
|
212
232
|
: diff,
|
|
213
233
|
"```",
|
|
214
234
|
untrackedBlocks ? "\n" + untrackedBlocks : "",
|
|
@@ -271,6 +291,273 @@ function collectUntracked(cwd, git) {
|
|
|
271
291
|
};
|
|
272
292
|
}
|
|
273
293
|
|
|
294
|
+
/**
|
|
295
|
+
* Collect the diff (+ untracked new files) for a review scope. Shared by
|
|
296
|
+
* runReview and runReviewComment. Returns the (possibly truncated) diff.
|
|
297
|
+
*/
|
|
298
|
+
function collectReviewDiff(scopeOpts, { cwd, git, includeUntracked }) {
|
|
299
|
+
const { args: diffArgs, scope, label } = resolveDiffArgs(scopeOpts, false);
|
|
300
|
+
const { args: statArgs } = resolveDiffArgs(scopeOpts, true);
|
|
301
|
+
let diff = "";
|
|
302
|
+
let summary = "";
|
|
303
|
+
try {
|
|
304
|
+
diff = git(diffArgs, { cwd });
|
|
305
|
+
summary = git(statArgs, { cwd });
|
|
306
|
+
} catch (err) {
|
|
307
|
+
throw new Error(`git diff failed: ${err.message}`);
|
|
308
|
+
}
|
|
309
|
+
// Untracked new files only matter for the default working scope; staged /
|
|
310
|
+
// base / range are already fully described by git.
|
|
311
|
+
let untracked = { blocks: "", files: [], skipped: [] };
|
|
312
|
+
if (scope === "working" && includeUntracked) {
|
|
313
|
+
untracked = collectUntracked(cwd, git);
|
|
314
|
+
}
|
|
315
|
+
const hasDiff = Boolean(diff.trim());
|
|
316
|
+
const hasUntracked = Boolean(untracked.blocks);
|
|
317
|
+
const truncated = diff.length > MAX_DIFF_CHARS;
|
|
318
|
+
if (truncated) diff = diff.slice(0, MAX_DIFF_CHARS);
|
|
319
|
+
return {
|
|
320
|
+
diff,
|
|
321
|
+
summary,
|
|
322
|
+
scope,
|
|
323
|
+
label,
|
|
324
|
+
untracked,
|
|
325
|
+
hasDiff,
|
|
326
|
+
hasUntracked,
|
|
327
|
+
truncated,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/** Run `gh` with an argv array (no shell). UTF-8 in/out; throws on failure. */
|
|
332
|
+
function ghCli(args, { cwd, input } = {}) {
|
|
333
|
+
const res = spawnSync("gh", args, {
|
|
334
|
+
cwd,
|
|
335
|
+
input,
|
|
336
|
+
encoding: "utf-8",
|
|
337
|
+
windowsHide: true,
|
|
338
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
339
|
+
});
|
|
340
|
+
if (res.error) throw res.error;
|
|
341
|
+
if (res.status !== 0) {
|
|
342
|
+
const msg = (res.stderr || res.stdout || "").toString().trim();
|
|
343
|
+
throw new Error(msg || `gh ${args.join(" ")} failed (exit ${res.status})`);
|
|
344
|
+
}
|
|
345
|
+
return (res.stdout || "").toString();
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/** Resolve the PR for the current branch via gh (read-only). Throws if none. */
|
|
349
|
+
function resolvePr(cwd, gh) {
|
|
350
|
+
let out;
|
|
351
|
+
try {
|
|
352
|
+
out = gh(
|
|
353
|
+
["pr", "view", "--json", "number,baseRefName,headRefName,headRefOid,url"],
|
|
354
|
+
{ cwd },
|
|
355
|
+
);
|
|
356
|
+
} catch (err) {
|
|
357
|
+
throw new Error(
|
|
358
|
+
`no open PR for the current branch (gh: ${err.message}). ` +
|
|
359
|
+
"Push the branch and open a PR first, or use `cc review` without --comment.",
|
|
360
|
+
);
|
|
361
|
+
}
|
|
362
|
+
let pr;
|
|
363
|
+
try {
|
|
364
|
+
pr = JSON.parse(out);
|
|
365
|
+
} catch {
|
|
366
|
+
throw new Error("could not parse `gh pr view` output.");
|
|
367
|
+
}
|
|
368
|
+
let repo = null;
|
|
369
|
+
try {
|
|
370
|
+
repo = JSON.parse(gh(["repo", "view", "--json", "nameWithOwner"], { cwd }))
|
|
371
|
+
.nameWithOwner;
|
|
372
|
+
} catch {
|
|
373
|
+
repo = null;
|
|
374
|
+
}
|
|
375
|
+
return { ...pr, repo };
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Parse the agent's findings JSON (lenient). Strips a code fence, extracts the
|
|
380
|
+
* first JSON array, and keeps only well-formed findings. Pure.
|
|
381
|
+
*
|
|
382
|
+
* @returns {{path:string,line:number,severity:string,title:string,body:string}[]}
|
|
383
|
+
*/
|
|
384
|
+
export function parseFindings(text) {
|
|
385
|
+
if (!text) return [];
|
|
386
|
+
let s = String(text).trim();
|
|
387
|
+
const fence = s.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
388
|
+
if (fence) s = fence[1].trim();
|
|
389
|
+
const start = s.indexOf("[");
|
|
390
|
+
const end = s.lastIndexOf("]");
|
|
391
|
+
if (start === -1 || end === -1 || end < start) return [];
|
|
392
|
+
let arr;
|
|
393
|
+
try {
|
|
394
|
+
arr = JSON.parse(s.slice(start, end + 1));
|
|
395
|
+
} catch {
|
|
396
|
+
return [];
|
|
397
|
+
}
|
|
398
|
+
if (!Array.isArray(arr)) return [];
|
|
399
|
+
return arr
|
|
400
|
+
.filter(
|
|
401
|
+
(f) =>
|
|
402
|
+
f &&
|
|
403
|
+
typeof f === "object" &&
|
|
404
|
+
f.path &&
|
|
405
|
+
Number.isFinite(Number(f.line)) &&
|
|
406
|
+
Number(f.line) > 0,
|
|
407
|
+
)
|
|
408
|
+
.map((f) => ({
|
|
409
|
+
path: String(f.path),
|
|
410
|
+
line: Math.floor(Number(f.line)),
|
|
411
|
+
severity: f.severity ? String(f.severity) : "Note",
|
|
412
|
+
title: f.title ? String(f.title) : "",
|
|
413
|
+
body: f.body ? String(f.body) : f.title ? String(f.title) : "finding",
|
|
414
|
+
}));
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/** Format one finding into a PR comment body. Pure. */
|
|
418
|
+
export function buildCommentBody(f) {
|
|
419
|
+
const sev = f.severity ? `**[${f.severity}]** ` : "";
|
|
420
|
+
const title = f.title ? `${f.title}\n\n` : "";
|
|
421
|
+
return `${sev}${title}${f.body}`.trim();
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/** Build the GitHub "create review" API payload from findings. Pure. */
|
|
425
|
+
export function buildReviewPayload(findings, { commitId } = {}) {
|
|
426
|
+
const comments = (findings || []).map((f) => ({
|
|
427
|
+
path: f.path,
|
|
428
|
+
line: f.line,
|
|
429
|
+
side: "RIGHT",
|
|
430
|
+
body: buildCommentBody(f),
|
|
431
|
+
}));
|
|
432
|
+
const payload = {
|
|
433
|
+
event: "COMMENT",
|
|
434
|
+
body: `cc review — ${comments.length} finding(s).`,
|
|
435
|
+
comments,
|
|
436
|
+
};
|
|
437
|
+
if (commitId) payload.commit_id = commitId;
|
|
438
|
+
return payload;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Post the findings to the PR as a single review with inline comments
|
|
443
|
+
* (outward-facing — callers gate this behind --dry-run / confirmation).
|
|
444
|
+
*/
|
|
445
|
+
export function postReviewComments(pr, findings, { gh = ghCli, cwd, commitId } = {}) {
|
|
446
|
+
if (!pr || !pr.repo || !pr.number) {
|
|
447
|
+
throw new Error("cannot post: PR repo/number not resolved.");
|
|
448
|
+
}
|
|
449
|
+
const payload = buildReviewPayload(findings, { commitId });
|
|
450
|
+
const out = gh(
|
|
451
|
+
[
|
|
452
|
+
"api",
|
|
453
|
+
"--method",
|
|
454
|
+
"POST",
|
|
455
|
+
`repos/${pr.repo}/pulls/${pr.number}/reviews`,
|
|
456
|
+
"--input",
|
|
457
|
+
"-",
|
|
458
|
+
],
|
|
459
|
+
{ cwd, input: JSON.stringify(payload) },
|
|
460
|
+
);
|
|
461
|
+
try {
|
|
462
|
+
return JSON.parse(out);
|
|
463
|
+
} catch {
|
|
464
|
+
return { raw: out };
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Comment-mode review: resolve the PR, collect its diff, get machine-readable
|
|
470
|
+
* findings from one read-only agent turn. Side-effect-free (PR resolution is a
|
|
471
|
+
* read); the caller posts after confirmation. Deps injected for tests.
|
|
472
|
+
*
|
|
473
|
+
* @returns {Promise<{empty:boolean, pr:object, findings:object[], scope?:string,
|
|
474
|
+
* label?:string, isError?:boolean}>}
|
|
475
|
+
*/
|
|
476
|
+
export async function runReviewComment(options = {}, deps = {}) {
|
|
477
|
+
const cwd = options.cwd || process.cwd();
|
|
478
|
+
const git = deps.git || gitCli;
|
|
479
|
+
const gh = deps.gh || ghCli;
|
|
480
|
+
const repoCheck = deps.isGitRepo || isGitRepo;
|
|
481
|
+
if (!repoCheck(cwd, git)) {
|
|
482
|
+
throw new Error("cc review needs a git work tree.");
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const pr = (deps.resolvePr || resolvePr)(cwd, gh);
|
|
486
|
+
|
|
487
|
+
// Default the scope to the PR's base branch (review the PR's changes) unless
|
|
488
|
+
// the user gave an explicit scope.
|
|
489
|
+
const explicitScope =
|
|
490
|
+
options.staged || options.base || options.range || (options.paths || []).length;
|
|
491
|
+
const scopeOpts = {
|
|
492
|
+
staged: options.staged === true,
|
|
493
|
+
base: options.base || (explicitScope ? null : pr.baseRefName),
|
|
494
|
+
range: options.range || null,
|
|
495
|
+
paths: options.paths || [],
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
const collected = collectReviewDiff(scopeOpts, {
|
|
499
|
+
cwd,
|
|
500
|
+
git,
|
|
501
|
+
includeUntracked: false,
|
|
502
|
+
});
|
|
503
|
+
if (!collected.hasDiff && !collected.hasUntracked) {
|
|
504
|
+
return { empty: true, pr, findings: [] };
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// LLM config defaults (parity with runReview).
|
|
508
|
+
try {
|
|
509
|
+
const loadConfig =
|
|
510
|
+
deps.loadConfig || (await import("../lib/config-manager.js")).loadConfig;
|
|
511
|
+
const { applyConfigLlmDefaults } = deps.applyConfigLlmDefaults
|
|
512
|
+
? { applyConfigLlmDefaults: deps.applyConfigLlmDefaults }
|
|
513
|
+
: await import("../lib/llm-config-defaults.js");
|
|
514
|
+
applyConfigLlmDefaults(options, loadConfig().llm || {}, {
|
|
515
|
+
explicitModel: options.model,
|
|
516
|
+
});
|
|
517
|
+
} catch {
|
|
518
|
+
/* fall back to runner defaults */
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const prompt = buildReviewPrompt({
|
|
522
|
+
diff: collected.hasDiff ? collected.diff : "(no tracked changes)",
|
|
523
|
+
summary: collected.summary,
|
|
524
|
+
effort: normalizeEffort(options.effort),
|
|
525
|
+
mode: resolveReviewMode(options),
|
|
526
|
+
comment: true,
|
|
527
|
+
label: collected.label,
|
|
528
|
+
truncated: collected.truncated,
|
|
529
|
+
});
|
|
530
|
+
|
|
531
|
+
const run =
|
|
532
|
+
deps.runAgentHeadless ||
|
|
533
|
+
(await import("../runtime/headless-runner.js")).runAgentHeadless;
|
|
534
|
+
// Suppress the runner's own stdout/stderr — we only want the structured result.
|
|
535
|
+
const outcome = await run(
|
|
536
|
+
{
|
|
537
|
+
prompt,
|
|
538
|
+
model: options.model,
|
|
539
|
+
provider: options.provider,
|
|
540
|
+
baseUrl: options.baseUrl,
|
|
541
|
+
apiKey: options.apiKey,
|
|
542
|
+
outputFormat: "text",
|
|
543
|
+
permissionMode: "plan",
|
|
544
|
+
maxTurns: Number.isFinite(options.maxTurns) ? options.maxTurns : 20,
|
|
545
|
+
cwd,
|
|
546
|
+
expandFileRefs: false,
|
|
547
|
+
},
|
|
548
|
+
{ writeOut: () => {}, writeErr: () => {} },
|
|
549
|
+
);
|
|
550
|
+
|
|
551
|
+
return {
|
|
552
|
+
empty: false,
|
|
553
|
+
pr,
|
|
554
|
+
scope: collected.scope,
|
|
555
|
+
label: collected.label,
|
|
556
|
+
findings: parseFindings(outcome.result || ""),
|
|
557
|
+
isError: outcome.isError === true,
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
|
|
274
561
|
/**
|
|
275
562
|
* Core review run — collects the diff and dispatches one headless agent turn.
|
|
276
563
|
* Deps are injected for tests (git / runAgentHeadless / config helpers).
|
|
@@ -299,34 +586,16 @@ export async function runReview(options = {}, deps = {}) {
|
|
|
299
586
|
paths: options.paths || [],
|
|
300
587
|
};
|
|
301
588
|
|
|
302
|
-
const {
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
diff = git(diffArgs, { cwd });
|
|
309
|
-
summary = git(statArgs, { cwd });
|
|
310
|
-
} catch (err) {
|
|
311
|
-
throw new Error(`git diff failed: ${err.message}`);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
// Untracked new files only matter for the default working scope; staged /
|
|
315
|
-
// base / range are already fully described by git.
|
|
316
|
-
let untracked = { blocks: "", files: [], skipped: [] };
|
|
317
|
-
if (scope === "working" && options.untracked !== false) {
|
|
318
|
-
untracked = collectUntracked(cwd, git);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
const hasDiff = Boolean(diff.trim());
|
|
322
|
-
const hasUntracked = Boolean(untracked.blocks);
|
|
589
|
+
const { diff, summary, scope, label, untracked, hasDiff, hasUntracked, truncated } =
|
|
590
|
+
collectReviewDiff(scopeOpts, {
|
|
591
|
+
cwd,
|
|
592
|
+
git,
|
|
593
|
+
includeUntracked: options.untracked !== false,
|
|
594
|
+
});
|
|
323
595
|
if (!hasDiff && !hasUntracked) {
|
|
324
596
|
return { exitCode: 0, isError: false, scope, empty: true };
|
|
325
597
|
}
|
|
326
598
|
|
|
327
|
-
const truncated = diff.length > MAX_DIFF_CHARS;
|
|
328
|
-
if (truncated) diff = diff.slice(0, MAX_DIFF_CHARS);
|
|
329
|
-
|
|
330
599
|
const prompt = buildReviewPrompt({
|
|
331
600
|
diff: hasDiff ? diff : "(no tracked changes)",
|
|
332
601
|
summary,
|
|
@@ -341,11 +610,11 @@ export async function runReview(options = {}, deps = {}) {
|
|
|
341
610
|
// LLM defaults: honor .chainlesschain/config.json `llm` like cc agent/ask.
|
|
342
611
|
// Explicit flags win. Best-effort — never block the review.
|
|
343
612
|
try {
|
|
344
|
-
const loadConfig =
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
613
|
+
const loadConfig =
|
|
614
|
+
deps.loadConfig || (await import("../lib/config-manager.js")).loadConfig;
|
|
615
|
+
const { applyConfigLlmDefaults } = deps.applyConfigLlmDefaults
|
|
616
|
+
? { applyConfigLlmDefaults: deps.applyConfigLlmDefaults }
|
|
617
|
+
: await import("../lib/llm-config-defaults.js");
|
|
349
618
|
applyConfigLlmDefaults(options, loadConfig().llm || {}, {
|
|
350
619
|
explicitModel: options.model,
|
|
351
620
|
});
|
|
@@ -362,7 +631,8 @@ export async function runReview(options = {}, deps = {}) {
|
|
|
362
631
|
? options.maxTurns
|
|
363
632
|
: defaultMaxTurns;
|
|
364
633
|
|
|
365
|
-
const run =
|
|
634
|
+
const run =
|
|
635
|
+
deps.runAgentHeadless ||
|
|
366
636
|
(await import("../runtime/headless-runner.js")).runAgentHeadless;
|
|
367
637
|
|
|
368
638
|
const outcome = await run({
|
|
@@ -403,12 +673,23 @@ export function registerReviewCommand(program) {
|
|
|
403
673
|
.option("--security", "Security-focused review (/security-review parity)")
|
|
404
674
|
.option("--simplify", "Cleanup-only review, no bug hunt (/simplify parity)")
|
|
405
675
|
.option("--no-untracked", "Skip untracked new files (working scope)")
|
|
406
|
-
.option(
|
|
676
|
+
.option(
|
|
677
|
+
"--no-checkpoint",
|
|
678
|
+
"With --fix: do not auto-checkpoint before edits",
|
|
679
|
+
)
|
|
407
680
|
.option("--model <model>", "Override the review model")
|
|
408
681
|
.option("--provider <provider>", "Override the LLM provider")
|
|
409
682
|
.option("--base-url <url>", "Override the API base URL")
|
|
410
683
|
.option("--api-key <key>", "Override the API key")
|
|
411
684
|
.option("--max-turns <n>", "Cap agent loop iterations")
|
|
685
|
+
.option(
|
|
686
|
+
"--comment",
|
|
687
|
+
"Post findings as inline comments on the current branch's PR (via gh); defaults the scope to the PR base",
|
|
688
|
+
)
|
|
689
|
+
.option(
|
|
690
|
+
"--dry-run",
|
|
691
|
+
"With --comment: show what would be posted without posting",
|
|
692
|
+
)
|
|
412
693
|
.option("--json", "Emit the agent result envelope as JSON")
|
|
413
694
|
.action(async (effortArg, options) => {
|
|
414
695
|
try {
|
|
@@ -439,6 +720,69 @@ export function registerReviewCommand(program) {
|
|
|
439
720
|
: mode === "simplify"
|
|
440
721
|
? "cleanup-only"
|
|
441
722
|
: "bugs + cleanup";
|
|
723
|
+
|
|
724
|
+
// ── --comment: review the PR's diff and post inline comments ────────
|
|
725
|
+
if (merged.comment) {
|
|
726
|
+
logger.info(
|
|
727
|
+
chalk.gray(
|
|
728
|
+
`Reviewing PR diff · ${effort} effort · ${modeLabel} · ` +
|
|
729
|
+
(merged.dryRun ? "dry-run" : "will post comments"),
|
|
730
|
+
),
|
|
731
|
+
);
|
|
732
|
+
const res = await runReviewComment(merged, {});
|
|
733
|
+
if (res.empty) {
|
|
734
|
+
logger.log(chalk.gray("No changes to review on this PR."));
|
|
735
|
+
return;
|
|
736
|
+
}
|
|
737
|
+
logger.log(
|
|
738
|
+
chalk.bold(
|
|
739
|
+
`${res.findings.length} finding(s) for PR #${res.pr.number}`,
|
|
740
|
+
) + chalk.gray(` ${res.pr.url || ""}`),
|
|
741
|
+
);
|
|
742
|
+
for (const f of res.findings) {
|
|
743
|
+
logger.log(
|
|
744
|
+
` ${chalk.yellow(`[${f.severity}]`)} ${chalk.cyan(`${f.path}:${f.line}`)} ${f.title}`,
|
|
745
|
+
);
|
|
746
|
+
}
|
|
747
|
+
if (res.findings.length === 0) {
|
|
748
|
+
logger.log(chalk.gray("Nothing to post."));
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
if (merged.dryRun) {
|
|
752
|
+
logger.log(
|
|
753
|
+
chalk.gray("(--dry-run: not posting; re-run without --dry-run)"),
|
|
754
|
+
);
|
|
755
|
+
return;
|
|
756
|
+
}
|
|
757
|
+
// Outward-facing: confirm before posting when interactive.
|
|
758
|
+
if (process.stdin.isTTY) {
|
|
759
|
+
const { confirm } = await import("@inquirer/prompts");
|
|
760
|
+
const ok = await confirm({
|
|
761
|
+
message: `Post ${res.findings.length} comment(s) to PR #${res.pr.number}?`,
|
|
762
|
+
default: false,
|
|
763
|
+
}).catch(() => false);
|
|
764
|
+
if (!ok) {
|
|
765
|
+
logger.log(chalk.gray("Aborted — nothing posted."));
|
|
766
|
+
return;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
try {
|
|
770
|
+
postReviewComments(res.pr, res.findings, {
|
|
771
|
+
cwd: merged.cwd,
|
|
772
|
+
commitId: res.pr.headRefOid,
|
|
773
|
+
});
|
|
774
|
+
logger.log(
|
|
775
|
+
chalk.green(
|
|
776
|
+
`✓ posted ${res.findings.length} comment(s) to PR #${res.pr.number}`,
|
|
777
|
+
),
|
|
778
|
+
);
|
|
779
|
+
} catch (err) {
|
|
780
|
+
logger.error(chalk.red(`failed to post review: ${err.message}`));
|
|
781
|
+
process.exitCode = 1;
|
|
782
|
+
}
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
|
|
442
786
|
logger.info(
|
|
443
787
|
chalk.gray(
|
|
444
788
|
`Reviewing ${label} · ${effort} effort · ${modeLabel}` +
|
package/src/index.js
CHANGED
|
@@ -65,6 +65,7 @@ import { registerCommandCommand } from "./commands/command.js";
|
|
|
65
65
|
import { registerCompactCommand } from "./commands/compact.js";
|
|
66
66
|
import { registerLoopCommand } from "./commands/loop.js";
|
|
67
67
|
import { registerReviewCommand } from "./commands/review.js";
|
|
68
|
+
import { registerInsightsCommand } from "./commands/insights.js";
|
|
68
69
|
import { registerPermissionsCommand } from "./commands/permissions.js";
|
|
69
70
|
import { registerOutputStyleCommand } from "./commands/output-style.js";
|
|
70
71
|
import { registerStatuslineCommand } from "./commands/statusline.js";
|
|
@@ -479,6 +480,7 @@ export function createProgram(opts = {}) {
|
|
|
479
480
|
registerCompactCommand(program);
|
|
480
481
|
registerLoopCommand(program);
|
|
481
482
|
registerReviewCommand(program);
|
|
483
|
+
registerInsightsCommand(program);
|
|
482
484
|
registerPermissionsCommand(program);
|
|
483
485
|
registerOutputStyleCommand(program);
|
|
484
486
|
registerStatuslineCommand(program);
|
|
@@ -74,6 +74,10 @@ const {
|
|
|
74
74
|
AppleHealthAdapter,
|
|
75
75
|
NeteaseMusicAdapter,
|
|
76
76
|
KugouMusicAdapter,
|
|
77
|
+
QQMusicAdapter,
|
|
78
|
+
FanqieReadingAdapter,
|
|
79
|
+
QimaoReadingAdapter,
|
|
80
|
+
JoyrunAdapter,
|
|
77
81
|
IqiyiVideoAdapter,
|
|
78
82
|
TencentVideoAdapter,
|
|
79
83
|
XiguaVideoAdapter,
|
|
@@ -85,6 +89,12 @@ const {
|
|
|
85
89
|
IXiamenAdapter,
|
|
86
90
|
MeiyouAdapter,
|
|
87
91
|
TaxAdapter,
|
|
92
|
+
CmbcBankAdapter,
|
|
93
|
+
BocBankAdapter,
|
|
94
|
+
BankcommBankAdapter,
|
|
95
|
+
IcbcBankAdapter,
|
|
96
|
+
DcepAdapter,
|
|
97
|
+
Tmri12123Adapter,
|
|
88
98
|
DingTalkPcAdapter,
|
|
89
99
|
FeishuPcAdapter,
|
|
90
100
|
WeWorkPcAdapter,
|
|
@@ -554,6 +564,10 @@ async function initHub() {
|
|
|
554
564
|
AppleHealthAdapter,
|
|
555
565
|
NeteaseMusicAdapter,
|
|
556
566
|
KugouMusicAdapter,
|
|
567
|
+
QQMusicAdapter,
|
|
568
|
+
FanqieReadingAdapter,
|
|
569
|
+
QimaoReadingAdapter,
|
|
570
|
+
JoyrunAdapter,
|
|
557
571
|
IqiyiVideoAdapter,
|
|
558
572
|
TencentVideoAdapter,
|
|
559
573
|
XiguaVideoAdapter,
|
|
@@ -565,6 +579,12 @@ async function initHub() {
|
|
|
565
579
|
IXiamenAdapter,
|
|
566
580
|
MeiyouAdapter,
|
|
567
581
|
TaxAdapter,
|
|
582
|
+
CmbcBankAdapter,
|
|
583
|
+
BocBankAdapter,
|
|
584
|
+
BankcommBankAdapter,
|
|
585
|
+
IcbcBankAdapter,
|
|
586
|
+
DcepAdapter,
|
|
587
|
+
Tmri12123Adapter,
|
|
568
588
|
DingTalkPcAdapter,
|
|
569
589
|
FeishuPcAdapter,
|
|
570
590
|
WeWorkPcAdapter,
|