wormclaude 1.0.19 → 1.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +2 -0
- package/dist/cli.js +18 -59
- package/dist/highlight.js +132 -0
- package/dist/markdown.js +17 -3
- package/dist/telemetry.js +37 -0
- package/dist/theme.js +9 -1
- package/dist/tools.js +5 -0
- package/package.json +1 -1
package/dist/api.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { loadStored, DEFAULT_BASE_URL } from './auth.js';
|
|
5
5
|
import { StreamingToolCallParser } from './streamparser.js';
|
|
6
6
|
import { safeJsonStringify } from './safejson.js';
|
|
7
|
+
import { getTrace, getSession } from './telemetry.js';
|
|
7
8
|
export function loadConfig() {
|
|
8
9
|
const stored = loadStored();
|
|
9
10
|
return {
|
|
@@ -124,6 +125,7 @@ export async function* streamChat(messages, tools, config, signal) {
|
|
|
124
125
|
headers: {
|
|
125
126
|
'Content-Type': 'application/json',
|
|
126
127
|
...(config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}),
|
|
128
|
+
...(getTrace() ? { 'X-WC-Trace': getTrace(), 'X-WC-Session': getSession() } : {}),
|
|
127
129
|
},
|
|
128
130
|
body: JSON.stringify(body),
|
|
129
131
|
signal,
|
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import React, { useState, useRef, useEffect } from 'react';
|
|
3
|
-
import { render, Box, Text, useApp, useInput } from 'ink';
|
|
3
|
+
import { render, Box, Text, Static, useApp, useInput } from 'ink';
|
|
4
4
|
import TextInput from 'ink-text-input';
|
|
5
5
|
import * as path from 'node:path';
|
|
6
6
|
import { theme, VERSION } from './theme.js';
|
|
7
7
|
import { loadConfig, streamChat, fetchAccount } from './api.js';
|
|
8
|
+
import { newTrace, flushTelemetry } from './telemetry.js';
|
|
8
9
|
import { tier } from './program.js';
|
|
9
10
|
import { allToolSchemas, executeToolCalls, executeTool, toolLabel, setToolConfig } from './tools.js';
|
|
10
11
|
import { sanitizeError, sanitizeOutput } from './errorsan.js';
|
|
@@ -84,18 +85,10 @@ const _initHistory = () => {
|
|
|
84
85
|
sys.push({ role: 'system', content: _memCtx });
|
|
85
86
|
return sys;
|
|
86
87
|
};
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
// ?1049h alt-screen
|
|
90
|
-
|
|
91
|
-
process.stdout.write('\x1b[?1049h\x1b[?1007h\x1b[2J\x1b[H');
|
|
92
|
-
}
|
|
93
|
-
catch { }
|
|
94
|
-
const _leaveAlt = () => { try {
|
|
95
|
-
process.stdout.write('\x1b[?1007l\x1b[?1049l');
|
|
96
|
-
}
|
|
97
|
-
catch { } };
|
|
98
|
-
process.on('exit', _leaveAlt);
|
|
88
|
+
// NORMAL buffer (alt-screen YOK) — transcript <Static> ile gerçek terminal scrollback'ine
|
|
89
|
+
// basılır. Böylece terminalin doğal kaydırması (fare tekerleği / Shift+PageUp) ve metin
|
|
90
|
+
// seçip kopyalama tam çalışır. Eskiden ?1049h alt-screen kullanılıyordu; o, scrollback'i ve
|
|
91
|
+
// kopyalamayı engelliyordu — kaldırıldı.
|
|
99
92
|
function useDimensions() {
|
|
100
93
|
const [d, setD] = useState({
|
|
101
94
|
cols: process.stdout.columns || 80,
|
|
@@ -447,25 +440,9 @@ function App() {
|
|
|
447
440
|
else if (key.downArrow)
|
|
448
441
|
setCmdSel((s) => (s + 1) % n);
|
|
449
442
|
});
|
|
450
|
-
//
|
|
451
|
-
//
|
|
452
|
-
|
|
453
|
-
if (!started || perm || ask || lang === null)
|
|
454
|
-
return;
|
|
455
|
-
// satır-temelli; üst sınır render'da off=min(scroll,maxScroll) ile kırpılır
|
|
456
|
-
if (key.pageUp)
|
|
457
|
-
setScroll((s) => s + 10);
|
|
458
|
-
else if (key.pageDown)
|
|
459
|
-
setScroll((s) => Math.max(0, s - 10));
|
|
460
|
-
else if (input === '' && !busy) {
|
|
461
|
-
if (key.upArrow)
|
|
462
|
-
setScroll((s) => s + 3);
|
|
463
|
-
else if (key.downArrow)
|
|
464
|
-
setScroll((s) => Math.max(0, s - 3));
|
|
465
|
-
}
|
|
466
|
-
});
|
|
467
|
-
// Yeni mesaj gelince en alta dön
|
|
468
|
-
useEffect(() => { setScroll(0); }, [items.length]);
|
|
443
|
+
// NOT: Transcript artık <Static> ile terminal scrollback'ine basılıyor; kaydırma
|
|
444
|
+
// terminalin kendi işi (fare tekerleği / Shift+PageUp). Tuşları YAKALAMIYORUZ ki
|
|
445
|
+
// doğal kaydırma + metin seçip kopyalama bozulmasın.
|
|
469
446
|
// Başlangıçta güven seviyesini (Doğrulanmış Araştırmacı Programı) çek → StatusLine rozeti
|
|
470
447
|
useEffect(() => {
|
|
471
448
|
if (!started)
|
|
@@ -518,6 +495,7 @@ function App() {
|
|
|
518
495
|
const ac = new AbortController();
|
|
519
496
|
abortRef.current = ac;
|
|
520
497
|
setBusy(true);
|
|
498
|
+
newTrace(); // observability: bu tur için yeni dağıtık-trace id (gateway + tool span'ları birleşir)
|
|
521
499
|
push({ kind: 'user', text: displayText ?? userText });
|
|
522
500
|
historyRef.current = [...historyRef.current, { role: 'user', content: userText }];
|
|
523
501
|
let iter = 0;
|
|
@@ -675,6 +653,8 @@ function App() {
|
|
|
675
653
|
// Oto-hafıza: eşik geçildiyse arka planda hafızayı güncelle
|
|
676
654
|
if (shouldExtract(historyRef.current))
|
|
677
655
|
triggerMemory(historyRef.current, config);
|
|
656
|
+
// Observability: bu turun CLI span'larını (tool/skill/agent) gateway'e yolla — best-effort.
|
|
657
|
+
flushTelemetry(config.baseUrl, config.apiKey);
|
|
678
658
|
}
|
|
679
659
|
async function onSubmit(value) {
|
|
680
660
|
let v = value.trim();
|
|
@@ -852,33 +832,12 @@ function App() {
|
|
|
852
832
|
React.createElement(Box, { flexGrow: 1 }),
|
|
853
833
|
React.createElement(StatusLine, { model: config.model, ctxTokens: 0 })));
|
|
854
834
|
}
|
|
855
|
-
return (React.createElement(Box, { flexDirection: "column",
|
|
856
|
-
React.createElement(
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
const maxScroll = Math.max(0, all.length - avail);
|
|
862
|
-
const off = Math.min(scroll, maxScroll); // alttan kaç satır yukarı
|
|
863
|
-
const startLine = Math.max(0, all.length - avail - off);
|
|
864
|
-
const view = all.slice(startLine, startLine + avail);
|
|
865
|
-
return (React.createElement(React.Fragment, null,
|
|
866
|
-
startLine > 0 ? React.createElement(Text, { color: theme.greyDim },
|
|
867
|
-
" \u2191 ",
|
|
868
|
-
startLine,
|
|
869
|
-
" sat\u0131r \u00B7 PageUp") : null,
|
|
870
|
-
view.map((segs, i) => (React.createElement(Text, { key: i }, segs.length === 0
|
|
871
|
-
? ' '
|
|
872
|
-
: segs.map((s, j) => (React.createElement(Text, { key: j, color: s.dim ? theme.greyDim : s.color, bold: s.bold }, linkify(s.text))))))),
|
|
873
|
-
off > 0 ? React.createElement(Text, { color: theme.greyDim },
|
|
874
|
-
" \u2193 ",
|
|
875
|
-
off,
|
|
876
|
-
" sat\u0131r \u00B7 PageDown / Son") : null,
|
|
877
|
-
streaming && off === 0 ? (React.createElement(Box, { flexDirection: "row" },
|
|
878
|
-
React.createElement(Text, { color: theme.redBright, bold: true }, "\u23FA "),
|
|
879
|
-
React.createElement(Box, { flexDirection: "column" },
|
|
880
|
-
React.createElement(Text, { color: theme.white }, streaming)))) : null));
|
|
881
|
-
})()),
|
|
835
|
+
return (React.createElement(Box, { flexDirection: "column", width: cols },
|
|
836
|
+
React.createElement(Static, { items: items }, (item, i) => React.createElement(RenderItem, { key: i, item: item })),
|
|
837
|
+
streaming ? (React.createElement(Box, { marginTop: 1, flexDirection: "row" },
|
|
838
|
+
React.createElement(Text, { color: theme.redBright, bold: true }, "\u23FA "),
|
|
839
|
+
React.createElement(Box, { flexDirection: "column", flexGrow: 1 },
|
|
840
|
+
React.createElement(MarkdownDisplay, { text: streaming })))) : null,
|
|
882
841
|
perm ? (React.createElement(Box, { flexDirection: "column", borderStyle: "round", borderColor: theme.red, paddingX: 1, marginTop: 1 },
|
|
883
842
|
React.createElement(Text, { color: theme.redBright, bold: true }, t('perm.title', perm.label)),
|
|
884
843
|
permMode === 'feedback' ? (React.createElement(React.Fragment, null,
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// Bağımlılıksız terminal sözdizimi vurgusu (lowlight/highlight.js yerine hafif tokenizer).
|
|
2
|
+
// Kod bloklarını dile göre token'lara böler; her token'a tema rengi atar. Asla patlamaz —
|
|
3
|
+
// tanımadığı dilde ortak kurallarla (string/sayı/yorum/anahtar kelime) renklendirir.
|
|
4
|
+
import { theme } from './theme.js';
|
|
5
|
+
// Dil bazlı anahtar kelime setleri (ortak + spesifik).
|
|
6
|
+
const KW = {
|
|
7
|
+
js: ['const', 'let', 'var', 'function', 'return', 'if', 'else', 'for', 'while', 'do', 'switch', 'case', 'break', 'continue', 'new', 'class', 'extends', 'super', 'this', 'typeof', 'instanceof', 'in', 'of', 'await', 'async', 'yield', 'try', 'catch', 'finally', 'throw', 'import', 'export', 'from', 'default', 'delete', 'void', 'null', 'undefined', 'true', 'false'],
|
|
8
|
+
ts: ['interface', 'type', 'enum', 'implements', 'public', 'private', 'protected', 'readonly', 'abstract', 'namespace', 'declare', 'as', 'keyof', 'infer', 'satisfies'],
|
|
9
|
+
py: ['def', 'class', 'return', 'if', 'elif', 'else', 'for', 'while', 'break', 'continue', 'import', 'from', 'as', 'with', 'try', 'except', 'finally', 'raise', 'lambda', 'yield', 'global', 'nonlocal', 'pass', 'assert', 'del', 'in', 'is', 'not', 'and', 'or', 'None', 'True', 'False', 'self', 'async', 'await'],
|
|
10
|
+
bash: ['if', 'then', 'else', 'elif', 'fi', 'for', 'while', 'do', 'done', 'case', 'esac', 'function', 'in', 'return', 'export', 'local', 'echo', 'cd', 'source', 'set', 'unset'],
|
|
11
|
+
go: ['func', 'package', 'import', 'var', 'const', 'type', 'struct', 'interface', 'map', 'chan', 'go', 'defer', 'return', 'if', 'else', 'for', 'range', 'switch', 'case', 'select', 'break', 'continue', 'nil', 'true', 'false'],
|
|
12
|
+
rust: ['fn', 'let', 'mut', 'const', 'struct', 'enum', 'impl', 'trait', 'pub', 'use', 'mod', 'match', 'if', 'else', 'for', 'while', 'loop', 'return', 'self', 'Self', 'where', 'async', 'await', 'move', 'ref', 'true', 'false'],
|
|
13
|
+
java: ['public', 'private', 'protected', 'class', 'interface', 'extends', 'implements', 'static', 'final', 'void', 'new', 'return', 'if', 'else', 'for', 'while', 'switch', 'case', 'break', 'continue', 'try', 'catch', 'finally', 'throw', 'throws', 'import', 'package', 'this', 'super', 'null', 'true', 'false'],
|
|
14
|
+
css: ['important', 'inherit', 'initial', 'auto', 'none', 'flex', 'grid', 'block', 'inline'],
|
|
15
|
+
};
|
|
16
|
+
function langKeywords(lang) {
|
|
17
|
+
const l = (lang || '').toLowerCase();
|
|
18
|
+
const base = [];
|
|
19
|
+
if (l === 'ts' || l === 'tsx' || l === 'typescript')
|
|
20
|
+
base.push(...KW.js, ...KW.ts);
|
|
21
|
+
else if (l === 'js' || l === 'jsx' || l === 'javascript' || l === 'json' || l === 'node')
|
|
22
|
+
base.push(...KW.js);
|
|
23
|
+
else if (l === 'py' || l === 'python')
|
|
24
|
+
base.push(...KW.py);
|
|
25
|
+
else if (l === 'sh' || l === 'bash' || l === 'shell' || l === 'zsh')
|
|
26
|
+
base.push(...KW.bash);
|
|
27
|
+
else if (l === 'go' || l === 'golang')
|
|
28
|
+
base.push(...KW.go);
|
|
29
|
+
else if (l === 'rs' || l === 'rust')
|
|
30
|
+
base.push(...KW.rust);
|
|
31
|
+
else if (l === 'java')
|
|
32
|
+
base.push(...KW.java);
|
|
33
|
+
else if (l === 'css' || l === 'scss')
|
|
34
|
+
base.push(...KW.css);
|
|
35
|
+
else
|
|
36
|
+
base.push(...KW.js, ...KW.py); // bilinmeyen dil → en yaygın iki set
|
|
37
|
+
return new Set(base);
|
|
38
|
+
}
|
|
39
|
+
const lineComment = (lang) => {
|
|
40
|
+
const l = (lang || '').toLowerCase();
|
|
41
|
+
if (['py', 'python', 'sh', 'bash', 'shell', 'zsh', 'yaml', 'yml', 'rb', 'ruby', 'toml'].includes(l))
|
|
42
|
+
return '#';
|
|
43
|
+
return '//';
|
|
44
|
+
};
|
|
45
|
+
// Bir satırı token'lara böl. Basit ama sağlam bir durum makinesi.
|
|
46
|
+
function tokenizeLine(line, kw, lc) {
|
|
47
|
+
const toks = [];
|
|
48
|
+
let i = 0;
|
|
49
|
+
const n = line.length;
|
|
50
|
+
const push = (text, color) => { if (text)
|
|
51
|
+
toks.push({ text, color }); };
|
|
52
|
+
while (i < n) {
|
|
53
|
+
const ch = line[i];
|
|
54
|
+
// satır yorumu (// veya #)
|
|
55
|
+
if (line.startsWith(lc, i)) {
|
|
56
|
+
push(line.slice(i), theme.synComment);
|
|
57
|
+
break;
|
|
58
|
+
}
|
|
59
|
+
// dizgi: " ' `
|
|
60
|
+
if (ch === '"' || ch === "'" || ch === '`') {
|
|
61
|
+
let j = i + 1;
|
|
62
|
+
while (j < n && line[j] !== ch) {
|
|
63
|
+
if (line[j] === '\\')
|
|
64
|
+
j++;
|
|
65
|
+
j++;
|
|
66
|
+
}
|
|
67
|
+
push(line.slice(i, Math.min(j + 1, n)), theme.synString);
|
|
68
|
+
i = j + 1;
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
// sayı
|
|
72
|
+
if (/[0-9]/.test(ch) && (i === 0 || !/[A-Za-z_]/.test(line[i - 1]))) {
|
|
73
|
+
let j = i;
|
|
74
|
+
while (j < n && /[0-9a-fA-FxX._]/.test(line[j]))
|
|
75
|
+
j++;
|
|
76
|
+
push(line.slice(i, j), theme.synNumber);
|
|
77
|
+
i = j;
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
// tanımlayıcı / anahtar kelime
|
|
81
|
+
if (/[A-Za-z_$@]/.test(ch)) {
|
|
82
|
+
let j = i;
|
|
83
|
+
while (j < n && /[A-Za-z0-9_$]/.test(line[j]))
|
|
84
|
+
j++;
|
|
85
|
+
const word = line.slice(i, j);
|
|
86
|
+
const after = line[j];
|
|
87
|
+
if (kw.has(word))
|
|
88
|
+
push(word, theme.synKeyword);
|
|
89
|
+
else if (after === '(')
|
|
90
|
+
push(word, theme.synFunc); // fonksiyon çağrısı
|
|
91
|
+
else if (/^[A-Z]/.test(word))
|
|
92
|
+
push(word, theme.synType); // Tip/Sınıf
|
|
93
|
+
else
|
|
94
|
+
push(word); // düz
|
|
95
|
+
i = j;
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
// tek karakter (operatör/noktalama) — düz
|
|
99
|
+
push(ch);
|
|
100
|
+
i++;
|
|
101
|
+
}
|
|
102
|
+
return toks;
|
|
103
|
+
}
|
|
104
|
+
/** Kodu satır-satır token dizilerine çevirir. Her satır Tok[]. */
|
|
105
|
+
export function highlight(code, lang = '') {
|
|
106
|
+
try {
|
|
107
|
+
const kw = langKeywords(lang);
|
|
108
|
+
const lc = lineComment(lang);
|
|
109
|
+
let blockComment = false; // /* ... */ için
|
|
110
|
+
return code.split('\n').map((line) => {
|
|
111
|
+
// çok-satırlı /* */ yorum bloğu (basit destek)
|
|
112
|
+
if (blockComment) {
|
|
113
|
+
const end = line.indexOf('*/');
|
|
114
|
+
if (end === -1)
|
|
115
|
+
return [{ text: line, color: theme.synComment }];
|
|
116
|
+
blockComment = false;
|
|
117
|
+
const rest = tokenizeLine(line.slice(end + 2), kw, lc);
|
|
118
|
+
return [{ text: line.slice(0, end + 2), color: theme.synComment }, ...rest];
|
|
119
|
+
}
|
|
120
|
+
const start = line.indexOf('/*');
|
|
121
|
+
if (start !== -1 && line.indexOf('*/', start) === -1) {
|
|
122
|
+
blockComment = true;
|
|
123
|
+
const pre = tokenizeLine(line.slice(0, start), kw, lc);
|
|
124
|
+
return [...pre, { text: line.slice(start), color: theme.synComment }];
|
|
125
|
+
}
|
|
126
|
+
return tokenizeLine(line, kw, lc);
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
return code.split('\n').map((l) => [{ text: l, color: theme.synString }]);
|
|
131
|
+
}
|
|
132
|
+
}
|
package/dist/markdown.js
CHANGED
|
@@ -4,6 +4,18 @@ import React from 'react';
|
|
|
4
4
|
import { Text, Box } from 'ink';
|
|
5
5
|
import stringWidth from 'string-width';
|
|
6
6
|
import { theme } from './theme.js';
|
|
7
|
+
import { highlight } from './highlight.js';
|
|
8
|
+
// Kod bloğunu sözdizimi-vurgulu render eder (sol kenarda ince kırmızı çubuk + dil etiketi).
|
|
9
|
+
function CodeBlock({ code, lang }) {
|
|
10
|
+
const hl = highlight(code.join('\n'), lang);
|
|
11
|
+
return (React.createElement(Box, { flexDirection: "column", marginY: 1 },
|
|
12
|
+
lang ? React.createElement(Text, { color: theme.greyDim },
|
|
13
|
+
' ',
|
|
14
|
+
lang) : null,
|
|
15
|
+
hl.map((toks, i) => (React.createElement(Box, { key: i },
|
|
16
|
+
React.createElement(Text, { color: theme.greyDim }, "\u2502 "),
|
|
17
|
+
React.createElement(Text, null, toks.length ? toks.map((tk, j) => React.createElement(Text, { key: j, color: tk.color }, tk.text)) : ' '))))));
|
|
18
|
+
}
|
|
7
19
|
// ── Inline markdown: **bold** *italik* ~~strike~~ `code` [text](url) <u>u</u> url ──
|
|
8
20
|
const INLINE_RE = /(\*\*.*?\*\*|\*.*?\*|_.*?_|~~.*?~~|\[.*?\]\(.*?\)|`+.+?`+|<u>.*?<\/u>|https?:\/\/\S+)/g;
|
|
9
21
|
export function RenderInline({ text }) {
|
|
@@ -122,7 +134,7 @@ export function MarkdownDisplay({ text, width }) {
|
|
|
122
134
|
const blocks = [];
|
|
123
135
|
let key = 0;
|
|
124
136
|
const push = (n) => blocks.push(React.createElement(React.Fragment, { key: key++ }, n));
|
|
125
|
-
let inCode = false, codeFence = '', codeLines = [];
|
|
137
|
+
let inCode = false, codeFence = '', codeLang = '', codeLines = [];
|
|
126
138
|
let inTable = false, tHeaders = [], tRows = [];
|
|
127
139
|
const flushTable = () => { if (tHeaders.length)
|
|
128
140
|
push(React.createElement(Table, { headers: tHeaders, rows: tRows, width: W })); inTable = false; tHeaders = []; tRows = []; };
|
|
@@ -137,9 +149,10 @@ export function MarkdownDisplay({ text, width }) {
|
|
|
137
149
|
if (inCode) {
|
|
138
150
|
const fm = line.match(fenceRe);
|
|
139
151
|
if (fm && fm[1][0] === codeFence[0] && fm[1].length >= codeFence.length) {
|
|
140
|
-
push(React.createElement(
|
|
152
|
+
push(React.createElement(CodeBlock, { code: codeLines, lang: codeLang }));
|
|
141
153
|
inCode = false;
|
|
142
154
|
codeFence = '';
|
|
155
|
+
codeLang = '';
|
|
143
156
|
codeLines = [];
|
|
144
157
|
}
|
|
145
158
|
else
|
|
@@ -153,6 +166,7 @@ export function MarkdownDisplay({ text, width }) {
|
|
|
153
166
|
flushTable();
|
|
154
167
|
inCode = true;
|
|
155
168
|
codeFence = fm[1];
|
|
169
|
+
codeLang = (fm[2] || '').trim();
|
|
156
170
|
return;
|
|
157
171
|
}
|
|
158
172
|
if (rm && !inTable) {
|
|
@@ -214,7 +228,7 @@ export function MarkdownDisplay({ text, width }) {
|
|
|
214
228
|
React.createElement(RenderInline, { text: line })));
|
|
215
229
|
});
|
|
216
230
|
if (inCode)
|
|
217
|
-
push(React.createElement(
|
|
231
|
+
push(React.createElement(CodeBlock, { code: codeLines, lang: codeLang }));
|
|
218
232
|
if (inTable)
|
|
219
233
|
flushTable();
|
|
220
234
|
return React.createElement(Box, { flexDirection: "column" }, blocks);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Observability — istemci-tarafı dağıtık tracing. CLI kendi span'larını (tool/skill/agent/memory)
|
|
2
|
+
// gateway'e POST /v1/telemetry ile yollar; gateway kendi span'larını AYNI trace_id ile yazar →
|
|
3
|
+
// admin panelinde birleşik waterfall. trace_id ayrıca X-WC-Trace header'ı ile her isteğe gider.
|
|
4
|
+
let currentTrace = '';
|
|
5
|
+
let buffer = [];
|
|
6
|
+
const sessionId = 's-' + Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
|
|
7
|
+
const rid = () => Math.random().toString(36).slice(2, 8);
|
|
8
|
+
/** Yeni tur başında çağrılır — yeni trace_id üretir, tamponu temizler. */
|
|
9
|
+
export function newTrace() {
|
|
10
|
+
currentTrace = 't-' + Date.now().toString(36) + rid();
|
|
11
|
+
buffer = [];
|
|
12
|
+
return currentTrace;
|
|
13
|
+
}
|
|
14
|
+
export function getTrace() { return currentTrace; }
|
|
15
|
+
export function getSession() { return sessionId; }
|
|
16
|
+
/** Bir span ekle (tampona). type: tool_called/tool_failed/skill_selected/agent_spawned/memory_summary_created… */
|
|
17
|
+
export function emit(type, attrs = {}, duration_ms = 0, status = 'ok') {
|
|
18
|
+
if (!currentTrace)
|
|
19
|
+
return;
|
|
20
|
+
buffer.push({ type, span_id: rid(), duration_ms: Math.round(duration_ms), status, ts: Date.now() / 1000, attrs });
|
|
21
|
+
}
|
|
22
|
+
/** Tampondaki span'ları gateway'e gönder (tur sonunda). Hata sessizce yutulur. */
|
|
23
|
+
export async function flushTelemetry(baseUrl, apiKey) {
|
|
24
|
+
if (!currentTrace || buffer.length === 0)
|
|
25
|
+
return;
|
|
26
|
+
const events = buffer;
|
|
27
|
+
buffer = [];
|
|
28
|
+
try {
|
|
29
|
+
await fetch(`${baseUrl}/telemetry`, {
|
|
30
|
+
method: 'POST',
|
|
31
|
+
headers: { 'Content-Type': 'application/json', ...(apiKey ? { Authorization: `Bearer ${apiKey}` } : {}) },
|
|
32
|
+
body: JSON.stringify({ trace_id: currentTrace, session_id: sessionId, events }),
|
|
33
|
+
signal: AbortSignal.timeout(5000),
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
catch { /* telemetri best-effort — kullanıcıyı etkilemez */ }
|
|
37
|
+
}
|
package/dist/theme.js
CHANGED
|
@@ -7,5 +7,13 @@ export const theme = {
|
|
|
7
7
|
greyDim: '#666666',
|
|
8
8
|
green: '#4ade80',
|
|
9
9
|
errorRed: '#ff6b6b',
|
|
10
|
+
// ── Sözdizimi vurgusu (kod blokları) ──
|
|
11
|
+
synKeyword: '#ff5c5c', // anahtar kelimeler (if, function, def…) — marka kırmızısı
|
|
12
|
+
synString: '#4ade80', // dizgiler "…" '…' `…`
|
|
13
|
+
synNumber: '#f0b429', // sayılar
|
|
14
|
+
synComment: '#666666', // yorumlar
|
|
15
|
+
synFunc: '#4fc3f7', // fonksiyon/metot adları
|
|
16
|
+
synType: '#a78bfa', // tip/sınıf adları, sabitler
|
|
17
|
+
synProp: '#e0e0e0', // özellik/anahtar adları
|
|
10
18
|
};
|
|
11
|
-
export const VERSION = '1.0.
|
|
19
|
+
export const VERSION = '1.0.21';
|
package/dist/tools.js
CHANGED
|
@@ -10,6 +10,7 @@ import { loadConfig } from './api.js';
|
|
|
10
10
|
import { runAgentLoop } from './agent.js';
|
|
11
11
|
import { resolveSubagent, subagentTypesHint } from './subagents.js';
|
|
12
12
|
import { saveMemoryFact } from './memory.js';
|
|
13
|
+
import { emit as emitSpan } from './telemetry.js';
|
|
13
14
|
import { tasks } from './tasks.js';
|
|
14
15
|
import { getMcpToolSchemas, callMcpTool } from './mcp.js';
|
|
15
16
|
import { getSkills, getSkill, buildSkillPrompt } from './skills.js';
|
|
@@ -707,7 +708,9 @@ export async function executeToolCalls(calls, hooks) {
|
|
|
707
708
|
while (p < b.items.length) {
|
|
708
709
|
const { c, i } = b.items[p++];
|
|
709
710
|
hooks?.onStart?.(c, i);
|
|
711
|
+
const _t = Date.now();
|
|
710
712
|
results[i] = await execOne(c, hooks);
|
|
713
|
+
emitSpan(results[i].ok ? 'tool_called' : 'tool_failed', { tool: c.name }, Date.now() - _t, results[i].ok ? 'ok' : 'error');
|
|
711
714
|
hooks?.onResult?.(c, i, results[i]);
|
|
712
715
|
}
|
|
713
716
|
};
|
|
@@ -716,7 +719,9 @@ export async function executeToolCalls(calls, hooks) {
|
|
|
716
719
|
else {
|
|
717
720
|
for (const { c, i } of b.items) {
|
|
718
721
|
hooks?.onStart?.(c, i);
|
|
722
|
+
const _t = Date.now();
|
|
719
723
|
results[i] = await execOne(c, hooks);
|
|
724
|
+
emitSpan(results[i].ok ? 'tool_called' : 'tool_failed', { tool: c.name }, Date.now() - _t, results[i].ok ? 'ok' : 'error');
|
|
720
725
|
hooks?.onResult?.(c, i, results[i]);
|
|
721
726
|
}
|
|
722
727
|
}
|