sticky-note-cli 3.1.17 → 3.1.19

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 (26) hide show
  1. package/bin/cli.js +11 -2
  2. package/package.json +1 -1
  3. package/sticky-server/.wrangler/state/v3/observability/miniflare-wobs-trace-store/a590acd76969f996ec6e4b599c3c09f58c283a76f2d61392b5d3046caf557602.sqlite-shm +0 -0
  4. package/sticky-server/.wrangler/state/v3/observability/miniflare-wobs-trace-store/a590acd76969f996ec6e4b599c3c09f58c283a76f2d61392b5d3046caf557602.sqlite-wal +0 -0
  5. package/sticky-server/.wrangler/tmp/{bundle-QVovzR → bundle-P0OxNJ}/middleware-loader.entry.ts +3 -3
  6. package/sticky-server/.wrangler/tmp/{bundle-cuweP4 → bundle-bnw3E4}/middleware-loader.entry.ts +3 -3
  7. package/sticky-server/.wrangler/tmp/{bundle-EyT3Z4 → bundle-seUgBC}/middleware-loader.entry.ts +3 -3
  8. package/sticky-server/.wrangler/tmp/{bundle-skMxAR → bundle-w4cy8K}/middleware-loader.entry.ts +3 -3
  9. package/sticky-server/.wrangler/tmp/{dev-ZhpGzw → dev-EAEq4Z}/worker.js +3 -3
  10. package/sticky-server/.wrangler/tmp/{dev-ZhpGzw → dev-EAEq4Z}/worker.js.map +3 -3
  11. package/sticky-server/.wrangler/tmp/{dev-dVJlR1 → dev-ELf1wJ}/worker.js +3 -3
  12. package/sticky-server/.wrangler/tmp/{dev-dVJlR1 → dev-ELf1wJ}/worker.js.map +3 -3
  13. package/sticky-server/.wrangler/tmp/{dev-gZFGI3 → dev-a8XdEc}/worker.js +3 -3
  14. package/sticky-server/.wrangler/tmp/{dev-gZFGI3 → dev-a8XdEc}/worker.js.map +3 -3
  15. package/sticky-server/.wrangler/tmp/{dev-rZTsQz → dev-lut6Lj}/worker.js +3 -3
  16. package/sticky-server/.wrangler/tmp/{dev-rZTsQz → dev-lut6Lj}/worker.js.map +3 -3
  17. package/sticky-server/wrangler.toml +1 -1
  18. package/templates/settings.json +7 -7
  19. /package/sticky-server/.wrangler/tmp/{bundle-EyT3Z4 → bundle-P0OxNJ}/checked-fetch.js +0 -0
  20. /package/sticky-server/.wrangler/tmp/{bundle-EyT3Z4 → bundle-P0OxNJ}/middleware-insertion-facade.js +0 -0
  21. /package/sticky-server/.wrangler/tmp/{bundle-QVovzR → bundle-bnw3E4}/checked-fetch.js +0 -0
  22. /package/sticky-server/.wrangler/tmp/{bundle-QVovzR → bundle-bnw3E4}/middleware-insertion-facade.js +0 -0
  23. /package/sticky-server/.wrangler/tmp/{bundle-cuweP4 → bundle-seUgBC}/checked-fetch.js +0 -0
  24. /package/sticky-server/.wrangler/tmp/{bundle-cuweP4 → bundle-seUgBC}/middleware-insertion-facade.js +0 -0
  25. /package/sticky-server/.wrangler/tmp/{bundle-skMxAR → bundle-w4cy8K}/checked-fetch.js +0 -0
  26. /package/sticky-server/.wrangler/tmp/{bundle-skMxAR → bundle-w4cy8K}/middleware-insertion-facade.js +0 -0
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../bundle-cuweP4/checked-fetch.js", "../../../adapters/cf-kv.js", "../../../mcp-tools.js", "../../../sticky-thread-do.js", "../../../worker.js", "../../../../../../../../AppData/Roaming/npm/node_modules/wrangler/templates/middleware/middleware-ensure-req-body-drained.ts", "../../../../../../../../AppData/Roaming/npm/node_modules/wrangler/templates/middleware/middleware-miniflare3-json-error.ts", "../bundle-cuweP4/middleware-insertion-facade.js", "../../../../../../../../AppData/Roaming/npm/node_modules/wrangler/templates/middleware/common.ts", "../bundle-cuweP4/middleware-loader.entry.ts"],
4
- "sourceRoot": "C:\\Users\\dheer\\OneDrive\\Desktop\\Projects\\sticky-note\\sticky-server\\.wrangler\\tmp\\dev-gZFGI3",
5
- "sourcesContent": ["const urls = new Set();\n\nfunction checkURL(request, init) {\n\tconst url =\n\t\trequest instanceof URL\n\t\t\t? request\n\t\t\t: new URL(\n\t\t\t\t\t(typeof request === \"string\" ? new Request(request, init) : request)\n\t\t\t\t\t\t.url\n\t\t\t\t);\n\tif (url.port && url.port !== \"443\" && url.protocol === \"https:\") {\n\t\tif (!urls.has(url.toString())) {\n\t\t\turls.add(url.toString());\n\t\t\tconsole.warn(\n\t\t\t\t`WARNING: known issue with \\`fetch()\\` requests to custom HTTPS ports in published Workers:\\n` +\n\t\t\t\t\t` - ${url.toString()} - the custom port will be ignored when the Worker is published using the \\`wrangler deploy\\` command.\\n`\n\t\t\t);\n\t\t}\n\t}\n}\n\nglobalThis.fetch = new Proxy(globalThis.fetch, {\n\tapply(target, thisArg, argArray) {\n\t\tconst [request, init] = argArray;\n\t\tcheckURL(request, init);\n\t\treturn Reflect.apply(target, thisArg, argArray);\n\t},\n});\n", "/**\n * Cloudflare KV adapter for Sticky Note V3.\n *\n * KV key schema (all prefixed by project):\n * {project}:thread:{uuid} \u2192 thread JSON\n * {project}:thread-index \u2192 JSON array of thread UUIDs\n * {project}:audit:{timestamp}:{uuid} \u2192 audit record JSON\n * {project}:audit-index \u2192 JSON array of audit keys\n * {project}:presence:{user} \u2192 presence record JSON\n * {project}:presence-index \u2192 JSON array of usernames\n * {project}:config \u2192 config JSON\n */\n\n// \u2500\u2500 Threads \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function getThreads(kv, project, filters = {}) {\n const indexKey = `${project}:thread-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n\n if (index.length === 0) return [];\n\n const threads = await Promise.all(\n index.map(async (id) => {\n const raw = await kv.get(`${project}:thread:${id}`);\n return raw ? JSON.parse(raw) : null;\n })\n );\n\n let result = threads.filter(Boolean);\n\n if (filters.status) {\n result = result.filter((t) => t.status === filters.status);\n }\n if (filters.q) {\n const q = filters.q.toLowerCase();\n result = result.filter(\n (t) =>\n (t.narrative || \"\").toLowerCase().includes(q) ||\n (t.handoff_summary || \"\").toLowerCase().includes(q) ||\n (t.last_note || \"\").toLowerCase().includes(q) ||\n (t.files_touched || []).some((f) => f.toLowerCase().includes(q))\n );\n }\n\n return result;\n}\n\nasync function getThread(kv, project, id) {\n const raw = await kv.get(`${project}:thread:${id}`);\n return raw ? JSON.parse(raw) : null;\n}\n\nasync function putThread(kv, project, thread) {\n const id = thread.id;\n await kv.put(`${project}:thread:${id}`, JSON.stringify(thread));\n\n // Update index\n const indexKey = `${project}:thread-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n if (!index.includes(id)) {\n index.push(id);\n await kv.put(indexKey, JSON.stringify(index));\n }\n}\n\nasync function deleteThread(kv, project, id) {\n // Tombstone: keep minimal record\n const existing = await getThread(kv, project, id);\n if (existing) {\n const tombstone = {\n id: existing.id,\n user: existing.user,\n status: \"expired\",\n closed_at: existing.closed_at || new Date().toISOString(),\n created_at: existing.created_at,\n };\n await kv.put(`${project}:thread:${id}`, JSON.stringify(tombstone));\n }\n}\n\n// \u2500\u2500 Audit \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function appendAudit(kv, project, record) {\n const ts = record.timestamp || new Date().toISOString();\n const uid = crypto.randomUUID();\n const key = `${project}:audit:${ts}:${uid}`;\n await kv.put(key, JSON.stringify(record));\n\n const indexKey = `${project}:audit-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n index.push(key);\n\n // Cap at 10,000 entries; trim oldest on overflow\n if (index.length > 10000) {\n const removed = index.splice(0, index.length - 10000);\n await Promise.all(removed.map((k) => kv.delete(k)));\n }\n await kv.put(indexKey, JSON.stringify(index));\n}\n\nasync function queryAudit(kv, project, filters = {}) {\n const indexKey = `${project}:audit-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n\n if (index.length === 0) return [];\n\n const records = await Promise.all(\n index.map(async (key) => {\n const raw = await kv.get(key);\n return raw ? JSON.parse(raw) : null;\n })\n );\n\n let result = records.filter(Boolean);\n\n if (filters.user) {\n result = result.filter((r) => r.user === filters.user);\n }\n if (filters.file) {\n result = result.filter((r) => (r.file || \"\").includes(filters.file));\n }\n if (filters.tool) {\n result = result.filter((r) => r.tool === filters.tool);\n }\n if (filters.since) {\n const since = new Date(filters.since).getTime();\n result = result.filter(\n (r) => new Date(r.timestamp || 0).getTime() >= since\n );\n }\n\n return result;\n}\n\n// \u2500\u2500 Presence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst PRESENCE_TTL_SECONDS = 15 * 60; // 15 minutes\n\nasync function getPresence(kv, project) {\n const indexKey = `${project}:presence-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n\n if (index.length === 0) return [];\n\n const records = await Promise.all(\n index.map(async (user) => {\n const raw = await kv.get(`${project}:presence:${user}`);\n return raw ? JSON.parse(raw) : null;\n })\n );\n\n return records.filter(Boolean);\n}\n\nasync function upsertPresence(kv, project, record) {\n const user = record.user;\n await kv.put(`${project}:presence:${user}`, JSON.stringify(record), {\n expirationTtl: PRESENCE_TTL_SECONDS,\n });\n\n const indexKey = `${project}:presence-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n if (!index.includes(user)) {\n index.push(user);\n await kv.put(indexKey, JSON.stringify(index));\n }\n}\n\nasync function deletePresence(kv, project, user) {\n await kv.delete(`${project}:presence:${user}`);\n\n const indexKey = `${project}:presence-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n const filtered = index.filter((u) => u !== user);\n await kv.put(indexKey, JSON.stringify(filtered));\n}\n\n// \u2500\u2500 Events \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst MAX_CHUNK_BYTES = 2 * 1024 * 1024; // 2 MB per KV value\n\nasync function getEvents(kv, project, threadId) {\n const metaKey = `${project}:thread:${threadId}`;\n const meta = await kv.get(metaKey, { type: \"json\" }).catch(() => null);\n const chunkCount = (meta && meta._event_chunks) || 0;\n\n if (chunkCount === 0) {\n // Try legacy single-key format\n const single = await kv.get(`${metaKey}:events`, { type: \"json\" }).catch(() => null);\n return Array.isArray(single) ? single : [];\n }\n\n const chunks = await Promise.all(\n Array.from({ length: chunkCount }, (_, i) =>\n kv.get(`${metaKey}:events:${i}`, { type: \"json\" }).catch(() => [])\n )\n );\n return chunks.flat().filter(Boolean);\n}\n\nasync function appendEvents(kv, project, threadId, newEvents) {\n if (!newEvents || newEvents.length === 0) return;\n\n const metaKey = `${project}:thread:${threadId}`;\n const meta = await kv.get(metaKey, { type: \"json\" }).catch(() => ({}));\n const chunkCount = (meta && meta._event_chunks) || 0;\n\n let currentChunkIdx = chunkCount === 0 ? 0 : chunkCount - 1;\n let currentChunk = [];\n if (chunkCount > 0) {\n currentChunk =\n (await kv.get(`${metaKey}:events:${currentChunkIdx}`, { type: \"json\" }).catch(() => [])) ||\n [];\n }\n\n const enc = new TextEncoder();\n let chunkBytes = enc.encode(JSON.stringify(currentChunk)).length;\n\n for (const event of newEvents) {\n const eventBytes = enc.encode(JSON.stringify(event)).length;\n if (chunkBytes + eventBytes > MAX_CHUNK_BYTES && currentChunk.length > 0) {\n await kv.put(`${metaKey}:events:${currentChunkIdx}`, JSON.stringify(currentChunk));\n currentChunkIdx++;\n currentChunk = [];\n chunkBytes = 0;\n }\n currentChunk.push(event);\n chunkBytes += eventBytes;\n }\n await kv.put(`${metaKey}:events:${currentChunkIdx}`, JSON.stringify(currentChunk));\n\n const newMeta = { ...(meta || {}), _event_chunks: currentChunkIdx + 1 };\n await kv.put(metaKey, JSON.stringify(newMeta));\n}\n\n// \u2500\u2500 Config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function getConfig(kv, project) {\n const raw = await kv.get(`${project}:config`);\n return raw ? JSON.parse(raw) : null;\n}\n\nasync function putConfig(kv, project, config) {\n await kv.put(`${project}:config`, JSON.stringify(config));\n}\n\n// \u2500\u2500 Export \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport {\n getThreads,\n getThread,\n putThread,\n deleteThread,\n appendAudit,\n queryAudit,\n getPresence,\n upsertPresence,\n deletePresence,\n getConfig,\n putConfig,\n getEvents,\n appendEvents,\n};\n", "// sticky-server/mcp-tools.js\n\n// crypto.randomUUID() is a Workers global \u2014 no import needed unless nodejs_compat is set.\n// We use the global directly to avoid a hard dep on node:crypto when that flag isn't active.\n\nexport const EVENT_TYPES = Object.freeze({\n SESSION_OPEN: \"session_open\",\n SESSION_CLOSE: \"session_close\",\n USER_PROMPT: \"user_prompt\",\n CHECKPOINT: \"checkpoint\",\n});\n\nexport const MCP_TOOL_DEFINITIONS = [\n {\n name: \"open_thread\",\n description: \"Call at session start. Creates a new thread and returns its thread_id for use in subsequent append_event and close_thread calls.\",\n inputSchema: {\n type: \"object\",\n properties: {\n prompt: { type: \"string\", description: \"Verbatim first user prompt\" },\n branch: { type: \"string\", description: \"Current git branch\" },\n user: { type: \"string\", description: \"Username\" },\n model: { type: \"string\", description: \"Model ID (e.g. claude-sonnet-4-6)\" },\n mcp_servers: { type: \"array\", items: { type: \"string\" }, description: \"Connected MCP server names\" },\n claude_md_hash: { type: \"string\", description: \"SHA256 of CLAUDE.md content (optional)\" },\n },\n required: [\"prompt\", \"user\"],\n },\n },\n {\n name: \"append_event\",\n description: \"Call for every action in the session. Records one event (user_prompt, ai_thinking, ai_response, tool_call, tool_result, tool_error, tool_denied, context_compressed, git_commit, subagent_spawn, subagent_result, checkpoint). Do not call for streaming tokens or internal transport retries.\",\n inputSchema: {\n type: \"object\",\n properties: {\n thread_id: { type: \"string\", description: \"thread_id returned by open_thread\" },\n type: { type: \"string\", description: \"Event type (see description)\" },\n data: { type: \"object\", description: \"Event-specific payload\" },\n },\n required: [\"thread_id\", \"type\", \"data\"],\n },\n },\n {\n name: \"set_checkpoint\",\n description: \"Call when the user switches to a different topic mid-session. Marks subsequent events with the new topic for attribution.\",\n inputSchema: {\n type: \"object\",\n properties: {\n thread_id: { type: \"string\" },\n topic: { type: \"string\", description: \"Short description of new work topic\" },\n },\n required: [\"thread_id\", \"topic\"],\n },\n },\n {\n name: \"close_thread\",\n description: \"Call at session end. Writes the session_close event, updates thread status to closed, and triggers a git commit of thread metadata.\",\n inputSchema: {\n type: \"object\",\n properties: {\n thread_id: { type: \"string\" },\n narrative: { type: \"string\", description: \"Summary of what was accomplished\" },\n work_type: { type: \"string\", description: \"e.g. bug-fix, feature-development, debugging, refactor, documentation\" },\n handoff_summary: { type: \"string\", description: \"Notes for teammates picking this up\" },\n failed_approaches: { type: \"array\", items: { type: \"string\" }, description: \"What was tried and didn't work\" },\n files_touched: { type: \"array\", items: { type: \"string\" }, description: \"Files modified during session\" },\n },\n required: [\"thread_id\", \"narrative\"],\n },\n },\n];\n\nexport async function handleMcpTool(toolName, input, env, project, getOrCreateDO) {\n switch (toolName) {\n case \"open_thread\": return handleOpenThread(input, env, project, getOrCreateDO);\n case \"append_event\": return handleAppendEvent(input, env, project, getOrCreateDO);\n case \"set_checkpoint\": return handleSetCheckpoint(input, env, project, getOrCreateDO);\n case \"close_thread\": return handleCloseThread(input, env, project, getOrCreateDO);\n default: throw new Error(`Unknown tool: ${toolName}`);\n }\n}\n\nasync function handleOpenThread(input, env, project, getOrCreateDO) {\n const threadId = crypto.randomUUID();\n const now = new Date().toISOString();\n\n const threadMeta = {\n id: threadId,\n status: \"open\",\n user: input.user,\n branch: input.branch || \"\",\n created_at: now,\n last_activity_at: now,\n files_touched: [],\n narrative: \"\",\n tool: \"claude-code\",\n session_id: null, // remote sessions don't have a local session_id\n _event_chunks: 0,\n };\n\n const metaKey = `${project}:thread:${threadId}`;\n await env.STICKY_KV.put(metaKey, JSON.stringify(threadMeta));\n\n const openEvent = {\n ts: now, type: EVENT_TYPES.SESSION_OPEN, session_id: null,\n data: {\n model: input.model || null,\n branch: input.branch || null,\n user: input.user,\n mcp_servers: input.mcp_servers || [],\n claude_md_hash: input.claude_md_hash || null,\n },\n };\n const promptEvent = {\n ts: now, type: EVENT_TYPES.USER_PROMPT, session_id: null,\n data: { content: input.prompt },\n };\n\n const do_stub = getOrCreateDO(env, threadId);\n await do_stub.fetch(new Request(\"http://do/do/open\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ thread_id: threadId, project, events: [openEvent, promptEvent] }),\n }));\n\n // Async GitHub commit \u2014 fire and forget\n _commitThreadToGit(env, project, threadId, getOrCreateDO).catch(() => {});\n\n return { thread_id: threadId };\n}\n\nasync function handleAppendEvent(input, env, project, getOrCreateDO) {\n const { thread_id, type, data } = input;\n\n const metaKey = `${project}:thread:${thread_id}`;\n const exists = await env.STICKY_KV.get(metaKey, { type: \"text\" });\n if (!exists) return { ok: false, error: \"unknown thread_id\" };\n\n const event = { ts: new Date().toISOString(), type, session_id: null, data: data || {} };\n\n const do_stub = getOrCreateDO(env, thread_id);\n await do_stub.fetch(new Request(\"http://do/do/append\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ event }),\n }));\n\n return { ok: true };\n}\n\nasync function handleSetCheckpoint(input, env, project, getOrCreateDO) {\n return handleAppendEvent(\n { thread_id: input.thread_id, type: EVENT_TYPES.CHECKPOINT, data: { topic: input.topic } },\n env, project, getOrCreateDO\n );\n}\n\nasync function handleCloseThread(input, env, project, getOrCreateDO) {\n const { thread_id, narrative, work_type, handoff_summary, failed_approaches, files_touched } = input;\n const now = new Date().toISOString();\n\n const closeEvent = {\n ts: now, type: EVENT_TYPES.SESSION_CLOSE, session_id: null,\n data: {\n narrative,\n work_type: work_type || \"general\",\n handoff_summary: handoff_summary || \"\",\n failed_approaches: failed_approaches || [],\n files_touched: files_touched || [],\n },\n };\n\n const do_stub = getOrCreateDO(env, thread_id);\n await do_stub.fetch(new Request(\"http://do/do/close\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ close_event: closeEvent }),\n }));\n\n // Update thread metadata\n const metaKey = `${project}:thread:${thread_id}`;\n const meta = await env.STICKY_KV.get(metaKey, { type: \"json\" }).catch(() => ({})) || {};\n meta.status = \"closed\";\n meta.closed_at = now;\n meta.narrative = narrative;\n meta.work_type = work_type || \"general\";\n meta.handoff_summary = handoff_summary || \"\";\n meta.failed_approaches = failed_approaches || [];\n if (files_touched) {\n meta.files_touched = [...new Set([...(meta.files_touched || []), ...files_touched])];\n }\n await env.STICKY_KV.put(metaKey, JSON.stringify(meta));\n\n // GitHub commit \u2014 synchronous (awaited) for close_thread\n await _commitThreadToGit(env, project, thread_id, getOrCreateDO);\n\n return { ok: true };\n}\n\n// Internal helper \u2014 used by open_thread (fire-and-forget), close_thread (awaited), and crash recovery\nexport async function _commitThreadToGit(env, project, threadId, getOrCreateDO) {\n const kv = env.STICKY_KV;\n\n // Always maintain the threads index (even without GitHub creds).\n // NOTE: There is a known read-modify-write race when two open_thread calls run\n // concurrently \u2014 both may read the same list before either writes back. This is\n // self-healing: the next close_thread call will re-add any dropped ID, and the\n // list is always capped at 500, so no corruption accumulates. A separate \"index DO\"\n // would be required to eliminate the race entirely, which is out of scope here.\n const threadsListKey = `${project}:threads_index`;\n let threadIds = await kv.get(threadsListKey, { type: \"json\" }).catch(() => []) || [];\n if (!threadIds.includes(threadId)) {\n threadIds = [threadId, ...threadIds].slice(0, 500); // cap at 500\n await kv.put(threadsListKey, JSON.stringify(threadIds));\n }\n\n // GitHub commit requires credentials \u2014 skip if not configured\n const pat = env.GITHUB_PAT;\n const repoFull = env.GITHUB_REPO; // format: \"owner/repo\"\n if (!pat || !repoFull) return;\n const [owner, repo] = repoFull.split(\"/\");\n if (!owner || !repo) return;\n\n // threadIds is already populated above \u2014 no second KV read needed\n const allMeta = await Promise.all(\n threadIds.map(id => kv.get(`${project}:thread:${id}`, { type: \"json\" }).catch(() => null))\n );\n const threads = allMeta.filter(Boolean).map(m => {\n // Strip internal KV fields before writing to git\n const { _event_chunks, _last_recovery_attempt, ...rest } = m;\n return rest;\n });\n\n const newContent = JSON.stringify({ version: \"2\", project, threads }, null, 2) + \"\\n\";\n\n // Use StickyThread DO for serialized GitHub commit (avoids race conditions)\n const do_stub = getOrCreateDO(env, threadId);\n await do_stub.fetch(new Request(\"http://do/do/github-commit\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n owner, repo,\n path: \".sticky-note/sticky-note.json\",\n content: newContent,\n message: `chore(sticky-note): sync thread ${threadId.slice(0, 8)}`,\n pat,\n }),\n }));\n}\n", "// sticky-server/sticky-thread-do.js\nimport { appendEvents } from \"./adapters/cf-kv.js\";\n\nexport class StickyThread {\n constructor(state, env) {\n this.state = state;\n this.env = env;\n this.buffer = [];\n this.flushThreshold = 10;\n this.threadId = null;\n this.project = \"default\";\n }\n\n async fetch(request) {\n const url = new URL(request.url);\n const body = await request.json().catch(() => ({}));\n\n if (url.pathname === \"/do/open\") {\n this.threadId = body.thread_id;\n this.project = body.project || \"default\";\n for (const ev of (body.events || [])) this.buffer.push(ev);\n await this._scheduleFlush();\n return new Response(JSON.stringify({ ok: true, thread_id: this.threadId }), {\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n if (url.pathname === \"/do/append\") {\n const event = body.event;\n if (event) this.buffer.push(event);\n if (this.buffer.length >= this.flushThreshold) {\n await this._flush();\n } else {\n await this._scheduleFlush();\n }\n return new Response(JSON.stringify({ ok: true }), {\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n if (url.pathname === \"/do/close\") {\n const closeEvent = body.close_event;\n if (closeEvent) this.buffer.push(closeEvent);\n await this._flush();\n try { await this.state.storage.deleteAlarm(); } catch (_) {}\n return new Response(JSON.stringify({ ok: true, flushed: true }), {\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n if (url.pathname === \"/do/github-commit\") {\n // Serialized GitHub REST write for this thread\n const result = await this._githubCommit(body);\n return new Response(JSON.stringify(result), {\n headers: { \"Content-Type\": \"application/json\" },\n status: result.ok ? 200 : 500,\n });\n }\n\n return new Response(\"not found\", { status: 404 });\n }\n\n async alarm() {\n if (this.buffer.length > 0) {\n await this._flush();\n }\n }\n\n async _scheduleFlush() {\n try {\n const existing = await this.state.storage.getAlarm();\n if (!existing) {\n await this.state.storage.setAlarm(Date.now() + 5000);\n }\n } catch (_) {}\n }\n\n async _flush() {\n if (this.buffer.length === 0 || !this.threadId) return;\n const toFlush = this.buffer.splice(0);\n try {\n await appendEvents(this.env.STICKY_KV, this.project, this.threadId, toFlush);\n } catch (err) {\n // Put unwritten events back at front of buffer for retry\n this.buffer.unshift(...toFlush);\n }\n }\n\n async _githubCommit(body) {\n const { owner, repo, path: filePath, content, message, pat } = body;\n if (!pat) return { ok: false, error: \"no PAT\" };\n const apiBase = `https://api.github.com/repos/${owner}/${repo}/contents/${filePath}`;\n const headers = {\n Authorization: `Bearer ${pat}`,\n Accept: \"application/vnd.github+json\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"sticky-note-worker\",\n };\n\n let sha = null;\n let retries = 3;\n while (retries-- > 0) {\n // GET current SHA\n const getResp = await fetch(apiBase, { headers }).catch(() => null);\n if (getResp && getResp.ok) {\n const data = await getResp.json().catch(() => ({}));\n sha = data.sha || null;\n }\n\n // PUT with SHA\n const putBody = {\n message,\n content: btoa(unescape(encodeURIComponent(content))), // base64 encode UTF-8\n ...(sha ? { sha } : {}),\n };\n const putResp = await fetch(apiBase, {\n method: \"PUT\",\n headers,\n body: JSON.stringify(putBody),\n }).catch(() => null);\n\n if (!putResp) return { ok: false, error: \"network error\" };\n if (putResp.ok) return { ok: true };\n if (putResp.status === 409) {\n // SHA mismatch \u2014 retry after backoff\n await new Promise(r => setTimeout(r, 200));\n continue;\n }\n const errBody = await putResp.json().catch(() => ({}));\n return { ok: false, error: errBody.message || `HTTP ${putResp.status}` };\n }\n return { ok: false, error: \"max retries exceeded (409 conflict)\" };\n }\n}\n", "/**\n * Sticky Note V3 \u2014 Cloudflare Worker\n *\n * REST API backed by Cloudflare KV.\n * Auth: X-Sticky-API-Key header matched against STICKY_API_KEY env var.\n * Project routing: X-Sticky-Project header (auto-set by client hooks).\n *\n * Endpoints:\n * POST /threads \u2014 create thread\n * GET /threads \u2014 list threads (?status=, ?q=)\n * GET /threads/:id \u2014 get thread\n * PUT /threads/:id \u2014 update thread\n * DELETE /threads/:id \u2014 tombstone thread\n * POST /threads/:id/events \u2014 append event batch (local session push)\n * GET /threads/:id/events \u2014 retrieve all stored events\n * GET /audit \u2014 query audit (?file=, ?user=, ?since=, ?tool=)\n * POST /audit \u2014 append audit record\n * GET /presence \u2014 list active developers\n * POST /presence \u2014 heartbeat upsert\n * DELETE /presence/:user \u2014 clear presence\n * GET /config \u2014 get team config\n * PUT /config \u2014 update team config\n */\n\nimport * as adapter from \"./adapters/cf-kv.js\";\nimport { MCP_TOOL_DEFINITIONS, handleMcpTool, _commitThreadToGit, EVENT_TYPES } from \"./mcp-tools.js\";\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction json(data, status = 200) {\n return new Response(JSON.stringify(data), {\n status,\n headers: { \"Content-Type\": \"application/json\" },\n });\n}\n\nfunction error(message, status = 400) {\n return json({ error: message }, status);\n}\n\nfunction authenticate(request, env) {\n const key = request.headers.get(\"X-Sticky-API-Key\");\n if (!env.STICKY_API_KEY) return true; // no key configured = open\n return key === env.STICKY_API_KEY;\n}\n\nfunction getProject(request) {\n return request.headers.get(\"X-Sticky-Project\") || \"default\";\n}\n\n// \u2500\u2500 Router \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction matchRoute(method, pathname) {\n // Thread routes\n if (method === \"POST\" && pathname === \"/threads\") return { handler: \"createThread\" };\n if (method === \"GET\" && pathname === \"/threads\") return { handler: \"listThreads\" };\n if (method === \"POST\" && pathname.match(/^\\/threads\\/[^/]+\\/events$/)) {\n const id = pathname.split(\"/\")[2];\n return { handler: \"appendThreadEvents\", id };\n }\n if (method === \"GET\" && pathname.match(/^\\/threads\\/[^/]+\\/events$/)) {\n const id = pathname.split(\"/\")[2];\n return { handler: \"getThreadEvents\", id };\n }\n if (method === \"GET\" && pathname.startsWith(\"/threads/\")) {\n return { handler: \"getThread\", id: pathname.slice(\"/threads/\".length) };\n }\n if (method === \"PUT\" && pathname.startsWith(\"/threads/\")) {\n return { handler: \"updateThread\", id: pathname.slice(\"/threads/\".length) };\n }\n if (method === \"DELETE\" && pathname.startsWith(\"/threads/\")) {\n return { handler: \"deleteThread\", id: pathname.slice(\"/threads/\".length) };\n }\n\n // Audit routes\n if (method === \"GET\" && pathname === \"/audit\") return { handler: \"queryAudit\" };\n if (method === \"POST\" && pathname === \"/audit\") return { handler: \"appendAudit\" };\n\n // Presence routes\n if (method === \"GET\" && pathname === \"/presence\") return { handler: \"getPresence\" };\n if (method === \"POST\" && pathname === \"/presence\") return { handler: \"upsertPresence\" };\n if (method === \"DELETE\" && pathname.startsWith(\"/presence/\")) {\n return { handler: \"deletePresence\", user: decodeURIComponent(pathname.slice(\"/presence/\".length)) };\n }\n\n // Config routes\n if (method === \"GET\" && pathname === \"/config\") return { handler: \"getConfig\" };\n if (method === \"PUT\" && pathname === \"/config\") return { handler: \"putConfig\" };\n\n // MCP routes\n if (method === \"GET\" && pathname === \"/mcp\") return { handler: \"mcpListTools\" };\n if (method === \"POST\" && pathname === \"/mcp\") return { handler: \"mcpCallTool\" };\n\n // Health\n if (method === \"GET\" && pathname === \"/health\") return { handler: \"health\" };\n\n return null;\n}\n\n// \u2500\u2500 Handlers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst handlers = {\n async health() {\n return json({ status: \"ok\", version: \"3.0.0\" });\n },\n\n // \u2500\u2500 Threads \u2500\u2500\n\n async createThread(request, kv, project) {\n const thread = await request.json();\n if (!thread.id) return error(\"thread.id is required\");\n await adapter.putThread(kv, project, thread);\n return json(thread, 201);\n },\n\n async listThreads(request, kv, project) {\n const url = new URL(request.url);\n const filters = {\n status: url.searchParams.get(\"status\") || undefined,\n q: url.searchParams.get(\"q\") || undefined,\n };\n const threads = await adapter.getThreads(kv, project, filters);\n return json({ threads });\n },\n\n async getThread(_request, kv, project, { id }) {\n const thread = await adapter.getThread(kv, project, id);\n if (!thread) return error(\"Thread not found\", 404);\n return json(thread);\n },\n\n async updateThread(request, kv, project, { id }) {\n const thread = await request.json();\n thread.id = id;\n await adapter.putThread(kv, project, thread);\n return json(thread);\n },\n\n async deleteThread(_request, kv, project, { id }) {\n await adapter.deleteThread(kv, project, id);\n return json({ deleted: id });\n },\n\n // \u2500\u2500 Thread Events \u2500\u2500\n\n async appendThreadEvents(request, kv, project, { id }) {\n const body = await request.json().catch(() => ({}));\n const events = Array.isArray(body.events) ? body.events : [];\n await adapter.appendEvents(kv, project, id, events);\n return json({ ok: true, appended: events.length });\n },\n\n async getThreadEvents(_request, kv, project, { id }) {\n const events = await adapter.getEvents(kv, project, id);\n return json({ events });\n },\n\n // \u2500\u2500 Audit \u2500\u2500\n\n async queryAudit(request, kv, project) {\n const url = new URL(request.url);\n const filters = {\n user: url.searchParams.get(\"user\") || undefined,\n file: url.searchParams.get(\"file\") || undefined,\n tool: url.searchParams.get(\"tool\") || undefined,\n since: url.searchParams.get(\"since\") || undefined,\n };\n const records = await adapter.queryAudit(kv, project, filters);\n return json({ audit: records });\n },\n\n async appendAudit(request, kv, project) {\n const record = await request.json();\n await adapter.appendAudit(kv, project, record);\n return json({ ok: true }, 201);\n },\n\n // \u2500\u2500 Presence \u2500\u2500\n\n async getPresence(_request, kv, project) {\n const records = await adapter.getPresence(kv, project);\n return json({ presence: records });\n },\n\n async upsertPresence(request, kv, project) {\n const record = await request.json();\n if (!record.user) return error(\"record.user is required\");\n await adapter.upsertPresence(kv, project, record);\n return json({ ok: true });\n },\n\n async deletePresence(_request, kv, project, { user }) {\n await adapter.deletePresence(kv, project, user);\n return json({ deleted: user });\n },\n\n // \u2500\u2500 MCP \u2500\u2500\n\n async mcpListTools() {\n return json({ tools: MCP_TOOL_DEFINITIONS });\n },\n\n async mcpCallTool(request, _kv, project, _route, env) {\n const body = await request.json().catch(() => ({}));\n const toolName = body.tool || body.name;\n const toolInput = body.input || body.arguments || {};\n if (!toolName) return error(\"tool name required\");\n try {\n const result = await handleMcpTool(toolName, toolInput, env, project, getOrCreateDO);\n return json({ content: [{ type: \"text\", text: JSON.stringify(result) }] });\n } catch (err) {\n return error(err.message, 400);\n }\n },\n\n // \u2500\u2500 Config \u2500\u2500\n\n async getConfig(_request, kv, project) {\n const config = await adapter.getConfig(kv, project);\n if (!config) return json({});\n return json(config);\n },\n\n async putConfig(request, kv, project) {\n const config = await request.json();\n await adapter.putConfig(kv, project, config);\n return json(config);\n },\n};\n\n// \u2500\u2500 Durable Object helper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction getOrCreateDO(env, threadId) {\n const id = env.STICKY_THREAD.idFromName(threadId);\n return env.STICKY_THREAD.get(id);\n}\n\n// \u2500\u2500 Worker entry point \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport default {\n async fetch(request, env) {\n // CORS preflight\n if (request.method === \"OPTIONS\") {\n return new Response(null, {\n status: 204,\n headers: {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type, X-Sticky-API-Key, X-Sticky-Project\",\n },\n });\n }\n\n // Auth\n if (!authenticate(request, env)) {\n return error(\"Unauthorized\", 401);\n }\n\n const url = new URL(request.url);\n const route = matchRoute(request.method, url.pathname);\n\n if (!route) {\n return error(\"Not found\", 404);\n }\n\n const project = getProject(request);\n const kv = env.STICKY_KV;\n\n try {\n const handler = handlers[route.handler];\n const response = await handler(request, kv, project, route, env);\n\n // Add CORS headers to all responses\n const headers = new Headers(response.headers);\n headers.set(\"Access-Control-Allow-Origin\", \"*\");\n return new Response(response.body, {\n status: response.status,\n headers,\n });\n } catch (err) {\n return error(`Internal error: ${err.message}`, 500);\n }\n },\n\n async scheduled(event, env, ctx) {\n ctx.waitUntil(runCrashRecovery(env));\n },\n};\n\n// \u2500\u2500 Crash recovery (cron) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function runCrashRecovery(env) {\n const projects = [\"default\"]; // TODO: discover from KV index if multi-project\n const staleThresholdMs = 30 * 60 * 1000; // 30 minutes\n const now = Date.now();\n\n for (const project of projects) {\n const threadsListKey = `${project}:threads_index`;\n const threadIds = await env.STICKY_KV.get(threadsListKey, { type: \"json\" })\n .catch(() => []) || [];\n\n const metas = await Promise.all(\n threadIds.map(id =>\n env.STICKY_KV.get(`${project}:thread:${id}`, { type: \"json\" }).catch(() => null)\n )\n );\n for (let i = 0; i < threadIds.length; i++) {\n const meta = metas[i];\n const threadId = threadIds[i];\n if (!meta || meta.status !== \"open\") continue;\n\n const lastActivity = new Date(meta.last_activity_at || meta.created_at).getTime();\n if (now - lastActivity < staleThresholdMs) continue;\n\n // Track last_recovery_attempt to avoid hammering\n const lastAttempt = meta._last_recovery_attempt || 0;\n if (now - lastAttempt < 5 * 60 * 1000) continue; // skip if tried < 5min ago\n\n // Thread is stale \u2014 flush DO buffer and mark as stale\n try {\n const do_stub = getOrCreateDO(env, threadId);\n const recovery_event = {\n ts: new Date().toISOString(), type: EVENT_TYPES.SESSION_CLOSE, session_id: null,\n data: { narrative: \"[recovered by cron]\", work_type: \"unknown\", handoff_summary: \"\", failed_approaches: [], files_touched: [] },\n };\n\n meta._last_recovery_attempt = now;\n await env.STICKY_KV.put(metaKey, JSON.stringify(meta));\n\n await do_stub.fetch(new Request(\"http://do/do/close\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ close_event: recovery_event }),\n }));\n\n meta.status = \"stale\";\n meta.last_activity_at = new Date().toISOString();\n await env.STICKY_KV.put(metaKey, JSON.stringify(meta));\n\n // GitHub commit for stale thread \u2014 commit the already-written stale metadata directly\n await _commitThreadToGit(env, project, threadId, getOrCreateDO).catch(() => {});\n } catch (_) {\n // best-effort \u2014 log to console for observability\n console.error(`[sticky-note] crash recovery failed for thread ${threadId}`);\n }\n }\n }\n}\n\nexport { StickyThread } from \"./sticky-thread-do.js\";\n", "import type { Middleware } from \"./common\";\n\nconst drainBody: Middleware = async (request, env, _ctx, middlewareCtx) => {\n\ttry {\n\t\treturn await middlewareCtx.next(request, env);\n\t} finally {\n\t\ttry {\n\t\t\tif (request.body !== null && !request.bodyUsed) {\n\t\t\t\tconst reader = request.body.getReader();\n\t\t\t\twhile (!(await reader.read()).done) {}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.error(\"Failed to drain the unused request body.\", e);\n\t\t}\n\t}\n};\n\nexport default drainBody;\n", "import type { Middleware } from \"./common\";\n\ninterface JsonError {\n\tmessage?: string;\n\tname?: string;\n\tstack?: string;\n\tcause?: JsonError;\n}\n\nfunction reduceError(e: any): JsonError {\n\treturn {\n\t\tname: e?.name,\n\t\tmessage: e?.message ?? String(e),\n\t\tstack: e?.stack,\n\t\tcause: e?.cause === undefined ? undefined : reduceError(e.cause),\n\t};\n}\n\n// See comment in `bundle.ts` for details on why this is needed\nconst jsonError: Middleware = async (request, env, _ctx, middlewareCtx) => {\n\ttry {\n\t\treturn await middlewareCtx.next(request, env);\n\t} catch (e: any) {\n\t\tconst error = reduceError(e);\n\t\tconst body = JSON.stringify(error);\n\t\tconst headers: Record<string, string> = {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\"MF-Experimental-Error-Stack\": \"true\",\n\t\t};\n\t\t// `workerd` drops response bodies for `HEAD` requests, so also carry the\n\t\t// serialised error in a header. Past roughly 16KB of encoded header the\n\t\t// runtime drops the whole response, so stay well under that; the body\n\t\t// remains the primary channel for every method that keeps one.\n\t\tconst encoded = encodeURIComponent(body);\n\t\tif (encoded.length <= 8192) {\n\t\t\theaders[\"MF-Experimental-Error-Stack-Payload\"] = encoded;\n\t\t}\n\t\treturn new Response(body, { status: 500, headers });\n\t}\n};\n\nexport default jsonError;\n", "\t\t\t\timport worker, * as OTHER_EXPORTS from \"C:\\\\Users\\\\dheer\\\\OneDrive\\\\Desktop\\\\Projects\\\\sticky-note\\\\sticky-server\\\\worker.js\";\n\t\t\t\timport * as __MIDDLEWARE_0__ from \"C:\\\\Users\\\\dheer\\\\AppData\\\\Roaming\\\\npm\\\\node_modules\\\\wrangler\\\\templates\\\\middleware\\\\middleware-ensure-req-body-drained.ts\";\nimport * as __MIDDLEWARE_1__ from \"C:\\\\Users\\\\dheer\\\\AppData\\\\Roaming\\\\npm\\\\node_modules\\\\wrangler\\\\templates\\\\middleware\\\\middleware-miniflare3-json-error.ts\";\n\n\t\t\t\texport * from \"C:\\\\Users\\\\dheer\\\\OneDrive\\\\Desktop\\\\Projects\\\\sticky-note\\\\sticky-server\\\\worker.js\";\n\t\t\t\tconst MIDDLEWARE_TEST_INJECT = \"__INJECT_FOR_TESTING_WRANGLER_MIDDLEWARE__\";\n\t\t\t\texport const __INTERNAL_WRANGLER_MIDDLEWARE__ = [\n\t\t\t\t\t\n\t\t\t\t\t__MIDDLEWARE_0__.default,__MIDDLEWARE_1__.default\n\t\t\t\t]\n\t\t\t\texport default worker;", "export type Awaitable<T> = T | Promise<T>;\n// TODO: allow dispatching more events?\nexport type Dispatcher = (\n\ttype: \"scheduled\",\n\tinit: { cron?: string }\n) => Awaitable<void>;\n\nexport type IncomingRequest = Request<\n\tunknown,\n\tIncomingRequestCfProperties<unknown>\n>;\n\nexport interface MiddlewareContext {\n\tdispatch: Dispatcher;\n\tnext(request: IncomingRequest, env: any): Awaitable<Response>;\n}\n\nexport type Middleware = (\n\trequest: IncomingRequest,\n\tenv: any,\n\tctx: ExecutionContext,\n\tmiddlewareCtx: MiddlewareContext\n) => Awaitable<Response>;\n\nconst __facade_middleware__: Middleware[] = [];\n\n// The register functions allow for the insertion of one or many middleware,\n// We register internal middleware first in the stack, but have no way of controlling\n// the order that addMiddleware is run in service workers so need an internal function.\nexport function __facade_register__(...args: (Middleware | Middleware[])[]) {\n\t__facade_middleware__.push(...args.flat());\n}\nexport function __facade_registerInternal__(\n\t...args: (Middleware | Middleware[])[]\n) {\n\t__facade_middleware__.unshift(...args.flat());\n}\n\nfunction __facade_invokeChain__(\n\trequest: IncomingRequest,\n\tenv: any,\n\tctx: ExecutionContext,\n\tdispatch: Dispatcher,\n\tmiddlewareChain: Middleware[]\n): Awaitable<Response> {\n\tconst [head, ...tail] = middlewareChain;\n\tconst middlewareCtx: MiddlewareContext = {\n\t\tdispatch,\n\t\tnext(newRequest, newEnv) {\n\t\t\treturn __facade_invokeChain__(newRequest, newEnv, ctx, dispatch, tail);\n\t\t},\n\t};\n\treturn head(request, env, ctx, middlewareCtx);\n}\n\nexport function __facade_invoke__(\n\trequest: IncomingRequest,\n\tenv: any,\n\tctx: ExecutionContext,\n\tdispatch: Dispatcher,\n\tfinalMiddleware: Middleware\n): Awaitable<Response> {\n\treturn __facade_invokeChain__(request, env, ctx, dispatch, [\n\t\t...__facade_middleware__,\n\t\tfinalMiddleware,\n\t]);\n}\n", "// This loads all middlewares exposed on the middleware object and then starts\n// the invocation chain. The big idea is that we can add these to the middleware\n// export dynamically through wrangler, or we can potentially let users directly\n// add them as a sort of \"plugin\" system.\n\nimport ENTRY, { __INTERNAL_WRANGLER_MIDDLEWARE__ } from \"C:\\\\Users\\\\dheer\\\\OneDrive\\\\Desktop\\\\Projects\\\\sticky-note\\\\sticky-server\\\\.wrangler\\\\tmp\\\\bundle-cuweP4\\\\middleware-insertion-facade.js\";\nimport { __facade_invoke__, __facade_register__, Dispatcher } from \"C:\\\\Users\\\\dheer\\\\AppData\\\\Roaming\\\\npm\\\\node_modules\\\\wrangler\\\\templates\\\\middleware\\\\common.ts\";\nimport type { WorkerEntrypointConstructor } from \"C:\\\\Users\\\\dheer\\\\OneDrive\\\\Desktop\\\\Projects\\\\sticky-note\\\\sticky-server\\\\.wrangler\\\\tmp\\\\bundle-cuweP4\\\\middleware-insertion-facade.js\";\n\n// Preserve all the exports from the worker\nexport * from \"C:\\\\Users\\\\dheer\\\\OneDrive\\\\Desktop\\\\Projects\\\\sticky-note\\\\sticky-server\\\\.wrangler\\\\tmp\\\\bundle-cuweP4\\\\middleware-insertion-facade.js\";\n\nclass __Facade_ScheduledController__ implements ScheduledController {\n\treadonly #noRetry: ScheduledController[\"noRetry\"];\n\n\tconstructor(\n\t\treadonly scheduledTime: number,\n\t\treadonly cron: string,\n\t\tnoRetry: ScheduledController[\"noRetry\"]\n\t) {\n\t\tthis.#noRetry = noRetry;\n\t}\n\n\tnoRetry() {\n\t\tif (!(this instanceof __Facade_ScheduledController__)) {\n\t\t\tthrow new TypeError(\"Illegal invocation\");\n\t\t}\n\t\t// Need to call native method immediately in case uncaught error thrown\n\t\tthis.#noRetry();\n\t}\n}\n\nfunction wrapExportedHandler(worker: ExportedHandler): ExportedHandler {\n\t// If we don't have any middleware defined, just return the handler as is\n\tif (\n\t\t__INTERNAL_WRANGLER_MIDDLEWARE__ === undefined ||\n\t\t__INTERNAL_WRANGLER_MIDDLEWARE__.length === 0\n\t) {\n\t\treturn worker;\n\t}\n\t// Otherwise, register all middleware once\n\tfor (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {\n\t\t__facade_register__(middleware);\n\t}\n\n\tconst fetchDispatcher: ExportedHandlerFetchHandler = function (\n\t\trequest,\n\t\tenv,\n\t\tctx\n\t) {\n\t\tif (worker.fetch === undefined) {\n\t\t\tthrow new Error(\"Handler does not export a fetch() function.\");\n\t\t}\n\t\treturn worker.fetch(request, env, ctx);\n\t};\n\n\treturn {\n\t\t...worker,\n\t\tfetch(request, env, ctx) {\n\t\t\tconst dispatcher: Dispatcher = function (type, init) {\n\t\t\t\tif (type === \"scheduled\" && worker.scheduled !== undefined) {\n\t\t\t\t\tconst controller = new __Facade_ScheduledController__(\n\t\t\t\t\t\tDate.now(),\n\t\t\t\t\t\tinit.cron ?? \"\",\n\t\t\t\t\t\t() => {}\n\t\t\t\t\t);\n\t\t\t\t\treturn worker.scheduled(controller, env, ctx);\n\t\t\t\t}\n\t\t\t};\n\t\t\treturn __facade_invoke__(request, env, ctx, dispatcher, fetchDispatcher);\n\t\t},\n\t};\n}\n\nfunction wrapWorkerEntrypoint(\n\tklass: WorkerEntrypointConstructor\n): WorkerEntrypointConstructor {\n\t// If we don't have any middleware defined, just return the handler as is\n\tif (\n\t\t__INTERNAL_WRANGLER_MIDDLEWARE__ === undefined ||\n\t\t__INTERNAL_WRANGLER_MIDDLEWARE__.length === 0\n\t) {\n\t\treturn klass;\n\t}\n\t// Otherwise, register all middleware once\n\tfor (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {\n\t\t__facade_register__(middleware);\n\t}\n\n\t// `extend`ing `klass` here so other RPC methods remain callable\n\treturn class extends klass {\n\t\t#fetchDispatcher: ExportedHandlerFetchHandler<Record<string, unknown>> = (\n\t\t\trequest,\n\t\t\tenv,\n\t\t\tctx\n\t\t) => {\n\t\t\tthis.env = env;\n\t\t\tthis.ctx = ctx;\n\t\t\tif (super.fetch === undefined) {\n\t\t\t\tthrow new Error(\"Entrypoint class does not define a fetch() function.\");\n\t\t\t}\n\t\t\treturn super.fetch(request);\n\t\t};\n\n\t\t#dispatcher: Dispatcher = (type, init) => {\n\t\t\tif (type === \"scheduled\" && super.scheduled !== undefined) {\n\t\t\t\tconst controller = new __Facade_ScheduledController__(\n\t\t\t\t\tDate.now(),\n\t\t\t\t\tinit.cron ?? \"\",\n\t\t\t\t\t() => {}\n\t\t\t\t);\n\t\t\t\treturn super.scheduled(controller);\n\t\t\t}\n\t\t};\n\n\t\tfetch(request: Request<unknown, IncomingRequestCfProperties>) {\n\t\t\treturn __facade_invoke__(\n\t\t\t\trequest,\n\t\t\t\tthis.env,\n\t\t\t\tthis.ctx,\n\t\t\t\tthis.#dispatcher,\n\t\t\t\tthis.#fetchDispatcher\n\t\t\t);\n\t\t}\n\t};\n}\n\nlet WRAPPED_ENTRY: ExportedHandler | WorkerEntrypointConstructor | undefined;\nif (typeof ENTRY === \"object\") {\n\tWRAPPED_ENTRY = wrapExportedHandler(ENTRY);\n} else if (typeof ENTRY === \"function\") {\n\tWRAPPED_ENTRY = wrapWorkerEntrypoint(ENTRY);\n}\nexport default WRAPPED_ENTRY;\n"],
3
+ "sources": ["../bundle-P0OxNJ/checked-fetch.js", "../../../adapters/cf-kv.js", "../../../mcp-tools.js", "../../../sticky-thread-do.js", "../../../worker.js", "../../../../../../../../AppData/Roaming/npm/node_modules/wrangler/templates/middleware/middleware-ensure-req-body-drained.ts", "../../../../../../../../AppData/Roaming/npm/node_modules/wrangler/templates/middleware/middleware-miniflare3-json-error.ts", "../bundle-P0OxNJ/middleware-insertion-facade.js", "../../../../../../../../AppData/Roaming/npm/node_modules/wrangler/templates/middleware/common.ts", "../bundle-P0OxNJ/middleware-loader.entry.ts"],
4
+ "sourceRoot": "C:\\Users\\dheer\\OneDrive\\Desktop\\Projects\\sticky-note\\sticky-server\\.wrangler\\tmp\\dev-a8XdEc",
5
+ "sourcesContent": ["const urls = new Set();\n\nfunction checkURL(request, init) {\n\tconst url =\n\t\trequest instanceof URL\n\t\t\t? request\n\t\t\t: new URL(\n\t\t\t\t\t(typeof request === \"string\" ? new Request(request, init) : request)\n\t\t\t\t\t\t.url\n\t\t\t\t);\n\tif (url.port && url.port !== \"443\" && url.protocol === \"https:\") {\n\t\tif (!urls.has(url.toString())) {\n\t\t\turls.add(url.toString());\n\t\t\tconsole.warn(\n\t\t\t\t`WARNING: known issue with \\`fetch()\\` requests to custom HTTPS ports in published Workers:\\n` +\n\t\t\t\t\t` - ${url.toString()} - the custom port will be ignored when the Worker is published using the \\`wrangler deploy\\` command.\\n`\n\t\t\t);\n\t\t}\n\t}\n}\n\nglobalThis.fetch = new Proxy(globalThis.fetch, {\n\tapply(target, thisArg, argArray) {\n\t\tconst [request, init] = argArray;\n\t\tcheckURL(request, init);\n\t\treturn Reflect.apply(target, thisArg, argArray);\n\t},\n});\n", "/**\n * Cloudflare KV adapter for Sticky Note V3.\n *\n * KV key schema (all prefixed by project):\n * {project}:thread:{uuid} \u2192 thread JSON\n * {project}:thread-index \u2192 JSON array of thread UUIDs\n * {project}:audit:{timestamp}:{uuid} \u2192 audit record JSON\n * {project}:audit-index \u2192 JSON array of audit keys\n * {project}:presence:{user} \u2192 presence record JSON\n * {project}:presence-index \u2192 JSON array of usernames\n * {project}:config \u2192 config JSON\n */\n\n// \u2500\u2500 Threads \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function getThreads(kv, project, filters = {}) {\n const indexKey = `${project}:thread-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n\n if (index.length === 0) return [];\n\n const threads = await Promise.all(\n index.map(async (id) => {\n const raw = await kv.get(`${project}:thread:${id}`);\n return raw ? JSON.parse(raw) : null;\n })\n );\n\n let result = threads.filter(Boolean);\n\n if (filters.status) {\n result = result.filter((t) => t.status === filters.status);\n }\n if (filters.q) {\n const q = filters.q.toLowerCase();\n result = result.filter(\n (t) =>\n (t.narrative || \"\").toLowerCase().includes(q) ||\n (t.handoff_summary || \"\").toLowerCase().includes(q) ||\n (t.last_note || \"\").toLowerCase().includes(q) ||\n (t.files_touched || []).some((f) => f.toLowerCase().includes(q))\n );\n }\n\n return result;\n}\n\nasync function getThread(kv, project, id) {\n const raw = await kv.get(`${project}:thread:${id}`);\n return raw ? JSON.parse(raw) : null;\n}\n\nasync function putThread(kv, project, thread) {\n const id = thread.id;\n await kv.put(`${project}:thread:${id}`, JSON.stringify(thread));\n\n // Update index\n const indexKey = `${project}:thread-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n if (!index.includes(id)) {\n index.push(id);\n await kv.put(indexKey, JSON.stringify(index));\n }\n}\n\nasync function deleteThread(kv, project, id) {\n // Tombstone: keep minimal record\n const existing = await getThread(kv, project, id);\n if (existing) {\n const tombstone = {\n id: existing.id,\n user: existing.user,\n status: \"expired\",\n closed_at: existing.closed_at || new Date().toISOString(),\n created_at: existing.created_at,\n };\n await kv.put(`${project}:thread:${id}`, JSON.stringify(tombstone));\n }\n}\n\n// \u2500\u2500 Audit \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function appendAudit(kv, project, record) {\n const ts = record.timestamp || new Date().toISOString();\n const uid = crypto.randomUUID();\n const key = `${project}:audit:${ts}:${uid}`;\n await kv.put(key, JSON.stringify(record));\n\n const indexKey = `${project}:audit-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n index.push(key);\n\n // Cap at 10,000 entries; trim oldest on overflow\n if (index.length > 10000) {\n const removed = index.splice(0, index.length - 10000);\n await Promise.all(removed.map((k) => kv.delete(k)));\n }\n await kv.put(indexKey, JSON.stringify(index));\n}\n\nasync function queryAudit(kv, project, filters = {}) {\n const indexKey = `${project}:audit-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n\n if (index.length === 0) return [];\n\n const records = await Promise.all(\n index.map(async (key) => {\n const raw = await kv.get(key);\n return raw ? JSON.parse(raw) : null;\n })\n );\n\n let result = records.filter(Boolean);\n\n if (filters.user) {\n result = result.filter((r) => r.user === filters.user);\n }\n if (filters.file) {\n result = result.filter((r) => (r.file || \"\").includes(filters.file));\n }\n if (filters.tool) {\n result = result.filter((r) => r.tool === filters.tool);\n }\n if (filters.since) {\n const since = new Date(filters.since).getTime();\n result = result.filter(\n (r) => new Date(r.timestamp || 0).getTime() >= since\n );\n }\n\n return result;\n}\n\n// \u2500\u2500 Presence \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst PRESENCE_TTL_SECONDS = 15 * 60; // 15 minutes\n\nasync function getPresence(kv, project) {\n const indexKey = `${project}:presence-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n\n if (index.length === 0) return [];\n\n const records = await Promise.all(\n index.map(async (user) => {\n const raw = await kv.get(`${project}:presence:${user}`);\n return raw ? JSON.parse(raw) : null;\n })\n );\n\n return records.filter(Boolean);\n}\n\nasync function upsertPresence(kv, project, record) {\n const user = record.user;\n await kv.put(`${project}:presence:${user}`, JSON.stringify(record), {\n expirationTtl: PRESENCE_TTL_SECONDS,\n });\n\n const indexKey = `${project}:presence-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n if (!index.includes(user)) {\n index.push(user);\n await kv.put(indexKey, JSON.stringify(index));\n }\n}\n\nasync function deletePresence(kv, project, user) {\n await kv.delete(`${project}:presence:${user}`);\n\n const indexKey = `${project}:presence-index`;\n const index = JSON.parse((await kv.get(indexKey)) || \"[]\");\n const filtered = index.filter((u) => u !== user);\n await kv.put(indexKey, JSON.stringify(filtered));\n}\n\n// \u2500\u2500 Events \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst MAX_CHUNK_BYTES = 2 * 1024 * 1024; // 2 MB per KV value\n\nasync function getEvents(kv, project, threadId) {\n const metaKey = `${project}:thread:${threadId}`;\n const meta = await kv.get(metaKey, { type: \"json\" }).catch(() => null);\n const chunkCount = (meta && meta._event_chunks) || 0;\n\n if (chunkCount === 0) {\n // Try legacy single-key format\n const single = await kv.get(`${metaKey}:events`, { type: \"json\" }).catch(() => null);\n return Array.isArray(single) ? single : [];\n }\n\n const chunks = await Promise.all(\n Array.from({ length: chunkCount }, (_, i) =>\n kv.get(`${metaKey}:events:${i}`, { type: \"json\" }).catch(() => [])\n )\n );\n return chunks.flat().filter(Boolean);\n}\n\nasync function appendEvents(kv, project, threadId, newEvents) {\n if (!newEvents || newEvents.length === 0) return;\n\n const metaKey = `${project}:thread:${threadId}`;\n const meta = await kv.get(metaKey, { type: \"json\" }).catch(() => ({}));\n const chunkCount = (meta && meta._event_chunks) || 0;\n\n let currentChunkIdx = chunkCount === 0 ? 0 : chunkCount - 1;\n let currentChunk = [];\n if (chunkCount > 0) {\n currentChunk =\n (await kv.get(`${metaKey}:events:${currentChunkIdx}`, { type: \"json\" }).catch(() => [])) ||\n [];\n }\n\n const enc = new TextEncoder();\n let chunkBytes = enc.encode(JSON.stringify(currentChunk)).length;\n\n for (const event of newEvents) {\n const eventBytes = enc.encode(JSON.stringify(event)).length;\n if (chunkBytes + eventBytes > MAX_CHUNK_BYTES && currentChunk.length > 0) {\n await kv.put(`${metaKey}:events:${currentChunkIdx}`, JSON.stringify(currentChunk));\n currentChunkIdx++;\n currentChunk = [];\n chunkBytes = 0;\n }\n currentChunk.push(event);\n chunkBytes += eventBytes;\n }\n await kv.put(`${metaKey}:events:${currentChunkIdx}`, JSON.stringify(currentChunk));\n\n const newMeta = { ...(meta || {}), _event_chunks: currentChunkIdx + 1 };\n await kv.put(metaKey, JSON.stringify(newMeta));\n}\n\n// \u2500\u2500 Config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function getConfig(kv, project) {\n const raw = await kv.get(`${project}:config`);\n return raw ? JSON.parse(raw) : null;\n}\n\nasync function putConfig(kv, project, config) {\n await kv.put(`${project}:config`, JSON.stringify(config));\n}\n\n// \u2500\u2500 Export \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport {\n getThreads,\n getThread,\n putThread,\n deleteThread,\n appendAudit,\n queryAudit,\n getPresence,\n upsertPresence,\n deletePresence,\n getConfig,\n putConfig,\n getEvents,\n appendEvents,\n};\n", "// sticky-server/mcp-tools.js\n\n// crypto.randomUUID() is a Workers global \u2014 no import needed unless nodejs_compat is set.\n// We use the global directly to avoid a hard dep on node:crypto when that flag isn't active.\n\nexport const EVENT_TYPES = Object.freeze({\n SESSION_OPEN: \"session_open\",\n SESSION_CLOSE: \"session_close\",\n USER_PROMPT: \"user_prompt\",\n CHECKPOINT: \"checkpoint\",\n});\n\nexport const MCP_TOOL_DEFINITIONS = [\n {\n name: \"open_thread\",\n description: \"Call at session start. Creates a new thread and returns its thread_id for use in subsequent append_event and close_thread calls.\",\n inputSchema: {\n type: \"object\",\n properties: {\n prompt: { type: \"string\", description: \"Verbatim first user prompt\" },\n branch: { type: \"string\", description: \"Current git branch\" },\n user: { type: \"string\", description: \"Username\" },\n model: { type: \"string\", description: \"Model ID (e.g. claude-sonnet-4-6)\" },\n mcp_servers: { type: \"array\", items: { type: \"string\" }, description: \"Connected MCP server names\" },\n claude_md_hash: { type: \"string\", description: \"SHA256 of CLAUDE.md content (optional)\" },\n },\n required: [\"prompt\", \"user\"],\n },\n },\n {\n name: \"append_event\",\n description: \"Call for every action in the session. Records one event (user_prompt, ai_thinking, ai_response, tool_call, tool_result, tool_error, tool_denied, context_compressed, git_commit, subagent_spawn, subagent_result, checkpoint). Do not call for streaming tokens or internal transport retries.\",\n inputSchema: {\n type: \"object\",\n properties: {\n thread_id: { type: \"string\", description: \"thread_id returned by open_thread\" },\n type: { type: \"string\", description: \"Event type (see description)\" },\n data: { type: \"object\", description: \"Event-specific payload\" },\n },\n required: [\"thread_id\", \"type\", \"data\"],\n },\n },\n {\n name: \"set_checkpoint\",\n description: \"Call when the user switches to a different topic mid-session. Marks subsequent events with the new topic for attribution.\",\n inputSchema: {\n type: \"object\",\n properties: {\n thread_id: { type: \"string\" },\n topic: { type: \"string\", description: \"Short description of new work topic\" },\n },\n required: [\"thread_id\", \"topic\"],\n },\n },\n {\n name: \"close_thread\",\n description: \"Call at session end. Writes the session_close event, updates thread status to closed, and triggers a git commit of thread metadata.\",\n inputSchema: {\n type: \"object\",\n properties: {\n thread_id: { type: \"string\" },\n narrative: { type: \"string\", description: \"Summary of what was accomplished\" },\n work_type: { type: \"string\", description: \"e.g. bug-fix, feature-development, debugging, refactor, documentation\" },\n handoff_summary: { type: \"string\", description: \"Notes for teammates picking this up\" },\n failed_approaches: { type: \"array\", items: { type: \"string\" }, description: \"What was tried and didn't work\" },\n files_touched: { type: \"array\", items: { type: \"string\" }, description: \"Files modified during session\" },\n },\n required: [\"thread_id\", \"narrative\"],\n },\n },\n];\n\nexport async function handleMcpTool(toolName, input, env, project, getOrCreateDO) {\n switch (toolName) {\n case \"open_thread\": return handleOpenThread(input, env, project, getOrCreateDO);\n case \"append_event\": return handleAppendEvent(input, env, project, getOrCreateDO);\n case \"set_checkpoint\": return handleSetCheckpoint(input, env, project, getOrCreateDO);\n case \"close_thread\": return handleCloseThread(input, env, project, getOrCreateDO);\n default: throw new Error(`Unknown tool: ${toolName}`);\n }\n}\n\nasync function handleOpenThread(input, env, project, getOrCreateDO) {\n const threadId = crypto.randomUUID();\n const now = new Date().toISOString();\n\n const threadMeta = {\n id: threadId,\n status: \"open\",\n user: input.user,\n branch: input.branch || \"\",\n created_at: now,\n last_activity_at: now,\n files_touched: [],\n narrative: \"\",\n tool: \"claude-code\",\n session_id: null, // remote sessions don't have a local session_id\n _event_chunks: 0,\n };\n\n const metaKey = `${project}:thread:${threadId}`;\n await env.STICKY_KV.put(metaKey, JSON.stringify(threadMeta));\n\n const openEvent = {\n ts: now, type: EVENT_TYPES.SESSION_OPEN, session_id: null,\n data: {\n model: input.model || null,\n branch: input.branch || null,\n user: input.user,\n mcp_servers: input.mcp_servers || [],\n claude_md_hash: input.claude_md_hash || null,\n },\n };\n const promptEvent = {\n ts: now, type: EVENT_TYPES.USER_PROMPT, session_id: null,\n data: { content: input.prompt },\n };\n\n const do_stub = getOrCreateDO(env, threadId);\n await do_stub.fetch(new Request(\"http://do/do/open\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ thread_id: threadId, project, events: [openEvent, promptEvent] }),\n }));\n\n // Async GitHub commit \u2014 fire and forget\n _commitThreadToGit(env, project, threadId, getOrCreateDO).catch(() => {});\n\n return { thread_id: threadId };\n}\n\nasync function handleAppendEvent(input, env, project, getOrCreateDO) {\n const { thread_id, type, data } = input;\n\n const metaKey = `${project}:thread:${thread_id}`;\n const exists = await env.STICKY_KV.get(metaKey, { type: \"text\" });\n if (!exists) return { ok: false, error: \"unknown thread_id\" };\n\n const event = { ts: new Date().toISOString(), type, session_id: null, data: data || {} };\n\n const do_stub = getOrCreateDO(env, thread_id);\n await do_stub.fetch(new Request(\"http://do/do/append\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ event }),\n }));\n\n return { ok: true };\n}\n\nasync function handleSetCheckpoint(input, env, project, getOrCreateDO) {\n return handleAppendEvent(\n { thread_id: input.thread_id, type: EVENT_TYPES.CHECKPOINT, data: { topic: input.topic } },\n env, project, getOrCreateDO\n );\n}\n\nasync function handleCloseThread(input, env, project, getOrCreateDO) {\n const { thread_id, narrative, work_type, handoff_summary, failed_approaches, files_touched } = input;\n const now = new Date().toISOString();\n\n const closeEvent = {\n ts: now, type: EVENT_TYPES.SESSION_CLOSE, session_id: null,\n data: {\n narrative,\n work_type: work_type || \"general\",\n handoff_summary: handoff_summary || \"\",\n failed_approaches: failed_approaches || [],\n files_touched: files_touched || [],\n },\n };\n\n const do_stub = getOrCreateDO(env, thread_id);\n await do_stub.fetch(new Request(\"http://do/do/close\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ close_event: closeEvent }),\n }));\n\n // Update thread metadata\n const metaKey = `${project}:thread:${thread_id}`;\n const meta = await env.STICKY_KV.get(metaKey, { type: \"json\" }).catch(() => ({})) || {};\n meta.status = \"closed\";\n meta.closed_at = now;\n meta.narrative = narrative;\n meta.work_type = work_type || \"general\";\n meta.handoff_summary = handoff_summary || \"\";\n meta.failed_approaches = failed_approaches || [];\n if (files_touched) {\n meta.files_touched = [...new Set([...(meta.files_touched || []), ...files_touched])];\n }\n await env.STICKY_KV.put(metaKey, JSON.stringify(meta));\n\n // GitHub commit \u2014 synchronous (awaited) for close_thread\n await _commitThreadToGit(env, project, thread_id, getOrCreateDO);\n\n return { ok: true };\n}\n\n// Internal helper \u2014 used by open_thread (fire-and-forget), close_thread (awaited), and crash recovery\nexport async function _commitThreadToGit(env, project, threadId, getOrCreateDO) {\n const kv = env.STICKY_KV;\n\n // Always maintain the threads index (even without GitHub creds).\n // NOTE: There is a known read-modify-write race when two open_thread calls run\n // concurrently \u2014 both may read the same list before either writes back. This is\n // self-healing: the next close_thread call will re-add any dropped ID, and the\n // list is always capped at 500, so no corruption accumulates. A separate \"index DO\"\n // would be required to eliminate the race entirely, which is out of scope here.\n const threadsListKey = `${project}:threads_index`;\n let threadIds = await kv.get(threadsListKey, { type: \"json\" }).catch(() => []) || [];\n if (!threadIds.includes(threadId)) {\n threadIds = [threadId, ...threadIds].slice(0, 500); // cap at 500\n await kv.put(threadsListKey, JSON.stringify(threadIds));\n }\n\n // GitHub commit requires credentials \u2014 skip if not configured\n const pat = env.GITHUB_PAT;\n const repoFull = env.GITHUB_REPO; // format: \"owner/repo\"\n if (!pat || !repoFull) return;\n const [owner, repo] = repoFull.split(\"/\");\n if (!owner || !repo) return;\n\n // threadIds is already populated above \u2014 no second KV read needed\n const allMeta = await Promise.all(\n threadIds.map(id => kv.get(`${project}:thread:${id}`, { type: \"json\" }).catch(() => null))\n );\n const threads = allMeta.filter(Boolean).map(m => {\n // Strip internal KV fields before writing to git\n const { _event_chunks, _last_recovery_attempt, ...rest } = m;\n return rest;\n });\n\n const newContent = JSON.stringify({ version: \"2\", project, threads }, null, 2) + \"\\n\";\n\n // Use StickyThread DO for serialized GitHub commit (avoids race conditions)\n const do_stub = getOrCreateDO(env, threadId);\n await do_stub.fetch(new Request(\"http://do/do/github-commit\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n owner, repo,\n path: \".sticky-note/sticky-note.json\",\n content: newContent,\n message: `chore(sticky-note): sync thread ${threadId.slice(0, 8)}`,\n pat,\n }),\n }));\n}\n", "// sticky-server/sticky-thread-do.js\nimport { appendEvents } from \"./adapters/cf-kv.js\";\n\nexport class StickyThread {\n constructor(state, env) {\n this.state = state;\n this.env = env;\n this.buffer = [];\n this.flushThreshold = 10;\n this.threadId = null;\n this.project = \"default\";\n }\n\n async fetch(request) {\n const url = new URL(request.url);\n const body = await request.json().catch(() => ({}));\n\n if (url.pathname === \"/do/open\") {\n this.threadId = body.thread_id;\n this.project = body.project || \"default\";\n for (const ev of (body.events || [])) this.buffer.push(ev);\n await this._scheduleFlush();\n return new Response(JSON.stringify({ ok: true, thread_id: this.threadId }), {\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n if (url.pathname === \"/do/append\") {\n const event = body.event;\n if (event) this.buffer.push(event);\n if (this.buffer.length >= this.flushThreshold) {\n await this._flush();\n } else {\n await this._scheduleFlush();\n }\n return new Response(JSON.stringify({ ok: true }), {\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n if (url.pathname === \"/do/close\") {\n const closeEvent = body.close_event;\n if (closeEvent) this.buffer.push(closeEvent);\n await this._flush();\n try { await this.state.storage.deleteAlarm(); } catch (_) {}\n return new Response(JSON.stringify({ ok: true, flushed: true }), {\n headers: { \"Content-Type\": \"application/json\" },\n });\n }\n\n if (url.pathname === \"/do/github-commit\") {\n // Serialized GitHub REST write for this thread\n const result = await this._githubCommit(body);\n return new Response(JSON.stringify(result), {\n headers: { \"Content-Type\": \"application/json\" },\n status: result.ok ? 200 : 500,\n });\n }\n\n return new Response(\"not found\", { status: 404 });\n }\n\n async alarm() {\n if (this.buffer.length > 0) {\n await this._flush();\n }\n }\n\n async _scheduleFlush() {\n try {\n const existing = await this.state.storage.getAlarm();\n if (!existing) {\n await this.state.storage.setAlarm(Date.now() + 5000);\n }\n } catch (_) {}\n }\n\n async _flush() {\n if (this.buffer.length === 0 || !this.threadId) return;\n const toFlush = this.buffer.splice(0);\n try {\n await appendEvents(this.env.STICKY_KV, this.project, this.threadId, toFlush);\n } catch (err) {\n // Put unwritten events back at front of buffer for retry\n this.buffer.unshift(...toFlush);\n }\n }\n\n async _githubCommit(body) {\n const { owner, repo, path: filePath, content, message, pat } = body;\n if (!pat) return { ok: false, error: \"no PAT\" };\n const apiBase = `https://api.github.com/repos/${owner}/${repo}/contents/${filePath}`;\n const headers = {\n Authorization: `Bearer ${pat}`,\n Accept: \"application/vnd.github+json\",\n \"Content-Type\": \"application/json\",\n \"User-Agent\": \"sticky-note-worker\",\n };\n\n let sha = null;\n let retries = 3;\n while (retries-- > 0) {\n // GET current SHA\n const getResp = await fetch(apiBase, { headers }).catch(() => null);\n if (getResp && getResp.ok) {\n const data = await getResp.json().catch(() => ({}));\n sha = data.sha || null;\n }\n\n // PUT with SHA\n const putBody = {\n message,\n content: btoa(unescape(encodeURIComponent(content))), // base64 encode UTF-8\n ...(sha ? { sha } : {}),\n };\n const putResp = await fetch(apiBase, {\n method: \"PUT\",\n headers,\n body: JSON.stringify(putBody),\n }).catch(() => null);\n\n if (!putResp) return { ok: false, error: \"network error\" };\n if (putResp.ok) return { ok: true };\n if (putResp.status === 409) {\n // SHA mismatch \u2014 retry after backoff\n await new Promise(r => setTimeout(r, 200));\n continue;\n }\n const errBody = await putResp.json().catch(() => ({}));\n return { ok: false, error: errBody.message || `HTTP ${putResp.status}` };\n }\n return { ok: false, error: \"max retries exceeded (409 conflict)\" };\n }\n}\n", "/**\n * Sticky Note V3 \u2014 Cloudflare Worker\n *\n * REST API backed by Cloudflare KV.\n * Auth: X-Sticky-API-Key header matched against STICKY_API_KEY env var.\n * Project routing: X-Sticky-Project header (auto-set by client hooks).\n *\n * Endpoints:\n * POST /threads \u2014 create thread\n * GET /threads \u2014 list threads (?status=, ?q=)\n * GET /threads/:id \u2014 get thread\n * PUT /threads/:id \u2014 update thread\n * DELETE /threads/:id \u2014 tombstone thread\n * POST /threads/:id/events \u2014 append event batch (local session push)\n * GET /threads/:id/events \u2014 retrieve all stored events\n * GET /audit \u2014 query audit (?file=, ?user=, ?since=, ?tool=)\n * POST /audit \u2014 append audit record\n * GET /presence \u2014 list active developers\n * POST /presence \u2014 heartbeat upsert\n * DELETE /presence/:user \u2014 clear presence\n * GET /config \u2014 get team config\n * PUT /config \u2014 update team config\n */\n\nimport * as adapter from \"./adapters/cf-kv.js\";\nimport { MCP_TOOL_DEFINITIONS, handleMcpTool, _commitThreadToGit, EVENT_TYPES } from \"./mcp-tools.js\";\n\n// \u2500\u2500 Helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction json(data, status = 200) {\n return new Response(JSON.stringify(data), {\n status,\n headers: { \"Content-Type\": \"application/json\" },\n });\n}\n\nfunction error(message, status = 400) {\n return json({ error: message }, status);\n}\n\nfunction authenticate(request, env) {\n const key = request.headers.get(\"X-Sticky-API-Key\");\n if (!env.STICKY_API_KEY) return true; // no key configured = open\n return key === env.STICKY_API_KEY;\n}\n\nfunction getProject(request) {\n return request.headers.get(\"X-Sticky-Project\") || \"default\";\n}\n\n// \u2500\u2500 Router \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction matchRoute(method, pathname) {\n // Thread routes\n if (method === \"POST\" && pathname === \"/threads\") return { handler: \"createThread\" };\n if (method === \"GET\" && pathname === \"/threads\") return { handler: \"listThreads\" };\n if (method === \"POST\" && pathname.match(/^\\/threads\\/[^/]+\\/events$/)) {\n const id = pathname.split(\"/\")[2];\n return { handler: \"appendThreadEvents\", id };\n }\n if (method === \"GET\" && pathname.match(/^\\/threads\\/[^/]+\\/events$/)) {\n const id = pathname.split(\"/\")[2];\n return { handler: \"getThreadEvents\", id };\n }\n if (method === \"GET\" && pathname.startsWith(\"/threads/\")) {\n return { handler: \"getThread\", id: pathname.slice(\"/threads/\".length) };\n }\n if (method === \"PUT\" && pathname.startsWith(\"/threads/\")) {\n return { handler: \"updateThread\", id: pathname.slice(\"/threads/\".length) };\n }\n if (method === \"DELETE\" && pathname.startsWith(\"/threads/\")) {\n return { handler: \"deleteThread\", id: pathname.slice(\"/threads/\".length) };\n }\n\n // Audit routes\n if (method === \"GET\" && pathname === \"/audit\") return { handler: \"queryAudit\" };\n if (method === \"POST\" && pathname === \"/audit\") return { handler: \"appendAudit\" };\n\n // Presence routes\n if (method === \"GET\" && pathname === \"/presence\") return { handler: \"getPresence\" };\n if (method === \"POST\" && pathname === \"/presence\") return { handler: \"upsertPresence\" };\n if (method === \"DELETE\" && pathname.startsWith(\"/presence/\")) {\n return { handler: \"deletePresence\", user: decodeURIComponent(pathname.slice(\"/presence/\".length)) };\n }\n\n // Config routes\n if (method === \"GET\" && pathname === \"/config\") return { handler: \"getConfig\" };\n if (method === \"PUT\" && pathname === \"/config\") return { handler: \"putConfig\" };\n\n // MCP routes\n if (method === \"GET\" && pathname === \"/mcp\") return { handler: \"mcpListTools\" };\n if (method === \"POST\" && pathname === \"/mcp\") return { handler: \"mcpCallTool\" };\n\n // Health\n if (method === \"GET\" && pathname === \"/health\") return { handler: \"health\" };\n\n return null;\n}\n\n// \u2500\u2500 Handlers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nconst handlers = {\n async health() {\n return json({ status: \"ok\", version: \"3.0.0\" });\n },\n\n // \u2500\u2500 Threads \u2500\u2500\n\n async createThread(request, kv, project) {\n const thread = await request.json();\n if (!thread.id) return error(\"thread.id is required\");\n await adapter.putThread(kv, project, thread);\n return json(thread, 201);\n },\n\n async listThreads(request, kv, project) {\n const url = new URL(request.url);\n const filters = {\n status: url.searchParams.get(\"status\") || undefined,\n q: url.searchParams.get(\"q\") || undefined,\n };\n const threads = await adapter.getThreads(kv, project, filters);\n return json({ threads });\n },\n\n async getThread(_request, kv, project, { id }) {\n const thread = await adapter.getThread(kv, project, id);\n if (!thread) return error(\"Thread not found\", 404);\n return json(thread);\n },\n\n async updateThread(request, kv, project, { id }) {\n const thread = await request.json();\n thread.id = id;\n await adapter.putThread(kv, project, thread);\n return json(thread);\n },\n\n async deleteThread(_request, kv, project, { id }) {\n await adapter.deleteThread(kv, project, id);\n return json({ deleted: id });\n },\n\n // \u2500\u2500 Thread Events \u2500\u2500\n\n async appendThreadEvents(request, kv, project, { id }) {\n const body = await request.json().catch(() => ({}));\n const events = Array.isArray(body.events) ? body.events : [];\n await adapter.appendEvents(kv, project, id, events);\n return json({ ok: true, appended: events.length });\n },\n\n async getThreadEvents(_request, kv, project, { id }) {\n const events = await adapter.getEvents(kv, project, id);\n return json({ events });\n },\n\n // \u2500\u2500 Audit \u2500\u2500\n\n async queryAudit(request, kv, project) {\n const url = new URL(request.url);\n const filters = {\n user: url.searchParams.get(\"user\") || undefined,\n file: url.searchParams.get(\"file\") || undefined,\n tool: url.searchParams.get(\"tool\") || undefined,\n since: url.searchParams.get(\"since\") || undefined,\n };\n const records = await adapter.queryAudit(kv, project, filters);\n return json({ audit: records });\n },\n\n async appendAudit(request, kv, project) {\n const record = await request.json();\n await adapter.appendAudit(kv, project, record);\n return json({ ok: true }, 201);\n },\n\n // \u2500\u2500 Presence \u2500\u2500\n\n async getPresence(_request, kv, project) {\n const records = await adapter.getPresence(kv, project);\n return json({ presence: records });\n },\n\n async upsertPresence(request, kv, project) {\n const record = await request.json();\n if (!record.user) return error(\"record.user is required\");\n await adapter.upsertPresence(kv, project, record);\n return json({ ok: true });\n },\n\n async deletePresence(_request, kv, project, { user }) {\n await adapter.deletePresence(kv, project, user);\n return json({ deleted: user });\n },\n\n // \u2500\u2500 MCP \u2500\u2500\n\n async mcpListTools() {\n return json({ tools: MCP_TOOL_DEFINITIONS });\n },\n\n async mcpCallTool(request, _kv, project, _route, env) {\n const body = await request.json().catch(() => ({}));\n const toolName = body.tool || body.name;\n const toolInput = body.input || body.arguments || {};\n if (!toolName) return error(\"tool name required\");\n try {\n const result = await handleMcpTool(toolName, toolInput, env, project, getOrCreateDO);\n return json({ content: [{ type: \"text\", text: JSON.stringify(result) }] });\n } catch (err) {\n return error(err.message, 400);\n }\n },\n\n // \u2500\u2500 Config \u2500\u2500\n\n async getConfig(_request, kv, project) {\n const config = await adapter.getConfig(kv, project);\n if (!config) return json({});\n return json(config);\n },\n\n async putConfig(request, kv, project) {\n const config = await request.json();\n await adapter.putConfig(kv, project, config);\n return json(config);\n },\n};\n\n// \u2500\u2500 Durable Object helper \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nfunction getOrCreateDO(env, threadId) {\n const id = env.STICKY_THREAD.idFromName(threadId);\n return env.STICKY_THREAD.get(id);\n}\n\n// \u2500\u2500 Worker entry point \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport default {\n async fetch(request, env) {\n // CORS preflight\n if (request.method === \"OPTIONS\") {\n return new Response(null, {\n status: 204,\n headers: {\n \"Access-Control-Allow-Origin\": \"*\",\n \"Access-Control-Allow-Methods\": \"GET, POST, PUT, DELETE, OPTIONS\",\n \"Access-Control-Allow-Headers\": \"Content-Type, X-Sticky-API-Key, X-Sticky-Project\",\n },\n });\n }\n\n // Auth\n if (!authenticate(request, env)) {\n return error(\"Unauthorized\", 401);\n }\n\n const url = new URL(request.url);\n const route = matchRoute(request.method, url.pathname);\n\n if (!route) {\n return error(\"Not found\", 404);\n }\n\n const project = getProject(request);\n const kv = env.STICKY_KV;\n\n try {\n const handler = handlers[route.handler];\n const response = await handler(request, kv, project, route, env);\n\n // Add CORS headers to all responses\n const headers = new Headers(response.headers);\n headers.set(\"Access-Control-Allow-Origin\", \"*\");\n return new Response(response.body, {\n status: response.status,\n headers,\n });\n } catch (err) {\n return error(`Internal error: ${err.message}`, 500);\n }\n },\n\n async scheduled(event, env, ctx) {\n ctx.waitUntil(runCrashRecovery(env));\n },\n};\n\n// \u2500\u2500 Crash recovery (cron) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nasync function runCrashRecovery(env) {\n const projects = [\"default\"]; // TODO: discover from KV index if multi-project\n const staleThresholdMs = 30 * 60 * 1000; // 30 minutes\n const now = Date.now();\n\n for (const project of projects) {\n const threadsListKey = `${project}:threads_index`;\n const threadIds = await env.STICKY_KV.get(threadsListKey, { type: \"json\" })\n .catch(() => []) || [];\n\n const metas = await Promise.all(\n threadIds.map(id =>\n env.STICKY_KV.get(`${project}:thread:${id}`, { type: \"json\" }).catch(() => null)\n )\n );\n for (let i = 0; i < threadIds.length; i++) {\n const meta = metas[i];\n const threadId = threadIds[i];\n if (!meta || meta.status !== \"open\") continue;\n\n const lastActivity = new Date(meta.last_activity_at || meta.created_at).getTime();\n if (now - lastActivity < staleThresholdMs) continue;\n\n // Track last_recovery_attempt to avoid hammering\n const lastAttempt = meta._last_recovery_attempt || 0;\n if (now - lastAttempt < 5 * 60 * 1000) continue; // skip if tried < 5min ago\n\n // Thread is stale \u2014 flush DO buffer and mark as stale\n try {\n const do_stub = getOrCreateDO(env, threadId);\n const recovery_event = {\n ts: new Date().toISOString(), type: EVENT_TYPES.SESSION_CLOSE, session_id: null,\n data: { narrative: \"[recovered by cron]\", work_type: \"unknown\", handoff_summary: \"\", failed_approaches: [], files_touched: [] },\n };\n\n meta._last_recovery_attempt = now;\n await env.STICKY_KV.put(metaKey, JSON.stringify(meta));\n\n await do_stub.fetch(new Request(\"http://do/do/close\", {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ close_event: recovery_event }),\n }));\n\n meta.status = \"stale\";\n meta.last_activity_at = new Date().toISOString();\n await env.STICKY_KV.put(metaKey, JSON.stringify(meta));\n\n // GitHub commit for stale thread \u2014 commit the already-written stale metadata directly\n await _commitThreadToGit(env, project, threadId, getOrCreateDO).catch(() => {});\n } catch (_) {\n // best-effort \u2014 log to console for observability\n console.error(`[sticky-note] crash recovery failed for thread ${threadId}`);\n }\n }\n }\n}\n\nexport { StickyThread } from \"./sticky-thread-do.js\";\n", "import type { Middleware } from \"./common\";\n\nconst drainBody: Middleware = async (request, env, _ctx, middlewareCtx) => {\n\ttry {\n\t\treturn await middlewareCtx.next(request, env);\n\t} finally {\n\t\ttry {\n\t\t\tif (request.body !== null && !request.bodyUsed) {\n\t\t\t\tconst reader = request.body.getReader();\n\t\t\t\twhile (!(await reader.read()).done) {}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.error(\"Failed to drain the unused request body.\", e);\n\t\t}\n\t}\n};\n\nexport default drainBody;\n", "import type { Middleware } from \"./common\";\n\ninterface JsonError {\n\tmessage?: string;\n\tname?: string;\n\tstack?: string;\n\tcause?: JsonError;\n}\n\nfunction reduceError(e: any): JsonError {\n\treturn {\n\t\tname: e?.name,\n\t\tmessage: e?.message ?? String(e),\n\t\tstack: e?.stack,\n\t\tcause: e?.cause === undefined ? undefined : reduceError(e.cause),\n\t};\n}\n\n// See comment in `bundle.ts` for details on why this is needed\nconst jsonError: Middleware = async (request, env, _ctx, middlewareCtx) => {\n\ttry {\n\t\treturn await middlewareCtx.next(request, env);\n\t} catch (e: any) {\n\t\tconst error = reduceError(e);\n\t\tconst body = JSON.stringify(error);\n\t\tconst headers: Record<string, string> = {\n\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\"MF-Experimental-Error-Stack\": \"true\",\n\t\t};\n\t\t// `workerd` drops response bodies for `HEAD` requests, so also carry the\n\t\t// serialised error in a header. Past roughly 16KB of encoded header the\n\t\t// runtime drops the whole response, so stay well under that; the body\n\t\t// remains the primary channel for every method that keeps one.\n\t\tconst encoded = encodeURIComponent(body);\n\t\tif (encoded.length <= 8192) {\n\t\t\theaders[\"MF-Experimental-Error-Stack-Payload\"] = encoded;\n\t\t}\n\t\treturn new Response(body, { status: 500, headers });\n\t}\n};\n\nexport default jsonError;\n", "\t\t\t\timport worker, * as OTHER_EXPORTS from \"C:\\\\Users\\\\dheer\\\\OneDrive\\\\Desktop\\\\Projects\\\\sticky-note\\\\sticky-server\\\\worker.js\";\n\t\t\t\timport * as __MIDDLEWARE_0__ from \"C:\\\\Users\\\\dheer\\\\AppData\\\\Roaming\\\\npm\\\\node_modules\\\\wrangler\\\\templates\\\\middleware\\\\middleware-ensure-req-body-drained.ts\";\nimport * as __MIDDLEWARE_1__ from \"C:\\\\Users\\\\dheer\\\\AppData\\\\Roaming\\\\npm\\\\node_modules\\\\wrangler\\\\templates\\\\middleware\\\\middleware-miniflare3-json-error.ts\";\n\n\t\t\t\texport * from \"C:\\\\Users\\\\dheer\\\\OneDrive\\\\Desktop\\\\Projects\\\\sticky-note\\\\sticky-server\\\\worker.js\";\n\t\t\t\tconst MIDDLEWARE_TEST_INJECT = \"__INJECT_FOR_TESTING_WRANGLER_MIDDLEWARE__\";\n\t\t\t\texport const __INTERNAL_WRANGLER_MIDDLEWARE__ = [\n\t\t\t\t\t\n\t\t\t\t\t__MIDDLEWARE_0__.default,__MIDDLEWARE_1__.default\n\t\t\t\t]\n\t\t\t\texport default worker;", "export type Awaitable<T> = T | Promise<T>;\n// TODO: allow dispatching more events?\nexport type Dispatcher = (\n\ttype: \"scheduled\",\n\tinit: { cron?: string }\n) => Awaitable<void>;\n\nexport type IncomingRequest = Request<\n\tunknown,\n\tIncomingRequestCfProperties<unknown>\n>;\n\nexport interface MiddlewareContext {\n\tdispatch: Dispatcher;\n\tnext(request: IncomingRequest, env: any): Awaitable<Response>;\n}\n\nexport type Middleware = (\n\trequest: IncomingRequest,\n\tenv: any,\n\tctx: ExecutionContext,\n\tmiddlewareCtx: MiddlewareContext\n) => Awaitable<Response>;\n\nconst __facade_middleware__: Middleware[] = [];\n\n// The register functions allow for the insertion of one or many middleware,\n// We register internal middleware first in the stack, but have no way of controlling\n// the order that addMiddleware is run in service workers so need an internal function.\nexport function __facade_register__(...args: (Middleware | Middleware[])[]) {\n\t__facade_middleware__.push(...args.flat());\n}\nexport function __facade_registerInternal__(\n\t...args: (Middleware | Middleware[])[]\n) {\n\t__facade_middleware__.unshift(...args.flat());\n}\n\nfunction __facade_invokeChain__(\n\trequest: IncomingRequest,\n\tenv: any,\n\tctx: ExecutionContext,\n\tdispatch: Dispatcher,\n\tmiddlewareChain: Middleware[]\n): Awaitable<Response> {\n\tconst [head, ...tail] = middlewareChain;\n\tconst middlewareCtx: MiddlewareContext = {\n\t\tdispatch,\n\t\tnext(newRequest, newEnv) {\n\t\t\treturn __facade_invokeChain__(newRequest, newEnv, ctx, dispatch, tail);\n\t\t},\n\t};\n\treturn head(request, env, ctx, middlewareCtx);\n}\n\nexport function __facade_invoke__(\n\trequest: IncomingRequest,\n\tenv: any,\n\tctx: ExecutionContext,\n\tdispatch: Dispatcher,\n\tfinalMiddleware: Middleware\n): Awaitable<Response> {\n\treturn __facade_invokeChain__(request, env, ctx, dispatch, [\n\t\t...__facade_middleware__,\n\t\tfinalMiddleware,\n\t]);\n}\n", "// This loads all middlewares exposed on the middleware object and then starts\n// the invocation chain. The big idea is that we can add these to the middleware\n// export dynamically through wrangler, or we can potentially let users directly\n// add them as a sort of \"plugin\" system.\n\nimport ENTRY, { __INTERNAL_WRANGLER_MIDDLEWARE__ } from \"C:\\\\Users\\\\dheer\\\\OneDrive\\\\Desktop\\\\Projects\\\\sticky-note\\\\sticky-server\\\\.wrangler\\\\tmp\\\\bundle-P0OxNJ\\\\middleware-insertion-facade.js\";\nimport { __facade_invoke__, __facade_register__, Dispatcher } from \"C:\\\\Users\\\\dheer\\\\AppData\\\\Roaming\\\\npm\\\\node_modules\\\\wrangler\\\\templates\\\\middleware\\\\common.ts\";\nimport type { WorkerEntrypointConstructor } from \"C:\\\\Users\\\\dheer\\\\OneDrive\\\\Desktop\\\\Projects\\\\sticky-note\\\\sticky-server\\\\.wrangler\\\\tmp\\\\bundle-P0OxNJ\\\\middleware-insertion-facade.js\";\n\n// Preserve all the exports from the worker\nexport * from \"C:\\\\Users\\\\dheer\\\\OneDrive\\\\Desktop\\\\Projects\\\\sticky-note\\\\sticky-server\\\\.wrangler\\\\tmp\\\\bundle-P0OxNJ\\\\middleware-insertion-facade.js\";\n\nclass __Facade_ScheduledController__ implements ScheduledController {\n\treadonly #noRetry: ScheduledController[\"noRetry\"];\n\n\tconstructor(\n\t\treadonly scheduledTime: number,\n\t\treadonly cron: string,\n\t\tnoRetry: ScheduledController[\"noRetry\"]\n\t) {\n\t\tthis.#noRetry = noRetry;\n\t}\n\n\tnoRetry() {\n\t\tif (!(this instanceof __Facade_ScheduledController__)) {\n\t\t\tthrow new TypeError(\"Illegal invocation\");\n\t\t}\n\t\t// Need to call native method immediately in case uncaught error thrown\n\t\tthis.#noRetry();\n\t}\n}\n\nfunction wrapExportedHandler(worker: ExportedHandler): ExportedHandler {\n\t// If we don't have any middleware defined, just return the handler as is\n\tif (\n\t\t__INTERNAL_WRANGLER_MIDDLEWARE__ === undefined ||\n\t\t__INTERNAL_WRANGLER_MIDDLEWARE__.length === 0\n\t) {\n\t\treturn worker;\n\t}\n\t// Otherwise, register all middleware once\n\tfor (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {\n\t\t__facade_register__(middleware);\n\t}\n\n\tconst fetchDispatcher: ExportedHandlerFetchHandler = function (\n\t\trequest,\n\t\tenv,\n\t\tctx\n\t) {\n\t\tif (worker.fetch === undefined) {\n\t\t\tthrow new Error(\"Handler does not export a fetch() function.\");\n\t\t}\n\t\treturn worker.fetch(request, env, ctx);\n\t};\n\n\treturn {\n\t\t...worker,\n\t\tfetch(request, env, ctx) {\n\t\t\tconst dispatcher: Dispatcher = function (type, init) {\n\t\t\t\tif (type === \"scheduled\" && worker.scheduled !== undefined) {\n\t\t\t\t\tconst controller = new __Facade_ScheduledController__(\n\t\t\t\t\t\tDate.now(),\n\t\t\t\t\t\tinit.cron ?? \"\",\n\t\t\t\t\t\t() => {}\n\t\t\t\t\t);\n\t\t\t\t\treturn worker.scheduled(controller, env, ctx);\n\t\t\t\t}\n\t\t\t};\n\t\t\treturn __facade_invoke__(request, env, ctx, dispatcher, fetchDispatcher);\n\t\t},\n\t};\n}\n\nfunction wrapWorkerEntrypoint(\n\tklass: WorkerEntrypointConstructor\n): WorkerEntrypointConstructor {\n\t// If we don't have any middleware defined, just return the handler as is\n\tif (\n\t\t__INTERNAL_WRANGLER_MIDDLEWARE__ === undefined ||\n\t\t__INTERNAL_WRANGLER_MIDDLEWARE__.length === 0\n\t) {\n\t\treturn klass;\n\t}\n\t// Otherwise, register all middleware once\n\tfor (const middleware of __INTERNAL_WRANGLER_MIDDLEWARE__) {\n\t\t__facade_register__(middleware);\n\t}\n\n\t// `extend`ing `klass` here so other RPC methods remain callable\n\treturn class extends klass {\n\t\t#fetchDispatcher: ExportedHandlerFetchHandler<Record<string, unknown>> = (\n\t\t\trequest,\n\t\t\tenv,\n\t\t\tctx\n\t\t) => {\n\t\t\tthis.env = env;\n\t\t\tthis.ctx = ctx;\n\t\t\tif (super.fetch === undefined) {\n\t\t\t\tthrow new Error(\"Entrypoint class does not define a fetch() function.\");\n\t\t\t}\n\t\t\treturn super.fetch(request);\n\t\t};\n\n\t\t#dispatcher: Dispatcher = (type, init) => {\n\t\t\tif (type === \"scheduled\" && super.scheduled !== undefined) {\n\t\t\t\tconst controller = new __Facade_ScheduledController__(\n\t\t\t\t\tDate.now(),\n\t\t\t\t\tinit.cron ?? \"\",\n\t\t\t\t\t() => {}\n\t\t\t\t);\n\t\t\t\treturn super.scheduled(controller);\n\t\t\t}\n\t\t};\n\n\t\tfetch(request: Request<unknown, IncomingRequestCfProperties>) {\n\t\t\treturn __facade_invoke__(\n\t\t\t\trequest,\n\t\t\t\tthis.env,\n\t\t\t\tthis.ctx,\n\t\t\t\tthis.#dispatcher,\n\t\t\t\tthis.#fetchDispatcher\n\t\t\t);\n\t\t}\n\t};\n}\n\nlet WRAPPED_ENTRY: ExportedHandler | WorkerEntrypointConstructor | undefined;\nif (typeof ENTRY === \"object\") {\n\tWRAPPED_ENTRY = wrapExportedHandler(ENTRY);\n} else if (typeof ENTRY === \"function\") {\n\tWRAPPED_ENTRY = wrapWorkerEntrypoint(ENTRY);\n}\nexport default WRAPPED_ENTRY;\n"],
6
6
  "mappings": "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",
7
7
  "names": ["metaKey", "getOrCreateDO", "metaKey", "error"]
8
8
  }
@@ -1,7 +1,7 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
3
 
4
- // .wrangler/tmp/bundle-EyT3Z4/checked-fetch.js
4
+ // .wrangler/tmp/bundle-seUgBC/checked-fetch.js
5
5
  var urls = /* @__PURE__ */ new Set();
6
6
  function checkURL(request, init) {
7
7
  const url = request instanceof URL ? request : new URL(
@@ -868,7 +868,7 @@ var jsonError = /* @__PURE__ */ __name(async (request, env, _ctx, middlewareCtx)
868
868
  }, "jsonError");
869
869
  var middleware_miniflare3_json_error_default = jsonError;
870
870
 
871
- // .wrangler/tmp/bundle-EyT3Z4/middleware-insertion-facade.js
871
+ // .wrangler/tmp/bundle-seUgBC/middleware-insertion-facade.js
872
872
  var __INTERNAL_WRANGLER_MIDDLEWARE__ = [
873
873
  middleware_ensure_req_body_drained_default,
874
874
  middleware_miniflare3_json_error_default
@@ -900,7 +900,7 @@ function __facade_invoke__(request, env, ctx, dispatch, finalMiddleware) {
900
900
  }
901
901
  __name(__facade_invoke__, "__facade_invoke__");
902
902
 
903
- // .wrangler/tmp/bundle-EyT3Z4/middleware-loader.entry.ts
903
+ // .wrangler/tmp/bundle-seUgBC/middleware-loader.entry.ts
904
904
  var __Facade_ScheduledController__ = class ___Facade_ScheduledController__ {
905
905
  constructor(scheduledTime, cron, noRetry) {
906
906
  this.scheduledTime = scheduledTime;