codeep 2.15.0 → 2.17.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.
- package/README.md +41 -7
- package/dist/acp/serverHandlers.js +1 -1
- package/dist/acp/session.js +22 -1
- package/dist/config/index.js +20 -4
- package/dist/config/providers.d.ts +3 -2
- package/dist/config/providers.js +163 -69
- package/dist/renderer/App.d.ts +89 -0
- package/dist/renderer/App.js +637 -43
- package/dist/renderer/Screen.d.ts +1 -0
- package/dist/renderer/Screen.js +8 -3
- package/dist/renderer/commands/helpers.d.ts +189 -0
- package/dist/renderer/commands/helpers.js +345 -0
- package/dist/renderer/commands/registry.js +2 -1
- package/dist/renderer/commands.js +218 -267
- package/dist/renderer/components/AgentTimeline.d.ts +44 -0
- package/dist/renderer/components/AgentTimeline.js +157 -0
- package/dist/renderer/components/Autocomplete.d.ts +25 -0
- package/dist/renderer/components/Autocomplete.js +35 -0
- package/dist/renderer/components/Status.d.ts +2 -0
- package/dist/renderer/layout.d.ts +5 -1
- package/dist/renderer/layout.js +12 -0
- package/dist/renderer/main.js +110 -30
- package/dist/utils/agent.js +1 -1
- package/dist/utils/agents.d.ts +1 -1
- package/dist/utils/agents.js +1 -1
- package/dist/utils/checkpoints.d.ts +1 -1
- package/dist/utils/checkpoints.js +1 -1
- package/dist/utils/diffPreview.d.ts +31 -0
- package/dist/utils/diffPreview.js +102 -0
- package/dist/utils/git.d.ts +28 -0
- package/dist/utils/git.js +111 -1
- package/dist/utils/mentions.d.ts +195 -0
- package/dist/utils/mentions.js +672 -0
- package/dist/utils/resourceImpact.d.ts +25 -0
- package/dist/utils/resourceImpact.js +54 -0
- package/dist/utils/tokenTracker.js +52 -37
- package/dist/utils/webFetch.d.ts +101 -0
- package/dist/utils/webFetch.js +375 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Broad operational-impact estimate for hosted LLM inference.
|
|
3
|
+
*
|
|
4
|
+
* This is deliberately a range, not a meter reading:
|
|
5
|
+
* - 0.3–1.5 J/token covers published H100 inference benchmarks.
|
|
6
|
+
* - 0.27–1.08 L/kWh spans efficient direct cooling and a full-stack
|
|
7
|
+
* production estimate that also captures associated infrastructure.
|
|
8
|
+
*
|
|
9
|
+
* Model size, batching, context length, hardware, data-centre location and
|
|
10
|
+
* provider efficiency can move the real result outside this band. Local
|
|
11
|
+
* models are included because their token usage still consumes electricity,
|
|
12
|
+
* but Codeep cannot measure the device directly.
|
|
13
|
+
*/
|
|
14
|
+
const ENERGY_JOULES_PER_TOKEN = { low: 0.3, high: 1.5 };
|
|
15
|
+
const WATER_LITRES_PER_KWH = { low: 0.27, high: 1.08 };
|
|
16
|
+
export function estimateResourceImpact(totalTokens) {
|
|
17
|
+
const tokens = Number.isFinite(totalTokens) ? Math.max(0, totalTokens) : 0;
|
|
18
|
+
const energyWhLow = (tokens * ENERGY_JOULES_PER_TOKEN.low) / 3600;
|
|
19
|
+
const energyWhHigh = (tokens * ENERGY_JOULES_PER_TOKEN.high) / 3600;
|
|
20
|
+
return {
|
|
21
|
+
energyWhLow,
|
|
22
|
+
energyWhHigh,
|
|
23
|
+
waterMlLow: (energyWhLow / 1000) * WATER_LITRES_PER_KWH.low * 1000,
|
|
24
|
+
waterMlHigh: (energyWhHigh / 1000) * WATER_LITRES_PER_KWH.high * 1000,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function compact(value) {
|
|
28
|
+
if (value === 0)
|
|
29
|
+
return '0';
|
|
30
|
+
if (value < 0.01)
|
|
31
|
+
return value.toFixed(3);
|
|
32
|
+
if (value < 1)
|
|
33
|
+
return value.toFixed(2);
|
|
34
|
+
if (value < 10)
|
|
35
|
+
return value.toFixed(1);
|
|
36
|
+
return Math.round(value).toLocaleString('en-US');
|
|
37
|
+
}
|
|
38
|
+
export function formatResourceImpact(estimate) {
|
|
39
|
+
const energy = estimate.energyWhHigh >= 1000
|
|
40
|
+
? `${compact(estimate.energyWhLow / 1000)}–${compact(estimate.energyWhHigh / 1000)} kWh`
|
|
41
|
+
: `${compact(estimate.energyWhLow)}–${compact(estimate.energyWhHigh)} Wh`;
|
|
42
|
+
const water = estimate.waterMlHigh >= 1000
|
|
43
|
+
? `${compact(estimate.waterMlLow / 1000)}–${compact(estimate.waterMlHigh / 1000)} L`
|
|
44
|
+
: `${compact(estimate.waterMlLow)}–${compact(estimate.waterMlHigh)} mL`;
|
|
45
|
+
return { energy, water };
|
|
46
|
+
}
|
|
47
|
+
export function formatResourceImpactReport(totalTokens) {
|
|
48
|
+
const formatted = formatResourceImpact(estimateResourceImpact(totalTokens));
|
|
49
|
+
return [
|
|
50
|
+
'### Estimated compute impact',
|
|
51
|
+
`**Electricity:** ${formatted.energy} · **Cooling water:** ${formatted.water}`,
|
|
52
|
+
'_Research-based range, not a provider measurement. Actual usage varies widely by model, hardware, batching, context length, data-centre location, and cooling system._',
|
|
53
|
+
];
|
|
54
|
+
}
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
* Token and cost tracking for API usage
|
|
3
3
|
*/
|
|
4
4
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
5
|
-
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
5
|
+
import { formatResourceImpactReport } from './resourceImpact.js';
|
|
6
|
+
// Context window sizes per model (in tokens). Primarily mirrors providers.ts;
|
|
7
|
+
// retired aliases remain only where restored historical sessions still need a
|
|
8
|
+
// meaningful context/cost display.
|
|
9
9
|
const MODEL_CONTEXT_WINDOWS = {
|
|
10
10
|
// Z.AI / ZhipuAI
|
|
11
|
-
'glm-5.2':
|
|
11
|
+
'glm-5.2': 1_000_000,
|
|
12
|
+
'glm-5.1': 200_000,
|
|
12
13
|
'glm-5-turbo': 202_752,
|
|
13
14
|
// OpenAI
|
|
14
15
|
'gpt-5.6-sol': 1_050_000,
|
|
@@ -19,7 +20,7 @@ const MODEL_CONTEXT_WINDOWS = {
|
|
|
19
20
|
'gpt-5.4-mini': 400_000,
|
|
20
21
|
// Anthropic
|
|
21
22
|
'claude-fable-5': 1_000_000,
|
|
22
|
-
'claude-opus-
|
|
23
|
+
'claude-opus-5': 1_000_000,
|
|
23
24
|
'claude-sonnet-4-6': 1_000_000,
|
|
24
25
|
'claude-sonnet-5': 1_000_000,
|
|
25
26
|
'claude-haiku-4-5-20251001': 200_000,
|
|
@@ -28,28 +29,34 @@ const MODEL_CONTEXT_WINDOWS = {
|
|
|
28
29
|
'deepseek-v4-flash': 1_000_000,
|
|
29
30
|
// Google
|
|
30
31
|
'gemini-3.1-pro-preview': 1_048_576,
|
|
31
|
-
'gemini-3.
|
|
32
|
-
'gemini-3.
|
|
32
|
+
'gemini-3.6-flash': 1_048_576,
|
|
33
|
+
'gemini-3.5-flash': 1_048_576,
|
|
34
|
+
'gemini-3.5-flash-lite': 1_048_576,
|
|
33
35
|
'gemini-3-flash-preview': 1_000_000,
|
|
34
36
|
// MiniMax
|
|
35
|
-
'MiniMax-M3':
|
|
36
|
-
// Kimi (Moonshot) — 256K across
|
|
37
|
+
'MiniMax-M3': 1_000_000,
|
|
38
|
+
// Kimi (Moonshot) — 1M on K3, 256K across K2.x
|
|
39
|
+
'kimi-k3': 1_000_000,
|
|
37
40
|
'kimi-k2.7-code': 262_144,
|
|
38
41
|
'kimi-k2.7-code-highspeed': 262_144,
|
|
39
42
|
'kimi-k2.6': 262_144,
|
|
40
|
-
'kimi-k2.5': 262_144,
|
|
41
43
|
'kimi-for-coding': 262_144,
|
|
44
|
+
'kimi-for-coding-highspeed': 262_144,
|
|
45
|
+
'k3': 1_000_000,
|
|
46
|
+
'k3-256k': 262_144,
|
|
42
47
|
// Grok (xAI)
|
|
43
48
|
'grok-4.5': 500_000,
|
|
44
49
|
'grok-build-0.1': 256_000,
|
|
45
50
|
'grok-4.3': 1_000_000,
|
|
46
51
|
'grok-code-fast-1': 256_000,
|
|
47
52
|
'grok-4-fast-reasoning': 2_000_000,
|
|
48
|
-
// Qwen (Alibaba) —
|
|
49
|
-
'qwen3-coder-plus': 262_144,
|
|
50
|
-
'qwen3-coder-next': 262_144,
|
|
51
|
-
'qwen3-coder-flash': 262_144,
|
|
53
|
+
// Qwen (Alibaba) — current hosted generation
|
|
52
54
|
'qwen3.7-max': 1_000_000,
|
|
55
|
+
'qwen3.8-max-preview': 1_000_000,
|
|
56
|
+
'qwen3.7-plus': 1_000_000,
|
|
57
|
+
'qwen3.6-plus': 1_000_000,
|
|
58
|
+
'qwen3.5-plus': 1_000_000,
|
|
59
|
+
'qwen3.6-flash': 1_000_000,
|
|
53
60
|
'Qwen/Qwen3-Coder-480B-A35B-Instruct': 262_144,
|
|
54
61
|
};
|
|
55
62
|
const DEFAULT_CONTEXT_WINDOW = 128_000;
|
|
@@ -60,58 +67,65 @@ export function getModelContextWindow(model) {
|
|
|
60
67
|
return MODEL_CONTEXT_WINDOWS[model] ?? DEFAULT_CONTEXT_WINDOW;
|
|
61
68
|
}
|
|
62
69
|
// Pricing table — USD per 1M tokens. Same rule as MODEL_CONTEXT_WINDOWS:
|
|
63
|
-
//
|
|
64
|
-
//
|
|
70
|
+
// Primarily mirrors `providers.ts`. A few retired aliases remain so restored
|
|
71
|
+
// historical sessions still show the rate that applied when they were created.
|
|
65
72
|
const MODEL_PRICING = {
|
|
66
73
|
// Z.AI / ZhipuAI
|
|
67
|
-
//
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
// subscription, so this only affects the pay-per-use estimate.
|
|
71
|
-
'glm-5.2': { inputPer1M: 1.00, outputPer1M: 3.20 },
|
|
74
|
+
// Coding Plan is flat-fee; these official rates apply to pay-per-use.
|
|
75
|
+
'glm-5.2': { inputPer1M: 1.40, outputPer1M: 4.40 },
|
|
76
|
+
'glm-5.1': { inputPer1M: 1.40, outputPer1M: 4.40 },
|
|
72
77
|
'glm-5-turbo': { inputPer1M: 1.20, outputPer1M: 4.00 },
|
|
73
78
|
// OpenAI
|
|
74
79
|
'gpt-5.6-sol': { inputPer1M: 5.00, outputPer1M: 30.00 },
|
|
75
|
-
'gpt-5.6-terra': { inputPer1M: 2.
|
|
76
|
-
'gpt-5.6-luna': { inputPer1M:
|
|
80
|
+
'gpt-5.6-terra': { inputPer1M: 2.00, outputPer1M: 12.00 },
|
|
81
|
+
'gpt-5.6-luna': { inputPer1M: 0.20, outputPer1M: 1.20 },
|
|
77
82
|
'gpt-5.5': { inputPer1M: 5.00, outputPer1M: 30.00 },
|
|
78
83
|
'gpt-5.4': { inputPer1M: 2.50, outputPer1M: 15.00 },
|
|
79
84
|
'gpt-5.4-mini': { inputPer1M: 0.75, outputPer1M: 4.50 },
|
|
80
85
|
// Anthropic
|
|
81
86
|
'claude-fable-5': { inputPer1M: 10.00, outputPer1M: 50.00 },
|
|
82
|
-
'claude-opus-
|
|
87
|
+
'claude-opus-5': { inputPer1M: 5.00, outputPer1M: 25.00 },
|
|
83
88
|
'claude-sonnet-4-6': { inputPer1M: 3.00, outputPer1M: 15.00 },
|
|
84
89
|
'claude-sonnet-5': { inputPer1M: 3.00, outputPer1M: 15.00 },
|
|
85
90
|
'claude-haiku-4-5-20251001': { inputPer1M: 1.00, outputPer1M: 5.00 },
|
|
86
91
|
// DeepSeek (cache-miss input pricing)
|
|
87
|
-
'deepseek-v4-pro': { inputPer1M:
|
|
92
|
+
'deepseek-v4-pro': { inputPer1M: 0.435, outputPer1M: 0.87 },
|
|
88
93
|
'deepseek-v4-flash': { inputPer1M: 0.14, outputPer1M: 0.28 },
|
|
89
94
|
// Google
|
|
90
95
|
'gemini-3.1-pro-preview': { inputPer1M: 2.00, outputPer1M: 12.00 },
|
|
96
|
+
'gemini-3.6-flash': { inputPer1M: 1.50, outputPer1M: 7.50 },
|
|
91
97
|
'gemini-3.5-flash': { inputPer1M: 1.50, outputPer1M: 9.00 },
|
|
92
|
-
'gemini-3.
|
|
98
|
+
'gemini-3.5-flash-lite': { inputPer1M: 0.30, outputPer1M: 2.50 },
|
|
93
99
|
'gemini-3-flash-preview': { inputPer1M: 0.50, outputPer1M: 3.00 },
|
|
94
100
|
// MiniMax
|
|
95
101
|
'MiniMax-M3': { inputPer1M: 0.60, outputPer1M: 2.40 },
|
|
96
102
|
// Kimi (Moonshot) — pay-per-use cache-miss rates; `kimi-for-coding` is the
|
|
97
103
|
// subscription alias (flat-fee in reality, priced notionally like K2.7 Code).
|
|
98
|
-
'kimi-
|
|
99
|
-
'kimi-k2.7-code
|
|
100
|
-
'
|
|
101
|
-
|
|
102
|
-
'kimi-
|
|
104
|
+
'kimi-k3': { inputPer1M: 3.00, outputPer1M: 15.00 },
|
|
105
|
+
'kimi-k2.7-code': { inputPer1M: 0.95, outputPer1M: 4.00 },
|
|
106
|
+
// Kimi doesn't publish a distinct high-speed price in its main table.
|
|
107
|
+
// Leave that variant unpriced rather than presenting an invented estimate.
|
|
108
|
+
'kimi-k2.6': { inputPer1M: 0.95, outputPer1M: 4.00 },
|
|
109
|
+
'kimi-for-coding': { inputPer1M: 0.95, outputPer1M: 4.00 },
|
|
110
|
+
'kimi-for-coding-highspeed': { inputPer1M: 0.95, outputPer1M: 4.00 },
|
|
111
|
+
'k3': { inputPer1M: 3.00, outputPer1M: 15.00 },
|
|
112
|
+
'k3-256k': { inputPer1M: 3.00, outputPer1M: 15.00 },
|
|
103
113
|
// Grok (xAI)
|
|
104
114
|
'grok-4.5': { inputPer1M: 2.00, outputPer1M: 6.00 },
|
|
105
115
|
'grok-build-0.1': { inputPer1M: 1.00, outputPer1M: 2.00 },
|
|
106
116
|
'grok-4.3': { inputPer1M: 1.25, outputPer1M: 2.50 },
|
|
107
117
|
'grok-code-fast-1': { inputPer1M: 0.20, outputPer1M: 1.50 },
|
|
108
118
|
'grok-4-fast-reasoning': { inputPer1M: 0.20, outputPer1M: 0.50 },
|
|
109
|
-
// Qwen (Alibaba) —
|
|
110
|
-
//
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
119
|
+
// Qwen (Alibaba) — list prices for the first context tier. Coding Plan
|
|
120
|
+
// variants are flat-fee; these rates describe pay-per-use calls.
|
|
121
|
+
// `qwen3.8-max-preview` is Token-Plan-only (credit-metered, promotional
|
|
122
|
+
// preview rate); Alibaba publishes no pay-per-use per-token price for it.
|
|
123
|
+
// Leave it unpriced rather than borrowing the GA qwen3.8-max rate.
|
|
114
124
|
'qwen3.7-max': { inputPer1M: 2.50, outputPer1M: 7.50 },
|
|
125
|
+
'qwen3.7-plus': { inputPer1M: 0.40, outputPer1M: 1.60 },
|
|
126
|
+
'qwen3.6-plus': { inputPer1M: 0.40, outputPer1M: 2.40 },
|
|
127
|
+
'qwen3.5-plus': { inputPer1M: 0.40, outputPer1M: 2.40 },
|
|
128
|
+
'qwen3.6-flash': { inputPer1M: 0.25, outputPer1M: 1.50 },
|
|
115
129
|
// ModelScope free tier — no per-token charge.
|
|
116
130
|
'Qwen/Qwen3-Coder-480B-A35B-Instruct': { inputPer1M: 0, outputPer1M: 0 },
|
|
117
131
|
};
|
|
@@ -362,6 +376,7 @@ export function formatCostReport() {
|
|
|
362
376
|
lines.push(`**Estimated savings vs no caching:** $${cache.estimatedSavingsUsd.toFixed(4)}`);
|
|
363
377
|
}
|
|
364
378
|
}
|
|
379
|
+
lines.push('', ...formatResourceImpactReport(stats.totalTokens));
|
|
365
380
|
// Models with no pricing entry don't contribute to cost — flag so users
|
|
366
381
|
// aren't surprised the total looks low.
|
|
367
382
|
const untracked = breakdown.filter(b => b.estimatedCost === 0 && (b.promptTokens + b.completionTokens) > 0);
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@web <url>` inline context — fetch a web page and attach its text
|
|
3
|
+
* content to the prompt, the same way `@file` attaches a file.
|
|
4
|
+
*
|
|
5
|
+
* Supported forms (anywhere in the message, like file mentions):
|
|
6
|
+
* @web https://example.com/docs → full URL
|
|
7
|
+
* @web example.com/docs → https:// is auto-prepended
|
|
8
|
+
* @web http://localhost:3000/api → dev servers work too
|
|
9
|
+
*
|
|
10
|
+
* The fetch is best-effort:
|
|
11
|
+
* - HTML is stripped to readable text (tags, scripts, styles removed).
|
|
12
|
+
* - Output is capped at `MAX_WEB_BYTES` (default 32 KB) so a single
|
|
13
|
+
* page can't blow the context window.
|
|
14
|
+
* - Markdown conversion is lightweight (headings, links, lists) — we
|
|
15
|
+
* don't run a full HTML→Markdown pipeline; the goal is "agent can
|
|
16
|
+
* read the page", not "pretty render".
|
|
17
|
+
* - Failures (network, non-2xx, non-text content type) surface as
|
|
18
|
+
* inline notifications, same as missing files.
|
|
19
|
+
*
|
|
20
|
+
* The fetcher is async, so `expandWebMentions` is async — unlike the
|
|
21
|
+
* sync `expandMentions` for files. Callers await it.
|
|
22
|
+
*/
|
|
23
|
+
/** Max bytes of text we'll inline from a fetched page (32 KB). */
|
|
24
|
+
export declare const MAX_WEB_BYTES: number;
|
|
25
|
+
/** Result of expanding `@web` mentions in a prompt. */
|
|
26
|
+
export interface WebExpansionResult {
|
|
27
|
+
/** The prompt with fetched page text prepended. */
|
|
28
|
+
enrichedPrompt: string;
|
|
29
|
+
/** Successfully fetched pages. */
|
|
30
|
+
loaded: Array<{
|
|
31
|
+
url: string;
|
|
32
|
+
title: string;
|
|
33
|
+
content: string;
|
|
34
|
+
}>;
|
|
35
|
+
/** Mentions that couldn't be fetched, with a human-readable reason. */
|
|
36
|
+
failures: Array<{
|
|
37
|
+
mention: string;
|
|
38
|
+
reason: string;
|
|
39
|
+
}>;
|
|
40
|
+
}
|
|
41
|
+
/** One `@web` mention match. */
|
|
42
|
+
interface WebToken {
|
|
43
|
+
/** Full match including `@web `, for display. */
|
|
44
|
+
raw: string;
|
|
45
|
+
/** The URL (normalized: `https://` prepended if missing a scheme). */
|
|
46
|
+
url: string;
|
|
47
|
+
/** Start index of `raw` in the source. */
|
|
48
|
+
start: number;
|
|
49
|
+
/** End index (exclusive). */
|
|
50
|
+
end: number;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Extract all `@web` mentions from `text`. Pure (no network).
|
|
54
|
+
* Returns them in document order.
|
|
55
|
+
*/
|
|
56
|
+
export declare function extractWebMentions(text: string): WebToken[];
|
|
57
|
+
export interface WebFetchOptions {
|
|
58
|
+
/**
|
|
59
|
+
* The fetch implementation. Defaults to the global `fetch` (Node 18+).
|
|
60
|
+
* Injected so tests can mock without hitting the network.
|
|
61
|
+
*/
|
|
62
|
+
fetchImpl?: typeof fetch;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Expand all `@web` mentions in `prompt`: fetch each URL, convert the
|
|
66
|
+
* HTML to readable text, and prepend it as a `[Web pages]` block.
|
|
67
|
+
* Failures are collected, not thrown.
|
|
68
|
+
*/
|
|
69
|
+
export declare function expandWebMentions(prompt: string, opts?: WebFetchOptions): Promise<WebExpansionResult>;
|
|
70
|
+
/**
|
|
71
|
+
* Reset the session web cache. Public so callers (e.g. `/web-cache clear`
|
|
72
|
+
* command, or tests) can force a fresh fetch.
|
|
73
|
+
*/
|
|
74
|
+
export declare function clearWebCache(): void;
|
|
75
|
+
/**
|
|
76
|
+
* Stats about the session web cache — for `/web-cache status`.
|
|
77
|
+
*/
|
|
78
|
+
export declare function webCacheStats(): {
|
|
79
|
+
entries: number;
|
|
80
|
+
maxEntries: number;
|
|
81
|
+
ttlMinutes: number;
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Convert HTML to readable plain text + a title.
|
|
85
|
+
*
|
|
86
|
+
* Lightweight — no full parser dependency. Strips `<script>`, `<style>`,
|
|
87
|
+
* and tags, collapses whitespace, extracts `<title>` and the first
|
|
88
|
+
* `<h1>` as the page title. Good enough for the agent to read docs;
|
|
89
|
+
* not a faithful rendering.
|
|
90
|
+
*/
|
|
91
|
+
export declare function htmlToText(html: string): {
|
|
92
|
+
title: string;
|
|
93
|
+
content: string;
|
|
94
|
+
};
|
|
95
|
+
/** Format the `[Web pages]` block prepended to the enriched prompt. */
|
|
96
|
+
export declare function formatWebBlock(pages: Array<{
|
|
97
|
+
url: string;
|
|
98
|
+
title: string;
|
|
99
|
+
content: string;
|
|
100
|
+
}>): string;
|
|
101
|
+
export {};
|