octocode-cli 1.5.1 → 1.5.3
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/README.md +28 -9
- package/out/chunks/chunk-375ZNU3A.js +317 -0
- package/out/chunks/{chunk-V64AXUWB.js → chunk-AYILFPX4.js} +1 -1
- package/out/chunks/chunk-BRHVQB64.js +10 -0
- package/out/chunks/{command-help-specs-JZXVSLZ5.js → chunk-KWJUBVXJ.js} +1 -1
- package/out/chunks/chunk-OMXWZJBJ.js +100 -0
- package/out/chunks/command-help-specs-RVJK6V6M.js +8 -0
- package/out/chunks/commands-JFDCC4Q7.js +8 -0
- package/out/chunks/{help-P7TCOYAJ.js → help-H3WGUJO7.js} +1 -1
- package/out/chunks/main-help-BUTDD4IR.js +10 -0
- package/out/chunks/{spinner-URV2OX6O.js → spinner-DXD4JQIU.js} +1 -1
- package/out/chunks/tool-command-L6PVHUNS.js +8 -0
- package/out/octocode-cli.js +1 -1
- package/package.json +2 -2
- package/skills/octocode-brainstorming/scripts/tavily-search.mjs +1 -10
- package/skills/octocode-chrome-devtools/scripts/cdp-runner.mjs +0 -2
- package/skills/octocode-chrome-devtools/scripts/cdp-sandbox.mjs +1 -5
- package/skills/octocode-chrome-devtools/scripts/cdp-template.mjs +1 -10
- package/skills/octocode-chrome-devtools/scripts/open-browser.mjs +0 -3
- package/skills/octocode-chrome-devtools/scripts/sourcemap-resolver.mjs +1 -4
- package/skills/octocode-chrome-devtools/scripts/undercover.mjs +0 -2
- package/skills/octocode-engineer/SKILL.md +7 -33
- package/skills/octocode-engineer/references/cli-reference.md +5 -11
- package/skills/octocode-engineer/references/externals.md +0 -4
- package/skills/octocode-engineer/references/quality-indicators.md +10 -50
- package/skills/octocode-engineer/references/tool-workflows.md +10 -13
- package/skills/octocode-engineer/src/analysis/dependency-summary.test.ts +2 -2
- package/skills/octocode-engineer/src/ast/metrics.test.ts +2 -2
- package/skills/octocode-engineer/src/ast/search-main.ts +2 -15
- package/skills/octocode-engineer/src/ast/search.ts +1 -7
- package/skills/octocode-engineer/src/ast/tree-sitter.test.ts +4 -4
- package/skills/octocode-engineer/src/ast/tree-sitter.ts +2 -2
- package/skills/octocode-engineer/src/collectors/chains.ts +3 -10
- package/skills/octocode-engineer/src/collectors/prototype-pollution.ts +3 -3
- package/skills/octocode-engineer/src/collectors/security.ts +3 -3
- package/skills/octocode-engineer/src/common/ensure-deps.ts +3 -20
- package/skills/octocode-engineer/src/detectors/code-quality.ts +0 -1
- package/skills/octocode-engineer/src/index.test.ts +1 -1
- package/skills/octocode-engineer/src/index.ts +1 -11
- package/skills/octocode-engineer/src/pipeline/affected.ts +2 -7
- package/skills/octocode-engineer/src/pipeline/baseline.ts +2 -8
- package/skills/octocode-engineer/src/pipeline/cache.ts +2 -2
- package/skills/octocode-engineer/src/pipeline/config-loader.test.ts +1 -2
- package/skills/octocode-engineer/src/pipeline/config-loader.ts +0 -9
- package/skills/octocode-engineer/src/pipeline/create-options.ts +2 -15
- package/skills/octocode-engineer/src/pipeline/reporters.ts +2 -12
- package/skills/octocode-engineer/src/reporting/summary-md.test.ts +2 -2
- package/skills/octocode-engineer/src/run.ts +1 -7
- package/skills/octocode-engineer/src/types/constants.ts +0 -5
- package/skills/octocode-engineer/src/types/core.ts +0 -5
- package/skills/octocode-news/eslint.config.mjs +1 -6
- package/skills/octocode-news/src/rss-core.ts +2 -4
- package/skills/octocode-research/ecosystem.config.cjs +0 -31
- package/skills/octocode-research/package.json +1 -1
- package/skills/octocode-research/scripts/server.js +272 -230
- package/skills/octocode-research/src/__tests__/integration/circuitBreaker.test.ts +0 -24
- package/skills/octocode-research/src/__tests__/integration/routes.test.ts +0 -10
- package/skills/octocode-research/src/__tests__/integration/serverLifecycle.test.ts +5 -22
- package/skills/octocode-research/src/__tests__/integration/toolsRoutes.test.ts +0 -27
- package/skills/octocode-research/src/__tests__/unit/circuitBreaker.test.ts +0 -29
- package/skills/octocode-research/src/__tests__/unit/errorHandler.test.ts +1 -12
- package/skills/octocode-research/src/__tests__/unit/httpPreprocess.test.ts +1 -9
- package/skills/octocode-research/src/__tests__/unit/logger.test.ts +0 -7
- package/skills/octocode-research/src/__tests__/unit/queryParser.test.ts +1 -7
- package/skills/octocode-research/src/__tests__/unit/responseBuilder.test.ts +0 -11
- package/skills/octocode-research/src/__tests__/unit/retry.test.ts +1 -18
- package/skills/octocode-research/src/__tests__/unit/schemas.test.ts +2 -25
- package/skills/octocode-research/src/index.ts +0 -27
- package/skills/octocode-research/src/mcpCache.ts +3 -18
- package/skills/octocode-research/src/middleware/errorHandler.ts +1 -4
- package/skills/octocode-research/src/middleware/logger.ts +1 -6
- package/skills/octocode-research/src/middleware/queryParser.ts +3 -22
- package/skills/octocode-research/src/routes/github.ts +0 -11
- package/skills/octocode-research/src/routes/local.ts +0 -12
- package/skills/octocode-research/src/routes/lsp.ts +1 -10
- package/skills/octocode-research/src/routes/package.ts +0 -2
- package/skills/octocode-research/src/routes/prompts.ts +2 -32
- package/skills/octocode-research/src/routes/tools.ts +12 -177
- package/skills/octocode-research/src/server-init.ts +0 -32
- package/skills/octocode-research/src/server.ts +8 -37
- package/skills/octocode-research/src/types/errorGuards.ts +0 -15
- package/skills/octocode-research/src/types/guards.ts +6 -27
- package/skills/octocode-research/src/types/mcp.ts +1 -8
- package/skills/octocode-research/src/types/responses.ts +0 -15
- package/skills/octocode-research/src/utils/asyncTimeout.ts +1 -63
- package/skills/octocode-research/src/utils/circuitBreaker.ts +43 -166
- package/skills/octocode-research/src/utils/colors.ts +3 -17
- package/skills/octocode-research/src/utils/errorQueue.ts +6 -28
- package/skills/octocode-research/src/utils/logger.ts +11 -93
- package/skills/octocode-research/src/utils/resilience.ts +22 -77
- package/skills/octocode-research/src/utils/responseBuilder.ts +26 -78
- package/skills/octocode-research/src/utils/responseFactory.ts +0 -7
- package/skills/octocode-research/src/utils/responseParser.ts +11 -59
- package/skills/octocode-research/src/utils/retry.ts +12 -75
- package/skills/octocode-research/src/utils/routeFactory.ts +10 -61
- package/skills/octocode-research/src/utils/url.ts +0 -5
- package/skills/octocode-research/src/validation/httpPreprocess.ts +15 -61
- package/skills/octocode-research/src/validation/schemas.ts +14 -101
- package/skills/octocode-research/src/validation/toolCallSchema.ts +5 -65
- package/skills/octocode-research/tsdown.config.ts +2 -7
- package/skills/octocode-search-skill/SKILL.md +9 -2
- package/skills/octocode-search-skill/references/discovery-surfaces.md +2 -1
- package/skills/octocode-slides/scripts/navbridge.js +1 -14
- package/skills/octocode-slides/scripts/presenter.js +2 -61
- package/skills/octocode-stats/scripts/build_dashboard.mjs +1 -19
- package/out/chunks/chunk-7476PETK.js +0 -309
- package/out/chunks/chunk-OQBJTZWK.js +0 -60
- package/out/chunks/chunk-UCZCF3BQ.js +0 -9
- package/out/chunks/commands-XBFPLHSQ.js +0 -8
- package/out/chunks/main-help-ULF5PAQY.js +0 -10
- package/out/chunks/tool-command-M6VA7P2F.js +0 -8
- package/skills/octocode-research/AGENTS.md +0 -349
|
@@ -15,28 +15,23 @@ export default defineConfig({
|
|
|
15
15
|
target: 'node20',
|
|
16
16
|
platform: 'node',
|
|
17
17
|
|
|
18
|
-
// Bundle ALL dependencies for standalone execution
|
|
19
18
|
noExternal: [/.*/],
|
|
20
19
|
|
|
21
|
-
// Keep Node.js built-ins and native modules external
|
|
22
20
|
external: [
|
|
23
21
|
...builtinModules,
|
|
24
22
|
...builtinModules.map((m) => `node:${m}`),
|
|
25
23
|
],
|
|
26
24
|
|
|
27
|
-
// Code splitting disabled for standalone scripts
|
|
28
25
|
splitting: false,
|
|
29
26
|
|
|
30
27
|
treeshake: true,
|
|
31
28
|
minify: true,
|
|
32
|
-
shims: true,
|
|
33
|
-
dts: true,
|
|
29
|
+
shims: true,
|
|
30
|
+
dts: true,
|
|
34
31
|
sourcemap: false,
|
|
35
32
|
|
|
36
|
-
// Output as server.js
|
|
37
33
|
outExtensions: () => ({ js: '.js' }),
|
|
38
34
|
|
|
39
|
-
// Shebang for direct execution
|
|
40
35
|
banner: '#!/usr/bin/env node',
|
|
41
36
|
|
|
42
37
|
define: {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: octocode-search-skill
|
|
3
|
-
description: Use this skill when the user asks to find, evaluate, preview, install, rate, review, score, improve, refactor, or synthesize Agent Skills (the `SKILL.md` folder format) across GitHub, local skill folders, and skill marketplaces. Covers searching for a skill for a task, deep-diving a candidate, installing one or more skills into one or more agents at user or project scope, rating or reviewing an existing SKILL.md, refactoring a skill, or creating a new local skill from researched patterns. Do NOT activate for general package search (npm, PyPI, cargo), web search, or code research not involving SKILL.md files.
|
|
3
|
+
description: Use this skill when the user asks to find, evaluate, preview, install, rate, review, score, improve, refactor, or synthesize Agent Skills (the `SKILL.md` folder format) across GitHub, local skill folders, and skill marketplaces. Covers searching for a skill for a task, deep-diving a candidate, installing one or more skills into one or more agents at user or project scope, rating or reviewing an existing SKILL.md, refactoring a skill, or creating a new local skill from researched patterns. Do NOT activate for general package search (npm, PyPI, cargo), general (non-skill) web search, or code research not involving SKILL.md files.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Octocode Search Skill
|
|
@@ -52,6 +52,7 @@ Use Octocode MCP for all research — locally and externally — and let user in
|
|
|
52
52
|
- Lead GitHub when the user is shopping for a skill, comparing options, or asking about something not present locally.
|
|
53
53
|
- Read code or files: `localGetFileContent` or `githubGetFileContent`.
|
|
54
54
|
- Download a remote skill folder before writing it locally: `githubGetFileContent(type="directory")` or `githubCloneRepo`.
|
|
55
|
+
- Web search: for every PUBLIC skill query, MUST also run the runtime's web search tool (e.g. `WebSearch`) in parallel with Octocode/GitHub and the skills.sh API. It catches skills surfaced in articles, awesome-lists, release notes, and registries outside the known set. Treat web-only mentions as LEADS, not recommendations — always resolve the real `(owner/repo, path-to-SKILL.md)` and confirm the actual `SKILL.md` via Octocode (`githubGetFileContent`) before recommending. Skip only for local-only or org/private scopes (Octocode tools only there).
|
|
55
56
|
|
|
56
57
|
Fallbacks:
|
|
57
58
|
|
|
@@ -92,6 +93,12 @@ Set depth before searching:
|
|
|
92
93
|
- Improve, rate, or create request: inspect the target skill, adjacent local examples, and `references/agent-skills-guide.md` before writing.
|
|
93
94
|
- Weak results: broaden once, then report the gap and the next best action.
|
|
94
95
|
|
|
96
|
+
For every public skill query, fan out across three surfaces IN PARALLEL, then merge and dedupe by `(owner/repo, skill name)`:
|
|
97
|
+
|
|
98
|
+
1. Octocode/GitHub — code and path search for `SKILL.md` (see "Useful GitHub patterns").
|
|
99
|
+
2. skills.sh Registry API — install-ranked candidates (see "Skills.sh Registry API").
|
|
100
|
+
3. Web search — runtime web search tool (e.g. `WebSearch`) for the topic + "agent skill"/"claude skill"/"SKILL.md", to catch skills outside the known registries. Confirm each web lead's real `SKILL.md` via Octocode before recommending.
|
|
101
|
+
|
|
95
102
|
Search angles:
|
|
96
103
|
|
|
97
104
|
- Name: exact phrase, lowercase, hyphenated folder name, aliases.
|
|
@@ -112,7 +119,7 @@ Useful GitHub patterns:
|
|
|
112
119
|
|
|
113
120
|
### Skills.sh Registry API
|
|
114
121
|
|
|
115
|
-
MUST run this in parallel with GitHub/Octocode search for every public skill query. MUST NOT use for org-specific or private searches — use Octocode tools only for those.
|
|
122
|
+
MUST run this in parallel with GitHub/Octocode search AND web search for every public skill query (the three-surface fan-out above). MUST NOT use for org-specific or private searches — use Octocode tools only for those.
|
|
116
123
|
|
|
117
124
|
```bash
|
|
118
125
|
curl 'https://www.skills.sh/api/search?q={{SEARCH_KEY}}&limit=100' \
|
|
@@ -6,7 +6,8 @@ Use when the user wants to shop for skills beyond raw GitHub code search — mar
|
|
|
6
6
|
|
|
7
7
|
| User goal | Best first surface |
|
|
8
8
|
|-----------|--------------------|
|
|
9
|
-
| "Search skills by keyword or topic" | skills.sh Registry API (`/api/search?q=...`) — sort by `installs` |
|
|
9
|
+
| "Search skills by keyword or topic" | skills.sh Registry API (`/api/search?q=...`) — sort by `installs` — run in parallel with GitHub/Octocode + web search |
|
|
10
|
+
| "Find skills mentioned in articles / awesome-lists / outside known registries" | Runtime web search tool (e.g. `WebSearch`): topic + "agent skill"/"claude skill"/"SKILL.md"; confirm each lead's real `SKILL.md` via Octocode |
|
|
10
11
|
| "Is skill X published / battle-tested?" | `https://www.skills.sh/<owner>/<repo>/<skill-name>` |
|
|
11
12
|
| "What are the most-installed skills right now?" | `https://www.skills.sh` leaderboard |
|
|
12
13
|
| "Find a Claude Code plugin" | `claude-plugins.dev` (REST + UI) |
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* Each slide includes: <script src="../js/navbridge.js"></script>
|
|
11
11
|
*/
|
|
12
12
|
(function () {
|
|
13
|
-
if (window.parent === window) return;
|
|
13
|
+
if (window.parent === window) return;
|
|
14
14
|
|
|
15
15
|
var NAV_KEYS = {
|
|
16
16
|
ArrowLeft: 1, ArrowRight: 1, ArrowUp: 1, ArrowDown: 1,
|
|
@@ -50,24 +50,11 @@
|
|
|
50
50
|
e.preventDefault();
|
|
51
51
|
}, true);
|
|
52
52
|
|
|
53
|
-
// Forward mouse activity so the parent HUD wakes back up
|
|
54
53
|
document.addEventListener('mousemove', function () {
|
|
55
54
|
try { window.parent.postMessage({ type: 'octocode-slides:activity' }, '*'); }
|
|
56
55
|
catch (_) {}
|
|
57
56
|
}, { passive: true });
|
|
58
57
|
|
|
59
|
-
// ── Step-animation back-channel ─────────────────────────────────────────
|
|
60
|
-
// The parent forwards nav keys here (instead of navigating immediately) so
|
|
61
|
-
// animation.js gets first refusal on each keystroke, even when the parent
|
|
62
|
-
// window has focus. We dispatch a synthetic keydown on the slide's document:
|
|
63
|
-
// • animation.js (capture, registered first) intercepts — if a step is
|
|
64
|
-
// pending it calls stopImmediatePropagation, navbridge's own listener
|
|
65
|
-
// never fires, no postMessage goes back, parent stays on this slide.
|
|
66
|
-
// • If animation.js has nothing left to consume the event falls through to
|
|
67
|
-
// navbridge's keydown listener, which posts back to the parent, and the
|
|
68
|
-
// parent's message handler calls handleKey(passthrough:true) → navigate.
|
|
69
|
-
// Slides without animation.js: the synthetic event reaches navbridge's
|
|
70
|
-
// listener directly and posts back immediately — no delay, no hang.
|
|
71
58
|
window.addEventListener('message', function (event) {
|
|
72
59
|
var data = event.data;
|
|
73
60
|
if (!data || data.type !== 'octocode-slides:key' || !data.key) return;
|
|
@@ -1,32 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Octocode Slides — Presenter View
|
|
3
|
-
*
|
|
4
|
-
* Press P in the generated deck shell to open the presenter popup.
|
|
5
|
-
*
|
|
6
|
-
* The popup shows:
|
|
7
|
-
* - Current slide live preview (scaled iframe)
|
|
8
|
-
* - Next slide live preview (scaled iframe)
|
|
9
|
-
* - Speaker notes
|
|
10
|
-
* - Running timer (persisted across page refreshes via localStorage)
|
|
11
|
-
* - Jump-to-slide control (updates the main deck window)
|
|
12
|
-
*
|
|
13
|
-
* Requires same-origin serving (npx serve works; file:// does not).
|
|
14
|
-
* The default scripts/base.html template already loads and wires this file;
|
|
15
|
-
* custom index.html files should copy that integration instead of inventing
|
|
16
|
-
* a second keyboard handler.
|
|
17
|
-
*
|
|
18
|
-
* Expected call site in index.html:
|
|
19
|
-
*
|
|
20
|
-
* initPresenter(
|
|
21
|
-
* () => stage.querySelector('.slide-frame[data-active]'),
|
|
22
|
-
* playable,
|
|
23
|
-
* () => current
|
|
24
|
-
* );
|
|
25
|
-
*/
|
|
26
1
|
function initPresenter(getActiveFrame, playable, getCurrentIndex) {
|
|
27
|
-
// ── localStorage key — scoped to this deck (title + pathname) ───────────
|
|
28
|
-
// Survives page refreshes on localhost so the timer keeps running while
|
|
29
|
-
// you edit slides. Cleared on "Reset timer" or when the deck changes.
|
|
30
2
|
var LS_KEY = 'octocode-slides:timer:' +
|
|
31
3
|
(document.title || 'deck') + ':' + location.pathname;
|
|
32
4
|
|
|
@@ -35,7 +7,6 @@ function initPresenter(getActiveFrame, playable, getCurrentIndex) {
|
|
|
35
7
|
var timerRef = null;
|
|
36
8
|
var startTime = null;
|
|
37
9
|
|
|
38
|
-
// ── Restore timer across page refreshes ─────────────────────────────────
|
|
39
10
|
(function restoreTimer() {
|
|
40
11
|
try {
|
|
41
12
|
var saved = localStorage.getItem(LS_KEY);
|
|
@@ -49,12 +20,6 @@ function initPresenter(getActiveFrame, playable, getCurrentIndex) {
|
|
|
49
20
|
} catch (_) {}
|
|
50
21
|
})();
|
|
51
22
|
|
|
52
|
-
// ── Popup HTML ───────────────────────────────────────────────────────────
|
|
53
|
-
// Layout (4-row grid):
|
|
54
|
-
// topbar — slide name (left) + running timer (right)
|
|
55
|
-
// previews — current slide iframe + next slide iframe (two columns)
|
|
56
|
-
// notes — scrollable speaker notes (fills remaining height)
|
|
57
|
-
// bottom — jump-to-slide input · Reset timer · Close
|
|
58
23
|
var POPUP_HTML =
|
|
59
24
|
'<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8">' +
|
|
60
25
|
'<title>Presenter View</title><style>' +
|
|
@@ -133,7 +98,6 @@ function initPresenter(getActiveFrame, playable, getCurrentIndex) {
|
|
|
133
98
|
'</div>' +
|
|
134
99
|
|
|
135
100
|
'<script>' +
|
|
136
|
-
// Scale preview iframes to fill their boxes (slides are 1280×720)
|
|
137
101
|
'function updateScale(){' +
|
|
138
102
|
' ["curr","next"].forEach(function(id){' +
|
|
139
103
|
' var box=document.getElementById(id+"-box");' +
|
|
@@ -146,26 +110,21 @@ function initPresenter(getActiveFrame, playable, getCurrentIndex) {
|
|
|
146
110
|
'}' +
|
|
147
111
|
'window.addEventListener("resize",updateScale);' +
|
|
148
112
|
|
|
149
|
-
// Receive state updates from the deck window
|
|
150
113
|
'window.addEventListener("message",function(e){' +
|
|
151
114
|
' var d=e.data;if(!d||d.type!=="octocode-slides:presenter-update")return;' +
|
|
152
115
|
|
|
153
|
-
// Notes
|
|
154
116
|
' var nEl=document.getElementById("notes");' +
|
|
155
117
|
' if(d.notes){nEl.textContent=d.notes;nEl.className=""}' +
|
|
156
118
|
' else{nEl.textContent="(no speaker notes)";nEl.className="empty"}' +
|
|
157
119
|
|
|
158
|
-
// Slide name
|
|
159
120
|
' document.getElementById("slide-name").textContent=d.name||"\u2014";' +
|
|
160
121
|
|
|
161
|
-
// Jump control
|
|
162
122
|
' if(typeof d.totalSlides==="number"){' +
|
|
163
123
|
' document.getElementById("jump-total").textContent="/ "+d.totalSlides;' +
|
|
164
124
|
' document.getElementById("jump-input").max=d.totalSlides;' +
|
|
165
125
|
' document.getElementById("jump-input").value=(d.currentIndex||0)+1;' +
|
|
166
126
|
' }' +
|
|
167
127
|
|
|
168
|
-
// Current slide preview
|
|
169
128
|
' var cBox=document.getElementById("curr-box");' +
|
|
170
129
|
' if(d.currUrl){' +
|
|
171
130
|
' var cf=cBox.querySelector("iframe");' +
|
|
@@ -175,7 +134,6 @@ function initPresenter(getActiveFrame, playable, getCurrentIndex) {
|
|
|
175
134
|
' }' +
|
|
176
135
|
' }' +
|
|
177
136
|
|
|
178
|
-
// Next slide preview
|
|
179
137
|
' var nBox=document.getElementById("next-box");' +
|
|
180
138
|
' if(d.nextUrl){' +
|
|
181
139
|
' var nf=nBox.querySelector("iframe");' +
|
|
@@ -188,7 +146,6 @@ function initPresenter(getActiveFrame, playable, getCurrentIndex) {
|
|
|
188
146
|
' }' +
|
|
189
147
|
'});' +
|
|
190
148
|
|
|
191
|
-
// Jump-to-slide: send index to opener so deck navigates
|
|
192
149
|
'document.getElementById("jump-input").addEventListener("change",function(){' +
|
|
193
150
|
' var n=parseInt(this.value,10);if(!isFinite(n))return;' +
|
|
194
151
|
' window.opener&&window.opener.postMessage(' +
|
|
@@ -201,10 +158,8 @@ function initPresenter(getActiveFrame, playable, getCurrentIndex) {
|
|
|
201
158
|
'document.getElementById("btn-close").onclick=function(){window.close()};' +
|
|
202
159
|
'<\/script></body></html>';
|
|
203
160
|
|
|
204
|
-
// ── Timer ───────────────────────────────────────────────────────────────
|
|
205
161
|
function startTimer() {
|
|
206
162
|
if (!startTime) startTime = Date.now() - elapsed * 1000;
|
|
207
|
-
// Persist start time so a page refresh doesn't reset the clock
|
|
208
163
|
try { localStorage.setItem(LS_KEY, JSON.stringify({ startTime: startTime })); }
|
|
209
164
|
catch (_) {}
|
|
210
165
|
|
|
@@ -222,7 +177,6 @@ function initPresenter(getActiveFrame, playable, getCurrentIndex) {
|
|
|
222
177
|
}, 1000);
|
|
223
178
|
}
|
|
224
179
|
|
|
225
|
-
// ── Read speaker notes from active iframe ───────────────────────────────
|
|
226
180
|
function readNotes(frame) {
|
|
227
181
|
try {
|
|
228
182
|
var el = frame && frame.contentDocument &&
|
|
@@ -243,17 +197,12 @@ function initPresenter(getActiveFrame, playable, getCurrentIndex) {
|
|
|
243
197
|
}
|
|
244
198
|
}
|
|
245
199
|
|
|
246
|
-
// ── Push update to popup ────────────────────────────────────────────────
|
|
247
|
-
// Sends: slide names, speaker notes, slide URLs (for live previews),
|
|
248
|
-
// total count and current index (for jump control).
|
|
249
200
|
function push() {
|
|
250
201
|
if (!win || win.closed) return;
|
|
251
202
|
var idx = getCurrentIndex();
|
|
252
203
|
var curr = playable[idx];
|
|
253
204
|
var next = playable[idx + 1];
|
|
254
205
|
var frame = getActiveFrame();
|
|
255
|
-
// Compute absolute base URL so iframe srcs work in the popup window
|
|
256
|
-
// (popup is opened with '', so relative URLs would not resolve).
|
|
257
206
|
var deckBase = location.href.replace(/[^\/]*$/, '');
|
|
258
207
|
|
|
259
208
|
function doSend() {
|
|
@@ -276,7 +225,6 @@ function initPresenter(getActiveFrame, playable, getCurrentIndex) {
|
|
|
276
225
|
}
|
|
277
226
|
}
|
|
278
227
|
|
|
279
|
-
// ── Open popup ──────────────────────────────────────────────────────────
|
|
280
228
|
function open() {
|
|
281
229
|
if (win && !win.closed) { win.focus(); return; }
|
|
282
230
|
win = window.open('', 'octocode-presenter',
|
|
@@ -285,32 +233,25 @@ function initPresenter(getActiveFrame, playable, getCurrentIndex) {
|
|
|
285
233
|
win.document.open();
|
|
286
234
|
win.document.write(POPUP_HTML);
|
|
287
235
|
win.document.close();
|
|
288
|
-
// startTimer picks up startTime from localStorage restore if already running
|
|
289
236
|
startTimer();
|
|
290
|
-
setTimeout(push, 200);
|
|
237
|
+
setTimeout(push, 200);
|
|
291
238
|
}
|
|
292
239
|
|
|
293
|
-
// ── Listen for messages from popup ──────────────────────────────────────
|
|
294
240
|
window.addEventListener('message', function (e) {
|
|
295
241
|
if (!e.data) return;
|
|
296
242
|
if (e.data.type === 'octocode-slides:presenter-reset') {
|
|
297
243
|
elapsed = 0;
|
|
298
244
|
startTime = Date.now();
|
|
299
|
-
// Clear persisted timer so a refresh after reset starts from 00:00
|
|
300
245
|
try { localStorage.removeItem(LS_KEY); } catch (_) {}
|
|
301
|
-
// Re-persist the fresh start time
|
|
302
246
|
try { localStorage.setItem(LS_KEY, JSON.stringify({ startTime: startTime })); }
|
|
303
247
|
catch (_) {}
|
|
304
248
|
}
|
|
305
249
|
});
|
|
306
250
|
|
|
307
|
-
// ── Slide change hook ───────────────────────────────────────────────────
|
|
308
|
-
// Call push() whenever the slide changes.
|
|
309
|
-
// index.html should call presenter.onSlideChange() after go().
|
|
310
251
|
return {
|
|
311
252
|
open: open,
|
|
312
253
|
push: push,
|
|
313
|
-
|
|
254
|
+
|
|
314
255
|
onSlideChange: push
|
|
315
256
|
};
|
|
316
257
|
}
|
|
@@ -1,18 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
* build_dashboard.mjs
|
|
4
|
-
*
|
|
5
|
-
* Read Octocode MCP `stats.json`, pre-compute every dashboard metric, embed the
|
|
6
|
-
* resulting JSON into the HTML template, write the result to disk, and
|
|
7
|
-
* optionally open it in the default browser.
|
|
8
|
-
*
|
|
9
|
-
* Schema source of truth:
|
|
10
|
-
* packages/octocode-shared/src/session/schemas.ts
|
|
11
|
-
*
|
|
12
|
-
* Usage:
|
|
13
|
-
* node build_dashboard.mjs [--stats <path>] [--output <path>]
|
|
14
|
-
* [--template <path>] [--no-open] [--allow-empty]
|
|
15
|
-
*/
|
|
2
|
+
|
|
16
3
|
|
|
17
4
|
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs';
|
|
18
5
|
import { resolve, dirname, join, isAbsolute } from 'node:path';
|
|
@@ -23,9 +10,6 @@ import { spawn } from 'node:child_process';
|
|
|
23
10
|
const __filename = fileURLToPath(import.meta.url);
|
|
24
11
|
const __dirname = dirname(__filename);
|
|
25
12
|
|
|
26
|
-
// Universal heuristic used by OpenAI / Anthropic tokenizers (~4 chars per token
|
|
27
|
-
// for English text and code). Actual token usage varies by model and content —
|
|
28
|
-
// surfaced as an explicit disclaimer on the dashboard.
|
|
29
13
|
const TOKEN_CHAR_RATIO = 4;
|
|
30
14
|
const TOKEN_ESTIMATE_NOTE =
|
|
31
15
|
`Token counts are estimated at ~${TOKEN_CHAR_RATIO} chars per token. ` +
|
|
@@ -136,7 +120,6 @@ function readStats(statsPath, allowEmpty) {
|
|
|
136
120
|
}
|
|
137
121
|
|
|
138
122
|
function readSessionMeta(statsPath) {
|
|
139
|
-
// session.json lives next to stats.json in OCTOCODE_HOME
|
|
140
123
|
const sessionPath = join(dirname(statsPath), 'session.json');
|
|
141
124
|
if (!existsSync(sessionPath)) return null;
|
|
142
125
|
try {
|
|
@@ -324,7 +307,6 @@ function injectData(template, data) {
|
|
|
324
307
|
`Confirm the template file is the one shipped with this skill.`
|
|
325
308
|
);
|
|
326
309
|
}
|
|
327
|
-
// JSON.stringify never produces </script>, but we still defend against it.
|
|
328
310
|
const json = JSON.stringify(data).replace(/</g, '\\u003c');
|
|
329
311
|
return template.replace(SENTINEL, json);
|
|
330
312
|
}
|