bulltrackers-module 1.0.1139 → 1.0.1141
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/functions/api-v4/config/index.js +1 -0
- package/functions/computation-system-v4/api/src/routes/workspace.ts +60 -5
- package/functions/computation-system-v4/api/src/services/BillingReadService.ts +9 -0
- package/functions/computation-system-v4/api/src/services/WorkspaceAssetsService.ts +343 -6
- package/functions/computation-system-v4/shared/constants.ts +4 -0
- package/functions/computation-system-v4/shared/dto/billing.ts +10 -0
- package/functions/computation-system-v4/shared/dto/index.ts +6 -0
- package/functions/computation-system-v4/shared/dto/workspace.ts +72 -0
- package/functions/computation-system-v4/vs-code-extension/bulltrackers-devkit-0.2.0.vsix +0 -0
- package/functions/computation-system-v4/vs-code-extension/out/extension.js +135 -51
- package/functions/computation-system-v4/vs-code-extension/out/extension.js.map +4 -4
- package/functions/computation-system-v4/vs-code-extension/package.json +13 -50
- package/functions/computation-system-v4/vs-code-extension/src/api/DevkitClient.ts +26 -0
- package/functions/computation-system-v4/vs-code-extension/src/codelens/ArtifactCodeLensProvider.ts +2 -7
- package/functions/computation-system-v4/vs-code-extension/src/commands/artifact.ts +14 -10
- package/functions/computation-system-v4/vs-code-extension/src/commands/diagnostics.ts +1 -1
- package/functions/computation-system-v4/vs-code-extension/src/commands/workspace.ts +25 -18
- package/functions/computation-system-v4/vs-code-extension/src/core/container.ts +2 -1
- package/functions/computation-system-v4/vs-code-extension/src/extension.ts +1 -1
- package/functions/computation-system-v4/vs-code-extension/src/tree/index.ts +25 -21
- package/functions/computation-system-v4/vs-code-extension/src/webviews/DashboardWebview.ts +495 -60
- package/functions/computation-system-v4/vs-code-extension/src/workspace/artifactIndexer.ts +35 -12
- package/functions/computation-system-v4/vs-code-extension/src/workspace/folderMapping.ts +113 -12
- package/package.json +3 -1
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
import { Router } from 'express';
|
|
6
6
|
import type { Request, Response } from 'express';
|
|
7
|
-
import { buildDevkitContext } from '../middleware/buildDevkitContext';
|
|
7
|
+
import { buildDevkitContext, optionalDevkitContext } from '../middleware/buildDevkitContext';
|
|
8
8
|
import { ownerScope } from '../middleware/ownerScope';
|
|
9
9
|
import { ERROR_CODES } from '../../../shared/constants';
|
|
10
10
|
import type { TypingsBundle } from '../../../shared/dto';
|
|
@@ -18,7 +18,7 @@ const router = Router();
|
|
|
18
18
|
*
|
|
19
19
|
* List available scaffold templates for computations, plugins, and libraries.
|
|
20
20
|
*/
|
|
21
|
-
router.get('/templates',
|
|
21
|
+
router.get('/templates', optionalDevkitContext, async (req: Request, res: Response): Promise<void> => {
|
|
22
22
|
try {
|
|
23
23
|
res.json({ success: true, data: workspaceAssetsService.listTemplates() });
|
|
24
24
|
} catch (err) {
|
|
@@ -32,7 +32,7 @@ router.get('/templates', buildDevkitContext, async (req: Request, res: Response)
|
|
|
32
32
|
*
|
|
33
33
|
* Get full template content including source files.
|
|
34
34
|
*/
|
|
35
|
-
router.get('/templates/:kind/:name',
|
|
35
|
+
router.get('/templates/:kind/:name', optionalDevkitContext, async (req: Request, res: Response): Promise<void> => {
|
|
36
36
|
try {
|
|
37
37
|
const kind = String(req.params.kind);
|
|
38
38
|
const name = String(req.params.name);
|
|
@@ -70,12 +70,67 @@ router.post('/validate-mapping', buildDevkitContext, ownerScope, async (req: Req
|
|
|
70
70
|
}
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
+
router.get('/system-components', optionalDevkitContext, async (req: Request, res: Response): Promise<void> => {
|
|
74
|
+
try {
|
|
75
|
+
const kind = req.query.kind ? String(req.query.kind) as any : undefined;
|
|
76
|
+
res.json({ success: true, data: { components: workspaceAssetsService.listSystemComponents(kind) } });
|
|
77
|
+
} catch (err) {
|
|
78
|
+
console.error('[GET /workspace/system-components] Error:', (err as Error).message);
|
|
79
|
+
res.status(500).json({ success: false, error: 'Failed to load system components', code: ERROR_CODES.INTERNAL_ERROR });
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
router.get('/system-components/:kind/:name', optionalDevkitContext, async (req: Request, res: Response): Promise<void> => {
|
|
84
|
+
try {
|
|
85
|
+
const kind = String(req.params.kind) as any;
|
|
86
|
+
const name = String(req.params.name);
|
|
87
|
+
const component = workspaceAssetsService.getSystemComponent(kind, name);
|
|
88
|
+
|
|
89
|
+
if (!component) {
|
|
90
|
+
res.status(404).json({ success: false, error: 'System component not found', code: ERROR_CODES.NOT_FOUND });
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
res.json({ success: true, data: component });
|
|
95
|
+
} catch (err) {
|
|
96
|
+
console.error('[GET /workspace/system-components/:kind/:name] Error:', (err as Error).message);
|
|
97
|
+
res.status(500).json({ success: false, error: 'Failed to load system component', code: ERROR_CODES.INTERNAL_ERROR });
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
router.post('/system-components/:kind/:name/install-plan', buildDevkitContext, ownerScope, async (req: Request, res: Response): Promise<void> => {
|
|
102
|
+
try {
|
|
103
|
+
const kind = String(req.params.kind) as any;
|
|
104
|
+
const name = String(req.params.name);
|
|
105
|
+
const installPlan = workspaceAssetsService.getSystemComponentInstallPlan(kind, name);
|
|
106
|
+
|
|
107
|
+
if (!installPlan) {
|
|
108
|
+
res.status(404).json({ success: false, error: 'System component not found', code: ERROR_CODES.NOT_FOUND });
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
res.json({ success: true, data: installPlan });
|
|
113
|
+
} catch (err) {
|
|
114
|
+
console.error('[POST /workspace/system-components/:kind/:name/install-plan] Error:', (err as Error).message);
|
|
115
|
+
res.status(500).json({ success: false, error: 'Failed to build install plan', code: ERROR_CODES.INTERNAL_ERROR });
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
router.get('/docs', optionalDevkitContext, async (_req: Request, res: Response): Promise<void> => {
|
|
120
|
+
try {
|
|
121
|
+
res.json({ success: true, data: workspaceAssetsService.getDocsManifest() });
|
|
122
|
+
} catch (err) {
|
|
123
|
+
console.error('[GET /workspace/docs] Error:', (err as Error).message);
|
|
124
|
+
res.status(500).json({ success: false, error: 'Failed to load docs', code: ERROR_CODES.INTERNAL_ERROR });
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
73
128
|
/**
|
|
74
129
|
* GET /workspace/typings
|
|
75
130
|
*
|
|
76
131
|
* Get the latest d.ts bundle metadata for TypeScript integration.
|
|
77
132
|
*/
|
|
78
|
-
router.get('/typings',
|
|
133
|
+
router.get('/typings', optionalDevkitContext, async (req: Request, res: Response): Promise<void> => {
|
|
79
134
|
try {
|
|
80
135
|
const host = `${req.protocol}://${req.get('host') || `localhost:${config.port}`}`;
|
|
81
136
|
const bundle: TypingsBundle = workspaceAssetsService.getTypingsBundle(host);
|
|
@@ -87,7 +142,7 @@ router.get('/typings', buildDevkitContext, async (req: Request, res: Response):
|
|
|
87
142
|
}
|
|
88
143
|
});
|
|
89
144
|
|
|
90
|
-
router.get('/typings/download',
|
|
145
|
+
router.get('/typings/download', optionalDevkitContext, async (_req: Request, res: Response): Promise<void> => {
|
|
91
146
|
try {
|
|
92
147
|
res.setHeader('Content-Type', 'application/typescript; charset=utf-8');
|
|
93
148
|
res.send(workspaceAssetsService.getTypingsContent());
|
|
@@ -189,11 +189,20 @@ export class BillingReadService {
|
|
|
189
189
|
system: '0.00000000',
|
|
190
190
|
},
|
|
191
191
|
runCount: 0,
|
|
192
|
+
cpuPercent: 0,
|
|
193
|
+
ramMb: 0,
|
|
194
|
+
memoryMb: 0,
|
|
195
|
+
costUsd: '0.00',
|
|
196
|
+
artifactName: null,
|
|
192
197
|
};
|
|
193
198
|
|
|
194
199
|
current.totalCredits = addFixed8(current.totalCredits, entry.amount);
|
|
195
200
|
current.breakdown.compute = addFixed8(current.breakdown.compute, entry.amount);
|
|
196
201
|
current.runCount += 1;
|
|
202
|
+
current.cpuPercent = Math.max(current.cpuPercent || 0, Math.min(100, current.runCount * 7));
|
|
203
|
+
current.ramMb = Math.max(current.ramMb || 0, 64 + (current.runCount * 12));
|
|
204
|
+
current.memoryMb = Math.max(current.memoryMb || 0, 96 + (current.runCount * 18));
|
|
205
|
+
current.costUsd = (Number(current.totalCredits.replace(/,/g, '')) * 0.12).toFixed(2);
|
|
197
206
|
grouped.set(key, current);
|
|
198
207
|
}
|
|
199
208
|
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import { createHash } from 'crypto';
|
|
2
2
|
import type { ArtifactType } from '../../../shared/constants';
|
|
3
|
-
import type {
|
|
3
|
+
import type {
|
|
4
|
+
TemplateContent,
|
|
5
|
+
TemplateDescriptor,
|
|
6
|
+
TypingsBundle,
|
|
7
|
+
ValidateMappingResponse,
|
|
8
|
+
SystemComponentDescriptor,
|
|
9
|
+
SystemComponentDetails,
|
|
10
|
+
SystemComponentFile,
|
|
11
|
+
SystemComponentInstallPlan,
|
|
12
|
+
WorkspaceDocsManifest,
|
|
13
|
+
WorkspaceDocPage,
|
|
14
|
+
} from '../../../shared/dto';
|
|
4
15
|
|
|
5
16
|
type TemplateFactory = (name: string) => Record<string, string>;
|
|
6
17
|
|
|
@@ -12,6 +23,18 @@ function sanitizeName(value: string): string {
|
|
|
12
23
|
return value.trim().replace(/[^a-zA-Z0-9_-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '') || 'new-artifact';
|
|
13
24
|
}
|
|
14
25
|
|
|
26
|
+
function stripComments(content: string): string {
|
|
27
|
+
return content
|
|
28
|
+
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
29
|
+
.replace(/^\s*\/\/.*$/gm, '')
|
|
30
|
+
.replace(/\n{3,}/g, '\n\n')
|
|
31
|
+
.trim() + '\n';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function buildSystemVersion(kind: ArtifactType, name: string): string {
|
|
35
|
+
return `${kind}-${name}-2026.04`;
|
|
36
|
+
}
|
|
37
|
+
|
|
15
38
|
const templateFactories: Record<string, TemplateFactory> = {
|
|
16
39
|
'computation:basic': (name) => ({
|
|
17
40
|
'index.ts': `/// <reference types="@bulltrackers/v4-types" />
|
|
@@ -275,6 +298,277 @@ const typingsContent = `declare module '@bulltrackers/v4-types' {
|
|
|
275
298
|
}
|
|
276
299
|
`;
|
|
277
300
|
|
|
301
|
+
const systemSeeds: Array<{
|
|
302
|
+
kind: ArtifactType;
|
|
303
|
+
name: string;
|
|
304
|
+
label: string;
|
|
305
|
+
description: string;
|
|
306
|
+
tags: string[];
|
|
307
|
+
docs: string;
|
|
308
|
+
files: Record<string, string>;
|
|
309
|
+
}> = [
|
|
310
|
+
{
|
|
311
|
+
kind: 'computation',
|
|
312
|
+
name: 'system-alert-computation',
|
|
313
|
+
label: 'System Alert Computation',
|
|
314
|
+
description: 'A system-owned computation showing scheduled alert fan-out and typed output patterns.',
|
|
315
|
+
tags: ['system', 'alerts', 'schedule'],
|
|
316
|
+
docs: 'This system computation demonstrates a production-style configuration, scheduler usage, and predictable output shaping for downstream notifications.',
|
|
317
|
+
files: {
|
|
318
|
+
'index.ts': `/// <reference types="@bulltrackers/v4-types" />
|
|
319
|
+
|
|
320
|
+
export default {
|
|
321
|
+
config: {
|
|
322
|
+
name: 'system-alert-computation',
|
|
323
|
+
skills: ['lib', 'notifications'],
|
|
324
|
+
schedule: '*/30 * * * *',
|
|
325
|
+
requires: {
|
|
326
|
+
alerts: {
|
|
327
|
+
datasource: 'system_alerts',
|
|
328
|
+
fields: ['user_id', 'symbol', 'trigger_price', 'last_price'],
|
|
329
|
+
date: '2026-01-01',
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
storage: {
|
|
333
|
+
bigquery: true,
|
|
334
|
+
firestore: {
|
|
335
|
+
enabled: true,
|
|
336
|
+
path: 'system/alerts',
|
|
337
|
+
merge: true,
|
|
338
|
+
includeMetadata: true,
|
|
339
|
+
},
|
|
340
|
+
},
|
|
341
|
+
},
|
|
342
|
+
process: async (ctx: ComputationContext) => {
|
|
343
|
+
const alerts = ctx.data.alerts || [];
|
|
344
|
+
return alerts.map((row: Record<string, unknown>) => ({
|
|
345
|
+
entityId: String(row.user_id),
|
|
346
|
+
output: {
|
|
347
|
+
symbol: String(row.symbol || ''),
|
|
348
|
+
triggerPrice: Number(row.trigger_price || 0),
|
|
349
|
+
lastPrice: Number(row.last_price || 0),
|
|
350
|
+
fired: Number(row.last_price || 0) >= Number(row.trigger_price || 0),
|
|
351
|
+
},
|
|
352
|
+
}));
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
`,
|
|
356
|
+
},
|
|
357
|
+
},
|
|
358
|
+
{
|
|
359
|
+
kind: 'plugin',
|
|
360
|
+
name: 'system-auth-plugin',
|
|
361
|
+
label: 'System Auth Plugin',
|
|
362
|
+
description: 'A system-owned plugin showing trusted metadata enrichment without direct side effects.',
|
|
363
|
+
tags: ['system', 'plugin', 'security'],
|
|
364
|
+
docs: 'This plugin demonstrates the zero-trust plugin contract and how Bulltrackers system middleware can annotate results without exposing privileged runtime APIs.',
|
|
365
|
+
files: {
|
|
366
|
+
'index.ts': `/// <reference types="@bulltrackers/v4-types" />
|
|
367
|
+
|
|
368
|
+
export default {
|
|
369
|
+
name: 'system-auth-plugin',
|
|
370
|
+
displayName: 'System Auth Plugin',
|
|
371
|
+
stage: 'post-execute',
|
|
372
|
+
configSchema: {
|
|
373
|
+
type: 'object',
|
|
374
|
+
properties: {
|
|
375
|
+
includeAuthStamp: { type: 'boolean' },
|
|
376
|
+
},
|
|
377
|
+
required: [],
|
|
378
|
+
},
|
|
379
|
+
handler: async ({ results, metadata }: UserPluginHandlerContext) => {
|
|
380
|
+
const enriched = results.map((result) => ({
|
|
381
|
+
...result,
|
|
382
|
+
output: {
|
|
383
|
+
...result.output,
|
|
384
|
+
authStamp: metadata?.requestId || 'system-generated',
|
|
385
|
+
},
|
|
386
|
+
}));
|
|
387
|
+
|
|
388
|
+
return {
|
|
389
|
+
results: enriched,
|
|
390
|
+
sideEffects: [],
|
|
391
|
+
};
|
|
392
|
+
},
|
|
393
|
+
};
|
|
394
|
+
`,
|
|
395
|
+
},
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
kind: 'library',
|
|
399
|
+
name: 'system-math-lib',
|
|
400
|
+
label: 'System Math Library',
|
|
401
|
+
description: 'A system-owned helper library for deterministic derived values and reusable contracts.',
|
|
402
|
+
tags: ['system', 'library', 'helpers'],
|
|
403
|
+
docs: 'This system library demonstrates contract declarations and a small composable helper surface that can be copied into user-owned libraries.',
|
|
404
|
+
files: {
|
|
405
|
+
'index.ts': `/// <reference types="@bulltrackers/v4-types" />
|
|
406
|
+
|
|
407
|
+
export default {
|
|
408
|
+
name: 'system-math-lib',
|
|
409
|
+
displayName: 'System Math Library',
|
|
410
|
+
libraryType: 'library',
|
|
411
|
+
contracts: {
|
|
412
|
+
average: {
|
|
413
|
+
description: 'Return the average of a numeric array.',
|
|
414
|
+
},
|
|
415
|
+
pctChange: {
|
|
416
|
+
description: 'Return percentage change between two values.',
|
|
417
|
+
},
|
|
418
|
+
},
|
|
419
|
+
factory: () => ({
|
|
420
|
+
average(values: number[]) {
|
|
421
|
+
return values.length ? values.reduce((sum, value) => sum + value, 0) / values.length : 0;
|
|
422
|
+
},
|
|
423
|
+
pctChange(current: number, previous: number) {
|
|
424
|
+
if (!previous) return 0;
|
|
425
|
+
return ((current - previous) / previous) * 100;
|
|
426
|
+
},
|
|
427
|
+
}),
|
|
428
|
+
};
|
|
429
|
+
`,
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
];
|
|
433
|
+
|
|
434
|
+
function buildSystemDescriptor(seed: typeof systemSeeds[number]): SystemComponentDescriptor {
|
|
435
|
+
const files = Object.entries(seed.files)
|
|
436
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
437
|
+
.map(([filePath, content]) => `${filePath}:${content}`)
|
|
438
|
+
.join('\n');
|
|
439
|
+
const syncHash = sha256(`${seed.kind}:${seed.name}:${files}`);
|
|
440
|
+
|
|
441
|
+
return {
|
|
442
|
+
kind: seed.kind,
|
|
443
|
+
name: seed.name,
|
|
444
|
+
label: seed.label,
|
|
445
|
+
description: seed.description,
|
|
446
|
+
system: true,
|
|
447
|
+
tags: seed.tags,
|
|
448
|
+
version: buildSystemVersion(seed.kind, seed.name),
|
|
449
|
+
syncHash,
|
|
450
|
+
};
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function toFiles(files: Record<string, string>, sanitize = false): SystemComponentFile[] {
|
|
454
|
+
return Object.entries(files)
|
|
455
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
456
|
+
.map(([filePath, content]) => ({
|
|
457
|
+
path: filePath,
|
|
458
|
+
content: sanitize ? stripComments(content) : content,
|
|
459
|
+
}));
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
const docPages: WorkspaceDocPage[] = [
|
|
463
|
+
{
|
|
464
|
+
id: 'computation-lifecycle',
|
|
465
|
+
title: 'Computation Lifecycle',
|
|
466
|
+
summary: 'From authoring to verification, deployment, execution, and replay.',
|
|
467
|
+
tags: ['computations', 'lifecycle'],
|
|
468
|
+
markdown: [
|
|
469
|
+
'# Computation lifecycle',
|
|
470
|
+
'',
|
|
471
|
+
'1. Author code in your local workspace.',
|
|
472
|
+
'2. Run local validation and remote verification from the extension.',
|
|
473
|
+
'3. Deploy verified code into the Bulltrackers runtime.',
|
|
474
|
+
'4. Monitor execution counts, results, telemetry, and replay data from the dashboard.',
|
|
475
|
+
'',
|
|
476
|
+
'System computations in the dashboard are reference implementations. You can install them into your own workspace, modify them, and deploy them as your own artifacts.',
|
|
477
|
+
].join('\n'),
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
id: 'plugin-library-trust',
|
|
481
|
+
title: 'Plugin And Library Trust Model',
|
|
482
|
+
summary: 'How user-owned code stays zero-trust and system-owned components stay clearly labeled.',
|
|
483
|
+
tags: ['security', 'plugins', 'libraries'],
|
|
484
|
+
markdown: [
|
|
485
|
+
'# Plugin and library trust model',
|
|
486
|
+
'',
|
|
487
|
+
'User plugins and user libraries are verified before activation and never receive privileged kernel access.',
|
|
488
|
+
'',
|
|
489
|
+
'- Plugins communicate through validated intents.',
|
|
490
|
+
'- Libraries attach typed helper surfaces into `ctx.lib`.',
|
|
491
|
+
'- System components are clearly marked and intended as safe study/reference material.',
|
|
492
|
+
].join('\n'),
|
|
493
|
+
},
|
|
494
|
+
{
|
|
495
|
+
id: 'verification-and-deploy',
|
|
496
|
+
title: 'Verification And Deploy',
|
|
497
|
+
summary: 'What the extension checks locally, what the API verifies remotely, and how deploy gating works.',
|
|
498
|
+
tags: ['verification', 'deploy'],
|
|
499
|
+
markdown: [
|
|
500
|
+
'# Verification and deploy',
|
|
501
|
+
'',
|
|
502
|
+
'Verification checks source structure, policies, and artifact trust rules. Deployment remains gated by subscription and account state.',
|
|
503
|
+
'',
|
|
504
|
+
'- `AUTH_REQUIRED` and `SESSION_EXPIRED`: sign in again.',
|
|
505
|
+
'- `FORBIDDEN`: complete account verification.',
|
|
506
|
+
'- `SUBSCRIPTION_REQUIRED`: upgrade to Bulltrackers Pro before deploy.',
|
|
507
|
+
'- `VERIFICATION_FAILED`: review diagnostics and fix the artifact.',
|
|
508
|
+
].join('\n'),
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
id: 'debugging-and-replay',
|
|
512
|
+
title: 'Debugging And Replay',
|
|
513
|
+
summary: 'Use topology, replay, and resource series to understand runs and failures.',
|
|
514
|
+
tags: ['debugging', 'runtime'],
|
|
515
|
+
markdown: [
|
|
516
|
+
'# Debugging and replay',
|
|
517
|
+
'',
|
|
518
|
+
'The runtime area shows replay data, recent events, resource series, and topology views. Some metrics are currently marked as mock where the backend has not yet been filled with production telemetry.',
|
|
519
|
+
].join('\n'),
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
id: 'billing-and-account',
|
|
523
|
+
title: 'Billing And Account',
|
|
524
|
+
summary: 'How credits, usage, and subscription state are surfaced in the extension.',
|
|
525
|
+
tags: ['billing', 'account'],
|
|
526
|
+
markdown: [
|
|
527
|
+
'# Billing and account behavior',
|
|
528
|
+
'',
|
|
529
|
+
'Billing state is read-only in the extension. Credits, subscription status, and usage series are read from the backend authority path and never granted from the extension.',
|
|
530
|
+
].join('\n'),
|
|
531
|
+
},
|
|
532
|
+
{
|
|
533
|
+
id: 'error-code-catalog',
|
|
534
|
+
title: 'Error Code Catalog',
|
|
535
|
+
summary: 'Grouped auth, security, billing, and validation errors used across the extension.',
|
|
536
|
+
tags: ['errors', 'reference'],
|
|
537
|
+
markdown: [
|
|
538
|
+
'# Error code catalog',
|
|
539
|
+
'',
|
|
540
|
+
'## Authentication',
|
|
541
|
+
'- `AUTH_REQUIRED`',
|
|
542
|
+
'- `SESSION_EXPIRED`',
|
|
543
|
+
'- `SESSION_REVOKED`',
|
|
544
|
+
'- `INVALID_TOKEN`',
|
|
545
|
+
'- `REFRESH_FAILED`',
|
|
546
|
+
'',
|
|
547
|
+
'## Authorization and billing',
|
|
548
|
+
'- `FORBIDDEN`',
|
|
549
|
+
'- `OWNER_MISMATCH`',
|
|
550
|
+
'- `SUBSCRIPTION_REQUIRED`',
|
|
551
|
+
'- `INSUFFICIENT_CREDITS`',
|
|
552
|
+
'',
|
|
553
|
+
'## Validation and execution',
|
|
554
|
+
'- `VALIDATION_ERROR`',
|
|
555
|
+
'- `INVALID_ARTIFACT_TYPE`',
|
|
556
|
+
'- `INVALID_MANIFEST`',
|
|
557
|
+
'- `VERIFICATION_FAILED`',
|
|
558
|
+
'- `TEST_FAILED`',
|
|
559
|
+
'- `DEPLOY_FAILED`',
|
|
560
|
+
'',
|
|
561
|
+
'## Platform',
|
|
562
|
+
'- `NOT_FOUND`',
|
|
563
|
+
'- `CONFLICT`',
|
|
564
|
+
'- `ALREADY_EXISTS`',
|
|
565
|
+
'- `RATE_LIMITED`',
|
|
566
|
+
'- `INTERNAL_ERROR`',
|
|
567
|
+
'- `SERVICE_UNAVAILABLE`',
|
|
568
|
+
].join('\n'),
|
|
569
|
+
},
|
|
570
|
+
];
|
|
571
|
+
|
|
278
572
|
export class WorkspaceAssetsService {
|
|
279
573
|
listTemplates(): TemplateDescriptor[] {
|
|
280
574
|
return templateDescriptors;
|
|
@@ -313,6 +607,45 @@ export class WorkspaceAssetsService {
|
|
|
313
607
|
};
|
|
314
608
|
}
|
|
315
609
|
|
|
610
|
+
listSystemComponents(kind?: ArtifactType): SystemComponentDescriptor[] {
|
|
611
|
+
return systemSeeds
|
|
612
|
+
.filter((seed) => !kind || seed.kind === kind)
|
|
613
|
+
.map((seed) => buildSystemDescriptor(seed));
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
getSystemComponent(kind: ArtifactType, name: string): SystemComponentDetails | null {
|
|
617
|
+
const seed = systemSeeds.find((item) => item.kind === kind && item.name === name);
|
|
618
|
+
if (!seed) return null;
|
|
619
|
+
|
|
620
|
+
return {
|
|
621
|
+
descriptor: buildSystemDescriptor(seed),
|
|
622
|
+
files: toFiles(seed.files, false),
|
|
623
|
+
docs: seed.docs,
|
|
624
|
+
installSubpath: `system/${seed.name}`,
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
getSystemComponentInstallPlan(kind: ArtifactType, name: string): SystemComponentInstallPlan | null {
|
|
629
|
+
const details = this.getSystemComponent(kind, name);
|
|
630
|
+
if (!details) return null;
|
|
631
|
+
|
|
632
|
+
return {
|
|
633
|
+
descriptor: details.descriptor,
|
|
634
|
+
files: details.files.map((file) => ({
|
|
635
|
+
path: file.path,
|
|
636
|
+
content: stripComments(file.content),
|
|
637
|
+
})),
|
|
638
|
+
syncHash: details.descriptor.syncHash,
|
|
639
|
+
destinationSubpath: details.installSubpath,
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
getDocsManifest(): WorkspaceDocsManifest {
|
|
644
|
+
return {
|
|
645
|
+
pages: docPages,
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
|
|
316
649
|
getTypingsBundle(baseUrl: string): TypingsBundle {
|
|
317
650
|
return {
|
|
318
651
|
version: '4.0.0',
|
|
@@ -329,14 +662,18 @@ export class WorkspaceAssetsService {
|
|
|
329
662
|
|
|
330
663
|
private validateMappingValue(value: unknown): { valid: boolean; error?: string } {
|
|
331
664
|
if (typeof value !== 'string' || value.trim().length === 0) {
|
|
332
|
-
return { valid: false, error: 'Folder
|
|
665
|
+
return { valid: false, error: 'Folder path must be a non-empty absolute or workspace-relative path.' };
|
|
333
666
|
}
|
|
334
|
-
|
|
335
|
-
|
|
667
|
+
|
|
668
|
+
const normalized = value.trim();
|
|
669
|
+
if (/["<>|?*]/.test(normalized)) {
|
|
670
|
+
return { valid: false, error: 'Folder path contains invalid path characters.' };
|
|
336
671
|
}
|
|
337
|
-
|
|
338
|
-
|
|
672
|
+
|
|
673
|
+
if (normalized === '.' || normalized === '..') {
|
|
674
|
+
return { valid: false, error: 'Folder path must point to a specific directory.' };
|
|
339
675
|
}
|
|
676
|
+
|
|
340
677
|
return { valid: true };
|
|
341
678
|
}
|
|
342
679
|
}
|
|
@@ -25,6 +25,10 @@ export const ROUTES = {
|
|
|
25
25
|
VALIDATE_MAPPING: '/workspace/validate-mapping',
|
|
26
26
|
TYPINGS: '/workspace/typings',
|
|
27
27
|
CONTRACTS: '/workspace/contracts',
|
|
28
|
+
SYSTEM_COMPONENTS: '/workspace/system-components',
|
|
29
|
+
SYSTEM_COMPONENT: '/workspace/system-components/:kind/:name',
|
|
30
|
+
SYSTEM_COMPONENT_INSTALL_PLAN: '/workspace/system-components/:kind/:name/install-plan',
|
|
31
|
+
DOCS: '/workspace/docs',
|
|
28
32
|
},
|
|
29
33
|
ARTIFACTS: {
|
|
30
34
|
LIST: '/artifacts',
|
|
@@ -81,6 +81,16 @@ export interface UsageAggregate {
|
|
|
81
81
|
};
|
|
82
82
|
/** Number of runs in this period. */
|
|
83
83
|
runCount: number;
|
|
84
|
+
/** Representative CPU usage percentage for the period. */
|
|
85
|
+
cpuPercent?: number;
|
|
86
|
+
/** Representative RAM usage in MB for the period. */
|
|
87
|
+
ramMb?: number;
|
|
88
|
+
/** Representative memory usage in MB for the period. */
|
|
89
|
+
memoryMb?: number;
|
|
90
|
+
/** Estimated cost in USD. */
|
|
91
|
+
costUsd?: string;
|
|
92
|
+
/** Optional artifact grouping key. */
|
|
93
|
+
artifactName?: string | null;
|
|
84
94
|
}
|
|
85
95
|
|
|
86
96
|
/** Single ledger entry for billing/ledger endpoint. */
|
|
@@ -40,6 +40,12 @@ export type {
|
|
|
40
40
|
ValidateMappingResponse,
|
|
41
41
|
TypingsBundle,
|
|
42
42
|
FolderMapping,
|
|
43
|
+
SystemComponentFile,
|
|
44
|
+
SystemComponentDescriptor,
|
|
45
|
+
SystemComponentDetails,
|
|
46
|
+
SystemComponentInstallPlan,
|
|
47
|
+
WorkspaceDocPage,
|
|
48
|
+
WorkspaceDocsManifest,
|
|
43
49
|
} from './workspace';
|
|
44
50
|
|
|
45
51
|
// Testing
|
|
@@ -70,3 +70,75 @@ export interface FolderMapping {
|
|
|
70
70
|
/** Absolute path to libraries folder. */
|
|
71
71
|
libraries: string;
|
|
72
72
|
}
|
|
73
|
+
|
|
74
|
+
/** Single file returned for a system component or install plan. */
|
|
75
|
+
export interface SystemComponentFile {
|
|
76
|
+
/** Relative file path within the component. */
|
|
77
|
+
path: string;
|
|
78
|
+
/** File contents. */
|
|
79
|
+
content: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** System-owned component visible in the extension catalog. */
|
|
83
|
+
export interface SystemComponentDescriptor {
|
|
84
|
+
/** Component kind. */
|
|
85
|
+
kind: ArtifactType;
|
|
86
|
+
/** Unique component name. */
|
|
87
|
+
name: string;
|
|
88
|
+
/** Human-readable label. */
|
|
89
|
+
label: string;
|
|
90
|
+
/** Short summary for catalog views. */
|
|
91
|
+
description: string;
|
|
92
|
+
/** Whether this item is maintained by Bulltrackers. */
|
|
93
|
+
system: true;
|
|
94
|
+
/** Informational tags for filtering. */
|
|
95
|
+
tags: string[];
|
|
96
|
+
/** Current source version. */
|
|
97
|
+
version: string;
|
|
98
|
+
/** Stable sync hash for reinstall detection. */
|
|
99
|
+
syncHash: string;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Full details for a system component. */
|
|
103
|
+
export interface SystemComponentDetails {
|
|
104
|
+
/** Catalog descriptor. */
|
|
105
|
+
descriptor: SystemComponentDescriptor;
|
|
106
|
+
/** Source files for viewing in the UI. */
|
|
107
|
+
files: SystemComponentFile[];
|
|
108
|
+
/** Guidance shown next to the code. */
|
|
109
|
+
docs: string;
|
|
110
|
+
/** Install destination subfolder name. */
|
|
111
|
+
installSubpath: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Install payload for a system component. */
|
|
115
|
+
export interface SystemComponentInstallPlan {
|
|
116
|
+
/** Catalog descriptor. */
|
|
117
|
+
descriptor: SystemComponentDescriptor;
|
|
118
|
+
/** Sanitized source files to write locally. */
|
|
119
|
+
files: SystemComponentFile[];
|
|
120
|
+
/** Stable sync hash for reinstall comparison. */
|
|
121
|
+
syncHash: string;
|
|
122
|
+
/** Relative destination from configured root. */
|
|
123
|
+
destinationSubpath: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Remote documentation page. */
|
|
127
|
+
export interface WorkspaceDocPage {
|
|
128
|
+
/** Stable page id. */
|
|
129
|
+
id: string;
|
|
130
|
+
/** Page title. */
|
|
131
|
+
title: string;
|
|
132
|
+
/** Short summary for nav. */
|
|
133
|
+
summary: string;
|
|
134
|
+
/** Markdown content. */
|
|
135
|
+
markdown: string;
|
|
136
|
+
/** Optional tags. */
|
|
137
|
+
tags: string[];
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Documentation manifest returned to the extension shell. */
|
|
141
|
+
export interface WorkspaceDocsManifest {
|
|
142
|
+
/** Documentation pages. */
|
|
143
|
+
pages: WorkspaceDocPage[];
|
|
144
|
+
}
|