linguclaw 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,351 @@
1
+ "use strict";
2
+ /**
3
+ * Session Memory - Short-term contextual memory for active sessions
4
+ *
5
+ * Core capabilities:
6
+ * - Short-term Memory: Tracks current session history, prevents repeating mistakes
7
+ * - Action History: Remembers what has been tried and what worked/failed
8
+ * - Context Window: Maintains relevant context within token limits
9
+ * - Learning: Extracts patterns from sessions to improve long-term memory
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.SessionMemory = void 0;
13
+ exports.getSessionMemory = getSessionMemory;
14
+ const logger_1 = require("./logger");
15
+ const logger = (0, logger_1.getLogger)();
16
+ const DEFAULT_CONFIG = {
17
+ maxEntries: 200,
18
+ maxTokens: 16000,
19
+ maxActionHistory: 100,
20
+ maxFailedAttempts: 3,
21
+ enableLearning: true,
22
+ summaryThreshold: 50,
23
+ };
24
+ // ==================== Session Memory ====================
25
+ class SessionMemory {
26
+ config;
27
+ sessions = new Map();
28
+ activeSessionId = null;
29
+ longTermMemory = null;
30
+ idCounter = 0;
31
+ constructor(config, longTermMemory) {
32
+ this.config = { ...DEFAULT_CONFIG, ...config };
33
+ this.longTermMemory = longTermMemory || null;
34
+ }
35
+ /**
36
+ * Start a new session
37
+ */
38
+ startSession(task, sessionId) {
39
+ const id = sessionId || `sess-${Date.now()}-${Math.random().toString(36).substr(2, 6)}`;
40
+ this.sessions.set(id, {
41
+ task,
42
+ entries: [],
43
+ actionHistory: [],
44
+ failedAttempts: new Map(),
45
+ discoveredFacts: [],
46
+ currentFocus: task,
47
+ tokensUsed: 0,
48
+ });
49
+ this.activeSessionId = id;
50
+ this.addEntry(id, 'context', `Session started for task: ${task}`);
51
+ // Load relevant context from long-term memory
52
+ if (this.longTermMemory) {
53
+ const pastKnowledge = this.longTermMemory.search(task, 'learned_patterns', 5);
54
+ if (pastKnowledge.length > 0) {
55
+ for (const item of pastKnowledge) {
56
+ this.addEntry(id, 'context', `Past knowledge: ${JSON.stringify(item.value).substring(0, 300)}`, {
57
+ source: 'long_term_memory',
58
+ });
59
+ }
60
+ logger.info(`[SessionMemory] Loaded ${pastKnowledge.length} relevant memories for session`);
61
+ }
62
+ }
63
+ logger.info(`[SessionMemory] Session started: ${id}`);
64
+ return id;
65
+ }
66
+ /**
67
+ * End a session and optionally learn from it
68
+ */
69
+ endSession(sessionId) {
70
+ const sid = sessionId || this.activeSessionId;
71
+ if (!sid)
72
+ return;
73
+ const session = this.sessions.get(sid);
74
+ if (!session)
75
+ return;
76
+ // Extract learnings and save to long-term memory
77
+ if (this.config.enableLearning && this.longTermMemory && session.actionHistory.length > 0) {
78
+ this.extractLearnings(sid, session);
79
+ }
80
+ if (this.activeSessionId === sid) {
81
+ this.activeSessionId = null;
82
+ }
83
+ logger.info(`[SessionMemory] Session ended: ${sid} (${session.entries.length} entries, ${session.actionHistory.length} actions)`);
84
+ }
85
+ /**
86
+ * Add an entry to the session
87
+ */
88
+ addEntry(sessionId, type, content, metadata) {
89
+ const sid = sessionId || this.activeSessionId;
90
+ const session = sid ? this.sessions.get(sid) : null;
91
+ const entry = {
92
+ id: `entry-${++this.idCounter}`,
93
+ timestamp: new Date(),
94
+ type,
95
+ content,
96
+ metadata,
97
+ tokenEstimate: Math.ceil(content.length / 4), // rough estimate
98
+ };
99
+ if (session) {
100
+ session.entries.push(entry);
101
+ session.tokensUsed += entry.tokenEstimate || 0;
102
+ // Compact if over limits
103
+ if (session.entries.length > this.config.maxEntries) {
104
+ this.compactSession(sid);
105
+ }
106
+ if (session.tokensUsed > this.config.maxTokens) {
107
+ this.compactSession(sid);
108
+ }
109
+ }
110
+ return entry;
111
+ }
112
+ /**
113
+ * Record an action attempt
114
+ */
115
+ recordAction(sessionId, action, input, success, output, error, duration) {
116
+ const sid = sessionId || this.activeSessionId;
117
+ const session = sid ? this.sessions.get(sid) : null;
118
+ if (!session)
119
+ return;
120
+ const attempt = {
121
+ action,
122
+ input: input.substring(0, 1000),
123
+ output: output?.substring(0, 2000),
124
+ success,
125
+ timestamp: new Date(),
126
+ duration,
127
+ error,
128
+ };
129
+ session.actionHistory.push(attempt);
130
+ // Track failed attempts
131
+ if (!success) {
132
+ const signature = `${action}:${input.substring(0, 200)}`;
133
+ const count = (session.failedAttempts.get(signature) || 0) + 1;
134
+ session.failedAttempts.set(signature, count);
135
+ this.addEntry(sid, 'error', `Action failed (attempt ${count}): ${action} — ${error || 'unknown error'}`, {
136
+ action,
137
+ attemptCount: count,
138
+ });
139
+ }
140
+ else {
141
+ this.addEntry(sid, 'action_result', `Action succeeded: ${action} — ${(output || '').substring(0, 200)}`, {
142
+ action,
143
+ duration,
144
+ });
145
+ }
146
+ // Trim action history
147
+ if (session.actionHistory.length > this.config.maxActionHistory) {
148
+ session.actionHistory = session.actionHistory.slice(-this.config.maxActionHistory);
149
+ }
150
+ }
151
+ /**
152
+ * Check if an action has been tried too many times
153
+ */
154
+ shouldAvoid(sessionId, action, input) {
155
+ const sid = sessionId || this.activeSessionId;
156
+ const session = sid ? this.sessions.get(sid) : null;
157
+ if (!session)
158
+ return { avoid: false, attempts: 0 };
159
+ const signature = `${action}:${input.substring(0, 200)}`;
160
+ const count = session.failedAttempts.get(signature) || 0;
161
+ if (count >= this.config.maxFailedAttempts) {
162
+ return {
163
+ avoid: true,
164
+ reason: `This action has failed ${count} times already. Try a different approach.`,
165
+ attempts: count,
166
+ };
167
+ }
168
+ return { avoid: false, attempts: count };
169
+ }
170
+ /**
171
+ * Add a discovered fact
172
+ */
173
+ addFact(sessionId, fact) {
174
+ const sid = sessionId || this.activeSessionId;
175
+ const session = sid ? this.sessions.get(sid) : null;
176
+ if (!session)
177
+ return;
178
+ if (!session.discoveredFacts.includes(fact)) {
179
+ session.discoveredFacts.push(fact);
180
+ this.addEntry(sid, 'context', `Discovered: ${fact}`);
181
+ }
182
+ }
183
+ /**
184
+ * Update the current focus
185
+ */
186
+ setFocus(sessionId, focus) {
187
+ const sid = sessionId || this.activeSessionId;
188
+ const session = sid ? this.sessions.get(sid) : null;
189
+ if (!session)
190
+ return;
191
+ session.currentFocus = focus;
192
+ this.addEntry(sid, 'context', `Focus shifted to: ${focus}`);
193
+ }
194
+ /**
195
+ * Get context string for LLM prompt
196
+ */
197
+ getContextForLLM(sessionId, maxTokens) {
198
+ const sid = sessionId || this.activeSessionId;
199
+ const session = sid ? this.sessions.get(sid) : null;
200
+ if (!session)
201
+ return '';
202
+ const limit = maxTokens || this.config.maxTokens;
203
+ const parts = [];
204
+ let tokens = 0;
205
+ // Task and focus
206
+ parts.push(`Current task: ${session.task}`);
207
+ parts.push(`Current focus: ${session.currentFocus}`);
208
+ tokens += Math.ceil((session.task.length + session.currentFocus.length) / 4);
209
+ // Discovered facts
210
+ if (session.discoveredFacts.length > 0) {
211
+ parts.push(`\nDiscovered facts:`);
212
+ for (const fact of session.discoveredFacts.slice(-10)) {
213
+ parts.push(` - ${fact}`);
214
+ tokens += Math.ceil(fact.length / 4);
215
+ }
216
+ }
217
+ // Failed attempts warning
218
+ if (session.failedAttempts.size > 0) {
219
+ parts.push(`\nFailed approaches (avoid these):`);
220
+ for (const [sig, count] of session.failedAttempts) {
221
+ if (count >= 2) {
222
+ parts.push(` - ${sig.substring(0, 100)} (failed ${count}x)`);
223
+ tokens += 30;
224
+ }
225
+ }
226
+ }
227
+ // Recent entries (most recent first, within token budget)
228
+ parts.push(`\nRecent activity:`);
229
+ const recentEntries = session.entries.slice(-30).reverse();
230
+ for (const entry of recentEntries) {
231
+ const line = ` [${entry.type}] ${entry.content.substring(0, 300)}`;
232
+ const lineTokens = Math.ceil(line.length / 4);
233
+ if (tokens + lineTokens > limit)
234
+ break;
235
+ parts.push(line);
236
+ tokens += lineTokens;
237
+ }
238
+ return parts.join('\n');
239
+ }
240
+ /**
241
+ * Get action history for a session
242
+ */
243
+ getActionHistory(sessionId) {
244
+ const sid = sessionId || this.activeSessionId;
245
+ const session = sid ? this.sessions.get(sid) : null;
246
+ return session?.actionHistory || [];
247
+ }
248
+ /**
249
+ * Get session stats
250
+ */
251
+ getStats(sessionId) {
252
+ const sid = sessionId || this.activeSessionId;
253
+ const session = sid ? this.sessions.get(sid) : null;
254
+ if (!session)
255
+ return { entries: 0, actions: 0, failedActions: 0, facts: 0, tokensUsed: 0 };
256
+ return {
257
+ entries: session.entries.length,
258
+ actions: session.actionHistory.length,
259
+ failedActions: session.actionHistory.filter(a => !a.success).length,
260
+ facts: session.discoveredFacts.length,
261
+ tokensUsed: session.tokensUsed,
262
+ };
263
+ }
264
+ /**
265
+ * Compact session by summarizing old entries
266
+ */
267
+ compactSession(sessionId) {
268
+ const session = this.sessions.get(sessionId);
269
+ if (!session)
270
+ return;
271
+ // Keep last 30% of entries, summarize the rest
272
+ const keepCount = Math.max(20, Math.floor(session.entries.length * 0.3));
273
+ const toSummarize = session.entries.slice(0, session.entries.length - keepCount);
274
+ const toKeep = session.entries.slice(-keepCount);
275
+ // Create a summary entry
276
+ const actionCount = toSummarize.filter(e => e.type === 'action' || e.type === 'action_result').length;
277
+ const errorCount = toSummarize.filter(e => e.type === 'error').length;
278
+ const summary = `[Session compacted] ${toSummarize.length} older entries summarized: ${actionCount} actions, ${errorCount} errors`;
279
+ session.entries = [
280
+ {
281
+ id: `entry-summary-${Date.now()}`,
282
+ timestamp: new Date(),
283
+ type: 'context',
284
+ content: summary,
285
+ tokenEstimate: Math.ceil(summary.length / 4),
286
+ },
287
+ ...toKeep,
288
+ ];
289
+ session.tokensUsed = session.entries.reduce((sum, e) => sum + (e.tokenEstimate || 0), 0);
290
+ logger.info(`[SessionMemory] Compacted session ${sessionId}: ${toSummarize.length} entries summarized`);
291
+ }
292
+ /**
293
+ * Extract learnings from a session and save to long-term memory
294
+ */
295
+ extractLearnings(sessionId, session) {
296
+ if (!this.longTermMemory)
297
+ return;
298
+ // Learn from successful action patterns
299
+ const successfulActions = session.actionHistory.filter(a => a.success);
300
+ const failedActions = session.actionHistory.filter(a => !a.success);
301
+ if (successfulActions.length > 0) {
302
+ const patterns = successfulActions.map(a => `${a.action}: ${a.input.substring(0, 100)}`).join('; ');
303
+ this.longTermMemory.store(`learned:${sessionId}:success`, {
304
+ task: session.task,
305
+ successfulApproaches: patterns,
306
+ totalActions: session.actionHistory.length,
307
+ successRate: successfulActions.length / session.actionHistory.length,
308
+ timestamp: new Date().toISOString(),
309
+ }, 'learned_patterns', ['session_learning', 'success_pattern'], 30 // 30 day TTL
310
+ );
311
+ }
312
+ // Learn from repeated failures
313
+ for (const [signature, count] of session.failedAttempts) {
314
+ if (count >= 2) {
315
+ this.longTermMemory.store(`learned:${sessionId}:avoid:${signature.substring(0, 50)}`, {
316
+ task: session.task,
317
+ failedApproach: signature,
318
+ failureCount: count,
319
+ timestamp: new Date().toISOString(),
320
+ }, 'learned_patterns', ['session_learning', 'failure_pattern'], 14 // 14 day TTL
321
+ );
322
+ }
323
+ }
324
+ // Store discovered facts
325
+ if (session.discoveredFacts.length > 0) {
326
+ this.longTermMemory.store(`facts:${sessionId}`, {
327
+ task: session.task,
328
+ facts: session.discoveredFacts,
329
+ timestamp: new Date().toISOString(),
330
+ }, 'discovered_facts', ['session_learning', 'facts'], 60 // 60 day TTL
331
+ );
332
+ }
333
+ logger.info(`[SessionMemory] Extracted learnings from session ${sessionId}`);
334
+ }
335
+ /**
336
+ * Get active session ID
337
+ */
338
+ getActiveSessionId() {
339
+ return this.activeSessionId;
340
+ }
341
+ }
342
+ exports.SessionMemory = SessionMemory;
343
+ // ==================== Singleton ====================
344
+ let instance = null;
345
+ function getSessionMemory(config, longTermMemory) {
346
+ if (!instance) {
347
+ instance = new SessionMemory(config, longTermMemory);
348
+ }
349
+ return instance;
350
+ }
351
+ //# sourceMappingURL=session-memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-memory.js","sourceRoot":"","sources":["../src/session-memory.ts"],"names":[],"mappings":"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"}
@@ -223,7 +223,7 @@ select.inp{appearance:none;background-image:url("data:image/svg+xml,%3Csvg xmlns
223
223
  <body>
224
224
  <div id="toast" class="toast"></div>
225
225
  <div class="top">
226
- <div class="top-left"><svg class="logo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M12 3c-1.5 0-2.7.5-3.5 1.3C7.7 5.1 7 6.3 7 8c0 1.3.4 2.4 1 3.2V13c0 1.5-.5 2.5-1.2 3.2-.4.4-.4 1 0 1.4.4.4 1 .4 1.4 0 .9-.9 1.5-2.2 1.7-3.7.5.2 1 .3 1.6.3h.9c.6 0 1.1-.1 1.6-.3.2 1.5.8 2.8 1.7 3.7.4.4 1 .4 1.4 0 .4-.4.4-1 0-1.4-.7-.7-1.2-1.7-1.2-3.2v-1.8c.6-.8 1-1.9 1-3.2 0-1.7-.7-2.9-1.5-3.7C14.7 3.5 13.5 3 12 3z"/><path d="M5 9c-1.5 0-3 .5-4 1.5C.5 11.5 0 12.5 0 14c0 1.5.5 2.5 1.2 3.2.4.4 1 .4 1.4 0 .4-.4.4-1 0-1.4-.4-.4-.6-1-.6-1.8 0-.8.3-1.4.7-1.8.4-.4 1-.6 1.8-.6"/><path d="M19 9c1.5 0 3 .5 4 1.5.5.5 1 1.5 1 3 0 1.5-.5 2.5-1.2 3.2-.4.4-1 .4-1.4 0-.4-.4-.4-1 0-1.4.4-.4.6-1 .6-1.8 0-.8-.3-1.4-.7-1.8-.4-.4-1-.6-1.8-.6"/><path d="M4 20c-.8 0-1.5.5-1.8 1.2-.2.5.1 1.1.6 1.3.5.2 1.1-.1 1.3-.6.1-.2.3-.4.6-.4.3 0 .5.2.6.4.2.5.8.8 1.3.6.5-.2.8-.8.6-1.3C7 20.5 6.3 20 5.5 20H4z"/><path d="M16 20c-.8 0-1.5.5-1.8 1.2-.2.5.1 1.1.6 1.3.5.2 1.1-.1 1.3-.6.1-.2.3-.4.6-.4.3 0 .5.2.6.4.2.5.8.8 1.3.6.5-.2.8-.8.6-1.3-.3-.7-1-1.2-1.8-1.2h-1.5z"/></svg><div class="brand">Lingu<span>Claw</span></div></div>
226
+ <div class="top-left"><svg class="logo" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M12 3c-1.5 0-2.7.5-3.5 1.3C7.7 5.1 7 6.3 7 8c0 1.3.4 2.4 1 3.2V13c0 1.5-.5 2.5-1.2 3.2-.4.4-.4 1 0 1.4.4.4 1 .4 1.4 0 .9-.9 1.5-2.2 1.7-3.7.5.2 1 .3 1.6.3h.9c.6 0 1.1-.1 1.6-.3.2 1.5.8 2.8 1.7 3.7.4.4 1 .4 1.4 0 .4-.4.4-1 0-1.4-.7-.7-1.2-1.7-1.2-3.2v-1.8c.6-.8 1-1.9 1-3.2 0-1.7-.7-2.9-1.5-3.7C14.7 3.5 13.5 3 12 3z"/><path d="M5 9c-1.5 0-3 .5-4 1.5C.5 11.5 0 12.5 0 14c0 1.5.5 2.5 1.2 3.2.4.4 1 .4 1.4 0 .4-.4.4-1 0-1.4-.4-.4-.6-1-.6-1.8 0-.8.3-1.4.7-1.8.4-.4 1-.6 1.8-.6"/><path d="M19 9c1.5 0 3 .5 4 1.5.5.5 1 1.5 1 3 0 1.5-.5 2.5-1.2 3.2-.4.4-1 .4-1.4 0-.4-.4-.4-1 0-1.4.4-.4.6-1 .6-1.8 0-.8-.3-1.4-.7-1.8-.4-.4-1-.6-1.8-.6"/><path d="M4 20c-.8 0-1.5.5-1.8 1.2-.2.5.1 1.1.6 1.3.5.2 1.1-.1 1.3-.6.1-.2.3-.4.6-.4.3 0 .5.2.6.4.2.5.8.8 1.3.6.5-.2.8-.8.6-1.3C7 20.5 6.3 20 5.5 20H4z"/><path d="M16 20c-.8 0-1.5.5-1.8 1.2-.2.5.1 1.1.6 1.3.5.2 1.1-.1 1.3-.6.1-.2.3-.4.6-.4.3 0 .5.2.6.4.2.5.8.8 1.3.6.5-.2.8-.8.6-1.3-.3-.7-1-1.2-1.8-1.2h-1.5z"/></svg><div class="brand">Lingu<span>Claw</span></div><div class="badge" style="margin-left:10px;background:var(--bg2);color:var(--accent2);font-weight:700">v0.4.3</div></div>
227
227
  <div class="top-right">
228
228
  <div class="badge" id="modelBadge">loading...</div>
229
229
  <div class="badge"><div class="dot on" id="wsDot"></div><span id="wsLabel">Connected</span></div>
@@ -228,7 +228,7 @@ section{padding:120px 0;position:relative;overflow:hidden}
228
228
  </div>
229
229
  <div class="container hub-hero-content">
230
230
  <div class="hub-hero-badge">
231
- <span class="tag">Open Source</span>
231
+ <span class="tag">v0.4.3</span>
232
232
  Community Skills Marketplace
233
233
  </div>
234
234
  <h1><span class="grad">ClawLing Hub</span></h1>
@@ -231,6 +231,27 @@ section{padding:120px 0;position:relative;overflow:hidden}
231
231
  .gs-card p{font-size:12.5px;color:var(--dim);line-height:1.7}
232
232
  .gs-card code{display:inline-block;margin-top:12px;padding:8px 16px;border-radius:8px;background:var(--bg);border:1px solid var(--border);font-family:'JetBrains Mono',monospace;font-size:12px;color:var(--green)}
233
233
 
234
+ /* ============ API KEY CONFIG ============ */
235
+ .apikeys{background:var(--bg1);position:relative}
236
+ .apikeys::before{content:'';position:absolute;inset:0;background:radial-gradient(ellipse at 30% 50%,rgba(108,92,231,.04),transparent 60%);pointer-events:none}
237
+ .ak-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:16px;margin-top:40px}
238
+ .ak-card{padding:24px;border-radius:var(--r2);background:var(--bg2);border:1px solid var(--border);transition:all .3s;position:relative}
239
+ .ak-card:hover{border-color:rgba(108,92,231,.3);transform:translateY(-3px);box-shadow:0 8px 28px rgba(0,0,0,.2)}
240
+ .ak-card .ak-ico{font-size:28px;margin-bottom:12px;display:block}
241
+ .ak-card .ak-name{font-size:15px;font-weight:700;margin-bottom:4px}
242
+ .ak-card .ak-desc{font-size:12px;color:var(--dim);line-height:1.6;margin-bottom:12px}
243
+ .ak-card .ak-env{font-family:'JetBrains Mono',monospace;font-size:10.5px;padding:6px 10px;border-radius:8px;background:var(--bg);border:1px solid var(--border);color:var(--cyan);word-break:break-all}
244
+ .ak-card .ak-free{display:inline-block;padding:3px 10px;border-radius:100px;font-size:10px;font-weight:700;background:rgba(0,230,118,.1);color:var(--green);border:1px solid rgba(0,230,118,.15);margin-top:8px}
245
+ .ak-methods{max-width:720px;margin:0 auto 32px}
246
+ .ak-methods h3{font-size:17px;font-weight:700;margin-bottom:14px;display:flex;align-items:center;gap:10px}
247
+ .ak-methods h3 .num{width:28px;height:28px;border-radius:50%;background:linear-gradient(135deg,var(--accent),var(--accent3));color:#fff;font-size:13px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
248
+ .ak-code{border-radius:var(--r2);overflow:hidden;border:1px solid var(--border);background:var(--bg);margin-bottom:8px}
249
+ .ak-code-bar{padding:10px 14px;background:var(--bg2);border-bottom:1px solid var(--border);font-size:11px;color:var(--muted);font-family:'JetBrains Mono',monospace}
250
+ .ak-code pre{padding:16px 20px;font-family:'JetBrains Mono',monospace;font-size:12.5px;line-height:1.8;color:var(--dim);overflow-x:auto;margin:0;white-space:pre}
251
+ .ak-code .env-key{color:var(--cyan)}.ak-code .env-val{color:var(--green)}.ak-code .env-cm{color:var(--muted);font-style:italic}
252
+ .ak-note{max-width:720px;margin:28px auto 0;padding:16px 20px;border-radius:var(--r);background:rgba(24,255,255,.04);border:1px solid rgba(24,255,255,.12);font-size:13px;color:var(--dim);line-height:1.7;display:flex;gap:12px;align-items:flex-start}
253
+ .ak-note .note-ico{font-size:16px;flex-shrink:0;margin-top:2px}
254
+
234
255
  /* ============ CTA ============ */
235
256
  .cta{text-align:center;padding:100px 0 120px;position:relative}
236
257
  .cta::before{content:'';position:absolute;inset:0;background:radial-gradient(ellipse at center,rgba(108,92,231,.05),transparent 70%);pointer-events:none}
@@ -256,7 +277,7 @@ section{padding:120px 0;position:relative;overflow:hidden}
256
277
  /* ============ RESPONSIVE ============ */
257
278
  @media(max-width:1024px){.feat-grid{grid-template-columns:repeat(2,1fr)}.lang-grid{grid-template-columns:repeat(3,1fr)}.footer-grid{grid-template-columns:1fr 1fr}}
258
279
  @media(max-width:768px){
259
- .feat-grid,.gs-grid{grid-template-columns:1fr}
280
+ .feat-grid,.gs-grid,.ak-grid{grid-template-columns:1fr}
260
281
  .arch-grid,.wf-grid,.hub-intro{grid-template-columns:1fr}
261
282
  .how-steps{grid-template-columns:repeat(2,1fr)}.how-line{display:none}
262
283
  .lang-grid{grid-template-columns:repeat(2,1fr)}
@@ -286,6 +307,7 @@ section{padding:120px 0;position:relative;overflow:hidden}
286
307
  <a href="#workflows" class="nav-link">Workflows</a>
287
308
  <a href="#hub" class="nav-link">Hub</a>
288
309
  <a href="#architecture" class="nav-link">Architecture</a>
310
+ <a href="#apikeys" class="nav-link">API Keys</a>
289
311
  <a href="hub.html" class="nav-link">ClawLing Hub</a>
290
312
  <a href="https://github.com/LinguDeep/LinguClaw" target="_blank" class="nav-cta">
291
313
  <svg viewBox="0 0 24 24" fill="currentColor" width="16" height="16" style="width:16px;height:16px"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23A11.509 11.509 0 0112 5.803c1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576C20.566 21.797 24 17.3 24 12c0-6.627-5.373-12-12-12z"/></svg>
@@ -307,7 +329,7 @@ section{padding:120px 0;position:relative;overflow:hidden}
307
329
  </div>
308
330
  <div class="container hero-content">
309
331
  <div class="hero-eyebrow">
310
- <span class="tag">v0.4.0</span>
332
+ <span class="tag">v0.4.3</span>
311
333
  <span class="dot"></span>
312
334
  Open Source &middot; Multi-Agent &middot; TypeScript
313
335
  </div>
@@ -348,7 +370,7 @@ section{padding:120px 0;position:relative;overflow:hidden}
348
370
  <div class="sc-body">
349
371
  <div class="sc-line"><span class="t-prompt">❯</span> <span class="t-cmd">npm install -g linguclaw</span></div>
350
372
  <div class="sc-line"><span class="t-prompt">❯</span> <span class="t-cmd">linguclaw init</span> <span class="t-flag">--provider ollama</span></div>
351
- <div class="sc-line"><span class="t-out">🦀 LinguClaw v0.4.0 initialized</span></div>
373
+ <div class="sc-line"><span class="t-out">🦀 LinguClaw v0.4.3 initialized</span></div>
352
374
  <div class="sc-line"><span class="t-out"> ✓ Multi-agent system ready (Coder, Reviewer, Architect)</span></div>
353
375
  <div class="sc-line"><span class="t-out"> ✓ Semantic memory indexed files across <strong style="color:var(--text)">6</strong> languages</span></div>
354
376
  <div class="sc-line"><span class="t-out"> ✓ Workflow engine loaded <strong style="color:var(--text)">22</strong> node types</span></div>
@@ -609,7 +631,7 @@ section{padding:120px 0;position:relative;overflow:hidden}
609
631
  <div class="sh reveal">
610
632
  <div class="sh-badge">🚀 Get Started</div>
611
633
  <h2>Start building in under a minute</h2>
612
- <p>No API key required if you run Ollama locally.</p>
634
+ <p>Supports local and cloud LLMs. See dashboard for provider setup.</p>
613
635
  </div>
614
636
  <div class="gs-grid">
615
637
  <div class="gs-card reveal d1">
@@ -621,7 +643,7 @@ section{padding:120px 0;position:relative;overflow:hidden}
621
643
  <div class="gs-card reveal d2">
622
644
  <div class="gs-step">2</div>
623
645
  <h3>Initialize</h3>
624
- <p>Set up your project with your preferred LLM provider.</p>
646
+ <p>Set up your project with your preferred LLM provider. <a href="#apikeys" style="color:var(--accent2);font-weight:600">Configure API keys ↓</a></p>
625
647
  <code>linguclaw init</code>
626
648
  </div>
627
649
  <div class="gs-card reveal d3">
@@ -634,6 +656,109 @@ section{padding:120px 0;position:relative;overflow:hidden}
634
656
  </div>
635
657
  </section>
636
658
 
659
+ <!-- ======== API KEY CONFIGURATION ======== -->
660
+ <section class="apikeys" id="apikeys">
661
+ <div class="container">
662
+ <div class="sh reveal">
663
+ <div class="sh-badge">🔑 Configuration</div>
664
+ <h2>Set up your API keys</h2>
665
+ <p>Configure cloud LLM providers with API keys, or use Ollama / LM Studio for completely free local inference.</p>
666
+ </div>
667
+
668
+ <div class="ak-methods reveal">
669
+ <h3><span class="num">1</span> Environment Variables (Recommended)</h3>
670
+ <div class="ak-code">
671
+ <div class="ak-code-bar">.env &nbsp;/&nbsp; ~/.bashrc &nbsp;/&nbsp; ~/.zshrc</div>
672
+ <pre><span class="env-cm"># Cloud Providers — pick one or more</span>
673
+ <span class="env-key">OPENAI_API_KEY</span>=<span class="env-val">"sk-proj-..."</span>
674
+ <span class="env-key">ANTHROPIC_API_KEY</span>=<span class="env-val">"sk-ant-api03-..."</span>
675
+ <span class="env-key">OPENROUTER_API_KEY</span>=<span class="env-val">"sk-or-v1-..."</span>
676
+ <span class="env-key">GOOGLE_API_KEY</span>=<span class="env-val">"AIza..."</span>
677
+ <span class="env-key">XAI_API_KEY</span>=<span class="env-val">"xai-..."</span>
678
+
679
+ <span class="env-cm"># Optional: Set default provider</span>
680
+ <span class="env-key">LINGUCLAW_PROVIDER</span>=<span class="env-val">"openai"</span></pre>
681
+ </div>
682
+ </div>
683
+
684
+ <div class="ak-methods reveal">
685
+ <h3><span class="num">2</span> Interactive Setup via CLI</h3>
686
+ <div class="ak-code">
687
+ <div class="ak-code-bar">terminal</div>
688
+ <pre><span class="env-cm"># Initialize with a specific provider</span>
689
+ <span class="env-key">❯</span> linguclaw init <span class="env-val">--provider openai</span>
690
+ <span class="env-cm"># You'll be prompted for your API key interactively</span>
691
+
692
+ <span class="env-cm"># Or switch providers anytime</span>
693
+ <span class="env-key">❯</span> linguclaw config <span class="env-val">set provider anthropic</span>
694
+ <span class="env-key">❯</span> linguclaw config <span class="env-val">set api-key sk-ant-...</span></pre>
695
+ </div>
696
+ </div>
697
+
698
+ <div class="ak-note reveal">
699
+ <span class="note-ico">💡</span>
700
+ <span>Using <strong style="color:var(--text)">Ollama</strong> or <strong style="color:var(--text)">LM Studio</strong>? No API key needed — just install and run locally. LinguClaw auto-detects local providers on <code style="color:var(--cyan)">localhost:11434</code> (Ollama) or <code style="color:var(--cyan)">localhost:1234</code> (LM Studio).</span>
701
+ </div>
702
+
703
+ <div class="ak-grid">
704
+ <div class="ak-card reveal d1">
705
+ <span class="ak-ico">🤖</span>
706
+ <div class="ak-name">OpenAI</div>
707
+ <div class="ak-desc">GPT-4o, o1, GPT-5</div>
708
+ <div class="ak-env">OPENAI_API_KEY</div>
709
+ </div>
710
+ <div class="ak-card reveal d2">
711
+ <span class="ak-ico">🧠</span>
712
+ <div class="ak-name">Anthropic</div>
713
+ <div class="ak-desc">Claude 3.5 / Claude 4</div>
714
+ <div class="ak-env">ANTHROPIC_API_KEY</div>
715
+ </div>
716
+ <div class="ak-card reveal d3">
717
+ <span class="ak-ico">🌐</span>
718
+ <div class="ak-name">OpenRouter</div>
719
+ <div class="ak-desc">100+ models, one key</div>
720
+ <div class="ak-env">OPENROUTER_API_KEY</div>
721
+ </div>
722
+ <div class="ak-card reveal d1">
723
+ <span class="ak-ico">🔵</span>
724
+ <div class="ak-name">Google</div>
725
+ <div class="ak-desc">Gemini 1.5 / 2.5</div>
726
+ <div class="ak-env">GOOGLE_API_KEY</div>
727
+ </div>
728
+ <div class="ak-card reveal d2">
729
+ <span class="ak-ico">✖️</span>
730
+ <div class="ak-name">xAI</div>
731
+ <div class="ak-desc">Grok models</div>
732
+ <div class="ak-env">XAI_API_KEY</div>
733
+ </div>
734
+ <div class="ak-card reveal d3">
735
+ <span class="ak-ico">🦙</span>
736
+ <div class="ak-name">Ollama</div>
737
+ <div class="ak-desc">Free local models</div>
738
+ <span class="ak-free">No API Key Required</span>
739
+ </div>
740
+ <div class="ak-card reveal d1">
741
+ <span class="ak-ico">💻</span>
742
+ <div class="ak-name">LM Studio</div>
743
+ <div class="ak-desc">Desktop local models</div>
744
+ <span class="ak-free">No API Key Required</span>
745
+ </div>
746
+ <div class="ak-card reveal d2">
747
+ <span class="ak-ico">🌬️</span>
748
+ <div class="ak-name">Mistral</div>
749
+ <div class="ak-desc">Mistral AI models</div>
750
+ <div class="ak-env">MISTRAL_API_KEY</div>
751
+ </div>
752
+ <div class="ak-card reveal d3">
753
+ <span class="ak-ico">🔍</span>
754
+ <div class="ak-name">DeepSeek</div>
755
+ <div class="ak-desc">DeepSeek V3 &amp; R1</div>
756
+ <div class="ak-env">DEEPSEEK_API_KEY</div>
757
+ </div>
758
+ </div>
759
+ </div>
760
+ </section>
761
+
637
762
  <!-- ======== CTA ======== -->
638
763
  <section class="cta">
639
764
  <div class="container reveal">