tina4-nodejs 3.13.100 → 3.13.103

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.
@@ -0,0 +1,66 @@
1
+ export declare class AiError extends Error {
2
+ }
3
+ export declare class AiConfigError extends AiError {
4
+ }
5
+ export declare class AiTimeoutError extends AiError {
6
+ }
7
+ export declare class AiParseError extends AiError {
8
+ }
9
+ export declare class AiHTTPError extends AiError {
10
+ readonly status: number | null;
11
+ constructor(message: string, status?: number | null);
12
+ }
13
+ export interface ChatResponse {
14
+ text: string;
15
+ model: string;
16
+ usage: {
17
+ promptTokens: number;
18
+ completionTokens: number;
19
+ totalTokens: number;
20
+ };
21
+ finishReason: string | null;
22
+ raw: Record<string, unknown>;
23
+ }
24
+ export interface AiMessage {
25
+ role: "system" | "user" | "assistant";
26
+ content: string;
27
+ }
28
+ export interface AiChatOptions {
29
+ model?: string;
30
+ temperature?: number;
31
+ maxTokens?: number;
32
+ stream?: boolean;
33
+ timeout?: number;
34
+ provider?: "local" | "openai" | "anthropic";
35
+ }
36
+ export interface AiEmbedOptions {
37
+ model?: string;
38
+ timeout?: number;
39
+ provider?: "local" | "openai" | "anthropic";
40
+ }
41
+ export declare class Ai {
42
+ static chat(messages: AiMessage[], options: AiChatOptions & {
43
+ stream: true;
44
+ }): AsyncGenerator<string>;
45
+ static chat(messages: AiMessage[], options?: AiChatOptions & {
46
+ stream?: false;
47
+ }): Promise<ChatResponse>;
48
+ static complete(prompt: string, options?: Omit<AiChatOptions, "stream">): Promise<string>;
49
+ static embed(textOrTexts: string | string[], options?: AiEmbedOptions): Promise<number[] | number[][]>;
50
+ private static validateMessages;
51
+ private static number;
52
+ private static config;
53
+ private static endpoint;
54
+ private static headers;
55
+ private static chatBody;
56
+ private static open;
57
+ private static readBody;
58
+ private static retryDelay;
59
+ private static requestJson;
60
+ private static normalizeChat;
61
+ private static chatResponse;
62
+ private static streamDelta;
63
+ private static streamData;
64
+ private static streamError;
65
+ private static streamRequest;
66
+ }
@@ -55,6 +55,8 @@ export { HtmlElement, htmlElement, addHtmlHelpers, Raw, SafeString } from "./htm
55
55
  export { renderErrorOverlay, isDebugMode } from "./errorOverlay.js";
56
56
  export { AI_TOOLS, isInstalled, showMenu, installSelected, installAll, generateContext } from "./ai.js";
57
57
  export type { AiTool } from "./ai.js";
58
+ export { Ai, AiError, AiConfigError, AiHTTPError, AiTimeoutError, AiParseError } from "./aiClient.js";
59
+ export type { ChatResponse, AiMessage, AiChatOptions, AiEmbedOptions } from "./aiClient.js";
58
60
  export type { ImapMessage, ImapFullMessage, ImapAttachment } from "./messenger.js";
59
61
  export { LiteBackend } from "./queueBackends/liteBackend.js";
60
62
  export { RabbitMQBackend, parseAmqpUrl } from "./queueBackends/rabbitmqBackend.js";
@@ -1,41 +1,6 @@
1
- export declare function quickMetrics(root?: string): Record<string, any>;
2
- /**
3
- * The native metrics engine could not produce a payload.
4
- *
5
- * Thrown instead of falling back to a second implementation.
6
- */
7
1
  export declare class MetricsEngineError extends Error {
8
2
  constructor(message: string);
9
3
  }
10
- export declare const SEVERITY_RANK: Record<string, number>;
11
- /**
12
- * Return [directory to scan, scanMode] for any metrics producer.
13
- *
14
- * The engine is language-agnostic and cannot know which directory holds a
15
- * framework package, so root resolution and the "framework" label stay here,
16
- * shared by the census and the engine adapter so the two never disagree.
17
- */
18
- export declare function resolveScanTarget(root?: string): [string, string];
19
- /** Absolute path to the tina4 CLI binary, or null when it is not installed. */
20
4
  export declare function enginePath(): string | null;
21
- /** Full code analysis from the native engine, shaped for the dashboard. */
22
5
  export declare function fullAnalysis(root?: string): Record<string, any>;
23
- export interface OffendersResult {
24
- offenders: Record<string, any>[];
25
- summary: Record<string, any>;
26
- }
27
- /**
28
- * Top code-health offenders from the native engine.
29
- *
30
- * The engine ranks and severity-tags them, and its own --fail-on gate reads the
31
- * same list, so the CLI and the dashboard can never disagree about what counts
32
- * as an offender.
33
- */
34
- export declare function offenders(root?: string, top?: number): OffendersResult;
35
- /**
36
- * Per-file metrics from the native engine.
37
- *
38
- * The engine accepts a single file for --path, so one code path serves both the
39
- * whole-tree scan and one file.
40
- */
41
6
  export declare function fileDetail(filePath: string): Record<string, any>;
@@ -36,8 +36,8 @@ export declare const pathParseCache: Map<string, [string[], boolean[]]>;
36
36
  */
37
37
  export declare const TEMPLATE_CACHE_MAX = 256;
38
38
  /**
39
- * Hard cap on every per-expression memo cache — `filterChainCache` and
40
- * `pathParseCache` (ADR-0004, parity with PHP's MEMO_CACHE_MAX and the
39
+ * Hard cap on every per-expression memo cache — `filterChainCache`,
40
+ * `pathParseCache`, and `expressionFormCache` (ADR-0004, parity with PHP's MEMO_CACHE_MAX and the
41
41
  * Python master's `@lru_cache(maxsize=1024)` on the equivalent module-level
42
42
  * parsers). Deliberately higher than TEMPLATE_CACHE_MAX: one entry here is a
43
43
  * small parsed-path array, orders of magnitude smaller than a token list.
@@ -47,6 +47,8 @@ export declare const TEMPLATE_CACHE_MAX = 256;
47
47
  * string, the same order of magnitude as a compiled template.
48
48
  */
49
49
  export declare const MEMO_CACHE_MAX = 1024;
50
+ /** Cached expression dispatcher branch; exported only for cache-bound verification. */
51
+ export declare const expressionFormCache: Map<string, number>;
50
52
  /**
51
53
  * Set the session ID used by formToken() / form_token() for CSRF session binding.
52
54
  */
@@ -1,160 +0,0 @@
1
- /**
2
- * CLI command: metrics — Rank top code-quality offenders.
3
- *
4
- * Exposes the existing static analyzer (cyclomatic complexity, maintainability,
5
- * large-file, too-many-functions, and the now-precise has_tests) on the CLI as
6
- * a self-monitoring tool.
7
- *
8
- * tina4nodejs metrics # human report, scans src/ (or framework)
9
- * tina4nodejs metrics --top 10 # only the worst 10
10
- * tina4nodejs metrics --path packages/core/src # scan a specific directory
11
- * tina4nodejs metrics --json # machine-readable for CI (ONLY json printed)
12
- * tina4nodejs metrics --fail-on warn # exit 1 if any warn/error offender
13
- * tina4nodejs metrics --fail-on error # exit 1 only on error-severity
14
- *
15
- * Returns the intended process exit code (the caller exits). Splitting "compute
16
- * exit code" from "exit the process" keeps the handler unit-testable.
17
- */
18
- import { offenders, MetricsEngineError } from "../../../core/src/metrics.js";
19
-
20
- type Flags = {
21
- top: number;
22
- json: boolean;
23
- path: string;
24
- failOn: "warn" | "error" | null;
25
- };
26
-
27
- /** Parse `--top N`, `--json`, `--fail-on warn|error`, `--path DIR` out of argv. */
28
- function parseFlags(args: string[]): Flags | { error: string } {
29
- const flags: Flags = { top: 20, json: false, path: "src", failOn: null };
30
-
31
- for (let i = 0; i < args.length; i++) {
32
- const a = args[i];
33
- switch (a) {
34
- case "--json":
35
- flags.json = true;
36
- break;
37
- case "--top": {
38
- const v = args[++i];
39
- if (v === undefined || !/^\d+$/.test(v)) {
40
- return { error: `--top expects a number (got '${v ?? ""}')` };
41
- }
42
- flags.top = parseInt(v, 10);
43
- break;
44
- }
45
- case "--path": {
46
- const v = args[++i];
47
- if (v === undefined) return { error: "--path expects a directory" };
48
- flags.path = v;
49
- break;
50
- }
51
- case "--fail-on": {
52
- const v = args[++i];
53
- if (v !== "warn" && v !== "error") {
54
- return { error: `invalid --fail-on '${v ?? ""}' (use warn or error)` };
55
- }
56
- flags.failOn = v;
57
- break;
58
- }
59
- default:
60
- return { error: `unknown option '${a}'` };
61
- }
62
- }
63
-
64
- return flags;
65
- }
66
-
67
- /**
68
- * Run the metrics report. Returns the process exit code; does NOT call
69
- * process.exit (the bin wrapper does). 0 = ok / below threshold, 1 = gated
70
- * failure, 2 = bad arguments / analysis error.
71
- */
72
- export function runMetrics(args: string[] = []): number {
73
- const parsed = parseFlags(args);
74
- if ("error" in parsed) {
75
- console.log(` ${parsed.error}`);
76
- return 2;
77
- }
78
- const { top, json, path, failOn } = parsed;
79
-
80
- // ONE engine run. Ask for every offender and slice for display: the gate must
81
- // read the FULL set, not the printed top-N, and the old second call re-ran the
82
- // whole analysis (its "mtime-cached" comment stopped being true when the
83
- // in-process analyzer and its cache were deleted -- ADR-0002).
84
- let result;
85
- try {
86
- result = offenders(path, Number.MAX_SAFE_INTEGER);
87
- } catch (e) {
88
- if (e instanceof MetricsEngineError) {
89
- console.error(` metrics error: ${e.message}`);
90
- return 2;
91
- }
92
- throw e;
93
- }
94
- const summary = result.summary;
95
- const allOffenders = result.offenders;
96
- const found = allOffenders.slice(0, top);
97
-
98
- const severities = new Set(allOffenders.map((o) => o.severity));
99
- let exitCode = 0;
100
- if (failOn === "warn" && (severities.has("warn") || severities.has("error"))) {
101
- exitCode = 1;
102
- } else if (failOn === "error" && severities.has("error")) {
103
- exitCode = 1;
104
- }
105
-
106
- if (json) {
107
- // Print ONLY the JSON — machine-readable for CI / tooling.
108
- console.log(JSON.stringify({ summary, offenders: found }, null, 2));
109
- return exitCode;
110
- }
111
-
112
- // ── Human report ──────────────────────────────────────────────────
113
- const useColor = Boolean(process.stdout.isTTY);
114
- const c = (text: string, code: string): string =>
115
- useColor ? `\x1b[${code}m${text}\x1b[0m` : text;
116
- const sevColor: Record<string, string> = { error: "31", warn: "33", info: "2" }; // red / yellow / dim
117
-
118
- console.log("");
119
- console.log(` Tina4 Metrics — ${summary.scan_mode} scan (${summary.scan_root})`);
120
- console.log(
121
- ` files: ${summary.files_analyzed} ` +
122
- `functions: ${summary.total_functions} ` +
123
- `avg complexity: ${summary.avg_complexity} ` +
124
- `avg maintainability: ${summary.avg_maintainability}`
125
- );
126
- console.log(
127
- ` offenders: ${summary.total_offenders} total` +
128
- (found.length ? ` (showing top ${found.length})` : "")
129
- );
130
- console.log("");
131
-
132
- if (found.length === 0) {
133
- console.log(" " + c("✓ no offenders — clean", "32"));
134
- console.log("");
135
- return exitCode;
136
- }
137
-
138
- // Column widths so the table lines up.
139
- const locs = found.map((o) => `${o.file}:${o.line}`);
140
- const locW = Math.max("FILE:LINE".length, ...locs.map((s) => s.length));
141
- const kindW = Math.max("KIND".length, ...found.map((o) => o.kind.length));
142
-
143
- const pad = (s: string, w: number) => s.padEnd(w);
144
- const header = ` ${pad("#", 3)} ${pad("SEVERITY", 8)} ${pad("KIND", kindW)} ${pad(
145
- "FILE:LINE",
146
- locW
147
- )} DETAIL`;
148
- console.log(c(header, "1"));
149
- console.log(" " + "-".repeat(header.length - 2));
150
- found.forEach((o, idx) => {
151
- const i = idx + 1;
152
- const sevCell = c(pad(o.severity, 8), sevColor[o.severity]);
153
- console.log(
154
- ` ${String(i).padStart(3)} ${sevCell} ${pad(o.kind, kindW)} ` +
155
- `${pad(locs[idx], locW)} ${o.detail}`
156
- );
157
- });
158
- console.log("");
159
- return exitCode;
160
- }
@@ -1,6 +0,0 @@
1
- /**
2
- * Run the metrics report. Returns the process exit code; does NOT call
3
- * process.exit (the bin wrapper does). 0 = ok / below threshold, 1 = gated
4
- * failure, 2 = bad arguments / analysis error.
5
- */
6
- export declare function runMetrics(args?: string[]): number;