@starlove/orbit 1.4.0 → 2.0.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.
- package/Dockerfile +10 -8
- package/README.md +146 -164
- package/dist/full/csp.txt +1 -0
- package/dist/full/fonts/JetBrains_Mono/JetBrainsMono-subset.woff2 +0 -0
- package/dist/full/fonts/JetBrains_Mono/README.txt +5 -0
- package/dist/full/fonts/Mona_Sans/MonaSans-subset.woff2 +0 -0
- package/{public/fonts/Open_Sans → dist/full/fonts/Mona_Sans}/OFL.txt +93 -93
- package/dist/full/fonts/Mona_Sans/README.txt +10 -0
- package/{public/fonts/JetBrains_Mono → dist/full/fonts/Newsreader}/OFL.txt +93 -93
- package/dist/full/fonts/Newsreader/README.txt +8 -0
- package/dist/full/fonts/Newsreader/newsreader.woff2 +0 -0
- package/dist/full/index.html +36 -653
- package/dist/full/js/app.BmuponPJ.js +32 -0
- package/dist/full/js/app.BmuponPJ.js.map +1 -0
- package/dist/full/js/chunk.1fJGQGbW.js +2 -0
- package/dist/full/js/chunk.1fJGQGbW.js.map +1 -0
- package/dist/full/js/chunk.5D7JO2zp.js +2 -0
- package/dist/full/js/chunk.5D7JO2zp.js.map +1 -0
- package/dist/full/js/chunk.BrNn_D79.js +2 -0
- package/dist/full/js/chunk.BrNn_D79.js.map +1 -0
- package/dist/full/js/chunk.CokJXIqM.js +2 -0
- package/dist/full/js/chunk.CokJXIqM.js.map +1 -0
- package/dist/full/js/chunk.D_Haqy6R.js +2 -0
- package/dist/full/js/chunk.D_Haqy6R.js.map +1 -0
- package/dist/full/js/chunk.RO0jsH6I.js +15 -0
- package/dist/full/js/chunk.RO0jsH6I.js.map +1 -0
- package/dist/full/js/chunk.dqWOEtBM.js +2 -0
- package/dist/full/js/chunk.dqWOEtBM.js.map +1 -0
- package/dist/full/js/warm.f260bbbc.js +15 -0
- package/dist/full/orbits-favicon.png +0 -0
- package/dist/full/orbits-logo-bg-wide.png +0 -0
- package/dist/full/orbits-logo-bg.png +0 -0
- package/dist/full/orbits-logo.png +0 -0
- package/dist/full/styles.2b154ffe.css +1 -0
- package/dist/full/vendor/starlove-ui/theme-init.js +66 -0
- package/dist/full/version.json +2 -2
- package/docs/AGENT_GUIDE.md +114 -0
- package/docs/UPDATING.md +249 -64
- package/lib/adapters/indexeddb/blobs.d.ts +3 -0
- package/lib/adapters/indexeddb/blobs.js +54 -0
- package/lib/adapters/indexeddb/database.d.ts +60 -0
- package/lib/adapters/indexeddb/database.js +126 -0
- package/lib/adapters/indexeddb/index.d.ts +5 -0
- package/lib/adapters/indexeddb/index.js +3 -0
- package/lib/adapters/indexeddb/locks.d.ts +14 -0
- package/lib/adapters/indexeddb/locks.js +40 -0
- package/lib/adapters/indexeddb/store.d.ts +40 -0
- package/lib/adapters/indexeddb/store.js +424 -0
- package/lib/adapters/indexeddb/tables.d.ts +43 -0
- package/lib/adapters/indexeddb/tables.js +127 -0
- package/lib/adapters/memory/blobs.d.ts +3 -0
- package/lib/adapters/memory/blobs.js +44 -0
- package/lib/adapters/memory/board.d.ts +41 -0
- package/lib/adapters/memory/board.js +521 -0
- package/lib/adapters/memory/index.d.ts +2 -0
- package/lib/adapters/memory/index.js +2 -0
- package/lib/adapters/memory/search.d.ts +6 -0
- package/lib/adapters/memory/search.js +30 -0
- package/lib/adapters/memory/store.d.ts +34 -0
- package/lib/adapters/memory/store.js +266 -0
- package/lib/adapters/sqlite/backups.d.ts +53 -0
- package/lib/adapters/sqlite/backups.js +232 -0
- package/lib/adapters/sqlite/blobs.d.ts +14 -0
- package/lib/adapters/sqlite/blobs.js +109 -0
- package/lib/adapters/sqlite/board.d.ts +77 -0
- package/lib/adapters/sqlite/board.js +328 -0
- package/lib/adapters/sqlite/database.d.ts +67 -0
- package/lib/adapters/sqlite/database.js +285 -0
- package/lib/adapters/sqlite/index.d.ts +3 -0
- package/lib/adapters/sqlite/index.js +2 -0
- package/lib/adapters/sqlite/lock.d.ts +11 -0
- package/lib/adapters/sqlite/lock.js +34 -0
- package/lib/adapters/sqlite/records.d.ts +54 -0
- package/lib/adapters/sqlite/records.js +546 -0
- package/lib/adapters/sqlite/schema.d.ts +54 -0
- package/lib/adapters/sqlite/schema.js +276 -0
- package/lib/adapters/sqlite/store.d.ts +39 -0
- package/lib/adapters/sqlite/store.js +385 -0
- package/lib/browser/in-page.d.ts +31 -0
- package/lib/browser/in-page.js +46 -0
- package/lib/browser/old-preview.d.ts +13 -0
- package/lib/browser/old-preview.js +80 -0
- package/lib/browser/preview-board.d.ts +8 -0
- package/lib/browser/preview-board.js +69 -0
- package/lib/cli/main.d.ts +7 -0
- package/lib/cli/main.js +343 -0
- package/lib/cli/orbit.d.ts +8 -0
- package/lib/cli/orbit.js +25 -0
- package/lib/client/http.d.ts +38 -0
- package/lib/client/http.js +334 -0
- package/lib/client/local.d.ts +26 -0
- package/lib/client/local.js +190 -0
- package/lib/client/object-url.d.ts +8 -0
- package/lib/client/object-url.js +21 -0
- package/lib/client/types.d.ts +268 -0
- package/lib/client/types.js +8 -0
- package/lib/commands/agent-tools.d.ts +31 -0
- package/lib/commands/agent-tools.js +100 -0
- package/lib/commands/index.d.ts +56 -0
- package/lib/commands/index.js +298 -0
- package/lib/commands/parse.d.ts +73 -0
- package/lib/commands/parse.js +231 -0
- package/lib/commands/present.d.ts +134 -0
- package/lib/commands/present.js +198 -0
- package/lib/commands/session.d.ts +85 -0
- package/lib/commands/session.js +138 -0
- package/lib/commands/verbs.d.ts +35 -0
- package/lib/commands/verbs.js +842 -0
- package/lib/core/actors.d.ts +18 -0
- package/lib/core/actors.js +45 -0
- package/lib/core/agent.d.ts +128 -0
- package/lib/core/agent.js +323 -0
- package/lib/core/boards.d.ts +113 -0
- package/lib/core/boards.js +288 -0
- package/lib/core/bootstrap.d.ts +47 -0
- package/lib/core/bootstrap.js +100 -0
- package/lib/core/bytes.d.ts +10 -0
- package/lib/core/bytes.js +52 -0
- package/lib/core/card-paths.d.ts +25 -0
- package/lib/core/card-paths.js +44 -0
- package/lib/core/context.d.ts +60 -0
- package/lib/core/context.js +42 -0
- package/lib/core/cross-board.d.ts +81 -0
- package/lib/core/cross-board.js +228 -0
- package/lib/core/describe.d.ts +21 -0
- package/lib/core/describe.js +81 -0
- package/lib/core/errors.d.ts +159 -0
- package/lib/core/errors.js +160 -0
- package/lib/core/files.d.ts +79 -0
- package/lib/core/files.js +262 -0
- package/lib/core/history.d.ts +20 -0
- package/lib/core/history.js +53 -0
- package/lib/core/image-types.d.ts +16 -0
- package/lib/core/image-types.js +36 -0
- package/lib/core/model.d.ts +263 -0
- package/lib/core/model.js +34 -0
- package/lib/core/nebula-link.d.ts +14 -0
- package/lib/core/nebula-link.js +39 -0
- package/lib/core/relations.d.ts +58 -0
- package/lib/core/relations.js +112 -0
- package/lib/core/search.d.ts +38 -0
- package/lib/core/search.js +92 -0
- package/lib/core/sessions.d.ts +44 -0
- package/lib/core/sessions.js +158 -0
- package/lib/core/snapshot-schema.d.ts +295 -0
- package/lib/core/snapshot-schema.js +82 -0
- package/lib/core/snapshots.d.ts +75 -0
- package/lib/core/snapshots.js +409 -0
- package/lib/core/states.d.ts +25 -0
- package/lib/core/states.js +126 -0
- package/lib/core/text.d.ts +40 -0
- package/lib/core/text.js +113 -0
- package/lib/core/tickets.d.ts +69 -0
- package/lib/core/tickets.js +311 -0
- package/lib/core/trello.d.ts +17 -0
- package/lib/core/trello.js +269 -0
- package/lib/core/verdicts.d.ts +28 -0
- package/lib/core/verdicts.js +92 -0
- package/lib/core/views.d.ts +95 -0
- package/lib/core/views.js +186 -0
- package/lib/http/app.d.ts +46 -0
- package/lib/http/app.js +491 -0
- package/lib/mcp-server.d.ts +10 -0
- package/lib/mcp-server.js +120 -0
- package/lib/node/assets.d.ts +7 -0
- package/lib/node/assets.js +68 -0
- package/lib/node/data-folder.d.ts +21 -0
- package/lib/node/data-folder.js +34 -0
- package/lib/node/env.d.ts +38 -0
- package/lib/node/env.js +49 -0
- package/lib/node/host-check.d.ts +24 -0
- package/lib/node/host-check.js +53 -0
- package/lib/node/host-services.d.ts +9 -0
- package/lib/node/host-services.js +150 -0
- package/lib/node/local.d.ts +22 -0
- package/lib/node/local.js +61 -0
- package/lib/node/migrate.d.ts +53 -0
- package/lib/node/migrate.js +635 -0
- package/lib/node/package.d.ts +7 -0
- package/lib/node/package.js +14 -0
- package/lib/node/repo-board.d.ts +49 -0
- package/lib/node/repo-board.js +245 -0
- package/lib/node/serve.d.ts +8 -0
- package/lib/node/serve.js +106 -0
- package/lib/orbit.d.ts +47 -0
- package/lib/orbit.js +44 -0
- package/lib/quiet-sqlite-warning.d.ts +1 -0
- package/lib/quiet-sqlite-warning.js +18 -0
- package/lib/store/blob-path.d.ts +6 -0
- package/lib/store/blob-path.js +12 -0
- package/lib/store/conformance.d.ts +52 -0
- package/lib/store/conformance.js +1449 -0
- package/lib/store/search-words.d.ts +10 -0
- package/lib/store/search-words.js +19 -0
- package/lib/store/types.d.ts +452 -0
- package/lib/store/types.js +34 -0
- package/llms.txt +63 -0
- package/package.json +109 -25
- package/src/cli/orbit.js +11 -658
- package/src/mcp-server.js +16 -876
- package/SKILL-ORBIT.md +0 -151
- package/build.mjs +0 -210
- package/dist/full/js/app.62905fcb.js +0 -952
- package/dist/full/js/app.62905fcb.js.map +0 -7
- package/dist/full/styles.4e60d824.css +0 -1
- package/docs/AGENT_PROTOCOL.md +0 -424
- package/docs/MCP_SETUP.md +0 -54
- package/docs/ORBIT_DISPATCH.md +0 -280
- package/docs/SS-Orbit-Dark.png +0 -0
- package/docs/SS-Orbit-Light.png +0 -0
- package/docs/mcp-client.example.json +0 -13
- package/docs/setup/orbit-init-wizard.md +0 -174
- package/public/apple-touch-icon.png +0 -0
- package/public/cursors/live_arrow.cur +0 -0
- package/public/cursors/live_link.cur +0 -0
- package/public/cursors/live_move.cur +0 -0
- package/public/cursors/live_select.cur +0 -0
- package/public/cursors/live_unavail.cur +0 -0
- package/public/favicon-32x32.png +0 -0
- package/public/fonts/Chakra_Petch/ChakraPetch-Bold.ttf +0 -0
- package/public/fonts/Chakra_Petch/ChakraPetch-BoldItalic.ttf +0 -0
- package/public/fonts/Chakra_Petch/ChakraPetch-Italic.ttf +0 -0
- package/public/fonts/Chakra_Petch/ChakraPetch-Light.ttf +0 -0
- package/public/fonts/Chakra_Petch/ChakraPetch-LightItalic.ttf +0 -0
- package/public/fonts/Chakra_Petch/ChakraPetch-Medium.ttf +0 -0
- package/public/fonts/Chakra_Petch/ChakraPetch-MediumItalic.ttf +0 -0
- package/public/fonts/Chakra_Petch/ChakraPetch-Regular.ttf +0 -0
- package/public/fonts/Chakra_Petch/ChakraPetch-SemiBold.ttf +0 -0
- package/public/fonts/Chakra_Petch/ChakraPetch-SemiBoldItalic.ttf +0 -0
- package/public/fonts/Chakra_Petch/OFL.txt +0 -93
- package/public/fonts/Inter/Inter-Italic-VariableFont_opsz,wght.ttf +0 -0
- package/public/fonts/Inter/Inter-VariableFont_opsz,wght.ttf +0 -0
- package/public/fonts/Inter/OFL.txt +0 -93
- package/public/fonts/Inter/README.txt +0 -118
- package/public/fonts/JetBrains_Mono/JetBrainsMono-Italic-VariableFont_wght.ttf +0 -0
- package/public/fonts/JetBrains_Mono/JetBrainsMono-VariableFont_wght.ttf +0 -0
- package/public/fonts/JetBrains_Mono/README.txt +0 -79
- package/public/fonts/OpenRing-Regular.ttf +0 -0
- package/public/fonts/Open_Sans/OpenSans-Italic-VariableFont_wdth,wght.ttf +0 -0
- package/public/fonts/Open_Sans/OpenSans-VariableFont_wdth,wght.ttf +0 -0
- package/public/fonts/Open_Sans/README.txt +0 -100
- package/public/fonts/Orbitron/OFL.txt +0 -93
- package/public/fonts/Orbitron/Orbitron-VariableFont_wght.ttf +0 -0
- package/public/fonts/Orbitron/README.txt +0 -68
- package/public/fonts/Rajdhani/OFL.txt +0 -93
- package/public/fonts/Rajdhani/Rajdhani-Bold.ttf +0 -0
- package/public/fonts/Rajdhani/Rajdhani-Light.ttf +0 -0
- package/public/fonts/Rajdhani/Rajdhani-Medium.ttf +0 -0
- package/public/fonts/Rajdhani/Rajdhani-Regular.ttf +0 -0
- package/public/fonts/Rajdhani/Rajdhani-SemiBold.ttf +0 -0
- package/public/fonts/runescape-uf.ttf +0 -0
- package/public/index.html +0 -769
- package/public/js/actor-labels.js +0 -65
- package/public/js/api.js +0 -39
- package/public/js/app.js +0 -45
- package/public/js/artifact-drawer.js +0 -79
- package/public/js/board-export.js +0 -161
- package/public/js/board-menu.js +0 -374
- package/public/js/card-actions.js +0 -545
- package/public/js/config.js +0 -20
- package/public/js/create-card.js +0 -190
- package/public/js/dom.js +0 -19
- package/public/js/drawer.js +0 -273
- package/public/js/font-preference.js +0 -229
- package/public/js/format.js +0 -433
- package/public/js/help-menu.js +0 -31
- package/public/js/icons.js +0 -16
- package/public/js/kanban.js +0 -694
- package/public/js/local-backend.js +0 -1015
- package/public/js/main.js +0 -161
- package/public/js/modal.js +0 -33
- package/public/js/motion-preference.js +0 -64
- package/public/js/panel.js +0 -58
- package/public/js/router.js +0 -134
- package/public/js/search.js +0 -56
- package/public/js/settings-tabs.js +0 -7
- package/public/js/settings.js +0 -1634
- package/public/js/sse.js +0 -159
- package/public/js/starscape.js +0 -332
- package/public/js/state.js +0 -129
- package/public/js/text-editing.js +0 -128
- package/public/js/theme-preference.js +0 -95
- package/public/js/ticket-detail.js +0 -1516
- package/public/js/ticket-typeahead.js +0 -49
- package/public/js/toast.js +0 -89
- package/public/js/topbar-notes.js +0 -155
- package/public/js/transport.js +0 -22
- package/public/js/typeahead.js +0 -206
- package/public/js/unread.js +0 -121
- package/public/js/update-check.js +0 -58
- package/public/js/url-routes.js +0 -94
- package/public/orbits-favicon.png +0 -0
- package/public/orbits-logo-bg-wide.png +0 -0
- package/public/orbits-logo-bg.png +0 -0
- package/public/orbits-logo.png +0 -0
- package/public/styles.css +0 -7709
- package/src/core/agent.js +0 -387
- package/src/core/agents-md.js +0 -109
- package/src/core/artifacts.js +0 -149
- package/src/core/attachments.js +0 -238
- package/src/core/auth.js +0 -85
- package/src/core/backups.js +0 -142
- package/src/core/board.js +0 -148
- package/src/core/boards.js +0 -409
- package/src/core/bootstrap.js +0 -170
- package/src/core/css-bundle.js +0 -30
- package/src/core/db.js +0 -315
- package/src/core/delete-board.js +0 -163
- package/src/core/dispatch.js +0 -1007
- package/src/core/events.js +0 -314
- package/src/core/http.js +0 -115
- package/src/core/migrate.js +0 -198
- package/src/core/paths.js +0 -55
- package/src/core/provision-repo-board.js +0 -119
- package/src/core/queries.js +0 -246
- package/src/core/registry.js +0 -211
- package/src/core/relations.js +0 -163
- package/src/core/review-verdicts.js +0 -138
- package/src/core/router.js +0 -556
- package/src/core/search.js +0 -183
- package/src/core/seed.js +0 -234
- package/src/core/snapshots.js +0 -692
- package/src/core/states.js +0 -167
- package/src/core/system-picker.js +0 -109
- package/src/core/tickets.js +0 -400
- package/src/core/util.js +0 -106
- package/src/core/version-check.js +0 -154
- package/src/mcp/orbit-client.js +0 -287
- package/src/server.js +0 -115
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
// Human-facing actor labels for ticket activity. The storage layer keeps
|
|
2
|
-
// compact/internal identifiers such as "local" and "local-agent"; the drawer
|
|
3
|
-
// should translate those into labels that explain who acted without exposing
|
|
4
|
-
// implementation details or blaming agent actions on the current user.
|
|
5
|
-
|
|
6
|
-
const INTERNAL_LOCAL_NAMES = new Set(["local", "local-owner", "owner"]);
|
|
7
|
-
const GENERIC_AGENT_NAMES = new Set(["agent", "local-agent", "orbit-agent"]);
|
|
8
|
-
const AGENT_COMMENT_KINDS = new Set(["agent_note", "checkpoint", "completion"]);
|
|
9
|
-
|
|
10
|
-
function clean(value) {
|
|
11
|
-
return String(value || "").trim();
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function humanizeIdentifier(value) {
|
|
15
|
-
const raw = clean(value);
|
|
16
|
-
if (!raw) return "";
|
|
17
|
-
return raw
|
|
18
|
-
.replace(/^@+/, "")
|
|
19
|
-
.replace(/[-_]+/g, " ")
|
|
20
|
-
.replace(/\s+/g, " ")
|
|
21
|
-
.trim()
|
|
22
|
-
.replace(/\b\w/g, (char) => char.toUpperCase());
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
function agentNameFrom({ actor, actorId } = {}) {
|
|
26
|
-
const name = clean(actor);
|
|
27
|
-
const id = clean(actorId);
|
|
28
|
-
const lowerName = name.toLowerCase();
|
|
29
|
-
const lowerId = id.toLowerCase();
|
|
30
|
-
|
|
31
|
-
if (name && !INTERNAL_LOCAL_NAMES.has(lowerName) && !GENERIC_AGENT_NAMES.has(lowerName)) {
|
|
32
|
-
return humanizeIdentifier(name);
|
|
33
|
-
}
|
|
34
|
-
if (id && !INTERNAL_LOCAL_NAMES.has(lowerId) && !GENERIC_AGENT_NAMES.has(lowerId)) {
|
|
35
|
-
return humanizeIdentifier(id);
|
|
36
|
-
}
|
|
37
|
-
return "";
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export function formatActorLabel({ actor, actorType, actorId } = {}) {
|
|
41
|
-
const type = clean(actorType).toLowerCase();
|
|
42
|
-
const name = clean(actor);
|
|
43
|
-
const lowerName = name.toLowerCase();
|
|
44
|
-
|
|
45
|
-
if (type === "agent") {
|
|
46
|
-
const agentName = agentNameFrom({ actor: name, actorId });
|
|
47
|
-
return agentName ? `Agent · ${agentName}` : "Agent";
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (!name || INTERNAL_LOCAL_NAMES.has(lowerName)) return "You";
|
|
51
|
-
return humanizeIdentifier(name);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function formatCommentAuthor(comment = {}) {
|
|
55
|
-
const kind = clean(comment.kind).toLowerCase();
|
|
56
|
-
const author = clean(comment.author);
|
|
57
|
-
const isAgentKind = AGENT_COMMENT_KINDS.has(kind) || (kind && kind !== "human_comment");
|
|
58
|
-
|
|
59
|
-
if (isAgentKind) {
|
|
60
|
-
const agentName = agentNameFrom({ actor: author });
|
|
61
|
-
return agentName ? `Agent · ${agentName}` : "Agent";
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
return formatActorLabel({ actor: author, actorType: "human" });
|
|
65
|
-
}
|
package/public/js/api.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// Network layer. `api()` is the single fetch wrapper used everywhere; it
|
|
2
|
-
// delegates raw I/O to transport.js (swappable per edition) and surfaces
|
|
3
|
-
// errors as toasts. Path helpers live here because they're shared by every
|
|
4
|
-
// caller regardless of transport.
|
|
5
|
-
|
|
6
|
-
import { state } from "./state.js";
|
|
7
|
-
import { toast } from "./toast.js";
|
|
8
|
-
import { request } from "./transport.js";
|
|
9
|
-
|
|
10
|
-
/** Bootstrap for the currently selected board (server opens the right DB). */
|
|
11
|
-
export function bootstrapPath() {
|
|
12
|
-
const q = state.boardId
|
|
13
|
-
? `?board_id=${encodeURIComponent(state.boardId)}`
|
|
14
|
-
: state.boardSlug
|
|
15
|
-
? `?board=${encodeURIComponent(state.boardSlug)}`
|
|
16
|
-
: "";
|
|
17
|
-
return `/api/bootstrap${q}`;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Append board_id for ticket/state/entry routes when the path has no board prefix. */
|
|
21
|
-
export function withBoardQuery(path) {
|
|
22
|
-
if (!state.boardId || path.includes("board_id=")) return path;
|
|
23
|
-
const sep = path.includes("?") ? "&" : "?";
|
|
24
|
-
return `${path}${sep}board_id=${encodeURIComponent(state.boardId)}`;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export async function api(path, options = {}) {
|
|
28
|
-
try {
|
|
29
|
-
return await request({
|
|
30
|
-
method: options.method || "GET",
|
|
31
|
-
path,
|
|
32
|
-
body: options.body,
|
|
33
|
-
headers: options.headers
|
|
34
|
-
});
|
|
35
|
-
} catch (err) {
|
|
36
|
-
toast.error(err.payload?.error || err.message || "Request failed");
|
|
37
|
-
throw err;
|
|
38
|
-
}
|
|
39
|
-
}
|
package/public/js/app.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
// Bootstrap reload + top-level render. Extracted from main.js so feature
|
|
2
|
-
// modules can import `load` / `render` without pulling in the entry-point
|
|
3
|
-
// init wiring (which would create import cycles).
|
|
4
|
-
|
|
5
|
-
import { state, syncBoardSelection, currentBoard } from "./state.js";
|
|
6
|
-
import { api, bootstrapPath } from "./api.js";
|
|
7
|
-
import { renderBoard, renderBoardSelection } from "./kanban.js";
|
|
8
|
-
import { renderDetail } from "./ticket-detail.js";
|
|
9
|
-
import { closeMenuFlyouts, updateTopbarChips } from "./board-menu.js";
|
|
10
|
-
import { connectEventStream } from "./sse.js";
|
|
11
|
-
import { seedReadIfNeeded } from "./unread.js";
|
|
12
|
-
import { features } from "./config.js";
|
|
13
|
-
import { renderTopbarFocus } from "./topbar-notes.js";
|
|
14
|
-
|
|
15
|
-
let sseBoardId = null;
|
|
16
|
-
|
|
17
|
-
export async function load() {
|
|
18
|
-
closeMenuFlyouts();
|
|
19
|
-
state.data = await api(bootstrapPath());
|
|
20
|
-
syncBoardSelection();
|
|
21
|
-
// First-time-per-board seed so existing cards don't all flash unread.
|
|
22
|
-
// No-op once the seed flag is set for this board.
|
|
23
|
-
seedReadIfNeeded(state.boardId, state.data?.tickets || []);
|
|
24
|
-
await render();
|
|
25
|
-
if (features.sse && state.boardId !== sseBoardId) {
|
|
26
|
-
sseBoardId = state.boardId;
|
|
27
|
-
connectEventStream();
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export async function render() {
|
|
32
|
-
syncBoardSelection();
|
|
33
|
-
updateTopbarChips();
|
|
34
|
-
renderTopbarFocus(currentBoard());
|
|
35
|
-
renderBoard();
|
|
36
|
-
await renderDetail();
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export async function renderDetailOnly() {
|
|
40
|
-
syncBoardSelection();
|
|
41
|
-
updateTopbarChips();
|
|
42
|
-
renderTopbarFocus(currentBoard());
|
|
43
|
-
renderBoardSelection();
|
|
44
|
-
await renderDetail();
|
|
45
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import { api, withBoardQuery } from "./api.js";
|
|
2
|
-
import { escapeHtml, renderMarkdown } from "./format.js";
|
|
3
|
-
import { toast } from "./toast.js";
|
|
4
|
-
|
|
5
|
-
const backdrop = document.getElementById("artifactDrawerBackdrop");
|
|
6
|
-
const drawer = document.getElementById("artifactDrawer");
|
|
7
|
-
const titleEl = document.getElementById("artifactDrawerTitle");
|
|
8
|
-
const metaEl = document.getElementById("artifactDrawerMeta");
|
|
9
|
-
const bodyEl = document.getElementById("artifactDrawerBody");
|
|
10
|
-
const closeBtn = document.getElementById("artifactDrawerCloseBtn");
|
|
11
|
-
|
|
12
|
-
function setOpen(open) {
|
|
13
|
-
if (!drawer || !backdrop) return;
|
|
14
|
-
drawer.hidden = false;
|
|
15
|
-
backdrop.hidden = false;
|
|
16
|
-
requestAnimationFrame(() => {
|
|
17
|
-
drawer.classList.toggle("is-open", open);
|
|
18
|
-
backdrop.classList.toggle("is-visible", open);
|
|
19
|
-
});
|
|
20
|
-
if (!open) {
|
|
21
|
-
setTimeout(() => {
|
|
22
|
-
if (drawer.classList.contains("is-open")) return;
|
|
23
|
-
drawer.hidden = true;
|
|
24
|
-
backdrop.hidden = true;
|
|
25
|
-
if (bodyEl) bodyEl.innerHTML = "";
|
|
26
|
-
}, 260);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function closeArtifactDrawer() {
|
|
31
|
-
setOpen(false);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function localPathHint(path, error) {
|
|
35
|
-
const code = error?.payload?.error || error?.message || "Unable to load artifact";
|
|
36
|
-
const parts = [escapeHtml(code)];
|
|
37
|
-
if (code === "artifact_path_outside_allowed_roots" || code === "artifact_not_found") {
|
|
38
|
-
parts.push("<br><br>The Orbit server could not read that artifact path. If this webapp is hosted on another machine, the file needs to be stored on the hosted Orbit server or linked as a server-readable/repo-relative path.");
|
|
39
|
-
}
|
|
40
|
-
const mntDrive = String(path || "").match(/^\/mnt\/([a-z])\/(.+)$/i);
|
|
41
|
-
const slashDrive = String(path || "").match(/^\/([a-z])\/Users\/(.+)$/i);
|
|
42
|
-
if (mntDrive) {
|
|
43
|
-
const drive = mntDrive[1].toUpperCase();
|
|
44
|
-
parts.push(`<br><br>Windows spelling for this WSL path: <code>${escapeHtml(`${drive}:\\${mntDrive[2].replace(/\//g, "\\")}`)}</code>`);
|
|
45
|
-
} else if (slashDrive) {
|
|
46
|
-
const drive = slashDrive[1].toUpperCase();
|
|
47
|
-
parts.push(`<br><br>Windows spelling for this path: <code>${escapeHtml(`${drive}:\\Users\\${slashDrive[2].replace(/\//g, "\\")}`)}</code>`);
|
|
48
|
-
}
|
|
49
|
-
return parts.join("");
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export async function openArtifactDrawer({ ticketId, path, title = "Linked artifact" }) {
|
|
53
|
-
if (!ticketId || !path) return false;
|
|
54
|
-
if (!drawer || !bodyEl || !titleEl || !metaEl) return false;
|
|
55
|
-
titleEl.textContent = title;
|
|
56
|
-
metaEl.textContent = path;
|
|
57
|
-
bodyEl.innerHTML = `<p class="artifact-drawer-loading">Loading artifact…</p>`;
|
|
58
|
-
setOpen(true);
|
|
59
|
-
|
|
60
|
-
try {
|
|
61
|
-
const result = await api(
|
|
62
|
-
withBoardQuery(`/api/tickets/${encodeURIComponent(ticketId)}/artifacts/markdown?path=${encodeURIComponent(path)}`),
|
|
63
|
-
);
|
|
64
|
-
titleEl.textContent = title;
|
|
65
|
-
metaEl.textContent = result.path || path;
|
|
66
|
-
bodyEl.innerHTML = `<article class="markdown-body artifact-markdown-body">${renderMarkdown(result.content || "") || `<p>${escapeHtml("Empty artifact.")}</p>`}</article>`;
|
|
67
|
-
return true;
|
|
68
|
-
} catch (err) {
|
|
69
|
-
bodyEl.innerHTML = `<p class="artifact-drawer-error">${localPathHint(path, err)}</p>`;
|
|
70
|
-
toast.error("Artifact could not be opened");
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
closeBtn?.addEventListener("click", closeArtifactDrawer);
|
|
76
|
-
backdrop?.addEventListener("click", closeArtifactDrawer);
|
|
77
|
-
document.addEventListener("keydown", (event) => {
|
|
78
|
-
if (event.key === "Escape" && drawer && !drawer.hidden) closeArtifactDrawer();
|
|
79
|
-
});
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
// Board snapshot export: builds a ZIP of every board's `.orbit.json` and
|
|
2
|
-
// triggers a browser download. Extracted from board-menu.js so both the Board
|
|
3
|
-
// flyout's "Export All" and Settings → Appearance's "Back up all boards" can
|
|
4
|
-
// reuse the exact same archive without importing the heavier board-menu module
|
|
5
|
-
// (which would create a settings ↔ board-menu import cycle). Depends only on
|
|
6
|
-
// state/api/toast, so it stays safe to import from anywhere.
|
|
7
|
-
|
|
8
|
-
import { state } from "./state.js";
|
|
9
|
-
import { api } from "./api.js";
|
|
10
|
-
import { toast } from "./toast.js";
|
|
11
|
-
|
|
12
|
-
const crcTable = Array.from({ length: 256 }, (_, index) => {
|
|
13
|
-
let crc = index;
|
|
14
|
-
for (let bit = 0; bit < 8; bit += 1) {
|
|
15
|
-
crc = crc & 1 ? 0xedb88320 ^ (crc >>> 1) : crc >>> 1;
|
|
16
|
-
}
|
|
17
|
-
return crc >>> 0;
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
function crc32(bytes) {
|
|
21
|
-
let crc = 0xffffffff;
|
|
22
|
-
for (const byte of bytes) crc = crcTable[(crc ^ byte) & 0xff] ^ (crc >>> 8);
|
|
23
|
-
return (crc ^ 0xffffffff) >>> 0;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function writeUint16(bytes, value) {
|
|
27
|
-
bytes.push(value & 0xff, (value >>> 8) & 0xff);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function writeUint32(bytes, value) {
|
|
31
|
-
bytes.push(value & 0xff, (value >>> 8) & 0xff, (value >>> 16) & 0xff, (value >>> 24) & 0xff);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function zipDateTime(date = new Date()) {
|
|
35
|
-
return {
|
|
36
|
-
time:
|
|
37
|
-
((date.getHours() & 0x1f) << 11) |
|
|
38
|
-
((date.getMinutes() & 0x3f) << 5) |
|
|
39
|
-
(Math.floor(date.getSeconds() / 2) & 0x1f),
|
|
40
|
-
date:
|
|
41
|
-
(((date.getFullYear() - 1980) & 0x7f) << 9) |
|
|
42
|
-
(((date.getMonth() + 1) & 0xf) << 5) |
|
|
43
|
-
(date.getDate() & 0x1f)
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function createZip(files) {
|
|
48
|
-
const encoder = new TextEncoder();
|
|
49
|
-
const localParts = [];
|
|
50
|
-
const centralParts = [];
|
|
51
|
-
let offset = 0;
|
|
52
|
-
const timestamp = zipDateTime();
|
|
53
|
-
|
|
54
|
-
files.forEach((file) => {
|
|
55
|
-
const nameBytes = encoder.encode(file.name);
|
|
56
|
-
const dataBytes = encoder.encode(file.content);
|
|
57
|
-
const checksum = crc32(dataBytes);
|
|
58
|
-
const localHeader = [];
|
|
59
|
-
writeUint32(localHeader, 0x04034b50);
|
|
60
|
-
writeUint16(localHeader, 20);
|
|
61
|
-
writeUint16(localHeader, 0x0800);
|
|
62
|
-
writeUint16(localHeader, 0);
|
|
63
|
-
writeUint16(localHeader, timestamp.time);
|
|
64
|
-
writeUint16(localHeader, timestamp.date);
|
|
65
|
-
writeUint32(localHeader, checksum);
|
|
66
|
-
writeUint32(localHeader, dataBytes.length);
|
|
67
|
-
writeUint32(localHeader, dataBytes.length);
|
|
68
|
-
writeUint16(localHeader, nameBytes.length);
|
|
69
|
-
writeUint16(localHeader, 0);
|
|
70
|
-
localParts.push(new Uint8Array(localHeader), nameBytes, dataBytes);
|
|
71
|
-
|
|
72
|
-
const centralHeader = [];
|
|
73
|
-
writeUint32(centralHeader, 0x02014b50);
|
|
74
|
-
writeUint16(centralHeader, 20);
|
|
75
|
-
writeUint16(centralHeader, 20);
|
|
76
|
-
writeUint16(centralHeader, 0x0800);
|
|
77
|
-
writeUint16(centralHeader, 0);
|
|
78
|
-
writeUint16(centralHeader, timestamp.time);
|
|
79
|
-
writeUint16(centralHeader, timestamp.date);
|
|
80
|
-
writeUint32(centralHeader, checksum);
|
|
81
|
-
writeUint32(centralHeader, dataBytes.length);
|
|
82
|
-
writeUint32(centralHeader, dataBytes.length);
|
|
83
|
-
writeUint16(centralHeader, nameBytes.length);
|
|
84
|
-
writeUint16(centralHeader, 0);
|
|
85
|
-
writeUint16(centralHeader, 0);
|
|
86
|
-
writeUint16(centralHeader, 0);
|
|
87
|
-
writeUint16(centralHeader, 0);
|
|
88
|
-
writeUint32(centralHeader, 0);
|
|
89
|
-
writeUint32(centralHeader, offset);
|
|
90
|
-
centralParts.push(new Uint8Array(centralHeader), nameBytes);
|
|
91
|
-
|
|
92
|
-
offset += localHeader.length + nameBytes.length + dataBytes.length;
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
const centralOffset = offset;
|
|
96
|
-
const centralSize = centralParts.reduce((sum, part) => sum + part.length, 0);
|
|
97
|
-
const endHeader = [];
|
|
98
|
-
writeUint32(endHeader, 0x06054b50);
|
|
99
|
-
writeUint16(endHeader, 0);
|
|
100
|
-
writeUint16(endHeader, 0);
|
|
101
|
-
writeUint16(endHeader, files.length);
|
|
102
|
-
writeUint16(endHeader, files.length);
|
|
103
|
-
writeUint32(endHeader, centralSize);
|
|
104
|
-
writeUint32(endHeader, centralOffset);
|
|
105
|
-
writeUint16(endHeader, 0);
|
|
106
|
-
|
|
107
|
-
return new Blob([...localParts, ...centralParts, new Uint8Array(endHeader)], { type: "application/zip" });
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export function downloadBlob(filename, blob) {
|
|
111
|
-
const url = URL.createObjectURL(blob);
|
|
112
|
-
const anchor = document.createElement("a");
|
|
113
|
-
anchor.href = url;
|
|
114
|
-
anchor.download = filename;
|
|
115
|
-
document.body.append(anchor);
|
|
116
|
-
anchor.click();
|
|
117
|
-
anchor.remove();
|
|
118
|
-
URL.revokeObjectURL(url);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function safeExportName(board, usedNames) {
|
|
122
|
-
const base = String(board?.slug || board?.name || board?.id || "board")
|
|
123
|
-
.trim()
|
|
124
|
-
.toLowerCase()
|
|
125
|
-
.replace(/[^a-z0-9._-]+/g, "-")
|
|
126
|
-
.replace(/^-+|-+$/g, "") || "board";
|
|
127
|
-
let name = `${base}.orbit.json`;
|
|
128
|
-
let suffix = 2;
|
|
129
|
-
while (usedNames.has(name)) {
|
|
130
|
-
name = `${base}-${suffix}.orbit.json`;
|
|
131
|
-
suffix += 1;
|
|
132
|
-
}
|
|
133
|
-
usedNames.add(name);
|
|
134
|
-
return name;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/** Export every board the actor can see as a single ZIP of `.orbit.json`
|
|
138
|
-
* snapshots. Resolves `true` once the download starts, `false` if there are
|
|
139
|
-
* no boards. Throws on a failed export request so callers can surface it. */
|
|
140
|
-
export async function exportAllBoards({ includeAttachments = false } = {}) {
|
|
141
|
-
const boards = state.data?.boards || [];
|
|
142
|
-
if (!boards.length) {
|
|
143
|
-
toast.error("No boards to export");
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
const suffix = includeAttachments ? "?include_attachments=true" : "";
|
|
147
|
-
const usedNames = new Set();
|
|
148
|
-
const files = [];
|
|
149
|
-
for (const board of boards) {
|
|
150
|
-
const snapshot = await api(`/api/boards/${encodeURIComponent(board.id)}/export${suffix}`);
|
|
151
|
-
files.push({
|
|
152
|
-
name: safeExportName(board, usedNames),
|
|
153
|
-
content: JSON.stringify(snapshot, null, 2)
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
const archive = createZip(files);
|
|
157
|
-
const date = new Date().toISOString().slice(0, 10);
|
|
158
|
-
downloadBlob(`orbit-boards-${date}${includeAttachments ? ".with-images" : ""}.zip`, archive);
|
|
159
|
-
toast.success(`Exported ${files.length} board${files.length === 1 ? "" : "s"}`);
|
|
160
|
-
return true;
|
|
161
|
-
}
|