careermate 0.0.4 → 0.0.6
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/AGENTS.md +11 -7
- package/INSTALL.md +18 -16
- package/README.md +28 -26
- package/THIRD_PARTY_NOTICES.md +2 -3
- package/bin/careermate.mjs +8 -1
- package/dist/career-os/README.md +8 -3
- package/dist/career-os/eop/career-description.md +136 -0
- package/dist/career-os/eop/cover-letter.md +7 -5
- package/dist/career-os/eop/fit-analysis.md +15 -5
- package/dist/career-os/eop/interview-prep.md +209 -21
- package/dist/career-os/eop/job-analysis.md +5 -3
- package/dist/career-os/eop/profile-extraction.md +5 -4
- package/dist/career-os/knowledge/cover-letter.md +4 -4
- package/dist/career-os/knowledge/fit-matching.md +8 -8
- package/dist/career-os/knowledge/interview-behavioral.md +76 -8
- package/dist/career-os/knowledge/interview-technical.md +106 -4
- package/dist/career-os/knowledge/linkedin-profile.md +1 -1
- package/dist/career-os/knowledge/networking-referrals.md +1 -1
- package/dist/career-os/knowledge/offer-evaluation-decision.md +10 -10
- package/dist/career-os/knowledge/portfolio.md +3 -3
- package/dist/career-os/knowledge/verifiers/ats-compat.md +8 -4
- package/dist/career-os/knowledge/verifiers/human-voice.md +2 -2
- package/dist/career-os/knowledge/verifiers/recency-staleness.md +1 -1
- package/dist/career-os/knowledge/verifiers/responsiveness-on-target.md +2 -2
- package/dist/career-os/knowledge/verifiers/truthfulness.md +1 -1
- package/dist/doctor.mjs +1019 -127
- package/dist/mcp.mjs +1036 -126
- package/dist/migrate.mjs +52 -1
- package/dist/public/app.js +42 -16
- package/dist/public/i18n/en/applications.js +23 -0
- package/dist/public/i18n/en/common.js +22 -0
- package/dist/public/i18n/en/documents.js +133 -0
- package/dist/public/i18n/en/home.js +75 -0
- package/dist/public/i18n/en/interview.js +69 -0
- package/dist/public/i18n/en/jobs.js +152 -0
- package/dist/public/i18n/en/nav.js +18 -0
- package/dist/public/i18n/en/profile.js +201 -0
- package/dist/public/i18n/en/settings.js +127 -0
- package/dist/public/i18n/en/status.js +22 -0
- package/dist/public/i18n/en.js +17 -0
- package/dist/public/i18n/ko/applications.js +23 -0
- package/dist/public/i18n/ko/common.js +22 -0
- package/dist/public/i18n/ko/documents.js +133 -0
- package/dist/public/i18n/ko/home.js +63 -0
- package/dist/public/i18n/ko/interview.js +69 -0
- package/dist/public/i18n/ko/jobs.js +152 -0
- package/dist/public/i18n/ko/nav.js +18 -0
- package/dist/public/i18n/ko/profile.js +201 -0
- package/dist/public/i18n/ko/settings.js +127 -0
- package/dist/public/i18n/ko/status.js +23 -0
- package/dist/public/i18n/ko.js +18 -0
- package/dist/public/i18n.js +55 -0
- package/dist/public/index.html +1 -0
- package/dist/public/lib.js +25 -17
- package/dist/public/pages/applications.js +17 -21
- package/dist/public/pages/documents.js +153 -107
- package/dist/public/pages/home.js +88 -53
- package/dist/public/pages/interview.js +105 -51
- package/dist/public/pages/jobs.js +330 -106
- package/dist/public/pages/profile.js +157 -152
- package/dist/public/pages/settings.js +270 -72
- package/dist/public/styles.css +38 -3
- package/dist/web.mjs +859 -103
- package/docs/FAQ.md +26 -5
- package/docs/MCP_TOOLS.md +26 -12
- package/docs/START_WORKFLOW.md +2 -2
- package/docs/SUPPORTED_AI_APPS.md +13 -0
- package/docs/WORKFLOWS.md +80 -23
- package/docs/career-os/README.md +8 -3
- package/docs/career-os/eop/career-description.md +136 -0
- package/docs/career-os/eop/cover-letter.md +7 -5
- package/docs/career-os/eop/fit-analysis.md +15 -5
- package/docs/career-os/eop/interview-prep.md +209 -21
- package/docs/career-os/eop/job-analysis.md +5 -3
- package/docs/career-os/eop/profile-extraction.md +5 -4
- package/docs/career-os/knowledge/cover-letter.md +4 -4
- package/docs/career-os/knowledge/fit-matching.md +8 -8
- package/docs/career-os/knowledge/interview-behavioral.md +76 -8
- package/docs/career-os/knowledge/interview-technical.md +106 -4
- package/docs/career-os/knowledge/linkedin-profile.md +1 -1
- package/docs/career-os/knowledge/networking-referrals.md +1 -1
- package/docs/career-os/knowledge/offer-evaluation-decision.md +10 -10
- package/docs/career-os/knowledge/portfolio.md +3 -3
- package/docs/career-os/knowledge/verifiers/ats-compat.md +8 -4
- package/docs/career-os/knowledge/verifiers/human-voice.md +2 -2
- package/docs/career-os/knowledge/verifiers/recency-staleness.md +1 -1
- package/docs/career-os/knowledge/verifiers/responsiveness-on-target.md +2 -2
- package/docs/career-os/knowledge/verifiers/truthfulness.md +1 -1
- package/package.json +2 -2
- package/packages/core/src/onboarding.ts +2 -1
- package/packages/core/src/services.ts +138 -21
- package/packages/core/src/summary.ts +59 -1
- package/packages/core/src/verify/lint.ts +4 -0
- package/packages/db/src/index.ts +1 -0
- package/packages/db/src/repositories.ts +0 -0
- package/packages/db/src/schema.ts +17 -0
- package/packages/exporters/src/index.ts +28 -17
- package/packages/knowledge/src/index.ts +46 -7
- package/packages/mcp-tools/src/bridge.ts +194 -13
- package/packages/mcp-tools/src/tools.ts +390 -38
- package/packages/mcp-tools/src/update.ts +31 -16
- package/packages/parsers/src/documents.ts +12 -1
- package/packages/prompts/src/humanize.ts +46 -0
- package/packages/prompts/src/index.ts +5 -1
- package/packages/prompts/src/install.ts +4 -4
- package/packages/prompts/src/onboarding.ts +4 -4
- package/packages/prompts/src/system.ts +17 -8
- package/packages/shared/src/enums.ts +14 -4
- package/packages/shared/src/schemas.ts +41 -0
- package/packages/workflows/src/definitions.ts +47 -10
- package/scripts/init.ts +284 -13
- package/dist/site/analytics.js +0 -97
- package/dist/site/favicon.svg +0 -1
- package/dist/site/fonts/PretendardVariable.woff2 +0 -0
- package/dist/site/icon-180.png +0 -0
- package/dist/site/icon-512.png +0 -0
- package/dist/site/index.html +0 -565
- package/dist/site/landing.js +0 -54
- package/dist/site/llms-install.txt +0 -218
- package/dist/site/robots.txt +0 -4
- package/dist/site/sitemap.xml +0 -21
- package/dist/site/start.html +0 -353
- package/dist/site/style.css +0 -559
- package/dist/site/vercel.json +0 -20
package/dist/web.mjs
CHANGED
|
@@ -6746,15 +6746,15 @@ var require_generators = __commonJS({
|
|
|
6746
6746
|
var stack = new Error().stack;
|
|
6747
6747
|
return function() {
|
|
6748
6748
|
var generator = generatorFunction.apply(this, arguments);
|
|
6749
|
-
var
|
|
6749
|
+
var spawn3 = new PromiseSpawn$(
|
|
6750
6750
|
void 0,
|
|
6751
6751
|
void 0,
|
|
6752
6752
|
yieldHandler,
|
|
6753
6753
|
stack
|
|
6754
6754
|
);
|
|
6755
|
-
var ret2 =
|
|
6756
|
-
|
|
6757
|
-
|
|
6755
|
+
var ret2 = spawn3.promise();
|
|
6756
|
+
spawn3._generator = generator;
|
|
6757
|
+
spawn3._promiseFulfilled(void 0);
|
|
6758
6758
|
return ret2;
|
|
6759
6759
|
};
|
|
6760
6760
|
};
|
|
@@ -6769,9 +6769,9 @@ var require_generators = __commonJS({
|
|
|
6769
6769
|
if (typeof generatorFunction !== "function") {
|
|
6770
6770
|
return apiRejection("generatorFunction must be a function\n\n See http://goo.gl/MqrFmX\n");
|
|
6771
6771
|
}
|
|
6772
|
-
var
|
|
6773
|
-
var ret2 =
|
|
6774
|
-
|
|
6772
|
+
var spawn3 = new PromiseSpawn(generatorFunction, this);
|
|
6773
|
+
var ret2 = spawn3.promise();
|
|
6774
|
+
spawn3._run(Promise2.spawn);
|
|
6775
6775
|
return ret2;
|
|
6776
6776
|
};
|
|
6777
6777
|
};
|
|
@@ -28299,7 +28299,7 @@ var require_files = __commonJS({
|
|
|
28299
28299
|
"use strict";
|
|
28300
28300
|
var fs5 = __require("fs");
|
|
28301
28301
|
var url = __require("url");
|
|
28302
|
-
var
|
|
28302
|
+
var os3 = __require("os");
|
|
28303
28303
|
var dirname = __require("path").dirname;
|
|
28304
28304
|
var resolvePath = __require("path").resolve;
|
|
28305
28305
|
var isAbsolutePath = require_path_is_absolute();
|
|
@@ -28341,7 +28341,7 @@ var require_files = __commonJS({
|
|
|
28341
28341
|
var readFile = promises.promisify(fs5.readFile.bind(fs5));
|
|
28342
28342
|
function uriToPath(uriString, platform) {
|
|
28343
28343
|
if (!platform) {
|
|
28344
|
-
platform =
|
|
28344
|
+
platform = os3.platform();
|
|
28345
28345
|
}
|
|
28346
28346
|
var uri = url.parse(uriString);
|
|
28347
28347
|
if (isLocalFileUri(uri) || isRelativeUri(uri)) {
|
|
@@ -39354,12 +39354,12 @@ var require_cjs = __commonJS({
|
|
|
39354
39354
|
});
|
|
39355
39355
|
|
|
39356
39356
|
// apps/web/src/index.ts
|
|
39357
|
-
import { spawn } from "node:child_process";
|
|
39357
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
39358
39358
|
|
|
39359
39359
|
// apps/web/src/server.ts
|
|
39360
39360
|
import http from "node:http";
|
|
39361
39361
|
import path5 from "node:path";
|
|
39362
|
-
import { fileURLToPath } from "node:url";
|
|
39362
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
39363
39363
|
|
|
39364
39364
|
// packages/db/src/paths.ts
|
|
39365
39365
|
import os from "node:os";
|
|
@@ -39681,6 +39681,22 @@ var MIGRATIONS = [
|
|
|
39681
39681
|
|
|
39682
39682
|
COMMIT;
|
|
39683
39683
|
PRAGMA foreign_keys=ON;
|
|
39684
|
+
`,
|
|
39685
|
+
// v3 — per-job timeline entries. Document/cover-letter refs live in payload
|
|
39686
|
+
// snapshots instead of FKs so deleting a document does not erase the history.
|
|
39687
|
+
`
|
|
39688
|
+
CREATE TABLE IF NOT EXISTS application_timeline_events (
|
|
39689
|
+
id TEXT PRIMARY KEY,
|
|
39690
|
+
job_id TEXT NOT NULL REFERENCES jobs(id) ON DELETE CASCADE,
|
|
39691
|
+
type TEXT NOT NULL,
|
|
39692
|
+
title TEXT NOT NULL,
|
|
39693
|
+
summary TEXT,
|
|
39694
|
+
payload TEXT NOT NULL DEFAULT '{}',
|
|
39695
|
+
occurred_at TEXT NOT NULL,
|
|
39696
|
+
created_at TEXT NOT NULL
|
|
39697
|
+
);
|
|
39698
|
+
|
|
39699
|
+
CREATE INDEX IF NOT EXISTS idx_timeline_job ON application_timeline_events(job_id, occurred_at ASC);
|
|
39684
39700
|
`
|
|
39685
39701
|
];
|
|
39686
39702
|
function migrate(db) {
|
|
@@ -39869,6 +39885,13 @@ var ACTIVITY_TYPES = [
|
|
|
39869
39885
|
"interview_prep_saved",
|
|
39870
39886
|
"document_exported"
|
|
39871
39887
|
];
|
|
39888
|
+
var APPLICATION_TIMELINE_TYPES = [
|
|
39889
|
+
"job_saved",
|
|
39890
|
+
"fit_analysis_saved",
|
|
39891
|
+
"cover_letter_version_saved",
|
|
39892
|
+
"application_status_changed",
|
|
39893
|
+
"interview_prep_saved"
|
|
39894
|
+
];
|
|
39872
39895
|
var ENTITY_TYPES = [
|
|
39873
39896
|
"profile",
|
|
39874
39897
|
"experience",
|
|
@@ -44176,11 +44199,19 @@ var ApplicationInputSchema = external_exports.object({
|
|
|
44176
44199
|
applied_at: optLine,
|
|
44177
44200
|
notes: optNote
|
|
44178
44201
|
});
|
|
44202
|
+
var ApplicationSubmissionSchema = external_exports.object({
|
|
44203
|
+
submitted_at: optLine.describe("\uC2E4\uC81C \uC81C\uCD9C\uC77C YYYY-MM-DD"),
|
|
44204
|
+
channel: optLine.describe("\uC81C\uCD9C \uCC44\uB110(\uC6D0\uD2F0\uB4DC/\uC0AC\uB78C\uC778/\uD68C\uC0AC \uCC44\uC6A9\uD398\uC774\uC9C0 \uB4F1)"),
|
|
44205
|
+
cover_letter_id: optLine,
|
|
44206
|
+
cover_letter_version_id: optLine,
|
|
44207
|
+
document_ids: strList.optional().describe("\uC81C\uCD9C\uD55C \uC774\uB825\uC11C\xB7\uACBD\uB825\uAE30\uC220\uC11C\xB7\uD3EC\uD2B8\uD3F4\uB9AC\uC624 \uBB38\uC11C ID \uBAA9\uB85D")
|
|
44208
|
+
});
|
|
44179
44209
|
var ApplicationStatusUpdateSchema = external_exports.object({
|
|
44180
44210
|
job_id: optLine,
|
|
44181
44211
|
application_id: optLine,
|
|
44182
44212
|
status: external_exports.enum(APPLICATION_STATUSES),
|
|
44183
|
-
note: optNote.describe("\uC0C1\uD0DC \uBCC0\uACBD \uC0AC\uC720/\uBA54\uBAA8")
|
|
44213
|
+
note: optNote.describe("\uC0C1\uD0DC \uBCC0\uACBD \uC0AC\uC720/\uBA54\uBAA8"),
|
|
44214
|
+
submission: ApplicationSubmissionSchema.optional().describe("\uC9C0\uC6D0 \uC644\uB8CC \uAE30\uB85D\uC5D0 \uB0A8\uAE38 \uC81C\uCD9C \uC790\uB8CC \uC2A4\uB0C5\uC0F7")
|
|
44184
44215
|
});
|
|
44185
44216
|
var ApplicationRecordSchema = external_exports.object({
|
|
44186
44217
|
...baseRecord,
|
|
@@ -44198,8 +44229,10 @@ var StarGuideSchema = external_exports.object({
|
|
|
44198
44229
|
action: optNote,
|
|
44199
44230
|
result: optNote
|
|
44200
44231
|
});
|
|
44232
|
+
var INTERVIEW_CATEGORIES = ["technical", "behavioral"];
|
|
44201
44233
|
var InterviewQuestionSchema = external_exports.object({
|
|
44202
44234
|
question: external_exports.string().max(MAX_NOTE),
|
|
44235
|
+
category: external_exports.enum(INTERVIEW_CATEGORIES).optional().describe("\uC9C8\uBB38 \uAC08\uB798: 'technical'(\uAE30\uC220\xB7\uC9C1\uBB34 1\uCC28) | 'behavioral'(\uC778\uC131\xB7\uCEEC\uCC98\uD54F\xB7\uC784\uC6D0 2\uCC28, \uC790\uAE30\uC18C\uAC1C\uC11C \uAE30\uBC18). \uC0DD\uB7B5 \uC2DC \uAE30\uC220\uB85C \uAC04\uC8FC."),
|
|
44203
44236
|
intent: external_exports.string().max(MAX_NOTE).optional().describe("\uC9C8\uBB38 \uC758\uB3C4"),
|
|
44204
44237
|
followups: strList.optional().describe("\uC608\uC0C1 \uAF2C\uB9AC \uC9C8\uBB38"),
|
|
44205
44238
|
answer_outline: optBody.describe("\uB2F5\uBCC0 \uAC00\uC774\uB4DC/\uD575\uC2EC \uD3EC\uC778\uD2B8")
|
|
@@ -44227,6 +44260,24 @@ var ActivityRecordSchema = external_exports.object({
|
|
|
44227
44260
|
summary: external_exports.string(),
|
|
44228
44261
|
created_at: isoDateTime
|
|
44229
44262
|
});
|
|
44263
|
+
var ApplicationTimelineInputSchema = external_exports.object({
|
|
44264
|
+
job_id: reqLine,
|
|
44265
|
+
type: external_exports.enum(APPLICATION_TIMELINE_TYPES),
|
|
44266
|
+
title: reqLine,
|
|
44267
|
+
summary: optNote,
|
|
44268
|
+
payload: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
|
|
44269
|
+
occurred_at: optLine
|
|
44270
|
+
});
|
|
44271
|
+
var ApplicationTimelineRecordSchema = external_exports.object({
|
|
44272
|
+
id,
|
|
44273
|
+
job_id: external_exports.string(),
|
|
44274
|
+
type: external_exports.enum(APPLICATION_TIMELINE_TYPES),
|
|
44275
|
+
title: external_exports.string(),
|
|
44276
|
+
summary: external_exports.string().nullable(),
|
|
44277
|
+
payload: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
44278
|
+
occurred_at: isoDateTime,
|
|
44279
|
+
created_at: isoDateTime
|
|
44280
|
+
});
|
|
44230
44281
|
var OnboardingStatusSchema = external_exports.object({
|
|
44231
44282
|
completed: external_exports.boolean(),
|
|
44232
44283
|
has_profile: external_exports.boolean(),
|
|
@@ -44263,7 +44314,7 @@ var ApplicationContextSchema = external_exports.object({
|
|
|
44263
44314
|
});
|
|
44264
44315
|
|
|
44265
44316
|
// packages/shared/src/build-info.ts
|
|
44266
|
-
var APP_VERSION = true ? "0.0.
|
|
44317
|
+
var APP_VERSION = true ? "0.0.6" : "0.0.0-dev";
|
|
44267
44318
|
var BUNDLED = true;
|
|
44268
44319
|
|
|
44269
44320
|
// packages/shared/src/index.ts
|
|
@@ -44357,7 +44408,7 @@ function mapExperience(r) {
|
|
|
44357
44408
|
};
|
|
44358
44409
|
}
|
|
44359
44410
|
function expKey(company, role, start) {
|
|
44360
|
-
return [norm(company), norm(role), norm(start)].join("
|
|
44411
|
+
return [norm(company), norm(role), norm(start)].join("");
|
|
44361
44412
|
}
|
|
44362
44413
|
var experienceRepo = {
|
|
44363
44414
|
list() {
|
|
@@ -44775,6 +44826,7 @@ var coverLetterRepo = {
|
|
|
44775
44826
|
remove(id3) {
|
|
44776
44827
|
const db = getDb();
|
|
44777
44828
|
return tx(() => {
|
|
44829
|
+
db.prepare(`UPDATE applications SET cover_letter_id=NULL, updated_at=? WHERE cover_letter_id=?`).run(now(), id3);
|
|
44778
44830
|
db.prepare(`DELETE FROM cover_letter_versions WHERE cover_letter_id=?`).run(id3);
|
|
44779
44831
|
return db.prepare(`DELETE FROM cover_letters WHERE id=?`).run(id3).changes > 0;
|
|
44780
44832
|
});
|
|
@@ -44863,9 +44915,11 @@ var jobRepo = {
|
|
|
44863
44915
|
remove(id3) {
|
|
44864
44916
|
const db = getDb();
|
|
44865
44917
|
return tx(() => {
|
|
44918
|
+
db.prepare(`UPDATE cover_letters SET job_id=NULL, updated_at=? WHERE job_id=?`).run(now(), id3);
|
|
44866
44919
|
db.prepare(`DELETE FROM fit_analyses WHERE job_id=?`).run(id3);
|
|
44867
44920
|
db.prepare(`DELETE FROM applications WHERE job_id=?`).run(id3);
|
|
44868
44921
|
db.prepare(`DELETE FROM interview_preps WHERE job_id=?`).run(id3);
|
|
44922
|
+
db.prepare(`DELETE FROM application_timeline_events WHERE job_id=?`).run(id3);
|
|
44869
44923
|
return db.prepare(`DELETE FROM jobs WHERE id=?`).run(id3).changes > 0;
|
|
44870
44924
|
});
|
|
44871
44925
|
}
|
|
@@ -44978,7 +45032,7 @@ var applicationRepo = {
|
|
|
44978
45032
|
const m = { ...app, ...input };
|
|
44979
45033
|
getDb().prepare(
|
|
44980
45034
|
`UPDATE applications SET status=?,resume_id=?,cover_letter_id=?,applied_at=?,notes=?,updated_at=? WHERE id=?`
|
|
44981
|
-
).run(m.status, m.resume_id, m.cover_letter_id, m.applied_at, m.notes, now(), app.id);
|
|
45035
|
+
).run(m.status, m.resume_id ?? null, m.cover_letter_id ?? null, m.applied_at ?? null, m.notes ?? null, now(), app.id);
|
|
44982
45036
|
return this.get(app.id);
|
|
44983
45037
|
},
|
|
44984
45038
|
setStatus(jobId, status, note) {
|
|
@@ -45059,6 +45113,48 @@ var activityRepo = {
|
|
|
45059
45113
|
return getDb().prepare(`SELECT * FROM activities ORDER BY created_at DESC LIMIT ?`).all(limit);
|
|
45060
45114
|
}
|
|
45061
45115
|
};
|
|
45116
|
+
function mapTimelineEvent(r) {
|
|
45117
|
+
return {
|
|
45118
|
+
id: r.id,
|
|
45119
|
+
job_id: r.job_id,
|
|
45120
|
+
type: r.type,
|
|
45121
|
+
title: r.title,
|
|
45122
|
+
summary: r.summary,
|
|
45123
|
+
payload: fromJson(r.payload, {}),
|
|
45124
|
+
occurred_at: r.occurred_at,
|
|
45125
|
+
created_at: r.created_at
|
|
45126
|
+
};
|
|
45127
|
+
}
|
|
45128
|
+
var timelineRepo = {
|
|
45129
|
+
add(input) {
|
|
45130
|
+
const ts = now();
|
|
45131
|
+
const id3 = newId("tl_");
|
|
45132
|
+
getDb().prepare(
|
|
45133
|
+
`INSERT INTO application_timeline_events (id,job_id,type,title,summary,payload,occurred_at,created_at)
|
|
45134
|
+
VALUES (?,?,?,?,?,?,?,?)`
|
|
45135
|
+
).run(
|
|
45136
|
+
id3,
|
|
45137
|
+
input.job_id,
|
|
45138
|
+
input.type,
|
|
45139
|
+
input.title,
|
|
45140
|
+
input.summary ?? null,
|
|
45141
|
+
toJson(input.payload ?? {}),
|
|
45142
|
+
input.occurred_at ?? ts,
|
|
45143
|
+
ts
|
|
45144
|
+
);
|
|
45145
|
+
return this.get(id3);
|
|
45146
|
+
},
|
|
45147
|
+
get(id3) {
|
|
45148
|
+
const r = getDb().prepare(`SELECT * FROM application_timeline_events WHERE id=?`).get(id3);
|
|
45149
|
+
return r ? mapTimelineEvent(r) : null;
|
|
45150
|
+
},
|
|
45151
|
+
listByJob(jobId) {
|
|
45152
|
+
return getDb().prepare(`SELECT * FROM application_timeline_events WHERE job_id=? ORDER BY occurred_at ASC, created_at ASC`).all(jobId).map(mapTimelineEvent);
|
|
45153
|
+
},
|
|
45154
|
+
remove(id3) {
|
|
45155
|
+
return getDb().prepare(`DELETE FROM application_timeline_events WHERE id=?`).run(id3).changes > 0;
|
|
45156
|
+
}
|
|
45157
|
+
};
|
|
45062
45158
|
function getEntityCounts() {
|
|
45063
45159
|
const db = getDb();
|
|
45064
45160
|
const ALLOWED_TABLES = /* @__PURE__ */ new Set([
|
|
@@ -45070,7 +45166,8 @@ function getEntityCounts() {
|
|
|
45070
45166
|
"cover_letters",
|
|
45071
45167
|
"jobs",
|
|
45072
45168
|
"applications",
|
|
45073
|
-
"interview_preps"
|
|
45169
|
+
"interview_preps",
|
|
45170
|
+
"application_timeline_events"
|
|
45074
45171
|
]);
|
|
45075
45172
|
const c = (t) => {
|
|
45076
45173
|
if (!ALLOWED_TABLES.has(t)) throw new Error(`getEntityCounts: \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uC740 \uD14C\uC774\uBE14 \uC774\uB984: ${t}`);
|
|
@@ -45085,7 +45182,8 @@ function getEntityCounts() {
|
|
|
45085
45182
|
cover_letters: c("cover_letters"),
|
|
45086
45183
|
jobs: c("jobs"),
|
|
45087
45184
|
applications: c("applications"),
|
|
45088
|
-
interview_preps: c("interview_preps")
|
|
45185
|
+
interview_preps: c("interview_preps"),
|
|
45186
|
+
application_timeline_events: c("application_timeline_events")
|
|
45089
45187
|
};
|
|
45090
45188
|
}
|
|
45091
45189
|
|
|
@@ -45151,7 +45249,7 @@ function injectToken(html) {
|
|
|
45151
45249
|
// apps/web/src/http.ts
|
|
45152
45250
|
import fs3 from "node:fs";
|
|
45153
45251
|
import path3 from "node:path";
|
|
45154
|
-
var MAX_BODY2 =
|
|
45252
|
+
var MAX_BODY2 = 32 * 1024 * 1024;
|
|
45155
45253
|
var Router = class {
|
|
45156
45254
|
routes = [];
|
|
45157
45255
|
add(method, path6, handler) {
|
|
@@ -45330,12 +45428,13 @@ function profileCompleteness(p) {
|
|
|
45330
45428
|
function getOnboardingStatus() {
|
|
45331
45429
|
const profile = profileRepo.get();
|
|
45332
45430
|
const resumes = documentRepo.list("resume");
|
|
45431
|
+
const careerDescriptions = documentRepo.list("career_description");
|
|
45333
45432
|
const coverLetters = coverLetterRepo.list();
|
|
45334
45433
|
const experiences = experienceRepo.list();
|
|
45335
45434
|
const skills = skillRepo.list();
|
|
45336
45435
|
const jobs = jobRepo.list();
|
|
45337
45436
|
const has_profile = !!(profile && profile.name);
|
|
45338
|
-
const has_resume = resumes.length > 0;
|
|
45437
|
+
const has_resume = resumes.length > 0 || careerDescriptions.length > 0;
|
|
45339
45438
|
const has_cover_letter = coverLetters.length > 0;
|
|
45340
45439
|
const has_experience = experiences.length > 0;
|
|
45341
45440
|
const has_skills = skills.length > 0;
|
|
@@ -45738,6 +45837,29 @@ function addSkill(input) {
|
|
|
45738
45837
|
activityRepo.log("profile_updated", `\uAE30\uC220(${skill.name})\uC744 \uCD94\uAC00\uD588\uC2B5\uB2C8\uB2E4.`, "skill", skill.id);
|
|
45739
45838
|
return skill;
|
|
45740
45839
|
}
|
|
45840
|
+
function coverLetterTimelineRef(coverLetter, version, requestedVersionId) {
|
|
45841
|
+
const resolvedVersion = version ?? coverLetter.versions?.find((v) => v.id === requestedVersionId || v.id === coverLetter.current_version_id) ?? null;
|
|
45842
|
+
return {
|
|
45843
|
+
kind: "cover_letter",
|
|
45844
|
+
id: coverLetter.id,
|
|
45845
|
+
title: coverLetter.title,
|
|
45846
|
+
version_id: resolvedVersion?.id ?? requestedVersionId ?? coverLetter.current_version_id,
|
|
45847
|
+
version_no: resolvedVersion?.version_no ?? coverLetter.version_count
|
|
45848
|
+
};
|
|
45849
|
+
}
|
|
45850
|
+
function documentTimelineRef(doc) {
|
|
45851
|
+
return {
|
|
45852
|
+
kind: "document",
|
|
45853
|
+
id: doc.id,
|
|
45854
|
+
title: doc.title,
|
|
45855
|
+
document_kind: doc.kind
|
|
45856
|
+
};
|
|
45857
|
+
}
|
|
45858
|
+
function submittedAtToOccurrence(value) {
|
|
45859
|
+
if (!value) return void 0;
|
|
45860
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(value)) return `${value}T00:00:00.000Z`;
|
|
45861
|
+
return void 0;
|
|
45862
|
+
}
|
|
45741
45863
|
function saveJobPosting(input, id3) {
|
|
45742
45864
|
const job = jobRepo.upsert(input, id3);
|
|
45743
45865
|
const application = applicationRepo.ensure(job.id, "draft");
|
|
@@ -45746,11 +45868,22 @@ function saveJobPosting(input, id3) {
|
|
|
45746
45868
|
}
|
|
45747
45869
|
function saveFitAnalysis(input) {
|
|
45748
45870
|
const job = jobRepo.get(input.job_id);
|
|
45749
|
-
if (!job) throw notFound(
|
|
45871
|
+
if (!job) throw notFound("\uACF5\uACE0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 \uACF5\uACE0\uB97C \uC800\uC7A5\uD55C \uB4A4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694.");
|
|
45750
45872
|
applicationRepo.ensure(job.id, "draft");
|
|
45751
45873
|
const fit = fitRepo.save(input);
|
|
45752
45874
|
const scoreText = fit.score != null ? ` (\uC801\uD569\uB3C4 ${fit.score}\uC810)` : "";
|
|
45753
45875
|
activityRepo.log("fit_analysis_saved", `${job.company} \xB7 ${job.position} \uC801\uD569\uB3C4 \uBD84\uC11D\uC744 \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4${scoreText}.`, "fit_analysis", fit.id);
|
|
45876
|
+
timelineRepo.add({
|
|
45877
|
+
job_id: job.id,
|
|
45878
|
+
type: "fit_analysis_saved",
|
|
45879
|
+
title: "\uC801\uD569\uB3C4 \uBD84\uC11D",
|
|
45880
|
+
summary: fit.score != null ? `\uC885\uD569 ${fit.score}\uC810` : fit.summary ?? void 0,
|
|
45881
|
+
payload: {
|
|
45882
|
+
fit_id: fit.id,
|
|
45883
|
+
score: fit.score
|
|
45884
|
+
},
|
|
45885
|
+
occurred_at: fit.updated_at
|
|
45886
|
+
});
|
|
45754
45887
|
return fit;
|
|
45755
45888
|
}
|
|
45756
45889
|
function saveCoverLetterVersion(input) {
|
|
@@ -45784,51 +45917,123 @@ function saveCoverLetterVersion(input) {
|
|
|
45784
45917
|
"cover_letter",
|
|
45785
45918
|
coverLetter.id
|
|
45786
45919
|
);
|
|
45920
|
+
if (coverLetter.job_id) {
|
|
45921
|
+
timelineRepo.add({
|
|
45922
|
+
job_id: coverLetter.job_id,
|
|
45923
|
+
type: "cover_letter_version_saved",
|
|
45924
|
+
title: "\uC790\uAE30\uC18C\uAC1C\uC11C \uC791\uC131",
|
|
45925
|
+
summary: `${coverLetter.title} v${version.version_no}`,
|
|
45926
|
+
payload: {
|
|
45927
|
+
cover_letter: coverLetterTimelineRef(coverLetter, version)
|
|
45928
|
+
},
|
|
45929
|
+
occurred_at: version.created_at
|
|
45930
|
+
});
|
|
45931
|
+
}
|
|
45787
45932
|
return { coverLetter, version, verification, forced };
|
|
45788
45933
|
}
|
|
45789
|
-
function updateApplicationStatus(jobId, status, note) {
|
|
45934
|
+
function updateApplicationStatus(jobId, status, note, submission) {
|
|
45790
45935
|
const job = jobRepo.get(jobId);
|
|
45791
|
-
if (!job) throw notFound(
|
|
45792
|
-
const
|
|
45793
|
-
|
|
45794
|
-
|
|
45795
|
-
|
|
45796
|
-
|
|
45797
|
-
|
|
45798
|
-
|
|
45936
|
+
if (!job) throw notFound("\uACF5\uACE0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
45937
|
+
const before2 = applicationRepo.getByJob(jobId);
|
|
45938
|
+
const application = tx(() => {
|
|
45939
|
+
let application2 = applicationRepo.setStatus(jobId, status, note);
|
|
45940
|
+
const submittedDocs = (submission?.document_ids ?? []).map((docId) => documentRepo.get(docId)).filter((doc) => !!doc);
|
|
45941
|
+
const submittedCoverLetter = submission?.cover_letter_id ? coverLetterRepo.get(submission.cover_letter_id, true) : null;
|
|
45942
|
+
if (status === "applied" && submission) {
|
|
45943
|
+
const resumeLike = submittedDocs.find((doc) => doc.kind === "resume" || doc.kind === "career_description") ?? submittedDocs[0] ?? null;
|
|
45944
|
+
application2 = applicationRepo.upsert({
|
|
45945
|
+
job_id: jobId,
|
|
45946
|
+
resume_id: resumeLike?.id ?? application2.resume_id ?? void 0,
|
|
45947
|
+
cover_letter_id: submittedCoverLetter?.id ?? application2.cover_letter_id ?? void 0,
|
|
45948
|
+
applied_at: submission.submitted_at ?? application2.applied_at ?? void 0
|
|
45949
|
+
});
|
|
45950
|
+
}
|
|
45951
|
+
activityRepo.log(
|
|
45952
|
+
"application_status_changed",
|
|
45953
|
+
`${job.company} \xB7 ${job.position} \uC0C1\uD0DC\uB97C '${APPLICATION_STATUS_LABELS[status]}'(\uC73C)\uB85C \uBCC0\uACBD\uD588\uC2B5\uB2C8\uB2E4.`,
|
|
45954
|
+
"application",
|
|
45955
|
+
application2.id
|
|
45956
|
+
);
|
|
45957
|
+
const submittedAt = submission?.submitted_at?.trim();
|
|
45958
|
+
const channel = submission?.channel?.trim();
|
|
45959
|
+
const submissionPayload = submission && (submittedAt || channel || submittedCoverLetter || submittedDocs.length > 0) ? {
|
|
45960
|
+
submitted_at: submittedAt || null,
|
|
45961
|
+
channel: channel || null,
|
|
45962
|
+
cover_letter: submittedCoverLetter ? coverLetterTimelineRef(submittedCoverLetter, null, submission.cover_letter_version_id) : null,
|
|
45963
|
+
documents: submittedDocs.map(documentTimelineRef)
|
|
45964
|
+
} : null;
|
|
45965
|
+
timelineRepo.add({
|
|
45966
|
+
job_id: job.id,
|
|
45967
|
+
type: "application_status_changed",
|
|
45968
|
+
title: APPLICATION_STATUS_LABELS[status],
|
|
45969
|
+
summary: channel && status === "applied" ? `${channel}\uB85C \uC81C\uCD9C` : note ?? void 0,
|
|
45970
|
+
payload: {
|
|
45971
|
+
from_status: before2?.status ?? null,
|
|
45972
|
+
status,
|
|
45973
|
+
status_label: APPLICATION_STATUS_LABELS[status],
|
|
45974
|
+
note: note ?? null,
|
|
45975
|
+
submission: submissionPayload
|
|
45976
|
+
},
|
|
45977
|
+
occurred_at: submittedAtToOccurrence(submittedAt)
|
|
45978
|
+
});
|
|
45979
|
+
return application2;
|
|
45980
|
+
});
|
|
45799
45981
|
const interview_unlocked = INTERVIEW_UNLOCK_STATUSES.includes(status);
|
|
45800
45982
|
const hasPrep = !!interviewRepo.getByJob(jobId);
|
|
45801
|
-
const hint = interview_unlocked && !hasPrep ? "\uC11C\uB958 \uB2E8\uACC4\uB97C \uD1B5\uACFC\uD588\uC5B4\uC694. \uC774 \uACF5\uACE0 \uAE30\uC900\uC73C\uB85C \uC608\uC0C1 \uBA74\uC811 \uC9C8\uBB38\uACFC 1\uBD84 \uC790\uAE30\uC18C\uAC1C\uB97C \uC900\uBE44\uD560\uAE4C\uC694?
|
|
45983
|
+
const hint = interview_unlocked && !hasPrep ? "\uC11C\uB958 \uB2E8\uACC4\uB97C \uD1B5\uACFC\uD588\uC5B4\uC694. \uC774 \uACF5\uACE0 \uAE30\uC900\uC73C\uB85C \uC608\uC0C1 \uBA74\uC811 \uC9C8\uBB38\uACFC 1\uBD84 \uC790\uAE30\uC18C\uAC1C\uB97C \uC900\uBE44\uD560\uAE4C\uC694?" : null;
|
|
45802
45984
|
return { application, job, interview_unlocked, hint };
|
|
45803
45985
|
}
|
|
45804
45986
|
function saveInterviewPrep(input) {
|
|
45805
45987
|
const job = jobRepo.get(input.job_id);
|
|
45806
|
-
if (!job) throw notFound(
|
|
45807
|
-
const app = applicationRepo.getByJob(job.id);
|
|
45808
|
-
if (!app || !INTERVIEW_UNLOCK_STATUSES.includes(app.status)) {
|
|
45809
|
-
const current = app ? APPLICATION_STATUS_LABELS[app.status] : "\uBBF8\uC9C0\uC6D0";
|
|
45810
|
-
throw conflict(
|
|
45811
|
-
`\uBA74\uC811 \uC900\uBE44\uB294 '\uC11C\uB958 \uD569\uACA9' \uC774\uC0C1 \uC0C1\uD0DC\uC5D0\uC11C\uB9CC \uC800\uC7A5\uD560 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uD604\uC7AC \uC0C1\uD0DC: '${current}'. \uBA3C\uC800 update_application_status\uB85C \uC0C1\uD0DC\uB97C \uC62C\uB9B0 \uB4A4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694.`
|
|
45812
|
-
);
|
|
45813
|
-
}
|
|
45988
|
+
if (!job) throw notFound("\uACF5\uACE0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
45814
45989
|
const prep = interviewRepo.save(input);
|
|
45815
45990
|
activityRepo.log("interview_prep_saved", `${job.company} \xB7 ${job.position} \uBA74\uC811 \uC900\uBE44 \uC790\uB8CC\uB97C \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4.`, "interview_prep", prep.id);
|
|
45991
|
+
timelineRepo.add({
|
|
45992
|
+
job_id: job.id,
|
|
45993
|
+
type: "interview_prep_saved",
|
|
45994
|
+
title: "\uBA74\uC811 \uC900\uBE44",
|
|
45995
|
+
summary: prep.questions.length > 0 ? `\uC608\uC0C1 \uC9C8\uBB38 ${prep.questions.length}\uAC1C` : prep.notes ?? void 0,
|
|
45996
|
+
payload: {
|
|
45997
|
+
interview_prep_id: prep.id,
|
|
45998
|
+
question_count: prep.questions.length
|
|
45999
|
+
},
|
|
46000
|
+
occurred_at: prep.updated_at
|
|
46001
|
+
});
|
|
45816
46002
|
return prep;
|
|
45817
46003
|
}
|
|
45818
46004
|
|
|
45819
46005
|
// packages/core/src/summary.ts
|
|
45820
46006
|
var ACTIVE = ["draft", "planned", "applied", "document_passed", "interview"];
|
|
46007
|
+
var DEADLINE_ACTIONABLE = ["draft", "planned"];
|
|
46008
|
+
var DEADLINE_SOON_DAYS = 14;
|
|
46009
|
+
var FOLLOWUP_STALE_DAYS = 10;
|
|
46010
|
+
var DAY_MS = 864e5;
|
|
46011
|
+
function daysUntilDate(dateStr, now2) {
|
|
46012
|
+
if (!dateStr) return null;
|
|
46013
|
+
const d = /* @__PURE__ */ new Date(`${dateStr}T00:00:00`);
|
|
46014
|
+
if (isNaN(d.getTime())) return null;
|
|
46015
|
+
const today = new Date(now2);
|
|
46016
|
+
today.setHours(0, 0, 0, 0);
|
|
46017
|
+
return Math.round((d.getTime() - today.getTime()) / DAY_MS);
|
|
46018
|
+
}
|
|
46019
|
+
function daysSinceTimestamp(iso, now2) {
|
|
46020
|
+
if (!iso) return null;
|
|
46021
|
+
const d = new Date(iso);
|
|
46022
|
+
if (isNaN(d.getTime())) return null;
|
|
46023
|
+
return Math.floor((now2.getTime() - d.getTime()) / DAY_MS);
|
|
46024
|
+
}
|
|
45821
46025
|
function jobWithMeta(job) {
|
|
45822
46026
|
const app = applicationRepo.getByJob(job.id);
|
|
45823
46027
|
const fit = fitRepo.getByJob(job.id);
|
|
45824
46028
|
const status = app?.status ?? "draft";
|
|
45825
46029
|
return { ...job, status, status_label: APPLICATION_STATUS_LABELS[status], fit_score: fit?.score ?? null };
|
|
45826
46030
|
}
|
|
45827
|
-
function getHomeSummary() {
|
|
46031
|
+
function getHomeSummary(now2 = /* @__PURE__ */ new Date()) {
|
|
45828
46032
|
const onboarding = getOnboardingStatus();
|
|
45829
46033
|
const jobs = jobRepo.list();
|
|
45830
46034
|
const applications = applicationRepo.list();
|
|
45831
46035
|
const coverLetters = coverLetterRepo.list();
|
|
46036
|
+
const statusByJob = new Map(applications.map((a) => [a.job_id, a]));
|
|
45832
46037
|
const status_breakdown = Object.keys(APPLICATION_STATUS_LABELS).map((status) => ({
|
|
45833
46038
|
status,
|
|
45834
46039
|
label: APPLICATION_STATUS_LABELS[status],
|
|
@@ -45839,6 +46044,19 @@ function getHomeSummary() {
|
|
|
45839
46044
|
const job = jobRepo.get(a.job_id);
|
|
45840
46045
|
return job ? { job, status_label: APPLICATION_STATUS_LABELS[a.status] } : null;
|
|
45841
46046
|
}).filter((x) => x !== null);
|
|
46047
|
+
const deadlines = jobs.map((job) => {
|
|
46048
|
+
const status = statusByJob.get(job.id)?.status ?? "draft";
|
|
46049
|
+
if (!DEADLINE_ACTIONABLE.includes(status)) return null;
|
|
46050
|
+
const days_left = daysUntilDate(job.deadline, now2);
|
|
46051
|
+
if (days_left == null || days_left > DEADLINE_SOON_DAYS) return null;
|
|
46052
|
+
return { job, status, status_label: APPLICATION_STATUS_LABELS[status], days_left };
|
|
46053
|
+
}).filter((x) => x !== null).sort((a, b) => a.days_left - b.days_left).slice(0, 5);
|
|
46054
|
+
const followups = applications.filter((a) => a.status === "applied").map((a) => {
|
|
46055
|
+
const days_since = daysSinceTimestamp(a.applied_at, now2);
|
|
46056
|
+
if (days_since == null || days_since < FOLLOWUP_STALE_DAYS) return null;
|
|
46057
|
+
const job = jobRepo.get(a.job_id);
|
|
46058
|
+
return job ? { job, days_since } : null;
|
|
46059
|
+
}).filter((x) => x !== null).sort((a, b) => b.days_since - a.days_since).slice(0, 5);
|
|
45842
46060
|
return {
|
|
45843
46061
|
onboarding,
|
|
45844
46062
|
counts: {
|
|
@@ -45859,6 +46077,8 @@ function getHomeSummary() {
|
|
|
45859
46077
|
}),
|
|
45860
46078
|
recent_cover_letters: coverLetters.slice(0, 5),
|
|
45861
46079
|
interview_todo,
|
|
46080
|
+
deadlines,
|
|
46081
|
+
followups,
|
|
45862
46082
|
recent_activity: activityRepo.recent(10)
|
|
45863
46083
|
};
|
|
45864
46084
|
}
|
|
@@ -45879,7 +46099,7 @@ CareerMate\uB294 \uC0AC\uC6A9\uC790\uC758 \uCEF4\uD4E8\uD130\uC5D0\uC11C \uB3D9\
|
|
|
45879
46099
|
- \uAE30\uC5B5\uC5D0 \uC758\uC874\uD558\uC9C0 \uB9D0\uACE0, \uB9E4 \uC791\uC5C5 \uC2DC\uC791 \uC2DC \uC2E4\uC81C \uB370\uC774\uD130\uB97C \uB2E4\uC2DC \uBD88\uB7EC\uC624\uC138\uC694.
|
|
45880
46100
|
|
|
45881
46101
|
2. \uACB0\uACFC\uB294 \uBC18\uB4DC\uC2DC \uB2E4\uC2DC \uC800\uC7A5\uD569\uB2C8\uB2E4.
|
|
45882
|
-
- \uBD84\uC11D\xB7\uC791\uC131\uD55C \uB0B4\uC6A9\uC740 \uBA38\uB9BF\uC18D\uC774\uB098 \uB300\uD654\uCC3D\uC5D0\uB9CC \uB0A8\uAE30\uC9C0 \uB9D0\uACE0 \uD574\uB2F9 \uC800\uC7A5 \uD234\uB85C CareerMate\uC5D0 \uAE30\uB85D\uD558\uC138\uC694: \uACF5\uACE0\uB294 \`save_job_posting\`, \uC801\uD569\uB3C4 \uBD84\uC11D\uC740 \`save_fit_analysis\`, \uC790\uAE30\uC18C\uAC1C\uC11C \uBC84\uC804\uC740 \`save_cover_letter_version\`, \uBA74\uC811 \uC900\uBE44\uB294 \`save_interview_prep\`, \uC0C1\uD0DC \uBCC0\uACBD\uC740 \`update_application_status\`.
|
|
46102
|
+
- \uBD84\uC11D\xB7\uC791\uC131\uD55C \uB0B4\uC6A9\uC740 \uBA38\uB9BF\uC18D\uC774\uB098 \uB300\uD654\uCC3D\uC5D0\uB9CC \uB0A8\uAE30\uC9C0 \uB9D0\uACE0 \uD574\uB2F9 \uC800\uC7A5 \uD234\uB85C CareerMate\uC5D0 \uAE30\uB85D\uD558\uC138\uC694: \uACF5\uACE0\uB294 \`save_job_posting\`, \uC801\uD569\uB3C4 \uBD84\uC11D\uC740 \`save_fit_analysis\`, \uC790\uAE30\uC18C\uAC1C\uC11C \uBC84\uC804\uC740 \`save_cover_letter_version\`, \uACBD\uB825\uAE30\uC220\uC11C\uB294 \`add_resume\`(kind=career_description), \uBA74\uC811 \uC900\uBE44\uB294 \`save_interview_prep\`, \uC0C1\uD0DC \uBCC0\uACBD\uC740 \`update_application_status\`.
|
|
45883
46103
|
- \uC800\uC7A5 \uD6C4\uC5D0\uB294 \uBB34\uC5C7\uC774 \uC800\uC7A5\uB418\uC5C8\uB294\uC9C0 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uAC04\uB2E8\uD788 \uC54C\uB824\uC8FC\uC138\uC694.
|
|
45884
46104
|
|
|
45885
46105
|
3. \uB370\uC774\uD130\uB97C \uC9C0\uC5B4\uB0B4\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
|
@@ -45891,23 +46111,32 @@ CareerMate\uB294 \uC0AC\uC6A9\uC790\uC758 \uCEF4\uD4E8\uD130\uC5D0\uC11C \uB3D9\
|
|
|
45891
46111
|
- \uBBFC\uAC10 \uC815\uBCF4(\uC5F0\uB77D\uCC98, \uC8FC\uC18C \uB4F1)\uB294 \uAF2D \uD544\uC694\uD55C \uC791\uC5C5\uC5D0\uB9CC \uC0AC\uC6A9\uD558\uACE0 \uBD88\uD544\uC694\uD558\uAC8C \uB178\uCD9C\uD558\uC9C0 \uB9C8\uC138\uC694.
|
|
45892
46112
|
|
|
45893
46113
|
5. \uC790\uAE30\uC18C\uAC1C\uC11C\uB294 \uC791\uC131 \uC804 \uD655\uC778\uC744 \uBC1B\uC2B5\uB2C8\uB2E4.
|
|
45894
|
-
- \uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uC0C8\uB85C \uC4F0\uAC70\uB098 \uD06C\uAC8C \uACE0\uCE58\uAE30 \uC804\uC5D0, \uC5B4\uB5A4 \uACF5\uACE0\uB97C \uB300\uC0C1\uC73C\uB85C \uC5B4\uB5A4 \uD1A4\uACFC \uAC15\uC870\uC810\uC73C\uB85C \uC4F8\uC9C0 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBA3C\uC800 \uD655\uC778\uD558\uC138\uC694.
|
|
46114
|
+
- \uC790\uAE30\uC18C\uAC1C\uC11C\uB098 \uACBD\uB825\uAE30\uC220\uC11C\uB97C \uC0C8\uB85C \uC4F0\uAC70\uB098 \uD06C\uAC8C \uACE0\uCE58\uAE30 \uC804\uC5D0, \uC5B4\uB5A4 \uACF5\uACE0/\uC9C1\uBB34\uB97C \uB300\uC0C1\uC73C\uB85C \uC5B4\uB5A4 \uD1A4\uACFC \uAC15\uC870\uC810\uC73C\uB85C \uC4F8\uC9C0 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBA3C\uC800 \uD655\uC778\uD558\uC138\uC694.
|
|
45895
46115
|
- \uC791\uC131 \uD6C4\uC5D0\uB294 \`save_cover_letter_version\`\uC73C\uB85C \uBC84\uC804\uC744 \uC800\uC7A5\uD558\uACE0, \uBCC0\uACBD \uC694\uC57D\uC744 \`note\`\uC5D0 \uB0A8\uAE30\uC138\uC694. \uC0AC\uC6A9\uC790\uAC00 \uC6D0\uD558\uBA74 \`export_cover_letter\`\uB85C \uB0B4\uBCF4\uB0B4\uC138\uC694.
|
|
45896
46116
|
|
|
45897
|
-
6. \uC0AC\uC6A9\uC790\uC5D0\uAC8C\uB294 \
|
|
46117
|
+
6. \uC0AC\uC6A9\uC790\uC5D0\uAC8C\uB294 \uC0AC\uC6A9\uC790\uC758 \uC5B8\uC5B4\uB85C \uC27D\uAC8C \uC54C\uB9BD\uB2C8\uB2E4.
|
|
46118
|
+
- **\uC751\uB2F5 \uC5B8\uC5B4 = \uC0AC\uC6A9\uC790\uC758 \uC5B8\uC5B4.** \uC0AC\uC6A9\uC790\uAC00 \uD55C\uAD6D\uC5B4\uB85C \uB9D0\uD558\uBA74 \uD55C\uAD6D\uC5B4\uB85C, \uC601\uC5B4 \uB4F1 \uB2E4\uB978 \uC5B8\uC5B4\uB85C \uB9D0\uD558\uBA74 \uADF8 \uC5B8\uC5B4\uB85C \uB2F5\uD569\uB2C8\uB2E4. \uC774 \uC9C0\uCE68\xB7\uB3C4\uAD6C \uC751\uB2F5\xB7\uD50C\uB808\uC774\uBD81\uC774 \uD55C\uAD6D\uC5B4\uB85C \uC801\uD600 \uC788\uC5B4\uB3C4 \uADF8\uB300\uB85C \uBCF5\uC0AC\uD558\uC9C0 \uB9D0\uACE0 \uC0AC\uC6A9\uC790 \uC5B8\uC5B4\uB85C \uC62E\uACA8 \uC804\uB2EC\uD558\uC138\uC694(\uC0AC\uC2E4\xB7\uC218\uCE58\xB7\uACE0\uC720\uBA85\uC0AC\uB294 \uBCF4\uC874).
|
|
45898
46119
|
- "MCP", "\uD234 \uD638\uCD9C", "job_id" \uAC19\uC740 \uAE30\uC220 \uC6A9\uC5B4\uB294 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC9C1\uC811 \uB178\uCD9C\uD558\uC9C0 \uB9C8\uC138\uC694. "\uACF5\uACE0\uB97C \uC800\uC7A5\uD588\uC5B4\uC694", "\uC801\uD569\uB3C4\uB97C \uBD84\uC11D\uD588\uC5B4\uC694"\uCC98\uB7FC \uC77C\uC0C1\uC801\uC778 \uD45C\uD604\uC73C\uB85C \uC9C4\uD589 \uC0C1\uD669\uC744 \uC54C\uB9AC\uC138\uC694.
|
|
46120
|
+
- \uB3C4\uAD6C \uC751\uB2F5\uC5D0 \`user_message\`\uAC00 \uC788\uC73C\uBA74 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBCF4\uACE0\uD560 \uB54C \uADF8 \uB0B4\uC6A9\uC744 \uC6B0\uC120 \uD65C\uC6A9\uD558\uB418, \uC0AC\uC6A9\uC790\uAC00 \uD55C\uAD6D\uC5B4\uAC00 \uC544\uB2CC \uC5B8\uC5B4\uB85C \uB300\uD654\uD558\uBA74 \uD55C\uAD6D\uC5B4 \uC6D0\uBB38\uC744 \uADF8\uB300\uB85C \uBCF5\uC0AC\uD558\uC9C0 \uB9D0\uACE0 \uC0AC\uC6A9\uC790 \uC5B8\uC5B4\uB85C \uC62E\uACA8 \uC804\uB2EC\uD558\uC138\uC694. \`id\`, \`job_id\`, \`cover_letter_id\`, \`workflow_id\`, JSON \uC6D0\uBB38, \uB3C4\uAD6C \uC774\uB984\uC740 \uB0B4\uBD80 \uC791\uC5C5\uC6A9\uC73C\uB85C\uB9CC \uC4F0\uACE0 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uADF8\uB300\uB85C \uBCF5\uC0AC\uD558\uC9C0 \uB9C8\uC138\uC694.
|
|
46121
|
+
- \uB3C4\uAD6C \uC751\uB2F5\uC5D0 \`suggested_next_action\`\uC774 \uC788\uC73C\uBA74 \uB2E4\uC74C \uD589\uB3D9\uC744 \uAC15\uC694\uD558\uC9C0 \uB9D0\uACE0 \uC120\uD0DD\uC9C0\uB85C \uC81C\uC548\uD558\uC138\uC694.
|
|
45899
46122
|
- \uBB34\uC5C7\uC744 \uD588\uACE0, \uBB34\uC5C7\uC744 \uC54C\uAC8C \uB418\uC5C8\uACE0, \uB2E4\uC74C\uC5D0 \uBB34\uC5C7\uC744 \uD560 \uC218 \uC788\uB294\uC9C0 \uC9E7\uACE0 \uBA85\uD655\uD558\uAC8C \uC804\uB2EC\uD558\uC138\uC694.
|
|
45900
46123
|
|
|
45901
46124
|
7. \uB2E4\uC74C \uB2E8\uACC4\uB97C \uBA3C\uC800 \uC81C\uC548\uD569\uB2C8\uB2E4.
|
|
45902
|
-
- \uC791\uC5C5\uC774 \uB05D\uB098\uBA74 \uC790\uC5F0\uC2A4\uB7EC\uC6B4 \uB2E4\uC74C \uD589\uB3D9\uC744 \uC81C\uC548\uD558\uC138\uC694. \uC608: \uACF5\uACE0 \uBD84\uC11D \uD6C4 \u2192 "\uC774 \uACF5\uACE0\uC5D0 \uB9DE\uCD98 \uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uC368\uB4DC\uB9B4\uAE4C\uC694?", \uC790\uAE30\uC18C\uAC1C\uC11C \uC800\uC7A5 \uD6C4 \u2192 "\uC9C0\uC6D0 \uC0C1\uD0DC\uB97C '\uC9C0\uC6D0 \uC644\uB8CC'\uB85C \uBC14\uAFC0\uAE4C\uC694?", \uC0C1\uD0DC\uAC00 '\uC11C\uB958 \uD569\uACA9'\uC774 \uB418\uBA74 \u2192 "\uBA74\uC811 \uC900\uBE44\uB97C \uB3C4\uC640\uB4DC\uB9B4\uAE4C\uC694?".
|
|
46125
|
+
- \uC791\uC5C5\uC774 \uB05D\uB098\uBA74 \uC790\uC5F0\uC2A4\uB7EC\uC6B4 \uB2E4\uC74C \uD589\uB3D9\uC744 \uC81C\uC548\uD558\uC138\uC694. \uC608: \uACF5\uACE0 \uBD84\uC11D \uD6C4 \u2192 "\uC774 \uACF5\uACE0\uC5D0 \uB9DE\uCD98 \uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uC368\uB4DC\uB9B4\uAE4C\uC694?", \uACBD\uB825\uAE30\uC220\uC11C \uC800\uC7A5 \uD6C4 \u2192 "\uC774 \uACF5\uACE0\uC5D0 \uB9DE\uCDB0 \uC790\uAE30\uC18C\uAC1C\uC11C\uB3C4 \uC815\uB9AC\uD560\uAE4C\uC694?", \uC790\uAE30\uC18C\uAC1C\uC11C \uC800\uC7A5 \uD6C4 \u2192 "\uC9C0\uC6D0 \uC0C1\uD0DC\uB97C '\uC9C0\uC6D0 \uC644\uB8CC'\uB85C \uBC14\uAFC0\uAE4C\uC694?", \uC0C1\uD0DC\uAC00 '\uC11C\uB958 \uD569\uACA9'\uC774 \uB418\uBA74 \u2192 "\uBA74\uC811 \uC900\uBE44\uB97C \uB3C4\uC640\uB4DC\uB9B4\uAE4C\uC694?".
|
|
46126
|
+
- \uACF5\uACE0 \uBD84\uC11D \uD6C4\uC5D0\uB294 \uACE7\uC7A5 \uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uC4F0\uC9C0 \uB9D0\uACE0, \uBC18\uB4DC\uC2DC \uC120\uD0DD\uC9C0\uB97C \uBCF4\uC5EC\uC8FC\uC138\uC694: "1. \uB124, \uC774 \uACF5\uACE0\uC5D0 \uB9DE\uCD98 \uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uC368\uC918" / "2. \uC544\uB2C8\uC694, \uBD84\uC11D\uB9CC \uC800\uC7A5\uD574\uC918". \uC0AC\uC6A9\uC790\uAC00 1\uBC88\uC744 \uACE0\uB978 \uACBD\uC6B0\uC5D0\uB9CC \uC790\uAE30\uC18C\uAC1C\uC11C \uC791\uC131 \uD750\uB984\uC73C\uB85C \uC774\uC5B4\uAC11\uB2C8\uB2E4.
|
|
45903
46127
|
- \`get_onboarding_status\`\uC758 next_steps\uB098 \`open_dashboard\`/\`open_application\`\uC744 \uD65C\uC6A9\uD574 \uC0AC\uC6A9\uC790\uB97C \uB2E4\uC74C \uD589\uB3D9\uC73C\uB85C \uC548\uB0B4\uD558\uC138\uC694.
|
|
45904
46128
|
|
|
45905
|
-
8. \
|
|
46129
|
+
8. \uC5C5\uB370\uC774\uD2B8 \uC694\uCCAD\uC740 \uBA85\uD655\uD558\uAC8C \uCC98\uB9AC\uD569\uB2C8\uB2E4.
|
|
46130
|
+
- \uC0AC\uC6A9\uC790\uAC00 "\uCD5C\uC2E0\uC774\uC57C?", "\uC5C5\uB370\uC774\uD2B8 \uC788\uC5B4?"\uCC98\uB7FC \uD655\uC778\uB9CC \uC694\uCCAD\uD558\uBA74 \`check_for_update\`\uB97C \uD638\uCD9C\uD558\uACE0 \uACB0\uACFC\uB97C \uC26C\uC6B4 \uB9D0\uB85C \uC54C\uB824\uC8FC\uC138\uC694.
|
|
46131
|
+
- \uC0AC\uC6A9\uC790\uAC00 "\uC5C5\uB370\uC774\uD2B8\uD574\uC918", "CareerMate \uC5C5\uB370\uC774\uD2B8\uD574\uC918", "\uCD5C\uC2E0\uC73C\uB85C \uC62C\uB824\uC918"\uCC98\uB7FC \uC801\uC6A9\uC744 \uBA85\uC2DC\uD558\uBA74 \`update_careermate\`\uB97C \uBC14\uB85C \uD638\uCD9C\uD558\uC138\uC694. \uC774 \uB3C4\uAD6C\uAC00 \uCD5C\uC2E0 \uBC84\uC804 \uD655\uC778\uB3C4 \uD568\uAED8 \uD569\uB2C8\uB2E4.
|
|
46132
|
+
- \uC5C5\uB370\uC774\uD2B8 \uC131\uACF5 \uD6C4\uC5D0\uB294 \uC801\uC6A9\uD558\uB824\uBA74 AI \uC571 \uB610\uB294 MCP \uC5F0\uACB0\uC744 \uC7AC\uC2DC\uC791\uD574\uC57C \uD55C\uB2E4\uACE0 \uC548\uB0B4\uD558\uC138\uC694. \uC0AC\uC6A9\uC790 \uCEE4\uB9AC\uC5B4 \uB370\uC774\uD130\uB294 \uB85C\uCEEC\uC5D0 \uBCF4\uC874\uB418\uACE0, npm\uC5D0\uB294 \uACF5\uAC1C \uBC84\uC804 \uC815\uBCF4 \uD655\uC778/\uC124\uCE58 \uC694\uCCAD\uB9CC \uB098\uAC11\uB2C8\uB2E4.
|
|
46133
|
+
|
|
46134
|
+
9. \uAE00\uC740 AI \uD2F0 \uC548 \uB098\uAC8C \uC501\uB2C8\uB2E4.
|
|
45906
46135
|
- \uC790\uAE30\uC18C\uAC1C\uC11C\xB7\uC790\uAE30 PR\xB7\uC9C0\uC6D0 \uBA54\uC77C \uB4F1 \uC0AC\uB78C\uC774 \uC4F4 \uB4EF\uD55C \uAE00\uC744 \uC791\uC131\uD558\uAE30 \uC9C1\uC804\uC5D0\uB294 \`get_writing_style_guide\`\uB97C \uD638\uCD9C\uD574 \uAE00\uC4F0\uAE30 \uADDC\uCE59\uC744 \uAC00\uC838\uC624\uACE0 \uADF8\uB300\uB85C \uC801\uC6A9\uD558\uC138\uC694.
|
|
45907
|
-
- \uBC88\uC5ED\uD22C, "\uC5F4\uC815\uC744 \uAC00\uC9C0\uACE0/\uADC0\uC0AC\uC758 \uBC1C\uC804\uC5D0 \uAE30\uC5EC" \uAC19\uC740 \uD074\uB9AC\uC170, \uAE30\uACC4\uC801 \uBCD1\uB82C(\uCCAB\uC9F8\xB7\uB458\uC9F8\xB7\uC14B\uC9F8), \uC0C1\uD22C\uC801 \uC5F0\uACB0\uC5B4, \uADE0\uC77C\uD55C \uBB38\uC7A5 \uB9AC\uB4EC\uC744 \uD53C\uD558\uACE0 \uB2F4\uBC31\uD558\uACE0 \uAD6C\uCCB4\uC801\uC73C\uB85C \uC501\uB2C8\uB2E4. \uB2E8, \uC0AC\uC2E4\xB7\uC218\uCE58\xB7\uACE0\uC720\uBA85\uC0AC\uB294 \uC808\uB300 \uBC14\uAFB8\uAC70\uB098 \uC9C0\uC5B4\uB0B4\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
|
46136
|
+
- \uBC88\uC5ED\uD22C, "\uC5F4\uC815\uC744 \uAC00\uC9C0\uACE0/\uADC0\uC0AC\uC758 \uBC1C\uC804\uC5D0 \uAE30\uC5EC" \uAC19\uC740 \uD074\uB9AC\uC170, \uAE30\uACC4\uC801 \uBCD1\uB82C(\uCCAB\uC9F8\xB7\uB458\uC9F8\xB7\uC14B\uC9F8), \uC0C1\uD22C\uC801 \uC5F0\uACB0\uC5B4, \uADE0\uC77C\uD55C \uBB38\uC7A5 \uB9AC\uB4EC\uC744 \uD53C\uD558\uACE0 \uB2F4\uBC31\uD558\uACE0 \uAD6C\uCCB4\uC801\uC73C\uB85C \uC501\uB2C8\uB2E4. \uB2E8, \uC0AC\uC2E4\xB7\uC218\uCE58\xB7\uACE0\uC720\uBA85\uC0AC\uB294 \uC808\uB300 \uBC14\uAFB8\uAC70\uB098 \uC9C0\uC5B4\uB0B4\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC774 AI-tell \uBAA9\uB85D\uC740 \uD55C\uAD6D\uC5B4 \uAE00 \uAE30\uC900\uC774\uBA70, \uB2E4\uB978 \uC5B8\uC5B4\uB85C \uC4F8 \uB54C\uB294 \uAC19\uC740 \uC6D0\uB9AC\uB97C \uADF8 \uC5B8\uC5B4\uC758 \uC790\uC5F0\uC2A4\uB7EC\uC6B4 \uAD00\uC2B5\uC73C\uB85C \uC801\uC6A9\uD569\uB2C8\uB2E4(\uC0B0\uCD9C\uBB3C \uC5B8\uC5B4\xB7\uAD00\uD589\uC740 \uB300\uC0C1 \uACF5\uACE0\xB7\uC2DC\uC7A5\uC744 \uB530\uB984).
|
|
45908
46137
|
|
|
45909
|
-
|
|
45910
|
-
- \uACF5\uACE0 \uBD84\uC11D\xB7\uC790\uC18C\uC11C\xB7\uBA74\uC811 \uC790\uB8CC\uCC98\uB7FC \uC0AC\uC6A9\uC790 \uB300\uBA74 \uACB0\uACFC\uB97C \uB9CC\uB4E4\uAE30 \uC804\uC5D0\uB294, \uC989\uB2F5\uD558\uC9C0 \uB9D0\uACE0 \`get_workflow_guide\`(workflow_id \uC9C0\uC815)\uB97C \uBA3C\uC800 \uD638\uCD9C\uD574 \uADF8 \uC791\uC5C5\uC758 \uC804\uBB38\uAC00 \uC2E4\uD589 \uC808\uCC28(EOP)\uC640 \uC801\uC6A9\uD560 \uD50C\uB808\uC774\uBD81\xB7\uAC80\uC99D\uAE30 \uC21C\uC11C\uB97C \uBC1B\uC73C\uC138\uC694. \uC774\uC5B4 \`get_playbook\`\uC73C\uB85C \uB3C4\uBA54\uC778 \uC9C0\uC2DD\uC744 \uBC1B\uC544 \uC791\uC131\uD558\uACE0, save\uB85C \uC800\uC7A5\uD558\uAE30 \uC9C1\uC804 \`get_verifier\`\uB85C \uAC80\uC99D \uB8E8\uBE0C\uB9AD\uC744 \uBC1B\uC544 **\uB2F9\uC2E0\uC774 \uC9C1\uC811** \uC810\uAC80\xB7\uC218\uC815\uD55C \uB4A4 \uC800\uC7A5\uD569\uB2C8\uB2E4.
|
|
46138
|
+
10. \uC804\uBB38\uAC00 \uC808\uCC28\uB85C \uB9CC\uB4E4\uACE0, \uC800\uC7A5 \uC804 \uB2F9\uC2E0\uC774 \uC790\uAC00\uAC80\uC99D\uD569\uB2C8\uB2E4.
|
|
46139
|
+
- \uACF5\uACE0 \uBD84\uC11D\xB7\uC790\uC18C\uC11C\xB7\uACBD\uB825\uAE30\uC220\uC11C\xB7\uBA74\uC811 \uC790\uB8CC\uCC98\uB7FC \uC0AC\uC6A9\uC790 \uB300\uBA74 \uACB0\uACFC\uB97C \uB9CC\uB4E4\uAE30 \uC804\uC5D0\uB294, \uC989\uB2F5\uD558\uC9C0 \uB9D0\uACE0 \`get_workflow_guide\`(workflow_id \uC9C0\uC815)\uB97C \uBA3C\uC800 \uD638\uCD9C\uD574 \uADF8 \uC791\uC5C5\uC758 \uC804\uBB38\uAC00 \uC2E4\uD589 \uC808\uCC28(EOP)\uC640 \uC801\uC6A9\uD560 \uD50C\uB808\uC774\uBD81\xB7\uAC80\uC99D\uAE30 \uC21C\uC11C\uB97C \uBC1B\uC73C\uC138\uC694. \uC774\uC5B4 \`get_playbook\`\uC73C\uB85C \uB3C4\uBA54\uC778 \uC9C0\uC2DD\uC744 \uBC1B\uC544 \uC791\uC131\uD558\uACE0, save\uB85C \uC800\uC7A5\uD558\uAE30 \uC9C1\uC804 \`get_verifier\`\uB85C \uAC80\uC99D \uB8E8\uBE0C\uB9AD\uC744 \uBC1B\uC544 **\uB2F9\uC2E0\uC774 \uC9C1\uC811** \uC810\uAC80\xB7\uC218\uC815\uD55C \uB4A4 \uC800\uC7A5\uD569\uB2C8\uB2E4.
|
|
45911
46140
|
- CareerMate\uB294 \uC2AC\uB86D \uBC00\uB3C4\xB7\uD0A4\uC6CC\uB4DC \uB9E4\uCE6D\uCC98\uB7FC \uC140 \uC218 \uC788\uB294 \uD56D\uBAA9\uB9CC \uBCF4\uC870\uB85C \uB3D5\uACE0, \uC758\uBBF8 \uD310\uB2E8(\uC774 \uAE00\uC774 \uC9C8\uBB38\uC5D0 \uB2F5\uD558\uB294\uAC00\xB7\uD1A4\uC774 \uB9DE\uB294\uAC00)\uC740 \uB2F9\uC2E0\uC774 \uD569\uB2C8\uB2E4. \uC0AC\uC2E4\xB7\uC218\uCE58\xB7\uACE0\uC720\uBA85\uC0AC\uB294 \uADF8\uB300\uB85C \uBCF4\uC874\uD569\uB2C8\uB2E4.
|
|
45912
46141
|
|
|
45913
46142
|
# \uC791\uC5C5 \uBC29\uC2DD \uC694\uC57D
|
|
@@ -45925,7 +46154,7 @@ var INSTALL_PROMPT_CLAUDE = `Claude\uC57C, \uC544\uB798 CareerMate \uC124\uCE58
|
|
|
45925
46154
|
4. \uADF8\uB2E4\uC74C \uB098\uC5D0\uAC8C \uC774\uB825\uC11C\uB098 \uC790\uAE30\uC18C\uAC1C\uC11C \uD30C\uC77C\uC744 \uC5C5\uB85C\uB4DC\uD558\uB77C\uACE0 \uC548\uB0B4\uD574\uC918.
|
|
45926
46155
|
5. \uB0B4\uAC00 \uC62C\uB9B0 \uD30C\uC77C\uC744 \uBC14\uD0D5\uC73C\uB85C \uB0B4 \uD504\uB85C\uD544\uC744 \uAD6C\uC870\uD654\uD574\uC11C \`save_profile\`\uB85C CareerMate\uC5D0 \uC800\uC7A5\uD558\uACE0, \uC628\uBCF4\uB529\uC744 \uC2DC\uC791\uD574\uC918.
|
|
45927
46156
|
|
|
45928
|
-
\uAE30\uC220 \uC6A9\uC5B4\uB294 \uCD5C\uB300\uD55C \uBE7C\uACE0, \uB9E4 \uB2E8\uACC4\uB9C8\uB2E4 \uC9C0\uAE08 \uBB58 \uD558\uACE0 \uC788\uB294\uC9C0 \
|
|
46157
|
+
\uAE30\uC220 \uC6A9\uC5B4\uB294 \uCD5C\uB300\uD55C \uBE7C\uACE0, \uB9E4 \uB2E8\uACC4\uB9C8\uB2E4 \uC9C0\uAE08 \uBB58 \uD558\uACE0 \uC788\uB294\uC9C0 \uB0B4\uAC00 \uC4F0\uB294 \uC5B8\uC5B4\uB85C \uC27D\uAC8C \uC54C\uB824\uC918. \uB9C9\uD788\uB294 \uBD80\uBD84\uC774 \uC788\uC73C\uBA74 \uCD94\uCE21\uD558\uC9C0 \uB9D0\uACE0 \uB098\uC5D0\uAC8C \uBB3C\uC5B4\uBD10\uC918.`;
|
|
45929
46158
|
var INSTALL_PROMPT_CHATGPT = `ChatGPT\uC57C, \uC544\uB798 \uD398\uC774\uC9C0\uB97C \uC77D\uACE0 \uB0B4 \uCEF4\uD4E8\uD130\uC5D0 CareerMate\uB97C \uC124\uCE58\uD558\uACE0 \uC124\uC815\uD574\uC918. \uC124\uCE58\uAC00 \uB05D\uB098\uBA74 \uC5F0\uACB0 \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uACE0, \uB098\uC5D0\uAC8C \uC774\uB825\uC11C\uB098 \uC790\uAE30\uC18C\uAC1C\uC11C \uD30C\uC77C\uC744 \uC5C5\uB85C\uB4DC\uD558\uB77C\uACE0 \uC548\uB0B4\uD574\uC918. \uADF8\uB2E4\uC74C \uB0B4 \uD504\uB85C\uD544\uC744 \uAD6C\uC870\uD654\uD574\uC11C CareerMate\uC5D0 \uC800\uC7A5\uD574\uC918.
|
|
45930
46159
|
|
|
45931
46160
|
\uAD6C\uCCB4\uC801\uC73C\uB85C\uB294 \uC774\uB807\uAC8C \uD574\uC918.
|
|
@@ -45935,7 +46164,7 @@ var INSTALL_PROMPT_CHATGPT = `ChatGPT\uC57C, \uC544\uB798 \uD398\uC774\uC9C0\uB9
|
|
|
45935
46164
|
4. \uC774\uB825\uC11C\xB7\uC790\uAE30\uC18C\uAC1C\uC11C \uD30C\uC77C\uC744 \uC5C5\uB85C\uB4DC\uD558\uB77C\uACE0 \uB098\uC5D0\uAC8C \uC548\uB0B4\uD574\uC918.
|
|
45936
46165
|
5. \uC62C\uB9B0 \uD30C\uC77C\uB85C \uB0B4 \uD504\uB85C\uD544\uC744 \uC815\uB9AC\uD574\uC11C \`save_profile\`\uB85C \uC800\uC7A5\uD558\uACE0 \uC628\uBCF4\uB529\uC744 \uC2DC\uC791\uD574\uC918.
|
|
45937
46166
|
|
|
45938
|
-
\uC9C4\uD589 \uC0C1\uD669\uC740 \uD56D\uC0C1 \
|
|
46167
|
+
\uC9C4\uD589 \uC0C1\uD669\uC740 \uD56D\uC0C1 \uB0B4\uAC00 \uC4F0\uB294 \uC5B8\uC5B4\uB85C \uC27D\uAC8C \uC124\uBA85\uD558\uACE0, \uD655\uC2E4\uD558\uC9C0 \uC54A\uC740 \uC815\uBCF4\uB294 \uC9C0\uC5B4\uB0B4\uC9C0 \uB9D0\uACE0 \uB098\uC5D0\uAC8C \uBB3C\uC5B4\uBD10\uC918.`;
|
|
45939
46168
|
var INSTALL_PROMPT_GENERIC = `\uC548\uB155, \uC544\uB798 CareerMate \uC124\uCE58 \uC548\uB0B4(\uC124\uCE58 \uD398\uC774\uC9C0 \uB610\uB294 INSTALL.md)\uB97C \uC77D\uACE0 \uB0B4 \uCEF4\uD4E8\uD130\uC5D0 CareerMate\uB97C \uC124\uCE58\uD558\uACE0 \uC124\uC815\uD574\uC918.
|
|
45940
46169
|
|
|
45941
46170
|
CareerMate\uB294 \uB0B4 \uCEE4\uB9AC\uC5B4 \uB370\uC774\uD130(\uD504\uB85C\uD544\xB7\uC774\uB825\uC11C\xB7\uC790\uAE30\uC18C\uAC1C\uC11C\xB7\uC9C0\uC6D0 \uD604\uD669)\uB97C \uB0B4 \uCEF4\uD4E8\uD130\uC5D0 \uC800\uC7A5\uD558\uACE0, MCP\uB97C \uD1B5\uD574 \uB108(\uB0B4 AI)\uAC00 \uADF8 \uB370\uC774\uD130\uB97C \uC77D\uACE0 \uC4F8 \uC218 \uC788\uAC8C \uD574\uC8FC\uB294 \uB3C4\uAD6C\uC57C. \uBD84\uC11D\uACFC \uC791\uC131\uC740 \uC804\uBD80 \uB124\uAC00 \uD574.
|
|
@@ -45943,21 +46172,21 @@ CareerMate\uB294 \uB0B4 \uCEE4\uB9AC\uC5B4 \uB370\uC774\uD130(\uD504\uB85C\uD544
|
|
|
45943
46172
|
\uC774\uB807\uAC8C \uC9C4\uD589\uD574\uC918.
|
|
45944
46173
|
1. \uC124\uCE58 \uC548\uB0B4 \uBB38\uC11C\uB97C \uB05D\uAE4C\uC9C0 \uC77D\uACE0 \uADF8\uB300\uB85C \uB530\uB77C \uC124\uCE58\uD574.
|
|
45945
46174
|
2. \uB124\uAC00 \uC4F0\uB294 AI \uB3C4\uAD6C\uC5D0 CareerMate MCP \uC11C\uBC84\uB97C \uC5F0\uACB0(\uC124\uC815)\uD574\uC918.
|
|
45946
|
-
3. \uC5F0\uACB0 \uD6C4 \`get_onboarding_status\`\uB97C \uD638\uCD9C\uD574 \uC5F0\uACB0 \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uACE0, \uACB0\uACFC\uB97C \
|
|
46175
|
+
3. \uC5F0\uACB0 \uD6C4 \`get_onboarding_status\`\uB97C \uD638\uCD9C\uD574 \uC5F0\uACB0 \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uACE0, \uACB0\uACFC\uB97C \uB0B4\uAC00 \uC4F0\uB294 \uC5B8\uC5B4\uB85C \uC27D\uAC8C \uC54C\uB824\uC918.
|
|
45947
46176
|
4. \uB098\uC5D0\uAC8C \uC774\uB825\uC11C\uB098 \uC790\uAE30\uC18C\uAC1C\uC11C \uD30C\uC77C\uC744 \uC5C5\uB85C\uB4DC\uD558\uB77C\uACE0 \uC548\uB0B4\uD574\uC918.
|
|
45948
46177
|
5. \uC62C\uB9B0 \uD30C\uC77C\uB85C \uB0B4 \uD504\uB85C\uD544\uC744 \uAD6C\uC870\uD654\uD574\uC11C \`save_profile\`\uB85C \uC800\uC7A5\uD558\uACE0 \uC628\uBCF4\uB529\uC744 \uC2DC\uC791\uD574\uC918.
|
|
45949
46178
|
|
|
45950
|
-
\uB9E4 \uB2E8\uACC4\uB9C8\uB2E4 \
|
|
46179
|
+
\uB9E4 \uB2E8\uACC4\uB9C8\uB2E4 \uB0B4\uAC00 \uC4F0\uB294 \uC5B8\uC5B4\uB85C \uC27D\uAC8C \uC124\uBA85\uD558\uACE0, \uBD88\uD655\uC2E4\uD55C \uB0B4\uC6A9\uC740 \uC9C0\uC5B4\uB0B4\uC9C0 \uB9D0\uACE0 \uB098\uC5D0\uAC8C \uD655\uC778\uD574\uC918.`;
|
|
45951
46180
|
|
|
45952
46181
|
// packages/prompts/src/onboarding.ts
|
|
45953
|
-
var ONBOARDING_PROMPT = `\uC774\uC81C CareerMate\uC5D0 \uC5F0\uACB0\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uC758 \uCEE4\uB9AC\uC5B4 \uB370\uC774\uD130 \uCCAB \uC14B\uC5C5(\uC628\uBCF4\uB529)\uC744 \uB3C4\uC640\uC8FC\uC138\uC694.
|
|
46182
|
+
var ONBOARDING_PROMPT = `\uC774\uC81C CareerMate\uC5D0 \uC5F0\uACB0\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uC758 \uCEE4\uB9AC\uC5B4 \uB370\uC774\uD130 \uCCAB \uC14B\uC5C5(\uC628\uBCF4\uB529)\uC744 \uB3C4\uC640\uC8FC\uC138\uC694. \uC0AC\uC6A9\uC790\uAC00 \uC4F0\uB294 \uC5B8\uC5B4\uB85C \uC548\uB0B4\uD558\uC138\uC694 \u2014 \uC774 \uC548\uB0B4\uBB38\uC774 \uD55C\uAD6D\uC5B4\uB77C\uB3C4 \uC0AC\uC6A9\uC790\uAC00 \uB2E4\uB978 \uC5B8\uC5B4\uB85C \uB9D0\uD558\uBA74 \uADF8 \uC5B8\uC5B4\uB85C \uB2F5\uD569\uB2C8\uB2E4.
|
|
45954
46183
|
|
|
45955
46184
|
# 1\uB2E8\uACC4 \u2014 \uD604\uC7AC \uC0C1\uD0DC \uD655\uC778
|
|
45956
46185
|
- \uBA3C\uC800 \`get_onboarding_status\`\uB97C \uD638\uCD9C\uD558\uC138\uC694. \uACB0\uACFC\uC758 has_profile / has_resume / has_cover_letter / has_experience / has_skills / has_job, profile_completeness(\uC644\uC131\uB3C4), next_steps(\uB2E4\uC74C \uB2E8\uACC4)\uB97C \uD655\uC778\uD569\uB2C8\uB2E4.
|
|
45957
|
-
- \uC0AC\uC6A9\uC790\uC5D0\uAC8C "\uC9C0\uAE08\uAE4C\uC9C0 \uB4F1\uB85D\uB41C \uC815\uBCF4"\uC640 "\uC55E\uC73C\uB85C \uCC44\uC6B0\uBA74 \uC88B\uC740 \uC815\uBCF4"\uB97C \
|
|
46186
|
+
- \uC0AC\uC6A9\uC790\uC5D0\uAC8C "\uC9C0\uAE08\uAE4C\uC9C0 \uB4F1\uB85D\uB41C \uC815\uBCF4"\uC640 "\uC55E\uC73C\uB85C \uCC44\uC6B0\uBA74 \uC88B\uC740 \uC815\uBCF4"\uB97C \uC0AC\uC6A9\uC790\uC758 \uC5B8\uC5B4\uB85C \uC27D\uACE0 \uC9E7\uAC8C \uC548\uB0B4\uD558\uC138\uC694. (\uC774\uBBF8 \uCC44\uC6CC\uC9C4 \uD56D\uBAA9\uC740 \uB2E4\uC2DC \uBB3B\uC9C0 \uB9C8\uC138\uC694.)
|
|
45958
46187
|
|
|
45959
46188
|
# 2\uB2E8\uACC4 \u2014 \uD504\uB85C\uD544 \uC218\uC9D1 \uBC0F \uC800\uC7A5
|
|
45960
|
-
- \uC0AC\uC6A9\uC790\uAC00 \uC62C\uB9B0 \uC774\uB825\uC11C/\uC790\uAE30\uC18C\uAC1C\uC11C \uD30C\uC77C\uC774\uB098 \uC0AC\uC6A9\uC790\uAC00 \uC9C1\uC811 \uC54C\uB824\uC900 \uB0B4\uC6A9\uC744 \uBC14\uD0D5\uC73C\uB85C \uD504\uB85C\uD544\uC744 \uAD6C\uC870\uD654\uD558\uC138\uC694.
|
|
46189
|
+
- \uC0AC\uC6A9\uC790\uAC00 \uC62C\uB9B0 \uC774\uB825\uC11C/\uACBD\uB825\uAE30\uC220\uC11C/\uD3EC\uD2B8\uD3F4\uB9AC\uC624/\uC790\uAE30\uC18C\uAC1C\uC11C \uD30C\uC77C\uC774\uB098 \uC0AC\uC6A9\uC790\uAC00 \uC9C1\uC811 \uC54C\uB824\uC900 \uB0B4\uC6A9\uC744 \uBC14\uD0D5\uC73C\uB85C \uD504\uB85C\uD544\uC744 \uAD6C\uC870\uD654\uD558\uC138\uC694.
|
|
45961
46190
|
- \uC774\uB984, \uC5F0\uB77D\uCC98, \uD55C \uC904 \uC18C\uAC1C(headline), \uC790\uAE30\uC18C\uAC1C \uC694\uC57D(summary), \uD76C\uB9DD \uC9C1\uBB34(desired_roles), \uD76C\uB9DD \uADFC\uBB34 \uC870\uAC74(desired_conditions)\uC744 \uC815\uB9AC\uD569\uB2C8\uB2E4.
|
|
45962
46191
|
- \uAE00\uC4F0\uAE30 \uC120\uD638\uB3C4 \uD568\uAED8 \uBB3C\uC5B4\uBCF4\uC138\uC694: \uC120\uD638 \uBB38\uCCB4(preferred_tone, \uC608: "\uB2F4\uBC31\uD558\uACE0 \uAD6C\uCCB4\uC801")\uC640 \uAC15\uC870\uD558\uACE0 \uC2F6\uC740 \uD575\uC2EC \uD3EC\uC778\uD2B8(emphasis_points). \uC774 \uC815\uBCF4\uB294 \uC774\uD6C4 \uC790\uAE30\uC18C\uAC1C\uC11C \uC791\uC131\uC5D0 \uADF8\uB300\uB85C \uD65C\uC6A9\uB429\uB2C8\uB2E4.
|
|
45963
46192
|
- \uC815\uB9AC\uD55C \uB0B4\uC6A9\uC744 \`save_profile\`\uB85C \uC800\uC7A5\uD558\uC138\uC694. \uD30C\uC77C\uC5D0\uC11C \uC77D\uC5B4\uC628 \uC815\uBCF4\uB294 source\uB97C 'upload', \uC0AC\uC6A9\uC790\uAC00 \uB9D0\uB85C \uC54C\uB824\uC900 \uC815\uBCF4\uB294 'manual'\uB85C \uD45C\uC2DC\uD558\uC138\uC694.
|
|
@@ -45976,7 +46205,7 @@ var ONBOARDING_PROMPT = `\uC774\uC81C CareerMate\uC5D0 \uC5F0\uACB0\uB418\uC5C8\
|
|
|
45976
46205
|
- \uB2E4\uC2DC \`get_onboarding_status\`\uB85C \uC644\uC131\uB3C4\uB97C \uD655\uC778\uD558\uACE0, \uBE44\uC5B4 \uC788\uB294 \uBD80\uBD84\uC774 \uC788\uC73C\uBA74 \uCC44\uC6B0\uC790\uACE0 \uC81C\uC548\uD558\uC138\uC694.
|
|
45977
46206
|
- \uB9C8\uBB34\uB9AC\uB85C \uB2E4\uC74C \uD589\uB3D9\uC744 \uC81C\uC548\uD558\uC138\uC694. \uC608: "\uC9C0\uC6D0\uD558\uACE0 \uC2F6\uC740 \uACF5\uACE0\uAC00 \uC788\uC73C\uBA74 \uB9C1\uD06C\uB098 \uB0B4\uC6A9\uC744 \uBD99\uC5EC\uC8FC\uC138\uC694. \uC801\uD569\uB3C4\uB97C \uBD84\uC11D\uD574\uB4DC\uB9B4\uAC8C\uC694."
|
|
45978
46207
|
|
|
45979
|
-
\uC9C4\uD589 \uB0B4\uB0B4 \uAE30\uC220 \uC6A9\uC5B4(MCP, job_id \uB4F1)\uB294 \uBE7C\uACE0, \uC9C0\uAE08 \uBB34\uC5C7\uC744 \uD558\uACE0 \uC788\uB294\uC9C0 \
|
|
46208
|
+
\uC9C4\uD589 \uB0B4\uB0B4 \uAE30\uC220 \uC6A9\uC5B4(MCP, job_id \uB4F1)\uB294 \uBE7C\uACE0, \uC9C0\uAE08 \uBB34\uC5C7\uC744 \uD558\uACE0 \uC788\uB294\uC9C0 \uC0AC\uC6A9\uC790\uC758 \uC5B8\uC5B4\uB85C \uC27D\uAC8C \uC54C\uB824\uC8FC\uC138\uC694.`;
|
|
45980
46209
|
|
|
45981
46210
|
// packages/prompts/src/humanize.ts
|
|
45982
46211
|
var HUMANIZE_WRITING_GUIDE = `# \uC0AC\uB78C\uC774 \uC4F4 \uAC83\uCC98\uB7FC: \uC790\uAE30\uC18C\uAC1C\uC11C\xB7\uCEE4\uB9AC\uC5B4 \uAE00\uC4F0\uAE30 \uADDC\uCE59
|
|
@@ -45984,6 +46213,8 @@ var HUMANIZE_WRITING_GUIDE = `# \uC0AC\uB78C\uC774 \uC4F4 \uAC83\uCC98\uB7FC: \u
|
|
|
45984
46213
|
\uBAA9\uD45C: \uC0AC\uC2E4\uACFC \uACBD\uD5D8\uC740 100% \uADF8\uB300\uB85C \uB450\uBA74\uC11C, "AI\uAC00 \uC4F4 \uD2F0"\uAC00 \uB098\uB294 \uBB38\uC7A5 \uC2B5\uAD00\uB9CC \uC81C\uAC70\uD55C\uB2E4.
|
|
45985
46214
|
\uAC80\uC5F4\uAE30\uB97C \uC18D\uC774\uB294 \uAC8C \uC544\uB2C8\uB77C, \uCC44\uC6A9 \uB2F4\uB2F9\uC790\uAC00 \uC77D\uAE30\uC5D0 \uC790\uC5F0\uC2A4\uB7FD\uACE0 \uC0AC\uB78C \uB0C4\uC0C8 \uB098\uB294 \uAE00\uC744 \uC4F0\uB294 \uAC83\uC774 \uBAA9\uC801\uC774\uB2E4.
|
|
45986
46215
|
|
|
46216
|
+
> **\uC5B8\uC5B4 \uBC94\uC704:** \uC544\uB798 AI-tell \uBAA9\uB85D\uC740 \uD55C\uAD6D\uC5B4 \uAE00 \uAE30\uC900\uC774\uB2E4. \uC601\uC5B4 \uB4F1 \uB2E4\uB978 \uC5B8\uC5B4\uB85C \uC4F8 \uB54C\uB294 \uC774 \uBAA9\uB85D\uC744 \uADF8\uB300\uB85C \uC801\uC6A9\uD558\uC9C0 \uB9D0\uACE0, **\uAC19\uC740 \uC6D0\uB9AC**(\uD074\uB9AC\uC170\xB7\uAE30\uACC4\uC801 \uBCD1\uB82C\xB7\uACFC\uC7A5 \uC218\uC2DD\xB7\uACF5\uD5C8\uD55C \uC77C\uBC18\uB860 \uC81C\uAC70, \uAD6C\uCCB4\uC131, \uC0AC\uC2E4\xB7\uC218\uCE58 \uBCF4\uC874)\uB97C \uADF8 \uC5B8\uC5B4\uC758 \uC790\uC5F0\uC2A4\uB7EC\uC6B4 \uAD00\uC2B5\uC73C\uB85C \uC801\uC6A9\uD55C\uB2E4. \uACB0\uACFC\uBB3C\uC758 \uC5B8\uC5B4\uB294 \uB300\uC0C1 \uACF5\uACE0\xB7\uC2DC\uC7A5\uC744 \uB530\uB978\uB2E4.
|
|
46217
|
+
|
|
45987
46218
|
## \uC808\uB300 \uC6D0\uCE59
|
|
45988
46219
|
- \uC800\uC7A5\uB41C \uC2E4\uC81C \uACBD\uD5D8\xB7\uC218\uCE58\xB7\uD68C\uC0AC\uBA85\xB7\uACE0\uC720\uBA85\uC0AC\xB7\uC9C1\uC811 \uC778\uC6A9\uC740 \uC808\uB300 \uBC14\uAFB8\uAC70\uB098 \uC9C0\uC5B4\uB0B4\uC9C0 \uC54A\uB294\uB2E4. \uBB38\uC7A5 \uACB0\uB9CC \uB2E4\uB4EC\uB294\uB2E4.
|
|
45989
46220
|
- \uBE48\uCE78\uC774\uB098 \uD655\uC778\uC774 \uD544\uC694\uD55C \uBD80\uBD84\uC740 \uB9E4\uB044\uB7FD\uAC8C \uCC44\uC6CC \uB123\uC9C0 \uB9D0\uACE0 \uADF8\uB300\uB85C \uD45C\uC2DC\uD574 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBB3B\uB294\uB2E4.
|
|
@@ -46075,7 +46306,7 @@ var WORKFLOWS = [
|
|
|
46075
46306
|
trigger: '\uC0AC\uC6A9\uC790\uAC00 \uCC98\uC74C CareerMate\uC5D0 \uC5F0\uACB0\uD588\uAC70\uB098, "\uC2DC\uC791\uD558\uC790 / \uC14B\uC5C5\uD574\uC918 / \uD504\uB85C\uD544 \uB4F1\uB85D"\uC774\uB77C\uACE0 \uC694\uCCAD\uD560 \uB54C.',
|
|
46076
46307
|
steps: [
|
|
46077
46308
|
"`get_onboarding_status`\uB97C \uD638\uCD9C\uD574 \uD604\uC7AC \uB4F1\uB85D \uC0C1\uD0DC(has_profile, has_resume, has_cover_letter, has_experience, has_skills, profile_completeness, next_steps)\uB97C \uD655\uC778\uD55C\uB2E4.",
|
|
46078
|
-
'\uBE44\uC5B4 \uC788\uB294 \uD56D\uBAA9\uC744 \uC0AC\uC6A9\uC790\
|
|
46309
|
+
'\uBE44\uC5B4 \uC788\uB294 \uD56D\uBAA9\uC744 \uC0AC\uC6A9\uC790\uC758 \uC5B8\uC5B4\uB85C \uC27D\uAC8C \uC548\uB0B4\uD558\uACE0, \uBA3C\uC800 "\uAE30\uC874\uC5D0 \uC791\uC131\uD574 \uB454 \uC774\uB825\uC11C\xB7\uACBD\uB825\uAE30\uC220\uC11C\xB7\uC790\uAE30\uC18C\uAC1C\uC11C \uD30C\uC77C\uC774 \uC788\uB294\uC9C0" \uBB3B\uB294\uB2E4(hwp/docx/pdf \uBAA8\uB450 \uAC00\uB2A5).',
|
|
46079
46310
|
'\uD30C\uC77C \uC785\uB825 \uBD84\uAE30: \u2460 \uC0AC\uC6A9\uC790\uAC00 "\uD30C\uC77C\uC774 \uC788\uB2E4"\uACE0 \uD558\uBA74 `open_inbox`\uB85C \uC778\uC785 \uD3F4\uB354\uB97C \uC5F4\uC5B4 \uD30C\uC77C\uC744 \uB123\uAC8C \uD558\uACE0, "\uB2E4 \uB123\uC5C8\uB2E4"\uACE0 \uD558\uBA74 `read_inbox`\uB85C \uBCF8\uBB38\uC744 \uC77D\uB294\uB2E4(pdf\xB7\uC774\uBBF8\uC9C0\uB294 read_inbox\uAC00 \uACBD\uB85C\uB9CC \uC8FC\uBBC0\uB85C \uD074\uB77C\uC774\uC5B8\uD2B8\uC758 \uD30C\uC77C \uC77D\uAE30\uB85C \uC9C1\uC811 \uC77D\uB294\uB2E4). \u2461 \uC0AC\uC6A9\uC790\uAC00 \uD30C\uC77C \uACBD\uB85C\uB97C \uC9C1\uC811 \uC54C\uB824\uC8FC\uBA74 `read_document`\uB85C \uC77D\uB294\uB2E4. \u2462 "\uC5C6\uB2E4/\uC9C1\uC811 \uC785\uB825/\uD14D\uC2A4\uD2B8\uB85C \uBD99\uC5EC\uB123\uAE30"\uBA74 \uD3F4\uB354\uB97C \uC5F4\uC9C0 \uB9D0\uACE0 \uBC1B\uC740 \uD14D\uC2A4\uD2B8\uB97C \uADF8\uB300\uB85C \uC4F4\uB2E4. (\uBB3B\uC9C0\uB3C4 \uC54A\uACE0 open_inbox\uB85C \uD3F4\uB354\uB97C \uC790\uB3D9\uC73C\uB85C \uC5F4\uC9C0 \uC54A\uB294\uB2E4.)',
|
|
46080
46311
|
"\uC218\uC9D1\uD55C \uC815\uBCF4\uB97C \uAD6C\uC870\uD654\uD574 `save_profile`\uB85C \uC800\uC7A5\uD55C\uB2E4(\uC774\uB984\xB7\uC5F0\uB77D\uCC98\xB7headline\xB7summary\xB7desired_roles\xB7desired_conditions, \uADF8\uB9AC\uACE0 \uAE00\uC4F0\uAE30 \uC120\uD638\uC778 preferred_tone\uACFC emphasis_points \uD3EC\uD568). \uD30C\uC77C \uCD9C\uCC98\uB294 source=upload, \uC9C1\uC811 \uC785\uB825\uC740 manual.",
|
|
46081
46312
|
"\uC5C5\uB85C\uB4DC\uD55C \uC774\uB825\uC11C/\uACBD\uB825\uAE30\uC220\uC11C/\uD3EC\uD2B8\uD3F4\uB9AC\uC624 \uBCF8\uBB38\uC744 `add_resume`\uB85C \uC800\uC7A5\uD55C\uB2E4(kind\xB7title \uC9C0\uC815, \uB300\uD45C \uBB38\uC11C\uB294 is_primary=true).",
|
|
@@ -46096,9 +46327,9 @@ var WORKFLOWS = [
|
|
|
46096
46327
|
"\uACF5\uACE0 \uC694\uAD6C\uC0AC\uD56D\uACFC \uC0AC\uC6A9\uC790 \uACBD\uB825/\uC2A4\uD0AC/\uD504\uB85C\uC81D\uD2B8\uB97C \uBE44\uAD50\uD55C\uB2E4: \uC77C\uCE58\uD558\uB294 \uAC15\uC810(strengths)\uACFC \uBD80\uC871\uD55C \uBD80\uBD84(gaps), \uB9E4\uCE6D \uD0A4\uC6CC\uB4DC(matched_keywords)\uC640 \uB204\uB77D \uD0A4\uC6CC\uB4DC(missing_keywords)\uB97C \uB3C4\uCD9C\uD558\uACE0, \uC885\uD569 \uC801\uD569\uB3C4 \uC810\uC218(score 0~100)\uC640 \uC694\uC57D(summary), \uC9C0\uC6D0 \uC804\uB7B5 \uC81C\uC548(recommendations)\uC744 \uC815\uB9AC\uD55C\uB2E4. \uC5C6\uB294 \uACBD\uD5D8\uC744 \uC9C0\uC5B4\uB0B4\uC9C0 \uC54A\uB294\uB2E4.",
|
|
46097
46328
|
"\uC544\uC9C1 \uC800\uC7A5\uB418\uC9C0 \uC54A\uC740 \uACF5\uACE0\uB77C\uBA74 `save_job_posting`\uC73C\uB85C \uACF5\uACE0\uB97C \uC800\uC7A5\uD558\uACE0 job_id\uB97C \uD655\uBCF4\uD55C\uB2E4.",
|
|
46098
46329
|
"\uB3C4\uCD9C\uD55C \uBD84\uC11D \uACB0\uACFC\uB97C `save_fit_analysis`\uB85C \uC800\uC7A5\uD55C\uB2E4(job_id, score, summary, strengths, gaps, matched_keywords, missing_keywords, recommendations).",
|
|
46099
|
-
"\uBD84\uC11D \uACB0\uACFC\uB97C \uC0AC\uC6A9\uC790\
|
|
46100
|
-
'"\uC774 \uACF5\uACE0\uC5D0 \uB9DE\uCD98 \uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uC368\uB4DC\uB9B4\uAE4C\uC694?"\uB77C\uACE0 \uC790\uAE30\uC18C\uAC1C\uC11C \
|
|
46101
|
-
'\uC0AC\uC6A9\uC790\uAC00 \
|
|
46330
|
+
"\uBD84\uC11D \uACB0\uACFC\uB97C \uC0AC\uC6A9\uC790\uC758 \uC5B8\uC5B4\uB85C \uC27D\uAC8C \uC124\uBA85\uD55C\uB2E4(\uC798 \uB9DE\uB294 \uC810, \uBCF4\uC644\uD560 \uC810, \uCD94\uCC9C \uC804\uB7B5). \uAE30\uC220 \uC6A9\uC5B4\uB294 \uBE7C\uACE0 \uC804\uB2EC\uD55C\uB2E4.",
|
|
46331
|
+
'\uBD84\uC11D \uB4A4 \uACE7\uC7A5 \uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uC4F0\uC9C0 \uB9D0\uACE0, "\uC774 \uACF5\uACE0\uC5D0 \uB9DE\uCD98 \uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uC368\uB4DC\uB9B4\uAE4C\uC694?"\uB77C\uACE0 \uBB3B\uACE0 \uC120\uD0DD\uC9C0\uB97C \uC81C\uC2DC\uD55C\uB2E4: \u2460 "\uB124, \uC774 \uACF5\uACE0\uC5D0 \uB9DE\uCD98 \uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uC368\uC918" \u2461 "\uC544\uB2C8\uC694, \uBD84\uC11D\uB9CC \uC800\uC7A5\uD574\uC918".',
|
|
46332
|
+
'\uC0AC\uC6A9\uC790\uAC00 \u2460\uC744 \uC120\uD0DD\uD558\uBA74 \uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uC791\uC131\uD558\uAE30 \uC9C1\uC804\uC5D0 `get_writing_style_guide`\uB97C \uD638\uCD9C\uD574 "AI \uD2F0 \uC548 \uB098\uB294 \uAE00\uC4F0\uAE30 \uADDC\uCE59"\uC744 \uAC00\uC838\uC628\uB2E4. \u2461\uB97C \uC120\uD0DD\uD558\uBA74 \uC790\uC18C\uC11C \uC791\uC131 \uC5C6\uC774 \uBA48\uCD94\uACE0 \uC800\uC7A5 \uACB0\uACFC\uC640 \uB300\uC2DC\uBCF4\uB4DC \uD655\uC778\uB9CC \uC548\uB0B4\uD55C\uB2E4.',
|
|
46102
46333
|
"\uC801\uD569\uB3C4 \uBD84\uC11D\xB7\uAE00\uC4F0\uAE30 \uC120\uD638\uC640 \uAE00\uC4F0\uAE30 \uADDC\uCE59\uC744 \uD568\uAED8 \uBC18\uC601\uD574 \uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uC791\uC131\uD558\uACE0(\uBC88\uC5ED\uD22C\xB7\uD074\uB9AC\uC170\xB7\uAE30\uACC4\uC801 \uBCD1\uB82C \uC81C\uAC70, \uC0AC\uC2E4\xB7\uC218\uCE58\uB294 \uADF8\uB300\uB85C), `save_cover_letter_version`\uC73C\uB85C \uC800\uC7A5\uD55C\uB2E4(job_id \uC5F0\uACB0, note\uC5D0 \uC791\uC131 \uC758\uB3C4 \uC694\uC57D).",
|
|
46103
46334
|
"`open_application`\uC73C\uB85C \uD574\uB2F9 \uC9C0\uC6D0 \uAC74\uC744 \uC5F4\uC5B4 \uC0AC\uC6A9\uC790\uAC00 \uACB0\uACFC\uB97C \uD655\uC778\uD558\uAC8C \uD558\uACE0, \uC9C0\uC6D0 \uC0C1\uD0DC \uBCC0\uACBD(\uC608: \uC9C0\uC6D0 \uC608\uC815/\uC9C0\uC6D0 \uC644\uB8CC)\uC744 \uC81C\uC548\uD55C\uB2E4."
|
|
46104
46335
|
]
|
|
@@ -46115,7 +46346,24 @@ var WORKFLOWS = [
|
|
|
46115
46346
|
"\uC800\uC7A5\uB41C \uC2E4\uC81C \uACBD\uD5D8\xB7\uC131\uACFC\uB9CC\uC73C\uB85C \uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uC791\uC131\uD558\uB418, \uC704 \uAE00\uC4F0\uAE30 \uADDC\uCE59\uC744 \uC801\uC6A9\uD574 \uC0AC\uB78C\uC774 \uC4F4 \uB4EF \uC790\uC5F0\uC2A4\uB7FD\uAC8C \uC4F4\uB2E4(\uC0AC\uC2E4\xB7\uC218\uCE58\xB7\uACE0\uC720\uBA85\uC0AC\uB294 \uADF8\uB300\uB85C). \uBE48\uCE78\uC774\uB098 \uD655\uC778\uC774 \uD544\uC694\uD55C \uBD80\uBD84\uC740 \uCD94\uCE21\uD558\uC9C0 \uB9D0\uACE0 \uD45C\uC2DC\uD574 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBB3B\uB294\uB2E4.",
|
|
46116
46347
|
"\uC644\uC131\uBCF8\uC744 `save_cover_letter_version`\uC73C\uB85C \uC800\uC7A5\uD55C\uB2E4(\uAE30\uC874 \uC790\uAE30\uC18C\uAC1C\uC11C\uBA74 cover_letter_id, \uC0C8\uB85C \uB9CC\uB4E4\uBA74 title, \uACF5\uACE0\uC6A9\uC774\uBA74 job_id, \uBCC0\uACBD \uC694\uC57D\uC740 note, source=ai).",
|
|
46117
46348
|
"\uC0AC\uC6A9\uC790\uAC00 \uC6D0\uD558\uBA74 `export_cover_letter`\uB85C \uD30C\uC77C\uB85C \uB0B4\uBCF4\uB0B4\uACE0, \uCD94\uAC00 \uC218\uC815 \uC694\uCCAD\uC774 \uC788\uC73C\uBA74 \uC0C8 \uBC84\uC804\uC73C\uB85C \uB2E4\uC2DC \uC800\uC7A5\uD55C\uB2E4.",
|
|
46118
|
-
"\uC800\uC7A5 \uACB0\uACFC\uB97C \
|
|
46349
|
+
"\uC800\uC7A5 \uACB0\uACFC\uB97C \uC0AC\uC6A9\uC790\uC758 \uC5B8\uC5B4\uB85C \uC54C\uB9AC\uACE0, \uC9C0\uC6D0 \uC0C1\uD0DC \uC5C5\uB370\uC774\uD2B8(`update_application_status`)\uB098 \uBA74\uC811 \uC900\uBE44 \uB4F1 \uB2E4\uC74C \uB2E8\uACC4\uB97C \uC81C\uC548\uD55C\uB2E4."
|
|
46350
|
+
]
|
|
46351
|
+
},
|
|
46352
|
+
{
|
|
46353
|
+
id: "write_career_description",
|
|
46354
|
+
title: "\uACBD\uB825\uAE30\uC220\uC11C \uC791\uC131",
|
|
46355
|
+
description: "\uD504\uB85C\uD544\xB7\uC774\uB825\uC11C\xB7\uACBD\uB825\xB7\uD504\uB85C\uC81D\uD2B8\xB7\uC2A4\uD0AC\uC744 \uADFC\uAC70\uB85C \uC2E4\uC81C \uC81C\uCD9C \uAC00\uB2A5\uD55C \uACBD\uB825\uAE30\uC220\uC11C\uB97C \uC791\uC131\uD558\uACE0 \uBB38\uC11C\uD568\uC5D0 \uC800\uC7A5\uD558\uB294 \uD750\uB984.",
|
|
46356
|
+
trigger: '\uC0AC\uC6A9\uC790\uAC00 "\uACBD\uB825\uAE30\uC220\uC11C \uC368\uC918 / \uACBD\uB825\uAE30\uC220\uC11C \uB9CC\uB4E4\uC5B4\uC918 / \uB0B4 \uACBD\uB825 \uC815\uB9AC\uD574\uC918"\uB77C\uACE0 \uC694\uCCAD\uD560 \uB54C.',
|
|
46357
|
+
steps: [
|
|
46358
|
+
"`get_onboarding_status`\uB85C \uC900\uBE44 \uC0C1\uD0DC\uB97C \uD655\uC778\uD558\uACE0, `get_profile`\xB7`get_resumes`\xB7`get_experiences`\xB7`get_projects`\xB7`get_skills`\uB97C \uD638\uCD9C\uD574 \uAE30\uC874 \uD504\uB85C\uD544, \uC774\uB825\uC11C, \uACBD\uB825\uAE30\uC220\uC11C(kind=career_description), \uACBD\uB825, \uD504\uB85C\uC81D\uD2B8, \uAE30\uC220\uC2A4\uD0DD\uC744 \uBAA8\uB450 \uD655\uC778\uD55C\uB2E4.",
|
|
46359
|
+
"\uC0AC\uC6A9\uC790\uAC00 \uD30C\uC77C \uACBD\uB85C\uB97C \uC8FC\uBA74 `read_document`\uB85C \uC77D\uACE0, \uC778\uC785 \uD3F4\uB354\uB97C \uC0AC\uC6A9\uD588\uB2E4\uBA74 `read_inbox`\uB85C \uBCF8\uBB38\uC744 \uC77D\uB294\uB2E4. \uC774\uBBF8 \uC800\uC7A5\uB41C \uC790\uB8CC\uC640 \uC0C8 \uD30C\uC77C\uC744 \uBE44\uAD50\uD574 \uC911\uBCF5\xB7\uC0C1\uCDA9\uB418\uB294 \uC0AC\uC2E4\uC740 \uD45C\uC2DC\uD558\uACE0 \uCD94\uCE21\uD558\uC9C0 \uC54A\uB294\uB2E4.",
|
|
46360
|
+
'`get_workflow_guide({ workflow_id: "write_career_description" })`\uAC00 \uC548\uB0B4\uD558\uB294 \uC804\uBB38\uAC00 \uC808\uCC28\uB97C \uB530\uB978\uB2E4. \uC791\uC131 \uC9C1\uC804 `get_playbook({ domain: "resume" })`\uC640 `get_playbook({ domain: "ats" })`\uB97C \uBC1B\uC544 \uC2E4\uC81C \uACBD\uB825\uAE30\uC220\uC11C \uD615\uC2DD\uACFC ATS \uCE5C\uD654\uC131\uC744 \uC801\uC6A9\uD55C\uB2E4.',
|
|
46361
|
+
"\uC791\uC131 \uC804\uC5D0 \uBAA9\uC801\uC744 \uD655\uC778\uD55C\uB2E4: \uBC94\uC6A9 \uB9C8\uC2A4\uD130\uBCF8\uC778\uC9C0, \uD2B9\uC815 \uC9C1\uBB34/\uACF5\uACE0\uC6A9\uC778\uC9C0, \uC2E0\uC785/\uBB34\uACBD\uB825\uC774\uB77C \uD504\uB85C\uC81D\uD2B8\xB7\uAD50\uC721\xB7\uD65C\uB3D9 \uC911\uC2EC \uC5ED\uB7C9\uAE30\uC220\uC11C\uB85C \uC4F8\uC9C0, \uBD84\uB7C9\uACFC \uD1A4\uC740 \uC5B4\uB5BB\uAC8C \uD560\uC9C0 \uBB3B\uB294\uB2E4.",
|
|
46362
|
+
"\uACBD\uB825\uAE30\uC220\uC11C\uB294 \uC790\uAE30\uC18C\uAC1C\uC11C\uCC98\uB7FC \uC11C\uC0AC\uB85C \uC4F0\uC9C0 \uC54A\uB294\uB2E4. \uC81C\uBAA9, \uD575\uC2EC \uC694\uC57D, \uD575\uC2EC \uC5ED\uB7C9, \uACBD\uB825/\uD504\uB85C\uC81D\uD2B8\uBCC4 \uC5ED\uD560\xB7\uAE30\uAC04\xB7\uB3C4\uAD6C\xB7\uBB38\uC81C\xB7\uD589\uB3D9\xB7\uC131\uACFC\uB97C \uD45C\uB098 \uBD88\uB9BF \uC911\uC2EC\uC73C\uB85C \uC815\uB9AC\uD55C\uB2E4. \uC218\uCE58\xB7\uD68C\uC0AC\uBA85\xB7\uAE30\uAC04\xB7\uC9C1\uCC45\uC740 \uC800\uC7A5\uB41C \uC0AC\uC2E4\uB9CC \uC4F0\uACE0, \uC5C6\uB294 \uC131\uACFC \uC218\uCE58\uB294 \uB9CC\uB4E4\uC9C0 \uC54A\uB294\uB2E4.",
|
|
46363
|
+
'\uBB34\uACBD\uB825/\uBE44\uAC1C\uBC1C\uC790\uB77C\uBA74 \uACBD\uB825\uC744 \uB0A0\uC870\uD558\uC9C0 \uB9D0\uACE0 \uAD50\uC721\xB7\uD504\uB85C\uC81D\uD2B8\xB7\uC6B4\uC601 \uACBD\uD5D8\xB7\uC5C5\uBB34 \uB3C4\uAD6C\xB7\uD611\uC5C5 \uACBD\uD5D8\xB7\uC131\uACFC \uC99D\uAC70 \uC911\uC2EC\uC758 "\uC5ED\uB7C9\uAE30\uC220\uC11C"\uB85C \uAD6C\uC131\uD55C\uB2E4.',
|
|
46364
|
+
'\uC800\uC7A5 \uC9C1\uC804 `get_verifier({ id: "truthfulness" })`, `get_verifier({ id: "consistency" })`, `get_verifier({ id: "ats-compat" })`\uB97C \uBC1B\uC544 \uB2F9\uC2E0\uC774 \uC9C1\uC811 \uC810\uAC80\uD558\uACE0, \uD5C8\uC704\xB7\uC0C1\uCDA9\xB7\uD0A4\uC6CC\uB4DC \uB204\uB77D\uC744 \uACE0\uCE5C\uB2E4. \uD655\uC778\uC774 \uD544\uC694\uD55C \uC0AC\uC2E4\uC740 \uBCF8\uBB38\uC5D0 \uD45C\uC2DC\uD558\uACE0 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBB3B\uB294\uB2E4.',
|
|
46365
|
+
"\uC644\uC131\uBCF8\uC744 `add_resume`\uC73C\uB85C \uC800\uC7A5\uD55C\uB2E4(kind=career_description, source=ai, title\uC740 \uC0AC\uC6A9 \uBAA9\uC801\uC774 \uB4DC\uB7EC\uB098\uAC8C \uC791\uC131, tags\uC5D0 \uC9C1\uBB34/\uC6A9\uB3C4 \uD0A4\uC6CC\uB4DC \uD3EC\uD568). \uB300\uD45C \uBB38\uC11C\uB85C \uC0BC\uC544\uB3C4 \uB418\uB294\uC9C0 \uD655\uC778\uB41C \uACBD\uC6B0\uC5D0\uB9CC is_primary=true\uB97C \uC4F4\uB2E4.",
|
|
46366
|
+
"\uC800\uC7A5 \uACB0\uACFC\uB97C \uC0AC\uC6A9\uC790\uC758 \uC5B8\uC5B4\uB85C \uC54C\uB9AC\uACE0, \uBB38\uC11C \uD0ED\uC5D0\uC11C \uD655\uC778\uD560 \uC218 \uC788\uC74C\uC744 \uC548\uB0B4\uD55C\uB2E4. \uD2B9\uC815 \uACF5\uACE0\uC6A9\uC73C\uB85C \uC791\uC131\uD588\uB2E4\uBA74 \uC774\uC5B4\uC11C \uC790\uAE30\uC18C\uAC1C\uC11C\uB098 \uBA74\uC811 \uC900\uBE44\uB97C \uC81C\uC548\uD55C\uB2E4."
|
|
46119
46367
|
]
|
|
46120
46368
|
},
|
|
46121
46369
|
{
|
|
@@ -46126,7 +46374,7 @@ var WORKFLOWS = [
|
|
|
46126
46374
|
steps: [
|
|
46127
46375
|
"\uD544\uC694\uD558\uBA74 `get_application_context` \uB610\uB294 `get_job_posting`\uC73C\uB85C \uB300\uC0C1 \uC9C0\uC6D0 \uAC74\uACFC \uACF5\uACE0\uB97C \uD655\uC778\uD55C\uB2E4.",
|
|
46128
46376
|
"\uC801\uC808\uD55C \uC0C1\uD0DC\uB85C `update_application_status`\uB97C \uD638\uCD9C\uD55C\uB2E4. 8\uB2E8\uACC4: draft(\uC791\uC131 \uC911), planned(\uC9C0\uC6D0 \uC608\uC815), applied(\uC9C0\uC6D0 \uC644\uB8CC), document_passed(\uC11C\uB958 \uD569\uACA9), interview(\uBA74\uC811 \uC9C4\uD589), final_passed(\uCD5C\uC885 \uD569\uACA9), rejected(\uBD88\uD569\uACA9), on_hold(\uBCF4\uB958). \uBCC0\uACBD \uC0AC\uC720\uB294 note\uC5D0 \uB0A8\uAE34\uB2E4.",
|
|
46129
|
-
"\uBCC0\uACBD \uACB0\uACFC\uB97C \uC0AC\uC6A9\uC790\
|
|
46377
|
+
"\uBCC0\uACBD \uACB0\uACFC\uB97C \uC0AC\uC6A9\uC790\uC758 \uC5B8\uC5B4\uB85C \uC27D\uAC8C \uC54C\uB9B0\uB2E4.",
|
|
46130
46378
|
"\uC0C1\uD0DC\uC5D0 \uB9DE\uB294 \uB2E4\uC74C \uB2E8\uACC4\uB97C \uC81C\uC548\uD55C\uB2E4: applied \u2192 \uACB0\uACFC \uAE30\uB2E4\uB9AC\uAE30 \uC548\uB0B4, document_passed/interview \u2192 \uBA74\uC811 \uC900\uBE44(prepare_interview) \uC81C\uC548, final_passed \u2192 \uCD95\uD558 \uBC0F \uB9C8\uBB34\uB9AC, rejected/on_hold \u2192 \uD68C\uACE0 \uB610\uB294 \uB2E4\uB978 \uACF5\uACE0 \uD0D0\uC0C9 \uC81C\uC548.",
|
|
46131
46379
|
"\uD544\uC694\uD558\uBA74 `open_application`\uC73C\uB85C \uD574\uB2F9 \uC9C0\uC6D0 \uAC74\uC744 \uC5F4\uC5B4 \uBCF4\uC5EC\uC900\uB2E4."
|
|
46132
46380
|
]
|
|
@@ -46134,14 +46382,29 @@ var WORKFLOWS = [
|
|
|
46134
46382
|
{
|
|
46135
46383
|
id: "prepare_interview",
|
|
46136
46384
|
title: "\uBA74\uC811 \uC900\uBE44",
|
|
46137
|
-
description: "\
|
|
46138
|
-
trigger: '\uC9C0\uC6D0 \uC0C1\uD0DC\uAC00 \uC11C\uB958 \uD569\uACA9(document_passed) \uB610\uB294 \uBA74\uC811 \uC9C4\uD589(interview)\uC73C\uB85C \uBC14\uB00C\uC5C8\uC744 \uB54C
|
|
46385
|
+
description: "\uACF5\uACE0 \uAE30\uC900 \uC608\uC0C1 \uC9C8\uBB38\xB7STAR \uB2F5\uBCC0\xB71\uBD84 \uC790\uAE30\uC18C\uAC1C\uB97C \uC900\uBE44\uD574 \uC800\uC7A5\uD558\uB294 \uD750\uB984.",
|
|
46386
|
+
trigger: '\uC0AC\uC6A9\uC790\uAC00 "\uBA74\uC811 \uC900\uBE44 \uB3C4\uC640\uC918"\uB77C\uACE0 \uC694\uCCAD\uD558\uAC70\uB098, \uC9C0\uC6D0 \uC0C1\uD0DC\uAC00 \uC11C\uB958 \uD569\uACA9(document_passed) \uB610\uB294 \uBA74\uC811 \uC9C4\uD589(interview)\uC73C\uB85C \uBC14\uB00C\uC5C8\uC744 \uB54C.',
|
|
46139
46387
|
steps: [
|
|
46140
46388
|
"`get_application_context`(job_id \uD3EC\uD568)\uB97C \uD638\uCD9C\uD574 \uACF5\uACE0, \uD504\uB85C\uD544, \uACBD\uB825/\uD504\uB85C\uC81D\uD2B8, \uC801\uD569\uB3C4 \uBD84\uC11D(\uAC15\uC810\xB7\uAC2D), \uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uAC00\uC838\uC628\uB2E4.",
|
|
46141
46389
|
"\uACF5\uACE0\uC640 \uC0AC\uC6A9\uC790 \uACBD\uD5D8\uC744 \uBC14\uD0D5\uC73C\uB85C \uC608\uC0C1 \uBA74\uC811 \uC9C8\uBB38(question, intent, followups, answer_outline)\uC744 \uB3C4\uCD9C\uD55C\uB2E4.",
|
|
46142
46390
|
"\uD575\uC2EC \uACBD\uD5D8\uC5D0 \uB300\uD55C STAR \uAC00\uC774\uB4DC(question, situation, task, action, result)\uC640 1\uBD84 \uC790\uAE30\uC18C\uAC1C(self_introduction) \uCD08\uC548\uC744 \uC791\uC131\uD55C\uB2E4. \uC2E4\uC81C \uACBD\uD5D8\uB9CC \uC0AC\uC6A9\uD55C\uB2E4.",
|
|
46143
46391
|
"\uC900\uBE44 \uB0B4\uC6A9\uC744 `save_interview_prep`\uB85C \uC800\uC7A5\uD55C\uB2E4(job_id, questions, star_guides, self_introduction, notes).",
|
|
46144
|
-
"\uC900\uBE44 \uB0B4\uC6A9\uC744 \uC0AC\uC6A9\uC790\
|
|
46392
|
+
"\uC900\uBE44 \uB0B4\uC6A9\uC744 \uC0AC\uC6A9\uC790\uC758 \uC5B8\uC5B4\uB85C \uC27D\uAC8C \uC694\uC57D\uD574 \uC804\uB2EC\uD558\uACE0, \uBAA8\uC758 \uBA74\uC811/\uCD94\uAC00 \uC9C8\uBB38 \uC5F0\uC2B5\uC774\uB098 \uC0C1\uD0DC \uC5C5\uB370\uC774\uD2B8(`update_application_status`\uB85C interview/final_passed)\uB97C \uC81C\uC548\uD55C\uB2E4."
|
|
46393
|
+
]
|
|
46394
|
+
},
|
|
46395
|
+
{
|
|
46396
|
+
id: "build_personal_brand",
|
|
46397
|
+
title: "\uD37C\uC2A4\uB110 \uBE0C\uB79C\uB4DC (LinkedIn\xB7\uD3EC\uD2B8\uD3F4\uB9AC\uC624)",
|
|
46398
|
+
description: "LinkedIn \uD504\uB85C\uD544\uACFC \uD3EC\uD2B8\uD3F4\uB9AC\uC624 \uAC19\uC740 \uC790\uAE30\uD45C\uD604 \uC790\uC0B0\uC744 \uC9C1\uBB34\uC5D0 \uB9DE\uCDB0 \uC791\uC131\xB7\uCD5C\uC801\uD654\uD558\uB294 \uD750\uB984. \uC774\uB825\uC11C \uC784\uD3EC\uD2B8(\uC628\uBCF4\uB529)\uC640 \uBD84\uB9AC\uB41C \uBCC4\uB3C4 \uC791\uC5C5.",
|
|
46399
|
+
trigger: '\uC0AC\uC6A9\uC790\uAC00 "\uB9C1\uD06C\uB4DC\uC778 \uD504\uB85C\uD544 \uBD10\uC918 / \uD3EC\uD2B8\uD3F4\uB9AC\uC624 \uC815\uB9AC\uD574\uC918 / \uD37C\uC2A4\uB110 \uBE0C\uB79C\uB529 \uB3C4\uC640\uC918"\uB77C\uACE0 \uC694\uCCAD\uD560 \uB54C.',
|
|
46400
|
+
steps: [
|
|
46401
|
+
"`get_application_context`(\uAC00\uB2A5\uD558\uBA74 \uB300\uC0C1 job_id \uD3EC\uD568)\uB97C \uD638\uCD9C\uD574 \uD504\uB85C\uD544\xB7\uACBD\uB825\xB7\uD504\uB85C\uC81D\uD2B8\xB7\uC2A4\uD0AC\xB7\uB300\uD45C \uC774\uB825\uC11C\xB7\uAE00\uC4F0\uAE30 \uC120\uD638\uB97C \uAC00\uC838\uC628\uB2E4. \uD0C0\uAE43 \uACF5\uACE0\uAC00 \uC788\uC73C\uBA74 \uADF8 \uD0A4\uC6CC\uB4DC\uB97C \uC0AC\uC804 \uC785\uB825\uC73C\uB85C \uC4F4\uB2E4.",
|
|
46402
|
+
'`get_workflow_guide({ workflow_id: "build_personal_brand" })`\uAC00 \uC548\uB0B4\uD558\uB294 \uC804\uBB38\uAC00 \uC808\uCC28\uB97C \uB530\uB978\uB2E4. \uC791\uC131 \uC9C1\uC804 `get_playbook({ domain: "linkedin-profile" })`\xB7`get_playbook({ domain: "portfolio" })`\uB97C \uBC1B\uC544 \uD5E4\uB4DC\uB77C\uC778\xB7About\xB7Featured\xB73\uB9C9(problem\u2192approach\u2192impact) \uADDC\uBC94\uC744 \uC801\uC6A9\uD55C\uB2E4.',
|
|
46403
|
+
"\uBB34\uC5C7\uC744 \uB9CC\uB4E4\uC9C0 \uD655\uC778\uD55C\uB2E4(LinkedIn \uD504\uB85C\uD544\uB9CC/\uD3EC\uD2B8\uD3F4\uB9AC\uC624\uB9CC/\uB458 \uB2E4, \uD0C0\uAE43 \uC9C1\uBB34, \uAC15\uC870 \uD3EC\uC778\uD2B8). \uC800\uC7A5\uB41C \uC2E4\uC81C \uACBD\uD5D8\xB7\uC131\uACFC\uB9CC \uC4F0\uACE0, \uC5C6\uB294 \uC218\uCE58\xB7\uACE0\uC720\uBA85\uC0AC\uB294 \uCD94\uCE21\uD558\uC9C0 \uB9D0\uACE0 `[\uD655\uC778 \uD544\uC694]`\uB85C \uD45C\uC2DC\uD574 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBB3B\uB294\uB2E4.",
|
|
46404
|
+
"LinkedIn: \uD5E4\uB4DC\uB77C\uC778(\uD575\uC2EC \uD0A4\uC6CC\uB4DC\uB97C \uC55E 120\uC790\uC5D0 front-load, \uD558\uB4DC \uC0C1\uD55C 220\uC790)\xB7About \uCCAB \uBB38\uC7A5 \uD6C5\xB7\uC815\uB7C9 \uC131\uACFC\xB7\uC9C1\uBB34 \uD0A4\uC6CC\uB4DC\uB97C \uC791\uC131. \uD3EC\uD2B8\uD3F4\uB9AC\uC624: \uC9C1\uBB34\uC5D0 \uB9DE\uB294 3~6\uAC1C \uD56D\uBAA9\uC744 problem\u2192approach\u2192impact 3\uB9C9\uC73C\uB85C \uAD6C\uC131\uD558\uACE0 \uBCF8\uC778 \uAE30\uC5EC(my_role)\uC640 \uC815\uB7C9 \uC784\uD329\uD2B8\uB97C \uBA85\uC2DC\uD55C\uB2E4.",
|
|
46405
|
+
'\uC800\uC7A5 \uC9C1\uC804 `get_verifier({ id: "human-voice" })`\xB7`get_verifier({ id: "truthfulness" })`\xB7`get_verifier({ id: "consistency" })`\uB97C \uBC1B\uC544 \uB2F9\uC2E0\uC774 \uC9C1\uC811 \uC810\uAC80\uD55C\uB2E4(AI \uD2F0\xB7\uD658\uAC01\xB7\uC0AC\uC2E4 \uBCF4\uC874). \uD0A4\uC6CC\uB4DC \uC0AC\uC804\uC774 \uBE44\uBA74 \uD0A4\uC6CC\uB4DC \uCCB4\uD06C\uB294 \uBCF4\uB958\uD55C\uB2E4.',
|
|
46406
|
+
"\uD3EC\uD2B8\uD3F4\uB9AC\uC624 \uBCF8\uBB38\uC740 `add_resume`(kind=portfolio)\uB85C \uC800\uC7A5\uD55C\uB2E4. LinkedIn \uD504\uB85C\uD544 \uCD08\uC548\uC740 \uC0AC\uC6A9\uC790\uAC00 \uBCF5\uC0AC\uD574 \uC4F0\uB3C4\uB85D \uC81C\uC2DC\uD558\uACE0(\uC804\uC6A9 \uC800\uC7A5\xB7\uAC80\uC99D \uB3C4\uAD6C validate_linkedin_profile\uC740 Phase B \uBBF8\uAD6C\uD604), \uC6D0\uD558\uBA74 \uD30C\uC77C\uB85C \uB0B4\uBCF4\uB0B8\uB2E4.",
|
|
46407
|
+
"\uC800\uC7A5 \uACB0\uACFC\uB97C \uC0AC\uC6A9\uC790\uC758 \uC5B8\uC5B4\uB85C \uC54C\uB9AC\uACE0 \uB300\uC2DC\uBCF4\uB4DC \uB9C1\uD06C\uB97C \uC548\uB0B4\uD558\uBA70, \uB124\uD2B8\uC6CC\uD0B9(\uCD94\uCC9C \uACBD\uB85C)\uC774\uB098 \uACF5\uACE0 \uC9C0\uC6D0\uC73C\uB85C \uC774\uC5B4\uAC08\uC9C0 \uC81C\uC548\uD55C\uB2E4."
|
|
46145
46408
|
]
|
|
46146
46409
|
}
|
|
46147
46410
|
];
|
|
@@ -46683,6 +46946,14 @@ function resumeToMarkdown(doc, profile) {
|
|
|
46683
46946
|
content: body
|
|
46684
46947
|
};
|
|
46685
46948
|
}
|
|
46949
|
+
function resumeToHtml(doc, profile) {
|
|
46950
|
+
const md = resumeToMarkdown(doc, profile);
|
|
46951
|
+
return {
|
|
46952
|
+
filename: `${slugify(doc.title, doc.kind)}.html`,
|
|
46953
|
+
mimeType: HTML_MIME,
|
|
46954
|
+
content: toPrintableHtml(doc.title, md.content)
|
|
46955
|
+
};
|
|
46956
|
+
}
|
|
46686
46957
|
function profileToMarkdown(profile, experiences = [], projects = [], skills = []) {
|
|
46687
46958
|
const name = profile.name?.trim() || "\uC774\uB825\uC11C";
|
|
46688
46959
|
const contact = [];
|
|
@@ -46764,6 +47035,15 @@ function profileToMarkdown(profile, experiences = [], projects = [], skills = []
|
|
|
46764
47035
|
content
|
|
46765
47036
|
};
|
|
46766
47037
|
}
|
|
47038
|
+
function profileToHtml(profile, experiences = [], projects = [], skills = []) {
|
|
47039
|
+
const md = profileToMarkdown(profile, experiences, projects, skills);
|
|
47040
|
+
const title = profile.name?.trim() || "\uC774\uB825\uC11C";
|
|
47041
|
+
return {
|
|
47042
|
+
filename: `${slugify(title, "resume")}-resume.html`,
|
|
47043
|
+
mimeType: HTML_MIME,
|
|
47044
|
+
content: toPrintableHtml(title, md.content)
|
|
47045
|
+
};
|
|
47046
|
+
}
|
|
46767
47047
|
function interviewPrepToMarkdown(prep, job) {
|
|
46768
47048
|
const titleBase = job ? `${job.company} ${job.position} \uBA74\uC811 \uC900\uBE44` : "\uBA74\uC811 \uC900\uBE44";
|
|
46769
47049
|
const meta = [];
|
|
@@ -46772,17 +47052,22 @@ function interviewPrepToMarkdown(prep, job) {
|
|
|
46772
47052
|
if (job.deadline) meta.push(kv("\uB9C8\uAC10", job.deadline));
|
|
46773
47053
|
}
|
|
46774
47054
|
const introBlock = prep.self_introduction?.trim() ? joinBlocks(["## 1\uBD84 \uC790\uAE30\uC18C\uAC1C", prep.self_introduction.trim()]) : "";
|
|
46775
|
-
const
|
|
46776
|
-
|
|
46777
|
-
|
|
46778
|
-
|
|
46779
|
-
|
|
46780
|
-
|
|
46781
|
-
|
|
46782
|
-
|
|
46783
|
-
|
|
46784
|
-
)
|
|
46785
|
-
|
|
47055
|
+
const renderQuestion = (q, idx, level) => joinBlocks([
|
|
47056
|
+
`${level} Q${idx + 1}. ${q.question}`,
|
|
47057
|
+
q.intent?.trim() ? kv("\uC758\uB3C4", q.intent) : "",
|
|
47058
|
+
q.answer_outline?.trim() ? joinBlocks(["**\uB2F5\uBCC0 \uAC00\uC774\uB4DC**", q.answer_outline.trim()]) : "",
|
|
47059
|
+
q.followups?.length ? joinBlocks(["**\uC608\uC0C1 \uAF2C\uB9AC \uC9C8\uBB38**", bulletList(q.followups)]) : ""
|
|
47060
|
+
]);
|
|
47061
|
+
let questionsBlock = "";
|
|
47062
|
+
if (prep.questions?.length) {
|
|
47063
|
+
const technical = prep.questions.filter((q) => (q.category ?? "technical") === "technical");
|
|
47064
|
+
const behavioral = prep.questions.filter((q) => q.category === "behavioral");
|
|
47065
|
+
questionsBlock = behavioral.length ? joinBlocks([
|
|
47066
|
+
"## \uC608\uC0C1 \uC9C8\uBB38",
|
|
47067
|
+
technical.length ? joinBlocks(["### \uAE30\uC220 \uBA74\uC811", ...technical.map((q, i) => renderQuestion(q, i, "####"))]) : "",
|
|
47068
|
+
joinBlocks(["### \uC778\uC131\xB7\uCEEC\uCC98\uD54F \uBA74\uC811", ...behavioral.map((q, i) => renderQuestion(q, i, "####"))])
|
|
47069
|
+
]) : joinBlocks(["## \uC608\uC0C1 \uC9C8\uBB38", ...prep.questions.map((q, i) => renderQuestion(q, i, "###"))]);
|
|
47070
|
+
}
|
|
46786
47071
|
const starBlock = prep.star_guides?.length ? joinBlocks([
|
|
46787
47072
|
"## STAR \uC815\uB9AC",
|
|
46788
47073
|
...prep.star_guides.map(
|
|
@@ -46811,6 +47096,15 @@ function interviewPrepToMarkdown(prep, job) {
|
|
|
46811
47096
|
content
|
|
46812
47097
|
};
|
|
46813
47098
|
}
|
|
47099
|
+
function interviewPrepToHtml(prep, job) {
|
|
47100
|
+
const md = interviewPrepToMarkdown(prep, job);
|
|
47101
|
+
const title = job ? `${job.company} ${job.position} \uBA74\uC811 \uC900\uBE44` : "\uBA74\uC811 \uC900\uBE44";
|
|
47102
|
+
return {
|
|
47103
|
+
filename: `${slugify(title, "interview-prep")}.html`,
|
|
47104
|
+
mimeType: HTML_MIME,
|
|
47105
|
+
content: toPrintableHtml(title, md.content)
|
|
47106
|
+
};
|
|
47107
|
+
}
|
|
46814
47108
|
|
|
46815
47109
|
// apps/web/src/exports.ts
|
|
46816
47110
|
function asFormat(result2, format) {
|
|
@@ -46834,20 +47128,25 @@ function exportCoverLetter(id3, format) {
|
|
|
46834
47128
|
function exportDocument(id3, format) {
|
|
46835
47129
|
const doc = documentRepo.get(id3);
|
|
46836
47130
|
if (!doc) throw new HttpError(404, "\uBB38\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
46837
|
-
|
|
47131
|
+
const profile = profileRepo.get();
|
|
47132
|
+
if (format === "html") return resumeToHtml(doc, profile);
|
|
47133
|
+
return asFormat(resumeToMarkdown(doc, profile), format);
|
|
46838
47134
|
}
|
|
46839
47135
|
function exportProfile(format) {
|
|
46840
47136
|
const profile = profileRepo.get();
|
|
46841
47137
|
if (!profile) throw new HttpError(404, "\uD504\uB85C\uD544\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
46842
|
-
|
|
46843
|
-
|
|
46844
|
-
|
|
46845
|
-
);
|
|
47138
|
+
const experiences = experienceRepo.list();
|
|
47139
|
+
const projects = projectRepo.list();
|
|
47140
|
+
const skills = skillRepo.list();
|
|
47141
|
+
if (format === "html") return profileToHtml(profile, experiences, projects, skills);
|
|
47142
|
+
return asFormat(profileToMarkdown(profile, experiences, projects, skills), format);
|
|
46846
47143
|
}
|
|
46847
47144
|
function exportInterview(jobId, format) {
|
|
46848
47145
|
const prep = interviewRepo.getByJob(jobId);
|
|
46849
47146
|
if (!prep) throw new HttpError(404, "\uBA74\uC811 \uC900\uBE44 \uC790\uB8CC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
46850
|
-
|
|
47147
|
+
const job = jobRepo.get(jobId);
|
|
47148
|
+
if (format === "html") return interviewPrepToHtml(prep, job);
|
|
47149
|
+
return asFormat(interviewPrepToMarkdown(prep, job), format);
|
|
46851
47150
|
}
|
|
46852
47151
|
|
|
46853
47152
|
// apps/web/src/info.ts
|
|
@@ -46874,20 +47173,287 @@ function getServerInfo() {
|
|
|
46874
47173
|
|
|
46875
47174
|
// apps/web/src/settings.ts
|
|
46876
47175
|
import fs4 from "node:fs";
|
|
47176
|
+
import os2 from "node:os";
|
|
46877
47177
|
import path4 from "node:path";
|
|
47178
|
+
import { spawn } from "node:child_process";
|
|
47179
|
+
import { fileURLToPath } from "node:url";
|
|
47180
|
+
var __dirname = path4.dirname(fileURLToPath(import.meta.url));
|
|
46878
47181
|
function listTables(db) {
|
|
46879
47182
|
return db.prepare(
|
|
46880
47183
|
`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name != '_meta' ORDER BY name`
|
|
46881
47184
|
).all().map((r) => r.name);
|
|
46882
47185
|
}
|
|
47186
|
+
var RESTORE_ORDER = [
|
|
47187
|
+
"profile",
|
|
47188
|
+
"experiences",
|
|
47189
|
+
"projects",
|
|
47190
|
+
"skills",
|
|
47191
|
+
"documents",
|
|
47192
|
+
"jobs",
|
|
47193
|
+
"cover_letters",
|
|
47194
|
+
"cover_letter_versions",
|
|
47195
|
+
"fit_analyses",
|
|
47196
|
+
"applications",
|
|
47197
|
+
"interview_preps",
|
|
47198
|
+
"application_timeline_events",
|
|
47199
|
+
"activities"
|
|
47200
|
+
];
|
|
47201
|
+
function quoteIdent(name) {
|
|
47202
|
+
return `"${name.replace(/"/g, '""')}"`;
|
|
47203
|
+
}
|
|
47204
|
+
function shQuote(value) {
|
|
47205
|
+
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
47206
|
+
}
|
|
47207
|
+
function cmdQuote(value) {
|
|
47208
|
+
return value.replace(/"/g, '""');
|
|
47209
|
+
}
|
|
47210
|
+
function schemaVersion(db) {
|
|
47211
|
+
const ver = db.prepare(`SELECT value FROM _meta WHERE key='schema_version'`).get();
|
|
47212
|
+
return Number(ver?.value ?? 0);
|
|
47213
|
+
}
|
|
47214
|
+
function tableColumns(db, table) {
|
|
47215
|
+
return db.prepare(`PRAGMA table_info(${quoteIdent(table)})`).all().map((r) => r.name);
|
|
47216
|
+
}
|
|
47217
|
+
function isRecord(v) {
|
|
47218
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
47219
|
+
}
|
|
47220
|
+
function appRoot() {
|
|
47221
|
+
return BUNDLED ? __dirname : path4.resolve(__dirname, "..", "..", "..");
|
|
47222
|
+
}
|
|
47223
|
+
function shortcutFolder() {
|
|
47224
|
+
const override = process.env.CAREERMATE_SHORTCUT_DIR?.trim();
|
|
47225
|
+
if (override) return override;
|
|
47226
|
+
const desktop = path4.join(os2.homedir(), "Desktop");
|
|
47227
|
+
const parent = fs4.existsSync(desktop) ? desktop : getExportsDir();
|
|
47228
|
+
return path4.join(parent, "CareerMate \uB300\uC2DC\uBCF4\uB4DC");
|
|
47229
|
+
}
|
|
47230
|
+
function openFolder(dir) {
|
|
47231
|
+
try {
|
|
47232
|
+
if (process.platform === "win32") spawn("explorer", [dir], { stdio: "ignore", detached: true }).unref();
|
|
47233
|
+
else if (process.platform === "darwin") spawn("open", [dir], { stdio: "ignore", detached: true }).unref();
|
|
47234
|
+
else spawn("xdg-open", [dir], { stdio: "ignore", detached: true }).unref();
|
|
47235
|
+
} catch {
|
|
47236
|
+
}
|
|
47237
|
+
}
|
|
47238
|
+
function parseBackup(raw) {
|
|
47239
|
+
if (!isRecord(raw) || !isRecord(raw.tables)) {
|
|
47240
|
+
throw new Error("CareerMate \uBC31\uC5C5 JSON \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4.");
|
|
47241
|
+
}
|
|
47242
|
+
const rawTables = raw.tables;
|
|
47243
|
+
const db = getDb();
|
|
47244
|
+
const currentVersion = schemaVersion(db);
|
|
47245
|
+
const version = Number(raw.version);
|
|
47246
|
+
if (!Number.isInteger(version) || version < 0) {
|
|
47247
|
+
throw new Error("\uBC31\uC5C5 \uD30C\uC77C\uC758 \uC2A4\uD0A4\uB9C8 \uBC84\uC804\uC744 \uD655\uC778\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
47248
|
+
}
|
|
47249
|
+
if (version > currentVersion) {
|
|
47250
|
+
throw new Error("\uC774 \uBC31\uC5C5\uC740 \uB354 \uCD5C\uC2E0 CareerMate\uC5D0\uC11C \uB9CC\uB4E4\uC5B4\uC84C\uC2B5\uB2C8\uB2E4. \uC571\uC744 \uC5C5\uB370\uC774\uD2B8\uD55C \uB4A4 \uB2E4\uC2DC \uAC00\uC838\uC640 \uC8FC\uC138\uC694.");
|
|
47251
|
+
}
|
|
47252
|
+
const allowedTables = new Set(listTables(db));
|
|
47253
|
+
const unknownTables = Object.keys(rawTables).filter((name) => !allowedTables.has(name));
|
|
47254
|
+
if (unknownTables.length > 0) {
|
|
47255
|
+
throw new Error(`\uD604\uC7AC \uC571\uC5D0\uC11C \uC54C \uC218 \uC5C6\uB294 \uB370\uC774\uD130\uAC00 \uD3EC\uD568\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4: ${unknownTables.join(", ")}`);
|
|
47256
|
+
}
|
|
47257
|
+
const columnsByTable = /* @__PURE__ */ new Map();
|
|
47258
|
+
for (const table of allowedTables) columnsByTable.set(table, new Set(tableColumns(db, table)));
|
|
47259
|
+
const tables = {};
|
|
47260
|
+
const counts = {};
|
|
47261
|
+
let totalRows = 0;
|
|
47262
|
+
for (const table of allowedTables) {
|
|
47263
|
+
const rows = rawTables[table] ?? [];
|
|
47264
|
+
if (!Array.isArray(rows)) throw new Error(`${table} \uB370\uC774\uD130\uAC00 \uBC30\uC5F4 \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4.`);
|
|
47265
|
+
const columns = columnsByTable.get(table);
|
|
47266
|
+
tables[table] = rows.map((row, rowIndex) => {
|
|
47267
|
+
if (!isRecord(row)) throw new Error(`${table} ${rowIndex + 1}\uBC88\uC9F8 \uD589\uC774 \uC62C\uBC14\uB978 \uD615\uC2DD\uC774 \uC544\uB2D9\uB2C8\uB2E4.`);
|
|
47268
|
+
const clean = {};
|
|
47269
|
+
for (const [key, value] of Object.entries(row)) {
|
|
47270
|
+
if (!columns.has(key)) throw new Error(`${table} \uB370\uC774\uD130\uC5D0 \uD604\uC7AC \uC571\uC5D0\uC11C \uC4F0\uC9C0 \uC54A\uB294 \uD56D\uBAA9(${key})\uC774 \uC788\uC2B5\uB2C8\uB2E4.`);
|
|
47271
|
+
if (value !== null && !["string", "number", "boolean"].includes(typeof value)) {
|
|
47272
|
+
throw new Error(`${table} \uB370\uC774\uD130\uC758 ${key} \uAC12 \uD615\uC2DD\uC774 \uC62C\uBC14\uB974\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.`);
|
|
47273
|
+
}
|
|
47274
|
+
clean[key] = value;
|
|
47275
|
+
}
|
|
47276
|
+
if (Object.keys(clean).length === 0) throw new Error(`${table} ${rowIndex + 1}\uBC88\uC9F8 \uD589\uC774 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4.`);
|
|
47277
|
+
return clean;
|
|
47278
|
+
});
|
|
47279
|
+
counts[table] = tables[table].length;
|
|
47280
|
+
totalRows += tables[table].length;
|
|
47281
|
+
}
|
|
47282
|
+
const warnings = [...allowedTables].filter((table) => !(table in rawTables)).map((table) => `${table} \uB370\uC774\uD130\uAC00 \uBC31\uC5C5 \uD30C\uC77C\uC5D0 \uC5C6\uC5B4 \uBE48 \uAC12\uC73C\uB85C \uAC00\uC838\uC635\uB2C8\uB2E4.`);
|
|
47283
|
+
return {
|
|
47284
|
+
exported_at: typeof raw.exported_at === "string" ? raw.exported_at : null,
|
|
47285
|
+
version,
|
|
47286
|
+
current_version: currentVersion,
|
|
47287
|
+
tables,
|
|
47288
|
+
counts,
|
|
47289
|
+
total_rows: totalRows,
|
|
47290
|
+
warnings
|
|
47291
|
+
};
|
|
47292
|
+
}
|
|
47293
|
+
function macLauncherScript() {
|
|
47294
|
+
const root2 = appRoot();
|
|
47295
|
+
const dataDir = getDataDir();
|
|
47296
|
+
const nodePath = process.execPath;
|
|
47297
|
+
const binPath = path4.join(root2, "bin", "careermate.mjs");
|
|
47298
|
+
const bundledWeb = BUNDLED ? path4.join(root2, "web.mjs") : path4.join(root2, "dist", "web.mjs");
|
|
47299
|
+
return `#!/bin/zsh
|
|
47300
|
+
set -e
|
|
47301
|
+
|
|
47302
|
+
export CAREERMATE_DATA_DIR=${shQuote(dataDir)}
|
|
47303
|
+
NODE=${shQuote(nodePath)}
|
|
47304
|
+
ROOT=${shQuote(root2)}
|
|
47305
|
+
BIN=${shQuote(binPath)}
|
|
47306
|
+
BUNDLED_WEB=${shQuote(bundledWeb)}
|
|
47307
|
+
INFO="$CAREERMATE_DATA_DIR/server.json"
|
|
47308
|
+
|
|
47309
|
+
if [ ! -x "$NODE" ]; then
|
|
47310
|
+
NODE="$(command -v node || true)"
|
|
47311
|
+
fi
|
|
47312
|
+
if [ -z "$NODE" ]; then
|
|
47313
|
+
echo "Node.js\uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. CareerMate\uB97C \uC124\uCE58\uD55C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD574 \uC8FC\uC138\uC694."
|
|
47314
|
+
exit 1
|
|
47315
|
+
fi
|
|
47316
|
+
|
|
47317
|
+
URL=$("$NODE" -e 'const fs=require("fs"); try { const info=JSON.parse(fs.readFileSync(process.argv[1], "utf8")); process.stdout.write(info.url || ""); } catch {}' "$INFO")
|
|
47318
|
+
if [ -n "$URL" ] && command -v curl >/dev/null 2>&1 && curl -fsS --max-time 1 "$URL/api/health" >/dev/null 2>&1; then
|
|
47319
|
+
open "$URL"
|
|
47320
|
+
exit 0
|
|
47321
|
+
fi
|
|
47322
|
+
|
|
47323
|
+
echo "CareerMate \uB300\uC2DC\uBCF4\uB4DC\uB97C \uC2DC\uC791\uD569\uB2C8\uB2E4."
|
|
47324
|
+
if [ -f "$BIN" ]; then
|
|
47325
|
+
cd "$ROOT"
|
|
47326
|
+
exec "$NODE" "$BIN" start
|
|
47327
|
+
fi
|
|
47328
|
+
|
|
47329
|
+
if [ -f "$BUNDLED_WEB" ]; then
|
|
47330
|
+
cd "$(dirname "$BUNDLED_WEB")"
|
|
47331
|
+
exec "$NODE" --no-warnings --experimental-sqlite "$BUNDLED_WEB"
|
|
47332
|
+
fi
|
|
47333
|
+
|
|
47334
|
+
if command -v careermate >/dev/null 2>&1; then
|
|
47335
|
+
exec careermate start
|
|
47336
|
+
fi
|
|
47337
|
+
|
|
47338
|
+
exec npx -y careermate start
|
|
47339
|
+
`;
|
|
47340
|
+
}
|
|
47341
|
+
function windowsLauncherScript() {
|
|
47342
|
+
const root2 = appRoot();
|
|
47343
|
+
const dataDir = getDataDir();
|
|
47344
|
+
const nodePath = process.execPath;
|
|
47345
|
+
const binPath = path4.join(root2, "bin", "careermate.mjs");
|
|
47346
|
+
const bundledWeb = BUNDLED ? path4.join(root2, "web.mjs") : path4.join(root2, "dist", "web.mjs");
|
|
47347
|
+
return `@echo off
|
|
47348
|
+
setlocal
|
|
47349
|
+
set "CAREERMATE_DATA_DIR=${cmdQuote(dataDir)}"
|
|
47350
|
+
set "NODE=${cmdQuote(nodePath)}"
|
|
47351
|
+
set "ROOT=${cmdQuote(root2)}"
|
|
47352
|
+
set "BIN=${cmdQuote(binPath)}"
|
|
47353
|
+
set "BUNDLED_WEB=${cmdQuote(bundledWeb)}"
|
|
47354
|
+
set "INFO=%CAREERMATE_DATA_DIR%\\server.json"
|
|
47355
|
+
set "URL="
|
|
47356
|
+
|
|
47357
|
+
if not exist "%NODE%" (
|
|
47358
|
+
for /f "usebackq delims=" %%N in (\`where node 2^>nul\`) do (
|
|
47359
|
+
set "NODE=%%N"
|
|
47360
|
+
goto :node_found
|
|
47361
|
+
)
|
|
47362
|
+
)
|
|
47363
|
+
:node_found
|
|
47364
|
+
if not exist "%NODE%" (
|
|
47365
|
+
echo Node.js\uB97C \uCC3E\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. CareerMate\uB97C \uC124\uCE58\uD55C \uB4A4 \uB2E4\uC2DC \uC2E4\uD589\uD574 \uC8FC\uC138\uC694.
|
|
47366
|
+
pause
|
|
47367
|
+
exit /b 1
|
|
47368
|
+
)
|
|
47369
|
+
|
|
47370
|
+
for /f "usebackq delims=" %%U in (\`"%NODE%" -e "const fs=require('fs'); try { const info=JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); process.stdout.write(info.url || ''); } catch {}" "%INFO%"\`) do set "URL=%%U"
|
|
47371
|
+
if defined URL (
|
|
47372
|
+
powershell -NoProfile -ExecutionPolicy Bypass -Command "try { Invoke-WebRequest -UseBasicParsing -TimeoutSec 1 '%URL%/api/health' | Out-Null; Start-Process '%URL%'; exit 0 } catch { exit 1 }"
|
|
47373
|
+
if not errorlevel 1 exit /b 0
|
|
47374
|
+
)
|
|
47375
|
+
|
|
47376
|
+
echo CareerMate \uB300\uC2DC\uBCF4\uB4DC\uB97C \uC2DC\uC791\uD569\uB2C8\uB2E4.
|
|
47377
|
+
if exist "%BIN%" (
|
|
47378
|
+
cd /d "%ROOT%"
|
|
47379
|
+
"%NODE%" "%BIN%" start
|
|
47380
|
+
exit /b %ERRORLEVEL%
|
|
47381
|
+
)
|
|
47382
|
+
|
|
47383
|
+
if exist "%BUNDLED_WEB%" (
|
|
47384
|
+
cd /d "%ROOT%"
|
|
47385
|
+
"%NODE%" --no-warnings --experimental-sqlite "%BUNDLED_WEB%"
|
|
47386
|
+
exit /b %ERRORLEVEL%
|
|
47387
|
+
)
|
|
47388
|
+
|
|
47389
|
+
where careermate >nul 2>nul
|
|
47390
|
+
if not errorlevel 1 (
|
|
47391
|
+
careermate start
|
|
47392
|
+
exit /b %ERRORLEVEL%
|
|
47393
|
+
)
|
|
47394
|
+
|
|
47395
|
+
npx -y careermate start
|
|
47396
|
+
`;
|
|
47397
|
+
}
|
|
47398
|
+
function linuxLauncherScript() {
|
|
47399
|
+
return macLauncherScript().replace("#!/bin/zsh", "#!/usr/bin/env sh").replace('\n open "$URL"', '\n xdg-open "$URL"');
|
|
47400
|
+
}
|
|
46883
47401
|
function exportAll() {
|
|
46884
47402
|
const db = getDb();
|
|
46885
47403
|
const tables = {};
|
|
46886
47404
|
for (const t of listTables(db)) {
|
|
46887
|
-
tables[t] = db.prepare(`SELECT * FROM ${t}`).all();
|
|
47405
|
+
tables[t] = db.prepare(`SELECT * FROM ${quoteIdent(t)}`).all();
|
|
46888
47406
|
}
|
|
46889
|
-
|
|
46890
|
-
|
|
47407
|
+
return { exported_at: (/* @__PURE__ */ new Date()).toISOString(), version: schemaVersion(db), tables };
|
|
47408
|
+
}
|
|
47409
|
+
function previewBackupImport(raw) {
|
|
47410
|
+
const parsed = parseBackup(raw);
|
|
47411
|
+
return {
|
|
47412
|
+
exported_at: parsed.exported_at,
|
|
47413
|
+
version: parsed.version,
|
|
47414
|
+
current_version: parsed.current_version,
|
|
47415
|
+
counts: parsed.counts,
|
|
47416
|
+
total_rows: parsed.total_rows,
|
|
47417
|
+
warnings: parsed.warnings
|
|
47418
|
+
};
|
|
47419
|
+
}
|
|
47420
|
+
function restoreBackup(raw) {
|
|
47421
|
+
const parsed = parseBackup(raw);
|
|
47422
|
+
const safety = createBackup();
|
|
47423
|
+
const db = getDb();
|
|
47424
|
+
const tables = listTables(db);
|
|
47425
|
+
const restoreOrder = [
|
|
47426
|
+
...RESTORE_ORDER.filter((table) => tables.includes(table)),
|
|
47427
|
+
...tables.filter((table) => !RESTORE_ORDER.includes(table))
|
|
47428
|
+
];
|
|
47429
|
+
tx(() => {
|
|
47430
|
+
for (const table of [...restoreOrder].reverse()) {
|
|
47431
|
+
db.prepare(`DELETE FROM ${quoteIdent(table)}`).run();
|
|
47432
|
+
}
|
|
47433
|
+
for (const table of restoreOrder) {
|
|
47434
|
+
for (const row of parsed.tables[table] ?? []) {
|
|
47435
|
+
const columns = Object.keys(row);
|
|
47436
|
+
const placeholders = columns.map(() => "?").join(",");
|
|
47437
|
+
const values2 = columns.map((column) => {
|
|
47438
|
+
const value = row[column];
|
|
47439
|
+
return typeof value === "boolean" ? Number(value) : value;
|
|
47440
|
+
});
|
|
47441
|
+
db.prepare(
|
|
47442
|
+
`INSERT INTO ${quoteIdent(table)} (${columns.map(quoteIdent).join(",")}) VALUES (${placeholders})`
|
|
47443
|
+
).run(...values2);
|
|
47444
|
+
}
|
|
47445
|
+
}
|
|
47446
|
+
const fkProblems = db.prepare(`PRAGMA foreign_key_check`).all();
|
|
47447
|
+
if (fkProblems.length > 0) {
|
|
47448
|
+
throw new Error("\uBC31\uC5C5 \uD30C\uC77C\uC758 \uB370\uC774\uD130 \uAD00\uACC4\uAC00 \uB9DE\uC9C0 \uC54A\uC544 \uAC00\uC838\uC62C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
47449
|
+
}
|
|
47450
|
+
});
|
|
47451
|
+
return {
|
|
47452
|
+
ok: true,
|
|
47453
|
+
safety_backup_path: safety.backup_path,
|
|
47454
|
+
safety_json_path: safety.json_path,
|
|
47455
|
+
restored: previewBackupImport(raw)
|
|
47456
|
+
};
|
|
46891
47457
|
}
|
|
46892
47458
|
function createBackup() {
|
|
46893
47459
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
@@ -46908,6 +47474,38 @@ function createBackup() {
|
|
|
46908
47474
|
fs4.writeFileSync(jsonBackup, JSON.stringify(exportAll(), null, 2), "utf8");
|
|
46909
47475
|
return { backup_path: dbBackup, json_path: jsonBackup };
|
|
46910
47476
|
}
|
|
47477
|
+
function createDashboardShortcut(open = false) {
|
|
47478
|
+
const dir = shortcutFolder();
|
|
47479
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
47480
|
+
const readme = `CareerMate \uB300\uC2DC\uBCF4\uB4DC \uBC14\uB85C\uAC00\uAE30
|
|
47481
|
+
|
|
47482
|
+
- \uB300\uC2DC\uBCF4\uB4DC\uAC00 \uC774\uBBF8 \uC2E4\uD589 \uC911\uC774\uBA74 \uBE0C\uB77C\uC6B0\uC800\uB9CC \uC5FD\uB2C8\uB2E4.
|
|
47483
|
+
- \uB300\uC2DC\uBCF4\uB4DC\uAC00 \uAEBC\uC838 \uC788\uC73C\uBA74 \uC11C\uBC84\uB97C \uC2DC\uC791\uD558\uACE0 \uBE0C\uB77C\uC6B0\uC800\uB97C \uC5FD\uB2C8\uB2E4.
|
|
47484
|
+
- \uC774 \uD3F4\uB354\uB294 \uC774 \uCEF4\uD4E8\uD130\uC758 CareerMate \uC124\uCE58 \uACBD\uB85C\uC640 \uB370\uC774\uD130 \uD3F4\uB354\uB97C \uAE30\uC900\uC73C\uB85C \uB9CC\uB4E4\uC5B4\uC84C\uC2B5\uB2C8\uB2E4.
|
|
47485
|
+
`;
|
|
47486
|
+
const readmePath = path4.join(dir, "README.txt");
|
|
47487
|
+
fs4.writeFileSync(readmePath, readme, "utf8");
|
|
47488
|
+
let launcherPath;
|
|
47489
|
+
if (process.platform === "win32") {
|
|
47490
|
+
launcherPath = path4.join(dir, "CareerMate \uB300\uC2DC\uBCF4\uB4DC.cmd");
|
|
47491
|
+
fs4.writeFileSync(launcherPath, windowsLauncherScript(), "utf8");
|
|
47492
|
+
} else if (process.platform === "darwin") {
|
|
47493
|
+
launcherPath = path4.join(dir, "CareerMate \uB300\uC2DC\uBCF4\uB4DC.command");
|
|
47494
|
+
fs4.writeFileSync(launcherPath, macLauncherScript(), { encoding: "utf8", mode: 493 });
|
|
47495
|
+
fs4.chmodSync(launcherPath, 493);
|
|
47496
|
+
} else {
|
|
47497
|
+
launcherPath = path4.join(dir, "careermate-dashboard.sh");
|
|
47498
|
+
fs4.writeFileSync(launcherPath, linuxLauncherScript(), { encoding: "utf8", mode: 493 });
|
|
47499
|
+
fs4.chmodSync(launcherPath, 493);
|
|
47500
|
+
}
|
|
47501
|
+
if (open) openFolder(dir);
|
|
47502
|
+
return {
|
|
47503
|
+
shortcut_dir: dir,
|
|
47504
|
+
launcher_path: launcherPath,
|
|
47505
|
+
platform: process.platform,
|
|
47506
|
+
files: [launcherPath, readmePath]
|
|
47507
|
+
};
|
|
47508
|
+
}
|
|
46911
47509
|
function resetAll(confirm) {
|
|
46912
47510
|
if (confirm !== "DELETE") {
|
|
46913
47511
|
return { ok: false };
|
|
@@ -46916,7 +47514,7 @@ function resetAll(confirm) {
|
|
|
46916
47514
|
const db = getDb();
|
|
46917
47515
|
db.exec("BEGIN");
|
|
46918
47516
|
try {
|
|
46919
|
-
for (const t of listTables(db)) db.exec(`DELETE FROM ${t}`);
|
|
47517
|
+
for (const t of listTables(db)) db.exec(`DELETE FROM ${quoteIdent(t)}`);
|
|
46920
47518
|
db.exec("COMMIT");
|
|
46921
47519
|
} catch (e) {
|
|
46922
47520
|
db.exec("ROLLBACK");
|
|
@@ -46944,6 +47542,141 @@ function fmt(ctx) {
|
|
|
46944
47542
|
const f = (ctx.query.get("format") ?? "md").toLowerCase();
|
|
46945
47543
|
return ["md", "html", "txt"].includes(f) ? f : "md";
|
|
46946
47544
|
}
|
|
47545
|
+
function backupError(e) {
|
|
47546
|
+
return new HttpError(400, e instanceof Error ? e.message : "\uBC31\uC5C5 \uD30C\uC77C\uC744 \uCC98\uB9AC\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.", "backup_import");
|
|
47547
|
+
}
|
|
47548
|
+
function isRecord2(v) {
|
|
47549
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
47550
|
+
}
|
|
47551
|
+
function documentRoute(doc) {
|
|
47552
|
+
return doc.kind === "career_description" ? `/documents/career/${doc.id}` : `/documents/docs/${doc.id}`;
|
|
47553
|
+
}
|
|
47554
|
+
function enrichDocumentRef(ref) {
|
|
47555
|
+
if (!isRecord2(ref)) return ref;
|
|
47556
|
+
const refId = typeof ref.id === "string" ? ref.id : null;
|
|
47557
|
+
const doc = refId ? documentRepo.get(refId) : null;
|
|
47558
|
+
const kind = doc?.kind ?? ref.document_kind ?? ref.kind ?? null;
|
|
47559
|
+
return {
|
|
47560
|
+
...ref,
|
|
47561
|
+
title: doc?.title ?? ref.title ?? "\uC0AD\uC81C\uB41C \uBB38\uC11C",
|
|
47562
|
+
document_kind: kind,
|
|
47563
|
+
exists: !!doc,
|
|
47564
|
+
route: doc ? documentRoute(doc) : null
|
|
47565
|
+
};
|
|
47566
|
+
}
|
|
47567
|
+
function enrichCoverLetterRef(ref) {
|
|
47568
|
+
if (!isRecord2(ref)) return ref;
|
|
47569
|
+
const refId = typeof ref.id === "string" ? ref.id : null;
|
|
47570
|
+
const cl = refId ? coverLetterRepo.get(refId, false) : null;
|
|
47571
|
+
return {
|
|
47572
|
+
...ref,
|
|
47573
|
+
title: cl?.title ?? ref.title ?? "\uC0AD\uC81C\uB41C \uC790\uAE30\uC18C\uAC1C\uC11C",
|
|
47574
|
+
exists: !!cl,
|
|
47575
|
+
route: cl ? `/documents/cover/${cl.id}` : null
|
|
47576
|
+
};
|
|
47577
|
+
}
|
|
47578
|
+
function enrichTimelinePayload(payload) {
|
|
47579
|
+
const out = isRecord2(payload) ? { ...payload } : {};
|
|
47580
|
+
if (out.cover_letter) out.cover_letter = enrichCoverLetterRef(out.cover_letter);
|
|
47581
|
+
if (isRecord2(out.submission)) {
|
|
47582
|
+
const submission = { ...out.submission };
|
|
47583
|
+
if (submission.cover_letter) submission.cover_letter = enrichCoverLetterRef(submission.cover_letter);
|
|
47584
|
+
if (Array.isArray(submission.documents)) submission.documents = submission.documents.map(enrichDocumentRef);
|
|
47585
|
+
out.submission = submission;
|
|
47586
|
+
}
|
|
47587
|
+
return out;
|
|
47588
|
+
}
|
|
47589
|
+
function buildTimeline(job) {
|
|
47590
|
+
const application = applicationRepo.getByJob(job.id);
|
|
47591
|
+
const fit = fitRepo.getByJob(job.id);
|
|
47592
|
+
const coverLetters = coverLetterRepo.listByJob(job.id);
|
|
47593
|
+
const interview = interviewRepo.getByJob(job.id);
|
|
47594
|
+
const stored = timelineRepo.listByJob(job.id);
|
|
47595
|
+
const events = [
|
|
47596
|
+
{
|
|
47597
|
+
id: `synthetic-job-${job.id}`,
|
|
47598
|
+
job_id: job.id,
|
|
47599
|
+
type: "job_saved",
|
|
47600
|
+
title: "\uACF5\uACE0 \uB4F1\uB85D",
|
|
47601
|
+
summary: `${job.company} \xB7 ${job.position}`,
|
|
47602
|
+
payload: { synthetic: true },
|
|
47603
|
+
occurred_at: job.created_at,
|
|
47604
|
+
created_at: job.created_at
|
|
47605
|
+
},
|
|
47606
|
+
...stored
|
|
47607
|
+
];
|
|
47608
|
+
const hasStored = (type, predicate) => stored.some((event) => event.type === type && (!predicate || predicate(enrichTimelinePayload(event.payload))));
|
|
47609
|
+
if (fit && !hasStored("fit_analysis_saved", (payload) => payload.fit_id === fit.id)) {
|
|
47610
|
+
events.push({
|
|
47611
|
+
id: `synthetic-fit-${fit.id}`,
|
|
47612
|
+
job_id: job.id,
|
|
47613
|
+
type: "fit_analysis_saved",
|
|
47614
|
+
title: "\uC801\uD569\uB3C4 \uBD84\uC11D",
|
|
47615
|
+
summary: fit.score != null ? `\uC885\uD569 ${fit.score}\uC810` : fit.summary,
|
|
47616
|
+
payload: { synthetic: true, fit_id: fit.id, score: fit.score },
|
|
47617
|
+
occurred_at: fit.updated_at,
|
|
47618
|
+
created_at: fit.created_at
|
|
47619
|
+
});
|
|
47620
|
+
}
|
|
47621
|
+
for (const cl of coverLetters) {
|
|
47622
|
+
const versionId = cl.current_version_id;
|
|
47623
|
+
const alreadyStored = hasStored("cover_letter_version_saved", (payload) => {
|
|
47624
|
+
const ref = isRecord2(payload.cover_letter) ? payload.cover_letter : null;
|
|
47625
|
+
return ref?.id === cl.id && (!versionId || ref.version_id === versionId);
|
|
47626
|
+
});
|
|
47627
|
+
if (!alreadyStored) {
|
|
47628
|
+
events.push({
|
|
47629
|
+
id: `synthetic-cover-${cl.id}`,
|
|
47630
|
+
job_id: job.id,
|
|
47631
|
+
type: "cover_letter_version_saved",
|
|
47632
|
+
title: "\uC790\uAE30\uC18C\uAC1C\uC11C \uC791\uC131",
|
|
47633
|
+
summary: `${cl.title}${cl.version_count ? ` v${cl.version_count}` : ""}`,
|
|
47634
|
+
payload: {
|
|
47635
|
+
synthetic: true,
|
|
47636
|
+
cover_letter: {
|
|
47637
|
+
kind: "cover_letter",
|
|
47638
|
+
id: cl.id,
|
|
47639
|
+
title: cl.title,
|
|
47640
|
+
version_id: versionId,
|
|
47641
|
+
version_no: cl.version_count
|
|
47642
|
+
}
|
|
47643
|
+
},
|
|
47644
|
+
occurred_at: cl.updated_at,
|
|
47645
|
+
created_at: cl.created_at
|
|
47646
|
+
});
|
|
47647
|
+
}
|
|
47648
|
+
}
|
|
47649
|
+
if (application?.status && application.status !== "draft" && !hasStored("application_status_changed", (payload) => payload.status === application.status)) {
|
|
47650
|
+
events.push({
|
|
47651
|
+
id: `synthetic-status-${application.id}`,
|
|
47652
|
+
job_id: job.id,
|
|
47653
|
+
type: "application_status_changed",
|
|
47654
|
+
title: APPLICATION_STATUS_LABELS[application.status],
|
|
47655
|
+
summary: application.notes,
|
|
47656
|
+
payload: {
|
|
47657
|
+
synthetic: true,
|
|
47658
|
+
status: application.status,
|
|
47659
|
+
status_label: APPLICATION_STATUS_LABELS[application.status],
|
|
47660
|
+
submission: null
|
|
47661
|
+
},
|
|
47662
|
+
occurred_at: application.applied_at ?? application.updated_at,
|
|
47663
|
+
created_at: application.created_at
|
|
47664
|
+
});
|
|
47665
|
+
}
|
|
47666
|
+
if (interview && !hasStored("interview_prep_saved", (payload) => payload.interview_prep_id === interview.id)) {
|
|
47667
|
+
events.push({
|
|
47668
|
+
id: `synthetic-interview-${interview.id}`,
|
|
47669
|
+
job_id: job.id,
|
|
47670
|
+
type: "interview_prep_saved",
|
|
47671
|
+
title: "\uBA74\uC811 \uC900\uBE44",
|
|
47672
|
+
summary: interview.questions.length > 0 ? `\uC608\uC0C1 \uC9C8\uBB38 ${interview.questions.length}\uAC1C` : interview.notes,
|
|
47673
|
+
payload: { synthetic: true, interview_prep_id: interview.id, question_count: interview.questions.length },
|
|
47674
|
+
occurred_at: interview.updated_at,
|
|
47675
|
+
created_at: interview.created_at
|
|
47676
|
+
});
|
|
47677
|
+
}
|
|
47678
|
+
return events.sort((a, b) => String(a.occurred_at).localeCompare(String(b.occurred_at)) || String(a.created_at).localeCompare(String(b.created_at))).map((event) => ({ ...event, payload: enrichTimelinePayload(event.payload) }));
|
|
47679
|
+
}
|
|
46947
47680
|
function jobDetail(jobId) {
|
|
46948
47681
|
const job = jobRepo.get(jobId);
|
|
46949
47682
|
if (!job) throw new HttpError(404, "\uACF5\uACE0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
@@ -46952,13 +47685,15 @@ function jobDetail(jobId) {
|
|
|
46952
47685
|
const cover_letters = coverLetterRepo.listByJob(jobId);
|
|
46953
47686
|
const interview = interviewRepo.getByJob(jobId);
|
|
46954
47687
|
const related = jobRepo.relatedTo(job.company, job.position, job.id).map(jobWithMeta);
|
|
47688
|
+
const timeline = buildTimeline(job);
|
|
46955
47689
|
return {
|
|
46956
47690
|
...jobWithMeta(job),
|
|
46957
47691
|
application,
|
|
46958
47692
|
fit,
|
|
46959
47693
|
cover_letters,
|
|
46960
47694
|
interview,
|
|
46961
|
-
related
|
|
47695
|
+
related,
|
|
47696
|
+
timeline
|
|
46962
47697
|
};
|
|
46963
47698
|
}
|
|
46964
47699
|
function registerApiRoutes(router2) {
|
|
@@ -47107,12 +47842,12 @@ function registerApiRoutes(router2) {
|
|
|
47107
47842
|
});
|
|
47108
47843
|
router2.get("/api/interview", () => {
|
|
47109
47844
|
const preps = interviewRepo.list().map((p) => ({ ...p, job: jobRepo.get(p.job_id) }));
|
|
47110
|
-
const eligible = applicationRepo.list().
|
|
47845
|
+
const eligible = applicationRepo.list().map((a) => ({
|
|
47111
47846
|
job: jobRepo.get(a.job_id),
|
|
47112
47847
|
status: a.status,
|
|
47113
47848
|
status_label: APPLICATION_STATUS_LABELS[a.status],
|
|
47114
47849
|
has_prep: !!interviewRepo.getByJob(a.job_id)
|
|
47115
|
-
})).filter((x) => x.job);
|
|
47850
|
+
})).filter((x) => x.job && (x.has_prep || INTERVIEW_UNLOCK_STATUSES.includes(x.status)));
|
|
47116
47851
|
return { preps, eligible };
|
|
47117
47852
|
});
|
|
47118
47853
|
router2.get("/api/jobs/:id/interview", (ctx) => ({ interview: interviewRepo.getByJob(id2(ctx)) }));
|
|
@@ -47131,7 +47866,7 @@ function registerApiRoutes(router2) {
|
|
|
47131
47866
|
});
|
|
47132
47867
|
router2.put("/api/applications/:jobId/status", async (ctx) => {
|
|
47133
47868
|
const body = await readJsonBody(ctx.req, ApplicationStatusUpdateSchema.omit({ job_id: true, application_id: true }));
|
|
47134
|
-
return updateApplicationStatus(id2(ctx, "jobId"), body.status, body.note);
|
|
47869
|
+
return updateApplicationStatus(id2(ctx, "jobId"), body.status, body.note, body.submission);
|
|
47135
47870
|
});
|
|
47136
47871
|
router2.put("/api/applications/:jobId", async (ctx) => {
|
|
47137
47872
|
const body = await readJsonBody(ctx.req, ApplicationInputSchema.omit({ job_id: true }));
|
|
@@ -47160,6 +47895,32 @@ function registerApiRoutes(router2) {
|
|
|
47160
47895
|
return { verify_strict: on };
|
|
47161
47896
|
});
|
|
47162
47897
|
router2.post("/api/settings/backup", () => createBackup());
|
|
47898
|
+
router2.post("/api/settings/dashboard-shortcut", async (ctx) => {
|
|
47899
|
+
const { open } = await readJsonBody(ctx.req, external_exports.object({ open: external_exports.boolean().optional() }));
|
|
47900
|
+
return { shortcut: createDashboardShortcut(open === true) };
|
|
47901
|
+
});
|
|
47902
|
+
router2.post("/api/settings/import-preview", async (ctx) => {
|
|
47903
|
+
const { backup } = await readJsonBody(ctx.req, external_exports.object({ backup: external_exports.unknown() }));
|
|
47904
|
+
try {
|
|
47905
|
+
return { preview: previewBackupImport(backup) };
|
|
47906
|
+
} catch (e) {
|
|
47907
|
+
throw backupError(e);
|
|
47908
|
+
}
|
|
47909
|
+
});
|
|
47910
|
+
router2.post("/api/settings/restore", async (ctx) => {
|
|
47911
|
+
const { backup, confirm } = await readJsonBody(
|
|
47912
|
+
ctx.req,
|
|
47913
|
+
external_exports.object({ backup: external_exports.unknown(), confirm: external_exports.string() })
|
|
47914
|
+
);
|
|
47915
|
+
if (confirm !== "RESTORE") {
|
|
47916
|
+
throw new HttpError(400, "\uBCF5\uC6D0\uC744 \uC9C4\uD589\uD558\uB824\uBA74 \uD655\uC778 \uAC12\uC774 \uD544\uC694\uD569\uB2C8\uB2E4.", "restore_confirm_required");
|
|
47917
|
+
}
|
|
47918
|
+
try {
|
|
47919
|
+
return restoreBackup(backup);
|
|
47920
|
+
} catch (e) {
|
|
47921
|
+
throw backupError(e);
|
|
47922
|
+
}
|
|
47923
|
+
});
|
|
47163
47924
|
router2.post("/api/settings/reset", async (ctx) => {
|
|
47164
47925
|
const { confirm } = await readJsonBody(ctx.req, external_exports.object({ confirm: external_exports.string() }));
|
|
47165
47926
|
const result2 = resetAll(confirm);
|
|
@@ -47187,9 +47948,9 @@ function isDownload(v) {
|
|
|
47187
47948
|
}
|
|
47188
47949
|
|
|
47189
47950
|
// apps/web/src/server.ts
|
|
47190
|
-
var
|
|
47191
|
-
var WEB_ROOT = BUNDLED ? path5.resolve(
|
|
47192
|
-
var
|
|
47951
|
+
var __dirname2 = path5.dirname(fileURLToPath2(import.meta.url));
|
|
47952
|
+
var WEB_ROOT = BUNDLED ? path5.resolve(__dirname2, "public") : path5.resolve(__dirname2, "..", "public");
|
|
47953
|
+
var LANDING_URL = "https://careermate.life/";
|
|
47193
47954
|
var router = new Router();
|
|
47194
47955
|
registerApiRoutes(router);
|
|
47195
47956
|
function createServer() {
|
|
@@ -47224,16 +47985,11 @@ function createServer() {
|
|
|
47224
47985
|
}
|
|
47225
47986
|
return;
|
|
47226
47987
|
}
|
|
47227
|
-
if (pathname === "/install") {
|
|
47228
|
-
res.writeHead(
|
|
47988
|
+
if (pathname === "/install" || pathname.startsWith("/install/")) {
|
|
47989
|
+
res.writeHead(302, { Location: LANDING_URL });
|
|
47229
47990
|
res.end();
|
|
47230
47991
|
return;
|
|
47231
47992
|
}
|
|
47232
|
-
if (pathname.startsWith("/install/")) {
|
|
47233
|
-
const rel2 = pathname === "/install/" ? "index.html" : pathname.slice("/install/".length);
|
|
47234
|
-
if (serveStatic(res, INSTALL_ROOT, rel2)) return;
|
|
47235
|
-
if (serveStatic(res, INSTALL_ROOT, "index.html")) return;
|
|
47236
|
-
}
|
|
47237
47993
|
const rel = pathname === "/" ? "index.html" : pathname.slice(1);
|
|
47238
47994
|
if (serveStatic(res, WEB_ROOT, rel, injectToken)) return;
|
|
47239
47995
|
if (serveStatic(res, WEB_ROOT, "index.html", injectToken)) return;
|
|
@@ -47291,11 +48047,11 @@ function openBrowser(url) {
|
|
|
47291
48047
|
const platform = process.platform;
|
|
47292
48048
|
try {
|
|
47293
48049
|
if (platform === "win32") {
|
|
47294
|
-
|
|
48050
|
+
spawn2("cmd", ["/c", "start", "", url], { stdio: "ignore", detached: true }).unref();
|
|
47295
48051
|
} else if (platform === "darwin") {
|
|
47296
|
-
|
|
48052
|
+
spawn2("open", [url], { stdio: "ignore", detached: true }).unref();
|
|
47297
48053
|
} else {
|
|
47298
|
-
|
|
48054
|
+
spawn2("xdg-open", [url], { stdio: "ignore", detached: true }).unref();
|
|
47299
48055
|
}
|
|
47300
48056
|
} catch {
|
|
47301
48057
|
}
|
|
@@ -47308,7 +48064,7 @@ async function main() {
|
|
|
47308
48064
|
console.log(` CareerMate v${APP_VERSION} \u2014 \uB0B4 \uCEE4\uB9AC\uC5B4 \uD750\uB984 \uAD00\uB9AC \uB3C4\uAD6C`);
|
|
47309
48065
|
console.log(`${" ".repeat(2)}${"\u2504".repeat(52)}`);
|
|
47310
48066
|
console.log(` \uB300\uC2DC\uBCF4\uB4DC ${url}`);
|
|
47311
|
-
console.log(` \uC124\uCE58
|
|
48067
|
+
console.log(` \uC124\uCE58\xB7\uC548\uB0B4 https://careermate.life`);
|
|
47312
48068
|
console.log(` \uB370\uC774\uD130 \uC704\uCE58 ${getDataDir()}`);
|
|
47313
48069
|
console.log(` (\uBAA8\uB4E0 \uB370\uC774\uD130\uB294 \uC774 \uCEF4\uD4E8\uD130\uC5D0\uB9CC \uC800\uC7A5\uB429\uB2C8\uB2E4)`);
|
|
47314
48070
|
console.log(`\u2514${line}\u2518
|