@duckcodeailabs/dql-cli 1.0.4 → 1.2.2
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/args.d.ts +1 -0
- package/dist/args.d.ts.map +1 -1
- package/dist/args.js +4 -0
- package/dist/args.js.map +1 -1
- package/dist/assets/dql-notebook/assets/index-DWPIGGBJ.js +628 -0
- package/dist/assets/dql-notebook/index.html +1 -1
- package/dist/commands/app.d.ts +3 -0
- package/dist/commands/app.d.ts.map +1 -0
- package/dist/commands/app.js +191 -0
- package/dist/commands/app.js.map +1 -0
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +30 -2
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/fmt.d.ts.map +1 -1
- package/dist/commands/fmt.js +26 -9
- package/dist/commands/fmt.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +1 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/mcp.d.ts +7 -0
- package/dist/commands/mcp.d.ts.map +1 -0
- package/dist/commands/mcp.js +16 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/schedule.d.ts +3 -0
- package/dist/commands/schedule.d.ts.map +1 -0
- package/dist/commands/schedule.js +215 -0
- package/dist/commands/schedule.js.map +1 -0
- package/dist/digest.d.ts +10 -0
- package/dist/digest.d.ts.map +1 -0
- package/dist/digest.js +83 -0
- package/dist/digest.js.map +1 -0
- package/dist/index.js +16 -1
- package/dist/index.js.map +1 -1
- package/dist/llm/index.d.ts +4 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +16 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/llm/providers/claude-agent-sdk.d.ts +3 -0
- package/dist/llm/providers/claude-agent-sdk.d.ts.map +1 -0
- package/dist/llm/providers/claude-agent-sdk.js +174 -0
- package/dist/llm/providers/claude-agent-sdk.js.map +1 -0
- package/dist/llm/providers/claude-code.d.ts +8 -0
- package/dist/llm/providers/claude-code.d.ts.map +1 -0
- package/dist/llm/providers/claude-code.js +171 -0
- package/dist/llm/providers/claude-code.js.map +1 -0
- package/dist/llm/tools.d.ts +9 -0
- package/dist/llm/tools.d.ts.map +1 -0
- package/dist/llm/tools.js +112 -0
- package/dist/llm/tools.js.map +1 -0
- package/dist/llm/types.d.ts +70 -0
- package/dist/llm/types.d.ts.map +1 -0
- package/dist/llm/types.js +2 -0
- package/dist/llm/types.js.map +1 -0
- package/dist/local-runtime.d.ts +6 -0
- package/dist/local-runtime.d.ts.map +1 -1
- package/dist/local-runtime.js +174 -3
- package/dist/local-runtime.js.map +1 -1
- package/dist/schedule/alerts.d.ts +5 -0
- package/dist/schedule/alerts.d.ts.map +1 -0
- package/dist/schedule/alerts.js +54 -0
- package/dist/schedule/alerts.js.map +1 -0
- package/dist/schedule/discovery.d.ts +4 -0
- package/dist/schedule/discovery.d.ts.map +1 -0
- package/dist/schedule/discovery.js +36 -0
- package/dist/schedule/discovery.js.map +1 -0
- package/dist/schedule/notifiers/email.d.ts +3 -0
- package/dist/schedule/notifiers/email.d.ts.map +1 -0
- package/dist/schedule/notifiers/email.js +76 -0
- package/dist/schedule/notifiers/email.js.map +1 -0
- package/dist/schedule/notifiers/file.d.ts +3 -0
- package/dist/schedule/notifiers/file.d.ts.map +1 -0
- package/dist/schedule/notifiers/file.js +50 -0
- package/dist/schedule/notifiers/file.js.map +1 -0
- package/dist/schedule/notifiers/index.d.ts +10 -0
- package/dist/schedule/notifiers/index.d.ts.map +1 -0
- package/dist/schedule/notifiers/index.js +33 -0
- package/dist/schedule/notifiers/index.js.map +1 -0
- package/dist/schedule/notifiers/slack.d.ts +3 -0
- package/dist/schedule/notifiers/slack.d.ts.map +1 -0
- package/dist/schedule/notifiers/slack.js +58 -0
- package/dist/schedule/notifiers/slack.js.map +1 -0
- package/dist/schedule/runner.d.ts +11 -0
- package/dist/schedule/runner.d.ts.map +1 -0
- package/dist/schedule/runner.js +109 -0
- package/dist/schedule/runner.js.map +1 -0
- package/dist/schedule/runs.d.ts +5 -0
- package/dist/schedule/runs.d.ts.map +1 -0
- package/dist/schedule/runs.js +41 -0
- package/dist/schedule/runs.js.map +1 -0
- package/dist/schedule/service.d.ts +12 -0
- package/dist/schedule/service.d.ts.map +1 -0
- package/dist/schedule/service.js +49 -0
- package/dist/schedule/service.js.map +1 -0
- package/dist/schedule/types.d.ts +64 -0
- package/dist/schedule/types.d.ts.map +1 -0
- package/dist/schedule/types.js +2 -0
- package/dist/schedule/types.js.map +1 -0
- package/package.json +16 -10
- package/dist/assets/dql-notebook/assets/index-dZVjj9xj.js +0 -623
package/dist/local-runtime.js
CHANGED
|
@@ -4,7 +4,9 @@ import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, wat
|
|
|
4
4
|
import { dirname, extname, join, normalize, relative, resolve } from 'node:path';
|
|
5
5
|
import { buildExecutionPlan, createWelcomeNotebook, deserializeNotebook, getConnectorFormSchemas, hasSemanticRefs, resolveSemanticRefs, } from '@duckcodeailabs/dql-notebook';
|
|
6
6
|
import { loadSemanticLayerFromDir, resolveSemanticLayerAsync, Parser, buildLineageGraph, buildManifest, analyzeImpact, buildTrustChain, detectDomainFlows, getDomainTrustOverview, queryLineage, queryCompleteLineagePaths, LineageGraph, canonicalize, canonicalizeNotebook, diffDQL, diffNotebook, } from '@duckcodeailabs/dql-core';
|
|
7
|
+
import { load as loadYaml } from 'js-yaml';
|
|
7
8
|
import { listBlockTemplates } from './block-templates.js';
|
|
9
|
+
import { getRunner as getLLMRunner } from './llm/index.js';
|
|
8
10
|
import { buildSemanticObjectDetail, buildSemanticTree, computeSyncDiff, loadSemanticImportManifest, performSemanticImport, previewSemanticImport, syncSemanticImport, } from './semantic-import.js';
|
|
9
11
|
export async function startLocalServer(opts) {
|
|
10
12
|
const { rootDir, executor, connection: rawConnection, preferredPort, projectRoot = process.cwd() } = opts;
|
|
@@ -304,8 +306,11 @@ export async function startLocalServer(opts) {
|
|
|
304
306
|
res.end(serializeJSON(merged));
|
|
305
307
|
}
|
|
306
308
|
catch (error) {
|
|
307
|
-
|
|
308
|
-
|
|
309
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
310
|
+
console.warn(`[dql] /api/schema introspection failed: ${message}`);
|
|
311
|
+
const fallback = scanDataFiles(projectRoot).map((f) => ({ ...f, source: 'file' }));
|
|
312
|
+
res.writeHead(500, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
313
|
+
res.end(serializeJSON({ error: message, fallback }));
|
|
309
314
|
}
|
|
310
315
|
return;
|
|
311
316
|
}
|
|
@@ -344,7 +349,7 @@ export async function startLocalServer(opts) {
|
|
|
344
349
|
if (req.method === 'POST' && path === '/api/blocks/save-from-cell') {
|
|
345
350
|
try {
|
|
346
351
|
const body = await readJSON(req);
|
|
347
|
-
const { name, domain, owner, content, description, tags, metricRefs, template, } = body;
|
|
352
|
+
const { name, domain, owner, content, description, tags, metricRefs, template, llmContext, examples, invariants, } = body;
|
|
348
353
|
if (!name || typeof name !== 'string' || !content || typeof content !== 'string') {
|
|
349
354
|
res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
350
355
|
res.end(serializeJSON({ error: 'name and content are required' }));
|
|
@@ -374,6 +379,9 @@ export async function startLocalServer(opts) {
|
|
|
374
379
|
tags,
|
|
375
380
|
metricRefs,
|
|
376
381
|
template,
|
|
382
|
+
llmContext,
|
|
383
|
+
examples,
|
|
384
|
+
invariants,
|
|
377
385
|
gitMetadata: readGitMetadata(projectRoot),
|
|
378
386
|
});
|
|
379
387
|
res.writeHead(201, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
@@ -422,6 +430,7 @@ export async function startLocalServer(opts) {
|
|
|
422
430
|
const parsedTags = tagsMatch
|
|
423
431
|
? tagsMatch[1].split(',').map((tag) => tag.trim().replace(/^"|"$/g, '')).filter(Boolean)
|
|
424
432
|
: [];
|
|
433
|
+
const llmMatch = /llmContext\s*=\s*"((?:[^"\\]|\\.)*)"/.exec(source);
|
|
425
434
|
blocks.push({
|
|
426
435
|
name: nameMatch?.[1] ?? entry.name.replace('.dql', ''),
|
|
427
436
|
domain: domainMatch?.[1] ?? 'uncategorized',
|
|
@@ -431,6 +440,7 @@ export async function startLocalServer(opts) {
|
|
|
431
440
|
path: relPath,
|
|
432
441
|
lastModified: stat.mtime.toISOString(),
|
|
433
442
|
description: descMatch?.[1] ?? '',
|
|
443
|
+
llmContext: llmMatch?.[1] ?? null,
|
|
434
444
|
});
|
|
435
445
|
}
|
|
436
446
|
catch { /* skip unreadable files */ }
|
|
@@ -449,6 +459,58 @@ export async function startLocalServer(opts) {
|
|
|
449
459
|
}
|
|
450
460
|
return;
|
|
451
461
|
}
|
|
462
|
+
// ── Apps (App artifact listing for notebook AppsPanel) ────────────────
|
|
463
|
+
if (req.method === 'GET' && path === '/api/apps') {
|
|
464
|
+
try {
|
|
465
|
+
const appsRoot = join(projectRoot, 'apps');
|
|
466
|
+
const apps = [];
|
|
467
|
+
const listFilesByExt = (dir, ext) => {
|
|
468
|
+
const out = [];
|
|
469
|
+
try {
|
|
470
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
471
|
+
const full = join(dir, entry.name);
|
|
472
|
+
if (entry.isDirectory()) {
|
|
473
|
+
out.push(...listFilesByExt(full, ext).map((n) => `${entry.name}/${n}`));
|
|
474
|
+
}
|
|
475
|
+
else if (entry.isFile() && entry.name.endsWith(ext)) {
|
|
476
|
+
out.push(entry.name);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
catch { /* dir missing; return [] */ }
|
|
481
|
+
return out;
|
|
482
|
+
};
|
|
483
|
+
if (existsSync(appsRoot)) {
|
|
484
|
+
for (const entry of readdirSync(appsRoot, { withFileTypes: true })) {
|
|
485
|
+
if (!entry.isDirectory() || !entry.name.endsWith('.dql-app'))
|
|
486
|
+
continue;
|
|
487
|
+
const appDir = join(appsRoot, entry.name);
|
|
488
|
+
try {
|
|
489
|
+
const raw = readFileSync(join(appDir, 'app.yml'), 'utf-8');
|
|
490
|
+
const manifest = loadYaml(raw);
|
|
491
|
+
if (!manifest || !manifest.name || !manifest.domain)
|
|
492
|
+
continue;
|
|
493
|
+
apps.push({
|
|
494
|
+
path: relative(projectRoot, appDir),
|
|
495
|
+
manifest,
|
|
496
|
+
notebooks: listFilesByExt(join(appDir, 'notebooks'), '.dqlnb'),
|
|
497
|
+
dashboards: listFilesByExt(join(appDir, 'dashboards'), '.dql'),
|
|
498
|
+
hasDigest: existsSync(join(appDir, 'digest.dql')),
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
catch { /* skip unreadable apps */ }
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
apps.sort((a, b) => a.manifest.name.localeCompare(b.manifest.name));
|
|
505
|
+
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
506
|
+
res.end(serializeJSON({ apps }));
|
|
507
|
+
}
|
|
508
|
+
catch (error) {
|
|
509
|
+
res.writeHead(500, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
510
|
+
res.end(serializeJSON({ error: error instanceof Error ? error.message : String(error) }));
|
|
511
|
+
}
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
452
514
|
// ── Block status update ──────────────────────────────────────────────
|
|
453
515
|
if (req.method === 'POST' && path === '/api/blocks/status') {
|
|
454
516
|
try {
|
|
@@ -512,6 +574,51 @@ export async function startLocalServer(opts) {
|
|
|
512
574
|
}
|
|
513
575
|
return;
|
|
514
576
|
}
|
|
577
|
+
// ── Block body (re-read from disk, used by bound-cell refresh) ──────
|
|
578
|
+
if (req.method === 'GET' && path === '/api/blocks/body') {
|
|
579
|
+
try {
|
|
580
|
+
const blockPath = url.searchParams.get('path');
|
|
581
|
+
if (!blockPath) {
|
|
582
|
+
res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
583
|
+
res.end(serializeJSON({ error: 'path parameter is required' }));
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
const absolutePath = resolve(projectRoot, blockPath);
|
|
587
|
+
if (!absolutePath.startsWith(projectRoot + '/') && absolutePath !== projectRoot) {
|
|
588
|
+
res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
589
|
+
res.end(serializeJSON({ error: 'path escapes project root' }));
|
|
590
|
+
return;
|
|
591
|
+
}
|
|
592
|
+
if (!existsSync(absolutePath)) {
|
|
593
|
+
res.writeHead(404, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
594
|
+
res.end(serializeJSON({ error: 'block not found' }));
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
const body = readFileSync(absolutePath, 'utf-8');
|
|
598
|
+
let commitSha = null;
|
|
599
|
+
try {
|
|
600
|
+
const { execSync } = await import('node:child_process');
|
|
601
|
+
const sha = execSync(`git log -1 --format=%H -- "${blockPath}"`, {
|
|
602
|
+
cwd: projectRoot,
|
|
603
|
+
encoding: 'utf-8',
|
|
604
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
605
|
+
timeout: 5000,
|
|
606
|
+
}).trim();
|
|
607
|
+
commitSha = sha.length > 0 ? sha : null;
|
|
608
|
+
}
|
|
609
|
+
catch {
|
|
610
|
+
commitSha = null;
|
|
611
|
+
}
|
|
612
|
+
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
613
|
+
res.end(serializeJSON({ path: blockPath, body, commitSha }));
|
|
614
|
+
}
|
|
615
|
+
catch (error) {
|
|
616
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
617
|
+
res.writeHead(500, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
618
|
+
res.end(serializeJSON({ error: message }));
|
|
619
|
+
}
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
515
622
|
// ── Run block tests ────────────────────────────────────────────────
|
|
516
623
|
if (req.method === 'POST' && path === '/api/blocks/run-tests') {
|
|
517
624
|
try {
|
|
@@ -1293,6 +1400,42 @@ export async function startLocalServer(opts) {
|
|
|
1293
1400
|
}
|
|
1294
1401
|
return;
|
|
1295
1402
|
}
|
|
1403
|
+
if (req.method === 'POST' && path === '/api/llm/run') {
|
|
1404
|
+
const body = await readJSON(req).catch(() => null);
|
|
1405
|
+
if (!body || typeof body !== 'object') {
|
|
1406
|
+
res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
1407
|
+
res.end(serializeJSON({ error: 'Invalid JSON body' }));
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1410
|
+
const { provider, messages, upstream } = body;
|
|
1411
|
+
const runner = provider === 'claude-agent-sdk' || provider === 'claude-code' ? getLLMRunner(provider) : null;
|
|
1412
|
+
if (!runner) {
|
|
1413
|
+
res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
1414
|
+
res.end(serializeJSON({ error: `Unknown provider: ${provider}` }));
|
|
1415
|
+
return;
|
|
1416
|
+
}
|
|
1417
|
+
if (!Array.isArray(messages) || messages.length === 0) {
|
|
1418
|
+
res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
1419
|
+
res.end(serializeJSON({ error: 'messages[] required' }));
|
|
1420
|
+
return;
|
|
1421
|
+
}
|
|
1422
|
+
res.writeHead(200, {
|
|
1423
|
+
'Content-Type': 'text/event-stream',
|
|
1424
|
+
'Cache-Control': 'no-cache, no-transform',
|
|
1425
|
+
Connection: 'keep-alive',
|
|
1426
|
+
});
|
|
1427
|
+
const controller = new AbortController();
|
|
1428
|
+
req.on('close', () => controller.abort());
|
|
1429
|
+
const emit = (turn) => { res.write(`data: ${JSON.stringify(turn)}\n\n`); };
|
|
1430
|
+
try {
|
|
1431
|
+
await runner.run({ provider: provider, messages, upstream, projectRoot }, emit, controller.signal);
|
|
1432
|
+
}
|
|
1433
|
+
catch (err) {
|
|
1434
|
+
emit({ kind: 'error', message: err instanceof Error ? err.message : String(err) });
|
|
1435
|
+
}
|
|
1436
|
+
res.end();
|
|
1437
|
+
return;
|
|
1438
|
+
}
|
|
1296
1439
|
if (req.method === 'POST' && path === '/api/query') {
|
|
1297
1440
|
try {
|
|
1298
1441
|
const body = await readJSON(req);
|
|
@@ -2826,6 +2969,9 @@ export function createBlockArtifacts(projectRoot, options) {
|
|
|
2826
2969
|
owner: options.owner,
|
|
2827
2970
|
description: options.description,
|
|
2828
2971
|
tags: options.tags,
|
|
2972
|
+
llmContext: options.llmContext,
|
|
2973
|
+
examples: options.examples,
|
|
2974
|
+
invariants: options.invariants,
|
|
2829
2975
|
content: options.content?.trim() || templateContent,
|
|
2830
2976
|
}));
|
|
2831
2977
|
writeFileSync(blockPath, fileContent, 'utf-8');
|
|
@@ -3069,6 +3215,9 @@ function normalizeBlockStudioContent(options) {
|
|
|
3069
3215
|
owner: options.owner,
|
|
3070
3216
|
description: options.description,
|
|
3071
3217
|
tags: options.tags,
|
|
3218
|
+
llmContext: options.llmContext,
|
|
3219
|
+
examples: options.examples,
|
|
3220
|
+
invariants: options.invariants,
|
|
3072
3221
|
sql: content || 'SELECT 1 AS value',
|
|
3073
3222
|
});
|
|
3074
3223
|
}
|
|
@@ -3081,6 +3230,28 @@ function buildBlankBlockContent(options) {
|
|
|
3081
3230
|
` owner = "${escapeDqlString(options.owner?.trim() ?? '')}"`,
|
|
3082
3231
|
];
|
|
3083
3232
|
lines.push(` tags = [${(options.tags ?? []).map((tag) => `"${escapeDqlString(tag)}"`).join(', ')}]`);
|
|
3233
|
+
if (options.llmContext && options.llmContext.trim()) {
|
|
3234
|
+
lines.push(` llmContext = "${escapeDqlString(options.llmContext.trim())}"`);
|
|
3235
|
+
}
|
|
3236
|
+
if (options.invariants && options.invariants.length > 0) {
|
|
3237
|
+
lines.push(` invariants = [${options.invariants
|
|
3238
|
+
.filter((inv) => inv && inv.trim())
|
|
3239
|
+
.map((inv) => `"${escapeDqlString(inv.trim())}"`)
|
|
3240
|
+
.join(', ')}]`);
|
|
3241
|
+
}
|
|
3242
|
+
if (options.examples && options.examples.length > 0) {
|
|
3243
|
+
const items = options.examples.filter((ex) => ex.question && ex.question.trim());
|
|
3244
|
+
if (items.length > 0) {
|
|
3245
|
+
lines.push(' examples = [');
|
|
3246
|
+
for (const ex of items) {
|
|
3247
|
+
const parts = [`question = "${escapeDqlString(ex.question.trim())}"`];
|
|
3248
|
+
if (ex.sql && ex.sql.trim())
|
|
3249
|
+
parts.push(`sql = "${escapeDqlString(ex.sql.trim())}"`);
|
|
3250
|
+
lines.push(` { ${parts.join(', ')} },`);
|
|
3251
|
+
}
|
|
3252
|
+
lines.push(' ]');
|
|
3253
|
+
}
|
|
3254
|
+
}
|
|
3084
3255
|
lines.push('');
|
|
3085
3256
|
lines.push(' query = """');
|
|
3086
3257
|
lines.push(...indentBlock(options.sql.trim(), 8).split('\n'));
|