@nac3/forge-cli 0.2.0-alpha.3 → 0.2.0-alpha.31
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/bin/yf.d.ts.map +1 -1
- package/dist/bin/yf.js +27 -0
- package/dist/bin/yf.js.map +1 -1
- package/dist/chat/claude.d.ts +22 -15
- package/dist/chat/claude.d.ts.map +1 -1
- package/dist/chat/claude.js +75 -22
- package/dist/chat/claude.js.map +1 -1
- package/dist/chat/panel.d.ts.map +1 -1
- package/dist/chat/panel.js +791 -17
- package/dist/chat/panel.js.map +1 -1
- package/dist/chat/server.js +734 -32
- package/dist/chat/server.js.map +1 -1
- package/dist/chat/spec_extract.d.ts.map +1 -1
- package/dist/chat/spec_extract.js +39 -0
- package/dist/chat/spec_extract.js.map +1 -1
- package/dist/chat/tools/audit_consumers.d.ts +66 -0
- package/dist/chat/tools/audit_consumers.d.ts.map +1 -0
- package/dist/chat/tools/audit_consumers.js +231 -0
- package/dist/chat/tools/audit_consumers.js.map +1 -0
- package/dist/chat/tools/git.js +4 -4
- package/dist/chat/tools/github.js +3 -3
- package/dist/chat/tools/keys.d.ts +9 -0
- package/dist/chat/tools/keys.d.ts.map +1 -0
- package/dist/chat/tools/keys.js +194 -0
- package/dist/chat/tools/keys.js.map +1 -0
- package/dist/chat/tools/lifecycle.js +3 -3
- package/dist/chat/tools/manual.js +1 -1
- package/dist/chat/tools/reader.js +8 -8
- package/dist/chat/tools/workflow.d.ts +45 -0
- package/dist/chat/tools/workflow.d.ts.map +1 -0
- package/dist/chat/tools/workflow.js +404 -0
- package/dist/chat/tools/workflow.js.map +1 -0
- package/dist/chat/tools.d.ts.map +1 -1
- package/dist/chat/tools.js +31 -4
- package/dist/chat/tools.js.map +1 -1
- package/dist/commands/approve.d.ts +32 -0
- package/dist/commands/approve.d.ts.map +1 -0
- package/dist/commands/approve.js +198 -0
- package/dist/commands/approve.js.map +1 -0
- package/dist/commands/block.d.ts +28 -0
- package/dist/commands/block.d.ts.map +1 -0
- package/dist/commands/block.js +189 -0
- package/dist/commands/block.js.map +1 -0
- package/dist/commands/bootstrap.d.ts +35 -0
- package/dist/commands/bootstrap.d.ts.map +1 -0
- package/dist/commands/bootstrap.js +205 -0
- package/dist/commands/bootstrap.js.map +1 -0
- package/dist/commands/chat.d.ts +3 -0
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +46 -1
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/clarify.d.ts +30 -0
- package/dist/commands/clarify.d.ts.map +1 -0
- package/dist/commands/clarify.js +671 -0
- package/dist/commands/clarify.js.map +1 -0
- package/dist/commands/discover.d.ts +30 -0
- package/dist/commands/discover.d.ts.map +1 -0
- package/dist/commands/discover.js +178 -0
- package/dist/commands/discover.js.map +1 -0
- package/dist/commands/doctor.js +94 -42
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/keys_setup.d.ts +53 -0
- package/dist/commands/keys_setup.d.ts.map +1 -0
- package/dist/commands/keys_setup.js +487 -0
- package/dist/commands/keys_setup.js.map +1 -0
- package/dist/commands/legacy-audit.d.ts +34 -0
- package/dist/commands/legacy-audit.d.ts.map +1 -0
- package/dist/commands/legacy-audit.js +270 -0
- package/dist/commands/legacy-audit.js.map +1 -0
- package/dist/commands/license.d.ts.map +1 -1
- package/dist/commands/license.js +41 -0
- package/dist/commands/license.js.map +1 -1
- package/dist/commands/operate.d.ts +22 -0
- package/dist/commands/operate.d.ts.map +1 -0
- package/dist/commands/operate.js +523 -0
- package/dist/commands/operate.js.map +1 -0
- package/dist/commands/spec.d.ts +38 -0
- package/dist/commands/spec.d.ts.map +1 -0
- package/dist/commands/spec.js +256 -0
- package/dist/commands/spec.js.map +1 -0
- package/dist/commands/support.d.ts +22 -0
- package/dist/commands/support.d.ts.map +1 -0
- package/dist/commands/support.js +143 -0
- package/dist/commands/support.js.map +1 -0
- package/dist/commands/triage.d.ts +34 -0
- package/dist/commands/triage.d.ts.map +1 -0
- package/dist/commands/triage.js +228 -0
- package/dist/commands/triage.js.map +1 -0
- package/dist/commands/vault-inventory.d.ts +30 -0
- package/dist/commands/vault-inventory.d.ts.map +1 -0
- package/dist/commands/vault-inventory.js +214 -0
- package/dist/commands/vault-inventory.js.map +1 -0
- package/dist/commands/vault.d.ts.map +1 -1
- package/dist/commands/vault.js +5 -0
- package/dist/commands/vault.js.map +1 -1
- package/dist/commands/voice.js +1 -1
- package/dist/commands/voice.js.map +1 -1
- package/dist/commands/workflow-coverage.d.ts +30 -0
- package/dist/commands/workflow-coverage.d.ts.map +1 -0
- package/dist/commands/workflow-coverage.js +138 -0
- package/dist/commands/workflow-coverage.js.map +1 -0
- package/dist/core/keys_envelope.d.ts +13 -0
- package/dist/core/keys_envelope.d.ts.map +1 -1
- package/dist/core/keys_envelope.js.map +1 -1
- package/dist/deploy/adapter.d.ts +93 -0
- package/dist/deploy/adapter.d.ts.map +1 -0
- package/dist/deploy/adapter.js +42 -0
- package/dist/deploy/adapter.js.map +1 -0
- package/dist/deploy/aws_adapter.d.ts +28 -0
- package/dist/deploy/aws_adapter.d.ts.map +1 -0
- package/dist/deploy/aws_adapter.js +98 -0
- package/dist/deploy/aws_adapter.js.map +1 -0
- package/dist/deploy/cloudflare.d.ts +24 -0
- package/dist/deploy/cloudflare.d.ts.map +1 -0
- package/dist/deploy/cloudflare.js +169 -0
- package/dist/deploy/cloudflare.js.map +1 -0
- package/dist/license/hito4_client.d.ts +17 -1
- package/dist/license/hito4_client.d.ts.map +1 -1
- package/dist/license/hito4_client.js +71 -10
- package/dist/license/hito4_client.js.map +1 -1
- package/dist/license/index.d.ts.map +1 -1
- package/dist/license/index.js +7 -0
- package/dist/license/index.js.map +1 -1
- package/dist/license/sync.d.ts +54 -0
- package/dist/license/sync.d.ts.map +1 -0
- package/dist/license/sync.js +131 -0
- package/dist/license/sync.js.map +1 -0
- package/dist/support/reports.d.ts +31 -0
- package/dist/support/reports.d.ts.map +1 -0
- package/dist/support/reports.js +162 -0
- package/dist/support/reports.js.map +1 -0
- package/dist/telemetry/usage.d.ts +67 -0
- package/dist/telemetry/usage.d.ts.map +1 -0
- package/dist/telemetry/usage.js +208 -0
- package/dist/telemetry/usage.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/voice/intents.d.ts +1 -1
- package/dist/voice/intents.js +0 -0
- package/dist/voice/providers/google.d.ts +9 -0
- package/dist/voice/providers/google.d.ts.map +1 -1
- package/dist/voice/providers/google.js +204 -28
- package/dist/voice/providers/google.js.map +1 -1
- package/dist/voice/router.d.ts +10 -0
- package/dist/voice/router.d.ts.map +1 -1
- package/dist/voice/router.js +39 -20
- package/dist/voice/router.js.map +1 -1
- package/dist/voice/types.d.ts +5 -2
- package/dist/voice/types.d.ts.map +1 -1
- package/dist/voice/types.js.map +1 -1
- package/dist/workflow/state.d.ts +190 -0
- package/dist/workflow/state.d.ts.map +1 -0
- package/dist/workflow/state.js +119 -0
- package/dist/workflow/state.js.map +1 -0
- package/package.json +13 -15
- package/templates/nextjs-app/README.md +48 -0
- package/templates/nextjs-app/next.config.js +8 -0
- package/templates/nextjs-app/package.json +33 -0
- package/templates/nextjs-app/src/app/globals.css +43 -0
- package/templates/nextjs-app/src/app/layout.tsx +29 -0
- package/templates/nextjs-app/src/app/page.tsx +63 -0
- package/templates/nextjs-app/src/nac/manifest.ts +36 -0
- package/templates/nextjs-app/tsconfig.json +21 -0
- package/templates/nextjs-app/yujin.forge.json +11 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloudflare Pages adapter (default for Simple + Medium projects).
|
|
3
|
+
*
|
|
4
|
+
* Implementation strategy: shell out to `wrangler pages deploy`.
|
|
5
|
+
* Wrangler handles authentication (oauth token at
|
|
6
|
+
* ~/.config/.wrangler/config/default.toml) + the project upload.
|
|
7
|
+
* We invoke + parse its output.
|
|
8
|
+
*
|
|
9
|
+
* Why Cloudflare for default:
|
|
10
|
+
* - Free tier covers 5M req/day -- 12+ months runway for new
|
|
11
|
+
* projects.
|
|
12
|
+
* - 20-40s typical deploy time.
|
|
13
|
+
* - Edge-deployed across 250+ POPs by default; no CDN setup.
|
|
14
|
+
* - DNS + ACM cert auto-managed under *.pages.dev.
|
|
15
|
+
* - Pablo's account is already wrangler-authed.
|
|
16
|
+
*
|
|
17
|
+
* What this adapter does NOT do today:
|
|
18
|
+
* - Custom domains (requires zone owned by the user's CF account).
|
|
19
|
+
* - Server-side workers (would need a separate `wrangler deploy`
|
|
20
|
+
* for the Worker bundle; the Pages adapter is static-only).
|
|
21
|
+
* - Environment variable updates (the user has to set those
|
|
22
|
+
* manually for now via the CF dashboard or `wrangler pages
|
|
23
|
+
* project create --variable`).
|
|
24
|
+
*
|
|
25
|
+
* ASCII-only.
|
|
26
|
+
*/
|
|
27
|
+
import { spawn } from 'node:child_process';
|
|
28
|
+
import { promises as fs } from 'node:fs';
|
|
29
|
+
import path from 'node:path';
|
|
30
|
+
export class CloudflareAdapter {
|
|
31
|
+
opts;
|
|
32
|
+
id = 'cloudflare';
|
|
33
|
+
description = 'Cloudflare Pages + Workers -- free tier, edge-deployed, 20-40s deploys. '
|
|
34
|
+
+ 'Best for simple + medium projects without persistent state.';
|
|
35
|
+
constructor(opts = {}) {
|
|
36
|
+
this.opts = opts;
|
|
37
|
+
}
|
|
38
|
+
tierFit() { return ['simple', 'medium']; }
|
|
39
|
+
async readyToRun() {
|
|
40
|
+
const wranglerBin = this.opts.wranglerBin ?? 'wrangler';
|
|
41
|
+
/* Check that wrangler is on PATH + has an OAuth/API token
|
|
42
|
+
* available. We rely on `wrangler whoami` to do this for us
|
|
43
|
+
* -- exit code 0 means authed. */
|
|
44
|
+
return new Promise((resolve) => {
|
|
45
|
+
let stdout = '';
|
|
46
|
+
let stderr = '';
|
|
47
|
+
const ps = spawn(wranglerBin, ['whoami'], { shell: true });
|
|
48
|
+
ps.stdout.on('data', (d) => { stdout += d.toString(); });
|
|
49
|
+
ps.stderr.on('data', (d) => { stderr += d.toString(); });
|
|
50
|
+
ps.on('error', (err) => {
|
|
51
|
+
resolve({ ok: false, reason: 'wrangler not runnable: ' + err.message });
|
|
52
|
+
});
|
|
53
|
+
ps.on('close', (code) => {
|
|
54
|
+
if (code !== 0) {
|
|
55
|
+
resolve({
|
|
56
|
+
ok: false,
|
|
57
|
+
reason: 'wrangler whoami exit ' + code + '. Run `wrangler login` first. stderr: '
|
|
58
|
+
+ stderr.slice(0, 200),
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
else if (/not authenticated|no.*token/i.test(stdout)) {
|
|
62
|
+
resolve({ ok: false, reason: 'wrangler not authenticated. Run `wrangler login`.' });
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
resolve({ ok: true });
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
async plan(input) {
|
|
71
|
+
const exists = await this.dirExists(input.buildDir);
|
|
72
|
+
if (!exists) {
|
|
73
|
+
throw new Error('cloudflare.plan: buildDir does not exist: ' + input.buildDir);
|
|
74
|
+
}
|
|
75
|
+
const fileCount = await this.countFiles(input.buildDir);
|
|
76
|
+
return {
|
|
77
|
+
resources: [
|
|
78
|
+
'Cloudflare Pages project: ' + input.projectSlug,
|
|
79
|
+
'Static assets: ' + fileCount + ' files',
|
|
80
|
+
'Edge-deployed at ' + input.projectSlug + '.pages.dev',
|
|
81
|
+
...(input.env && Object.keys(input.env).length > 0
|
|
82
|
+
? ['Env vars (set separately via wrangler pages project create): ' + Object.keys(input.env).join(', ')]
|
|
83
|
+
: []),
|
|
84
|
+
],
|
|
85
|
+
/* Free tier covers 500 builds/month + 5M req/day. New
|
|
86
|
+
* projects expect $0/mo for ~12+ months. */
|
|
87
|
+
estimated_cost_usd: 0,
|
|
88
|
+
estimated_minutes: Math.max(1, Math.ceil(fileCount / 200)),
|
|
89
|
+
notes: [
|
|
90
|
+
'Cloudflare Pages free tier covers 500 builds/month + 5M requests/day.',
|
|
91
|
+
'Above the free tier, Pages overage = $5/1M requests; build minutes overage = $0.005/min.',
|
|
92
|
+
'Workers (if added) free 100k req/day; $0.30 per million above.',
|
|
93
|
+
],
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
async apply(input) {
|
|
97
|
+
const exists = await this.dirExists(input.buildDir);
|
|
98
|
+
if (!exists) {
|
|
99
|
+
throw new Error('cloudflare.apply: buildDir does not exist: ' + input.buildDir);
|
|
100
|
+
}
|
|
101
|
+
const wranglerBin = this.opts.wranglerBin ?? 'wrangler';
|
|
102
|
+
const args = ['pages', 'deploy', input.buildDir,
|
|
103
|
+
'--project-name', input.projectSlug,
|
|
104
|
+
'--branch', 'main'];
|
|
105
|
+
const t0 = Date.now();
|
|
106
|
+
const out = await this.runWrangler(wranglerBin, args);
|
|
107
|
+
const seconds = Math.round((Date.now() - t0) / 1000);
|
|
108
|
+
/* Parse the URL out of wrangler's output. */
|
|
109
|
+
const urlMatch = out.combined.match(/https:\/\/[a-z0-9-]+\.[a-z0-9-]+\.pages\.dev/i);
|
|
110
|
+
if (!urlMatch) {
|
|
111
|
+
throw new Error('cloudflare.apply: could not parse deploy URL from wrangler output. '
|
|
112
|
+
+ 'Tail: ' + out.combined.slice(-500));
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
url: urlMatch[0],
|
|
116
|
+
deployed_at: new Date().toISOString(),
|
|
117
|
+
build_seconds: seconds,
|
|
118
|
+
logs_tail: out.combined.split('\n').slice(-20),
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
async runWrangler(bin, args) {
|
|
122
|
+
return new Promise((resolve, reject) => {
|
|
123
|
+
let combined = '';
|
|
124
|
+
const ps = spawn(bin, args, { shell: true });
|
|
125
|
+
ps.stdout.on('data', (d) => { combined += d.toString(); });
|
|
126
|
+
ps.stderr.on('data', (d) => { combined += d.toString(); });
|
|
127
|
+
ps.on('error', (err) => reject(new Error('wrangler spawn failed: ' + err.message)));
|
|
128
|
+
ps.on('close', (code) => {
|
|
129
|
+
if (code !== 0) {
|
|
130
|
+
reject(new Error('wrangler exit ' + code + '. Tail: ' + combined.slice(-500)));
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
resolve({ exit: code ?? 0, combined });
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
async dirExists(p) {
|
|
138
|
+
try {
|
|
139
|
+
const st = await fs.stat(p);
|
|
140
|
+
return st.isDirectory();
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async countFiles(p) {
|
|
147
|
+
let count = 0;
|
|
148
|
+
const walk = async (dir) => {
|
|
149
|
+
let entries;
|
|
150
|
+
try {
|
|
151
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
152
|
+
}
|
|
153
|
+
catch {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
for (const e of entries) {
|
|
157
|
+
if (e.name === 'node_modules' || e.name.startsWith('.'))
|
|
158
|
+
continue;
|
|
159
|
+
if (e.isDirectory())
|
|
160
|
+
await walk(path.join(dir, e.name));
|
|
161
|
+
else if (e.isFile())
|
|
162
|
+
count++;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
await walk(p);
|
|
166
|
+
return count;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=cloudflare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cloudflare.js","sourceRoot":"","sources":["../../src/deploy/cloudflare.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
import { Vault } from '../vault/store.js';
|
|
2
|
+
import type { BrainProvider } from '../core/keys_envelope.js';
|
|
2
3
|
export declare const HITO4_BASE_URL: string;
|
|
4
|
+
interface ResolvedBrain {
|
|
5
|
+
provider: BrainProvider | null;
|
|
6
|
+
apiKey: string | null;
|
|
7
|
+
modelAlias: string | null;
|
|
8
|
+
}
|
|
9
|
+
/** Resolve which brain provider + key + model alias to use for
|
|
10
|
+
* the current request. Mirrors the mobile-side logic that
|
|
11
|
+
* reads from the encrypted keys-sync cache. */
|
|
12
|
+
export declare function resolveBrainHeaders(): Promise<ResolvedBrain>;
|
|
3
13
|
export interface Hito4ClientDeps {
|
|
4
14
|
fetchImpl?: typeof fetch;
|
|
5
15
|
vaultOpener?: () => Promise<Vault>;
|
|
@@ -16,9 +26,15 @@ export interface FlowCallResult {
|
|
|
16
26
|
body: Record<string, unknown>;
|
|
17
27
|
}
|
|
18
28
|
/** Call a HITO 4 flow. Returns the raw server response (no
|
|
19
|
-
* retry / no backoff -- callers can decide).
|
|
29
|
+
* retry / no backoff -- callers can decide).
|
|
30
|
+
*
|
|
31
|
+
* Brain providers are BYOK: this call reads the local
|
|
32
|
+
* ~/.yujin-forge/provider_keys.json, picks the preferred
|
|
33
|
+
* provider + key + model, and forwards them as headers. The
|
|
34
|
+
* worker never persists nor logs the key. */
|
|
20
35
|
export declare function callFlow(flow: string, input: unknown, deps?: Hito4ClientDeps): Promise<FlowCallResult>;
|
|
21
36
|
/** Pull the up-to-date license row from the server. The CLI's
|
|
22
37
|
* Polar cache is then refreshed with the result. */
|
|
23
38
|
export declare function fetchServerLicense(deps?: Hito4ClientDeps): Promise<FlowCallResult>;
|
|
39
|
+
export {};
|
|
24
40
|
//# sourceMappingURL=hito4_client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hito4_client.d.ts","sourceRoot":"","sources":["../../src/license/hito4_client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hito4_client.d.ts","sourceRoot":"","sources":["../../src/license/hito4_client.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAG1C,OAAO,KAAK,EAAyB,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAErF,eAAO,MAAM,cAAc,QAA8E,CAAC;AAiB1G,UAAU,aAAa;IACrB,QAAQ,EAAE,aAAa,GAAG,IAAI,CAAC;IAC/B,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;gDAEgD;AAChD,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,aAAa,CAAC,CAelE;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;IACnC;qDACiD;IACjD,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IACvC,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AA+BD,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,GAAE,MAAmB,GAAG,MAAM,CAG1F;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED;;;;;;8CAM8C;AAC9C,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,GAAE,eAAoB,GACvD,OAAO,CAAC,cAAc,CAAC,CAoBzB;AAED;qDACqD;AACrD,wBAAsB,kBAAkB,CAAC,IAAI,GAAE,eAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CAc5F"}
|
|
@@ -19,11 +19,63 @@
|
|
|
19
19
|
* ASCII-only.
|
|
20
20
|
*/
|
|
21
21
|
import { createHmac } from 'node:crypto';
|
|
22
|
+
import { promises as fs } from 'node:fs';
|
|
23
|
+
import path from 'node:path';
|
|
24
|
+
import os from 'node:os';
|
|
22
25
|
import { Vault } from '../vault/store.js';
|
|
23
26
|
import { configDir } from './index.js';
|
|
24
27
|
import { readLicense } from '../core/polar.js';
|
|
25
28
|
export const HITO4_BASE_URL = process.env.YF_HITO4_BASE_URL ?? 'https://yujin-hito4.yujinapp.workers.dev';
|
|
26
29
|
const SECRET_SLOT = 'yf_server_api_key';
|
|
30
|
+
/** Read the local plaintext provider keys cache. The mobile
|
|
31
|
+
* equivalent is the `useProviderKeys` hook. Returns null if
|
|
32
|
+
* the file does not exist yet (user has not run keys setup). */
|
|
33
|
+
async function readLocalProviderKeys() {
|
|
34
|
+
const home = process.env.HOME || process.env.USERPROFILE || os.homedir();
|
|
35
|
+
const p = path.join(home, '.yujin-forge', 'provider_keys.json');
|
|
36
|
+
try {
|
|
37
|
+
const raw = await fs.readFile(p, 'utf-8');
|
|
38
|
+
const parsed = JSON.parse(raw);
|
|
39
|
+
if (parsed && parsed.v === 1)
|
|
40
|
+
return parsed;
|
|
41
|
+
}
|
|
42
|
+
catch { /* missing */ }
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
/** Resolve which brain provider + key + model alias to use for
|
|
46
|
+
* the current request. Mirrors the mobile-side logic that
|
|
47
|
+
* reads from the encrypted keys-sync cache. */
|
|
48
|
+
export async function resolveBrainHeaders() {
|
|
49
|
+
const cache = await readLocalProviderKeys();
|
|
50
|
+
if (!cache)
|
|
51
|
+
return { provider: null, apiKey: null, modelAlias: null };
|
|
52
|
+
const provider = (cache.brain_provider_preference ?? null);
|
|
53
|
+
if (!provider)
|
|
54
|
+
return { provider: null, apiKey: null, modelAlias: null };
|
|
55
|
+
let apiKey;
|
|
56
|
+
let modelAlias;
|
|
57
|
+
if (provider === 'anthropic') {
|
|
58
|
+
apiKey = cache.anthropic_api_key;
|
|
59
|
+
modelAlias = cache.anthropic_model_preference;
|
|
60
|
+
}
|
|
61
|
+
else if (provider === 'openai') {
|
|
62
|
+
apiKey = cache.openai_api_key;
|
|
63
|
+
modelAlias = cache.openai_brain_model_preference;
|
|
64
|
+
}
|
|
65
|
+
else if (provider === 'google') {
|
|
66
|
+
apiKey = cache.google_ai_key;
|
|
67
|
+
modelAlias = cache.google_brain_model_preference;
|
|
68
|
+
}
|
|
69
|
+
else if (provider === 'deepseek') {
|
|
70
|
+
apiKey = cache.deepseek_api_key;
|
|
71
|
+
modelAlias = cache.deepseek_model_preference;
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
provider,
|
|
75
|
+
apiKey: apiKey ?? null,
|
|
76
|
+
modelAlias: modelAlias ?? null,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
27
79
|
function hmacHex(secret, msg) {
|
|
28
80
|
return createHmac('sha256', secret).update(msg).digest('hex');
|
|
29
81
|
}
|
|
@@ -52,23 +104,32 @@ export function signBearer(secret, handle, ts = Date.now()) {
|
|
|
52
104
|
return ts + '.' + sig;
|
|
53
105
|
}
|
|
54
106
|
/** Call a HITO 4 flow. Returns the raw server response (no
|
|
55
|
-
* retry / no backoff -- callers can decide).
|
|
107
|
+
* retry / no backoff -- callers can decide).
|
|
108
|
+
*
|
|
109
|
+
* Brain providers are BYOK: this call reads the local
|
|
110
|
+
* ~/.yujin-forge/provider_keys.json, picks the preferred
|
|
111
|
+
* provider + key + model, and forwards them as headers. The
|
|
112
|
+
* worker never persists nor logs the key. */
|
|
56
113
|
export async function callFlow(flow, input, deps = {}) {
|
|
57
114
|
const base = deps.baseUrl ?? HITO4_BASE_URL;
|
|
58
115
|
const secret = await getSecret(deps);
|
|
59
116
|
const handle = await getHandle(deps);
|
|
60
117
|
const bearer = signBearer(secret, handle);
|
|
61
118
|
const fetchImpl = deps.fetchImpl ?? ((u, init) => globalThis.fetch(u, init));
|
|
119
|
+
const brain = await resolveBrainHeaders();
|
|
62
120
|
const url = base.replace(/\/+$/, '') + '/v1/flows/' + encodeURIComponent(flow);
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
121
|
+
const headers = {
|
|
122
|
+
'Authorization': 'Bearer ' + bearer,
|
|
123
|
+
'x-yf-user-handle': handle,
|
|
124
|
+
'content-type': 'application/json',
|
|
125
|
+
};
|
|
126
|
+
if (brain.provider)
|
|
127
|
+
headers['x-yf-brain-provider'] = brain.provider;
|
|
128
|
+
if (brain.apiKey)
|
|
129
|
+
headers['x-yf-brain-key'] = brain.apiKey;
|
|
130
|
+
if (brain.modelAlias)
|
|
131
|
+
headers['x-yf-brain-model'] = brain.modelAlias;
|
|
132
|
+
const r = await fetchImpl(url, { method: 'POST', headers, body: JSON.stringify(input ?? null) });
|
|
72
133
|
let body = {};
|
|
73
134
|
try {
|
|
74
135
|
body = await r.json();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hito4_client.js","sourceRoot":"","sources":["../../src/license/hito4_client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"hito4_client.js","sourceRoot":"","sources":["../../src/license/hito4_client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/license/index.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,YAAY,CAAC;AAIpB,wBAAgB,SAAS,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/license/index.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EACV,YAAY,EAIb,MAAM,YAAY,CAAC;AAIpB,wBAAgB,SAAS,IAAI,MAAM,CAQlC;AAoDD;;;;;;;;GAQG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC,CAwBzD;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAEvD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAE1D;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAEzD"}
|
package/dist/license/index.js
CHANGED
|
@@ -27,6 +27,13 @@ import { homedir } from 'node:os';
|
|
|
27
27
|
import path from 'node:path';
|
|
28
28
|
const TRIAL_DAYS = 30;
|
|
29
29
|
export function configDir() {
|
|
30
|
+
/* YF_CONFIG_DIR overrides the default ~/.yujin-forge location.
|
|
31
|
+
* Used by tests (tests/fresh-user/*) to point at a clean
|
|
32
|
+
* temp dir without touching the developer's real config.
|
|
33
|
+
* Also useful for users who want a portable install. */
|
|
34
|
+
const override = process.env['YF_CONFIG_DIR'];
|
|
35
|
+
if (override && override.trim() !== '')
|
|
36
|
+
return override.trim();
|
|
30
37
|
return path.join(homedir(), '.yujin-forge');
|
|
31
38
|
}
|
|
32
39
|
function trialPath() { return path.join(configDir(), 'trial.json'); }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/license/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/license/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* License sync -- pulls the canonical license row from the
|
|
3
|
+
* HITO 4 server and updates the local Polar cache.
|
|
4
|
+
*
|
|
5
|
+
* Flow:
|
|
6
|
+
* 1. Read local cache (~/.yujin-forge/license.json).
|
|
7
|
+
* Needs user_handle. If missing -> error pointing to
|
|
8
|
+
* `yf license activate --user-handle <email>`.
|
|
9
|
+
* 2. Call fetchServerLicense via the HMAC-signed Hito4 client.
|
|
10
|
+
* 3. Map the server response to a LicenseCache patch.
|
|
11
|
+
* 4. Merge + write back. Bumps last_validated_at to now.
|
|
12
|
+
* 5. Return a SyncReport for the CLI to print.
|
|
13
|
+
*
|
|
14
|
+
* Why this exists: the Polar webhook updates the SERVER-side D1
|
|
15
|
+
* row. The local cache was never wired to pull. The "activate"
|
|
16
|
+
* copy advertised "license.json updated automatically" -- it was
|
|
17
|
+
* not. This fixes that gap.
|
|
18
|
+
*
|
|
19
|
+
* ASCII-only.
|
|
20
|
+
*/
|
|
21
|
+
import { type LicenseCache } from '../core/polar.js';
|
|
22
|
+
import { type Hito4ClientDeps } from './hito4_client.js';
|
|
23
|
+
export interface SyncReport {
|
|
24
|
+
ok: boolean;
|
|
25
|
+
/** Plan as known to the server. */
|
|
26
|
+
server_plan?: string;
|
|
27
|
+
/** Plan we had locally before sync. */
|
|
28
|
+
local_plan_before?: string;
|
|
29
|
+
/** Plan we now have locally. */
|
|
30
|
+
local_plan_after?: string;
|
|
31
|
+
/** HTTP status from the server call. */
|
|
32
|
+
http_status?: number;
|
|
33
|
+
/** Server validated_at timestamp. */
|
|
34
|
+
last_validated_at?: string;
|
|
35
|
+
/** Error string when ok=false. */
|
|
36
|
+
error?: string;
|
|
37
|
+
/** Verbose log lines (URLs called, headers redacted). Only
|
|
38
|
+
* populated when verbose=true. */
|
|
39
|
+
log?: string[];
|
|
40
|
+
}
|
|
41
|
+
export interface SyncOptions extends Hito4ClientDeps {
|
|
42
|
+
verbose?: boolean;
|
|
43
|
+
/** Override the source of the local cache (for tests). */
|
|
44
|
+
readLocal?: () => Promise<LicenseCache>;
|
|
45
|
+
/** Override the persist path (for tests). */
|
|
46
|
+
writeLocal?: (next: LicenseCache) => Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
/** Map a server response body to the LicenseCache plan + fields.
|
|
49
|
+
* The server today returns the row in {plan, expires_at,
|
|
50
|
+
* subscription_id, customer_id, user_handle, cancel_grace_until,
|
|
51
|
+
* bills_first_on, trial_started_at, payment_method_attached}. */
|
|
52
|
+
export declare function serverBodyToPatch(body: Record<string, unknown>): Partial<LicenseCache> | null;
|
|
53
|
+
export declare function syncLicense(opts?: SyncOptions): Promise<SyncReport>;
|
|
54
|
+
//# sourceMappingURL=sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../../src/license/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAGL,KAAK,YAAY,EAElB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE7E,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,mCAAmC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uCAAuC;IACvC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gCAAgC;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,wCAAwC;IACxC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kCAAkC;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;uCACmC;IACnC,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,WAAY,SAAQ,eAAe;IAClD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,MAAM,OAAO,CAAC,YAAY,CAAC,CAAC;IACxC,6CAA6C;IAC7C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,YAAY,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD;AAED;;;kEAGkE;AAClE,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,GAAG,IAAI,CAuB7F;AAED,wBAAsB,WAAW,CAAC,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,UAAU,CAAC,CAgF7E"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* License sync -- pulls the canonical license row from the
|
|
3
|
+
* HITO 4 server and updates the local Polar cache.
|
|
4
|
+
*
|
|
5
|
+
* Flow:
|
|
6
|
+
* 1. Read local cache (~/.yujin-forge/license.json).
|
|
7
|
+
* Needs user_handle. If missing -> error pointing to
|
|
8
|
+
* `yf license activate --user-handle <email>`.
|
|
9
|
+
* 2. Call fetchServerLicense via the HMAC-signed Hito4 client.
|
|
10
|
+
* 3. Map the server response to a LicenseCache patch.
|
|
11
|
+
* 4. Merge + write back. Bumps last_validated_at to now.
|
|
12
|
+
* 5. Return a SyncReport for the CLI to print.
|
|
13
|
+
*
|
|
14
|
+
* Why this exists: the Polar webhook updates the SERVER-side D1
|
|
15
|
+
* row. The local cache was never wired to pull. The "activate"
|
|
16
|
+
* copy advertised "license.json updated automatically" -- it was
|
|
17
|
+
* not. This fixes that gap.
|
|
18
|
+
*
|
|
19
|
+
* ASCII-only.
|
|
20
|
+
*/
|
|
21
|
+
import { readLicense as readPolarLicense, writeLicense as writePolarLicense, } from '../core/polar.js';
|
|
22
|
+
import { fetchServerLicense } from './hito4_client.js';
|
|
23
|
+
/** Map a server response body to the LicenseCache plan + fields.
|
|
24
|
+
* The server today returns the row in {plan, expires_at,
|
|
25
|
+
* subscription_id, customer_id, user_handle, cancel_grace_until,
|
|
26
|
+
* bills_first_on, trial_started_at, payment_method_attached}. */
|
|
27
|
+
export function serverBodyToPatch(body) {
|
|
28
|
+
if (!body || typeof body !== 'object')
|
|
29
|
+
return null;
|
|
30
|
+
const planRaw = body.plan;
|
|
31
|
+
const validPlans = [
|
|
32
|
+
'none', 'trial', 'paid', 'cancelled', 'free-public', 'institutional', 'gifted',
|
|
33
|
+
];
|
|
34
|
+
if (typeof planRaw !== 'string' || !validPlans.includes(planRaw)) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
const patch = { plan: planRaw };
|
|
38
|
+
if (typeof body.subscription_id === 'string')
|
|
39
|
+
patch.subscription_id = body.subscription_id;
|
|
40
|
+
if (typeof body.user_handle === 'string')
|
|
41
|
+
patch.user_handle = body.user_handle.toLowerCase();
|
|
42
|
+
if (typeof body.cancel_grace_until === 'string')
|
|
43
|
+
patch.cancel_grace_until = body.cancel_grace_until;
|
|
44
|
+
if (typeof body.bills_first_on === 'string')
|
|
45
|
+
patch.bills_first_on = body.bills_first_on;
|
|
46
|
+
if (typeof body.trial_started_at === 'string')
|
|
47
|
+
patch.trial_started_at = body.trial_started_at;
|
|
48
|
+
if (body.expires_at === null || typeof body.expires_at === 'string') {
|
|
49
|
+
patch.expires_at = body.expires_at;
|
|
50
|
+
}
|
|
51
|
+
if (typeof body.payment_method_attached === 'boolean'
|
|
52
|
+
|| typeof body.payment_method_attached === 'number') {
|
|
53
|
+
patch.payment_method_attached = Boolean(body.payment_method_attached);
|
|
54
|
+
}
|
|
55
|
+
return patch;
|
|
56
|
+
}
|
|
57
|
+
export async function syncLicense(opts = {}) {
|
|
58
|
+
const log = [];
|
|
59
|
+
const verbose = Boolean(opts.verbose);
|
|
60
|
+
const readLocal = opts.readLocal ?? readPolarLicense;
|
|
61
|
+
const writeLocal = opts.writeLocal ?? writePolarLicense;
|
|
62
|
+
const local = await readLocal();
|
|
63
|
+
if (verbose) {
|
|
64
|
+
log.push('[license-sync] local cache loaded plan=' + local.plan
|
|
65
|
+
+ ' user_handle=' + (local.user_handle ?? '(none)'));
|
|
66
|
+
}
|
|
67
|
+
if (!local.user_handle) {
|
|
68
|
+
return {
|
|
69
|
+
ok: false,
|
|
70
|
+
error: 'no user_handle on local license cache. Run `yf license activate --user-handle <you@example.com>` first.',
|
|
71
|
+
local_plan_before: local.plan,
|
|
72
|
+
log: verbose ? log : undefined,
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
if (verbose)
|
|
76
|
+
log.push('[license-sync] calling Hito4 fetchServerLicense for ' + local.user_handle);
|
|
77
|
+
let resp;
|
|
78
|
+
try {
|
|
79
|
+
resp = await fetchServerLicense(opts);
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
return {
|
|
83
|
+
ok: false,
|
|
84
|
+
error: err instanceof Error ? err.message : String(err),
|
|
85
|
+
local_plan_before: local.plan,
|
|
86
|
+
log: verbose ? log : undefined,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (verbose) {
|
|
90
|
+
log.push('[license-sync] server HTTP ' + resp.status + ' ok=' + resp.ok);
|
|
91
|
+
}
|
|
92
|
+
if (!resp.ok) {
|
|
93
|
+
return {
|
|
94
|
+
ok: false,
|
|
95
|
+
error: typeof resp.body?.error === 'string' ? resp.body.error : 'server returned HTTP ' + resp.status,
|
|
96
|
+
http_status: resp.status,
|
|
97
|
+
server_plan: typeof resp.body?.plan === 'string' ? resp.body.plan : undefined,
|
|
98
|
+
local_plan_before: local.plan,
|
|
99
|
+
log: verbose ? log : undefined,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
const patch = serverBodyToPatch(resp.body);
|
|
103
|
+
if (!patch) {
|
|
104
|
+
return {
|
|
105
|
+
ok: false,
|
|
106
|
+
error: 'server response body did not contain a valid plan field',
|
|
107
|
+
http_status: resp.status,
|
|
108
|
+
local_plan_before: local.plan,
|
|
109
|
+
log: verbose ? log : undefined,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
const merged = {
|
|
113
|
+
...local,
|
|
114
|
+
...patch,
|
|
115
|
+
last_validated_at: new Date().toISOString(),
|
|
116
|
+
};
|
|
117
|
+
await writeLocal(merged);
|
|
118
|
+
if (verbose) {
|
|
119
|
+
log.push('[license-sync] local cache updated plan=' + local.plan + ' -> ' + merged.plan);
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
ok: true,
|
|
123
|
+
server_plan: patch.plan,
|
|
124
|
+
local_plan_before: local.plan,
|
|
125
|
+
local_plan_after: merged.plan,
|
|
126
|
+
http_status: resp.status,
|
|
127
|
+
last_validated_at: merged.last_validated_at,
|
|
128
|
+
log: verbose ? log : undefined,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync.js","sourceRoot":"","sources":["../../src/license/sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,WAAW,IAAI,gBAAgB,EAC/B,YAAY,IAAI,iBAAiB,GAGlC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,kBAAkB,EAAwB,MAAM,mBAAmB,CAAC;AA6B7E;;;kEAGkE;AAClE,MAAM,UAAU,iBAAiB,CAAC,IAA6B;IAC7D,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACnD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC;IAC1B,MAAM,UAAU,GAAkB;QAChC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,eAAe,EAAE,QAAQ;KAC/E,CAAC;IACF,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAsB,CAAC,EAAE,CAAC;QAChF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,KAAK,GAA0B,EAAE,IAAI,EAAE,OAAsB,EAAE,CAAC;IACtE,IAAI,OAAO,IAAI,CAAC,eAAe,KAAU,QAAQ;QAAE,KAAK,CAAC,eAAe,GAAM,IAAI,CAAC,eAAe,CAAC;IACnG,IAAI,OAAO,IAAI,CAAC,WAAW,KAAc,QAAQ;QAAE,KAAK,CAAC,WAAW,GAAU,IAAI,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;IAC7G,IAAI,OAAO,IAAI,CAAC,kBAAkB,KAAO,QAAQ;QAAE,KAAK,CAAC,kBAAkB,GAAG,IAAI,CAAC,kBAAkB,CAAC;IACtG,IAAI,OAAO,IAAI,CAAC,cAAc,KAAW,QAAQ;QAAE,KAAK,CAAC,cAAc,GAAO,IAAI,CAAC,cAAc,CAAC;IAClG,IAAI,OAAO,IAAI,CAAC,gBAAgB,KAAS,QAAQ;QAAE,KAAK,CAAC,gBAAgB,GAAK,IAAI,CAAC,gBAAgB,CAAC;IACpG,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,IAAI,OAAO,IAAI,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;QACpE,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC,UAA2B,CAAC;IACtD,CAAC;IACD,IAAI,OAAO,IAAI,CAAC,uBAAuB,KAAK,SAAS;WAC9C,OAAO,IAAI,CAAC,uBAAuB,KAAK,QAAQ,EAAE,CAAC;QACxD,KAAK,CAAC,uBAAuB,GAAG,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAoB,EAAE;IACtD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,SAAS,GAAI,IAAI,CAAC,SAAS,IAAK,gBAAgB,CAAC;IACvD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,iBAAiB,CAAC;IAExD,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAChC,IAAI,OAAO,EAAE,CAAC;QACZ,GAAG,CAAC,IAAI,CAAC,yCAAyC,GAAG,KAAK,CAAC,IAAI;cAC3D,eAAe,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,QAAQ,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QACvB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,yGAAyG;YAChH,iBAAiB,EAAE,KAAK,CAAC,IAAI;YAC7B,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAgC;SACtD,CAAC;IACJ,CAAC;IAED,IAAI,OAAO;QAAE,GAAG,CAAC,IAAI,CAAC,sDAAsD,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;IAElG,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;YACvD,iBAAiB,EAAE,KAAK,CAAC,IAAI;YAC7B,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAgC;SACtD,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,EAAE,CAAC;QACZ,GAAG,CAAC,IAAI,CAAC,6BAA6B,GAAG,IAAI,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC,CAAC;IAC3E,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,OAAO,IAAI,CAAC,IAAI,EAAE,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,uBAAuB,GAAG,IAAI,CAAC,MAAM;YACrG,WAAW,EAAE,IAAI,CAAC,MAAM;YACxB,WAAW,EAAE,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;YAC7E,iBAAiB,EAAE,KAAK,CAAC,IAAI;YAC7B,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAgC;SACtD,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,yDAAyD;YAChE,WAAW,EAAE,IAAI,CAAC,MAAM;YACxB,iBAAiB,EAAE,KAAK,CAAC,IAAI;YAC7B,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAgC;SACtD,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAiB;QAC3B,GAAG,KAAK;QACR,GAAG,KAAK;QACR,iBAAiB,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KAC5C,CAAC;IAEF,MAAM,UAAU,CAAC,MAAM,CAAC,CAAC;IACzB,IAAI,OAAO,EAAE,CAAC;QACZ,GAAG,CAAC,IAAI,CAAC,0CAA0C,GAAG,KAAK,CAAC,IAAI,GAAG,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3F,CAAC;IAED,OAAO;QACL,EAAE,EAAE,IAAI;QACR,WAAW,EAAE,KAAK,CAAC,IAAI;QACvB,iBAAiB,EAAE,KAAK,CAAC,IAAI;QAC7B,gBAAgB,EAAE,MAAM,CAAC,IAAI;QAC7B,WAAW,EAAE,IAAI,CAAC,MAAM;QACxB,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;QAC3C,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAgC;KACtD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export type ReportLevel = 'error' | 'warn' | 'info';
|
|
2
|
+
export interface SupportReport {
|
|
3
|
+
ts: string;
|
|
4
|
+
level: ReportLevel;
|
|
5
|
+
source: string;
|
|
6
|
+
message: string;
|
|
7
|
+
stack?: string;
|
|
8
|
+
url?: string;
|
|
9
|
+
line?: number;
|
|
10
|
+
col?: number;
|
|
11
|
+
user_agent?: string;
|
|
12
|
+
view?: string;
|
|
13
|
+
request_trail?: Array<{
|
|
14
|
+
method: string;
|
|
15
|
+
url: string;
|
|
16
|
+
status?: number;
|
|
17
|
+
}>;
|
|
18
|
+
client_ts?: string;
|
|
19
|
+
}
|
|
20
|
+
/** Replace PII patterns in any string field of the report. */
|
|
21
|
+
export declare function scrubPii(report: SupportReport): SupportReport;
|
|
22
|
+
/** Append a single report. Never throws. */
|
|
23
|
+
export declare function recordReport(report: SupportReport): Promise<void>;
|
|
24
|
+
/** Read all reports (current + rotated). Tolerates malformed lines. */
|
|
25
|
+
export declare function readReports(): Promise<SupportReport[]>;
|
|
26
|
+
/** Validate + normalize an inbound payload from the panel.
|
|
27
|
+
* Returns null when the payload shape is unacceptable. */
|
|
28
|
+
export declare function validateInbound(body: unknown, defaults?: {
|
|
29
|
+
user_agent?: string;
|
|
30
|
+
}): SupportReport | null;
|
|
31
|
+
//# sourceMappingURL=reports.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reports.d.ts","sourceRoot":"","sources":["../../src/support/reports.ts"],"names":[],"mappings":"AA4BA,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpD,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAU,MAAM,CAAC;IACnB,KAAK,EAAO,WAAW,CAAC;IACxB,MAAM,EAAM,MAAM,CAAC;IACnB,OAAO,EAAK,MAAM,CAAC;IACnB,KAAK,CAAC,EAAM,MAAM,CAAC;IACnB,GAAG,CAAC,EAAQ,MAAM,CAAC;IACnB,IAAI,CAAC,EAAO,MAAM,CAAC;IACnB,GAAG,CAAC,EAAQ,MAAM,CAAC;IACnB,UAAU,CAAC,EAAC,MAAM,CAAC;IACnB,IAAI,CAAC,EAAO,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAUD,8DAA8D;AAC9D,wBAAgB,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa,CAuB7D;AAuBD,4CAA4C;AAC5C,wBAAsB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CASvE;AAED,uEAAuE;AACvE,wBAAsB,WAAW,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC,CAY5D;AAED;2DAC2D;AAC3D,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,aAAa,GAAG,IAAI,CAiC3G"}
|