jinzd-ai-cli 0.4.222 → 0.4.224

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.
Files changed (40) hide show
  1. package/dist/{batch-QOOO7HRW.js → batch-EQER63CQ.js} +2 -2
  2. package/dist/{chat-index-FDSGKWQV.js → chat-index-O56HDGFI.js} +2 -2
  3. package/dist/{chat-index-PS274XM7.js → chat-index-WSI7ULRQ.js} +1 -1
  4. package/dist/{chunk-OJL3PY36.js → chunk-2X2DOHA6.js} +3 -2
  5. package/dist/{chunk-VWTUYDZG.js → chunk-34RV4ZKA.js} +1 -1
  6. package/dist/{chunk-UWUTLIOH.js → chunk-35OPVVEK.js} +1 -1
  7. package/dist/{chunk-NZ4X6GUC.js → chunk-3ARPAVNV.js} +2 -2
  8. package/dist/{chunk-FBK7NSIK.js → chunk-4CZZJQXJ.js} +2 -2
  9. package/dist/{chunk-5EE4GRGG.js → chunk-4RQPCOEE.js} +281 -41
  10. package/dist/{chunk-VBRCWH55.js → chunk-6FEZAWH5.js} +3 -3
  11. package/dist/{chunk-SISFAT6W.js → chunk-A2AVDSXJ.js} +1 -1
  12. package/dist/{chunk-SLSWPBK3.js → chunk-B5TYJO7V.js} +4 -1
  13. package/dist/{chunk-QT5FA2ZY.js → chunk-DEHVRQWW.js} +5 -5
  14. package/dist/{chunk-AV5OPK7Q.js → chunk-HLXQXV23.js} +1 -1
  15. package/dist/{chunk-TNW22OUY.js → chunk-JDMFVRFG.js} +3 -3
  16. package/dist/{chunk-S6L5R6SS.js → chunk-JU7OI4BN.js} +1 -1
  17. package/dist/{chunk-VHY6NVMQ.js → chunk-LF3OUJHK.js} +4 -1
  18. package/dist/{chunk-TB4W4Y4T.js → chunk-NVUCDUXE.js} +1 -1
  19. package/dist/{chunk-NNWWMGYK.js → chunk-QJUAQKH2.js} +1 -1
  20. package/dist/{chunk-5GTWZ4QF.js → chunk-QYQCCIBT.js} +1 -1
  21. package/dist/{chunk-Q3ZUDA6S.js → chunk-VT6NRDD2.js} +1 -1
  22. package/dist/{ci-IB7NWHZN.js → ci-UAQFOAMS.js} +4 -4
  23. package/dist/{ci-format-YLGZN3D4.js → ci-format-MNUHYUTO.js} +2 -2
  24. package/dist/{constants-BOMLZEXC.js → constants-PGDTYD2R.js} +1 -1
  25. package/dist/{doctor-cli-2ND4LONW.js → doctor-cli-F6A3GOVY.js} +4 -4
  26. package/dist/electron-server.js +2017 -1786
  27. package/dist/{hub-6WADFJNC.js → hub-EDTZKS7E.js} +6 -6
  28. package/dist/{hub-server-LJ2JSKZ2.js → hub-server-XX36DX7O.js} +2 -2
  29. package/dist/index.js +26 -22
  30. package/dist/{persist-GTBEKVFL.js → persist-XUXIPYUU.js} +3 -3
  31. package/dist/{pr-F7WXUH27.js → pr-YC7DMVC5.js} +4 -4
  32. package/dist/{run-tests-5NEMM6EF.js → run-tests-AUEKHJCC.js} +2 -2
  33. package/dist/{run-tests-NIY24YDP.js → run-tests-S36TE2W2.js} +1 -1
  34. package/dist/{server-ACFX2J66.js → server-347YIBHS.js} +6 -6
  35. package/dist/{server-QGZYDDZW.js → server-LQFHSFN4.js} +1278 -1271
  36. package/dist/{task-orchestrator-4GOBFXPN.js → task-orchestrator-FIR5MCND.js} +17 -9
  37. package/dist/{usage-JXT2YVA6.js → usage-3MXPFFBU.js} +2 -2
  38. package/dist/web/client/app.js +3 -2
  39. package/dist/web/client/util.js +42 -0
  40. package/package.json +1 -1
@@ -3,14 +3,14 @@ import {
3
3
  ToolRegistry,
4
4
  googleSearchContext,
5
5
  truncateOutput
6
- } from "./chunk-5EE4GRGG.js";
6
+ } from "./chunk-4RQPCOEE.js";
7
7
  import "./chunk-K3CF65QH.js";
8
8
  import "./chunk-UUSRWSSX.js";
9
9
  import "./chunk-CKH4KQ4E.js";
10
10
  import "./chunk-BXP6YZ2P.js";
11
11
  import {
12
12
  runTool
13
- } from "./chunk-SISFAT6W.js";
13
+ } from "./chunk-A2AVDSXJ.js";
14
14
  import {
15
15
  getDangerLevel,
16
16
  runLeanAgentLoop
@@ -18,13 +18,13 @@ import {
18
18
  import "./chunk-5ULLIOVC.js";
19
19
  import "./chunk-HOSJZMQS.js";
20
20
  import "./chunk-4BKXL7SM.js";
21
- import "./chunk-S6L5R6SS.js";
21
+ import "./chunk-JU7OI4BN.js";
22
22
  import {
23
23
  SUBAGENT_ALLOWED_TOOLS
24
- } from "./chunk-NNWWMGYK.js";
25
- import "./chunk-TB4W4Y4T.js";
24
+ } from "./chunk-QJUAQKH2.js";
25
+ import "./chunk-NVUCDUXE.js";
26
26
  import "./chunk-KHYD3WXE.js";
27
- import "./chunk-SLSWPBK3.js";
27
+ import "./chunk-B5TYJO7V.js";
28
28
  import {
29
29
  atomicWriteFileSync
30
30
  } from "./chunk-IW3Q7AE5.js";
@@ -187,6 +187,14 @@ var TaskToolExecutor = class {
187
187
 
188
188
  // src/hub/task-orchestrator.ts
189
189
  var TASK_STATE_FILE = ".aicli-task.json";
190
+ function asToolCapable(p) {
191
+ if (typeof p.chatWithTools !== "function") {
192
+ throw new Error(
193
+ `Provider '${p.info?.id ?? "unknown"}' does not support tool calls. Hub task orchestration requires a tool-capable provider (e.g. claude, openai, deepseek).`
194
+ );
195
+ }
196
+ return p;
197
+ }
190
198
  var TaskOrchestrator = class {
191
199
  constructor(config, providers, configManager) {
192
200
  this.config = config;
@@ -226,7 +234,7 @@ var TaskOrchestrator = class {
226
234
  }
227
235
  if (!plan) {
228
236
  this.renderPhaseHeader("PLAN", "Architect is decomposing the goal into tasks...");
229
- plan = await this.generatePlan(goal, provider);
237
+ plan = await this.generatePlan(goal, asToolCapable(provider));
230
238
  if (!plan || plan.tasks.length === 0) {
231
239
  console.log(chalk.red(" \u2717 Failed to generate a task plan."));
232
240
  return;
@@ -240,9 +248,9 @@ var TaskOrchestrator = class {
240
248
  }
241
249
  }
242
250
  this.renderPhaseHeader("EXECUTE", "Agents are executing tasks...");
243
- await this.executePlan(plan, provider);
251
+ await this.executePlan(plan, asToolCapable(provider));
244
252
  this.renderPhaseHeader("REVIEW", "Generating project summary...");
245
- await this.generateReview(plan, provider);
253
+ await this.generateReview(plan, asToolCapable(provider));
246
254
  const allDone = plan.tasks.every((t) => t.status === "done");
247
255
  if (allDone) {
248
256
  this.deleteState();
@@ -8,9 +8,9 @@ import {
8
8
  } from "./chunk-E44DTERW.js";
9
9
  import {
10
10
  ConfigManager
11
- } from "./chunk-UWUTLIOH.js";
11
+ } from "./chunk-35OPVVEK.js";
12
12
  import "./chunk-5ULLIOVC.js";
13
- import "./chunk-NNWWMGYK.js";
13
+ import "./chunk-QJUAQKH2.js";
14
14
  import "./chunk-IW3Q7AE5.js";
15
15
 
16
16
  // src/cli/usage.ts
@@ -7,7 +7,7 @@
7
7
  * global lexical environment and are read/reassigned here as free variables.
8
8
  */
9
9
 
10
- import { escapeHtml, formatToolArgs, formatDuration } from './util.js';
10
+ import { escapeHtml, formatToolArgs, formatDuration, sanitizeHtml } from './util.js';
11
11
 
12
12
  // ── State ──────────────────────────────────────────────────────────
13
13
  // All cross-cutting mutable state now lives in state.js (P0-4 Phase 1),
@@ -775,7 +775,8 @@ export function addErrorMessage(text) {
775
775
 
776
776
  function renderMarkdown(el, text) {
777
777
  try {
778
- el.innerHTML = marked.parse(text);
778
+ // P1-SEC-01: sanitize AI-generated HTML before innerHTML insertion
779
+ el.innerHTML = sanitizeHtml(marked.parse(text));
779
780
  // Add copy buttons to code blocks
780
781
  el.querySelectorAll('pre code').forEach(block => {
781
782
  const pre = block.parentElement;
@@ -43,3 +43,45 @@ export function formatToolArgs(args) {
43
43
  return `<span class="font-semibold">${escapeHtml(k)}</span>: ${escapeHtml(val)}`;
44
44
  }).join('<br>');
45
45
  }
46
+
47
+ /**
48
+ * Sanitize AI-generated HTML for safe innerHTML insertion (P1-SEC-01).
49
+ *
50
+ * Strips dangerous constructs that CSP cannot fully cover:
51
+ * - <script>, <form>, <base>, <link> (whitelist-removed entirely)
52
+ * - on* event handler attributes (onclick, onerror, onload…)
53
+ * - javascript:/data: links (rewritten to #blocked)
54
+ *
55
+ * This is defense-in-depth — CSP `script-src 'self'` already blocks inline
56
+ * scripts. But <a href="javascript:alert(1)"> clickjacking and <form action="…">
57
+ * hijack are not stopped by script-src alone, so we strip them at the HTML level.
58
+ *
59
+ * @param {string} html - Raw HTML from marked.parse (AI-generated Markdown)
60
+ * @returns {string} Sanitized HTML safe for innerHTML
61
+ */
62
+ export function sanitizeHtml(html) {
63
+ // 1) Strip entire dangerous tags (with their contents)
64
+ let safe = html.replace(/<script\b[^>]*>[\s\S]*?<\/script\s*>/gi, '');
65
+ safe = safe.replace(/<form\b[^>]*>[\s\S]*?<\/form\s*>/gi, '');
66
+ safe = safe.replace(/<base\b[^>]*\/?>/gi, '');
67
+ safe = safe.replace(/<link\b[^>]*\/?>/gi, '');
68
+ safe = safe.replace(/<meta\b[^>]*\/?>/gi, '');
69
+ safe = safe.replace(/<object\b[^>]*>[\s\S]*?<\/object\s*>/gi, '');
70
+ safe = safe.replace(/<embed\b[^>]*\/?>/gi, '');
71
+
72
+ // 2) Strip all on* event handler attributes (onclick, onerror, onload…)
73
+ safe = safe.replace(/\s+on\w+\s*=\s*(['"])(?:(?!\1).)*\1/gi, '');
74
+
75
+ // 3) Rewrite javascript:/data: protocol links to inert placeholders
76
+ safe = safe.replace(/\bhref\s*=\s*(['"])\s*javascript\s*:/gi, "href=$1#blocked-js:");
77
+ safe = safe.replace(/\bhref\s*=\s*(['"])\s*data\s*:/gi, "href=$1#blocked-data:");
78
+ safe = safe.replace(/\bsrc\s*=\s*(['"])\s*javascript\s*:/gi, "src=$1#blocked-js:");
79
+ safe = safe.replace(/\bsrc\s*=\s*(['"])\s*data\s*:/gi, (m, q) => {
80
+ // Allow data:image/ and data:text/ for legitimate inline images/blobs
81
+ const lower = m.toLowerCase();
82
+ if (lower.includes("data:image/") || lower.includes("data:text/")) return m;
83
+ return `src=${q}#blocked-data:`;
84
+ });
85
+
86
+ return safe;
87
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jinzd-ai-cli",
3
- "version": "0.4.222",
3
+ "version": "0.4.224",
4
4
  "description": "Cross-platform REPL-style AI CLI with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",