@starlove/orbit 1.0.6 → 1.1.0

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 (58) hide show
  1. package/README.md +22 -7
  2. package/SKILL-ORBIT.md +28 -1
  3. package/build.mjs +2 -2
  4. package/dist/full/index.html +2 -2
  5. package/dist/full/js/app.a4f045fc.js +676 -0
  6. package/dist/full/js/app.a4f045fc.js.map +7 -0
  7. package/dist/full/{styles.c2e3d20a.css → styles.836872e7.css} +1117 -47
  8. package/dist/full/version.json +2 -2
  9. package/docs/AGENT_PROTOCOL.md +27 -5
  10. package/docs/MCP_SETUP.md +7 -3
  11. package/docs/ORBIT_DISPATCH.md +185 -0
  12. package/docs/setup/orbit-init-wizard.md +174 -0
  13. package/package.json +2 -2
  14. package/public/js/actor-labels.js +65 -0
  15. package/public/js/api.js +5 -1
  16. package/public/js/app.js +8 -1
  17. package/public/js/card-actions.js +526 -0
  18. package/public/js/config.js +2 -1
  19. package/public/js/drawer.js +2 -0
  20. package/public/js/format.js +336 -0
  21. package/public/js/kanban.js +25 -2
  22. package/public/js/local-backend.js +24 -8
  23. package/public/js/main.js +14 -6
  24. package/public/js/motion-preference.js +53 -0
  25. package/public/js/router.js +78 -58
  26. package/public/js/search.js +6 -3
  27. package/public/js/settings-tabs.js +1 -1
  28. package/public/js/settings.js +192 -29
  29. package/public/js/starscape.js +25 -18
  30. package/public/js/state.js +61 -2
  31. package/public/js/theme-preference.js +88 -0
  32. package/public/js/ticket-detail.js +432 -126
  33. package/public/js/url-routes.js +94 -0
  34. package/public/styles.css +1117 -47
  35. package/src/cli/orbit.js +217 -32
  36. package/src/core/agent.js +1 -18
  37. package/src/core/agents-md.js +16 -10
  38. package/src/core/attachments.js +238 -0
  39. package/src/core/auth.js +36 -0
  40. package/src/core/backups.js +9 -3
  41. package/src/core/board.js +32 -1
  42. package/src/core/boards.js +1 -1
  43. package/src/core/bootstrap.js +9 -1
  44. package/src/core/db.js +42 -2
  45. package/src/core/delete-board.js +87 -21
  46. package/src/core/dispatch.js +532 -0
  47. package/src/core/http.js +31 -11
  48. package/src/core/migrate.js +198 -0
  49. package/src/core/paths.js +6 -0
  50. package/src/core/registry.js +12 -9
  51. package/src/core/router.js +62 -6
  52. package/src/core/search.js +56 -22
  53. package/src/core/snapshots.js +14 -2
  54. package/src/mcp/orbit-client.js +223 -0
  55. package/src/mcp-server.js +89 -129
  56. package/src/server.js +20 -0
  57. package/dist/full/js/app.aedc1bfe.js +0 -554
  58. package/dist/full/js/app.aedc1bfe.js.map +0 -7
@@ -0,0 +1,94 @@
1
+ import { SETTINGS_TAB_IDS } from "./settings-tabs.js";
2
+
3
+ const EMPTY_ROUTE = Object.freeze({ boardSlug: "", view: "board", ticketId: "", tab: "" });
4
+
5
+ function emptyRoute() {
6
+ return { ...EMPTY_ROUTE };
7
+ }
8
+
9
+ function normalizeLocation(input = globalThis.location) {
10
+ if (typeof input === "string") {
11
+ const url = new URL(input, "http://orbit.local");
12
+ return { pathname: url.pathname || "/", search: url.search || "", hash: url.hash || "" };
13
+ }
14
+ return {
15
+ pathname: input?.pathname || "/",
16
+ search: input?.search || "",
17
+ hash: input?.hash || ""
18
+ };
19
+ }
20
+
21
+ function decodeSegment(value) {
22
+ try {
23
+ return decodeURIComponent(value);
24
+ } catch {
25
+ return value;
26
+ }
27
+ }
28
+
29
+ function routeSegments(value) {
30
+ return String(value || "")
31
+ .replace(/^#/, "")
32
+ .replace(/^\/+/, "")
33
+ .replace(/\/+$/, "")
34
+ .split("/")
35
+ .filter(Boolean);
36
+ }
37
+
38
+ function routeFromSegments(parts) {
39
+ if (!parts.length) return null;
40
+
41
+ const out = emptyRoute();
42
+ let i = 0;
43
+
44
+ if (parts[i] === "b") {
45
+ if (!parts[i + 1]) return null;
46
+ out.boardSlug = decodeSegment(parts[i + 1]);
47
+ i += 2;
48
+ } else if (parts[i] !== "t" && parts[i] !== "settings") {
49
+ return null;
50
+ }
51
+
52
+ if (parts[i] === "t" && parts[i + 1]) {
53
+ out.view = "ticket";
54
+ out.ticketId = decodeSegment(parts[i + 1]);
55
+ } else if (parts[i] === "settings") {
56
+ out.view = "settings";
57
+ const tab = parts[i + 1] ? decodeSegment(parts[i + 1]) : "";
58
+ if (tab && SETTINGS_TAB_IDS.has(tab)) out.tab = tab;
59
+ }
60
+
61
+ return out;
62
+ }
63
+
64
+ export function parseLegacyHashRoute(hash) {
65
+ const raw = String(hash || "");
66
+ if (!raw || raw === "#" || raw === "#/") return null;
67
+ return routeFromSegments(routeSegments(raw));
68
+ }
69
+
70
+ export function parseRoute(input = globalThis.location) {
71
+ const loc = normalizeLocation(input);
72
+ return parseLegacyHashRoute(loc.hash) || emptyRoute();
73
+ }
74
+
75
+ export function hasRoute(input = globalThis.location) {
76
+ const loc = normalizeLocation(input);
77
+ return Boolean(parseLegacyHashRoute(loc.hash));
78
+ }
79
+
80
+ export function buildRoute({ boardSlug = "", view = "board", ticketId = "", tab = "" } = {}) {
81
+ const segs = [];
82
+ if (boardSlug) segs.push("b", encodeURIComponent(boardSlug));
83
+ if (view === "ticket" && ticketId) segs.push("t", encodeURIComponent(ticketId));
84
+ else if (view === "settings") {
85
+ segs.push("settings");
86
+ if (tab && SETTINGS_TAB_IDS.has(tab)) segs.push(tab);
87
+ }
88
+ return "#/" + segs.join("/");
89
+ }
90
+
91
+ export function isCanonicalRouteUrl(input = globalThis.location, routeObj = parseRoute(input)) {
92
+ const loc = normalizeLocation(input);
93
+ return loc.hash === buildRoute(routeObj);
94
+ }