@starlove/orbit 1.3.5 → 1.4.1

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 (129) hide show
  1. package/Dockerfile +2 -1
  2. package/README.md +10 -9
  3. package/SKILL-ORBIT.md +41 -17
  4. package/dist/full/fonts/Chakra_Petch/ChakraPetch-Bold.ttf +0 -0
  5. package/dist/full/fonts/Chakra_Petch/ChakraPetch-BoldItalic.ttf +0 -0
  6. package/dist/full/fonts/Chakra_Petch/ChakraPetch-Italic.ttf +0 -0
  7. package/dist/full/fonts/Chakra_Petch/ChakraPetch-Light.ttf +0 -0
  8. package/dist/full/fonts/Chakra_Petch/ChakraPetch-LightItalic.ttf +0 -0
  9. package/dist/full/fonts/Chakra_Petch/ChakraPetch-Medium.ttf +0 -0
  10. package/dist/full/fonts/Chakra_Petch/ChakraPetch-MediumItalic.ttf +0 -0
  11. package/dist/full/fonts/Chakra_Petch/ChakraPetch-Regular.ttf +0 -0
  12. package/dist/full/fonts/Chakra_Petch/ChakraPetch-SemiBold.ttf +0 -0
  13. package/dist/full/fonts/Chakra_Petch/ChakraPetch-SemiBoldItalic.ttf +0 -0
  14. package/dist/full/fonts/Chakra_Petch/OFL.txt +93 -0
  15. package/dist/full/fonts/Inter/Inter-Italic-VariableFont_opsz,wght.ttf +0 -0
  16. package/dist/full/fonts/Inter/Inter-VariableFont_opsz,wght.ttf +0 -0
  17. package/dist/full/fonts/Inter/OFL.txt +93 -0
  18. package/dist/full/fonts/Inter/README.txt +118 -0
  19. package/dist/full/fonts/JetBrains_Mono/JetBrainsMono-Italic-VariableFont_wght.ttf +0 -0
  20. package/dist/full/fonts/JetBrains_Mono/JetBrainsMono-VariableFont_wght.ttf +0 -0
  21. package/dist/full/fonts/JetBrains_Mono/OFL.txt +93 -0
  22. package/dist/full/fonts/JetBrains_Mono/README.txt +79 -0
  23. package/dist/full/fonts/OpenRing-Regular.ttf +0 -0
  24. package/dist/full/fonts/Open_Sans/OFL.txt +93 -0
  25. package/dist/full/fonts/Open_Sans/OpenSans-Italic-VariableFont_wdth,wght.ttf +0 -0
  26. package/dist/full/fonts/Open_Sans/OpenSans-VariableFont_wdth,wght.ttf +0 -0
  27. package/dist/full/fonts/Open_Sans/README.txt +100 -0
  28. package/dist/full/fonts/Orbitron/OFL.txt +93 -0
  29. package/dist/full/fonts/Orbitron/Orbitron-VariableFont_wght.ttf +0 -0
  30. package/dist/full/fonts/Orbitron/README.txt +68 -0
  31. package/dist/full/fonts/Rajdhani/OFL.txt +93 -0
  32. package/dist/full/fonts/Rajdhani/Rajdhani-Bold.ttf +0 -0
  33. package/dist/full/fonts/Rajdhani/Rajdhani-Light.ttf +0 -0
  34. package/dist/full/fonts/Rajdhani/Rajdhani-Medium.ttf +0 -0
  35. package/dist/full/fonts/Rajdhani/Rajdhani-Regular.ttf +0 -0
  36. package/dist/full/fonts/Rajdhani/Rajdhani-SemiBold.ttf +0 -0
  37. package/dist/full/fonts/runescape-uf.ttf +0 -0
  38. package/dist/full/index.html +135 -25
  39. package/dist/full/js/app.4e6fbe20.js +952 -0
  40. package/dist/full/js/app.4e6fbe20.js.map +7 -0
  41. package/dist/full/styles.4e60d824.css +1 -0
  42. package/dist/full/version.json +2 -2
  43. package/docs/AGENT_PROTOCOL.md +20 -13
  44. package/docs/ORBIT_DISPATCH.md +73 -38
  45. package/docs/UPDATING.md +114 -0
  46. package/package.json +5 -7
  47. package/public/fonts/Chakra_Petch/ChakraPetch-Bold.ttf +0 -0
  48. package/public/fonts/Chakra_Petch/ChakraPetch-BoldItalic.ttf +0 -0
  49. package/public/fonts/Chakra_Petch/ChakraPetch-Italic.ttf +0 -0
  50. package/public/fonts/Chakra_Petch/ChakraPetch-Light.ttf +0 -0
  51. package/public/fonts/Chakra_Petch/ChakraPetch-LightItalic.ttf +0 -0
  52. package/public/fonts/Chakra_Petch/ChakraPetch-Medium.ttf +0 -0
  53. package/public/fonts/Chakra_Petch/ChakraPetch-MediumItalic.ttf +0 -0
  54. package/public/fonts/Chakra_Petch/ChakraPetch-Regular.ttf +0 -0
  55. package/public/fonts/Chakra_Petch/ChakraPetch-SemiBold.ttf +0 -0
  56. package/public/fonts/Chakra_Petch/ChakraPetch-SemiBoldItalic.ttf +0 -0
  57. package/public/fonts/Chakra_Petch/OFL.txt +93 -0
  58. package/public/fonts/Inter/Inter-Italic-VariableFont_opsz,wght.ttf +0 -0
  59. package/public/fonts/Inter/Inter-VariableFont_opsz,wght.ttf +0 -0
  60. package/public/fonts/Inter/OFL.txt +93 -0
  61. package/public/fonts/Inter/README.txt +118 -0
  62. package/public/fonts/JetBrains_Mono/JetBrainsMono-Italic-VariableFont_wght.ttf +0 -0
  63. package/public/fonts/JetBrains_Mono/JetBrainsMono-VariableFont_wght.ttf +0 -0
  64. package/public/fonts/JetBrains_Mono/OFL.txt +93 -0
  65. package/public/fonts/JetBrains_Mono/README.txt +79 -0
  66. package/public/fonts/OpenRing-Regular.ttf +0 -0
  67. package/public/fonts/Open_Sans/OFL.txt +93 -0
  68. package/public/fonts/Open_Sans/OpenSans-Italic-VariableFont_wdth,wght.ttf +0 -0
  69. package/public/fonts/Open_Sans/OpenSans-VariableFont_wdth,wght.ttf +0 -0
  70. package/public/fonts/Open_Sans/README.txt +100 -0
  71. package/public/fonts/Orbitron/OFL.txt +93 -0
  72. package/public/fonts/Orbitron/Orbitron-VariableFont_wght.ttf +0 -0
  73. package/public/fonts/Orbitron/README.txt +68 -0
  74. package/public/fonts/Rajdhani/OFL.txt +93 -0
  75. package/public/fonts/Rajdhani/Rajdhani-Bold.ttf +0 -0
  76. package/public/fonts/Rajdhani/Rajdhani-Light.ttf +0 -0
  77. package/public/fonts/Rajdhani/Rajdhani-Medium.ttf +0 -0
  78. package/public/fonts/Rajdhani/Rajdhani-Regular.ttf +0 -0
  79. package/public/fonts/Rajdhani/Rajdhani-SemiBold.ttf +0 -0
  80. package/public/fonts/runescape-uf.ttf +0 -0
  81. package/public/index.html +133 -23
  82. package/public/js/artifact-drawer.js +79 -0
  83. package/public/js/board-export.js +161 -0
  84. package/public/js/board-menu.js +219 -17
  85. package/public/js/card-actions.js +1 -1
  86. package/public/js/create-card.js +60 -23
  87. package/public/js/drawer.js +164 -4
  88. package/public/js/font-preference.js +230 -0
  89. package/public/js/format.js +0 -10
  90. package/public/js/icons.js +16 -0
  91. package/public/js/local-backend.js +31 -4
  92. package/public/js/main.js +7 -1
  93. package/public/js/modal.js +3 -1
  94. package/public/js/panel.js +58 -0
  95. package/public/js/settings-tabs.js +1 -1
  96. package/public/js/settings.js +606 -275
  97. package/public/js/sse.js +3 -0
  98. package/public/js/state.js +1 -1
  99. package/public/js/text-editing.js +128 -0
  100. package/public/js/ticket-detail.js +377 -148
  101. package/public/js/ticket-typeahead.js +49 -0
  102. package/public/js/toast.js +19 -4
  103. package/public/js/topbar-notes.js +3 -3
  104. package/public/js/typeahead.js +206 -0
  105. package/public/js/update-check.js +58 -0
  106. package/public/styles.css +5447 -3572
  107. package/src/cli/orbit.js +9 -5
  108. package/src/core/agent.js +12 -4
  109. package/src/core/agents-md.js +3 -3
  110. package/src/core/artifacts.js +149 -0
  111. package/src/core/board.js +3 -2
  112. package/src/core/boards.js +0 -1
  113. package/src/core/css-bundle.js +1 -0
  114. package/src/core/db.js +6 -0
  115. package/src/core/dispatch.js +344 -34
  116. package/src/core/http.js +9 -2
  117. package/src/core/paths.js +26 -2
  118. package/src/core/router.js +33 -0
  119. package/src/core/search.js +3 -2
  120. package/src/core/snapshots.js +10 -5
  121. package/src/core/tickets.js +34 -3
  122. package/src/core/util.js +3 -2
  123. package/src/core/version-check.js +154 -0
  124. package/src/mcp/orbit-client.js +18 -2
  125. package/src/mcp-server.js +19 -14
  126. package/src/server.js +28 -3
  127. package/dist/full/js/app.4ae80764.js +0 -742
  128. package/dist/full/js/app.4ae80764.js.map +0 -7
  129. package/dist/full/styles.b9e0c130.css +0 -1
package/public/js/sse.js CHANGED
@@ -16,6 +16,7 @@ const CARD_TOUCHING_EVENTS = new Set([
16
16
  "state_changed",
17
17
  "ticket_updated",
18
18
  "comment_created",
19
+ "comment_ai_omission_changed",
19
20
  "agent_claimed",
20
21
  "checkpoint_requested",
21
22
  "agent_completed"
@@ -99,6 +100,8 @@ export function connectEventStream() {
99
100
  const label = ticket ? `#${ticket.number}` : "ticket";
100
101
  toast.info(`New comment on ${label}`);
101
102
  scheduleSSEReload();
103
+ } else if (eventType === "comment_ai_omission_changed") {
104
+ scheduleSSEReload();
102
105
  } else if (eventType === "agent_claimed") {
103
106
  const ticket = findTicket();
104
107
  toast.info(`Agent claimed ${ticket ? `#${ticket.number} ${ticket.title}` : "a ticket"}`);
@@ -16,7 +16,7 @@ export const state = {
16
16
  expandedCardIds: new Set(),
17
17
  /** "empty" | "ticket" | "settings" — drives the main right overlay drawer (not the New flyout). */
18
18
  detailMode: "empty",
19
- /** "lanes" | "ai" | "repository" | "notes" | "journal" — which Settings tab is active. */
19
+ /** "lanes" | "ai" | "data" | "notes" | "journal" — which Settings tab is active. */
20
20
  settingsTab: normalizeSettingsTab(localStorage.getItem("mab_settings_tab")),
21
21
  /** Whether to render the priority pill on kanban / related cards. The detail
22
22
  * drawer header always shows it. Default on; user can toggle it from the
@@ -0,0 +1,128 @@
1
+ // Shared textarea editing helpers. These stay DOM-light so node:test can cover
2
+ // editor behavior without booting the browser app.
3
+
4
+ const DEFAULT_INDENT = "\t";
5
+
6
+ function clampIndex(value, index) {
7
+ const n = Number(index);
8
+ if (!Number.isFinite(n)) return 0;
9
+ return Math.max(0, Math.min(value.length, n));
10
+ }
11
+
12
+ function lineStartFor(value, index) {
13
+ return value.lastIndexOf("\n", Math.max(0, index - 1)) + 1;
14
+ }
15
+
16
+ function selectedLineRange(value, selectionStart, selectionEnd) {
17
+ const lineStart = lineStartFor(value, selectionStart);
18
+ const effectiveEnd =
19
+ selectionEnd > selectionStart && value[selectionEnd - 1] === "\n"
20
+ ? selectionEnd - 1
21
+ : selectionEnd;
22
+ const nextBreak = value.indexOf("\n", Math.max(lineStart, effectiveEnd));
23
+ return {
24
+ lineStart,
25
+ lineEnd: nextBreak === -1 ? value.length : nextBreak,
26
+ };
27
+ }
28
+
29
+ function lineStartsForBlock(block, lineStart) {
30
+ const starts = [];
31
+ let cursor = lineStart;
32
+ for (const line of block.split("\n")) {
33
+ starts.push(cursor);
34
+ cursor += line.length + 1;
35
+ }
36
+ return starts;
37
+ }
38
+
39
+ function leadingOutdentWidth(line) {
40
+ if (line.startsWith("\t")) return 1;
41
+ const spaces = line.match(/^ {1,2}/)?.[0] || "";
42
+ return spaces.length;
43
+ }
44
+
45
+ function adjustmentBeforePosition(position, lineStarts, widths) {
46
+ let total = 0;
47
+ for (let i = 0; i < lineStarts.length; i += 1) {
48
+ if (position <= lineStarts[i]) continue;
49
+ total += Math.min(widths[i], position - lineStarts[i]);
50
+ }
51
+ return total;
52
+ }
53
+
54
+ export function applyTextareaIndentation({
55
+ value = "",
56
+ selectionStart = 0,
57
+ selectionEnd = selectionStart,
58
+ shiftKey = false,
59
+ indent = DEFAULT_INDENT,
60
+ } = {}) {
61
+ const source = String(value);
62
+ const start = clampIndex(source, selectionStart);
63
+ const end = clampIndex(source, selectionEnd);
64
+ const first = Math.min(start, end);
65
+ const last = Math.max(start, end);
66
+ const indentText = String(indent || DEFAULT_INDENT);
67
+
68
+ if (!shiftKey && first === last) {
69
+ const nextValue = `${source.slice(0, first)}${indentText}${source.slice(last)}`;
70
+ const nextCaret = first + indentText.length;
71
+ return {
72
+ value: nextValue,
73
+ selectionStart: nextCaret,
74
+ selectionEnd: nextCaret,
75
+ handled: true,
76
+ };
77
+ }
78
+
79
+ const { lineStart, lineEnd } = selectedLineRange(source, first, last);
80
+ const block = source.slice(lineStart, lineEnd);
81
+ const lines = block.split("\n");
82
+ const lineStarts = lineStartsForBlock(block, lineStart);
83
+
84
+ if (!shiftKey) {
85
+ const widths = lines.map(() => indentText.length);
86
+ const nextBlock = lines.map((line) => `${indentText}${line}`).join("\n");
87
+ const selectionStartDelta = adjustmentBeforePosition(first, lineStarts, widths);
88
+ const selectionEndDelta = adjustmentBeforePosition(last, lineStarts, widths);
89
+ return {
90
+ value: `${source.slice(0, lineStart)}${nextBlock}${source.slice(lineEnd)}`,
91
+ selectionStart: first + selectionStartDelta,
92
+ selectionEnd: last + selectionEndDelta,
93
+ handled: true,
94
+ };
95
+ }
96
+
97
+ const widths = lines.map(leadingOutdentWidth);
98
+ const nextBlock = lines
99
+ .map((line, index) => line.slice(widths[index]))
100
+ .join("\n");
101
+ const selectionStartDelta = adjustmentBeforePosition(first, lineStarts, widths);
102
+ const selectionEndDelta = adjustmentBeforePosition(last, lineStarts, widths);
103
+ return {
104
+ value: `${source.slice(0, lineStart)}${nextBlock}${source.slice(lineEnd)}`,
105
+ selectionStart: first - selectionStartDelta,
106
+ selectionEnd: last - selectionEndDelta,
107
+ handled: true,
108
+ };
109
+ }
110
+
111
+ export function handleTextareaIndentationKeydown(event, textarea = event?.currentTarget) {
112
+ if (!event || event.key !== "Tab") return false;
113
+ if (event.altKey || event.ctrlKey || event.metaKey) return false;
114
+ if (!textarea || textarea.tagName !== "TEXTAREA") return false;
115
+
116
+ event.preventDefault();
117
+ const next = applyTextareaIndentation({
118
+ value: textarea.value,
119
+ selectionStart: textarea.selectionStart,
120
+ selectionEnd: textarea.selectionEnd,
121
+ shiftKey: event.shiftKey,
122
+ });
123
+
124
+ textarea.value = next.value;
125
+ textarea.setSelectionRange(next.selectionStart, next.selectionEnd);
126
+ textarea.dispatchEvent(new Event("input", { bubbles: true }));
127
+ return next.handled;
128
+ }