careervivid 1.12.31 → 1.12.38

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,43 @@
1
+ /**
2
+ * agentAuditLog.ts — Forensic audit trail for every agent tool call.
3
+ *
4
+ * Architecture:
5
+ * PRIMARY: Local JSONL append at ~/.careervivid/agent-audit.log
6
+ * Fast, offline, zero network dependency.
7
+ * Each line is a self-contained JSON record.
8
+ *
9
+ * SECONDARY: Firebase Firestore (jastalk-firebase / agent_audit_logs)
10
+ * Written fire-and-forget (non-blocking). Fails silently.
11
+ * Gives cloud visibility and cross-device forensics via the web dashboard.
12
+ *
13
+ * Usage (in repl.ts):
14
+ * import { auditLog, flushAuditLog } from "./agentAuditLog.js";
15
+ * auditLog({ sessionId, tool: name, args, result, durationMs });
16
+ * // On session end:
17
+ * await flushAuditLog();
18
+ */
19
+ export interface AuditEntry {
20
+ ts: string;
21
+ sessionId: string;
22
+ tool: string;
23
+ args: Record<string, unknown>;
24
+ resultSummary: string;
25
+ durationMs: number;
26
+ ok: boolean;
27
+ }
28
+ export declare let SESSION_ID: string;
29
+ export declare function auditLog(entry: {
30
+ sessionId?: string;
31
+ tool: string;
32
+ args: Record<string, unknown>;
33
+ result: string;
34
+ durationMs: number;
35
+ }): void;
36
+ export declare function flushAuditLog(): Promise<void>;
37
+ export declare function writeSessionSummary(stats: {
38
+ turns: number;
39
+ mutations: number;
40
+ toolCalls: number;
41
+ creditsUsed?: number;
42
+ }): Promise<void>;
43
+ //# sourceMappingURL=agentAuditLog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentAuditLog.d.ts","sourceRoot":"","sources":["../../src/agent/agentAuditLog.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AASH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,OAAO,CAAC;CACb;AAID,eAAO,IAAI,UAAU,QAA2B,CAAC;AA8BjD,wBAAgB,QAAQ,CAAC,KAAK,EAAE;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB,GAAG,IAAI,CAuBP;AAwCD,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAMnD;AAID,wBAAsB,mBAAmB,CAAC,KAAK,EAAE;IAC/C,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwBhB"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * agentAuditLog.ts — Forensic audit trail for every agent tool call.
3
+ *
4
+ * Architecture:
5
+ * PRIMARY: Local JSONL append at ~/.careervivid/agent-audit.log
6
+ * Fast, offline, zero network dependency.
7
+ * Each line is a self-contained JSON record.
8
+ *
9
+ * SECONDARY: Firebase Firestore (jastalk-firebase / agent_audit_logs)
10
+ * Written fire-and-forget (non-blocking). Fails silently.
11
+ * Gives cloud visibility and cross-device forensics via the web dashboard.
12
+ *
13
+ * Usage (in repl.ts):
14
+ * import { auditLog, flushAuditLog } from "./agentAuditLog.js";
15
+ * auditLog({ sessionId, tool: name, args, result, durationMs });
16
+ * // On session end:
17
+ * await flushAuditLog();
18
+ */
19
+ import { appendFileSync, existsSync, mkdirSync } from "fs";
20
+ import { resolve } from "path";
21
+ import { homedir } from "os";
22
+ import { randomUUID } from "crypto";
23
+ // ── Session-level state ───────────────────────────────────────────────────────
24
+ export let SESSION_ID = randomUUID().slice(0, 8);
25
+ const pendingFirestore = [];
26
+ // ── Local JSONL path ──────────────────────────────────────────────────────────
27
+ function getAuditLogPath() {
28
+ const dir = resolve(homedir(), ".careervivid");
29
+ if (!existsSync(dir))
30
+ mkdirSync(dir, { recursive: true });
31
+ return resolve(dir, "agent-audit.log");
32
+ }
33
+ // ── Sanitize args (remove any key that looks like a secret) ─────────────────
34
+ function sanitizeArgs(args) {
35
+ const REDACT_KEYS = /key|secret|password|token|auth|credential/i;
36
+ const out = {};
37
+ for (const [k, v] of Object.entries(args)) {
38
+ if (REDACT_KEYS.test(k)) {
39
+ out[k] = "***REDACTED***";
40
+ }
41
+ else if (typeof v === "string" && v.length > 300) {
42
+ out[k] = v.slice(0, 300) + "…";
43
+ }
44
+ else {
45
+ out[k] = v;
46
+ }
47
+ }
48
+ return out;
49
+ }
50
+ // ── Core log function (sync local + async Firestore) ─────────────────────────
51
+ export function auditLog(entry) {
52
+ const record = {
53
+ ts: new Date().toISOString(),
54
+ sessionId: entry.sessionId ?? SESSION_ID,
55
+ tool: entry.tool,
56
+ args: sanitizeArgs(entry.args),
57
+ resultSummary: entry.result.slice(0, 200).replace(/\n/g, " "),
58
+ durationMs: Math.round(entry.durationMs),
59
+ ok: !entry.result.startsWith("❌"),
60
+ };
61
+ // ── 1. Local JSONL (synchronous, never fails) ─────────────────────────────
62
+ try {
63
+ appendFileSync(getAuditLogPath(), JSON.stringify(record) + "\n", "utf-8");
64
+ }
65
+ catch {
66
+ // Silently swallow — never break the agent because of logging
67
+ }
68
+ // ── 2. Firebase Firestore (fire-and-forget — non-blocking) ───────────────
69
+ pendingFirestore.push(record);
70
+ void writeToFirestore(record).catch(() => {
71
+ // Silently swallow — Firebase being unavailable must not affect the agent
72
+ });
73
+ }
74
+ // ── Firebase write (dynamic import to avoid hard dependency) ─────────────────
75
+ async function writeToFirestore(record) {
76
+ // Only attempt if firebase-admin is installed (it's optional)
77
+ let admin;
78
+ try {
79
+ admin = await import("firebase-admin");
80
+ }
81
+ catch {
82
+ return; // firebase-admin not installed — skip silently
83
+ }
84
+ try {
85
+ if (!admin.apps?.length) {
86
+ // Use Application Default Credentials (works in GCP/Cloud Shell)
87
+ // or the service account key if present
88
+ const keyPath = resolve(homedir(), ".careervivid", "firebase-service-account.json");
89
+ const credential = existsSync(keyPath)
90
+ ? admin.credential.cert(keyPath)
91
+ : admin.credential.applicationDefault();
92
+ admin.initializeApp({
93
+ credential,
94
+ projectId: "jastalk-firebase",
95
+ });
96
+ }
97
+ const db = admin.firestore();
98
+ await db.collection("agent_audit_logs").add({
99
+ ...record,
100
+ createdAt: admin.firestore.FieldValue.serverTimestamp(),
101
+ });
102
+ }
103
+ catch {
104
+ // Any Firebase error is silently swallowed
105
+ }
106
+ }
107
+ // ── Flush pending entries (call on session end) ───────────────────────────────
108
+ export async function flushAuditLog() {
109
+ // Pending Firestore writes are already in-flight via fire-and-forget.
110
+ // Give them 2 seconds to complete before exit.
111
+ if (pendingFirestore.length > 0) {
112
+ await new Promise(r => setTimeout(r, 2000));
113
+ }
114
+ }
115
+ // ── Session summary (call on exit) ─────────────────────────────────────────
116
+ export async function writeSessionSummary(stats) {
117
+ const record = {
118
+ type: "session_summary",
119
+ sessionId: SESSION_ID,
120
+ ts: new Date().toISOString(),
121
+ ...stats,
122
+ };
123
+ try {
124
+ appendFileSync(getAuditLogPath(), JSON.stringify(record) + "\n", "utf-8");
125
+ }
126
+ catch { /* silent */ }
127
+ // Firestore session summary
128
+ let admin;
129
+ try {
130
+ admin = await import("firebase-admin");
131
+ }
132
+ catch {
133
+ return;
134
+ }
135
+ try {
136
+ if (admin.apps?.length) {
137
+ const db = admin.firestore();
138
+ await db.collection("agent_session_summaries").add({
139
+ ...record,
140
+ createdAt: admin.firestore.FieldValue.serverTimestamp(),
141
+ });
142
+ }
143
+ }
144
+ catch { /* silent */ }
145
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../../src/agent/instructions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,aAAa,QAalB,CAAC;AAMT,eAAO,MAAM,cAAc,QAcnB,CAAC;AAMT,eAAO,MAAM,cAAc,QAgBnB,CAAC;AAMT,eAAO,MAAM,kBAAkB,QAoCvB,CAAC;AAMT,eAAO,MAAM,YAAY,QAsCjB,CAAC;AAMT,eAAO,MAAM,iBAAiB,QActB,CAAC;AAMT;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,MAAM,CAyBT"}
1
+ {"version":3,"file":"instructions.d.ts","sourceRoot":"","sources":["../../src/agent/instructions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,eAAO,MAAM,aAAa,QAalB,CAAC;AAMT,eAAO,MAAM,cAAc,QAcnB,CAAC;AAMT,eAAO,MAAM,cAAc,QAgBnB,CAAC;AAMT,eAAO,MAAM,kBAAkB,QAwCvB,CAAC;AAMT,eAAO,MAAM,YAAY,QA2CjB,CAAC;AAMT,eAAO,MAAM,iBAAiB,QActB,CAAC;AAMT;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE;IACzC,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,GAAG,MAAM,CAyBT"}
@@ -75,7 +75,10 @@ export const JOBS_TOOLS_SECTION = `
75
75
  - **delete_resume** — Permanently delete a resume (ask for confirmation first).
76
76
 
77
77
  ### Job Search
78
- - **search_jobs** — Search for jobs scored against the user's resume. Returns results for review (dry_run by default — does NOT auto-save).
78
+ - **search_jobs** — Search for NEW companies/roles NOT yet in the tracker. Returns results for review (dry_run by default — does NOT auto-save). Use for discovery only.
79
+ - **openings_scan** ⭐ — Drill into companies ALREADY in jobs.csv to find their SPECIFIC open roles with direct apply links (uses Greenhouse/Ashby/Lever APIs). Use this instead of search_jobs when the user wants roles at known tracked companies.
80
+ - **openings_list** — List saved job openings found by openings_scan.
81
+ - **openings_apply** — Mark a specific opening as Applied (requires explicit date).
79
82
 
80
83
  ### CSV Pipeline Tracker (tracker_*)
81
84
  These tools read/write jobs.csv — the local career-ops pipeline spreadsheet.
@@ -86,6 +89,7 @@ These tools read/write jobs.csv — the local career-ops pipeline spreadsheet.
86
89
  - **tracker_dashboard** — Full analytics: apply rate, avg scores, salary data, stale count.
87
90
  - **tracker_find_stale** — Surface cold companies with next-action recommendations.
88
91
  - **tracker_inspect_quality**— Scan for duplicates, missing URLs, and corrupted data (read-only).
92
+ - **tracker_recheck_urls** — Re-verify all careers URLs in the tracker; annotates dead links in notes.
89
93
 
90
94
  ### Web Kanban Board (kanban_*)
91
95
  These tools read/write the Firebase Kanban board at careervivid.app/job-tracker.
@@ -109,9 +113,10 @@ export const JOBS_HARNESS = `
109
113
  ## Autonomy Rules (Non-Negotiable)
110
114
 
111
115
  ### What you may do freely (no confirmation needed)
112
- - Call any read-only tool (tracker_list_jobs, tracker_dashboard, tracker_rank_priority, tracker_find_stale, tracker_inspect_quality, search_jobs, get_resume, etc.)
116
+ - Call any read-only tool (tracker_list_jobs, tracker_dashboard, tracker_rank_priority, tracker_find_stale, tracker_inspect_quality, tracker_recheck_urls, openings_scan, openings_list, search_jobs, get_resume, etc.)
113
117
  - Add a new company/job entry via tracker_add_job (when the user explicitly names a company or approves a search result)
114
118
  - Update non-status fields (attention_score, excitement, notes, follow_up_date, etc.) via tracker_update_job
119
+ - Run openings_scan to fetch real job postings from tracked companies
115
120
 
116
121
  ### What requires explicit user confirmation
117
122
  - Changing status to "Applied", "Rejected", or "Ghosted" — present the proposed change and wait for "yes"
@@ -138,11 +143,15 @@ If it does, call tracker_update_job instead — never create a duplicate row.
138
143
  | stats, dashboard, apply rate, search health | tracker_dashboard |
139
144
  | stale, cold, neglecting, need attention | tracker_find_stale |
140
145
  | duplicates, data quality, audit | tracker_inspect_quality |
146
+ | stale/dead job URLs, link check | tracker_recheck_urls |
141
147
  | adding a company, new job | tracker_add_job |
142
148
  | updating status, marking applied, follow-up | tracker_update_job |
143
149
  | Kanban board, web tracker | kanban_list_jobs |
144
150
  | resume, background, skills, experience | get_resume |
145
- | find jobs, search roles | get_resume search_jobs |
151
+ | specific roles at tracked companies | openings_scan |
152
+ | view saved openings | openings_list |
153
+ | applied to a specific opening | openings_apply |
154
+ | find NEW companies/roles not yet in tracker | get_resume → search_jobs |
146
155
  `.trim();
147
156
  // ---------------------------------------------------------------------------
148
157
  // §6 — Greeting protocol (shared across modes)
@@ -0,0 +1,21 @@
1
+ /**
2
+ * jobOpenings.ts — Job Openings Drill-Down Tools
3
+ *
4
+ * Bridges jobs.csv (company pipeline) → specific open roles with direct apply links.
5
+ *
6
+ * Architecture:
7
+ * jobs.csv → openings_scan → job_openings.csv
8
+ * (company-level) (ATS fetcher) (posting-level)
9
+ *
10
+ * ATS Support:
11
+ * Greenhouse — Free public REST API (boards-api.greenhouse.io)
12
+ * Ashby — HTML parse (JavaScript SPA; titles extracted from embedded JSON)
13
+ * Lever — Public REST API (api.lever.co/v0/postings/{slug})
14
+ * Direct — JSON-LD schema.org/JobPosting + heuristic <a> tag parsing
15
+ */
16
+ import { Tool } from "../Tool.js";
17
+ export declare const OpeningsScanTool: Tool;
18
+ export declare const OpeningsListTool: Tool;
19
+ export declare const OpeningsApplyTool: Tool;
20
+ export declare const ALL_JOB_OPENINGS_TOOLS: Tool[];
21
+ //# sourceMappingURL=jobOpenings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobOpenings.d.ts","sourceRoot":"","sources":["../../../src/agent/tools/jobOpenings.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAgclC,eAAO,MAAM,gBAAgB,EAAE,IA6O9B,CAAC;AAMF,eAAO,MAAM,gBAAgB,EAAE,IA4G9B,CAAC;AAQF,eAAO,MAAM,iBAAiB,EAAE,IA8F/B,CAAC;AAMF,eAAO,MAAM,sBAAsB,EAAE,IAAI,EAIxC,CAAC"}