@qduc/term2 0.1.4 → 0.1.5
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/app.d.ts.map +1 -1
- package/dist/app.js +2 -2
- package/dist/app.js.map +1 -1
- package/dist/components/BottomArea.d.ts +2 -0
- package/dist/components/BottomArea.d.ts.map +1 -1
- package/dist/components/BottomArea.js +2 -2
- package/dist/components/BottomArea.js.map +1 -1
- package/dist/components/ModelSelectionMenu.d.ts.map +1 -1
- package/dist/components/ModelSelectionMenu.js +24 -15
- package/dist/components/ModelSelectionMenu.js.map +1 -1
- package/dist/components/StatusBar.d.ts +2 -0
- package/dist/components/StatusBar.d.ts.map +1 -1
- package/dist/components/StatusBar.js +44 -39
- package/dist/components/StatusBar.js.map +1 -1
- package/dist/components/StatusBar.test.d.ts +2 -0
- package/dist/components/StatusBar.test.d.ts.map +1 -0
- package/dist/components/StatusBar.test.js +19 -0
- package/dist/components/StatusBar.test.js.map +1 -0
- package/dist/hooks/use-conversation.d.ts +2 -0
- package/dist/hooks/use-conversation.d.ts.map +1 -1
- package/dist/hooks/use-conversation.js +44 -3
- package/dist/hooks/use-conversation.js.map +1 -1
- package/dist/hooks/use-model-selection.d.ts.map +1 -1
- package/dist/hooks/use-model-selection.js +1 -25
- package/dist/hooks/use-model-selection.js.map +1 -1
- package/dist/lib/openai-agent-client.d.ts.map +1 -1
- package/dist/lib/openai-agent-client.js +12 -4
- package/dist/lib/openai-agent-client.js.map +1 -1
- package/dist/services/conversation-events.d.ts +3 -0
- package/dist/services/conversation-events.d.ts.map +1 -1
- package/dist/services/conversation-session.d.ts +2 -0
- package/dist/services/conversation-session.d.ts.map +1 -1
- package/dist/services/conversation-session.js +151 -28
- package/dist/services/conversation-session.js.map +1 -1
- package/dist/services/conversation-session.usage.test.d.ts +2 -0
- package/dist/services/conversation-session.usage.test.d.ts.map +1 -0
- package/dist/services/conversation-session.usage.test.js +59 -0
- package/dist/services/conversation-session.usage.test.js.map +1 -0
- package/dist/tools/find-files.d.ts +1 -0
- package/dist/tools/find-files.d.ts.map +1 -1
- package/dist/tools/find-files.js +92 -8
- package/dist/tools/find-files.js.map +1 -1
- package/dist/tools/find-files.test.js +45 -0
- package/dist/tools/find-files.test.js.map +1 -1
- package/dist/tools/web-fetch.d.ts +4 -4
- package/dist/tools/web-fetch.d.ts.map +1 -1
- package/dist/tools/web-fetch.js +30 -243
- package/dist/tools/web-fetch.js.map +1 -1
- package/dist/utils/token-usage.d.ts +16 -0
- package/dist/utils/token-usage.d.ts.map +1 -0
- package/dist/utils/token-usage.js +110 -0
- package/dist/utils/token-usage.js.map +1 -0
- package/dist/utils/token-usage.test.d.ts +2 -0
- package/dist/utils/token-usage.test.d.ts.map +1 -0
- package/dist/utils/token-usage.test.js +38 -0
- package/dist/utils/token-usage.test.js.map +1 -0
- package/dist/utils/trim-tool-output.d.ts +2 -0
- package/dist/utils/trim-tool-output.d.ts.map +1 -0
- package/dist/utils/trim-tool-output.js +52 -0
- package/dist/utils/trim-tool-output.js.map +1 -0
- package/package.json +2 -1
- package/{README.md → readme.md} +22 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token usage normalization and extraction utilities.
|
|
3
|
+
* Ported from backend/src/lib/utils/usage.js
|
|
4
|
+
*/
|
|
5
|
+
export interface NormalizedUsage {
|
|
6
|
+
prompt_tokens?: number;
|
|
7
|
+
completion_tokens?: number;
|
|
8
|
+
total_tokens?: number;
|
|
9
|
+
reasoning_tokens?: number;
|
|
10
|
+
prompt_ms?: number;
|
|
11
|
+
completion_ms?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare function normalizeUsage(usage: any): NormalizedUsage | undefined;
|
|
14
|
+
export declare function extractUsage(payload: any): NormalizedUsage | undefined;
|
|
15
|
+
export declare function formatFooterUsage(usage: NormalizedUsage | null | undefined): string;
|
|
16
|
+
//# sourceMappingURL=token-usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-usage.d.ts","sourceRoot":"","sources":["../../source/utils/token-usage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,eAAe;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CAC1B;AA6BD,wBAAgB,cAAc,CAAC,KAAK,EAAE,GAAG,GAAG,eAAe,GAAG,SAAS,CAiFtE;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,GAAG,GAAG,eAAe,GAAG,SAAS,CAgCtE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAgBnF"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token usage normalization and extraction utilities.
|
|
3
|
+
* Ported from backend/src/lib/utils/usage.js
|
|
4
|
+
*/
|
|
5
|
+
function toNumber(value) {
|
|
6
|
+
if (value == null)
|
|
7
|
+
return undefined;
|
|
8
|
+
const asNumber = Number(value);
|
|
9
|
+
if (!Number.isFinite(asNumber))
|
|
10
|
+
return undefined;
|
|
11
|
+
return asNumber;
|
|
12
|
+
}
|
|
13
|
+
function coalesceNumber(...values) {
|
|
14
|
+
for (const value of values) {
|
|
15
|
+
const num = toNumber(value);
|
|
16
|
+
if (num != null)
|
|
17
|
+
return num;
|
|
18
|
+
}
|
|
19
|
+
return undefined;
|
|
20
|
+
}
|
|
21
|
+
function sumNumbers(...values) {
|
|
22
|
+
let total = 0;
|
|
23
|
+
let found = false;
|
|
24
|
+
for (const value of values) {
|
|
25
|
+
const num = toNumber(value);
|
|
26
|
+
if (num == null)
|
|
27
|
+
continue;
|
|
28
|
+
total += num;
|
|
29
|
+
found = true;
|
|
30
|
+
}
|
|
31
|
+
return found ? total : undefined;
|
|
32
|
+
}
|
|
33
|
+
export function normalizeUsage(usage) {
|
|
34
|
+
if (!usage || typeof usage !== 'object')
|
|
35
|
+
return undefined;
|
|
36
|
+
const promptTokens = coalesceNumber(usage.prompt_tokens, usage.input_tokens, usage.input_token_count, usage.prompt_token_count, usage.promptTokenCount, usage.inputTokenCount, usage.inputTokens, // Agents SDK
|
|
37
|
+
usage.prompt_n !== undefined && usage.prompt_n != null
|
|
38
|
+
? (toNumber(usage.cache_n) || 0) + toNumber(usage.prompt_n)
|
|
39
|
+
: undefined);
|
|
40
|
+
const completionTokens = coalesceNumber(usage.completion_tokens, usage.output_tokens, usage.output_token_count, usage.completion_token_count, usage.candidatesTokenCount, usage.outputTokenCount, usage.outputTokens, // Agents SDK
|
|
41
|
+
usage.predicted_n);
|
|
42
|
+
const cacheCreationTokens = coalesceNumber(usage.cache_creation_input_tokens, usage.cacheCreationInputTokens);
|
|
43
|
+
const cacheReadTokens = coalesceNumber(usage.cache_read_input_tokens, usage.cacheReadInputTokens);
|
|
44
|
+
const totalTokens = coalesceNumber(usage.total_tokens, usage.total_token_count, usage.totalTokenCount, usage.totalTokens) ??
|
|
45
|
+
sumNumbers(promptTokens, completionTokens, cacheCreationTokens, cacheReadTokens);
|
|
46
|
+
const reasoningTokens = coalesceNumber(usage.reasoning_tokens, usage.reasoning_token_count, usage?.completion_tokens_details?.reasoning_tokens, usage?.output_tokens_details?.reasoning_tokens, usage.thoughtsTokenCount, usage.thoughts_token_count);
|
|
47
|
+
const promptMs = coalesceNumber(usage.prompt_ms, usage.promptMs);
|
|
48
|
+
const completionMs = coalesceNumber(usage.completion_ms, usage.completionMs, usage.predicted_ms, usage.predictedMs, usage.output_ms, usage.outputMs);
|
|
49
|
+
const mapped = {};
|
|
50
|
+
if (promptTokens != null)
|
|
51
|
+
mapped.prompt_tokens = promptTokens;
|
|
52
|
+
if (completionTokens != null)
|
|
53
|
+
mapped.completion_tokens = completionTokens;
|
|
54
|
+
if (totalTokens != null)
|
|
55
|
+
mapped.total_tokens = totalTokens;
|
|
56
|
+
if (reasoningTokens != null)
|
|
57
|
+
mapped.reasoning_tokens = reasoningTokens;
|
|
58
|
+
if (promptMs != null)
|
|
59
|
+
mapped.prompt_ms = promptMs;
|
|
60
|
+
if (completionMs != null)
|
|
61
|
+
mapped.completion_ms = completionMs;
|
|
62
|
+
return Object.keys(mapped).length > 0 ? mapped : undefined;
|
|
63
|
+
}
|
|
64
|
+
export function extractUsage(payload) {
|
|
65
|
+
if (!payload || typeof payload !== 'object')
|
|
66
|
+
return undefined;
|
|
67
|
+
const results = [];
|
|
68
|
+
const direct = normalizeUsage(payload.usage);
|
|
69
|
+
if (direct)
|
|
70
|
+
results.push(direct);
|
|
71
|
+
const metadata = normalizeUsage(payload.usageMetadata || payload.usage_metadata);
|
|
72
|
+
if (metadata)
|
|
73
|
+
results.push(metadata);
|
|
74
|
+
const nested = normalizeUsage(payload.response?.usage);
|
|
75
|
+
if (nested)
|
|
76
|
+
results.push(nested);
|
|
77
|
+
const timings = normalizeUsage(payload.timings);
|
|
78
|
+
if (timings)
|
|
79
|
+
results.push(timings);
|
|
80
|
+
// Fallback search for any usage field in the payload itself
|
|
81
|
+
const self = normalizeUsage(payload);
|
|
82
|
+
if (self)
|
|
83
|
+
results.push(self);
|
|
84
|
+
if (results.length === 0)
|
|
85
|
+
return undefined;
|
|
86
|
+
const merged = {};
|
|
87
|
+
for (let i = results.length - 1; i >= 0; i--) {
|
|
88
|
+
Object.assign(merged, results[i]);
|
|
89
|
+
}
|
|
90
|
+
// Re-normalize to fix up computed total_tokens if components were merged from different sources
|
|
91
|
+
return normalizeUsage(merged);
|
|
92
|
+
}
|
|
93
|
+
export function formatFooterUsage(usage) {
|
|
94
|
+
if (!usage)
|
|
95
|
+
return '';
|
|
96
|
+
const parts = [];
|
|
97
|
+
if (usage.prompt_tokens != null) {
|
|
98
|
+
parts.push(`${usage.prompt_tokens.toLocaleString()} in`);
|
|
99
|
+
}
|
|
100
|
+
if (usage.completion_tokens != null) {
|
|
101
|
+
parts.push(`${usage.completion_tokens.toLocaleString()} out`);
|
|
102
|
+
}
|
|
103
|
+
if (usage.total_tokens != null) {
|
|
104
|
+
parts.push(`${usage.total_tokens.toLocaleString()} total`);
|
|
105
|
+
}
|
|
106
|
+
if (parts.length === 0)
|
|
107
|
+
return '';
|
|
108
|
+
return `Tok: ${parts.join(' / ')}`;
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=token-usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-usage.js","sourceRoot":"","sources":["../../source/utils/token-usage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-usage.test.d.ts","sourceRoot":"","sources":["../../source/utils/token-usage.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { normalizeUsage, extractUsage, formatFooterUsage } from './token-usage.js';
|
|
3
|
+
test('normalizeUsage handles multiple formats', t => {
|
|
4
|
+
// OpenAI style
|
|
5
|
+
t.deepEqual(normalizeUsage({ prompt_tokens: 10, completion_tokens: 20, total_tokens: 30 }), {
|
|
6
|
+
prompt_tokens: 10,
|
|
7
|
+
completion_tokens: 20,
|
|
8
|
+
total_tokens: 30
|
|
9
|
+
});
|
|
10
|
+
// Agents SDK style
|
|
11
|
+
t.deepEqual(normalizeUsage({ inputTokens: 5, outputTokens: 15, totalTokens: 20 }), {
|
|
12
|
+
prompt_tokens: 5,
|
|
13
|
+
completion_tokens: 15,
|
|
14
|
+
total_tokens: 20
|
|
15
|
+
});
|
|
16
|
+
// Mixed/partial
|
|
17
|
+
t.deepEqual(normalizeUsage({ input_tokens: 100 }), {
|
|
18
|
+
prompt_tokens: 100,
|
|
19
|
+
total_tokens: 100
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
test('extractUsage finds usage in nested locations', t => {
|
|
23
|
+
const payload = {
|
|
24
|
+
usage: { prompt_tokens: 1, total_tokens: 3 },
|
|
25
|
+
response: { usage: { completion_tokens: 2, total_tokens: 3 } }
|
|
26
|
+
};
|
|
27
|
+
t.deepEqual(extractUsage(payload), {
|
|
28
|
+
prompt_tokens: 1,
|
|
29
|
+
completion_tokens: 2,
|
|
30
|
+
total_tokens: 3
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
test('formatFooterUsage returns formatted string', t => {
|
|
34
|
+
t.is(formatFooterUsage({ prompt_tokens: 1200, completion_tokens: 350, total_tokens: 1550 }), 'Tok: 1,200 in / 350 out / 1,550 total');
|
|
35
|
+
t.is(formatFooterUsage({ total_tokens: 100 }), 'Tok: 100 total');
|
|
36
|
+
t.is(formatFooterUsage(null), '');
|
|
37
|
+
});
|
|
38
|
+
//# sourceMappingURL=token-usage.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-usage.test.js","sourceRoot":"","sources":["../../source/utils/token-usage.test.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,KAAK,CAAC;AACvB,OAAO,EAAC,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAC,MAAM,kBAAkB,CAAC;AAEjF,IAAI,CAAC,yCAAyC,EAAE,CAAC,CAAC,EAAE;IAChD,eAAe;IACf,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,EAAC,aAAa,EAAE,EAAE,EAAE,iBAAiB,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE,EAAC,CAAC,EAAE;QACtF,aAAa,EAAE,EAAE;QACjB,iBAAiB,EAAE,EAAE;QACrB,YAAY,EAAE,EAAE;KACnB,CAAC,CAAC;IAEH,mBAAmB;IACnB,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,EAAC,WAAW,EAAE,CAAC,EAAE,YAAY,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAC,CAAC,EAAE;QAC7E,aAAa,EAAE,CAAC;QAChB,iBAAiB,EAAE,EAAE;QACrB,YAAY,EAAE,EAAE;KACnB,CAAC,CAAC;IAEH,gBAAgB;IAChB,CAAC,CAAC,SAAS,CAAC,cAAc,CAAC,EAAC,YAAY,EAAE,GAAG,EAAC,CAAC,EAAE;QAC7C,aAAa,EAAE,GAAG;QAClB,YAAY,EAAE,GAAG;KACpB,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,8CAA8C,EAAE,CAAC,CAAC,EAAE;IACrD,MAAM,OAAO,GAAG;QACZ,KAAK,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE;QAC5C,QAAQ,EAAE,EAAE,KAAK,EAAE,EAAE,iBAAiB,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,EAAE;KACjE,CAAC;IACF,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE;QAC/B,aAAa,EAAE,CAAC;QAChB,iBAAiB,EAAE,CAAC;QACpB,YAAY,EAAE,CAAC;KAClB,CAAC,CAAC;AACP,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,4CAA4C,EAAE,CAAC,CAAC,EAAE;IACnD,CAAC,CAAC,EAAE,CAAC,iBAAiB,CAAC,EAAC,aAAa,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAC,CAAC,EAAE,uCAAuC,CAAC,CAAC;IACpI,CAAC,CAAC,EAAE,CAAC,iBAAiB,CAAC,EAAC,YAAY,EAAE,GAAG,EAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAC/D,CAAC,CAAC,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;AACtC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trim-tool-output.d.ts","sourceRoot":"","sources":["../../source/utils/trim-tool-output.ts"],"names":[],"mappings":"AAmDA,eAAO,MAAM,cAAc,GACvB,QAAQ,OAAO,EACf,WAAW,MAAM,EACjB,gBAAgB,MAAM,KACvB,MAgBF,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { trimOutput } from './output-trim.js';
|
|
2
|
+
const tryParseJson = (value) => {
|
|
3
|
+
if (!value.trim()) {
|
|
4
|
+
return null;
|
|
5
|
+
}
|
|
6
|
+
try {
|
|
7
|
+
return JSON.parse(value);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
const trimStringValue = (value, maxLines, maxCharacters) => {
|
|
14
|
+
if (!value) {
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
return trimOutput(value, maxLines, maxCharacters);
|
|
18
|
+
};
|
|
19
|
+
const trimJsonStrings = (value, maxLines, maxCharacters) => {
|
|
20
|
+
if (typeof value === 'string') {
|
|
21
|
+
return trimStringValue(value, maxLines, maxCharacters);
|
|
22
|
+
}
|
|
23
|
+
if (Array.isArray(value)) {
|
|
24
|
+
return value.map(entry => trimJsonStrings(entry, maxLines, maxCharacters));
|
|
25
|
+
}
|
|
26
|
+
if (value && typeof value === 'object') {
|
|
27
|
+
const record = value;
|
|
28
|
+
const next = {};
|
|
29
|
+
for (const [key, entry] of Object.entries(record)) {
|
|
30
|
+
next[key] = trimJsonStrings(entry, maxLines, maxCharacters);
|
|
31
|
+
}
|
|
32
|
+
return next;
|
|
33
|
+
}
|
|
34
|
+
return value;
|
|
35
|
+
};
|
|
36
|
+
export const trimToolOutput = (output, maxLines, maxCharacters) => {
|
|
37
|
+
if (typeof output !== 'string') {
|
|
38
|
+
return String(output ?? '');
|
|
39
|
+
}
|
|
40
|
+
const parsed = tryParseJson(output);
|
|
41
|
+
if (parsed !== null) {
|
|
42
|
+
const trimmed = trimJsonStrings(parsed, maxLines, maxCharacters);
|
|
43
|
+
try {
|
|
44
|
+
return JSON.stringify(trimmed);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
return trimStringValue(output, maxLines, maxCharacters);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return trimStringValue(output, maxLines, maxCharacters);
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=trim-tool-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"trim-tool-output.js","sourceRoot":"","sources":["../../source/utils/trim-tool-output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAE5C,MAAM,YAAY,GAAG,CAAC,KAAa,EAAkB,EAAE;IACnD,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CACpB,KAAa,EACb,QAAiB,EACjB,aAAsB,EAChB,EAAE;IACR,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,UAAU,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CACpB,KAAc,EACd,QAAiB,EACjB,aAAsB,EACf,EAAE;IACT,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;IAC3D,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CACrB,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,CAAC,CAClD,CAAC;IACN,CAAC;IAED,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,KAAgC,CAAC;QAChD,MAAM,IAAI,GAA4B,EAAE,CAAC;QACzC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,KAAK,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,cAAc,GAAG,CAC1B,MAAe,EACf,QAAiB,EACjB,aAAsB,EAChB,EAAE;IACR,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC7B,OAAO,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;QACjE,IAAI,CAAC;YACD,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;QAC5D,CAAC;IACL,CAAC;IAED,OAAO,eAAe,CAAC,MAAM,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;AAC5D,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qduc/term2",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.5",
|
|
4
4
|
"description": "A terminal-based AI assistant that can help you get things done on your computer",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "qduc",
|
|
@@ -48,6 +48,7 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@mozilla/readability": "^0.6.0",
|
|
50
50
|
"@openai/agents": "^0.4.3",
|
|
51
|
+
"@qduc/web-fetch": "^0.1.0",
|
|
51
52
|
"@types/ssh2": "^1.15.5",
|
|
52
53
|
"bash-parser": "^0.5.0",
|
|
53
54
|
"env-paths": "^3.0.0",
|
package/{README.md → readme.md}
RENAMED
|
@@ -5,13 +5,16 @@
|
|
|
5
5
|
|
|
6
6
|
A powerful terminal-based AI assistant that helps you get things done on your computer through natural conversation.
|
|
7
7
|
|
|
8
|
+
**Why term2?** Unlike proprietary alternatives, term2 is **open-source (MIT)**, works with **any AI provider** (OpenAI, OpenRouter, local self-hosted, etc.), requires **no subscription**, and uniquely supports **remote server management via SSH** — all while giving you full control over what commands execute on your system.
|
|
9
|
+
|
|
8
10
|
## Demo
|
|
9
11
|
|
|
10
12
|
https://github.com/user-attachments/assets/ac960d65-f7c8-453a-9440-91f6397ae842
|
|
11
13
|
|
|
12
14
|
## Features
|
|
13
15
|
|
|
14
|
-
- 🎭 **Three Operating Modes** - Default (full-power), Lite (fast & safe), and Mentor (
|
|
16
|
+
- 🎭 **Three Operating Modes** - Default (full-power), Lite (fast & safe), and Mentor (get help from a smarter model on complex problems)
|
|
17
|
+
- 🌍 **Open Source** - MIT licensed, hackable, auditable, community-driven
|
|
15
18
|
- 🤖 **Multi-Provider Support** - Works with OpenAI, OpenRouter, and OpenAI-compatible APIs
|
|
16
19
|
- 🔒 **Safe Execution** - Every command requires your explicit approval with diff preview
|
|
17
20
|
- 🛠️ **Advanced Tools** - Shell execution, file patching, search/replace, grep, find files, file reading, web search, and mentor consultation
|
|
@@ -24,6 +27,24 @@ https://github.com/user-attachments/assets/ac960d65-f7c8-453a-9440-91f6397ae842
|
|
|
24
27
|
- 🔄 **Retry Logic** - Automatic recovery from tool hallucinations and upstream errors
|
|
25
28
|
- 🌐 **SSH Mode** - Execute commands and edit files on remote servers over SSH
|
|
26
29
|
|
|
30
|
+
## Why term2 vs Alternatives?
|
|
31
|
+
|
|
32
|
+
| | **term2** | Claude Code | Warp |
|
|
33
|
+
|---|:---:|:---:|:---:|
|
|
34
|
+
| **Open Source** | ✅ MIT | ❌ Proprietary | ❌ Proprietary |
|
|
35
|
+
| **Cost** | Pay-per-use | $20-200/mo | Freemium |
|
|
36
|
+
| **AI Providers** | Any (OpenAI, OpenRouter, local, etc.) | Anthropic only | selected models only |
|
|
37
|
+
| **SSH Remote** | ✅ Native | ❌ No | ✅ Yes |
|
|
38
|
+
| **Mentor Mode** | ✅ Built-in | ❌ No | ❌ No |
|
|
39
|
+
| **Self-Hostable** | ✅ | ❌ | ❌ |
|
|
40
|
+
|
|
41
|
+
**term2 gives you:**
|
|
42
|
+
- **Freedom** — No vendor lock-in. Use any AI provider or model you prefer.
|
|
43
|
+
- **Transparency** — Open source means you can audit every line of code.
|
|
44
|
+
- **Cost Control** — Pay only for API usage, no monthly subscriptions.
|
|
45
|
+
- **Remote Work** — Troubleshoot and manage remote servers without installing anything on remote hosts.
|
|
46
|
+
- **Safety** — Every command requires explicit approval with diff previews before execution.
|
|
47
|
+
|
|
27
48
|
## Installation
|
|
28
49
|
|
|
29
50
|
**Requirements:**
|