careermate 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/doctor.mjs +185 -39
- package/dist/mcp.mjs +188 -42
- package/dist/migrate.mjs +23 -1
- package/dist/public/lib.js +5 -1
- package/dist/public/pages/applications.js +7 -0
- package/dist/public/pages/jobs.js +22 -15
- package/dist/public/styles.css +9 -0
- package/dist/site/index.html +3 -43
- package/dist/site/start.html +122 -102
- package/dist/web.mjs +138 -13
- package/docs/MCP_TOOLS.md +6 -5
- package/docs/START_WORKFLOW.md +2 -1
- package/docs/WORKFLOWS.md +1 -1
- package/package.json +1 -1
- package/packages/core/src/services.ts +67 -5
- package/packages/db/src/repositories.ts +0 -0
- package/packages/mcp-tools/src/tools.ts +21 -18
- package/packages/prompts/src/onboarding.ts +1 -1
- package/packages/shared/src/enums.ts +7 -2
- package/packages/shared/src/errors.ts +33 -0
- package/packages/shared/src/index.ts +1 -0
- package/packages/shared/src/schemas.ts +56 -2
- package/packages/workflows/src/definitions.ts +1 -1
package/dist/doctor.mjs
CHANGED
|
@@ -68172,7 +68172,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
68172
68172
|
const ij = i2 * width + j;
|
|
68173
68173
|
const center = buf[ij];
|
|
68174
68174
|
let sum = 0;
|
|
68175
|
-
let
|
|
68175
|
+
let norm2 = 0;
|
|
68176
68176
|
for (let k = 0; k < kernelSize; k++) {
|
|
68177
68177
|
const y = i2 + k - halfSize;
|
|
68178
68178
|
if (y < 0 || y >= height) {
|
|
@@ -68186,10 +68186,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
68186
68186
|
const neighbour = buf[y * width + x2];
|
|
68187
68187
|
const w = kernel[k * kernelSize + l2] * rangeValues[Math.abs(neighbour - center)];
|
|
68188
68188
|
sum += neighbour * w;
|
|
68189
|
-
|
|
68189
|
+
norm2 += w;
|
|
68190
68190
|
}
|
|
68191
68191
|
}
|
|
68192
|
-
const pix = out[ij] = Math.round(sum /
|
|
68192
|
+
const pix = out[ij] = Math.round(sum / norm2);
|
|
68193
68193
|
histogram[pix]++;
|
|
68194
68194
|
}
|
|
68195
68195
|
}
|
|
@@ -71451,6 +71451,24 @@ function setVerifyStrict(on) {
|
|
|
71451
71451
|
return on;
|
|
71452
71452
|
}
|
|
71453
71453
|
|
|
71454
|
+
// packages/shared/src/errors.ts
|
|
71455
|
+
var CareerMateError = class extends Error {
|
|
71456
|
+
constructor(message, httpStatus = 400, code) {
|
|
71457
|
+
super(message);
|
|
71458
|
+
this.httpStatus = httpStatus;
|
|
71459
|
+
this.code = code;
|
|
71460
|
+
this.name = "CareerMateError";
|
|
71461
|
+
}
|
|
71462
|
+
httpStatus;
|
|
71463
|
+
code;
|
|
71464
|
+
};
|
|
71465
|
+
function notFound(message) {
|
|
71466
|
+
return new CareerMateError(message, 404, "not_found");
|
|
71467
|
+
}
|
|
71468
|
+
function conflict(message) {
|
|
71469
|
+
return new CareerMateError(message, 409, "conflict");
|
|
71470
|
+
}
|
|
71471
|
+
|
|
71454
71472
|
// packages/shared/src/enums.ts
|
|
71455
71473
|
var APPLICATION_STATUSES = [
|
|
71456
71474
|
"draft",
|
|
@@ -71501,8 +71519,9 @@ function canTransitionStatus(from, to) {
|
|
|
71501
71519
|
}
|
|
71502
71520
|
function assertStatusTransition(from, to) {
|
|
71503
71521
|
if (!canTransitionStatus(from, to)) {
|
|
71504
|
-
|
|
71505
|
-
|
|
71522
|
+
const suffix = to === "draft" ? ` ('${APPLICATION_STATUS_LABELS[from]}' \uB2E8\uACC4\uC758 \uC9C0\uC6D0\uC740 \uC791\uC131 \uC911(\uBBF8\uCD94\uC801)\uC73C\uB85C \uB418\uB3CC\uB9B4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uCD08\uAE30 \uB2E8\uACC4\uB85C \uC62E\uAE30\uB824\uBA74 '\uC9C0\uC6D0 \uC608\uC815'\uC744 \uC120\uD0DD\uD558\uC138\uC694.)` : "";
|
|
71523
|
+
throw conflict(
|
|
71524
|
+
`'${APPLICATION_STATUS_LABELS[from]}'\uC5D0\uC11C '${APPLICATION_STATUS_LABELS[to]}'(\uC73C)\uB85C\uB294 \uC0C1\uD0DC\uB97C \uBC14\uAFC0 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.${suffix}`
|
|
71506
71525
|
);
|
|
71507
71526
|
}
|
|
71508
71527
|
}
|
|
@@ -75595,7 +75614,20 @@ var optLine = external_exports.string().max(MAX_LINE).optional();
|
|
|
75595
75614
|
var optNote = external_exports.string().max(MAX_NOTE).optional();
|
|
75596
75615
|
var optBody = external_exports.string().max(MAX_BODY).optional();
|
|
75597
75616
|
var reqBody = external_exports.string().max(MAX_BODY).refine((s) => s.trim().length > 0, { message: EMPTY_MSG });
|
|
75598
|
-
|
|
75617
|
+
function toStrList(v) {
|
|
75618
|
+
if (typeof v !== "string") return v;
|
|
75619
|
+
const s = v.trim();
|
|
75620
|
+
if (!s) return [];
|
|
75621
|
+
if (s.startsWith("[")) {
|
|
75622
|
+
try {
|
|
75623
|
+
const parsed = JSON.parse(s);
|
|
75624
|
+
if (Array.isArray(parsed)) return parsed;
|
|
75625
|
+
} catch {
|
|
75626
|
+
}
|
|
75627
|
+
}
|
|
75628
|
+
return s.split(/[\n,]/).map((x2) => x2.trim()).filter(Boolean);
|
|
75629
|
+
}
|
|
75630
|
+
var strList = external_exports.preprocess(toStrList, external_exports.array(external_exports.string().max(MAX_ITEM)).max(MAX_ITEMS));
|
|
75599
75631
|
var baseRecord = {
|
|
75600
75632
|
id,
|
|
75601
75633
|
created_at: isoDateTime,
|
|
@@ -75657,6 +75689,9 @@ var ExperienceRecordSchema = external_exports.object({
|
|
|
75657
75689
|
tech: external_exports.array(external_exports.string()),
|
|
75658
75690
|
order_index: external_exports.number()
|
|
75659
75691
|
});
|
|
75692
|
+
var ExperienceBatchInputSchema = external_exports.object({
|
|
75693
|
+
experiences: external_exports.array(ExperienceInputSchema).min(1).max(MAX_ITEMS).describe("\uCD94\uAC00\uD560 \uACBD\uB825 \uBAA9\uB85D(\uD55C \uAC74\uC774\uC5B4\uB3C4 \uBC30\uC5F4\uB85C). \uAC19\uC740 \uD68C\uC0AC\xB7\uC9C1\uBB34\xB7\uC785\uC0AC\uC77C\uC740 \uAC31\uC2E0\uB418\uACE0 \uC911\uBCF5 \uC0DD\uC131\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.")
|
|
75694
|
+
});
|
|
75660
75695
|
var ProjectInputSchema = external_exports.object({
|
|
75661
75696
|
name: reqLine,
|
|
75662
75697
|
role: optLine,
|
|
@@ -75680,6 +75715,9 @@ var ProjectRecordSchema = external_exports.object({
|
|
|
75680
75715
|
end_date: external_exports.string().nullable(),
|
|
75681
75716
|
order_index: external_exports.number()
|
|
75682
75717
|
});
|
|
75718
|
+
var ProjectBatchInputSchema = external_exports.object({
|
|
75719
|
+
projects: external_exports.array(ProjectInputSchema).min(1).max(MAX_ITEMS).describe("\uCD94\uAC00\uD560 \uD504\uB85C\uC81D\uD2B8 \uBAA9\uB85D(\uD55C \uAC1C\uC5EC\uB3C4 \uBC30\uC5F4\uB85C). \uAC19\uC740 \uC774\uB984\uC758 \uD504\uB85C\uC81D\uD2B8\uB294 \uAC31\uC2E0\uB418\uACE0 \uC911\uBCF5 \uC0DD\uC131\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.")
|
|
75720
|
+
});
|
|
75683
75721
|
var SkillInputSchema = external_exports.object({
|
|
75684
75722
|
name: reqLine,
|
|
75685
75723
|
category: external_exports.string().max(MAX_LINE).optional().describe("\uC5B8\uC5B4/\uD504\uB808\uC784\uC6CC\uD06C/\uD234/\uC18C\uD504\uD2B8\uC2A4\uD0AC \uB4F1"),
|
|
@@ -75695,6 +75733,9 @@ var SkillRecordSchema = external_exports.object({
|
|
|
75695
75733
|
years: external_exports.number().nullable(),
|
|
75696
75734
|
order_index: external_exports.number()
|
|
75697
75735
|
});
|
|
75736
|
+
var SkillBatchInputSchema = external_exports.object({
|
|
75737
|
+
skills: external_exports.array(SkillInputSchema).min(1).max(MAX_ITEMS).describe("\uCD94\uAC00\uD560 \uAE30\uC220\uC2A4\uD0DD \uBAA9\uB85D(\uD55C \uAC1C\uC5EC\uB3C4 \uBC30\uC5F4\uB85C). \uAC19\uC740 \uC774\uB984\uC758 \uAE30\uC220\uC740 \uAC31\uC2E0\uB418\uACE0 \uC911\uBCF5 \uC0DD\uC131\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.")
|
|
75738
|
+
});
|
|
75698
75739
|
var DocumentInputSchema = external_exports.object({
|
|
75699
75740
|
kind: external_exports.enum(DOCUMENT_KINDS),
|
|
75700
75741
|
title: reqLine,
|
|
@@ -75891,7 +75932,7 @@ var ApplicationContextSchema = external_exports.object({
|
|
|
75891
75932
|
});
|
|
75892
75933
|
|
|
75893
75934
|
// packages/shared/src/build-info.ts
|
|
75894
|
-
var APP_VERSION = true ? "0.0.
|
|
75935
|
+
var APP_VERSION = true ? "0.0.4" : "0.0.0-dev";
|
|
75895
75936
|
var BUNDLED = true;
|
|
75896
75937
|
|
|
75897
75938
|
// packages/shared/src/index.ts
|
|
@@ -75906,6 +75947,7 @@ function now() {
|
|
|
75906
75947
|
|
|
75907
75948
|
// packages/db/src/repositories.ts
|
|
75908
75949
|
var PROFILE_ID = "profile-singleton";
|
|
75950
|
+
var norm = (s) => (s ?? "").trim().toLowerCase();
|
|
75909
75951
|
function mapProfile(r) {
|
|
75910
75952
|
return {
|
|
75911
75953
|
id: r.id,
|
|
@@ -75983,6 +76025,9 @@ function mapExperience(r) {
|
|
|
75983
76025
|
updated_at: r.updated_at
|
|
75984
76026
|
};
|
|
75985
76027
|
}
|
|
76028
|
+
function expKey(company, role, start) {
|
|
76029
|
+
return [norm(company), norm(role), norm(start)].join("\0");
|
|
76030
|
+
}
|
|
75986
76031
|
var experienceRepo = {
|
|
75987
76032
|
list() {
|
|
75988
76033
|
return getDb().prepare(`SELECT * FROM experiences ORDER BY order_index ASC, start_date DESC`).all().map(mapExperience);
|
|
@@ -75991,6 +76036,32 @@ var experienceRepo = {
|
|
|
75991
76036
|
const r = getDb().prepare(`SELECT * FROM experiences WHERE id = ?`).get(id2);
|
|
75992
76037
|
return r ? mapExperience(r) : null;
|
|
75993
76038
|
},
|
|
76039
|
+
/** Existing experience with the same company+role+start_date, or null (for idempotent batch upserts). */
|
|
76040
|
+
findMatch(input) {
|
|
76041
|
+
const key = expKey(input.company, input.role ?? null, input.start_date ?? null);
|
|
76042
|
+
return this.list().find((e) => expKey(e.company, e.role, e.start_date) === key) ?? null;
|
|
76043
|
+
},
|
|
76044
|
+
/** Insert, or merge into the matching experience (omitted fields keep their stored value). */
|
|
76045
|
+
upsert(input) {
|
|
76046
|
+
const existing = this.findMatch(input);
|
|
76047
|
+
if (existing) return { record: this.update(existing.id, input), created: false };
|
|
76048
|
+
return { record: this.add(input), created: true };
|
|
76049
|
+
},
|
|
76050
|
+
/** Batch insert/merge in one transaction; within-batch duplicates collapse onto one row. */
|
|
76051
|
+
addMany(inputs) {
|
|
76052
|
+
return tx(() => {
|
|
76053
|
+
const records = [];
|
|
76054
|
+
let created = 0;
|
|
76055
|
+
let updated = 0;
|
|
76056
|
+
for (const input of inputs) {
|
|
76057
|
+
const { record, created: isNew } = this.upsert(input);
|
|
76058
|
+
records.push(record);
|
|
76059
|
+
if (isNew) created += 1;
|
|
76060
|
+
else updated += 1;
|
|
76061
|
+
}
|
|
76062
|
+
return { records, created, updated };
|
|
76063
|
+
});
|
|
76064
|
+
},
|
|
75994
76065
|
add(input) {
|
|
75995
76066
|
const ts = now();
|
|
75996
76067
|
const id2 = newId("exp_");
|
|
@@ -76064,6 +76135,32 @@ var projectRepo = {
|
|
|
76064
76135
|
const r = getDb().prepare(`SELECT * FROM projects WHERE id = ?`).get(id2);
|
|
76065
76136
|
return r ? mapProject(r) : null;
|
|
76066
76137
|
},
|
|
76138
|
+
/** Existing project with the same name (case-insensitive), or null (for idempotent batch upserts). */
|
|
76139
|
+
findByName(name) {
|
|
76140
|
+
const key = norm(name);
|
|
76141
|
+
return this.list().find((p) => norm(p.name) === key) ?? null;
|
|
76142
|
+
},
|
|
76143
|
+
/** Insert, or merge into the same-named project (omitted fields keep their stored value). */
|
|
76144
|
+
upsert(input) {
|
|
76145
|
+
const existing = this.findByName(input.name);
|
|
76146
|
+
if (existing) return { record: this.update(existing.id, input), created: false };
|
|
76147
|
+
return { record: this.add(input), created: true };
|
|
76148
|
+
},
|
|
76149
|
+
/** Batch insert/merge in one transaction; within-batch duplicates collapse onto one row. */
|
|
76150
|
+
addMany(inputs) {
|
|
76151
|
+
return tx(() => {
|
|
76152
|
+
const records = [];
|
|
76153
|
+
let created = 0;
|
|
76154
|
+
let updated = 0;
|
|
76155
|
+
for (const input of inputs) {
|
|
76156
|
+
const { record, created: isNew } = this.upsert(input);
|
|
76157
|
+
records.push(record);
|
|
76158
|
+
if (isNew) created += 1;
|
|
76159
|
+
else updated += 1;
|
|
76160
|
+
}
|
|
76161
|
+
return { records, created, updated };
|
|
76162
|
+
});
|
|
76163
|
+
},
|
|
76067
76164
|
add(input) {
|
|
76068
76165
|
const ts = now();
|
|
76069
76166
|
const id2 = newId("prj_");
|
|
@@ -76131,6 +76228,32 @@ var skillRepo = {
|
|
|
76131
76228
|
const r = getDb().prepare(`SELECT * FROM skills WHERE id = ?`).get(id2);
|
|
76132
76229
|
return r ? mapSkill(r) : null;
|
|
76133
76230
|
},
|
|
76231
|
+
/** Existing skill with the same name (case-insensitive), or null (for idempotent batch upserts). */
|
|
76232
|
+
findByName(name) {
|
|
76233
|
+
const key = norm(name);
|
|
76234
|
+
return this.list().find((s) => norm(s.name) === key) ?? null;
|
|
76235
|
+
},
|
|
76236
|
+
/** Insert, or merge into the same-named skill (omitted fields keep their stored value). */
|
|
76237
|
+
upsert(input) {
|
|
76238
|
+
const existing = this.findByName(input.name);
|
|
76239
|
+
if (existing) return { record: this.update(existing.id, input), created: false };
|
|
76240
|
+
return { record: this.add(input), created: true };
|
|
76241
|
+
},
|
|
76242
|
+
/** Batch insert/merge in one transaction; within-batch duplicates collapse onto one row. */
|
|
76243
|
+
addMany(inputs) {
|
|
76244
|
+
return tx(() => {
|
|
76245
|
+
const records = [];
|
|
76246
|
+
let created = 0;
|
|
76247
|
+
let updated = 0;
|
|
76248
|
+
for (const input of inputs) {
|
|
76249
|
+
const { record, created: isNew } = this.upsert(input);
|
|
76250
|
+
records.push(record);
|
|
76251
|
+
if (isNew) created += 1;
|
|
76252
|
+
else updated += 1;
|
|
76253
|
+
}
|
|
76254
|
+
return { records, created, updated };
|
|
76255
|
+
});
|
|
76256
|
+
},
|
|
76134
76257
|
add(input) {
|
|
76135
76258
|
const ts = now();
|
|
76136
76259
|
const id2 = newId("skl_");
|
|
@@ -76960,7 +77083,7 @@ function styleSignals(text) {
|
|
|
76960
77083
|
}
|
|
76961
77084
|
var DISCLAIMER = "\uC774 \uC810\uAC80\uC740 LLM \uC5C6\uC774 \uC140 \uC218 \uC788\uB294 \uAC83\uB9CC \uBD05\uB2C8\uB2E4(\uC22B\uC790 \uCD9C\uCC98\xB7\uBB38\uCCB4 \uC2E0\uD638). \uD1B5\uACFC=\uD569\uACA9\uC774 \uC544\uB2C8\uBA70, \uC0AC\uC2E4\xB7\uB3D9\uBB38\uC11C\uB2F5\xB7\uC758\uBBF8 \uD310\uB2E8\uC740 \uB2F9\uC2E0(AI)\uC774 \uC9C1\uC811 \uD574\uC57C \uD569\uB2C8\uB2E4.";
|
|
76962
77085
|
function lintArtifact(kind, text, corpus, opts = {}) {
|
|
76963
|
-
const
|
|
77086
|
+
const norm2 = normalizeText(text);
|
|
76964
77087
|
const corpusAvailable = (corpus.documents + corpus.structured).trim().length > 0;
|
|
76965
77088
|
const provenance = analyzeProvenance(text, corpus);
|
|
76966
77089
|
const signals = styleSignals(text);
|
|
@@ -76984,7 +77107,7 @@ function lintArtifact(kind, text, corpus, opts = {}) {
|
|
|
76984
77107
|
}
|
|
76985
77108
|
return {
|
|
76986
77109
|
kind,
|
|
76987
|
-
charCount: [...
|
|
77110
|
+
charCount: [...norm2].length,
|
|
76988
77111
|
signals,
|
|
76989
77112
|
provenance,
|
|
76990
77113
|
blocking,
|
|
@@ -77044,20 +77167,40 @@ function addResume(input) {
|
|
|
77044
77167
|
activityRepo.log("resume_added", `${doc.title} \uBB38\uC11C\uB97C \uCD94\uAC00\uD588\uC2B5\uB2C8\uB2E4.`, "document", doc.id);
|
|
77045
77168
|
return doc;
|
|
77046
77169
|
}
|
|
77047
|
-
function
|
|
77048
|
-
const
|
|
77049
|
-
|
|
77050
|
-
return
|
|
77170
|
+
function batchNames(names) {
|
|
77171
|
+
const shown = names.filter(Boolean).slice(0, 8).join(", ");
|
|
77172
|
+
if (!shown) return "";
|
|
77173
|
+
return `: ${shown}${names.length > 8 ? " \uC678" : ""}`;
|
|
77051
77174
|
}
|
|
77052
|
-
function
|
|
77053
|
-
const
|
|
77054
|
-
activityRepo.log(
|
|
77055
|
-
|
|
77175
|
+
function addExperiences(inputs) {
|
|
77176
|
+
const res = experienceRepo.addMany(inputs);
|
|
77177
|
+
activityRepo.log(
|
|
77178
|
+
"profile_updated",
|
|
77179
|
+
`\uACBD\uB825 ${res.records.length}\uAC74\uC744 \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4(\uC2E0\uADDC ${res.created} \xB7 \uAC31\uC2E0 ${res.updated})${batchNames(res.records.map((e) => e.company))}.`,
|
|
77180
|
+
"experience",
|
|
77181
|
+
res.records[0]?.id
|
|
77182
|
+
);
|
|
77183
|
+
return res;
|
|
77184
|
+
}
|
|
77185
|
+
function addProjects(inputs) {
|
|
77186
|
+
const res = projectRepo.addMany(inputs);
|
|
77187
|
+
activityRepo.log(
|
|
77188
|
+
"profile_updated",
|
|
77189
|
+
`\uD504\uB85C\uC81D\uD2B8 ${res.records.length}\uAC74\uC744 \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4(\uC2E0\uADDC ${res.created} \xB7 \uAC31\uC2E0 ${res.updated})${batchNames(res.records.map((p) => p.name))}.`,
|
|
77190
|
+
"project",
|
|
77191
|
+
res.records[0]?.id
|
|
77192
|
+
);
|
|
77193
|
+
return res;
|
|
77056
77194
|
}
|
|
77057
|
-
function
|
|
77058
|
-
const
|
|
77059
|
-
activityRepo.log(
|
|
77060
|
-
|
|
77195
|
+
function addSkills(inputs) {
|
|
77196
|
+
const res = skillRepo.addMany(inputs);
|
|
77197
|
+
activityRepo.log(
|
|
77198
|
+
"profile_updated",
|
|
77199
|
+
`\uAE30\uC220 ${res.records.length}\uAC1C\uB97C \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4(\uC2E0\uADDC ${res.created} \xB7 \uAC31\uC2E0 ${res.updated})${batchNames(res.records.map((s) => s.name))}.`,
|
|
77200
|
+
"skill",
|
|
77201
|
+
res.records[0]?.id
|
|
77202
|
+
);
|
|
77203
|
+
return res;
|
|
77061
77204
|
}
|
|
77062
77205
|
function saveJobPosting(input, id2) {
|
|
77063
77206
|
const job = jobRepo.upsert(input, id2);
|
|
@@ -77067,7 +77210,7 @@ function saveJobPosting(input, id2) {
|
|
|
77067
77210
|
}
|
|
77068
77211
|
function saveFitAnalysis(input) {
|
|
77069
77212
|
const job = jobRepo.get(input.job_id);
|
|
77070
|
-
if (!job) throw
|
|
77213
|
+
if (!job) throw notFound(`\uACF5\uACE0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${input.job_id}. \uBA3C\uC800 save_job_posting\uC73C\uB85C \uACF5\uACE0\uB97C \uC800\uC7A5\uD558\uC138\uC694.`);
|
|
77071
77214
|
applicationRepo.ensure(job.id, "draft");
|
|
77072
77215
|
const fit = fitRepo.save(input);
|
|
77073
77216
|
const scoreText = fit.score != null ? ` (\uC801\uD569\uB3C4 ${fit.score}\uC810)` : "";
|
|
@@ -77082,7 +77225,7 @@ function saveCoverLetterVersion(input) {
|
|
|
77082
77225
|
const detail = verification.blocking.map((b) => `${b.label}: ${b.detail}`).join("; ");
|
|
77083
77226
|
const strictHit = verification.blocking.some((b) => b.id === "unverified_numbers_strict");
|
|
77084
77227
|
const tail = strictHit ? `\uC5C4\uACA9 \uBAA8\uB4DC\uAC00 \uCF1C\uC838 \uC788\uC5B4, \uC62C\uB9B0 \uC774\uB825\uC11C \uBCF8\uBB38\uC5D0 \uC5C6\uB294 \uC218\uCE58\uB294 \uB9C9\uD799\uB2C8\uB2E4. \uC774\uB825\uC11C\uB97C \uC62C\uB9AC\uAC70\uB098 \uC5C4\uACA9 \uBAA8\uB4DC\uB97C \uB044\uAC70\uB098, \uC758\uB3C4\uD55C \uAC12\uC774\uBA74 force: true\uB85C \uC800\uC7A5\uD558\uC138\uC694.` : `\uC774 \uC218\uCE58\uB294 \uC800\uC7A5\uB41C \uACBD\uB825\xB7\uC774\uB825\uC11C\xB7\uD504\uB85C\uC81D\uD2B8\uC5D0 \uC5C6\uC2B5\uB2C8\uB2E4. \uC6D0\uBCF8 \uB370\uC774\uD130\uC758 \uC2E4\uC81C \uC218\uCE58\uB85C \uACE0\uCE58\uAC70\uB098, \uC758\uB3C4\uD55C \uAC12\uC774 \uB9DE\uB2E4\uBA74 \uBA3C\uC800 \uACBD\uB825/\uD504\uB85C\uC81D\uD2B8\uC5D0 \uADF8 \uC218\uCE58\uB97C \uCD94\uAC00\uD55C \uB4A4 \uB2E4\uC2DC \uC800\uC7A5\uD558\uC138\uC694(\uADF8\uB300\uB85C \uC800\uC7A5\uD558\uB824\uBA74 force: true).`;
|
|
77085
|
-
throw new
|
|
77228
|
+
throw new CareerMateError(`\uC800\uC7A5 \uC804 \uC790\uB3D9 \uC810\uAC80\uC5D0\uC11C \uB9C9\uD614\uC2B5\uB2C8\uB2E4 \u2014 ${detail}. ${tail}`, 400, "save_gate");
|
|
77086
77229
|
}
|
|
77087
77230
|
const { coverLetter, version: version2 } = coverLetterRepo.addVersion({
|
|
77088
77231
|
cover_letter_id: input.cover_letter_id,
|
|
@@ -77109,7 +77252,7 @@ function saveCoverLetterVersion(input) {
|
|
|
77109
77252
|
}
|
|
77110
77253
|
function updateApplicationStatus(jobId, status, note) {
|
|
77111
77254
|
const job = jobRepo.get(jobId);
|
|
77112
|
-
if (!job) throw
|
|
77255
|
+
if (!job) throw notFound(`\uACF5\uACE0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${jobId}`);
|
|
77113
77256
|
const application = applicationRepo.setStatus(jobId, status, note);
|
|
77114
77257
|
activityRepo.log(
|
|
77115
77258
|
"application_status_changed",
|
|
@@ -77124,11 +77267,11 @@ function updateApplicationStatus(jobId, status, note) {
|
|
|
77124
77267
|
}
|
|
77125
77268
|
function saveInterviewPrep(input) {
|
|
77126
77269
|
const job = jobRepo.get(input.job_id);
|
|
77127
|
-
if (!job) throw
|
|
77270
|
+
if (!job) throw notFound(`\uACF5\uACE0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${input.job_id}`);
|
|
77128
77271
|
const app = applicationRepo.getByJob(job.id);
|
|
77129
77272
|
if (!app || !INTERVIEW_UNLOCK_STATUSES.includes(app.status)) {
|
|
77130
77273
|
const current = app ? APPLICATION_STATUS_LABELS[app.status] : "\uBBF8\uC9C0\uC6D0";
|
|
77131
|
-
throw
|
|
77274
|
+
throw conflict(
|
|
77132
77275
|
`\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.`
|
|
77133
77276
|
);
|
|
77134
77277
|
}
|
|
@@ -77209,7 +77352,7 @@ var WORKFLOWS = [
|
|
|
77209
77352
|
'\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.)',
|
|
77210
77353
|
"\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.",
|
|
77211
77354
|
"\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).",
|
|
77212
|
-
"\uACBD\uB825\xB7\uD504\uB85C\uC81D\uD2B8\xB7\uC2A4\uD0AC\uC774 \uD30C\uC545\uB418\uBA74 `add_experience`\xB7`add_project`\xB7`add_skill`\uB85C \
|
|
77355
|
+
"\uACBD\uB825\xB7\uD504\uB85C\uC81D\uD2B8\xB7\uC2A4\uD0AC\uC774 \uD30C\uC545\uB418\uBA74 `add_experience`\xB7`add_project`\xB7`add_skill`\uB85C \uC800\uC7A5\uD55C\uB2E4 \u2014 \uAC01 \uB3C4\uAD6C\uB294 \uBC30\uC5F4\uC744 \uBC1B\uC73C\uBBC0\uB85C \uD30C\uC545\uD55C \uD56D\uBAA9\uC744 \uD55C \uBC88\uC5D0 \uBAA8\uC544 \uB118\uAE34\uB2E4(\uD56D\uBAA9\uB9C8\uB2E4 \uBC18\uBCF5 \uD638\uCD9C\uD558\uC9C0 \uC54A\uB294\uB2E4). \uAC19\uC740 \uD56D\uBAA9\uC744 \uB2E4\uC2DC \uB123\uC5B4\uB3C4 \uC911\uBCF5 \uC5C6\uC774 \uAC31\uC2E0\uB41C\uB2E4(\uC644\uC131\uB3C4\uC758 has_experience/has_skills\uC5D0 \uBC18\uC601).",
|
|
77213
77356
|
"\uAE30\uC874 \uC790\uAE30\uC18C\uAC1C\uC11C\uAC00 \uC788\uC73C\uBA74 `save_cover_letter_version`\uC73C\uB85C \uC800\uC7A5\uD55C\uB2E4(title+content\uBA74 v1\uB85C \uC800\uC7A5, \uC5C6\uC73C\uBA74 \uB098\uC911\uC5D0 \uC791\uC131 \uAC00\uB2A5\uD568\uC744 \uC548\uB0B4).",
|
|
77214
77357
|
"`open_dashboard`\uB97C \uD638\uCD9C\uD574 \uC0AC\uC6A9\uC790\uAC00 \uC790\uAE30 \uB370\uC774\uD130\uB97C \uD655\uC778\uD558\uAC8C \uD55C\uB2E4.",
|
|
77215
77358
|
"\uB2E4\uC2DC `get_onboarding_status`\uB85C \uC644\uC131\uB3C4\uB97C \uD655\uC778\uD558\uACE0, \uB2E4\uC74C \uB2E8\uACC4(\uACF5\uACE0 \uBD84\uC11D \uB4F1)\uB97C \uC81C\uC548\uD55C\uB2E4."
|
|
@@ -79018,11 +79161,12 @@ ${lines}`;
|
|
|
79018
79161
|
{
|
|
79019
79162
|
name: "add_experience",
|
|
79020
79163
|
title: "\uACBD\uB825 \uCD94\uAC00",
|
|
79021
|
-
description: "\uAD6C\uC870\uD654\uB41C \uACBD\uB825(\uC9C1\uC7A5 \uB2E8\uC704)\uC744 \
|
|
79022
|
-
inputSchema:
|
|
79164
|
+
description: "\uAD6C\uC870\uD654\uB41C \uACBD\uB825(\uC9C1\uC7A5 \uB2E8\uC704)\uC744 \uC800\uC7A5\uD569\uB2C8\uB2E4. \uC774\uB825\uC11C\uC5D0\uC11C \uD30C\uC545\uD55C \uACBD\uB825\uC744 experiences \uBC30\uC5F4\uC5D0 \uD55C \uBC88\uC5D0 \uB2F4\uC544 \uD638\uCD9C\uD558\uC138\uC694(\uD55C \uAC74\uC774\uC5B4\uB3C4 \uBC30\uC5F4\uB85C \u2014 \uD56D\uBAA9\uB9C8\uB2E4 \uB3C4\uAD6C\uB97C \uBC18\uBCF5 \uD638\uCD9C\uD558\uC9C0 \uB9C8\uC138\uC694). \uC774\uB825\uC11C \uBCF8\uBB38(add_resume)\uACFC \uB2EC\uB9AC \uD68C\uC0AC\xB7\uC9C1\uBB34\xB7\uAE30\uAC04\xB7\uC131\uACFC\uB97C \uD544\uB4DC\uB85C \uB098\uB220 \uC800\uC7A5\uD574 \uC801\uD569\uB3C4 \uBD84\uC11D/\uC790\uC18C\uC11C \uC791\uC131 \uC2DC \uC815\uBC00\uD558\uAC8C \uD65C\uC6A9\uB429\uB2C8\uB2E4. \uAC01 \uD56D\uBAA9\uC740 company\uAC00 \uD544\uC218\uC774\uBA70, achievements\uC5D0\uB294 \uC815\uB7C9 \uC9C0\uD45C\uAC00 \uB2F4\uAE34 \uC131\uACFC\uB97C, tech\uC5D0\uB294 \uC0AC\uC6A9 \uAE30\uC220\uC744 \uBC30\uC5F4\uB85C \uB123\uC73C\uC138\uC694. \uAC19\uC740 \uD68C\uC0AC\xB7\uC9C1\uBB34\xB7\uC785\uC0AC\uC77C(start_date)\uC774 \uC77C\uCE58\uD558\uBA74 \uAC31\uC2E0\uB418\uACE0 \uC911\uBCF5 \uC0DD\uC131\uB418\uC9C0 \uC54A\uC73C\uB2C8 \uC5EC\uB7EC \uBC88 \uC800\uC7A5\uD574\uB3C4 \uC548\uC804\uD569\uB2C8\uB2E4. \uC628\uBCF4\uB529 \uC644\uC131\uB3C4(get_onboarding_status)\uC758 has_experience\uB97C \uCC44\uC6B0\uB824\uBA74 1\uAC74 \uC774\uC0C1 \uCD94\uAC00\uD558\uC138\uC694.",
|
|
79165
|
+
inputSchema: ExperienceBatchInputSchema.shape,
|
|
79023
79166
|
handler: (args) => {
|
|
79024
|
-
const
|
|
79025
|
-
|
|
79167
|
+
const { records, created, updated } = addExperiences(args.experiences);
|
|
79168
|
+
const names = records.map((e) => `${e.company}${e.role ? ` \xB7 ${e.role}` : ""}`).join(", ");
|
|
79169
|
+
return ok(`\uACBD\uB825 ${records.length}\uAC74\uC744 \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4 (\uC2E0\uADDC ${created} \xB7 \uAC31\uC2E0 ${updated}): ${names}`, records);
|
|
79026
79170
|
}
|
|
79027
79171
|
},
|
|
79028
79172
|
{
|
|
@@ -79040,11 +79184,12 @@ ${lines}`;
|
|
|
79040
79184
|
{
|
|
79041
79185
|
name: "add_project",
|
|
79042
79186
|
title: "\uD504\uB85C\uC81D\uD2B8 \uCD94\uAC00",
|
|
79043
|
-
description: "\uB300\uD45C \uD504\uB85C\uC81D\uD2B8\uB97C \
|
|
79044
|
-
inputSchema:
|
|
79187
|
+
description: "\uB300\uD45C \uD504\uB85C\uC81D\uD2B8\uB97C \uC800\uC7A5\uD569\uB2C8\uB2E4. projects \uBC30\uC5F4\uC5D0 \uC5EC\uB7EC \uAC1C\uB97C \uD55C \uBC88\uC5D0 \uB2F4\uC544 \uD638\uCD9C\uD558\uC138\uC694(\uD55C \uAC1C\uC5EC\uB3C4 \uBC30\uC5F4\uB85C \u2014 \uD56D\uBAA9\uB9C8\uB2E4 \uBC18\uBCF5 \uD638\uCD9C\uD558\uC9C0 \uB9C8\uC138\uC694). \uAC01 \uD56D\uBAA9\uC740 name\uC774 \uD544\uC218\uC774\uBA70, highlights(\uD575\uC2EC \uC131\uACFC)\uC640 tech(\uC0AC\uC6A9 \uAE30\uC220)\uB97C \uBC30\uC5F4\uB85C \uB123\uC73C\uBA74 \uC790\uC18C\uC11C\xB7\uBA74\uC811 \uC900\uBE44\uC5D0\uC11C \uADFC\uAC70\uB85C \uD65C\uC6A9\uB429\uB2C8\uB2E4. url\uC5D0 \uACB0\uACFC\uBB3C \uB9C1\uD06C\uB97C \uB123\uC744 \uC218 \uC788\uC2B5\uB2C8\uB2E4. \uAC19\uC740 \uC774\uB984\uC758 \uD504\uB85C\uC81D\uD2B8\uB294 \uAC31\uC2E0\uB418\uACE0 \uC911\uBCF5 \uC0DD\uC131\uB418\uC9C0 \uC54A\uC73C\uB2C8 \uC5EC\uB7EC \uBC88 \uC800\uC7A5\uD574\uB3C4 \uC548\uC804\uD569\uB2C8\uB2E4.",
|
|
79188
|
+
inputSchema: ProjectBatchInputSchema.shape,
|
|
79045
79189
|
handler: (args) => {
|
|
79046
|
-
const
|
|
79047
|
-
|
|
79190
|
+
const { records, created, updated } = addProjects(args.projects);
|
|
79191
|
+
const names = records.map((p) => p.name).join(", ");
|
|
79192
|
+
return ok(`\uD504\uB85C\uC81D\uD2B8 ${records.length}\uAC74\uC744 \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4 (\uC2E0\uADDC ${created} \xB7 \uAC31\uC2E0 ${updated}): ${names}`, records);
|
|
79048
79193
|
}
|
|
79049
79194
|
},
|
|
79050
79195
|
{
|
|
@@ -79062,11 +79207,12 @@ ${lines}`;
|
|
|
79062
79207
|
{
|
|
79063
79208
|
name: "add_skill",
|
|
79064
79209
|
title: "\uAE30\uC220\uC2A4\uD0DD \uCD94\uAC00",
|
|
79065
|
-
description: "\uBCF4\uC720 \uAE30\uC220\uC2A4\uD0DD\uC744 \
|
|
79066
|
-
inputSchema:
|
|
79210
|
+
description: "\uBCF4\uC720 \uAE30\uC220\uC2A4\uD0DD\uC744 \uC800\uC7A5\uD569\uB2C8\uB2E4. \uC5EC\uB7EC \uAC1C\uB97C skills \uBC30\uC5F4\uC5D0 \uD55C \uBC88\uC5D0 \uB2F4\uC544 \uD638\uCD9C\uD558\uC138\uC694(\uD55C \uAC1C\uC5EC\uB3C4 \uBC30\uC5F4\uB85C \u2014 \uAE30\uC220\uB9C8\uB2E4 \uB3C4\uAD6C\uB97C \uBC18\uBCF5 \uD638\uCD9C\uD558\uC9C0 \uB9C8\uC138\uC694). \uAC01 \uD56D\uBAA9\uC740 name\uC774 \uD544\uC218\uC774\uBA70, category(\uC5B8\uC5B4/\uD504\uB808\uC784\uC6CC\uD06C/\uD234/\uC18C\uD504\uD2B8\uC2A4\uD0AC \uB4F1)\xB7level\xB7years\uB85C \uC219\uB828\uB3C4\uB97C \uD568\uAED8 \uAE30\uB85D\uD558\uBA74 \uACF5\uACE0 \uD0A4\uC6CC\uB4DC \uB9E4\uCE6D\uC774 \uC815\uD655\uD574\uC9D1\uB2C8\uB2E4. \uAC19\uC740 \uC774\uB984\uC758 \uAE30\uC220\uC740 \uAC31\uC2E0\uB418\uACE0 \uC911\uBCF5 \uC0DD\uC131\uB418\uC9C0 \uC54A\uC73C\uB2C8 \uC5EC\uB7EC \uBC88 \uC800\uC7A5\uD574\uB3C4 \uC548\uC804\uD569\uB2C8\uB2E4. \uC628\uBCF4\uB529 \uC644\uC131\uB3C4\uC758 has_skills\uB97C \uCC44\uC6B0\uB824\uBA74 1\uAC1C \uC774\uC0C1 \uCD94\uAC00\uD558\uC138\uC694.",
|
|
79211
|
+
inputSchema: SkillBatchInputSchema.shape,
|
|
79067
79212
|
handler: (args) => {
|
|
79068
|
-
const
|
|
79069
|
-
|
|
79213
|
+
const { records, created, updated } = addSkills(args.skills);
|
|
79214
|
+
const names = records.map((s) => s.name).join(", ");
|
|
79215
|
+
return ok(`\uAE30\uC220 ${records.length}\uAC1C\uB97C \uC800\uC7A5\uD588\uC2B5\uB2C8\uB2E4 (\uC2E0\uADDC ${created} \xB7 \uAC31\uC2E0 ${updated}): ${names}`, records);
|
|
79070
79216
|
}
|
|
79071
79217
|
},
|
|
79072
79218
|
{
|