@vesk/adapter 0.2.9 → 0.2.11
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/client-bundle.d.ts +29 -0
- package/dist/client-bundle.d.ts.map +1 -1
- package/dist/client-bundle.js +333 -52
- package/dist/dev-api.d.ts +78 -0
- package/dist/dev-api.d.ts.map +1 -0
- package/dist/dev-api.js +338 -0
- package/dist/dev-config.d.ts +48 -0
- package/dist/dev-config.d.ts.map +1 -0
- package/dist/dev-config.js +964 -0
- package/dist/dev-server.d.ts +85 -0
- package/dist/dev-server.d.ts.map +1 -1
- package/dist/dev-server.js +329 -8
- package/dist/error-codeframe.d.ts +23 -0
- package/dist/error-codeframe.d.ts.map +1 -0
- package/dist/error-codeframe.js +127 -0
- package/dist/error-tips.d.ts +7 -0
- package/dist/error-tips.d.ts.map +1 -0
- package/dist/error-tips.js +91 -0
- package/dist/hmr-utils.d.ts +14 -0
- package/dist/hmr-utils.d.ts.map +1 -0
- package/dist/hmr-utils.js +56 -0
- package/dist/hmr.d.ts +40 -0
- package/dist/hmr.d.ts.map +1 -1
- package/dist/hmr.js +139 -20
- package/dist/index.d.ts +37 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +105 -22
- package/dist/paths.d.ts +8 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +32 -0
- package/dist/platform-handler.d.ts.map +1 -1
- package/dist/platform-handler.js +2 -1
- package/dist/plugins.d.ts +147 -0
- package/dist/plugins.d.ts.map +1 -0
- package/dist/plugins.js +1109 -0
- package/dist/prod-server.d.ts.map +1 -1
- package/dist/prod-server.js +43 -9
- package/dist/ssr-function.d.ts.map +1 -1
- package/dist/ssr-function.js +14 -2
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/dev-server.d.ts
CHANGED
|
@@ -1,7 +1,92 @@
|
|
|
1
1
|
import { type Server } from 'node:http';
|
|
2
2
|
import type { DevServerOptions } from '@vesk/adapter/src/types';
|
|
3
|
+
/**
|
|
4
|
+
* Shape returned by the dev HMR state endpoint. Mirrors what the parallel
|
|
5
|
+
* `hmr.ts` agent's `getHmrState()` returns; we tolerate its absence at
|
|
6
|
+
* module-load time (see `devHmrState`) so this module stays importable even
|
|
7
|
+
* before the state provider lands.
|
|
8
|
+
*/
|
|
9
|
+
export interface DevHmrState {
|
|
10
|
+
status: 'up' | 'compiling' | 'error' | 'down';
|
|
11
|
+
lastCompileMs: number | null;
|
|
12
|
+
error: Record<string, unknown> | null;
|
|
13
|
+
hasError: boolean;
|
|
14
|
+
componentCount: number;
|
|
15
|
+
}
|
|
16
|
+
/** Default state when no HMR provider is available (no server). */
|
|
17
|
+
export declare function defaultDevHmrState(): DevHmrState;
|
|
3
18
|
export declare function bodyTooLarge(maxBytes: number): Error & {
|
|
4
19
|
status: number;
|
|
5
20
|
};
|
|
21
|
+
export interface DevPanelResponse {
|
|
22
|
+
status: number;
|
|
23
|
+
headers: Record<string, string>;
|
|
24
|
+
body: string;
|
|
25
|
+
/** When 'base64', the dev server writes Buffer.from(body, 'base64') to the socket (binary payloads like icons). */
|
|
26
|
+
encoding?: 'utf8' | 'base64';
|
|
27
|
+
/** When set, `body`/`encoding` are ignored and this async iterable of
|
|
28
|
+
(already-framed) strings is streamed to the client instead — used for
|
|
29
|
+
SSE agent progress. */
|
|
30
|
+
stream?: AsyncIterable<string>;
|
|
31
|
+
}
|
|
32
|
+
export interface PluginRouterChangeEvent {
|
|
33
|
+
type: 'activate' | 'deactivate' | 'install' | 'uninstall' | 'update';
|
|
34
|
+
name?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface PluginStateRouterOptions {
|
|
37
|
+
appDir: string;
|
|
38
|
+
veskDir: string;
|
|
39
|
+
configPluginNames: string[];
|
|
40
|
+
getHmrState?: () => DevHmrState;
|
|
41
|
+
/** Called after a mutation so the caller can rebuild + notify HMR clients. */
|
|
42
|
+
onPluginChange?: (event: PluginRouterChangeEvent) => void | Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Pure, dependency-injectable router for the dev panel HTTP endpoints
|
|
46
|
+
* (`/__vesk/...`). Everything is testable with fake inputs — no socket, no
|
|
47
|
+
* listener. Returns `null` for paths that are not dev-panel endpoints so the
|
|
48
|
+
* dev server can fall through to its normal route handling.
|
|
49
|
+
*
|
|
50
|
+
* Endpoints:
|
|
51
|
+
* GET /__vesk/hmr/state → { ...DevHmrState }
|
|
52
|
+
* GET /__vesk/plugins → { plugins: PluginRecord[] } (registry-enriched)
|
|
53
|
+
* POST /__vesk/plugins/activate → { ok, record }
|
|
54
|
+
* POST /__vesk/plugins/deactivate → { ok, record }
|
|
55
|
+
* POST /__vesk/plugins/install → { ok, record }
|
|
56
|
+
* POST /__vesk/plugins/uninstall → { ok }
|
|
57
|
+
* POST /__vesk/plugins/update → { ok, record }
|
|
58
|
+
* GET /__vesk/plugins/search?q=<query> → { results: PluginSearchResult[] }
|
|
59
|
+
* GET /__vesk/plugins/:name/icon → { base64 + mime } (or 404)
|
|
60
|
+
* GET /__vesk/plugins/:name/exports → { PluginExportsInfo }
|
|
61
|
+
* (anything else under /__vesk/*) → 404 { error }
|
|
62
|
+
*/
|
|
63
|
+
export declare function createPluginStateRouter(opts: PluginStateRouterOptions): {
|
|
64
|
+
route: (method: string, pathname: string, body?: unknown, search?: string) => Promise<DevPanelResponse | null>;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Inline bootstrap script injected after the dev/HMR scripts on every served
|
|
68
|
+
* dev page. On DOMContentLoaded it polls `/__vesk/hmr/state` and — if the
|
|
69
|
+
* server reports a persisted error — calls the client's registered
|
|
70
|
+
* `globalThis.__vesk_hmr_show(payload)` to re-open the error overlay. This
|
|
71
|
+
* satisfies the Nuxt-like "a refresh during an active error should still show
|
|
72
|
+
* the overlay" requirement, because the client bundle's own state fetch only
|
|
73
|
+
* fires after its module runs.
|
|
74
|
+
*
|
|
75
|
+
* Idempotency: the `window.__vesk_hmr_bootstrap` guard makes the inline script
|
|
76
|
+
* run at most once per page even if it is injected at multiple `</body>` sites
|
|
77
|
+
* (or on a page served more than once). The overlay itself cannot be duplicated
|
|
78
|
+
* because the client's `showOverlay` reuses a single `#__vesk_overlay` element
|
|
79
|
+
* (guarded in `createOverlay`), and `__vesk_hmr_show` is registered once by
|
|
80
|
+
* `registerGlobalHmr`. So a double-show (inline bootstrap + client's own
|
|
81
|
+
* `loadPersistedState`) re-renders the same overlay rather than stacking a
|
|
82
|
+
* second one.
|
|
83
|
+
*/
|
|
84
|
+
export declare function devBootstrapScript(): string;
|
|
85
|
+
/**
|
|
86
|
+
* Inject the dev/HMR client script plus the inline state bootstrap into an HTML
|
|
87
|
+
* page at its first `</body>`. Idempotent when there is no `</body>`: the HTML
|
|
88
|
+
* is returned unchanged (never injected twice / never appended uncontrolled).
|
|
89
|
+
*/
|
|
90
|
+
export declare function injectDevScripts(html: string): string;
|
|
6
91
|
export declare function startDevServer(appDir: string, options?: DevServerOptions): Promise<Server | void>;
|
|
7
92
|
//# sourceMappingURL=dev-server.d.ts.map
|
package/dist/dev-server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,MAAM,EAA6C,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"dev-server.d.ts","sourceRoot":"","sources":["../src/dev-server.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgB,KAAK,MAAM,EAA6C,MAAM,WAAW,CAAC;AAUjG,OAAO,KAAK,EAAa,gBAAgB,EAAwB,MAAM,yBAAyB,CAAC;AAgBjG;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,IAAI,GAAG,WAAW,GAAG,OAAO,GAAG,MAAM,CAAC;IAC9C,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,QAAQ,EAAE,OAAO,CAAC;IAClB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,mEAAmE;AACnE,wBAAgB,kBAAkB,IAAI,WAAW,CAEhD;AAuCD,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAIzE;AAkBD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,mHAAmH;IACnH,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B;;8BAE0B;IAC1B,MAAM,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,CAAC;IACrE,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,WAAW,CAAC,EAAE,MAAM,WAAW,CAAC;IAChC,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,wBAAwB,GAAG;IACvE,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;CAChH,CAUA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAa3C;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAIrD;AA6CD,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoevG"}
|
package/dist/dev-server.js
CHANGED
|
@@ -5,10 +5,55 @@ import { fileURLToPath } from 'node:url';
|
|
|
5
5
|
import { stripCodeTypes } from '@vesk/compiler/src/strip-ts';
|
|
6
6
|
import { DEFAULT_MAX_BODY_BYTES } from '@vesk/compiler/src/server-codegen';
|
|
7
7
|
import { build } from '@vesk/adapter/src/index';
|
|
8
|
-
import { createHmrServer } from '
|
|
8
|
+
import { createHmrServer } from './hmr';
|
|
9
|
+
import * as hmrApi from './hmr';
|
|
10
|
+
import { createDevApiRouter } from './dev-api';
|
|
9
11
|
import { buildRuntimeCode } from '@vesk/adapter/src/client-bundle';
|
|
10
|
-
import { resolveWithin } from '@vesk/adapter/src/paths';
|
|
12
|
+
import { resolveWithin, installMdReadHook } from '@vesk/adapter/src/paths';
|
|
13
|
+
import { getPluginRecords } from './plugins';
|
|
14
|
+
// @vesk/agentic — optional AI plugin; gated by active state if installed
|
|
15
|
+
import { createAgentRouter } from '@vesk/agentic/src/dev-api';
|
|
16
|
+
import { CheckpointManager } from '@vesk/agentic/src/checkpoints';
|
|
17
|
+
import { AgentCapabilityTable } from '@vesk/agentic/src/permissions';
|
|
18
|
+
import { openAiProvider } from '@vesk/agentic/src/providers/openai';
|
|
19
|
+
import { anthropicProvider } from '@vesk/agentic/src/providers/anthropic';
|
|
20
|
+
import { Agent } from '@vesk/agentic/src/loop';
|
|
21
|
+
import { createVeskTools } from '@vesk/agentic/src/tools/vesk';
|
|
22
|
+
import { getApiKey, loadAgenticConfig, SUPPORTED_PROVIDERS } from '@vesk/agentic/src/config';
|
|
11
23
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
24
|
+
/** Default state when no HMR provider is available (no server). */
|
|
25
|
+
export function defaultDevHmrState() {
|
|
26
|
+
return { status: 'up', lastCompileMs: null, error: null, hasError: false, componentCount: 0 };
|
|
27
|
+
}
|
|
28
|
+
/** The live HMR state provider: the parallel agent's `getHmrState` if present, else a safe no-server default. */
|
|
29
|
+
const devHmrState = typeof hmrApi.getHmrState === 'function'
|
|
30
|
+
? hmrApi.getHmrState
|
|
31
|
+
: defaultDevHmrState;
|
|
32
|
+
/**
|
|
33
|
+
* Writes a handler Response to the socket, piping a streaming body
|
|
34
|
+
* chunk-by-chunk (SSE / text streams) instead of buffering everything.
|
|
35
|
+
*/
|
|
36
|
+
async function deliverResponse(res, response) {
|
|
37
|
+
res.writeHead(response.status, Object.fromEntries(response.headers));
|
|
38
|
+
const body = response.body;
|
|
39
|
+
if (body && typeof body.getReader === 'function') {
|
|
40
|
+
const reader = body.getReader();
|
|
41
|
+
try {
|
|
42
|
+
for (;;) {
|
|
43
|
+
const { done, value } = await reader.read();
|
|
44
|
+
if (done)
|
|
45
|
+
break;
|
|
46
|
+
res.write(Buffer.from(value));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
/* stream aborted by the client */
|
|
51
|
+
}
|
|
52
|
+
res.end();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
res.end(await response.text());
|
|
56
|
+
}
|
|
12
57
|
export function bodyTooLarge(maxBytes) {
|
|
13
58
|
const err = new Error(`Request body exceeds limit (${maxBytes} bytes)`);
|
|
14
59
|
err.status = 413;
|
|
@@ -29,6 +74,77 @@ async function readBody(req, maxBytes = DEFAULT_MAX_BODY_BYTES) {
|
|
|
29
74
|
}
|
|
30
75
|
return Buffer.concat(chunks);
|
|
31
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* Pure, dependency-injectable router for the dev panel HTTP endpoints
|
|
79
|
+
* (`/__vesk/...`). Everything is testable with fake inputs — no socket, no
|
|
80
|
+
* listener. Returns `null` for paths that are not dev-panel endpoints so the
|
|
81
|
+
* dev server can fall through to its normal route handling.
|
|
82
|
+
*
|
|
83
|
+
* Endpoints:
|
|
84
|
+
* GET /__vesk/hmr/state → { ...DevHmrState }
|
|
85
|
+
* GET /__vesk/plugins → { plugins: PluginRecord[] } (registry-enriched)
|
|
86
|
+
* POST /__vesk/plugins/activate → { ok, record }
|
|
87
|
+
* POST /__vesk/plugins/deactivate → { ok, record }
|
|
88
|
+
* POST /__vesk/plugins/install → { ok, record }
|
|
89
|
+
* POST /__vesk/plugins/uninstall → { ok }
|
|
90
|
+
* POST /__vesk/plugins/update → { ok, record }
|
|
91
|
+
* GET /__vesk/plugins/search?q=<query> → { results: PluginSearchResult[] }
|
|
92
|
+
* GET /__vesk/plugins/:name/icon → { base64 + mime } (or 404)
|
|
93
|
+
* GET /__vesk/plugins/:name/exports → { PluginExportsInfo }
|
|
94
|
+
* (anything else under /__vesk/*) → 404 { error }
|
|
95
|
+
*/
|
|
96
|
+
export function createPluginStateRouter(opts) {
|
|
97
|
+
// Delegates to the unified DevTools router (dev-api.ts) for the plugin +
|
|
98
|
+
// HMR-state surface, preserving the exact wire contract.
|
|
99
|
+
return createDevApiRouter({
|
|
100
|
+
appDir: opts.appDir,
|
|
101
|
+
veskDir: opts.veskDir,
|
|
102
|
+
configPluginNames: opts.configPluginNames,
|
|
103
|
+
getHmrState: opts.getHmrState,
|
|
104
|
+
onPluginChange: opts.onPluginChange,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Inline bootstrap script injected after the dev/HMR scripts on every served
|
|
109
|
+
* dev page. On DOMContentLoaded it polls `/__vesk/hmr/state` and — if the
|
|
110
|
+
* server reports a persisted error — calls the client's registered
|
|
111
|
+
* `globalThis.__vesk_hmr_show(payload)` to re-open the error overlay. This
|
|
112
|
+
* satisfies the Nuxt-like "a refresh during an active error should still show
|
|
113
|
+
* the overlay" requirement, because the client bundle's own state fetch only
|
|
114
|
+
* fires after its module runs.
|
|
115
|
+
*
|
|
116
|
+
* Idempotency: the `window.__vesk_hmr_bootstrap` guard makes the inline script
|
|
117
|
+
* run at most once per page even if it is injected at multiple `</body>` sites
|
|
118
|
+
* (or on a page served more than once). The overlay itself cannot be duplicated
|
|
119
|
+
* because the client's `showOverlay` reuses a single `#__vesk_overlay` element
|
|
120
|
+
* (guarded in `createOverlay`), and `__vesk_hmr_show` is registered once by
|
|
121
|
+
* `registerGlobalHmr`. So a double-show (inline bootstrap + client's own
|
|
122
|
+
* `loadPersistedState`) re-renders the same overlay rather than stacking a
|
|
123
|
+
* second one.
|
|
124
|
+
*/
|
|
125
|
+
export function devBootstrapScript() {
|
|
126
|
+
return ("<script>\n" +
|
|
127
|
+
"if(!window.__vesk_hmr_bootstrap){window.__vesk_hmr_bootstrap=1;" +
|
|
128
|
+
"(function(){function boot(){fetch('/__vesk/hmr/state')" +
|
|
129
|
+
".then(function(r){return r.ok?r.json():null;}).then(function(s){" +
|
|
130
|
+
"if(s&&s.error&&window.__vesk_hmr_show){window.__vesk_hmr_show(s.error);}" +
|
|
131
|
+
"}).catch(function(){});}" +
|
|
132
|
+
"if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',boot);}else{boot();}" +
|
|
133
|
+
"})();" +
|
|
134
|
+
"}\n" +
|
|
135
|
+
"</script>");
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Inject the dev/HMR client script plus the inline state bootstrap into an HTML
|
|
139
|
+
* page at its first `</body>`. Idempotent when there is no `</body>`: the HTML
|
|
140
|
+
* is returned unchanged (never injected twice / never appended uncontrolled).
|
|
141
|
+
*/
|
|
142
|
+
export function injectDevScripts(html) {
|
|
143
|
+
if (!html.includes('</body>'))
|
|
144
|
+
return html;
|
|
145
|
+
const scripts = '\t<script type="module" src="/_vesk/hmr.js"></script>\n' + devBootstrapScript() + '\n';
|
|
146
|
+
return html.replace('</body>', scripts + '</body>');
|
|
147
|
+
}
|
|
32
148
|
function makeWebRequest(nodeReq, url, maxBodyBytes = DEFAULT_MAX_BODY_BYTES) {
|
|
33
149
|
const parsedUrl = new URL(url, `http://${nodeReq.headers.host || 'localhost'}`);
|
|
34
150
|
const method = nodeReq.method || 'GET';
|
|
@@ -86,6 +202,139 @@ export async function startDevServer(appDir, options) {
|
|
|
86
202
|
process.env.NODE_ENV = 'development';
|
|
87
203
|
const devDir = resolve(appDir, '..', '.vesk', 'dev');
|
|
88
204
|
const publicDir = options?.publicDir || resolve(appDir, '..', 'public');
|
|
205
|
+
installMdReadHook([publicDir, resolve(devDir, 'static', 'public')]);
|
|
206
|
+
// Dev-panel plugin list: plugin / module names declared in the dev server's own config.
|
|
207
|
+
const configPluginNames = (options?.plugins || []).map((p) => {
|
|
208
|
+
if (typeof p === 'string')
|
|
209
|
+
return p;
|
|
210
|
+
return p.name;
|
|
211
|
+
}).filter((n) => typeof n === 'string' && !!n);
|
|
212
|
+
// ── @vesk/agentic dev API (B6-plug) — chained BEFORE the core dev API ─────
|
|
213
|
+
// Chain: createAgentRouter (CheckpointManager + AgentCapabilityTable + Provider
|
|
214
|
+
// via openAiProvider/anthropicProvider, .env.local VK_{PROVIDER}_KEY) →
|
|
215
|
+
// createDevApiRouter. Gate: only expose /__vesk/agent/* when @vesk/agentic
|
|
216
|
+
// is installed AND active (otherwise lean core, no agent surface).
|
|
217
|
+
const agenticCheckpointManager = new CheckpointManager();
|
|
218
|
+
const agenticVeskDir = resolve(appDir, '..', '.vesk');
|
|
219
|
+
const agenticProjectDir = resolve(appDir, '..');
|
|
220
|
+
function isAgenticActive() {
|
|
221
|
+
try {
|
|
222
|
+
if (SUPPORTED_PROVIDERS.some((p) => !!getApiKey(agenticProjectDir, p)))
|
|
223
|
+
return true;
|
|
224
|
+
}
|
|
225
|
+
catch { }
|
|
226
|
+
try {
|
|
227
|
+
const records = getPluginRecords(appDir, agenticVeskDir, configPluginNames);
|
|
228
|
+
const rec = records.find((r) => r.name === '@vesk/agentic' || r.package === '@vesk/agentic');
|
|
229
|
+
if (!rec)
|
|
230
|
+
return false;
|
|
231
|
+
return rec.active;
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function getAgenticPermissions() {
|
|
238
|
+
const rawMode = process.env.VESK_AGENTIC_MODE || 'explore';
|
|
239
|
+
const valid = ['explore', 'debug', 'agent'];
|
|
240
|
+
const mode = (valid.includes(rawMode) ? rawMode : 'explore');
|
|
241
|
+
return new AgentCapabilityTable(mode);
|
|
242
|
+
}
|
|
243
|
+
async function runAgenticAgent(prompt, _mode, providerConfig) {
|
|
244
|
+
const cfg = (providerConfig || {});
|
|
245
|
+
const provider = await buildAdapterAgenticProvider(cfg);
|
|
246
|
+
const tools = createVeskTools({ projectDir: agenticProjectDir, appDir, veskDir: agenticVeskDir });
|
|
247
|
+
const budget = resolveAdapterAgenticStepBudget(cfg);
|
|
248
|
+
const agent = new Agent({ provider, tools, maxSteps: budget.maxSteps, autoExtend: budget.autoExtend, hardMaxSteps: budget.hardMaxSteps });
|
|
249
|
+
return agent.run(prompt);
|
|
250
|
+
}
|
|
251
|
+
async function* runAgenticAgentStream(prompt, _mode, providerConfig) {
|
|
252
|
+
const cfg = (providerConfig || {});
|
|
253
|
+
const provider = await buildAdapterAgenticProvider(cfg);
|
|
254
|
+
const tools = createVeskTools({ projectDir: agenticProjectDir, appDir, veskDir: agenticVeskDir });
|
|
255
|
+
const budget = resolveAdapterAgenticStepBudget(cfg);
|
|
256
|
+
const agent = new Agent({ provider, tools, maxSteps: budget.maxSteps, autoExtend: budget.autoExtend, hardMaxSteps: budget.hardMaxSteps });
|
|
257
|
+
yield* agent.runStream(prompt);
|
|
258
|
+
}
|
|
259
|
+
async function buildAdapterAgenticProvider(cfg) {
|
|
260
|
+
const providerName = String(cfg.provider || loadAgenticConfig(agenticProjectDir).provider || 'openai');
|
|
261
|
+
const apiKey = cfg.apiKey || getApiKey(agenticProjectDir, providerName) || '';
|
|
262
|
+
const model = cfg.model || loadAgenticConfig(agenticProjectDir).model || (providerName === 'anthropic' ? 'claude-sonnet-4-6' : providerName === 'google' ? 'gemini-2.0-flash' : providerName === 'ollama' ? 'llama3.1' : providerName === 'opencode' ? 'claude-sonnet-4-6' : providerName === 'opencode-go' ? 'opencode-go/kimi-k3' : providerName === 'openrouter' ? 'openrouter/auto' : 'gpt-4o-mini');
|
|
263
|
+
const baseUrl = cfg.baseUrl || loadAgenticConfig(agenticProjectDir).baseUrl || undefined;
|
|
264
|
+
const maxTokens = typeof cfg.maxTokens === 'number' ? cfg.maxTokens : undefined;
|
|
265
|
+
if (providerName === 'anthropic')
|
|
266
|
+
return anthropicProvider({ apiKey, model, baseUrl, maxTokens });
|
|
267
|
+
if (providerName === 'google') {
|
|
268
|
+
const { googleProvider } = await import('@vesk/agentic/src/providers/google');
|
|
269
|
+
return googleProvider({ apiKey, model, baseUrl });
|
|
270
|
+
}
|
|
271
|
+
if (providerName === 'ollama') {
|
|
272
|
+
const { ollamaProvider } = await import('@vesk/agentic/src/providers/ollama');
|
|
273
|
+
return ollamaProvider({ model, baseUrl });
|
|
274
|
+
}
|
|
275
|
+
if (providerName === 'opencode')
|
|
276
|
+
return openAiProvider({ apiKey, model, baseUrl: baseUrl || 'https://opencode.ai/zen/v1' });
|
|
277
|
+
if (providerName === 'opencode-go')
|
|
278
|
+
return openAiProvider({ apiKey, model, baseUrl: baseUrl || 'https://opencode.ai/zen/go/v1' });
|
|
279
|
+
if (providerName === 'openrouter')
|
|
280
|
+
return openAiProvider({ apiKey, model, baseUrl: baseUrl || 'https://openrouter.ai/api/v1' });
|
|
281
|
+
if (providerName === 'loopers')
|
|
282
|
+
return openAiProvider({ apiKey, model, baseUrl: baseUrl || 'http://localhost:8080' });
|
|
283
|
+
return openAiProvider({ apiKey, model, baseUrl });
|
|
284
|
+
}
|
|
285
|
+
function resolveAdapterAgenticStepBudget(cfg) {
|
|
286
|
+
const fileCfg = loadAgenticConfig(agenticProjectDir);
|
|
287
|
+
const requestVal = typeof cfg.maxSteps === 'number' && Number.isFinite(cfg.maxSteps) ? cfg.maxSteps : NaN;
|
|
288
|
+
const fileVal = typeof fileCfg.maxSteps === 'number' && fileCfg.maxSteps > 0 ? fileCfg.maxSteps : NaN;
|
|
289
|
+
const maxSteps = Number.isFinite(requestVal) ? Math.max(1, Math.floor(requestVal)) : Number.isFinite(fileVal) ? Math.floor(fileVal) : 25;
|
|
290
|
+
return { maxSteps, autoExtend: true, hardMaxSteps: 200 };
|
|
291
|
+
}
|
|
292
|
+
let agentRouter = null;
|
|
293
|
+
try {
|
|
294
|
+
if (isAgenticActive()) {
|
|
295
|
+
agentRouter = createAgentRouter({
|
|
296
|
+
projectDir: agenticProjectDir,
|
|
297
|
+
appDir,
|
|
298
|
+
veskDir: agenticVeskDir,
|
|
299
|
+
getPermissions: getAgenticPermissions,
|
|
300
|
+
runAgent: runAgenticAgent,
|
|
301
|
+
runAgentStream: runAgenticAgentStream,
|
|
302
|
+
listCheckpoints: () => agenticCheckpointManager.listNewestFirst(),
|
|
303
|
+
rollback: (id) => agenticCheckpointManager.get(id) ?? null,
|
|
304
|
+
createCheckpoint: (...args) => {
|
|
305
|
+
const first = args[0];
|
|
306
|
+
if (first && typeof first === 'object' && ('label' in first || 'message' in first)) {
|
|
307
|
+
return agenticCheckpointManager.create(first);
|
|
308
|
+
}
|
|
309
|
+
const msg = typeof first === 'string' ? first : 'checkpoint';
|
|
310
|
+
return agenticCheckpointManager.create({ label: msg, message: msg });
|
|
311
|
+
},
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
agentRouter = null;
|
|
317
|
+
}
|
|
318
|
+
// Late-bound so the router's onPluginChange can broadcast over the HMR
|
|
319
|
+
// WebSocket, which is only created further down in this function.
|
|
320
|
+
let hmrSession = null;
|
|
321
|
+
const devPanel = createPluginStateRouter({
|
|
322
|
+
appDir,
|
|
323
|
+
veskDir: resolve(appDir, '..', '.vesk'),
|
|
324
|
+
configPluginNames,
|
|
325
|
+
getHmrState: devHmrState,
|
|
326
|
+
onPluginChange: async (event) => {
|
|
327
|
+
try {
|
|
328
|
+
await doBuild();
|
|
329
|
+
if (hmrSession) {
|
|
330
|
+
hmrSession.broadcast('reload', { reason: `Plugin ${event.type}: ${event.name ?? ''}`, time: Date.now() });
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
catch {
|
|
334
|
+
/* plugin change rebuild is best-effort; the server keeps serving */
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
});
|
|
89
338
|
let componentMap = new Map();
|
|
90
339
|
const monorepoRouter = resolve(__dirname, '..', '..', 'compiler', 'dist', 'router.js');
|
|
91
340
|
const pkgRouter = resolve(appDir, '..', 'node_modules', '@vesk/compiler', 'router.js');
|
|
@@ -126,6 +375,79 @@ export async function startDevServer(appDir, options) {
|
|
|
126
375
|
await doBuild();
|
|
127
376
|
const server = createServer(async (req, res) => {
|
|
128
377
|
const url = new URL(req.url || '/', `http://localhost:${port}`);
|
|
378
|
+
// Dev panel endpoints (/__vesk/...): HMR state, plugin list, activate/
|
|
379
|
+
// deactivate/install/uninstall. Routed through the pure injectable router.
|
|
380
|
+
// Chain: agent router (CheckpointManager + AgentCapabilityTable + Provider
|
|
381
|
+
// via openAiProvider/anthropicProvider, .env.local VK_{PROVIDER}_KEY)
|
|
382
|
+
// is tried BEFORE the core dev panel, gated by @vesk/agentic active.
|
|
383
|
+
if (url.pathname.startsWith('/__vesk/')) {
|
|
384
|
+
let body = undefined;
|
|
385
|
+
if ((req.method || 'GET') === 'POST') {
|
|
386
|
+
try {
|
|
387
|
+
const buf = await readBody(req, maxBodyBytes);
|
|
388
|
+
body = buf.length > 0 ? JSON.parse(buf.toString()) : {};
|
|
389
|
+
}
|
|
390
|
+
catch (e) {
|
|
391
|
+
res.writeHead(400, { 'Content-Type': 'application/json' });
|
|
392
|
+
res.end(JSON.stringify({ error: e instanceof Error ? e.message : String(e) }));
|
|
393
|
+
return;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
if (agentRouter) {
|
|
397
|
+
const agentResult = await agentRouter.route(req.method || 'GET', url.pathname, body, url.search);
|
|
398
|
+
if (agentResult) {
|
|
399
|
+
if (agentResult.stream) {
|
|
400
|
+
res.writeHead(agentResult.status, agentResult.headers);
|
|
401
|
+
res.flushHeaders?.();
|
|
402
|
+
void (async () => {
|
|
403
|
+
try {
|
|
404
|
+
for await (const chunk of agentResult.stream) {
|
|
405
|
+
if (!res.writableEnded)
|
|
406
|
+
res.write(chunk);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
catch {
|
|
410
|
+
/* stream aborted */
|
|
411
|
+
}
|
|
412
|
+
finally {
|
|
413
|
+
if (!res.writableEnded)
|
|
414
|
+
res.end();
|
|
415
|
+
}
|
|
416
|
+
})();
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
res.writeHead(agentResult.status, agentResult.headers);
|
|
420
|
+
res.end(agentResult.encoding === 'base64' ? Buffer.from(agentResult.body, 'base64') : agentResult.body);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
const result = await devPanel.route(req.method || 'GET', url.pathname, body, url.search);
|
|
425
|
+
if (result) {
|
|
426
|
+
if (result.stream) {
|
|
427
|
+
res.writeHead(result.status, result.headers);
|
|
428
|
+
res.flushHeaders?.();
|
|
429
|
+
void (async () => {
|
|
430
|
+
try {
|
|
431
|
+
for await (const chunk of result.stream) {
|
|
432
|
+
if (!res.writableEnded)
|
|
433
|
+
res.write(chunk);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
catch {
|
|
437
|
+
/* stream aborted */
|
|
438
|
+
}
|
|
439
|
+
finally {
|
|
440
|
+
if (!res.writableEnded)
|
|
441
|
+
res.end();
|
|
442
|
+
}
|
|
443
|
+
})();
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
446
|
+
res.writeHead(result.status, result.headers);
|
|
447
|
+
res.end(result.encoding === 'base64' ? Buffer.from(result.body, 'base64') : result.body);
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
129
451
|
if (url.pathname === '/_vesk/hmr.js') {
|
|
130
452
|
const monorepoRoot = resolve(__dirname, '..', '..', '..');
|
|
131
453
|
const runtimeSrc = resolve(monorepoRoot, 'packages', 'runtime', 'dist');
|
|
@@ -195,7 +517,7 @@ export async function startDevServer(appDir, options) {
|
|
|
195
517
|
const contentType = headers['content-type'] || '';
|
|
196
518
|
let finalBody = body;
|
|
197
519
|
if (contentType.includes('text/html')) {
|
|
198
|
-
finalBody =
|
|
520
|
+
finalBody = injectDevScripts(body);
|
|
199
521
|
}
|
|
200
522
|
res.writeHead(response.status, headers);
|
|
201
523
|
res.end(finalBody);
|
|
@@ -223,9 +545,7 @@ export async function startDevServer(appDir, options) {
|
|
|
223
545
|
const mod = await import(`${handlerPath}?t=${ssrVersion}`);
|
|
224
546
|
const webRequest = makeWebRequest(req, url.href, maxBodyBytes);
|
|
225
547
|
const response = await mod.handle(webRequest);
|
|
226
|
-
|
|
227
|
-
res.writeHead(response.status, Object.fromEntries(response.headers));
|
|
228
|
-
res.end(body);
|
|
548
|
+
await deliverResponse(res, response);
|
|
229
549
|
}
|
|
230
550
|
catch (e) {
|
|
231
551
|
const message = e instanceof Error ? e.message : String(e);
|
|
@@ -250,7 +570,7 @@ export async function startDevServer(appDir, options) {
|
|
|
250
570
|
const contentType = headers['content-type'] || '';
|
|
251
571
|
let finalBody = body;
|
|
252
572
|
if (contentType.includes('text/html')) {
|
|
253
|
-
finalBody =
|
|
573
|
+
finalBody = injectDevScripts(body);
|
|
254
574
|
}
|
|
255
575
|
res.writeHead(response.status, headers);
|
|
256
576
|
res.end(finalBody);
|
|
@@ -277,7 +597,7 @@ export async function startDevServer(appDir, options) {
|
|
|
277
597
|
const contentType = headers['content-type'] || '';
|
|
278
598
|
let finalBody = body;
|
|
279
599
|
if (contentType.includes('text/html')) {
|
|
280
|
-
finalBody =
|
|
600
|
+
finalBody = injectDevScripts(body);
|
|
281
601
|
}
|
|
282
602
|
res.writeHead(200, headers);
|
|
283
603
|
res.end(finalBody);
|
|
@@ -294,6 +614,7 @@ export async function startDevServer(appDir, options) {
|
|
|
294
614
|
res.end('<!DOCTYPE html><html><body><h1>404</h1><p>Not Found</p></body></html>');
|
|
295
615
|
});
|
|
296
616
|
const hmr = createHmrServer(server, appDir, devDir, componentMap);
|
|
617
|
+
hmrSession = hmr;
|
|
297
618
|
const srcDir = resolve(appDir, '..', 'src');
|
|
298
619
|
try {
|
|
299
620
|
if (existsSync(srcDir)) {
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface CodeLine {
|
|
2
|
+
no: number;
|
|
3
|
+
text: string;
|
|
4
|
+
isError: boolean;
|
|
5
|
+
}
|
|
6
|
+
export interface Codeframe {
|
|
7
|
+
file: string;
|
|
8
|
+
line: number;
|
|
9
|
+
column: number;
|
|
10
|
+
context: number;
|
|
11
|
+
code: CodeLine[];
|
|
12
|
+
}
|
|
13
|
+
export declare function buildCodeframe(src: string, line: number, column?: number, context?: number): Codeframe | null;
|
|
14
|
+
export interface ErroredLocation {
|
|
15
|
+
file: string;
|
|
16
|
+
line: number | null;
|
|
17
|
+
column: number | null;
|
|
18
|
+
message: string;
|
|
19
|
+
stack: string | null;
|
|
20
|
+
codeframe: Codeframe | null;
|
|
21
|
+
}
|
|
22
|
+
export declare function parseCompilerError(err: unknown, file: string, src?: string): ErroredLocation | null;
|
|
23
|
+
//# sourceMappingURL=error-codeframe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-codeframe.d.ts","sourceRoot":"","sources":["../src/error-codeframe.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,QAAQ,EAAE,CAAC;CAClB;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,EAAE,OAAO,SAAI,GAAG,SAAS,GAAG,IAAI,CAcxG;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,SAAS,GAAG,IAAI,CAAC;CAC7B;AAuBD,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,eAAe,GAAG,IAAI,CAwFnG"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
export function buildCodeframe(src, line, column, context = 5) {
|
|
2
|
+
if (typeof src !== 'string' || src.length === 0)
|
|
3
|
+
return null;
|
|
4
|
+
if (typeof line !== 'number' || !Number.isInteger(line))
|
|
5
|
+
return null;
|
|
6
|
+
const lines = src.split('\n');
|
|
7
|
+
if (line < 1 || line > lines.length)
|
|
8
|
+
return null;
|
|
9
|
+
const col = typeof column === 'number' && Number.isInteger(column) && column >= 1 ? column : 1;
|
|
10
|
+
const window = typeof context === 'number' && Number.isFinite(context) && context >= 0 ? context : 5;
|
|
11
|
+
const start = Math.max(1, line - window);
|
|
12
|
+
const end = Math.min(lines.length, line + window);
|
|
13
|
+
const code = [];
|
|
14
|
+
for (let i = start; i <= end; i++) {
|
|
15
|
+
code.push({ no: i, text: lines[i - 1] ?? '', isError: i === line });
|
|
16
|
+
}
|
|
17
|
+
return { file: '', line, column: col, context: window, code };
|
|
18
|
+
}
|
|
19
|
+
const LOCATION_RE = /\((\d+):(\d+)\)/;
|
|
20
|
+
function asRecord(v) {
|
|
21
|
+
if (typeof v === 'object' && v !== null)
|
|
22
|
+
return v;
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
function asNumber(v) {
|
|
26
|
+
if (typeof v === 'number' && Number.isFinite(v))
|
|
27
|
+
return Math.trunc(v);
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
function parseEmbeddedLocation(message) {
|
|
31
|
+
const m = message.match(LOCATION_RE);
|
|
32
|
+
if (!m)
|
|
33
|
+
return null;
|
|
34
|
+
const line = parseInt(m[1], 10);
|
|
35
|
+
const column = parseInt(m[2], 10);
|
|
36
|
+
if (!Number.isFinite(line) || !Number.isFinite(column))
|
|
37
|
+
return null;
|
|
38
|
+
return { line, column: column + 1 };
|
|
39
|
+
}
|
|
40
|
+
export function parseCompilerError(err, file, src) {
|
|
41
|
+
if (err === undefined || err === null)
|
|
42
|
+
return null;
|
|
43
|
+
const record = asRecord(err);
|
|
44
|
+
let message;
|
|
45
|
+
let stack = null;
|
|
46
|
+
if (record && typeof record.message === 'string') {
|
|
47
|
+
message = record.message;
|
|
48
|
+
if (typeof record.stack === 'string')
|
|
49
|
+
stack = record.stack;
|
|
50
|
+
}
|
|
51
|
+
else if (typeof err === 'string') {
|
|
52
|
+
message = err;
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
try {
|
|
56
|
+
message = String(err);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
message = 'Unknown compiler error';
|
|
60
|
+
}
|
|
61
|
+
const asAny = err;
|
|
62
|
+
if (asAny && typeof asAny.stack === 'string')
|
|
63
|
+
stack = asAny.stack;
|
|
64
|
+
}
|
|
65
|
+
let line = null;
|
|
66
|
+
let column = null;
|
|
67
|
+
let fileResolved = typeof file === 'string' ? file : '';
|
|
68
|
+
// acorn raises VeskError with `.loc { line, column }` (column 0-based) and
|
|
69
|
+
// other codegen errors carry `.position` / `.pos` plus `.line`/`.column`
|
|
70
|
+
// fields on the VeskError class itself. Prefer explicit fields.
|
|
71
|
+
if (record) {
|
|
72
|
+
const loc = asRecord(record.loc);
|
|
73
|
+
if (loc) {
|
|
74
|
+
const ln = asNumber(loc.line);
|
|
75
|
+
if (ln !== null) {
|
|
76
|
+
line = ln;
|
|
77
|
+
const rawCol = asNumber(loc.column);
|
|
78
|
+
column = rawCol !== null ? rawCol + 1 : 1;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (line === null) {
|
|
82
|
+
const pos = asRecord(record.position);
|
|
83
|
+
if (pos) {
|
|
84
|
+
const ln = asNumber(pos.line);
|
|
85
|
+
if (ln !== null) {
|
|
86
|
+
line = ln;
|
|
87
|
+
const rawCol = asNumber(pos.column);
|
|
88
|
+
column = rawCol !== null ? rawCol + 1 : 1;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (line === null) {
|
|
93
|
+
const ln = asNumber(record.line);
|
|
94
|
+
if (ln !== null && ln > 0) {
|
|
95
|
+
line = ln;
|
|
96
|
+
const rawCol = asNumber(record.column);
|
|
97
|
+
if (rawCol !== null)
|
|
98
|
+
column = rawCol;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (typeof record.file === 'string' && record.file)
|
|
102
|
+
fileResolved = record.file;
|
|
103
|
+
}
|
|
104
|
+
// Fall back to the "(line:column)" embedded in the message text (column is
|
|
105
|
+
// 0-based in VeskError messages, matching acorn's loc).
|
|
106
|
+
if (line === null) {
|
|
107
|
+
const embedded = parseEmbeddedLocation(message);
|
|
108
|
+
if (embedded) {
|
|
109
|
+
line = embedded.line;
|
|
110
|
+
column = embedded.column;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
let codeframe = null;
|
|
114
|
+
if (src !== undefined && typeof src === 'string' && src.length > 0 && line !== null) {
|
|
115
|
+
codeframe = buildCodeframe(src, line, column ?? 1);
|
|
116
|
+
if (codeframe)
|
|
117
|
+
codeframe.file = fileResolved;
|
|
118
|
+
}
|
|
119
|
+
return {
|
|
120
|
+
file: fileResolved,
|
|
121
|
+
line,
|
|
122
|
+
column,
|
|
123
|
+
message,
|
|
124
|
+
stack,
|
|
125
|
+
codeframe,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-tips.d.ts","sourceRoot":"","sources":["../src/error-tips.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AA8FD,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAMrD"}
|