@ai-setting/roy-plugin-task-show 0.8.10 → 0.9.6

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 (39) hide show
  1. package/dist/cli-tasks-adapter.d.ts +5 -0
  2. package/dist/cli-tasks-adapter.d.ts.map +1 -1
  3. package/dist/cli-tasks-adapter.js +9 -0
  4. package/dist/cli-tasks-adapter.js.map +1 -1
  5. package/dist/cli-tasks-tree-adapter.d.ts +5 -0
  6. package/dist/cli-tasks-tree-adapter.d.ts.map +1 -1
  7. package/dist/cli-tasks-tree-adapter.js +5 -0
  8. package/dist/cli-tasks-tree-adapter.js.map +1 -1
  9. package/dist/plugin.d.ts +8 -0
  10. package/dist/plugin.d.ts.map +1 -1
  11. package/dist/plugin.js +99 -0
  12. package/dist/plugin.js.map +1 -1
  13. package/dist/server.d.ts +15 -2
  14. package/dist/server.d.ts.map +1 -1
  15. package/dist/server.js +46 -10
  16. package/dist/server.js.map +1 -1
  17. package/dist/task-detail-mermaid.d.ts +9 -0
  18. package/dist/task-detail-mermaid.d.ts.map +1 -1
  19. package/dist/task-detail-mermaid.js +43 -3
  20. package/dist/task-detail-mermaid.js.map +1 -1
  21. package/dist/task-metadata.d.ts +21 -0
  22. package/dist/task-metadata.d.ts.map +1 -0
  23. package/dist/task-metadata.js +50 -0
  24. package/dist/task-metadata.js.map +1 -0
  25. package/dist/task-session-store.d.ts +70 -0
  26. package/dist/task-session-store.d.ts.map +1 -0
  27. package/dist/task-session-store.js +177 -0
  28. package/dist/task-session-store.js.map +1 -0
  29. package/dist/tracing/decorator.d.ts +48 -0
  30. package/dist/tracing/decorator.d.ts.map +1 -0
  31. package/dist/tracing/decorator.js +310 -0
  32. package/dist/tracing/decorator.js.map +1 -0
  33. package/package.json +1 -1
  34. package/plugin.json +2 -2
  35. package/public/app.js +45 -1
  36. package/public/index.html +3 -0
  37. package/public/session-forest.js +97 -0
  38. package/public/style.css +64 -0
  39. package/public/task-operations.js +7 -0
package/public/app.js CHANGED
@@ -247,7 +247,7 @@ function buildMermaidSource(session, operations) {
247
247
  // Top-level helpers used by buildMermaidSource. Kept here so both
248
248
  // IIFEs can call them via the script-wide closure.
249
249
  function toolLabel(t) {
250
- const head = escapeMermaid(`${t.sequence}. ${t.toolName}${t.hasAttachment ? " \ud83d\udcce" : ""}`);
250
+ const head = encodeMermaidLabelTextClient(`${t.sequence}. ${t.toolName}${t.hasAttachment ? " \ud83d\udcce" : ""}`);
251
251
  return `${head}<br/><small>${t.success ? "ok" : "FAIL"} \u00b7 ${t.durationMs}ms</small>`;
252
252
  }
253
253
 
@@ -263,6 +263,35 @@ function escapeMermaid(s) {
263
263
  return String(s).replace(/[<>"#]/g, "").replace(/[^A-Za-z0-9_.\-]/g, "_");
264
264
  }
265
265
 
266
+ /**
267
+ * v0.9.0 client-side mirror of `encodeMermaidLabelText` from
268
+ * `src/task-detail-mermaid.ts`. MUST stay byte-for-byte identical
269
+ * to the server implementation; the parity test in
270
+ * `test/mermaid-cjk-encoding-client.test.ts` enforces this.
271
+ */
272
+ function encodeMermaidLabelTextClient(s) {
273
+ var cleaned = String(s == null ? "" : s)
274
+ .replace(/["\r\n\t]+/g, " ")
275
+ .replace(/\s+/g, " ")
276
+ .trim();
277
+ var out = "";
278
+ for (var i = 0; i < cleaned.length; i++) {
279
+ var ch = cleaned[i];
280
+ var code = ch.codePointAt ? ch.codePointAt(0) : (ch.charCodeAt ? ch.charCodeAt(0) : undefined);
281
+ if (code === undefined) continue;
282
+ if (code < 0x80) { out += ch; continue; }
283
+ if (code <= 0xFFFF) {
284
+ out += "\\u" + code.toString(16).padStart(4, "0");
285
+ } else {
286
+ var v = code - 0x10000;
287
+ var hi = 0xD800 + (v >> 10);
288
+ var lo = 0xDC00 + (v & 0x3FF);
289
+ out += "\\u" + hi.toString(16).padStart(4, "0") + "\\u" + lo.toString(16).padStart(4, "0");
290
+ }
291
+ }
292
+ return out;
293
+ }
294
+
266
295
  // ---------------------------------------------------------------------------
267
296
  // v0.8.2 (fix/mermaid-readable-labels) — human-readable Mermaid
268
297
  // phase labels. This block mirrors `src/task-detail-mermaid.ts` so
@@ -481,6 +510,21 @@ function getPhaseLabel(op) {
481
510
  if (typeof window !== "undefined") {
482
511
  window.buildMermaidSource = buildMermaidSource;
483
512
  window.getPhaseLabel = getPhaseLabel;
513
+ window.encodeMermaidLabelTextClient = encodeMermaidLabelTextClient;
514
+ window.toolLabelClient = function (t) { return toolLabel(t); };
515
+ // v0.9.0 invariant: when invoked with a server encoder, the client
516
+ // encoder must produce byte-for-byte identical output. Drift is
517
+ // surfaced as a hard throw so SSR HTML and dynamic re-render stay
518
+ // in sync.
519
+ window.__cjkParityCheck = function (serverEncode) {
520
+ var cases = ["Phase 3: Plan", "\u4efb\u52a1\u7ba1\u7406", "Phase 1: \u4efb\u52a1\u7ba1\u7406"];
521
+ for (var i = 0; i < cases.length; i++) {
522
+ if (encodeMermaidLabelTextClient(cases[i]) !== serverEncode(cases[i])) {
523
+ throw new Error("CJK parity broken: " + JSON.stringify(cases[i]));
524
+ }
525
+ }
526
+ return true;
527
+ };
484
528
  }
485
529
  /**
486
530
  * v0.8.0+ Mermaid ↔ tool-table bridge.
package/public/index.html CHANGED
@@ -80,6 +80,9 @@
80
80
  </section>
81
81
 
82
82
  <script src="/static/app.js"></script>
83
+ <script src="/static/mermaid-renderer.js"></script>
83
84
  <script src="/static/tasks-tree.js"></script>
85
+ <script src="/static/task-operations.js"></script>
86
+ <script src="/static/session-forest.js"></script>
84
87
  </body>
85
88
  </html>
@@ -0,0 +1,97 @@
1
+ /**
2
+ * @fileoverview Client-side controller for the v0.9.0 session-scoped forest.
3
+ *
4
+ * - Wires each `[data-toggle="<id>"]` button to its matching
5
+ * `details[data-details="<id>"]` block (the "显示全部栏位" toggle).
6
+ * - Lazy-loads `/api/tasks/<id>/operations` into each
7
+ * `ul.session-operations[data-task-operations="<id>"]` placeholder,
8
+ * reusing `renderPipelineHtml` from `task-operations.js`.
9
+ *
10
+ * Vanilla JS, no framework dependency. Bootstraps on DOMContentLoaded.
11
+ */
12
+ (function () {
13
+ "use strict";
14
+
15
+ function esc(s) {
16
+ return String(s == null ? "" : s)
17
+ .replace(/&/g, "&amp;")
18
+ .replace(/</g, "&lt;")
19
+ .replace(/>/g, "&gt;")
20
+ .replace(/"/g, "&quot;")
21
+ .replace(/'/g, "&#39;");
22
+ }
23
+
24
+ function wireToggle(button) {
25
+ var id = button.getAttribute("data-toggle");
26
+ if (!id) return;
27
+ var target = document.querySelector('[data-details="' + cssEscape(id) + '"]');
28
+ if (!target) return;
29
+ button.addEventListener("click", function () {
30
+ target.open = !target.open;
31
+ });
32
+ }
33
+
34
+ function cssEscape(s) {
35
+ if (window.CSS && typeof window.CSS.escape === "function") {
36
+ return window.CSS.escape(s);
37
+ }
38
+ return String(s).replace(/[^a-zA-Z0-9_-]/g, function (c) {
39
+ return "\\" + c;
40
+ });
41
+ }
42
+
43
+ function loadOperationsFor(placeholder) {
44
+ var id = placeholder.getAttribute("data-task-operations");
45
+ if (!id) return;
46
+ placeholder.innerHTML = '<p class="empty">Loading operations…</p>';
47
+ fetch("/api/tasks/" + encodeURIComponent(id) + "/operations")
48
+ .then(function (r) {
49
+ if (!r.ok) throw new Error("HTTP " + r.status);
50
+ return r.json();
51
+ })
52
+ .then(function (envelope) {
53
+ if (typeof window.renderPipelineHtml === "function") {
54
+ placeholder.innerHTML = window.renderPipelineHtml(envelope.operations || [], envelope.stale, Number(id));
55
+ } else {
56
+ // Fallback: render a minimal list
57
+ var html = "<ol class=\"ops-fallback\">";
58
+ (envelope.operations || []).forEach(function (op) {
59
+ html += "<li>" + esc(op.title || op.milestoneType || "op") + "</li>";
60
+ });
61
+ html += "</ol>";
62
+ placeholder.innerHTML = html;
63
+ }
64
+ })
65
+ .catch(function (err) {
66
+ placeholder.innerHTML = '<p class="empty error">Failed to load operations: ' + esc(err && err.message || err) + '</p>';
67
+ });
68
+ }
69
+
70
+ function boot() {
71
+ var section = document.querySelector('[data-session-forest="1"]');
72
+ if (!section) return;
73
+ var buttons = section.querySelectorAll('[data-toggle]');
74
+ for (var i = 0; i < buttons.length; i++) wireToggle(buttons[i]);
75
+ var placeholders = section.querySelectorAll('[data-task-operations]');
76
+ for (var j = 0; j < placeholders.length; j++) loadOperationsFor(placeholders[j]);
77
+ }
78
+
79
+ if (typeof window !== "undefined") {
80
+ window.__sessionForestBoot = boot;
81
+ }
82
+
83
+ if (typeof document !== "undefined") {
84
+ if (document.readyState === "loading") {
85
+ document.addEventListener("DOMContentLoaded", boot);
86
+ } else {
87
+ boot();
88
+ }
89
+ } else if (typeof window !== "undefined" && window.document) {
90
+ // jsdom eval fallback: window may exist but document may not be in scope
91
+ if (window.document.readyState === "loading") {
92
+ window.document.addEventListener("DOMContentLoaded", boot);
93
+ } else {
94
+ boot();
95
+ }
96
+ }
97
+ })();
package/public/style.css CHANGED
@@ -1027,3 +1027,67 @@ details summary {
1027
1027
  border: 1px solid rgba(148, 163, 184, 0.4);
1028
1028
  }
1029
1029
 
1030
+ /* ---------- Session forest metadata ---------- */
1031
+ .session-forest > ul {
1032
+ list-style: none;
1033
+ margin: 0;
1034
+ padding: 0;
1035
+ }
1036
+ .session-row {
1037
+ min-width: 0;
1038
+ margin: 8px 0;
1039
+ padding: 10px 12px;
1040
+ border: 1px solid var(--border);
1041
+ border-radius: 8px;
1042
+ background: rgba(24, 36, 66, 0.45);
1043
+ }
1044
+ .session-row .session-title {
1045
+ display: inline-block;
1046
+ font-weight: 600;
1047
+ overflow-wrap: anywhere;
1048
+ }
1049
+ .session-toggle {
1050
+ margin-left: 10px;
1051
+ }
1052
+ .session-details {
1053
+ margin-top: 8px;
1054
+ }
1055
+ .session-details dl {
1056
+ display: grid;
1057
+ grid-template-columns: minmax(10rem, 15rem) minmax(0, 1fr);
1058
+ gap: 6px 12px;
1059
+ margin: 10px 0 0;
1060
+ }
1061
+ .session-details dt {
1062
+ color: var(--muted);
1063
+ font-weight: 600;
1064
+ overflow-wrap: anywhere;
1065
+ }
1066
+ .session-details dd {
1067
+ min-width: 0;
1068
+ margin: 0;
1069
+ overflow-wrap: anywhere;
1070
+ }
1071
+ .session-details pre.metadata-json,
1072
+ .session-details pre.metadata-text {
1073
+ max-height: 24rem;
1074
+ margin: 0;
1075
+ white-space: pre-wrap;
1076
+ overflow: auto;
1077
+ overflow-wrap: anywhere;
1078
+ word-break: break-word;
1079
+ }
1080
+ .session-operations {
1081
+ list-style: none;
1082
+ margin: 12px 0 0;
1083
+ padding: 0;
1084
+ }
1085
+ @media (max-width: 700px) {
1086
+ .session-details dl {
1087
+ grid-template-columns: 1fr;
1088
+ gap: 2px;
1089
+ }
1090
+ .session-details dd {
1091
+ margin-bottom: 8px;
1092
+ }
1093
+ }
@@ -282,6 +282,13 @@
282
282
  window.__pipelineController = new PipelineController(root);
283
283
  }
284
284
 
285
+ // v0.9.0: expose renderPipelineHtml to the global scope so other
286
+ // modules (session-forest.js) can re-use the same timeline rendering
287
+ // for the v0.9.0 session-forest view.
288
+ if (typeof window !== "undefined") {
289
+ window.renderPipelineHtml = renderPipelineHtml;
290
+ }
291
+
285
292
  if (document.readyState === "loading") {
286
293
  document.addEventListener("DOMContentLoaded", boot);
287
294
  } else {