mcpscraper-memory-db 1.0.0
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/README.md +40 -0
- package/dist/db/chat-link.d.ts +7 -0
- package/dist/db/chat-link.js +50 -0
- package/dist/db/chat-link.js.map +1 -0
- package/dist/db/facts.d.ts +60 -0
- package/dist/db/facts.js +186 -0
- package/dist/db/facts.js.map +1 -0
- package/dist/db/interlink-state.d.ts +34 -0
- package/dist/db/interlink-state.js +42 -0
- package/dist/db/interlink-state.js.map +1 -0
- package/dist/db/keys.d.ts +44 -0
- package/dist/db/keys.js +118 -0
- package/dist/db/keys.js.map +1 -0
- package/dist/db/messages.d.ts +77 -0
- package/dist/db/messages.js +198 -0
- package/dist/db/messages.js.map +1 -0
- package/dist/db/notes.d.ts +109 -0
- package/dist/db/notes.js +249 -0
- package/dist/db/notes.js.map +1 -0
- package/dist/db/pool.d.ts +7 -0
- package/dist/db/pool.js +37 -0
- package/dist/db/pool.js.map +1 -0
- package/dist/db/presence.d.ts +4 -0
- package/dist/db/presence.js +25 -0
- package/dist/db/presence.js.map +1 -0
- package/dist/db/props-snapshots.d.ts +18 -0
- package/dist/db/props-snapshots.js +37 -0
- package/dist/db/props-snapshots.js.map +1 -0
- package/dist/db/provenance.d.ts +26 -0
- package/dist/db/provenance.js +43 -0
- package/dist/db/provenance.js.map +1 -0
- package/dist/db/schedule-entitlements.d.ts +24 -0
- package/dist/db/schedule-entitlements.js +70 -0
- package/dist/db/schedule-entitlements.js.map +1 -0
- package/dist/db/schedule-link.d.ts +7 -0
- package/dist/db/schedule-link.js +50 -0
- package/dist/db/schedule-link.js.map +1 -0
- package/dist/db/scheduled-actions.d.ts +58 -0
- package/dist/db/scheduled-actions.js +139 -0
- package/dist/db/scheduled-actions.js.map +1 -0
- package/dist/db/schema.d.ts +3 -0
- package/dist/db/schema.js +340 -0
- package/dist/db/schema.js.map +1 -0
- package/dist/db/secure-notes.d.ts +26 -0
- package/dist/db/secure-notes.js +59 -0
- package/dist/db/secure-notes.js.map +1 -0
- package/dist/db/shares.d.ts +45 -0
- package/dist/db/shares.js +141 -0
- package/dist/db/shares.js.map +1 -0
- package/dist/db/tables.d.ts +50 -0
- package/dist/db/tables.js +226 -0
- package/dist/db/tables.js.map +1 -0
- package/dist/db/trust.d.ts +10 -0
- package/dist/db/trust.js +88 -0
- package/dist/db/trust.js.map +1 -0
- package/dist/db/usage.d.ts +30 -0
- package/dist/db/usage.js +106 -0
- package/dist/db/usage.js.map +1 -0
- package/dist/db/vaults.d.ts +98 -0
- package/dist/db/vaults.js +316 -0
- package/dist/db/vaults.js.map +1 -0
- package/dist/db/video-runs.d.ts +70 -0
- package/dist/db/video-runs.js +176 -0
- package/dist/db/video-runs.js.map +1 -0
- package/dist/db/webhooks.d.ts +20 -0
- package/dist/db/webhooks.js +43 -0
- package/dist/db/webhooks.js.map +1 -0
- package/dist/lib/auth.d.ts +75 -0
- package/dist/lib/auth.js +248 -0
- package/dist/lib/auth.js.map +1 -0
- package/dist/lib/cost-rates.d.ts +19 -0
- package/dist/lib/cost-rates.js +36 -0
- package/dist/lib/cost-rates.js.map +1 -0
- package/dist/lib/credit-debit.d.ts +15 -0
- package/dist/lib/credit-debit.js +21 -0
- package/dist/lib/credit-debit.js.map +1 -0
- package/dist/lib/operator.d.ts +5 -0
- package/dist/lib/operator.js +14 -0
- package/dist/lib/operator.js.map +1 -0
- package/dist/lib/schedule-cadence.d.ts +6 -0
- package/dist/lib/schedule-cadence.js +66 -0
- package/dist/lib/schedule-cadence.js.map +1 -0
- package/dist/lib/secret-crypto.d.ts +4 -0
- package/dist/lib/secret-crypto.js +28 -0
- package/dist/lib/secret-crypto.js.map +1 -0
- package/dist/lib/vault-contracts.d.ts +18 -0
- package/dist/lib/vault-contracts.js +248 -0
- package/dist/lib/vault-contracts.js.map +1 -0
- package/dist/lib/video-reaper.d.ts +13 -0
- package/dist/lib/video-reaper.js +19 -0
- package/dist/lib/video-reaper.js.map +1 -0
- package/dist/rag/embedder.d.ts +6 -0
- package/dist/rag/embedder.js +93 -0
- package/dist/rag/embedder.js.map +1 -0
- package/dist/rag/index-pipeline.d.ts +22 -0
- package/dist/rag/index-pipeline.js +62 -0
- package/dist/rag/index-pipeline.js.map +1 -0
- package/dist/rag/query-tool.d.ts +47 -0
- package/dist/rag/query-tool.js +47 -0
- package/dist/rag/query-tool.js.map +1 -0
- package/dist/rag/vector-store.d.ts +7 -0
- package/dist/rag/vector-store.js +25 -0
- package/dist/rag/vector-store.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
const COST_RATES = {
|
|
2
|
+
minimax_in_per_tok: 0.3 / 1e6,
|
|
3
|
+
minimax_out_per_tok: 1.2 / 1e6,
|
|
4
|
+
jina_per_tok: 0.02 / 1e6,
|
|
5
|
+
neon_per_gb_month: 0.35,
|
|
6
|
+
compute_per_run_usd: 5e-4
|
|
7
|
+
};
|
|
8
|
+
const FREE_COST_CAP_USD = 1;
|
|
9
|
+
const PRO_COST_BUDGET_USD = 19 / 3;
|
|
10
|
+
const MARGIN_MULTIPLE = 3;
|
|
11
|
+
function embedCostUsd(tokens) {
|
|
12
|
+
return tokens * COST_RATES.jina_per_tok;
|
|
13
|
+
}
|
|
14
|
+
function llmCostUsd(args) {
|
|
15
|
+
const inTok = args.inputTokens ?? 0;
|
|
16
|
+
const outTok = args.outputTokens ?? 0;
|
|
17
|
+
return inTok * COST_RATES.minimax_in_per_tok + outTok * COST_RATES.minimax_out_per_tok;
|
|
18
|
+
}
|
|
19
|
+
function storageCostUsdForMonth(bytes) {
|
|
20
|
+
const gb = bytes / 1e9;
|
|
21
|
+
return gb * COST_RATES.neon_per_gb_month;
|
|
22
|
+
}
|
|
23
|
+
function storageCostUsdForDay(bytes) {
|
|
24
|
+
return storageCostUsdForMonth(bytes) / 30;
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
COST_RATES,
|
|
28
|
+
FREE_COST_CAP_USD,
|
|
29
|
+
MARGIN_MULTIPLE,
|
|
30
|
+
PRO_COST_BUDGET_USD,
|
|
31
|
+
embedCostUsd,
|
|
32
|
+
llmCostUsd,
|
|
33
|
+
storageCostUsdForDay,
|
|
34
|
+
storageCostUsdForMonth
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=cost-rates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/cost-rates.ts"],"sourcesContent":["export const COST_RATES = {\n minimax_in_per_tok: 0.3 / 1_000_000,\n minimax_out_per_tok: 1.2 / 1_000_000,\n jina_per_tok: 0.02 / 1_000_000,\n neon_per_gb_month: 0.35,\n compute_per_run_usd: 0.0005,\n} as const\n\nexport const FREE_COST_CAP_USD = 1.0\nexport const PRO_COST_BUDGET_USD = 19 / 3\nexport const MARGIN_MULTIPLE = 3\n\nexport function embedCostUsd(tokens: number): number {\n return tokens * COST_RATES.jina_per_tok\n}\n\nexport function llmCostUsd(args: { inputTokens?: number; outputTokens?: number }): number {\n const inTok = args.inputTokens ?? 0\n const outTok = args.outputTokens ?? 0\n return inTok * COST_RATES.minimax_in_per_tok + outTok * COST_RATES.minimax_out_per_tok\n}\n\nexport function storageCostUsdForMonth(bytes: number): number {\n const gb = bytes / 1e9\n return gb * COST_RATES.neon_per_gb_month\n}\n\nexport function storageCostUsdForDay(bytes: number): number {\n return storageCostUsdForMonth(bytes) / 30\n}\n"],"mappings":"AAAO,MAAM,aAAa;AAAA,EACxB,oBAAoB,MAAM;AAAA,EAC1B,qBAAqB,MAAM;AAAA,EAC3B,cAAc,OAAO;AAAA,EACrB,mBAAmB;AAAA,EACnB,qBAAqB;AACvB;AAEO,MAAM,oBAAoB;AAC1B,MAAM,sBAAsB,KAAK;AACjC,MAAM,kBAAkB;AAExB,SAAS,aAAa,QAAwB;AACnD,SAAO,SAAS,WAAW;AAC7B;AAEO,SAAS,WAAW,MAA+D;AACxF,QAAM,QAAQ,KAAK,eAAe;AAClC,QAAM,SAAS,KAAK,gBAAgB;AACpC,SAAO,QAAQ,WAAW,qBAAqB,SAAS,WAAW;AACrE;AAEO,SAAS,uBAAuB,OAAuB;AAC5D,QAAM,KAAK,QAAQ;AACnB,SAAO,KAAK,WAAW;AACzB;AAEO,SAAS,qBAAqB,OAAuB;AAC1D,SAAO,uBAAuB,KAAK,IAAI;AACzC;","names":[]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface DebitResult {
|
|
2
|
+
ok: boolean;
|
|
3
|
+
insufficient?: boolean;
|
|
4
|
+
mc?: number;
|
|
5
|
+
balance_mc?: number | null;
|
|
6
|
+
reason?: string;
|
|
7
|
+
}
|
|
8
|
+
declare function debitAiCredits(args: {
|
|
9
|
+
identity: string;
|
|
10
|
+
costUsd: number;
|
|
11
|
+
op: string;
|
|
12
|
+
source: string;
|
|
13
|
+
}): Promise<DebitResult>;
|
|
14
|
+
|
|
15
|
+
export { type DebitResult, debitAiCredits };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const ENDPOINT = () => (process.env.MCP_SCRAPER_INTERNAL_URL ?? "https://mcpscraper.dev") + "/api/internal/memory/ai-debit";
|
|
2
|
+
async function debitAiCredits(args) {
|
|
3
|
+
const secret = process.env.INTERNAL_MEMORY_DEBIT_SECRET;
|
|
4
|
+
if (!secret) return { ok: false, reason: "no_secret" };
|
|
5
|
+
try {
|
|
6
|
+
const r = await fetch(ENDPOINT(), {
|
|
7
|
+
method: "POST",
|
|
8
|
+
headers: { "content-type": "application/json", "x-internal-secret": secret },
|
|
9
|
+
body: JSON.stringify({ identity: args.identity, costUsd: args.costUsd, op: args.op, source: args.source }),
|
|
10
|
+
signal: AbortSignal.timeout(5e3)
|
|
11
|
+
});
|
|
12
|
+
if (!r.ok) return { ok: false, reason: `http_${r.status}` };
|
|
13
|
+
return await r.json();
|
|
14
|
+
} catch (e) {
|
|
15
|
+
return { ok: false, reason: "fetch_failed" };
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
debitAiCredits
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=credit-debit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/credit-debit.ts"],"sourcesContent":["const ENDPOINT = () => (process.env.MCP_SCRAPER_INTERNAL_URL ?? 'https://mcpscraper.dev') + '/api/internal/memory/ai-debit'\n\nexport interface DebitResult { ok: boolean; insufficient?: boolean; mc?: number; balance_mc?: number | null; reason?: string }\n\nexport async function debitAiCredits(args: { identity: string; costUsd: number; op: string; source: string }): Promise<DebitResult> {\n const secret = process.env.INTERNAL_MEMORY_DEBIT_SECRET\n if (!secret) return { ok: false, reason: 'no_secret' } // fail-open: never block AI on misconfig, but log\n try {\n const r = await fetch(ENDPOINT(), {\n method: 'POST',\n headers: { 'content-type': 'application/json', 'x-internal-secret': secret },\n body: JSON.stringify({ identity: args.identity, costUsd: args.costUsd, op: args.op, source: args.source }),\n signal: AbortSignal.timeout(5000),\n })\n if (!r.ok) return { ok: false, reason: `http_${r.status}` }\n return await r.json() as DebitResult\n } catch (e) {\n return { ok: false, reason: 'fetch_failed' } // fail-open on network error\n }\n}\n"],"mappings":"AAAA,MAAM,WAAW,OAAO,QAAQ,IAAI,4BAA4B,4BAA4B;AAI5F,eAAsB,eAAe,MAA+F;AAClI,QAAM,SAAS,QAAQ,IAAI;AAC3B,MAAI,CAAC,OAAQ,QAAO,EAAE,IAAI,OAAO,QAAQ,YAAY;AACrD,MAAI;AACF,UAAM,IAAI,MAAM,MAAM,SAAS,GAAG;AAAA,MAChC,QAAQ;AAAA,MACR,SAAS,EAAE,gBAAgB,oBAAoB,qBAAqB,OAAO;AAAA,MAC3E,MAAM,KAAK,UAAU,EAAE,UAAU,KAAK,UAAU,SAAS,KAAK,SAAS,IAAI,KAAK,IAAI,QAAQ,KAAK,OAAO,CAAC;AAAA,MACzG,QAAQ,YAAY,QAAQ,GAAI;AAAA,IAClC,CAAC;AACD,QAAI,CAAC,EAAE,GAAI,QAAO,EAAE,IAAI,OAAO,QAAQ,QAAQ,EAAE,MAAM,GAAG;AAC1D,WAAO,MAAM,EAAE,KAAK;AAAA,EACtB,SAAS,GAAG;AACV,WAAO,EAAE,IAAI,OAAO,QAAQ,eAAe;AAAA,EAC7C;AACF;","names":[]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const OPERATOR_PLAN = "unlimited";
|
|
2
|
+
function operatorIdentities() {
|
|
3
|
+
return (process.env.MEMORY_OPERATOR_IDENTITIES ?? "").split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
4
|
+
}
|
|
5
|
+
function isOperatorIdentity(identity) {
|
|
6
|
+
if (!identity) return false;
|
|
7
|
+
return operatorIdentities().includes(identity.trim().toLowerCase());
|
|
8
|
+
}
|
|
9
|
+
export {
|
|
10
|
+
OPERATOR_PLAN,
|
|
11
|
+
isOperatorIdentity,
|
|
12
|
+
operatorIdentities
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=operator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/operator.ts"],"sourcesContent":["export const OPERATOR_PLAN = 'unlimited'\n\nexport function operatorIdentities(): string[] {\n return (process.env.MEMORY_OPERATOR_IDENTITIES ?? '')\n .split(',')\n .map(s => s.trim().toLowerCase())\n .filter(Boolean)\n}\n\nexport function isOperatorIdentity(identity: string | null | undefined): boolean {\n if (!identity) return false\n return operatorIdentities().includes(identity.trim().toLowerCase())\n}\n"],"mappings":"AAAO,MAAM,gBAAgB;AAEtB,SAAS,qBAA+B;AAC7C,UAAQ,QAAQ,IAAI,8BAA8B,IAC/C,MAAM,GAAG,EACT,IAAI,OAAK,EAAE,KAAK,EAAE,YAAY,CAAC,EAC/B,OAAO,OAAO;AACnB;AAEO,SAAS,mBAAmB,UAA8C;AAC/E,MAAI,CAAC,SAAU,QAAO;AACtB,SAAO,mBAAmB,EAAE,SAAS,SAAS,KAAK,EAAE,YAAY,CAAC;AACpE;","names":[]}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
type ScheduleCadence = 'once' | 'daily' | 'weekly' | 'monthly';
|
|
2
|
+
declare function dateOnlyToAnchor(deployDate: string, timezone?: string | null): string | null;
|
|
3
|
+
declare function addCadence(fromIso: string, cadence: ScheduleCadence, timeOfDay?: string | null, timezone?: string | null): string;
|
|
4
|
+
declare function defaultNextRunAt(cadence: ScheduleCadence, timeOfDay?: string | null, timezone?: string | null, deployDate?: string | null): string;
|
|
5
|
+
|
|
6
|
+
export { type ScheduleCadence, addCadence, dateOnlyToAnchor, defaultNextRunAt };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
function wallClockParts(date, timezone) {
|
|
2
|
+
const fmt = new Intl.DateTimeFormat("en-US", {
|
|
3
|
+
timeZone: timezone,
|
|
4
|
+
year: "numeric",
|
|
5
|
+
month: "2-digit",
|
|
6
|
+
day: "2-digit",
|
|
7
|
+
hour: "2-digit",
|
|
8
|
+
minute: "2-digit",
|
|
9
|
+
hourCycle: "h23"
|
|
10
|
+
});
|
|
11
|
+
const parts = Object.fromEntries(fmt.formatToParts(date).map((p) => [p.type, p.value]));
|
|
12
|
+
return { y: Number(parts.year), mo: Number(parts.month), d: Number(parts.day), h: Number(parts.hour), mi: Number(parts.minute) };
|
|
13
|
+
}
|
|
14
|
+
function zonedToUtc(y, mo, d, h, mi, timezone) {
|
|
15
|
+
const approxUtc = new Date(Date.UTC(y, mo - 1, d, h, mi));
|
|
16
|
+
const asZoned = wallClockParts(approxUtc, timezone);
|
|
17
|
+
const asZonedUtc = Date.UTC(asZoned.y, asZoned.mo - 1, asZoned.d, asZoned.h, asZoned.mi);
|
|
18
|
+
const offsetMs = asZonedUtc - approxUtc.getTime();
|
|
19
|
+
return new Date(approxUtc.getTime() - offsetMs);
|
|
20
|
+
}
|
|
21
|
+
function dateOnlyToAnchor(deployDate, timezone) {
|
|
22
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(deployDate);
|
|
23
|
+
if (!m) return null;
|
|
24
|
+
return zonedToUtc(Number(m[1]), Number(m[2]), Number(m[3]), 0, 0, timezone || "UTC").toISOString();
|
|
25
|
+
}
|
|
26
|
+
function addCadence(fromIso, cadence, timeOfDay, timezone) {
|
|
27
|
+
const from = new Date(fromIso);
|
|
28
|
+
if (!Number.isFinite(from.getTime())) return new Date(Date.now() + 24 * 60 * 60 * 1e3).toISOString();
|
|
29
|
+
const tz = timezone || "UTC";
|
|
30
|
+
if (cadence === "once") {
|
|
31
|
+
if (!timeOfDay) return from.toISOString();
|
|
32
|
+
const [onceHh, onceMm] = timeOfDay.split(":").map(Number);
|
|
33
|
+
const onceWc = wallClockParts(from, tz);
|
|
34
|
+
return zonedToUtc(onceWc.y, onceWc.mo, onceWc.d, onceHh, onceMm, tz).toISOString();
|
|
35
|
+
}
|
|
36
|
+
if (!timeOfDay) {
|
|
37
|
+
const next = new Date(from);
|
|
38
|
+
if (cadence === "daily") next.setUTCDate(next.getUTCDate() + 1);
|
|
39
|
+
else if (cadence === "weekly") next.setUTCDate(next.getUTCDate() + 7);
|
|
40
|
+
else next.setUTCMonth(next.getUTCMonth() + 1);
|
|
41
|
+
return next.toISOString();
|
|
42
|
+
}
|
|
43
|
+
const [hh, mm] = timeOfDay.split(":").map(Number);
|
|
44
|
+
const wc = wallClockParts(from, tz);
|
|
45
|
+
let target;
|
|
46
|
+
if (cadence === "monthly") {
|
|
47
|
+
target = zonedToUtc(wc.y, wc.mo + 1, wc.d, hh, mm, tz);
|
|
48
|
+
} else {
|
|
49
|
+
target = zonedToUtc(wc.y, wc.mo, wc.d, hh, mm, tz);
|
|
50
|
+
if (target.getTime() <= from.getTime()) {
|
|
51
|
+
const stepDays = cadence === "daily" ? 1 : 7;
|
|
52
|
+
target = zonedToUtc(wc.y, wc.mo, wc.d + stepDays, hh, mm, tz);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return target.toISOString();
|
|
56
|
+
}
|
|
57
|
+
function defaultNextRunAt(cadence, timeOfDay, timezone, deployDate) {
|
|
58
|
+
const anchor = deployDate && dateOnlyToAnchor(deployDate, timezone) || (/* @__PURE__ */ new Date()).toISOString();
|
|
59
|
+
return addCadence(anchor, cadence, timeOfDay, timezone);
|
|
60
|
+
}
|
|
61
|
+
export {
|
|
62
|
+
addCadence,
|
|
63
|
+
dateOnlyToAnchor,
|
|
64
|
+
defaultNextRunAt
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=schedule-cadence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/schedule-cadence.ts"],"sourcesContent":["export type ScheduleCadence = 'once' | 'daily' | 'weekly' | 'monthly'\n\nfunction wallClockParts(date: Date, timezone: string): { y: number; mo: number; d: number; h: number; mi: number } {\n const fmt = new Intl.DateTimeFormat('en-US', {\n timeZone: timezone,\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n hourCycle: 'h23',\n })\n const parts = Object.fromEntries(fmt.formatToParts(date).map((p) => [p.type, p.value]))\n return { y: Number(parts.year), mo: Number(parts.month), d: Number(parts.day), h: Number(parts.hour), mi: Number(parts.minute) }\n}\n\nfunction zonedToUtc(y: number, mo: number, d: number, h: number, mi: number, timezone: string): Date {\n const approxUtc = new Date(Date.UTC(y, mo - 1, d, h, mi))\n const asZoned = wallClockParts(approxUtc, timezone)\n const asZonedUtc = Date.UTC(asZoned.y, asZoned.mo - 1, asZoned.d, asZoned.h, asZoned.mi)\n const offsetMs = asZonedUtc - approxUtc.getTime()\n return new Date(approxUtc.getTime() - offsetMs)\n}\n\nexport function dateOnlyToAnchor(deployDate: string, timezone?: string | null): string | null {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(deployDate)\n if (!m) return null\n return zonedToUtc(Number(m[1]), Number(m[2]), Number(m[3]), 0, 0, timezone || 'UTC').toISOString()\n}\n\nexport function addCadence(fromIso: string, cadence: ScheduleCadence, timeOfDay?: string | null, timezone?: string | null): string {\n const from = new Date(fromIso)\n if (!Number.isFinite(from.getTime())) return new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString()\n const tz = timezone || 'UTC'\n\n if (cadence === 'once') {\n if (!timeOfDay) return from.toISOString()\n const [onceHh, onceMm] = timeOfDay.split(':').map(Number)\n const onceWc = wallClockParts(from, tz)\n return zonedToUtc(onceWc.y, onceWc.mo, onceWc.d, onceHh, onceMm, tz).toISOString()\n }\n\n if (!timeOfDay) {\n const next = new Date(from)\n if (cadence === 'daily') next.setUTCDate(next.getUTCDate() + 1)\n else if (cadence === 'weekly') next.setUTCDate(next.getUTCDate() + 7)\n else next.setUTCMonth(next.getUTCMonth() + 1)\n return next.toISOString()\n }\n\n const [hh, mm] = timeOfDay.split(':').map(Number)\n const wc = wallClockParts(from, tz)\n let target: Date\n if (cadence === 'monthly') {\n target = zonedToUtc(wc.y, wc.mo + 1, wc.d, hh, mm, tz)\n } else {\n target = zonedToUtc(wc.y, wc.mo, wc.d, hh, mm, tz)\n if (target.getTime() <= from.getTime()) {\n const stepDays = cadence === 'daily' ? 1 : 7\n target = zonedToUtc(wc.y, wc.mo, wc.d + stepDays, hh, mm, tz)\n }\n }\n return target.toISOString()\n}\n\nexport function defaultNextRunAt(cadence: ScheduleCadence, timeOfDay?: string | null, timezone?: string | null, deployDate?: string | null): string {\n const anchor = (deployDate && dateOnlyToAnchor(deployDate, timezone)) || new Date().toISOString()\n return addCadence(anchor, cadence, timeOfDay, timezone)\n}\n"],"mappings":"AAEA,SAAS,eAAe,MAAY,UAA+E;AACjH,QAAM,MAAM,IAAI,KAAK,eAAe,SAAS;AAAA,IAC3C,UAAU;AAAA,IACV,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,WAAW;AAAA,EACb,CAAC;AACD,QAAM,QAAQ,OAAO,YAAY,IAAI,cAAc,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;AACtF,SAAO,EAAE,GAAG,OAAO,MAAM,IAAI,GAAG,IAAI,OAAO,MAAM,KAAK,GAAG,GAAG,OAAO,MAAM,GAAG,GAAG,GAAG,OAAO,MAAM,IAAI,GAAG,IAAI,OAAO,MAAM,MAAM,EAAE;AACjI;AAEA,SAAS,WAAW,GAAW,IAAY,GAAW,GAAW,IAAY,UAAwB;AACnG,QAAM,YAAY,IAAI,KAAK,KAAK,IAAI,GAAG,KAAK,GAAG,GAAG,GAAG,EAAE,CAAC;AACxD,QAAM,UAAU,eAAe,WAAW,QAAQ;AAClD,QAAM,aAAa,KAAK,IAAI,QAAQ,GAAG,QAAQ,KAAK,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,EAAE;AACvF,QAAM,WAAW,aAAa,UAAU,QAAQ;AAChD,SAAO,IAAI,KAAK,UAAU,QAAQ,IAAI,QAAQ;AAChD;AAEO,SAAS,iBAAiB,YAAoB,UAAyC;AAC5F,QAAM,IAAI,4BAA4B,KAAK,UAAU;AACrD,MAAI,CAAC,EAAG,QAAO;AACf,SAAO,WAAW,OAAO,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,CAAC,GAAG,GAAG,GAAG,YAAY,KAAK,EAAE,YAAY;AACnG;AAEO,SAAS,WAAW,SAAiB,SAA0B,WAA2B,UAAkC;AACjI,QAAM,OAAO,IAAI,KAAK,OAAO;AAC7B,MAAI,CAAC,OAAO,SAAS,KAAK,QAAQ,CAAC,EAAG,QAAO,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,GAAI,EAAE,YAAY;AACpG,QAAM,KAAK,YAAY;AAEvB,MAAI,YAAY,QAAQ;AACtB,QAAI,CAAC,UAAW,QAAO,KAAK,YAAY;AACxC,UAAM,CAAC,QAAQ,MAAM,IAAI,UAAU,MAAM,GAAG,EAAE,IAAI,MAAM;AACxD,UAAM,SAAS,eAAe,MAAM,EAAE;AACtC,WAAO,WAAW,OAAO,GAAG,OAAO,IAAI,OAAO,GAAG,QAAQ,QAAQ,EAAE,EAAE,YAAY;AAAA,EACnF;AAEA,MAAI,CAAC,WAAW;AACd,UAAM,OAAO,IAAI,KAAK,IAAI;AAC1B,QAAI,YAAY,QAAS,MAAK,WAAW,KAAK,WAAW,IAAI,CAAC;AAAA,aACrD,YAAY,SAAU,MAAK,WAAW,KAAK,WAAW,IAAI,CAAC;AAAA,QAC/D,MAAK,YAAY,KAAK,YAAY,IAAI,CAAC;AAC5C,WAAO,KAAK,YAAY;AAAA,EAC1B;AAEA,QAAM,CAAC,IAAI,EAAE,IAAI,UAAU,MAAM,GAAG,EAAE,IAAI,MAAM;AAChD,QAAM,KAAK,eAAe,MAAM,EAAE;AAClC,MAAI;AACJ,MAAI,YAAY,WAAW;AACzB,aAAS,WAAW,GAAG,GAAG,GAAG,KAAK,GAAG,GAAG,GAAG,IAAI,IAAI,EAAE;AAAA,EACvD,OAAO;AACL,aAAS,WAAW,GAAG,GAAG,GAAG,IAAI,GAAG,GAAG,IAAI,IAAI,EAAE;AACjD,QAAI,OAAO,QAAQ,KAAK,KAAK,QAAQ,GAAG;AACtC,YAAM,WAAW,YAAY,UAAU,IAAI;AAC3C,eAAS,WAAW,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,UAAU,IAAI,IAAI,EAAE;AAAA,IAC9D;AAAA,EACF;AACA,SAAO,OAAO,YAAY;AAC5B;AAEO,SAAS,iBAAiB,SAA0B,WAA2B,UAA0B,YAAoC;AAClJ,QAAM,SAAU,cAAc,iBAAiB,YAAY,QAAQ,MAAM,oBAAI,KAAK,GAAE,YAAY;AAChG,SAAO,WAAW,QAAQ,SAAS,WAAW,QAAQ;AACxD;","names":[]}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
2
|
+
function encryptionKey() {
|
|
3
|
+
const hex = process.env.SCHEDULE_SECRET_ENC_KEY;
|
|
4
|
+
if (!hex || hex.length !== 64) {
|
|
5
|
+
throw new Error("SCHEDULE_SECRET_ENC_KEY must be set to a 32-byte hex string (64 chars)");
|
|
6
|
+
}
|
|
7
|
+
return Buffer.from(hex, "hex");
|
|
8
|
+
}
|
|
9
|
+
function encryptSecret(plaintext) {
|
|
10
|
+
const iv = randomBytes(12);
|
|
11
|
+
const cipher = createCipheriv("aes-256-gcm", encryptionKey(), iv);
|
|
12
|
+
const ciphertext = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
|
|
13
|
+
const authTag = cipher.getAuthTag();
|
|
14
|
+
return [iv.toString("hex"), authTag.toString("hex"), ciphertext.toString("hex")].join(".");
|
|
15
|
+
}
|
|
16
|
+
function decryptSecret(stored) {
|
|
17
|
+
const [ivHex, tagHex, ciphertextHex] = stored.split(".");
|
|
18
|
+
if (!ivHex || !tagHex || !ciphertextHex) throw new Error("malformed encrypted secret");
|
|
19
|
+
const decipher = createDecipheriv("aes-256-gcm", encryptionKey(), Buffer.from(ivHex, "hex"));
|
|
20
|
+
decipher.setAuthTag(Buffer.from(tagHex, "hex"));
|
|
21
|
+
const plaintext = Buffer.concat([decipher.update(Buffer.from(ciphertextHex, "hex")), decipher.final()]);
|
|
22
|
+
return plaintext.toString("utf8");
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
decryptSecret,
|
|
26
|
+
encryptSecret
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=secret-crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/secret-crypto.ts"],"sourcesContent":["import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto'\n\nfunction encryptionKey(): Buffer {\n const hex = process.env.SCHEDULE_SECRET_ENC_KEY\n if (!hex || hex.length !== 64) {\n throw new Error('SCHEDULE_SECRET_ENC_KEY must be set to a 32-byte hex string (64 chars)')\n }\n return Buffer.from(hex, 'hex')\n}\n\nexport function encryptSecret(plaintext: string): string {\n const iv = randomBytes(12)\n const cipher = createCipheriv('aes-256-gcm', encryptionKey(), iv)\n const ciphertext = Buffer.concat([cipher.update(plaintext, 'utf8'), cipher.final()])\n const authTag = cipher.getAuthTag()\n return [iv.toString('hex'), authTag.toString('hex'), ciphertext.toString('hex')].join('.')\n}\n\nexport function decryptSecret(stored: string): string {\n const [ivHex, tagHex, ciphertextHex] = stored.split('.')\n if (!ivHex || !tagHex || !ciphertextHex) throw new Error('malformed encrypted secret')\n const decipher = createDecipheriv('aes-256-gcm', encryptionKey(), Buffer.from(ivHex, 'hex'))\n decipher.setAuthTag(Buffer.from(tagHex, 'hex'))\n const plaintext = Buffer.concat([decipher.update(Buffer.from(ciphertextHex, 'hex')), decipher.final()])\n return plaintext.toString('utf8')\n}\n"],"mappings":"AAAA,SAAS,gBAAgB,kBAAkB,mBAAmB;AAE9D,SAAS,gBAAwB;AAC/B,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,CAAC,OAAO,IAAI,WAAW,IAAI;AAC7B,UAAM,IAAI,MAAM,wEAAwE;AAAA,EAC1F;AACA,SAAO,OAAO,KAAK,KAAK,KAAK;AAC/B;AAEO,SAAS,cAAc,WAA2B;AACvD,QAAM,KAAK,YAAY,EAAE;AACzB,QAAM,SAAS,eAAe,eAAe,cAAc,GAAG,EAAE;AAChE,QAAM,aAAa,OAAO,OAAO,CAAC,OAAO,OAAO,WAAW,MAAM,GAAG,OAAO,MAAM,CAAC,CAAC;AACnF,QAAM,UAAU,OAAO,WAAW;AAClC,SAAO,CAAC,GAAG,SAAS,KAAK,GAAG,QAAQ,SAAS,KAAK,GAAG,WAAW,SAAS,KAAK,CAAC,EAAE,KAAK,GAAG;AAC3F;AAEO,SAAS,cAAc,QAAwB;AACpD,QAAM,CAAC,OAAO,QAAQ,aAAa,IAAI,OAAO,MAAM,GAAG;AACvD,MAAI,CAAC,SAAS,CAAC,UAAU,CAAC,cAAe,OAAM,IAAI,MAAM,4BAA4B;AACrF,QAAM,WAAW,iBAAiB,eAAe,cAAc,GAAG,OAAO,KAAK,OAAO,KAAK,CAAC;AAC3F,WAAS,WAAW,OAAO,KAAK,QAAQ,KAAK,CAAC;AAC9C,QAAM,YAAY,OAAO,OAAO,CAAC,SAAS,OAAO,OAAO,KAAK,eAAe,KAAK,CAAC,GAAG,SAAS,MAAM,CAAC,CAAC;AACtG,SAAO,UAAU,SAAS,MAAM;AAClC;","names":[]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface VaultContract {
|
|
2
|
+
purpose: string;
|
|
3
|
+
folders: string[];
|
|
4
|
+
statuses: string[];
|
|
5
|
+
types: string[];
|
|
6
|
+
extraPrimitives: string[];
|
|
7
|
+
kind?: 'channel' | 'secure';
|
|
8
|
+
}
|
|
9
|
+
declare const SHARED_PRIMITIVES: readonly ["status", "summary", "tags", "pinned", "source_type", "source_ref", "related", "related_vault_notes", "embed", "embed_priority", "embedding_summary"];
|
|
10
|
+
type SharedPrimitive = (typeof SHARED_PRIMITIVES)[number];
|
|
11
|
+
declare const VAULT_CONTRACTS: Record<string, VaultContract>;
|
|
12
|
+
declare const OMNI_CHAT_CONTRACT: VaultContract;
|
|
13
|
+
declare const SECURE_VAULT_CONTRACT: VaultContract;
|
|
14
|
+
declare const DEFAULT_VAULTS: string[];
|
|
15
|
+
declare const LIBRARY_VAULT: "Library";
|
|
16
|
+
declare const KNOWLEDGE_VAULT: "Knowledge";
|
|
17
|
+
|
|
18
|
+
export { DEFAULT_VAULTS, KNOWLEDGE_VAULT, LIBRARY_VAULT, OMNI_CHAT_CONTRACT, SECURE_VAULT_CONTRACT, SHARED_PRIMITIVES, type SharedPrimitive, VAULT_CONTRACTS, type VaultContract };
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
const SHARED_PRIMITIVES = [
|
|
2
|
+
"status",
|
|
3
|
+
"summary",
|
|
4
|
+
"tags",
|
|
5
|
+
"pinned",
|
|
6
|
+
"source_type",
|
|
7
|
+
"source_ref",
|
|
8
|
+
"related",
|
|
9
|
+
"related_vault_notes",
|
|
10
|
+
"embed",
|
|
11
|
+
"embed_priority",
|
|
12
|
+
"embedding_summary"
|
|
13
|
+
];
|
|
14
|
+
const VAULT_CONTRACTS = {
|
|
15
|
+
Ideas: {
|
|
16
|
+
purpose: "Capture ideas from first raw note through shaping, parked state, archived state, or final version.",
|
|
17
|
+
folders: ["Raw", "Shaping", "Parked", "Archived", "Final"],
|
|
18
|
+
statuses: ["raw", "shaping", "parked", "archived", "final"],
|
|
19
|
+
types: [],
|
|
20
|
+
extraPrimitives: ["idea_scope", "confidence", "finalized_at", "next_review"]
|
|
21
|
+
},
|
|
22
|
+
Inspiration: {
|
|
23
|
+
purpose: "Store inspiring examples and refined inspirations that can be deconstructed and reused later.",
|
|
24
|
+
folders: ["Codebases", "Images", "Videos", "Ads", "Websites", "Refined Inspirations"],
|
|
25
|
+
statuses: ["captured", "refined", "archived"],
|
|
26
|
+
types: ["codebase", "image", "video", "ad", "website", "refined_inspiration"],
|
|
27
|
+
extraPrimitives: ["source_title", "source_author", "captured_at", "refined_from", "applied_to"]
|
|
28
|
+
},
|
|
29
|
+
Knowledge: {
|
|
30
|
+
purpose: "Store distilled learning notes by domain, not raw source material.",
|
|
31
|
+
folders: ["AI", "SEO", "Copywriting & Ads", "Business", "Spirituality"],
|
|
32
|
+
statuses: ["draft", "developing", "evergreen", "needs_review", "archived"],
|
|
33
|
+
types: ["principle", "pattern", "primitive", "implementation", "guide", "framework", "note"],
|
|
34
|
+
extraPrimitives: ["domain", "derived_from", "confidence", "review_after", "contradicts"]
|
|
35
|
+
},
|
|
36
|
+
Library: {
|
|
37
|
+
purpose: "Preserve raw/source material by domain as faithfully as practical.",
|
|
38
|
+
folders: ["AI", "SEO", "Copywriting & Ads", "Business", "Spirituality"],
|
|
39
|
+
statuses: ["captured", "processing", "extracted", "cited", "archived"],
|
|
40
|
+
types: ["pdf", "book", "ebook", "blog", "article", "youtube", "video", "audio", "transcript", "dataset", "webpage"],
|
|
41
|
+
extraPrimitives: [
|
|
42
|
+
"domain",
|
|
43
|
+
"source_title",
|
|
44
|
+
"source_author",
|
|
45
|
+
"source_path",
|
|
46
|
+
"published",
|
|
47
|
+
"captured_at",
|
|
48
|
+
"source_hash",
|
|
49
|
+
"extracted_to"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
People: {
|
|
53
|
+
purpose: "Maintain people records by relationship context and commercial lifecycle.",
|
|
54
|
+
folders: ["Work Life Friends", "Family", "Social Media Connection", "Client", "Prospect", "Churned Client"],
|
|
55
|
+
statuses: ["active", "warm", "watch", "inactive", "archived"],
|
|
56
|
+
types: ["person", "organization"],
|
|
57
|
+
extraPrimitives: [
|
|
58
|
+
"person_name",
|
|
59
|
+
"relationship",
|
|
60
|
+
"organization",
|
|
61
|
+
"role",
|
|
62
|
+
"email",
|
|
63
|
+
"slack",
|
|
64
|
+
"website",
|
|
65
|
+
"channels",
|
|
66
|
+
"last_seen",
|
|
67
|
+
"next_touch",
|
|
68
|
+
"source_refs"
|
|
69
|
+
]
|
|
70
|
+
},
|
|
71
|
+
Communications: {
|
|
72
|
+
purpose: "Capture and organize communication records across channels so people, projects, tasks, and decisions can be reconstructed later.",
|
|
73
|
+
folders: ["Inbox", "Email", "Slack", "Messages", "Calls", "Meetings", "Social Media", "Archive"],
|
|
74
|
+
statuses: ["inbox", "triaged", "waiting", "responded", "archived"],
|
|
75
|
+
types: ["email", "slack", "message", "call", "meeting", "social_media", "thread", "decision"],
|
|
76
|
+
extraPrimitives: [
|
|
77
|
+
"channel",
|
|
78
|
+
"participants",
|
|
79
|
+
"person_refs",
|
|
80
|
+
"occurred_at",
|
|
81
|
+
"response_due",
|
|
82
|
+
"waiting_on",
|
|
83
|
+
"thread_ref",
|
|
84
|
+
"linked_task",
|
|
85
|
+
"linked_project",
|
|
86
|
+
"linked_decision"
|
|
87
|
+
]
|
|
88
|
+
},
|
|
89
|
+
Calendar: {
|
|
90
|
+
purpose: "Manage daily, weekly, monthly, event, and reminder notes with Calendar and Periodic Notes.",
|
|
91
|
+
folders: ["Daily", "Weekly", "Monthly", "Quarterly", "Events", "Reminders", "Archive"],
|
|
92
|
+
statuses: ["planned", "scheduled", "done", "missed", "archived"],
|
|
93
|
+
types: ["daily_note", "weekly_note", "monthly_note", "quarterly_note", "event", "reminder", "review"],
|
|
94
|
+
extraPrimitives: [
|
|
95
|
+
"date",
|
|
96
|
+
"starts_at",
|
|
97
|
+
"ends_at",
|
|
98
|
+
"timezone",
|
|
99
|
+
"recurrence",
|
|
100
|
+
"participants",
|
|
101
|
+
"linked_task",
|
|
102
|
+
"linked_project",
|
|
103
|
+
"linked_communication"
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
Tasks: {
|
|
107
|
+
purpose: "Track active work and task history. Archive is a folder inside this vault, not its own vault.",
|
|
108
|
+
folders: ["To-Do", "In Progress", "Complete", "Scheduled", "Blocked", "Archive"],
|
|
109
|
+
statuses: ["to_do", "in_progress", "complete", "scheduled", "blocked", "archived"],
|
|
110
|
+
types: [],
|
|
111
|
+
extraPrimitives: [
|
|
112
|
+
"project",
|
|
113
|
+
"owner",
|
|
114
|
+
"priority",
|
|
115
|
+
"due",
|
|
116
|
+
"reminder_at",
|
|
117
|
+
"reminder_status",
|
|
118
|
+
"blocked_by",
|
|
119
|
+
"completed_at",
|
|
120
|
+
"archive_reason"
|
|
121
|
+
]
|
|
122
|
+
},
|
|
123
|
+
Projects: {
|
|
124
|
+
purpose: "Keep real-world projects as separate islands; top-level folders are real project names.",
|
|
125
|
+
folders: [],
|
|
126
|
+
statuses: ["proposed", "active", "paused", "maintenance", "shipped", "archived"],
|
|
127
|
+
types: [],
|
|
128
|
+
extraPrimitives: [
|
|
129
|
+
"project_name",
|
|
130
|
+
"repo_path",
|
|
131
|
+
"live_url",
|
|
132
|
+
"owner",
|
|
133
|
+
"phase",
|
|
134
|
+
"start_date",
|
|
135
|
+
"ship_date",
|
|
136
|
+
"related_tasks",
|
|
137
|
+
"related_issues"
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
Issues: {
|
|
141
|
+
purpose: "Record issues by whether AI observed them, humans confirmed them, or they are resolved.",
|
|
142
|
+
folders: ["AI Observed", "Human Confirmed", "Resolved"],
|
|
143
|
+
statuses: ["ai_observed", "human_confirmed", "resolved"],
|
|
144
|
+
types: ["tool", "skill", "agent", "workflow", "output", "user_friction", "system", "content", "policy"],
|
|
145
|
+
extraPrimitives: [
|
|
146
|
+
"severity",
|
|
147
|
+
"system",
|
|
148
|
+
"observed_at",
|
|
149
|
+
"detected_by",
|
|
150
|
+
"reproducible",
|
|
151
|
+
"linked_task",
|
|
152
|
+
"linked_improvement",
|
|
153
|
+
"resolved_at"
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
"Improvement Log": {
|
|
157
|
+
purpose: "Track improvements by the system they improve.",
|
|
158
|
+
folders: ["Hermes", "Mastra", "Thorbit", "Skills"],
|
|
159
|
+
statuses: ["proposed", "implemented", "verifying", "effective", "ineffective", "reverted"],
|
|
160
|
+
types: ["prompt", "skill", "script", "workflow", "tool", "template", "policy", "architecture"],
|
|
161
|
+
extraPrimitives: [
|
|
162
|
+
"target_system",
|
|
163
|
+
"linked_issue",
|
|
164
|
+
"implemented_at",
|
|
165
|
+
"verification_metric",
|
|
166
|
+
"verification_window",
|
|
167
|
+
"worked",
|
|
168
|
+
"reverted_at",
|
|
169
|
+
"owner"
|
|
170
|
+
]
|
|
171
|
+
},
|
|
172
|
+
Experiments: {
|
|
173
|
+
purpose: "Run structured tests, A/B tests, hypotheses, and measurable learning loops.",
|
|
174
|
+
folders: ["Proposed", "Running", "Concluded", "Invalidated", "Archived", "Evidence"],
|
|
175
|
+
statuses: ["proposed", "running", "concluded", "invalidated", "archived"],
|
|
176
|
+
types: ["ab_test", "copy_test", "product_test", "workflow_test", "model_test", "research", "hypothesis"],
|
|
177
|
+
extraPrimitives: [
|
|
178
|
+
"hypothesis",
|
|
179
|
+
"metric",
|
|
180
|
+
"baseline",
|
|
181
|
+
"variant_a",
|
|
182
|
+
"variant_b",
|
|
183
|
+
"start_date",
|
|
184
|
+
"end_date",
|
|
185
|
+
"result",
|
|
186
|
+
"decision"
|
|
187
|
+
]
|
|
188
|
+
},
|
|
189
|
+
Sprint: {
|
|
190
|
+
purpose: "Hold the singular active sprint and archive previous sprints.",
|
|
191
|
+
folders: ["Current", "Archive"],
|
|
192
|
+
statuses: ["planned", "active", "reviewing", "completed", "archived"],
|
|
193
|
+
types: [],
|
|
194
|
+
extraPrimitives: [
|
|
195
|
+
"focus",
|
|
196
|
+
"start_at",
|
|
197
|
+
"end_at",
|
|
198
|
+
"capacity_hours",
|
|
199
|
+
"active_project",
|
|
200
|
+
"active_tasks",
|
|
201
|
+
"definition_of_done",
|
|
202
|
+
"reviewed_at"
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
const OMNI_CHAT_CONTRACT = {
|
|
207
|
+
kind: "channel",
|
|
208
|
+
purpose: "A Slack-like communications channel: post messages, reply in threads, react, mention members.",
|
|
209
|
+
folders: [],
|
|
210
|
+
statuses: [],
|
|
211
|
+
types: ["message"],
|
|
212
|
+
extraPrimitives: ["parentMessageId", "mentions"]
|
|
213
|
+
};
|
|
214
|
+
const SECURE_VAULT_CONTRACT = {
|
|
215
|
+
kind: "secure",
|
|
216
|
+
purpose: "Private, encrypted storage for credentials and secrets. Never indexed for semantic search, never shareable (share-vault and share-note both refuse it), stored in a separate table with content encrypted at rest.",
|
|
217
|
+
folders: [],
|
|
218
|
+
statuses: [],
|
|
219
|
+
types: ["credential"],
|
|
220
|
+
extraPrimitives: []
|
|
221
|
+
};
|
|
222
|
+
const DEFAULT_VAULTS = [
|
|
223
|
+
"Ideas",
|
|
224
|
+
"Inspiration",
|
|
225
|
+
"Knowledge",
|
|
226
|
+
"Library",
|
|
227
|
+
"People",
|
|
228
|
+
"Communications",
|
|
229
|
+
"Calendar",
|
|
230
|
+
"Tasks",
|
|
231
|
+
"Projects",
|
|
232
|
+
"Issues",
|
|
233
|
+
"Improvement Log",
|
|
234
|
+
"Experiments",
|
|
235
|
+
"Sprint"
|
|
236
|
+
];
|
|
237
|
+
const LIBRARY_VAULT = "Library";
|
|
238
|
+
const KNOWLEDGE_VAULT = "Knowledge";
|
|
239
|
+
export {
|
|
240
|
+
DEFAULT_VAULTS,
|
|
241
|
+
KNOWLEDGE_VAULT,
|
|
242
|
+
LIBRARY_VAULT,
|
|
243
|
+
OMNI_CHAT_CONTRACT,
|
|
244
|
+
SECURE_VAULT_CONTRACT,
|
|
245
|
+
SHARED_PRIMITIVES,
|
|
246
|
+
VAULT_CONTRACTS
|
|
247
|
+
};
|
|
248
|
+
//# sourceMappingURL=vault-contracts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/vault-contracts.ts"],"sourcesContent":["export interface VaultContract {\n purpose: string\n folders: string[]\n statuses: string[]\n types: string[]\n extraPrimitives: string[]\n kind?: 'channel' | 'secure'\n}\n\nexport const SHARED_PRIMITIVES = [\n 'status',\n 'summary',\n 'tags',\n 'pinned',\n 'source_type',\n 'source_ref',\n 'related',\n 'related_vault_notes',\n 'embed',\n 'embed_priority',\n 'embedding_summary',\n] as const\n\nexport type SharedPrimitive = (typeof SHARED_PRIMITIVES)[number]\n\nexport const VAULT_CONTRACTS: Record<string, VaultContract> = {\n Ideas: {\n purpose:\n 'Capture ideas from first raw note through shaping, parked state, archived state, or final version.',\n folders: ['Raw', 'Shaping', 'Parked', 'Archived', 'Final'],\n statuses: ['raw', 'shaping', 'parked', 'archived', 'final'],\n types: [],\n extraPrimitives: ['idea_scope', 'confidence', 'finalized_at', 'next_review'],\n },\n Inspiration: {\n purpose:\n 'Store inspiring examples and refined inspirations that can be deconstructed and reused later.',\n folders: ['Codebases', 'Images', 'Videos', 'Ads', 'Websites', 'Refined Inspirations'],\n statuses: ['captured', 'refined', 'archived'],\n types: ['codebase', 'image', 'video', 'ad', 'website', 'refined_inspiration'],\n extraPrimitives: ['source_title', 'source_author', 'captured_at', 'refined_from', 'applied_to'],\n },\n Knowledge: {\n purpose: 'Store distilled learning notes by domain, not raw source material.',\n folders: ['AI', 'SEO', 'Copywriting & Ads', 'Business', 'Spirituality'],\n statuses: ['draft', 'developing', 'evergreen', 'needs_review', 'archived'],\n types: ['principle', 'pattern', 'primitive', 'implementation', 'guide', 'framework', 'note'],\n extraPrimitives: ['domain', 'derived_from', 'confidence', 'review_after', 'contradicts'],\n },\n Library: {\n purpose: 'Preserve raw/source material by domain as faithfully as practical.',\n folders: ['AI', 'SEO', 'Copywriting & Ads', 'Business', 'Spirituality'],\n statuses: ['captured', 'processing', 'extracted', 'cited', 'archived'],\n types: ['pdf', 'book', 'ebook', 'blog', 'article', 'youtube', 'video', 'audio', 'transcript', 'dataset', 'webpage'],\n extraPrimitives: [\n 'domain',\n 'source_title',\n 'source_author',\n 'source_path',\n 'published',\n 'captured_at',\n 'source_hash',\n 'extracted_to',\n ],\n },\n People: {\n purpose: 'Maintain people records by relationship context and commercial lifecycle.',\n folders: ['Work Life Friends', 'Family', 'Social Media Connection', 'Client', 'Prospect', 'Churned Client'],\n statuses: ['active', 'warm', 'watch', 'inactive', 'archived'],\n types: ['person', 'organization'],\n extraPrimitives: [\n 'person_name',\n 'relationship',\n 'organization',\n 'role',\n 'email',\n 'slack',\n 'website',\n 'channels',\n 'last_seen',\n 'next_touch',\n 'source_refs',\n ],\n },\n Communications: {\n purpose:\n 'Capture and organize communication records across channels so people, projects, tasks, and decisions can be reconstructed later.',\n folders: ['Inbox', 'Email', 'Slack', 'Messages', 'Calls', 'Meetings', 'Social Media', 'Archive'],\n statuses: ['inbox', 'triaged', 'waiting', 'responded', 'archived'],\n types: ['email', 'slack', 'message', 'call', 'meeting', 'social_media', 'thread', 'decision'],\n extraPrimitives: [\n 'channel',\n 'participants',\n 'person_refs',\n 'occurred_at',\n 'response_due',\n 'waiting_on',\n 'thread_ref',\n 'linked_task',\n 'linked_project',\n 'linked_decision',\n ],\n },\n Calendar: {\n purpose: 'Manage daily, weekly, monthly, event, and reminder notes with Calendar and Periodic Notes.',\n folders: ['Daily', 'Weekly', 'Monthly', 'Quarterly', 'Events', 'Reminders', 'Archive'],\n statuses: ['planned', 'scheduled', 'done', 'missed', 'archived'],\n types: ['daily_note', 'weekly_note', 'monthly_note', 'quarterly_note', 'event', 'reminder', 'review'],\n extraPrimitives: [\n 'date',\n 'starts_at',\n 'ends_at',\n 'timezone',\n 'recurrence',\n 'participants',\n 'linked_task',\n 'linked_project',\n 'linked_communication',\n ],\n },\n Tasks: {\n purpose: 'Track active work and task history. Archive is a folder inside this vault, not its own vault.',\n folders: ['To-Do', 'In Progress', 'Complete', 'Scheduled', 'Blocked', 'Archive'],\n statuses: ['to_do', 'in_progress', 'complete', 'scheduled', 'blocked', 'archived'],\n types: [],\n extraPrimitives: [\n 'project',\n 'owner',\n 'priority',\n 'due',\n 'reminder_at',\n 'reminder_status',\n 'blocked_by',\n 'completed_at',\n 'archive_reason',\n ],\n },\n Projects: {\n purpose: 'Keep real-world projects as separate islands; top-level folders are real project names.',\n folders: [],\n statuses: ['proposed', 'active', 'paused', 'maintenance', 'shipped', 'archived'],\n types: [],\n extraPrimitives: [\n 'project_name',\n 'repo_path',\n 'live_url',\n 'owner',\n 'phase',\n 'start_date',\n 'ship_date',\n 'related_tasks',\n 'related_issues',\n ],\n },\n Issues: {\n purpose: 'Record issues by whether AI observed them, humans confirmed them, or they are resolved.',\n folders: ['AI Observed', 'Human Confirmed', 'Resolved'],\n statuses: ['ai_observed', 'human_confirmed', 'resolved'],\n types: ['tool', 'skill', 'agent', 'workflow', 'output', 'user_friction', 'system', 'content', 'policy'],\n extraPrimitives: [\n 'severity',\n 'system',\n 'observed_at',\n 'detected_by',\n 'reproducible',\n 'linked_task',\n 'linked_improvement',\n 'resolved_at',\n ],\n },\n 'Improvement Log': {\n purpose: 'Track improvements by the system they improve.',\n folders: ['Hermes', 'Mastra', 'Thorbit', 'Skills'],\n statuses: ['proposed', 'implemented', 'verifying', 'effective', 'ineffective', 'reverted'],\n types: ['prompt', 'skill', 'script', 'workflow', 'tool', 'template', 'policy', 'architecture'],\n extraPrimitives: [\n 'target_system',\n 'linked_issue',\n 'implemented_at',\n 'verification_metric',\n 'verification_window',\n 'worked',\n 'reverted_at',\n 'owner',\n ],\n },\n Experiments: {\n purpose: 'Run structured tests, A/B tests, hypotheses, and measurable learning loops.',\n folders: ['Proposed', 'Running', 'Concluded', 'Invalidated', 'Archived', 'Evidence'],\n statuses: ['proposed', 'running', 'concluded', 'invalidated', 'archived'],\n types: ['ab_test', 'copy_test', 'product_test', 'workflow_test', 'model_test', 'research', 'hypothesis'],\n extraPrimitives: [\n 'hypothesis',\n 'metric',\n 'baseline',\n 'variant_a',\n 'variant_b',\n 'start_date',\n 'end_date',\n 'result',\n 'decision',\n ],\n },\n Sprint: {\n purpose: 'Hold the singular active sprint and archive previous sprints.',\n folders: ['Current', 'Archive'],\n statuses: ['planned', 'active', 'reviewing', 'completed', 'archived'],\n types: [],\n extraPrimitives: [\n 'focus',\n 'start_at',\n 'end_at',\n 'capacity_hours',\n 'active_project',\n 'active_tasks',\n 'definition_of_done',\n 'reviewed_at',\n ],\n },\n}\n\nexport const OMNI_CHAT_CONTRACT: VaultContract = {\n kind: 'channel',\n purpose: 'A Slack-like communications channel: post messages, reply in threads, react, mention members.',\n folders: [],\n statuses: [],\n types: ['message'],\n extraPrimitives: ['parentMessageId', 'mentions'],\n}\n\nexport const SECURE_VAULT_CONTRACT: VaultContract = {\n kind: 'secure',\n purpose: 'Private, encrypted storage for credentials and secrets. Never indexed for semantic search, never shareable (share-vault and share-note both refuse it), stored in a separate table with content encrypted at rest.',\n folders: [],\n statuses: [],\n types: ['credential'],\n extraPrimitives: [],\n}\n\nexport const DEFAULT_VAULTS: string[] = [\n 'Ideas',\n 'Inspiration',\n 'Knowledge',\n 'Library',\n 'People',\n 'Communications',\n 'Calendar',\n 'Tasks',\n 'Projects',\n 'Issues',\n 'Improvement Log',\n 'Experiments',\n 'Sprint',\n]\n\nexport const LIBRARY_VAULT = 'Library' as const\n\nexport const KNOWLEDGE_VAULT = 'Knowledge' as const\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { VideoRunStatus } from '../db/video-runs.js';
|
|
2
|
+
|
|
3
|
+
declare const VIDEO_RUN_REAP_MINUTES: number;
|
|
4
|
+
declare const VIDEO_RUN_TIMEOUT_ERROR = "processing timed out";
|
|
5
|
+
declare function isTerminalVideoStatus(status: VideoRunStatus): boolean;
|
|
6
|
+
interface ReapableRun {
|
|
7
|
+
status: VideoRunStatus;
|
|
8
|
+
createdAt: Date;
|
|
9
|
+
updatedAt: Date | null;
|
|
10
|
+
}
|
|
11
|
+
declare function isVideoRunStale(run: ReapableRun, now: Date, reapMinutes?: number): boolean;
|
|
12
|
+
|
|
13
|
+
export { type ReapableRun, VIDEO_RUN_REAP_MINUTES, VIDEO_RUN_TIMEOUT_ERROR, isTerminalVideoStatus, isVideoRunStale };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
const VIDEO_RUN_REAP_MINUTES = Number(process.env.VIDEO_RUN_REAP_MINUTES ?? 45);
|
|
2
|
+
const VIDEO_RUN_TIMEOUT_ERROR = "processing timed out";
|
|
3
|
+
const TERMINAL_VIDEO_STATUSES = /* @__PURE__ */ new Set(["done", "failed"]);
|
|
4
|
+
function isTerminalVideoStatus(status) {
|
|
5
|
+
return TERMINAL_VIDEO_STATUSES.has(status);
|
|
6
|
+
}
|
|
7
|
+
function isVideoRunStale(run, now, reapMinutes = VIDEO_RUN_REAP_MINUTES) {
|
|
8
|
+
if (isTerminalVideoStatus(run.status)) return false;
|
|
9
|
+
const last = run.updatedAt ?? run.createdAt;
|
|
10
|
+
const ageMs = now.getTime() - last.getTime();
|
|
11
|
+
return ageMs > reapMinutes * 6e4;
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
VIDEO_RUN_REAP_MINUTES,
|
|
15
|
+
VIDEO_RUN_TIMEOUT_ERROR,
|
|
16
|
+
isTerminalVideoStatus,
|
|
17
|
+
isVideoRunStale
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=video-reaper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/lib/video-reaper.ts"],"sourcesContent":["import type { VideoRunStatus } from '../db/video-runs'\n\nexport const VIDEO_RUN_REAP_MINUTES = Number(process.env.VIDEO_RUN_REAP_MINUTES ?? 45)\n\nexport const VIDEO_RUN_TIMEOUT_ERROR = 'processing timed out'\n\nconst TERMINAL_VIDEO_STATUSES: ReadonlySet<VideoRunStatus> = new Set(['done', 'failed'])\n\nexport function isTerminalVideoStatus(status: VideoRunStatus): boolean {\n return TERMINAL_VIDEO_STATUSES.has(status)\n}\n\nexport interface ReapableRun {\n status: VideoRunStatus\n createdAt: Date\n updatedAt: Date | null\n}\n\nexport function isVideoRunStale(run: ReapableRun, now: Date, reapMinutes: number = VIDEO_RUN_REAP_MINUTES): boolean {\n if (isTerminalVideoStatus(run.status)) return false\n const last = run.updatedAt ?? run.createdAt\n const ageMs = now.getTime() - last.getTime()\n return ageMs > reapMinutes * 60_000\n}\n"],"mappings":"AAEO,MAAM,yBAAyB,OAAO,QAAQ,IAAI,0BAA0B,EAAE;AAE9E,MAAM,0BAA0B;AAEvC,MAAM,0BAAuD,oBAAI,IAAI,CAAC,QAAQ,QAAQ,CAAC;AAEhF,SAAS,sBAAsB,QAAiC;AACrE,SAAO,wBAAwB,IAAI,MAAM;AAC3C;AAQO,SAAS,gBAAgB,KAAkB,KAAW,cAAsB,wBAAiC;AAClH,MAAI,sBAAsB,IAAI,MAAM,EAAG,QAAO;AAC9C,QAAM,OAAO,IAAI,aAAa,IAAI;AAClC,QAAM,QAAQ,IAAI,QAAQ,IAAI,KAAK,QAAQ;AAC3C,SAAO,QAAQ,cAAc;AAC/B;","names":[]}
|