openclacky 1.2.7 → 1.2.8
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/lib/clacky/agent.rb +3 -0
- data/lib/clacky/billing/billing_store.rb +107 -3
- data/lib/clacky/cli.rb +105 -0
- data/lib/clacky/client.rb +32 -3
- data/lib/clacky/default_skills/deploy/SKILL.md +2 -1
- data/lib/clacky/default_skills/extend-openclacky/SKILL.md +39 -0
- data/lib/clacky/default_skills/mcp-manager/SKILL.md +0 -7
- data/lib/clacky/patch_loader.rb +282 -0
- data/lib/clacky/server/channel/adapters/base.rb +4 -0
- data/lib/clacky/server/channel/channel_manager.rb +1 -1
- data/lib/clacky/server/channel/user_adapter_loader.rb +177 -0
- data/lib/clacky/server/channel.rb +5 -0
- data/lib/clacky/server/http_server.rb +26 -5
- data/lib/clacky/server/scheduler.rb +1 -4
- data/lib/clacky/shell_hook_loader.rb +181 -0
- data/lib/clacky/version.rb +1 -1
- data/lib/clacky/web/app.css +155 -13
- data/lib/clacky/web/billing.js +117 -22
- data/lib/clacky/web/i18n.js +26 -6
- data/lib/clacky.rb +6 -0
- metadata +6 -2
data/lib/clacky/web/billing.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
const Billing = (() => {
|
|
5
5
|
let _summary = null;
|
|
6
6
|
let _daily = [];
|
|
7
|
+
let _sessions = []; // 会话列表
|
|
7
8
|
let _allModels = []; // 保存完整的模型列表
|
|
8
9
|
let _currentPeriod = "day";
|
|
9
10
|
let _currentModel = "all";
|
|
@@ -73,15 +74,19 @@ const Billing = (() => {
|
|
|
73
74
|
|
|
74
75
|
try {
|
|
75
76
|
const modelParam = (_currentModel && _currentModel !== "all") ? `&model=${encodeURIComponent(_currentModel)}` : "";
|
|
76
|
-
const [summaryRes, dailyRes] = await Promise.all([
|
|
77
|
+
const [summaryRes, dailyRes, sessionsRes] = await Promise.all([
|
|
77
78
|
fetch(`/api/billing/summary?period=${_currentPeriod}${modelParam}`),
|
|
78
|
-
fetch(`/api/billing/daily?days=30${modelParam}`)
|
|
79
|
+
fetch(`/api/billing/daily?days=30${modelParam}`),
|
|
80
|
+
fetch(`/api/billing/sessions?period=${_currentPeriod}${modelParam}&limit=100`)
|
|
79
81
|
]);
|
|
80
82
|
|
|
81
83
|
_summary = await summaryRes.json();
|
|
82
84
|
const dailyData = await dailyRes.json();
|
|
83
85
|
_daily = dailyData.days || [];
|
|
84
86
|
|
|
87
|
+
const sessionsData = await sessionsRes.json();
|
|
88
|
+
_sessions = sessionsData.sessions || [];
|
|
89
|
+
|
|
85
90
|
// 保存完整模型列表(仅在未筛选时更新)
|
|
86
91
|
if (!_currentModel || _currentModel === "all") {
|
|
87
92
|
_allModels = _summary.by_model ? Object.keys(_summary.by_model) : [];
|
|
@@ -172,6 +177,10 @@ const Billing = (() => {
|
|
|
172
177
|
<div class="billing-chart-row">
|
|
173
178
|
${_renderCombinedChart()}
|
|
174
179
|
</div>
|
|
180
|
+
|
|
181
|
+
<div class="billing-sessions-row">
|
|
182
|
+
${_renderSessionList()}
|
|
183
|
+
</div>
|
|
175
184
|
</div>
|
|
176
185
|
`;
|
|
177
186
|
|
|
@@ -219,14 +228,19 @@ const Billing = (() => {
|
|
|
219
228
|
<span class="tooltip-date">${date}</span>
|
|
220
229
|
<span class="tooltip-total">${total} tokens</span>
|
|
221
230
|
</div>
|
|
231
|
+
<div class="tooltip-row">
|
|
232
|
+
<span class="tooltip-dot tooltip-total"></span>
|
|
233
|
+
<span class="tooltip-label">${I18n.t("billing.totalTokens") || "Total Tokens"}</span>
|
|
234
|
+
<span class="tooltip-value">${total}</span>
|
|
235
|
+
</div>
|
|
222
236
|
<div class="tooltip-row">
|
|
223
237
|
<span class="tooltip-dot tooltip-cache-hit"></span>
|
|
224
|
-
<span class="tooltip-label">${I18n.t("billing.inputCacheHit") || "Input (
|
|
238
|
+
<span class="tooltip-label">${I18n.t("billing.inputCacheHit") || "Input (Hit)"}</span>
|
|
225
239
|
<span class="tooltip-value">${cacheHit}</span>
|
|
226
240
|
</div>
|
|
227
241
|
<div class="tooltip-row">
|
|
228
242
|
<span class="tooltip-dot tooltip-cache-miss"></span>
|
|
229
|
-
<span class="tooltip-label">${I18n.t("billing.inputCacheMiss") || "Input (
|
|
243
|
+
<span class="tooltip-label">${I18n.t("billing.inputCacheMiss") || "Input (Miss)"}</span>
|
|
230
244
|
<span class="tooltip-value">${cacheMiss}</span>
|
|
231
245
|
</div>
|
|
232
246
|
<div class="tooltip-row">
|
|
@@ -333,35 +347,50 @@ const Billing = (() => {
|
|
|
333
347
|
}
|
|
334
348
|
|
|
335
349
|
function _renderTokenBreakdown() {
|
|
350
|
+
const totalTokens = _summary.total_tokens || 0;
|
|
351
|
+
const promptTokens = _summary.prompt_tokens || 0;
|
|
352
|
+
const completionTokens = _summary.completion_tokens || 0;
|
|
353
|
+
const cacheReadTokens = _summary.cache_read_tokens || 0;
|
|
354
|
+
const cacheMissTokens = promptTokens - cacheReadTokens;
|
|
355
|
+
|
|
336
356
|
return `
|
|
337
357
|
<div class="billing-section billing-token-section">
|
|
338
358
|
<h3>${I18n.t("billing.tokenBreakdown") || "Token Breakdown"}</h3>
|
|
339
359
|
<div class="billing-token-bars">
|
|
340
360
|
<div class="billing-token-bar-item">
|
|
341
361
|
<div class="billing-token-bar-header">
|
|
342
|
-
<span class="billing-token-bar-label">${I18n.t("billing.
|
|
343
|
-
<span class="billing-token-bar-value">${_formatCompact(
|
|
362
|
+
<span class="billing-token-bar-label">${I18n.t("billing.totalTokens") || "Total Tokens"}</span>
|
|
363
|
+
<span class="billing-token-bar-value">${_formatCompact(totalTokens)}</span>
|
|
344
364
|
</div>
|
|
345
365
|
<div class="billing-token-bar-track">
|
|
346
|
-
<div class="billing-token-bar-fill billing-bar-
|
|
366
|
+
<div class="billing-token-bar-fill billing-bar-total" style="width: 100%"></div>
|
|
347
367
|
</div>
|
|
348
368
|
</div>
|
|
349
369
|
<div class="billing-token-bar-item">
|
|
350
370
|
<div class="billing-token-bar-header">
|
|
351
|
-
<span class="billing-token-bar-label">${I18n.t("billing.
|
|
352
|
-
<span class="billing-token-bar-value">${_formatCompact(
|
|
371
|
+
<span class="billing-token-bar-label">${I18n.t("billing.inputCacheHit") || "Input (Hit)"}</span>
|
|
372
|
+
<span class="billing-token-bar-value">${_formatCompact(cacheReadTokens)}</span>
|
|
353
373
|
</div>
|
|
354
374
|
<div class="billing-token-bar-track">
|
|
355
|
-
<div class="billing-token-bar-fill billing-bar-
|
|
375
|
+
<div class="billing-token-bar-fill billing-bar-cache-read" style="width: ${_getTokenPercent(cacheReadTokens, totalTokens)}%"></div>
|
|
376
|
+
</div>
|
|
377
|
+
</div>
|
|
378
|
+
<div class="billing-token-bar-item">
|
|
379
|
+
<div class="billing-token-bar-header">
|
|
380
|
+
<span class="billing-token-bar-label">${I18n.t("billing.inputCacheMiss") || "Input (Miss)"}</span>
|
|
381
|
+
<span class="billing-token-bar-value">${_formatCompact(cacheMissTokens)}</span>
|
|
382
|
+
</div>
|
|
383
|
+
<div class="billing-token-bar-track">
|
|
384
|
+
<div class="billing-token-bar-fill billing-bar-cache-miss" style="width: ${_getTokenPercent(cacheMissTokens, totalTokens)}%"></div>
|
|
356
385
|
</div>
|
|
357
386
|
</div>
|
|
358
387
|
<div class="billing-token-bar-item">
|
|
359
388
|
<div class="billing-token-bar-header">
|
|
360
389
|
<span class="billing-token-bar-label">${I18n.t("billing.output") || "Output"}</span>
|
|
361
|
-
<span class="billing-token-bar-value">${_formatCompact(
|
|
390
|
+
<span class="billing-token-bar-value">${_formatCompact(completionTokens)}</span>
|
|
362
391
|
</div>
|
|
363
392
|
<div class="billing-token-bar-track">
|
|
364
|
-
<div class="billing-token-bar-fill billing-bar-completion" style="width: ${_getTokenPercent(
|
|
393
|
+
<div class="billing-token-bar-fill billing-bar-completion" style="width: ${_getTokenPercent(completionTokens, totalTokens)}%"></div>
|
|
365
394
|
</div>
|
|
366
395
|
</div>
|
|
367
396
|
</div>
|
|
@@ -369,9 +398,8 @@ const Billing = (() => {
|
|
|
369
398
|
`;
|
|
370
399
|
}
|
|
371
400
|
|
|
372
|
-
function _getTokenPercent(
|
|
373
|
-
|
|
374
|
-
const value = _summary[type + '_tokens'] || 0;
|
|
401
|
+
function _getTokenPercent(value, total) {
|
|
402
|
+
if (!total || total === 0) return 0;
|
|
375
403
|
return Math.min((value / total) * 100, 100).toFixed(1);
|
|
376
404
|
}
|
|
377
405
|
|
|
@@ -427,9 +455,8 @@ const Billing = (() => {
|
|
|
427
455
|
|
|
428
456
|
const recentDays = _daily.slice(-14);
|
|
429
457
|
// Max values for scaling
|
|
430
|
-
const maxInput = Math.max(...recentDays.map(d =>
|
|
431
|
-
const maxOutput = Math.max(...recentDays.map(d => d.completion_tokens || 0), 1);
|
|
432
|
-
const maxVal = Math.max(maxInput, maxOutput);
|
|
458
|
+
const maxInput = Math.max(...recentDays.map(d => d.prompt_tokens || 0), 1);
|
|
459
|
+
const maxOutput = Math.max(...recentDays.map(d => d.completion_tokens || 0), 1); const maxVal = Math.max(maxInput, maxOutput);
|
|
433
460
|
|
|
434
461
|
// Chart height in pixels
|
|
435
462
|
const chartHeight = 120;
|
|
@@ -437,9 +464,10 @@ const Billing = (() => {
|
|
|
437
464
|
// Generate bars: each date has Input (stacked: cache hit + cache miss) and Output
|
|
438
465
|
const chartBars = recentDays.map((d, i) => {
|
|
439
466
|
const cacheHit = d.cache_read_tokens || 0; // 命中缓存
|
|
440
|
-
const
|
|
467
|
+
const totalPrompt = d.prompt_tokens || 0; // 全部输入token
|
|
468
|
+
const cacheMiss = totalPrompt - cacheHit; // 未命中缓存 = 全部输入 - 命中
|
|
441
469
|
const output = d.completion_tokens || 0;
|
|
442
|
-
const totalInput =
|
|
470
|
+
const totalInput = totalPrompt;
|
|
443
471
|
const totalTokens = totalInput + output;
|
|
444
472
|
|
|
445
473
|
// Calculate heights in pixels
|
|
@@ -471,13 +499,17 @@ const Billing = (() => {
|
|
|
471
499
|
<div class="billing-chart-header">
|
|
472
500
|
<h4>${I18n.t("billing.dailyUsage") || "Usage Details"}</h4>
|
|
473
501
|
<div class="billing-chart-legends">
|
|
502
|
+
<span class="billing-chart-legend">
|
|
503
|
+
<span class="billing-legend-dot billing-legend-total"></span>
|
|
504
|
+
${I18n.t("billing.totalTokens") || "Total Tokens"}
|
|
505
|
+
</span>
|
|
474
506
|
<span class="billing-chart-legend">
|
|
475
507
|
<span class="billing-legend-dot billing-legend-cache-hit"></span>
|
|
476
|
-
${I18n.t("billing.inputCacheHit") || "Input (
|
|
508
|
+
${I18n.t("billing.inputCacheHit") || "Input (Hit)"}
|
|
477
509
|
</span>
|
|
478
510
|
<span class="billing-chart-legend">
|
|
479
511
|
<span class="billing-legend-dot billing-legend-cache-miss"></span>
|
|
480
|
-
${I18n.t("billing.inputCacheMiss") || "Input (
|
|
512
|
+
${I18n.t("billing.inputCacheMiss") || "Input (Miss)"}
|
|
481
513
|
</span>
|
|
482
514
|
<span class="billing-chart-legend">
|
|
483
515
|
<span class="billing-legend-dot billing-legend-output"></span>
|
|
@@ -493,6 +525,69 @@ const Billing = (() => {
|
|
|
493
525
|
`;
|
|
494
526
|
}
|
|
495
527
|
|
|
528
|
+
function _renderSessionList() {
|
|
529
|
+
if (!_sessions || _sessions.length === 0) {
|
|
530
|
+
return `
|
|
531
|
+
<div class="billing-section billing-sessions-section">
|
|
532
|
+
<h3>${I18n.t("billing.sessions") || "Sessions"}</h3>
|
|
533
|
+
<div class="billing-sessions-empty">${I18n.t("billing.noSessions") || "No session data"}</div>
|
|
534
|
+
</div>
|
|
535
|
+
`;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const rows = _sessions.map((s, index) => {
|
|
539
|
+
const sessionId = s.session_id || "unknown";
|
|
540
|
+
const isDeleted = s.is_deleted;
|
|
541
|
+
const sessionName = s.session_name || sessionId;
|
|
542
|
+
const displayName = isDeleted ? (I18n.t("billing.deletedSessions") || "已删除会话") : (sessionName.length > 25 ? sessionName.slice(0, 25) + "..." : sessionName);
|
|
543
|
+
const totalCost = _convertCost(s.total_cost || 0);
|
|
544
|
+
const totalTokens = s.total_tokens || 0;
|
|
545
|
+
const promptTokens = s.prompt_tokens || 0;
|
|
546
|
+
const cacheHit = s.cache_read_tokens || 0;
|
|
547
|
+
const cacheMiss = promptTokens - cacheHit;
|
|
548
|
+
const completionTokens = s.completion_tokens || 0;
|
|
549
|
+
const requests = s.requests || 0;
|
|
550
|
+
const models = (s.models || []).join(", ");
|
|
551
|
+
const lastRequest = s.last_request ? new Date(s.last_request).toLocaleString() : "-";
|
|
552
|
+
const rowClass = isDeleted ? "billing-session-row billing-session-deleted" : "billing-session-row";
|
|
553
|
+
|
|
554
|
+
return `
|
|
555
|
+
<div class="${rowClass}" data-session-id="${_esc(sessionId)}">
|
|
556
|
+
<div class="billing-cell billing-cell-index">${index + 1}</div>
|
|
557
|
+
<div class="billing-cell billing-cell-session" title="${_esc(sessionName)}">
|
|
558
|
+
<span class="billing-cell-main">${_esc(displayName)}</span>
|
|
559
|
+
<span class="billing-cell-sub">${requests} ${I18n.t("billing.requests") || "req"} · ${_esc(models)}</span>
|
|
560
|
+
</div>
|
|
561
|
+
<div class="billing-cell billing-cell-number">${_formatCompact(totalTokens)}</div>
|
|
562
|
+
<div class="billing-cell billing-cell-number billing-cell-hit">${_formatCompact(cacheHit)}</div>
|
|
563
|
+
<div class="billing-cell billing-cell-number billing-cell-miss">${_formatCompact(cacheMiss)}</div>
|
|
564
|
+
<div class="billing-cell billing-cell-number">${_formatCompact(completionTokens)}</div>
|
|
565
|
+
<div class="billing-cell billing-cell-cost">${_getCurrencySymbol()}${_formatCost(totalCost)}</div>
|
|
566
|
+
<div class="billing-cell billing-cell-time">${lastRequest}</div>
|
|
567
|
+
</div>
|
|
568
|
+
`;
|
|
569
|
+
}).join("");
|
|
570
|
+
|
|
571
|
+
return `
|
|
572
|
+
<div class="billing-section billing-sessions-section">
|
|
573
|
+
<h3>${I18n.t("billing.sessions") || "Sessions"}</h3>
|
|
574
|
+
<div class="billing-sessions-header">
|
|
575
|
+
<span class="billing-cell billing-cell-index">#</span>
|
|
576
|
+
<span class="billing-cell billing-cell-session">${I18n.t("billing.sessionId") || "Session"}</span>
|
|
577
|
+
<span class="billing-cell billing-cell-number">${I18n.t("billing.headerTotal") || "总消耗"}</span>
|
|
578
|
+
<span class="billing-cell billing-cell-number">${I18n.t("billing.headerHit") || "命中"}</span>
|
|
579
|
+
<span class="billing-cell billing-cell-number">${I18n.t("billing.headerMiss") || "未命中"}</span>
|
|
580
|
+
<span class="billing-cell billing-cell-number">${I18n.t("billing.headerOutput") || "输出"}</span>
|
|
581
|
+
<span class="billing-cell billing-cell-cost">${I18n.t("billing.cost") || "Cost"}</span>
|
|
582
|
+
<span class="billing-cell billing-cell-time">${I18n.t("billing.lastRequest") || "Time"}</span>
|
|
583
|
+
</div>
|
|
584
|
+
<div class="billing-sessions-list">
|
|
585
|
+
${rows}
|
|
586
|
+
</div>
|
|
587
|
+
</div>
|
|
588
|
+
`;
|
|
589
|
+
}
|
|
590
|
+
|
|
496
591
|
// ── Helpers ─────────────────────────────────────────────────────────────────
|
|
497
592
|
|
|
498
593
|
function _formatCost(cost) {
|
data/lib/clacky/web/i18n.js
CHANGED
|
@@ -686,15 +686,25 @@ const I18n = (() => {
|
|
|
686
686
|
"billing.cacheHit": "Cache Hit",
|
|
687
687
|
"billing.inputCacheHit": "Input (Cache Hit)",
|
|
688
688
|
"billing.inputCacheMiss": "Input (Cache Miss)",
|
|
689
|
-
"billing.
|
|
690
|
-
"billing.tokenUsage": "Token Usage",
|
|
689
|
+
"billing.totalInput": "Total Input",
|
|
690
|
+
"billing.output": "Output", "billing.tokenUsage": "Token Usage",
|
|
691
691
|
"billing.costTrend": "Cost Trend",
|
|
692
692
|
"billing.noData": "No data available",
|
|
693
693
|
|
|
694
694
|
"error.insufficient_credit": "Insufficient LLM credit. Please top up your account to continue.",
|
|
695
695
|
"error.insufficient_credit.action": "Top up",
|
|
696
|
-
},
|
|
697
696
|
|
|
697
|
+
"billing.sessions": "Sessions",
|
|
698
|
+
"billing.sessionId": "Session",
|
|
699
|
+
"billing.tokens": "Tokens",
|
|
700
|
+
"billing.lastRequest": "Last Request",
|
|
701
|
+
"billing.noSessions": "No session data",
|
|
702
|
+
"billing.deletedSessions": "Deleted Sessions",
|
|
703
|
+
"billing.headerTotal": "Total",
|
|
704
|
+
"billing.headerHit": "Hit",
|
|
705
|
+
"billing.headerMiss": "Miss",
|
|
706
|
+
"billing.headerOutput": "Output",
|
|
707
|
+
},
|
|
698
708
|
zh: {
|
|
699
709
|
// ── Sidebar ──
|
|
700
710
|
"sidebar.chat": "会话",
|
|
@@ -1366,16 +1376,26 @@ const I18n = (() => {
|
|
|
1366
1376
|
"billing.cacheHit": "缓存命中",
|
|
1367
1377
|
"billing.inputCacheHit": "输入(命中缓存)",
|
|
1368
1378
|
"billing.inputCacheMiss": "输入(未命中缓存)",
|
|
1369
|
-
"billing.
|
|
1370
|
-
"billing.
|
|
1379
|
+
"billing.totalTokens": "Token 总消耗",
|
|
1380
|
+
"billing.totalInput": "总输入",
|
|
1381
|
+
"billing.output": "输出", "billing.tokenUsage": "Token 用量",
|
|
1371
1382
|
"billing.costTrend": "费用趋势",
|
|
1372
1383
|
"billing.noData": "暂无数据",
|
|
1373
1384
|
|
|
1374
1385
|
"error.insufficient_credit": "LLM(大模型)余额不足,请充值后继续使用。",
|
|
1375
1386
|
"error.insufficient_credit.action": "去充值",
|
|
1387
|
+
"billing.sessions": "会话消耗",
|
|
1388
|
+
"billing.sessionId": "会话",
|
|
1389
|
+
"billing.tokens": "Token",
|
|
1390
|
+
"billing.lastRequest": "最后请求",
|
|
1391
|
+
"billing.noSessions": "暂无会话数据",
|
|
1392
|
+
"billing.deletedSessions": "已删除会话",
|
|
1393
|
+
"billing.headerTotal": "总消耗",
|
|
1394
|
+
"billing.headerHit": "命中",
|
|
1395
|
+
"billing.headerMiss": "未命中",
|
|
1396
|
+
"billing.headerOutput": "输出",
|
|
1376
1397
|
}
|
|
1377
1398
|
};
|
|
1378
|
-
|
|
1379
1399
|
// ── State ──────────────────────────────────────────────────────────────────
|
|
1380
1400
|
let _lang = localStorage.getItem(STORAGE_KEY) || DEFAULT_LANG;
|
|
1381
1401
|
|
data/lib/clacky.rb
CHANGED
|
@@ -83,6 +83,7 @@ require_relative "clacky/idle_compression_timer"
|
|
|
83
83
|
# Agent modules
|
|
84
84
|
require_relative "clacky/agent/message_compressor"
|
|
85
85
|
require_relative "clacky/agent/hook_manager"
|
|
86
|
+
require_relative "clacky/shell_hook_loader"
|
|
86
87
|
require_relative "clacky/agent/tool_registry"
|
|
87
88
|
|
|
88
89
|
# UI modules
|
|
@@ -132,6 +133,11 @@ require_relative "clacky/server/web_ui_controller"
|
|
|
132
133
|
require_relative "clacky/server/browser_manager"
|
|
133
134
|
require_relative "clacky/cli"
|
|
134
135
|
|
|
136
|
+
# Runtime patch layer: load user/AI patches from ~/.clacky/patches/ after all
|
|
137
|
+
# gem code is defined, so fingerprints reflect the actual installed source.
|
|
138
|
+
require_relative "clacky/patch_loader"
|
|
139
|
+
Clacky::PatchLoader.load_all
|
|
140
|
+
|
|
135
141
|
module Clacky
|
|
136
142
|
class AgentInterrupted < Exception; end # Inherit from Exception to bypass rescue StandardError
|
|
137
143
|
class AgentError < StandardError; end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: openclacky
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- windy
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-06-01 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: faraday
|
|
@@ -374,6 +374,7 @@ files:
|
|
|
374
374
|
- lib/clacky/default_skills/cron-task-creator/SKILL.md
|
|
375
375
|
- lib/clacky/default_skills/cron-task-creator/evals/evals.json
|
|
376
376
|
- lib/clacky/default_skills/deploy/SKILL.md
|
|
377
|
+
- lib/clacky/default_skills/extend-openclacky/SKILL.md
|
|
377
378
|
- lib/clacky/default_skills/mcp-manager/SKILL.md
|
|
378
379
|
- lib/clacky/default_skills/new/SKILL.md
|
|
379
380
|
- lib/clacky/default_skills/new/scripts/create_rails_project.sh
|
|
@@ -417,6 +418,7 @@ files:
|
|
|
417
418
|
- lib/clacky/message_format/open_ai.rb
|
|
418
419
|
- lib/clacky/message_history.rb
|
|
419
420
|
- lib/clacky/openai_stream_aggregator.rb
|
|
421
|
+
- lib/clacky/patch_loader.rb
|
|
420
422
|
- lib/clacky/plain_ui_controller.rb
|
|
421
423
|
- lib/clacky/platform_http_client.rb
|
|
422
424
|
- lib/clacky/providers.rb
|
|
@@ -444,6 +446,7 @@ files:
|
|
|
444
446
|
- lib/clacky/server/channel/channel_config.rb
|
|
445
447
|
- lib/clacky/server/channel/channel_manager.rb
|
|
446
448
|
- lib/clacky/server/channel/channel_ui_controller.rb
|
|
449
|
+
- lib/clacky/server/channel/user_adapter_loader.rb
|
|
447
450
|
- lib/clacky/server/discover.rb
|
|
448
451
|
- lib/clacky/server/epipe_safe_io.rb
|
|
449
452
|
- lib/clacky/server/http_server.rb
|
|
@@ -452,6 +455,7 @@ files:
|
|
|
452
455
|
- lib/clacky/server/session_registry.rb
|
|
453
456
|
- lib/clacky/server/web_ui_controller.rb
|
|
454
457
|
- lib/clacky/session_manager.rb
|
|
458
|
+
- lib/clacky/shell_hook_loader.rb
|
|
455
459
|
- lib/clacky/skill.rb
|
|
456
460
|
- lib/clacky/skill_loader.rb
|
|
457
461
|
- lib/clacky/telemetry.rb
|