shraga 0.0.3 → 0.1.2

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 (180) hide show
  1. package/README.md +82 -27
  2. package/defaults/agents/summarizer.md +16 -0
  3. package/defaults/agents/trace-extractor.md +84 -0
  4. package/defaults/bin/claude +45 -0
  5. package/defaults/bin/claude-revive +17 -0
  6. package/defaults/extensions/README.md +70 -0
  7. package/defaults/extensions/selftest.ext.ts +43 -0
  8. package/defaults/extensions/stripe-webhook.ext.ts +58 -0
  9. package/defaults/gmail-triage-prompt.md +42 -0
  10. package/defaults/scripts/README +4 -0
  11. package/defaults/scripts/agent-once.ts +67 -0
  12. package/defaults/scripts/backfill-slack-usernames.ts +82 -0
  13. package/defaults/scripts/notifier-throttle.ts +44 -0
  14. package/defaults/scripts/summarize-conversations.ts +5 -0
  15. package/defaults/shraga.config.ts +29 -0
  16. package/defaults/skills/add-skill.md +14 -0
  17. package/defaults/skills/artifacts.md +116 -0
  18. package/defaults/skills/code-review.md +26 -0
  19. package/defaults/skills/communications.md +54 -0
  20. package/defaults/skills/context-audit.md +87 -0
  21. package/defaults/skills/debug.md +10 -0
  22. package/defaults/skills/garden.md +179 -0
  23. package/defaults/skills/github-contributor.md +35 -0
  24. package/defaults/skills/identity.md +30 -0
  25. package/defaults/skills/mcp-server.md +62 -0
  26. package/defaults/skills/mcps-sync.md +105 -0
  27. package/defaults/skills/plan.md +9 -0
  28. package/defaults/skills/platform.md +177 -0
  29. package/defaults/skills/reconcile.md +239 -0
  30. package/defaults/skills/scheduler.md +192 -0
  31. package/defaults/skills/self-aware.md +136 -0
  32. package/defaults/skills/shraga-know.md +333 -0
  33. package/defaults/skills/stripe.md +55 -0
  34. package/defaults/skills/write-tests.md +10 -0
  35. package/defaults/skills-defaults.json +1 -0
  36. package/defaults/system-prompt.md +46 -0
  37. package/defaults/workspace/context.md +28 -0
  38. package/defaults/workspace.md +50 -0
  39. package/defaults/zdotdir/.gitignore +8 -0
  40. package/defaults/zdotdir/.zlogin +3 -0
  41. package/defaults/zdotdir/.zprofile +1 -0
  42. package/defaults/zdotdir/.zshenv +4 -0
  43. package/defaults/zdotdir/.zshrc +3 -0
  44. package/dist/client/assets/index-BoHttkMt.js +1940 -0
  45. package/dist/client/assets/index-DdibEb2O.css +10 -0
  46. package/dist/client/index.html +22 -0
  47. package/package.json +59 -14
  48. package/src/cli.ts +71 -46
  49. package/src/client/App.tsx +510 -0
  50. package/src/client/components/ArtifactCard.tsx +26 -0
  51. package/src/client/components/ArtifactPanel.tsx +138 -0
  52. package/src/client/components/AuthedImage.tsx +85 -0
  53. package/src/client/components/AutocompleteTextarea.tsx +149 -0
  54. package/src/client/components/ChatView.tsx +866 -0
  55. package/src/client/components/CliAuthConsent.tsx +98 -0
  56. package/src/client/components/ConfigPanel.tsx +328 -0
  57. package/src/client/components/ConversationHeader.tsx +156 -0
  58. package/src/client/components/ConversationPane.tsx +277 -0
  59. package/src/client/components/LoginPage.tsx +81 -0
  60. package/src/client/components/MachineStats.tsx +77 -0
  61. package/src/client/components/McpManager.tsx +209 -0
  62. package/src/client/components/MessageInput.tsx +263 -0
  63. package/src/client/components/OAuthConsent.tsx +103 -0
  64. package/src/client/components/SchedulesManager.tsx +99 -0
  65. package/src/client/components/Sidebar.tsx +235 -0
  66. package/src/client/components/SkillsManager.tsx +280 -0
  67. package/src/client/components/SmartChart.tsx +167 -0
  68. package/src/client/components/Toast.tsx +54 -0
  69. package/src/client/components/WorkspaceTree.tsx +313 -0
  70. package/src/client/components/ZoomableImage.tsx +123 -0
  71. package/src/client/components/artifact-presets.ts +10 -0
  72. package/src/client/components/schedules/ScheduleEditor.tsx +264 -0
  73. package/src/client/components/schedules/ScheduleList.tsx +271 -0
  74. package/src/client/components/ui/accordion.tsx +50 -0
  75. package/src/client/components/ui/button.tsx +43 -0
  76. package/src/client/components/ui/dialog.tsx +82 -0
  77. package/src/client/components/ui/input.tsx +19 -0
  78. package/src/client/components/ui/scroll-area.tsx +39 -0
  79. package/src/client/components/ui/textarea.tsx +18 -0
  80. package/src/client/globals.css +51 -0
  81. package/src/client/hooks/useAgentSocket.ts +79 -0
  82. package/src/client/hooks/useArtifacts.ts +89 -0
  83. package/src/client/hooks/useAuth.ts +127 -0
  84. package/src/client/hooks/useConversation.ts +412 -0
  85. package/src/client/hooks/useDarkMode.ts +57 -0
  86. package/src/client/hooks/useIsMobile.ts +23 -0
  87. package/src/client/hooks/usePush.ts +127 -0
  88. package/src/client/hooks/useSchedules.ts +73 -0
  89. package/src/client/hooks/useUnread.ts +238 -0
  90. package/src/client/lib/desktopAttention.ts +75 -0
  91. package/src/client/lib/firebase.ts +32 -0
  92. package/src/client/lib/googleAuthNative.ts +94 -0
  93. package/src/client/lib/native.ts +43 -0
  94. package/src/client/lib/schedule-types.ts +34 -0
  95. package/src/client/lib/sessionApi.ts +58 -0
  96. package/src/client/lib/slots.tsx +79 -0
  97. package/src/client/lib/storage.ts +39 -0
  98. package/src/client/lib/utils.ts +26 -0
  99. package/src/client/lib/workspaceContext.tsx +54 -0
  100. package/src/client/lib/ws.ts +203 -0
  101. package/src/client/main.tsx +14 -0
  102. package/src/mcp-stdio-bridge.ts +70 -0
  103. package/src/scripts/summarize-conversations.ts +5 -0
  104. package/src/scripts/typecheck.ts +43 -0
  105. package/src/server/agents.ts +54 -0
  106. package/src/server/api-keys.ts +63 -0
  107. package/src/server/artifacts/artifacts.export.ts +85 -0
  108. package/src/server/artifacts/artifacts.handler.ts +93 -0
  109. package/src/server/artifacts/artifacts.routes.ts +43 -0
  110. package/src/server/artifacts/artifacts.service.ts +100 -0
  111. package/src/server/artifacts/artifacts.types.ts +31 -0
  112. package/src/server/auth.ts +262 -0
  113. package/src/server/claude.ts +394 -0
  114. package/src/server/commands.ts +21 -0
  115. package/src/server/contacts.ts +177 -0
  116. package/src/server/conversation-summarizer.ts +204 -0
  117. package/src/server/data-sync.ts +664 -0
  118. package/src/server/directives.ts +91 -0
  119. package/src/server/engine/claude-code.ts +514 -0
  120. package/src/server/engine/index.ts +41 -0
  121. package/src/server/engine/registry.ts +21 -0
  122. package/src/server/engine/shared.ts +47 -0
  123. package/src/server/engine/types.ts +48 -0
  124. package/src/server/env-resolve.ts +71 -0
  125. package/src/server/env-sanitize.ts +9 -0
  126. package/src/server/events/bus.ts +29 -0
  127. package/src/server/events/dispatcher.ts +48 -0
  128. package/src/server/events/routes.ts +19 -0
  129. package/src/server/events/types.ts +9 -0
  130. package/src/server/extensions.ts +101 -0
  131. package/src/server/features.ts +109 -0
  132. package/src/server/file-inject.ts +45 -0
  133. package/src/server/hooks.ts +142 -0
  134. package/src/server/idempotency.ts +25 -0
  135. package/src/server/index.ts +1715 -0
  136. package/src/server/integrity-audit.ts +132 -0
  137. package/src/server/mcp-catalog.ts +70 -0
  138. package/src/server/mcp-oauth.ts +198 -0
  139. package/src/server/mcp-progress.ts +45 -0
  140. package/src/server/mcp-server.ts +456 -0
  141. package/src/server/mcp-sidecar.ts +87 -0
  142. package/src/server/mcp.ts +291 -0
  143. package/src/server/model-aliases.ts +76 -0
  144. package/src/server/paths.ts +24 -0
  145. package/src/server/polls.ts +175 -0
  146. package/src/server/push/apns.ts +113 -0
  147. package/src/server/push/fcm.ts +108 -0
  148. package/src/server/push/push.ts +66 -0
  149. package/src/server/push/store.ts +84 -0
  150. package/src/server/push/triggers.ts +99 -0
  151. package/src/server/scheduler/builtins.ts +157 -0
  152. package/src/server/scheduler/engine.ts +432 -0
  153. package/src/server/scheduler/index.ts +4 -0
  154. package/src/server/scheduler/runner.ts +334 -0
  155. package/src/server/scheduler/storage.ts +98 -0
  156. package/src/server/scheduler/timing.ts +70 -0
  157. package/src/server/scheduler/types.ts +62 -0
  158. package/src/server/sdk-utils.ts +45 -0
  159. package/src/server/seed.ts +174 -0
  160. package/src/server/session-bus.ts +18 -0
  161. package/src/server/sessions.ts +559 -0
  162. package/src/server/shraga-config.ts +167 -0
  163. package/src/server/skills.ts +372 -0
  164. package/src/server/slack/api.ts +37 -0
  165. package/src/server/slack/bot.ts +391 -0
  166. package/src/server/slack/context-cache.ts +42 -0
  167. package/src/server/slack/feature.ts +59 -0
  168. package/src/server/slack/mention-rewrite.ts +59 -0
  169. package/src/server/slack/oauth.ts +102 -0
  170. package/src/server/slack/questions.ts +112 -0
  171. package/src/server/slack/sessions.ts +139 -0
  172. package/src/server/stats.ts +106 -0
  173. package/src/server/summarize.ts +11 -0
  174. package/src/server/turn-context.ts +61 -0
  175. package/src/server/unclaw-config.ts +19 -0
  176. package/src/server/unread.ts +79 -0
  177. package/src/server/user-context.ts +33 -0
  178. package/src/server/vendor-sync.ts +52 -0
  179. package/src/server/voice-provider.ts +74 -0
  180. package/src/server/workspace.ts +249 -0
@@ -0,0 +1,204 @@
1
+ import { readdirSync, writeFileSync, statSync, existsSync } from 'node:fs';
2
+ import path from 'node:path';
3
+ import YAML from 'yaml';
4
+ import { dataPath } from './paths.ts';
5
+ import { loadAgents } from './agents.ts';
6
+ import { runTextQuery } from './sdk-utils.ts';
7
+ import { getAllSessions, loadConversation, type ConvMessage } from './sessions.ts';
8
+
9
+ const CONV_DIR = dataPath('conversations');
10
+ const DEFAULT_MAX_AGE = 0;
11
+
12
+ export interface SummarizerOptions {
13
+ maxAge?: number;
14
+ minFileSize?: number;
15
+ maxConvos?: number;
16
+ force?: boolean;
17
+ }
18
+
19
+ function getAgent() {
20
+ const agents = loadAgents();
21
+ const agent = agents['summarizer'];
22
+ if (!agent) throw new Error('No "summarizer" agent defined in defaults/agents/ or data/agents/');
23
+ return agent;
24
+ }
25
+
26
+ function getTraceAgent() {
27
+ const agents = loadAgents();
28
+ return agents['trace-extractor'] ?? null;
29
+ }
30
+
31
+ function extractText(messages: ConvMessage[], maxChars = 80_000): string {
32
+ const parts: string[] = [];
33
+ let len = 0;
34
+ for (const m of messages) {
35
+ const role = m.role === 'user' ? 'User' : 'Assistant';
36
+ for (const b of m.blocks) {
37
+ if (b.type === 'text' && b.text) {
38
+ const line = `${role}: ${b.text.slice(0, 500)}`;
39
+ parts.push(line);
40
+ len += line.length;
41
+ if (len > maxChars) return parts.join('\n');
42
+ } else if (b.type === 'tool_use') {
43
+ parts.push(`Assistant: (tool: ${b.tool})`);
44
+ }
45
+ }
46
+ }
47
+ return parts.join('\n');
48
+ }
49
+
50
+ async function runSummarizerAgent(text: string): Promise<string> {
51
+ const agent = getAgent();
52
+ return runTextQuery({
53
+ prompt: `Here is a transcript of a conversation between a user and an AI assistant. Write a briefing about what happened in this conversation.\n\n<transcript>\n${text}\n</transcript>`,
54
+ model: agent.model || 'haiku',
55
+ maxTurns: agent.maxTurns || 3,
56
+ systemPrompt: agent.prompt,
57
+ });
58
+ }
59
+
60
+ interface TraceMeta {
61
+ sessionId: string;
62
+ email: string;
63
+ date: string;
64
+ title: string;
65
+ messageCount: number;
66
+ }
67
+
68
+ async function runTraceExtractor(text: string, meta: TraceMeta): Promise<string | null> {
69
+ const agent = getTraceAgent();
70
+ if (!agent) return null;
71
+
72
+ const metaBlock = `Metadata:\n session_id: ${meta.sessionId}\n user: ${meta.email}\n date: "${meta.date}"\n title: "${meta.title}"\n message_count: ${meta.messageCount}`;
73
+
74
+ try {
75
+ return await runTextQuery({
76
+ prompt: `${metaBlock}\n\n<transcript>\n${text}\n</transcript>`,
77
+ model: agent.model || 'haiku',
78
+ maxTurns: 1,
79
+ systemPrompt: agent.prompt,
80
+ });
81
+ } catch (err) {
82
+ console.error(`[summarizer] Trace extraction failed:`, err);
83
+ return null;
84
+ }
85
+ }
86
+
87
+ const TRACE_REQUIRED_FIELDS = ['session_id', 'date', 'outcome'];
88
+
89
+ function validateAndWriteTrace(raw: string, tracePath: string): boolean {
90
+ try {
91
+ const cleaned = raw.replace(/^```ya?ml\n?/m, '').replace(/\n?```\s*$/m, '').trim();
92
+ const parsed = YAML.parse(cleaned);
93
+ if (!parsed || typeof parsed !== 'object') {
94
+ console.warn(`[summarizer] Trace not an object`);
95
+ return false;
96
+ }
97
+ for (const field of TRACE_REQUIRED_FIELDS) {
98
+ if (!(field in parsed)) {
99
+ console.warn(`[summarizer] Trace missing required field: ${field}`);
100
+ return false;
101
+ }
102
+ }
103
+ writeFileSync(tracePath, cleaned + '\n');
104
+ return true;
105
+ } catch (err) {
106
+ console.warn(`[summarizer] Trace YAML parse failed:`, err);
107
+ return false;
108
+ }
109
+ }
110
+
111
+ export async function summarizeConversations(options?: SummarizerOptions): Promise<{
112
+ summarized: number;
113
+ skipped: number;
114
+ errors: number;
115
+ tracesGenerated: number;
116
+ }> {
117
+ const maxAge = options?.maxAge ?? DEFAULT_MAX_AGE;
118
+ const minFileSize = options?.minFileSize ?? 5_000; // 5KB — filters out trivial "hey/hi" convos
119
+ const maxConvos = options?.maxConvos ?? 20;
120
+ const force = options?.force ?? false;
121
+
122
+ const now = Date.now();
123
+ const sessions = getAllSessions();
124
+ const sessionMap = new Map(sessions.map(s => [s.sessionId, s]));
125
+
126
+ const jsonlFiles = readdirSync(CONV_DIR).filter(f => f.endsWith('.jsonl'));
127
+
128
+ const candidates: { sessionId: string; jsonlPath: string; summaryPath: string; jsonlMtime: number }[] = [];
129
+
130
+ for (const f of jsonlFiles) {
131
+ const sessionId = f.slice(0, -6);
132
+ const jsonlPath = path.join(CONV_DIR, f);
133
+ const summaryPath = path.join(CONV_DIR, `${sessionId}.summary.md`);
134
+ const stat = statSync(jsonlPath);
135
+ const jsonlMtime = stat.mtimeMs;
136
+
137
+ if (now - jsonlMtime < maxAge) continue;
138
+ if (stat.size < minFileSize) continue;
139
+
140
+ if (!force && existsSync(summaryPath)) {
141
+ const summaryMtime = statSync(summaryPath).mtimeMs;
142
+ if (summaryMtime >= jsonlMtime) continue;
143
+ }
144
+
145
+ candidates.push({ sessionId, jsonlPath, summaryPath, jsonlMtime });
146
+ }
147
+
148
+ candidates.sort((a, b) => a.jsonlMtime - b.jsonlMtime);
149
+ const batch = candidates.slice(0, maxConvos);
150
+
151
+ let summarized = 0;
152
+ let skipped = 0;
153
+ let errors = 0;
154
+ let tracesGenerated = 0;
155
+
156
+ for (const { sessionId, jsonlPath, summaryPath, jsonlMtime } of batch) {
157
+ try {
158
+ const messages = loadConversation(sessionId);
159
+ const text = extractText(messages);
160
+ if (!text.trim()) {
161
+ skipped++;
162
+ continue;
163
+ }
164
+
165
+ const session = sessionMap.get(sessionId);
166
+ const title = session?.title || '(untitled)';
167
+ const email = session?.userEmail || 'unknown';
168
+ const date = new Date(session?.lastModified ?? Date.now()).toISOString().slice(0, 10);
169
+
170
+ console.log(`[summarizer] Summarizing ${sessionId.slice(0, 8)}... (${messages.length} msgs)`);
171
+ const summary = await runSummarizerAgent(text);
172
+
173
+ if (!summary?.trim()) {
174
+ console.warn(`[summarizer] Empty summary for ${sessionId.slice(0, 8)}`);
175
+ skipped++;
176
+ continue;
177
+ }
178
+
179
+ const content = `<!-- session: ${sessionId} | user: ${email} | date: ${date} | title: ${title} -->\n\n${summary}\n`;
180
+ writeFileSync(summaryPath, content);
181
+ summarized++;
182
+ console.log(`[summarizer] Done ${sessionId.slice(0, 8)} (${summary.length} chars)`);
183
+
184
+ // Trace extraction (second pass)
185
+ const tracePath = path.join(CONV_DIR, `${sessionId}.trace.yaml`);
186
+ const traceUpToDate = !force && existsSync(tracePath) && statSync(tracePath).mtimeMs >= jsonlMtime;
187
+
188
+ if (!traceUpToDate) {
189
+ const traceMeta: TraceMeta = { sessionId, email, date, title, messageCount: messages.length };
190
+ const traceRaw = await runTraceExtractor(text, traceMeta);
191
+ if (traceRaw && validateAndWriteTrace(traceRaw, tracePath)) {
192
+ tracesGenerated++;
193
+ console.log(`[summarizer] Trace written for ${sessionId.slice(0, 8)}`);
194
+ }
195
+ }
196
+ } catch (err) {
197
+ console.error(`[summarizer] Error on ${sessionId.slice(0, 8)}:`, err);
198
+ errors++;
199
+ }
200
+ }
201
+
202
+ console.log(`[summarizer] Finished: ${summarized} summarized, ${tracesGenerated} traces, ${skipped} skipped, ${errors} errors (${candidates.length - batch.length} deferred)`);
203
+ return { summarized, skipped, errors, tracesGenerated };
204
+ }