careermate 0.0.7 → 0.0.9
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 +2 -2
- package/LICENSE +1 -1
- package/README.md +108 -91
- package/THIRD_PARTY_NOTICES.md +2 -1
- package/bin/careermate.mjs +11 -2
- package/dist/career-os/eop/cover-letter.md +13 -6
- package/dist/career-os/eop/interview-prep.md +1 -0
- package/dist/career-os/knowledge/cover-letter.md +7 -3
- package/dist/career-os/knowledge/fit-matching.md +2 -0
- package/dist/career-os/knowledge/verifiers/ai-detection-risk.md +57 -0
- package/dist/career-os/knowledge/verifiers/human-voice.md +7 -2
- package/dist/career-os/knowledge/verifiers/truthfulness.md +1 -0
- package/dist/doctor.mjs +19760 -1018
- package/dist/mcp.mjs +19783 -1035
- package/dist/migrate.mjs +289 -20
- package/dist/public/i18n/en/applications.js +19 -0
- package/dist/public/i18n/en/common.js +10 -0
- package/dist/public/i18n/en/documents.js +0 -10
- package/dist/public/i18n/en/home.js +5 -0
- package/dist/public/i18n/en/jobs.js +18 -1
- package/dist/public/i18n/en/profile.js +0 -5
- package/dist/public/i18n/en/settings.js +5 -2
- package/dist/public/i18n/ko/applications.js +19 -0
- package/dist/public/i18n/ko/common.js +9 -0
- package/dist/public/i18n/ko/documents.js +0 -10
- package/dist/public/i18n/ko/home.js +5 -0
- package/dist/public/i18n/ko/jobs.js +18 -1
- package/dist/public/i18n/ko/profile.js +0 -5
- package/dist/public/i18n/ko/settings.js +5 -2
- package/dist/public/lib.js +101 -0
- package/dist/public/pages/applications.js +95 -15
- package/dist/public/pages/documents.js +20 -14
- package/dist/public/pages/home.js +38 -6
- package/dist/public/pages/interview.js +11 -4
- package/dist/public/pages/jobs.js +71 -1
- package/dist/public/pages/profile.js +2 -3
- package/dist/public/pages/settings.js +2 -2
- package/dist/public/styles.css +52 -4
- package/dist/web.mjs +19001 -758
- package/docs/FAQ.md +13 -3
- package/docs/MCP_TOOLS.md +32 -12
- package/docs/career-os/eop/cover-letter.md +13 -6
- package/docs/career-os/eop/interview-prep.md +1 -0
- package/docs/career-os/knowledge/cover-letter.md +7 -3
- package/docs/career-os/knowledge/fit-matching.md +2 -0
- package/docs/career-os/knowledge/verifiers/ai-detection-risk.md +57 -0
- package/docs/career-os/knowledge/verifiers/human-voice.md +7 -2
- package/docs/career-os/knowledge/verifiers/truthfulness.md +1 -0
- package/package.json +5 -2
- package/packages/core/src/index.ts +2 -0
- package/packages/core/src/jobsearch.ts +190 -0
- package/packages/core/src/offers.ts +41 -0
- package/packages/core/src/services.ts +29 -3
- package/packages/core/src/summary.ts +431 -9
- package/packages/core/src/verify/charcount.ts +87 -0
- package/packages/core/src/verify/index.ts +1 -0
- package/packages/core/src/verify/lint.ts +5 -0
- package/packages/db/src/connection.ts +70 -2
- package/packages/db/src/index.ts +1 -0
- package/packages/db/src/repositories.ts +179 -13
- package/packages/db/src/schema.ts +169 -8
- package/packages/exporters/src/docx.ts +165 -0
- package/packages/exporters/src/index.ts +142 -9
- package/packages/exporters/src/markdown.ts +16 -11
- package/packages/knowledge/src/index.ts +8 -3
- package/packages/mcp-tools/src/result.ts +9 -0
- package/packages/mcp-tools/src/tools.ts +303 -60
- package/packages/parsers/src/documents.ts +7 -1
- package/packages/prompts/src/humanize.ts +4 -0
- package/packages/shared/src/schemas.ts +198 -0
- package/scripts/init.ts +7 -0
package/dist/migrate.mjs
CHANGED
|
@@ -18,8 +18,15 @@ function getDataDir() {
|
|
|
18
18
|
function getDbPath() {
|
|
19
19
|
return path.join(getDataDir(), "careermate.sqlite");
|
|
20
20
|
}
|
|
21
|
+
function getBackupsDir() {
|
|
22
|
+
const dir = path.join(getDataDir(), "backups");
|
|
23
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
24
|
+
return dir;
|
|
25
|
+
}
|
|
21
26
|
|
|
22
27
|
// packages/db/src/connection.ts
|
|
28
|
+
import fs2 from "node:fs";
|
|
29
|
+
import path2 from "node:path";
|
|
23
30
|
import { DatabaseSync } from "node:sqlite";
|
|
24
31
|
|
|
25
32
|
// packages/db/src/schema.ts
|
|
@@ -312,33 +319,181 @@ var MIGRATIONS = [
|
|
|
312
319
|
);
|
|
313
320
|
|
|
314
321
|
CREATE INDEX IF NOT EXISTS idx_timeline_job ON application_timeline_events(job_id, occurred_at ASC);
|
|
322
|
+
`,
|
|
323
|
+
// v4 — structured quantitative credentials on the profile (학력·자격증·어학점수·수상).
|
|
324
|
+
// Stored as JSON arrays in TEXT columns (same pattern as profile.links), so the AI
|
|
325
|
+
// can cite exact values (GPA, TOEIC 920) without re-asking or hallucinating, and
|
|
326
|
+
// they feed the verify corpus. ALTER ADD COLUMN is non-destructive and idempotent
|
|
327
|
+
// across the ordered migration runner.
|
|
328
|
+
`
|
|
329
|
+
ALTER TABLE profile ADD COLUMN education TEXT NOT NULL DEFAULT '[]';
|
|
330
|
+
ALTER TABLE profile ADD COLUMN certifications TEXT NOT NULL DEFAULT '[]';
|
|
331
|
+
ALTER TABLE profile ADD COLUMN language_scores TEXT NOT NULL DEFAULT '[]';
|
|
332
|
+
ALTER TABLE profile ADD COLUMN awards TEXT NOT NULL DEFAULT '[]';
|
|
333
|
+
`,
|
|
334
|
+
// v5 — company research on the job posting (사업개요·인재상·핵심가치). Korea-centric: cover
|
|
335
|
+
// letters and interview prep align to a company's 인재상/핵심가치, so store it where the AI
|
|
336
|
+
// already reads it (the job context) rather than a separate entity. Additive ALTER, idempotent.
|
|
337
|
+
`
|
|
338
|
+
ALTER TABLE jobs ADD COLUMN company_overview TEXT;
|
|
339
|
+
ALTER TABLE jobs ADD COLUMN talent_profile TEXT;
|
|
340
|
+
ALTER TABLE jobs ADD COLUMN core_values TEXT NOT NULL DEFAULT '[]';
|
|
341
|
+
`,
|
|
342
|
+
// v6 — post-interview debrief on interview_preps (받은 질문·잘된 점·개선점·다음 라운드 포커스·
|
|
343
|
+
// 체감 분위기). Closes the loop: prep is pre-interview, debrief is post-interview, but both belong
|
|
344
|
+
// to the same per-job entity, so store as one JSON column rather than a new table. Additive ALTER,
|
|
345
|
+
// idempotent. Feeds next-round prep and consistency (lessons carry into later interviews).
|
|
346
|
+
`
|
|
347
|
+
ALTER TABLE interview_preps ADD COLUMN debrief TEXT NOT NULL DEFAULT '{}';
|
|
348
|
+
`,
|
|
349
|
+
// v7 — offer comparison (한국 총보상 필드) + company reputation research field on jobs.
|
|
350
|
+
// offers: one per job (UNIQUE job_id, mirrors interview_preps). Cash pieces are numeric (만원) so
|
|
351
|
+
// the server can deterministically sum an annual estimate; equity/other stay free-text (comp is
|
|
352
|
+
// messy). ai_score/verdict are written by the connected AI at save time (no LLM here) and rendered
|
|
353
|
+
// by the dashboard, so it never needs to call an LLM. jobs.reputation: AI-researched company
|
|
354
|
+
// reputation summary (same pattern as company_overview) — feeds offer verdicts + offer-evaluation.
|
|
355
|
+
`
|
|
356
|
+
CREATE TABLE IF NOT EXISTS offers (
|
|
357
|
+
id TEXT PRIMARY KEY,
|
|
358
|
+
job_id TEXT NOT NULL UNIQUE REFERENCES jobs(id) ON DELETE CASCADE,
|
|
359
|
+
base_salary INTEGER,
|
|
360
|
+
bonus_amount INTEGER,
|
|
361
|
+
welfare_amount INTEGER,
|
|
362
|
+
signing_amount INTEGER,
|
|
363
|
+
equity_note TEXT,
|
|
364
|
+
comp_note TEXT,
|
|
365
|
+
work_arrangement TEXT,
|
|
366
|
+
contract_type TEXT,
|
|
367
|
+
accept_deadline TEXT,
|
|
368
|
+
ai_score INTEGER,
|
|
369
|
+
verdict TEXT,
|
|
370
|
+
notes TEXT,
|
|
371
|
+
created_at TEXT NOT NULL,
|
|
372
|
+
updated_at TEXT NOT NULL
|
|
373
|
+
);
|
|
374
|
+
CREATE INDEX IF NOT EXISTS idx_offers_job ON offers(job_id);
|
|
375
|
+
ALTER TABLE jobs ADD COLUMN reputation TEXT;
|
|
376
|
+
`,
|
|
377
|
+
// v8 — offer lifecycle status. 지원 상태(전형 깔때기 = 회사의 프로세스)와 직교하는
|
|
378
|
+
// "내 응답" 축: open(진행)/accepted(수락)/declined(거절). declined여도 행을 지우지
|
|
379
|
+
// 않는다 — 조건(연봉·처우) 히스토리는 다음 협상의 자산이라, 대시보드가 접힌
|
|
380
|
+
// '지난 오퍼'로 강등해 보여줄 뿐이다. Additive ALTER (runner가 멱등 처리).
|
|
381
|
+
`
|
|
382
|
+
ALTER TABLE offers ADD COLUMN offer_status TEXT NOT NULL DEFAULT 'open';
|
|
383
|
+
`,
|
|
384
|
+
// v9 — 한국 문항형 자소서: 회사가 지정한 문항·글자수를 공고에 구조화 보관. 한국 자소서는
|
|
385
|
+
// 회사별 문항형(항목·글자수 제한)이 지배적이라, AI가 문항별로 답변을 쓰고 글자수를 점검할 때
|
|
386
|
+
// 참조할 원본을 공고 옆에 둔다(별도 엔티티가 아니라 job 컨텍스트에 함께 실린다). JSON 배열을
|
|
387
|
+
// TEXT에 저장(다른 JSON 필드와 동일). Additive ALTER (runner가 멱등 처리).
|
|
388
|
+
`
|
|
389
|
+
ALTER TABLE jobs ADD COLUMN questions TEXT NOT NULL DEFAULT '[]';
|
|
390
|
+
`,
|
|
391
|
+
// v10 — 탈락 회고: 어느 전형 단계에서 떨어졌는지 자가 기록. 탈락 사유를 고지하는 기업은 6%뿐이고
|
|
392
|
+
// 지원자 83%가 알고 싶어하므로, 이 자가 기록이 "서류는 붙는데 면접에서 떨어진다" 같은 패턴을 로컬
|
|
393
|
+
// 데이터로 드러내는 유일한 신호다. 탈락이 아니거나 미기록이면 NULL. Additive ALTER (runner가 멱등 처리).
|
|
394
|
+
`
|
|
395
|
+
ALTER TABLE applications ADD COLUMN rejected_stage TEXT;
|
|
396
|
+
`,
|
|
397
|
+
// v11 — 전형 일정: 서류마감→인적성·AI역검→1·2차 면접→발표로 이어지는 단계별 날짜를 공고에
|
|
398
|
+
// 구조화 보관. 일정을 jobs에 두는 이유: 서류마감(deadline)이 이미 jobs에 있고, save_job_posting
|
|
399
|
+
// 업서트를 그대로 재사용해 도구 신설 없이 갱신할 수 있다. 면접초대 메일·발표 공지를 사용자가
|
|
400
|
+
// 붙여넣으면 AI가 날짜를 추출해 저장하고, 서버가 D-day·같은 날짜 충돌을 결정론으로 계산한다.
|
|
401
|
+
// JSON 배열을 TEXT에 저장(다른 JSON 필드와 동일). Additive ALTER (runner가 멱등 처리).
|
|
402
|
+
`
|
|
403
|
+
ALTER TABLE jobs ADD COLUMN schedule TEXT NOT NULL DEFAULT '[]';
|
|
315
404
|
`
|
|
316
405
|
];
|
|
317
406
|
function migrate(db) {
|
|
318
407
|
db.exec(`CREATE TABLE IF NOT EXISTS _meta (key TEXT PRIMARY KEY, value TEXT NOT NULL);`);
|
|
319
408
|
const row = db.prepare(`SELECT value FROM _meta WHERE key = 'schema_version'`).get();
|
|
320
409
|
const from = row ? Number(row.value) : 0;
|
|
410
|
+
if (from >= MIGRATIONS.length) return { from, to: from };
|
|
321
411
|
for (let v = from; v < MIGRATIONS.length; v++) {
|
|
322
|
-
db
|
|
412
|
+
applyMigration(db, v);
|
|
323
413
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
414
|
+
return { from, to: MIGRATIONS.length };
|
|
415
|
+
}
|
|
416
|
+
function stampVersion(db, version) {
|
|
417
|
+
db.prepare(
|
|
418
|
+
`INSERT INTO _meta (key, value) VALUES ('schema_version', ?)
|
|
419
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value`
|
|
420
|
+
).run(String(version));
|
|
421
|
+
}
|
|
422
|
+
function columnExists(db, table, column) {
|
|
423
|
+
const rows = db.prepare(`PRAGMA table_info("${table.replaceAll('"', '""')}")`).all();
|
|
424
|
+
return rows.some((r) => r.name === column);
|
|
425
|
+
}
|
|
426
|
+
var SELF_TRANSACTIONAL_MIGRATIONS = /* @__PURE__ */ new Set([1]);
|
|
427
|
+
var ALTER_ADD_COLUMN_RE = /^[ \t]*ALTER TABLE\s+(\w+)\s+ADD COLUMN\s+(\w+)[^;]*;[ \t]*$/gm;
|
|
428
|
+
function skipExistingColumns(db, sql) {
|
|
429
|
+
return sql.replace(
|
|
430
|
+
ALTER_ADD_COLUMN_RE,
|
|
431
|
+
(stmt, table, column) => columnExists(db, table, column) ? "" : stmt
|
|
432
|
+
);
|
|
433
|
+
}
|
|
434
|
+
function applyMigration(db, v) {
|
|
435
|
+
const sql = MIGRATIONS[v];
|
|
436
|
+
if (SELF_TRANSACTIONAL_MIGRATIONS.has(v)) {
|
|
437
|
+
db.exec(sql);
|
|
438
|
+
stampVersion(db, v + 1);
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
db.exec("BEGIN");
|
|
442
|
+
try {
|
|
443
|
+
db.exec(skipExistingColumns(db, sql));
|
|
444
|
+
stampVersion(db, v + 1);
|
|
445
|
+
db.exec("COMMIT");
|
|
446
|
+
} catch (err) {
|
|
447
|
+
try {
|
|
448
|
+
db.exec("ROLLBACK");
|
|
449
|
+
} catch {
|
|
450
|
+
}
|
|
451
|
+
throw err;
|
|
330
452
|
}
|
|
331
|
-
return { from, to };
|
|
332
453
|
}
|
|
333
454
|
|
|
334
455
|
// packages/db/src/connection.ts
|
|
335
456
|
var _db = null;
|
|
457
|
+
var PRE_MIGRATE_KEEP = 5;
|
|
458
|
+
function vacuumInto(db, destPath) {
|
|
459
|
+
if (/[\0\n\r]/.test(destPath)) throw new Error("backup path not safe for SQL literal");
|
|
460
|
+
db.exec(`VACUUM INTO '${destPath.replace(/'/g, "''")}'`);
|
|
461
|
+
}
|
|
462
|
+
function preMigrationBackup(db) {
|
|
463
|
+
try {
|
|
464
|
+
const hasMeta = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='_meta'`).get();
|
|
465
|
+
if (!hasMeta) return;
|
|
466
|
+
const row = db.prepare(`SELECT value FROM _meta WHERE key = 'schema_version'`).get();
|
|
467
|
+
const from = row ? Number(row.value) : 0;
|
|
468
|
+
if (from === 0 || from >= MIGRATIONS.length) return;
|
|
469
|
+
const dir = getBackupsDir();
|
|
470
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
471
|
+
const dest = path2.join(dir, `pre-migrate-v${from}-${stamp}.sqlite`);
|
|
472
|
+
try {
|
|
473
|
+
vacuumInto(db, dest);
|
|
474
|
+
} catch {
|
|
475
|
+
fs2.copyFileSync(getDbPath(), dest);
|
|
476
|
+
}
|
|
477
|
+
const stale = fs2.readdirSync(dir).filter((f) => f.startsWith("pre-migrate-") && f.endsWith(".sqlite")).sort().reverse().slice(PRE_MIGRATE_KEEP);
|
|
478
|
+
for (const f of stale) {
|
|
479
|
+
try {
|
|
480
|
+
fs2.unlinkSync(path2.join(dir, f));
|
|
481
|
+
} catch {
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
} catch (err) {
|
|
485
|
+
console.error(
|
|
486
|
+
`[careermate] \uC5C5\uADF8\uB808\uC774\uB4DC \uC804 \uC790\uB3D9 \uBC31\uC5C5 \uC2E4\uD328(\uB9C8\uC774\uADF8\uB808\uC774\uC158\uC740 \uACC4\uC18D \uC9C4\uD589): ${err instanceof Error ? err.message : String(err)}`
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
336
490
|
function getDb() {
|
|
337
491
|
if (_db) return _db;
|
|
338
492
|
const db = new DatabaseSync(getDbPath());
|
|
339
493
|
db.exec("PRAGMA journal_mode = WAL;");
|
|
340
494
|
db.exec("PRAGMA foreign_keys = ON;");
|
|
341
495
|
db.exec("PRAGMA busy_timeout = 5000;");
|
|
496
|
+
preMigrationBackup(db);
|
|
342
497
|
migrate(db);
|
|
343
498
|
_db = db;
|
|
344
499
|
return db;
|
|
@@ -874,8 +1029,8 @@ function getErrorMap() {
|
|
|
874
1029
|
|
|
875
1030
|
// node_modules/zod/v3/helpers/parseUtil.js
|
|
876
1031
|
var makeIssue = (params) => {
|
|
877
|
-
const { data, path:
|
|
878
|
-
const fullPath = [...
|
|
1032
|
+
const { data, path: path3, errorMaps, issueData } = params;
|
|
1033
|
+
const fullPath = [...path3, ...issueData.path || []];
|
|
879
1034
|
const fullIssue = {
|
|
880
1035
|
...issueData,
|
|
881
1036
|
path: fullPath
|
|
@@ -991,11 +1146,11 @@ var errorUtil;
|
|
|
991
1146
|
|
|
992
1147
|
// node_modules/zod/v3/types.js
|
|
993
1148
|
var ParseInputLazyPath = class {
|
|
994
|
-
constructor(parent, value,
|
|
1149
|
+
constructor(parent, value, path3, key) {
|
|
995
1150
|
this._cachedPath = [];
|
|
996
1151
|
this.parent = parent;
|
|
997
1152
|
this.data = value;
|
|
998
|
-
this._path =
|
|
1153
|
+
this._path = path3;
|
|
999
1154
|
this._key = key;
|
|
1000
1155
|
}
|
|
1001
1156
|
get path() {
|
|
@@ -4482,6 +4637,33 @@ var LinkSchema = external_exports.object({
|
|
|
4482
4637
|
label: reqLine,
|
|
4483
4638
|
url: SafeUrl
|
|
4484
4639
|
});
|
|
4640
|
+
var EducationSchema = external_exports.object({
|
|
4641
|
+
school: reqLine.describe("\uD559\uAD50\uBA85"),
|
|
4642
|
+
degree: external_exports.string().max(MAX_LINE).optional().describe("\uD559\uC704/\uACFC\uC815 (\uACE0\uC878\xB7\uD559\uC0AC\xB7\uC11D\uC0AC\xB7\uBC15\uC0AC \uB4F1)"),
|
|
4643
|
+
major: external_exports.string().max(MAX_LINE).optional().describe("\uC804\uACF5"),
|
|
4644
|
+
gpa: external_exports.string().max(MAX_LINE).optional().describe("\uD559\uC810 (\uC608: 3.8)"),
|
|
4645
|
+
gpa_scale: external_exports.string().max(MAX_LINE).optional().describe("\uD559\uC810 \uB9CC\uC810 (\uC608: 4.5)"),
|
|
4646
|
+
start_date: external_exports.string().max(MAX_LINE).optional().describe("YYYY-MM"),
|
|
4647
|
+
end_date: external_exports.string().max(MAX_LINE).optional().describe("YYYY-MM (\uC878\uC5C5/\uC608\uC815)"),
|
|
4648
|
+
status: external_exports.string().max(MAX_LINE).optional().describe("\uC878\uC5C5/\uC7AC\uD559/\uD734\uD559/\uC911\uD1F4/\uC218\uB8CC")
|
|
4649
|
+
});
|
|
4650
|
+
var CertificationSchema = external_exports.object({
|
|
4651
|
+
name: reqLine.describe("\uC790\uACA9\uC99D/\uBA74\uD5C8\uBA85"),
|
|
4652
|
+
issuer: external_exports.string().max(MAX_LINE).optional().describe("\uBC1C\uAE09\uAE30\uAD00"),
|
|
4653
|
+
date: external_exports.string().max(MAX_LINE).optional().describe("\uCDE8\uB4DD\uC77C YYYY-MM"),
|
|
4654
|
+
score: external_exports.string().max(MAX_LINE).optional().describe("\uC810\uC218/\uB4F1\uAE09(\uC788\uC73C\uBA74)")
|
|
4655
|
+
});
|
|
4656
|
+
var LanguageScoreSchema = external_exports.object({
|
|
4657
|
+
test: reqLine.describe("\uC2DC\uD5D8\uBA85 (TOEIC\xB7OPIc\xB7TOEIC Speaking\xB7JLPT\xB7HSK \uB4F1)"),
|
|
4658
|
+
score: reqLine.describe("\uC810\uC218/\uB4F1\uAE09 (\uC608: 920, IH, N1)"),
|
|
4659
|
+
date: external_exports.string().max(MAX_LINE).optional().describe("\uC751\uC2DC/\uCDE8\uB4DD\uC77C YYYY-MM")
|
|
4660
|
+
});
|
|
4661
|
+
var AwardSchema = external_exports.object({
|
|
4662
|
+
title: reqLine.describe("\uC218\uC0C1/\uB300\uC678\uD65C\uB3D9\uBA85"),
|
|
4663
|
+
issuer: external_exports.string().max(MAX_LINE).optional().describe("\uC8FC\uCD5C/\uC218\uC5EC\uAE30\uAD00"),
|
|
4664
|
+
date: external_exports.string().max(MAX_LINE).optional().describe("YYYY-MM"),
|
|
4665
|
+
description: external_exports.string().max(MAX_NOTE).optional().describe("\uAC04\uB2E8 \uC124\uBA85")
|
|
4666
|
+
});
|
|
4485
4667
|
var ProfileInputSchema = external_exports.object({
|
|
4486
4668
|
name: reqLine.optional(),
|
|
4487
4669
|
email: optLine,
|
|
@@ -4493,7 +4675,11 @@ var ProfileInputSchema = external_exports.object({
|
|
|
4493
4675
|
desired_conditions: external_exports.string().max(MAX_NOTE).optional().describe("\uD76C\uB9DD \uADFC\uBB34 \uC870\uAC74 (\uC5F0\uBD09, \uC9C0\uC5ED, \uADFC\uBB34\uD615\uD0DC \uB4F1)"),
|
|
4494
4676
|
preferred_tone: external_exports.string().max(MAX_LINE).optional().describe("\uC790\uAE30\uC18C\uAC1C\uC11C \uC120\uD638 \uBB38\uCCB4 (\uC608: \uB2F4\uBC31\uD558\uACE0 \uAD6C\uCCB4\uC801)"),
|
|
4495
4677
|
emphasis_points: strList.optional().describe("\uAC15\uC870\uD558\uACE0 \uC2F6\uC740 \uD575\uC2EC \uD3EC\uC778\uD2B8"),
|
|
4496
|
-
links: external_exports.array(LinkSchema).max(MAX_ITEMS).optional().describe("\uD3EC\uD2B8\uD3F4\uB9AC\uC624/\uAE43\uD5C8\uBE0C/\uB9C1\uD06C\uB4DC\uC778 \uB4F1")
|
|
4678
|
+
links: external_exports.array(LinkSchema).max(MAX_ITEMS).optional().describe("\uD3EC\uD2B8\uD3F4\uB9AC\uC624/\uAE43\uD5C8\uBE0C/\uB9C1\uD06C\uB4DC\uC778 \uB4F1"),
|
|
4679
|
+
education: external_exports.array(EducationSchema).max(MAX_ITEMS).optional().describe("\uD559\uB825 (\uD559\uAD50\xB7\uD559\uC704\xB7\uC804\uACF5\xB7\uD559\uC810)"),
|
|
4680
|
+
certifications: external_exports.array(CertificationSchema).max(MAX_ITEMS).optional().describe("\uC790\uACA9\uC99D/\uBA74\uD5C8"),
|
|
4681
|
+
language_scores: external_exports.array(LanguageScoreSchema).max(MAX_ITEMS).optional().describe("\uC5B4\uD559 \uC810\uC218 (\uD1A0\uC775\xB7\uC624\uD53D \uB4F1)"),
|
|
4682
|
+
awards: external_exports.array(AwardSchema).max(MAX_ITEMS).optional().describe("\uC218\uC0C1/\uB300\uC678\uD65C\uB3D9")
|
|
4497
4683
|
});
|
|
4498
4684
|
var ProfileRecordSchema = external_exports.object({
|
|
4499
4685
|
...baseRecord,
|
|
@@ -4507,7 +4693,11 @@ var ProfileRecordSchema = external_exports.object({
|
|
|
4507
4693
|
desired_conditions: external_exports.string().nullable(),
|
|
4508
4694
|
preferred_tone: external_exports.string().nullable(),
|
|
4509
4695
|
emphasis_points: external_exports.array(external_exports.string()),
|
|
4510
|
-
links: external_exports.array(LinkSchema)
|
|
4696
|
+
links: external_exports.array(LinkSchema),
|
|
4697
|
+
education: external_exports.array(EducationSchema),
|
|
4698
|
+
certifications: external_exports.array(CertificationSchema),
|
|
4699
|
+
language_scores: external_exports.array(LanguageScoreSchema),
|
|
4700
|
+
awards: external_exports.array(AwardSchema)
|
|
4511
4701
|
});
|
|
4512
4702
|
var ExperienceInputSchema = external_exports.object({
|
|
4513
4703
|
company: reqLine,
|
|
@@ -4636,6 +4826,22 @@ var CoverLetterRecordSchema = external_exports.object({
|
|
|
4636
4826
|
current_content: external_exports.string().nullable(),
|
|
4637
4827
|
versions: external_exports.array(CoverLetterVersionRecordSchema).optional()
|
|
4638
4828
|
});
|
|
4829
|
+
var JobQuestionSchema = external_exports.object({
|
|
4830
|
+
no: external_exports.number().int().positive().optional().describe("\uBB38\uD56D \uBC88\uD638(\uC788\uC73C\uBA74)"),
|
|
4831
|
+
question: external_exports.string().max(MAX_BODY).describe("\uBB38\uD56D \uD14D\uC2A4\uD2B8(\uD68C\uC0AC\uAC00 \uC81C\uC2DC\uD55C \uC790\uC18C\uC11C \uD56D\uBAA9)"),
|
|
4832
|
+
min_chars: external_exports.number().int().positive().optional().describe("\uAE00\uC790\uC218 \uD558\uD55C(\uC788\uC73C\uBA74)"),
|
|
4833
|
+
max_chars: external_exports.number().int().positive().optional().describe("\uAE00\uC790\uC218 \uC0C1\uD55C(\uC788\uC73C\uBA74)"),
|
|
4834
|
+
count_mode: external_exports.enum(["with_space", "no_space", "byte"]).optional().describe("\uAE00\uC790\uC218 \uAE30\uC900: with_space=\uACF5\uBC31\uD3EC\uD568(\uAE30\uBCF8)\xB7no_space=\uACF5\uBC31\uC81C\uC678\xB7byte=UTF-8 \uBC14\uC774\uD2B8"),
|
|
4835
|
+
note: optLine.describe('\uBD80\uAC00 \uBA54\uBAA8(\uC608: "\uD544\uC218", "\uACBD\uD5D8 \uC911\uC2EC")')
|
|
4836
|
+
});
|
|
4837
|
+
var SCHEDULE_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
4838
|
+
var SCHEDULE_TIME_RE = /^([01]\d|2[0-3]):[0-5]\d$/;
|
|
4839
|
+
var JobScheduleItemSchema = external_exports.object({
|
|
4840
|
+
label: reqLine.describe("\uC77C\uC815 \uC774\uB984 (\uC608: 1\uCC28 \uBA74\uC811\xB7AI\uC5ED\uAC80\xB7\uC11C\uB958 \uBC1C\uD45C)"),
|
|
4841
|
+
date: external_exports.string().regex(SCHEDULE_DATE_RE, "YYYY-MM-DD \uD615\uC2DD\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4").describe("\uC77C\uC815 \uB0A0\uC9DC YYYY-MM-DD"),
|
|
4842
|
+
time: external_exports.string().regex(SCHEDULE_TIME_RE, "HH:MM(24\uC2DC\uAC04) \uD615\uC2DD\uC774\uC5B4\uC57C \uD569\uB2C8\uB2E4").optional().describe("\uC2DC\uAC01 HH:MM(24\uC2DC\uAC04, \uC120\uD0DD)"),
|
|
4843
|
+
note: optLine.describe("\uBD80\uAC00 \uBA54\uBAA8(\uC608: \uC7A5\uC18C\xB7\uC900\uBE44\uBB3C, \uC120\uD0DD)")
|
|
4844
|
+
});
|
|
4639
4845
|
var JobInputSchema = external_exports.object({
|
|
4640
4846
|
company: reqLine,
|
|
4641
4847
|
position: reqLine.describe("\uC9C1\uBB34/\uD3EC\uC9C0\uC158\uBA85"),
|
|
@@ -4646,7 +4852,13 @@ var JobInputSchema = external_exports.object({
|
|
|
4646
4852
|
requirements: strList.optional().describe("\uC790\uACA9\uC694\uAC74/\uC6B0\uB300\uC0AC\uD56D \uD575\uC2EC"),
|
|
4647
4853
|
keywords: strList.optional().describe("\uD575\uC2EC \uD0A4\uC6CC\uB4DC"),
|
|
4648
4854
|
deadline: external_exports.string().max(MAX_LINE).optional().describe("\uB9C8\uAC10\uC77C YYYY-MM-DD"),
|
|
4649
|
-
source: external_exports.string().max(MAX_LINE).optional().describe("\uCD9C\uCC98 (\uC0AC\uB78C\uC778/\uC6D0\uD2F0\uB4DC/\uC9C1\uC811 \uC785\uB825 \uB4F1)")
|
|
4855
|
+
source: external_exports.string().max(MAX_LINE).optional().describe("\uCD9C\uCC98 (\uC0AC\uB78C\uC778/\uC6D0\uD2F0\uB4DC/\uC9C1\uC811 \uC785\uB825 \uB4F1)"),
|
|
4856
|
+
company_overview: optBody.describe("\uD68C\uC0AC \uC0AC\uC5C5\uAC1C\uC694\xB7\uBBF8\uC158\xB7\uC8FC\uC694 \uC81C\uD488\xB7\uCD5C\uADFC \uD65C\uB3D9 (AI\uAC00 \uB9AC\uC11C\uCE58\uD574 \uCC44\uC6C0)"),
|
|
4857
|
+
talent_profile: optBody.describe("\uD68C\uC0AC\uAC00 \uAC15\uC870\uD558\uB294 \uC778\uC7AC\uC0C1 (\uD55C\uAD6D \uC790\uC18C\uC11C\xB7\uBA74\uC811\uC5D0\uC11C \uC815\uB82C \uAE30\uC900)"),
|
|
4858
|
+
core_values: strList.optional().describe("\uD68C\uC0AC \uD575\uC2EC\uAC00\uCE58 (\uD0A4\uC6CC\uB4DC \uBC30\uC5F4)"),
|
|
4859
|
+
reputation: optBody.describe("\uD68C\uC0AC \uD3C9\uD310 \uC694\uC57D \u2014 \uD3C9\uC810\xB7\uC6CC\uB77C\uBC38\xB7\uBB38\uD654 \uB9AC\uC2A4\uD06C \uB4F1 (AI\uAC00 company-research \uD50C\uB808\uC774\uBD81\uC73C\uB85C \uB9AC\uC11C\uCE58\uD574 \uCC44\uC6C0; \uCD9C\uCC98\xB7\uCD5C\uADFC\uC131 \uD45C\uAE30)"),
|
|
4860
|
+
questions: external_exports.array(JobQuestionSchema).max(MAX_ITEMS).optional().describe("\uD68C\uC0AC \uC9C0\uC815 \uC790\uC18C\uC11C \uBB38\uD56D\xB7\uAE00\uC790\uC218 \u2014 \uC0AC\uC6A9\uC790\uAC00 \uBB38\uD56D\uC744 \uC8FC\uBA74 \uAD6C\uC870\uD654 \uC800\uC7A5"),
|
|
4861
|
+
schedule: external_exports.array(JobScheduleItemSchema).max(MAX_ITEMS).optional().describe("\uC804\uD615 \uC77C\uC815 \u2014 \uBA74\uC811\uCD08\uB300 \uBA54\uC77C\xB7\uBC1C\uD45C \uACF5\uC9C0\uB97C \uBC1B\uC73C\uBA74 \uAD6C\uC870\uD654 \uC800\uC7A5(label\xB7date \uD544\uC218, time \uC120\uD0DD). \uC11C\uB958 \uB9C8\uAC10\uC740 deadline \uD544\uB4DC\uB97C \uC4F0\uC138\uC694.")
|
|
4650
4862
|
});
|
|
4651
4863
|
var JobRecordSchema = external_exports.object({
|
|
4652
4864
|
...baseRecord,
|
|
@@ -4659,7 +4871,49 @@ var JobRecordSchema = external_exports.object({
|
|
|
4659
4871
|
requirements: external_exports.array(external_exports.string()),
|
|
4660
4872
|
keywords: external_exports.array(external_exports.string()),
|
|
4661
4873
|
deadline: external_exports.string().nullable(),
|
|
4662
|
-
source: external_exports.string().nullable()
|
|
4874
|
+
source: external_exports.string().nullable(),
|
|
4875
|
+
company_overview: external_exports.string().nullable(),
|
|
4876
|
+
talent_profile: external_exports.string().nullable(),
|
|
4877
|
+
core_values: external_exports.array(external_exports.string()),
|
|
4878
|
+
reputation: external_exports.string().nullable(),
|
|
4879
|
+
questions: external_exports.array(JobQuestionSchema),
|
|
4880
|
+
schedule: external_exports.array(JobScheduleItemSchema)
|
|
4881
|
+
});
|
|
4882
|
+
var OFFER_STATUSES = ["open", "accepted", "declined"];
|
|
4883
|
+
var OfferInputSchema = external_exports.object({
|
|
4884
|
+
job_id: reqLine,
|
|
4885
|
+
offer_status: external_exports.enum(OFFER_STATUSES).optional().describe("\uC624\uD37C \uC0C1\uD0DC \u2014 open(\uC9C4\uD589 \uC911)/accepted(\uC218\uB77D)/declined(\uAC70\uC808). \uC0DD\uB7B5 \uC2DC \uAE30\uC874 \uAC12 \uC720\uC9C0(\uC2E0\uADDC \uC800\uC7A5\uC740 open)"),
|
|
4886
|
+
base_salary: external_exports.number().nonnegative().optional().describe("\uAE30\uBCF8\uAE09/\uC5F0\uBD09 (\uB9CC\uC6D0)"),
|
|
4887
|
+
bonus_amount: external_exports.number().nonnegative().optional().describe("\uC5F0 \uC131\uACFC\uAE09\xB7\uC0C1\uC5EC \uAE30\uB300\uC561 (\uB9CC\uC6D0)"),
|
|
4888
|
+
welfare_amount: external_exports.number().nonnegative().optional().describe("\uBCF5\uC9C0\uD3EC\uC778\uD2B8 \uB4F1 \uC5F0\uD658\uC0B0 (\uB9CC\uC6D0)"),
|
|
4889
|
+
signing_amount: external_exports.number().nonnegative().optional().describe("\uC0AC\uC774\uB2DD\uBCF4\uB108\uC2A4 \uC77C\uC2DC\uAE08 (\uB9CC\uC6D0)"),
|
|
4890
|
+
equity_note: optNote.describe("\uC8FC\uC2DD/\uC2A4\uD1A1\uC635\uC158 (\uC815\uC131 \uC11C\uC220 \u2014 \uAC00\uCE58\uD3C9\uAC00\uAC00 \uBAA8\uD638\uD558\uBBC0\uB85C \uD14D\uC2A4\uD2B8)"),
|
|
4891
|
+
comp_note: optBody.describe("\uAE30\uD0C0 \uBCF4\uC0C1 \uC790\uC720 \uC11C\uC220"),
|
|
4892
|
+
work_arrangement: optLine.describe("\uADFC\uBB34\uD615\uD0DC (\uC7AC\uD0DD/\uD558\uC774\uBE0C\uB9AC\uB4DC/\uCD9C\uADFC)"),
|
|
4893
|
+
contract_type: optLine.describe("\uACC4\uC57D\uD615\uD0DC (\uC815\uADDC/\uACC4\uC57D \uB4F1)"),
|
|
4894
|
+
accept_deadline: optLine.describe("\uC218\uB77D \uB9C8\uAC10\uC77C YYYY-MM-DD"),
|
|
4895
|
+
ai_score: external_exports.number().min(0).max(100).optional().describe("AI\uAC00 \uB9E4\uAE34 \uC885\uD569 \uC810\uC218 0~100 (\uC800\uC7A5 \uC2DC AI\uAC00 \uCC44\uC6C0)"),
|
|
4896
|
+
verdict: optBody.describe("\uCD5C\uC885\uD3C9 \u2014 \uC5B4\uB5A4 \uC0C1\uD669\uC774\uBA74 \uC5B4\uB514\uAC00 \uC88B\uC740\uC9C0 \uB4F1 (AI\uAC00 \uC800\uC7A5 \uC2DC \uC791\uC131)"),
|
|
4897
|
+
notes: optNote
|
|
4898
|
+
});
|
|
4899
|
+
var OfferRecordSchema = external_exports.object({
|
|
4900
|
+
...baseRecord,
|
|
4901
|
+
job_id: external_exports.string(),
|
|
4902
|
+
offer_status: external_exports.enum(OFFER_STATUSES),
|
|
4903
|
+
base_salary: external_exports.number().nullable(),
|
|
4904
|
+
bonus_amount: external_exports.number().nullable(),
|
|
4905
|
+
welfare_amount: external_exports.number().nullable(),
|
|
4906
|
+
signing_amount: external_exports.number().nullable(),
|
|
4907
|
+
equity_note: external_exports.string().nullable(),
|
|
4908
|
+
comp_note: external_exports.string().nullable(),
|
|
4909
|
+
work_arrangement: external_exports.string().nullable(),
|
|
4910
|
+
contract_type: external_exports.string().nullable(),
|
|
4911
|
+
accept_deadline: external_exports.string().nullable(),
|
|
4912
|
+
ai_score: external_exports.number().nullable(),
|
|
4913
|
+
verdict: external_exports.string().nullable(),
|
|
4914
|
+
notes: external_exports.string().nullable(),
|
|
4915
|
+
/** Server-computed annual cash estimate = base + bonus + welfare (signing is one-time, excluded). Null if no numeric pieces. */
|
|
4916
|
+
total_comp_annual_est: external_exports.number().nullable()
|
|
4663
4917
|
});
|
|
4664
4918
|
var FitAnalysisInputSchema = external_exports.object({
|
|
4665
4919
|
job_id: reqLine.describe("\uBD84\uC11D \uB300\uC0C1 \uACF5\uACE0 ID"),
|
|
@@ -4682,6 +4936,7 @@ var FitAnalysisRecordSchema = external_exports.object({
|
|
|
4682
4936
|
missing_keywords: external_exports.array(external_exports.string()),
|
|
4683
4937
|
recommendations: external_exports.array(external_exports.string())
|
|
4684
4938
|
});
|
|
4939
|
+
var REJECTED_STAGES = ["document", "assessment", "interview", "final", "other"];
|
|
4685
4940
|
var ApplicationInputSchema = external_exports.object({
|
|
4686
4941
|
job_id: reqLine,
|
|
4687
4942
|
status: external_exports.enum(APPLICATION_STATUSES).optional(),
|
|
@@ -4702,7 +4957,10 @@ var ApplicationStatusUpdateSchema = external_exports.object({
|
|
|
4702
4957
|
application_id: optLine,
|
|
4703
4958
|
status: external_exports.enum(APPLICATION_STATUSES),
|
|
4704
4959
|
note: optNote.describe("\uC0C1\uD0DC \uBCC0\uACBD \uC0AC\uC720/\uBA54\uBAA8"),
|
|
4705
|
-
submission: ApplicationSubmissionSchema.optional().describe("\uC9C0\uC6D0 \uC644\uB8CC \uAE30\uB85D\uC5D0 \uB0A8\uAE38 \uC81C\uCD9C \uC790\uB8CC \uC2A4\uB0C5\uC0F7")
|
|
4960
|
+
submission: ApplicationSubmissionSchema.optional().describe("\uC9C0\uC6D0 \uC644\uB8CC \uAE30\uB85D\uC5D0 \uB0A8\uAE38 \uC81C\uCD9C \uC790\uB8CC \uC2A4\uB0C5\uC0F7"),
|
|
4961
|
+
rejected_stage: external_exports.enum(REJECTED_STAGES).optional().describe(
|
|
4962
|
+
"\uD0C8\uB77D \uD68C\uACE0 \u2014 'rejected'\uB85C \uBC14\uAFC0 \uB54C \uC5B4\uB290 \uB2E8\uACC4\uC5D0\uC11C \uB5A8\uC5B4\uC84C\uB294\uC9C0: \uC11C\uB958=document, \uC778\uC801\uC131\xB7AI\uC5ED\uAC80=assessment, \uBA74\uC811=interview, \uCD5C\uC885\xB7\uCC98\uC6B0=final, \uAE30\uD0C0=other. rejected\uAC00 \uC544\uB2CC \uC0C1\uD0DC\uC5D0\uB294 \uC800\uC7A5\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."
|
|
4963
|
+
)
|
|
4706
4964
|
});
|
|
4707
4965
|
var ApplicationRecordSchema = external_exports.object({
|
|
4708
4966
|
...baseRecord,
|
|
@@ -4711,7 +4969,8 @@ var ApplicationRecordSchema = external_exports.object({
|
|
|
4711
4969
|
resume_id: external_exports.string().nullable(),
|
|
4712
4970
|
cover_letter_id: external_exports.string().nullable(),
|
|
4713
4971
|
applied_at: external_exports.string().nullable(),
|
|
4714
|
-
notes: external_exports.string().nullable()
|
|
4972
|
+
notes: external_exports.string().nullable(),
|
|
4973
|
+
rejected_stage: external_exports.enum(REJECTED_STAGES).nullable()
|
|
4715
4974
|
});
|
|
4716
4975
|
var StarGuideSchema = external_exports.object({
|
|
4717
4976
|
question: external_exports.string().max(MAX_NOTE),
|
|
@@ -4728,12 +4987,21 @@ var InterviewQuestionSchema = external_exports.object({
|
|
|
4728
4987
|
followups: strList.optional().describe("\uC608\uC0C1 \uAF2C\uB9AC \uC9C8\uBB38"),
|
|
4729
4988
|
answer_outline: optBody.describe("\uB2F5\uBCC0 \uAC00\uC774\uB4DC/\uD575\uC2EC \uD3EC\uC778\uD2B8")
|
|
4730
4989
|
});
|
|
4990
|
+
var InterviewDebriefSchema = external_exports.object({
|
|
4991
|
+
asked_questions: strList.optional().describe("\uC2E4\uC81C\uB85C \uBC1B\uC740 \uC9C8\uBB38\uB4E4"),
|
|
4992
|
+
went_well: optBody.describe("\uC798\uB41C \uC810/\uAC15\uD588\uB358 \uB2F5\uBCC0"),
|
|
4993
|
+
to_improve: optBody.describe("\uC544\uC26C\uC6B4 \uC810/\uB2E4\uC74C\uC5D0 \uAC1C\uC120\uD560 \uC810"),
|
|
4994
|
+
next_round_focus: optBody.describe("\uB2E4\uC74C \uB77C\uC6B4\uB4DC/\uBA74\uC811\uC5D0 \uB300\uBE44\uD574 \uC900\uBE44\uD560 \uD3EC\uC778\uD2B8"),
|
|
4995
|
+
sentiment: external_exports.enum(["positive", "neutral", "negative"]).optional().describe("\uCCB4\uAC10 \uBD84\uC704\uAE30"),
|
|
4996
|
+
interviewed_at: optLine.describe("\uBA74\uC811 \uBCF8 \uB0A0\uC9DC(YYYY-MM-DD)")
|
|
4997
|
+
});
|
|
4731
4998
|
var InterviewPrepInputSchema = external_exports.object({
|
|
4732
4999
|
job_id: reqLine,
|
|
4733
5000
|
questions: external_exports.array(InterviewQuestionSchema).max(MAX_ITEMS).optional(),
|
|
4734
5001
|
star_guides: external_exports.array(StarGuideSchema).max(MAX_ITEMS).optional(),
|
|
4735
5002
|
self_introduction: optBody.describe("1\uBD84 \uC790\uAE30\uC18C\uAC1C \uCD08\uC548"),
|
|
4736
|
-
notes: optNote.describe("\uBA74\uC811 \uD6C4\uAE30/\uBA54\uBAA8")
|
|
5003
|
+
notes: optNote.describe("\uBA74\uC811 \uD6C4\uAE30/\uBA54\uBAA8"),
|
|
5004
|
+
debrief: InterviewDebriefSchema.optional().describe("\uBA74\uC811 \uD6C4 \uB514\uBE0C\uB9AC\uD504(\uBC1B\uC740 \uC9C8\uBB38\xB7\uC798\uB41C \uC810\xB7\uAC1C\uC120\uC810\xB7\uB2E4\uC74C \uB77C\uC6B4\uB4DC \uD3EC\uCEE4\uC2A4)")
|
|
4737
5005
|
});
|
|
4738
5006
|
var InterviewPrepRecordSchema = external_exports.object({
|
|
4739
5007
|
...baseRecord,
|
|
@@ -4741,7 +5009,8 @@ var InterviewPrepRecordSchema = external_exports.object({
|
|
|
4741
5009
|
questions: external_exports.array(InterviewQuestionSchema),
|
|
4742
5010
|
star_guides: external_exports.array(StarGuideSchema),
|
|
4743
5011
|
self_introduction: external_exports.string().nullable(),
|
|
4744
|
-
notes: external_exports.string().nullable()
|
|
5012
|
+
notes: external_exports.string().nullable(),
|
|
5013
|
+
debrief: InterviewDebriefSchema.nullable()
|
|
4745
5014
|
});
|
|
4746
5015
|
var ActivityRecordSchema = external_exports.object({
|
|
4747
5016
|
id,
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
// Applications page.
|
|
2
2
|
export default {
|
|
3
|
+
// offers comparison
|
|
4
|
+
'applications.offers.title': 'Offer comparison',
|
|
5
|
+
'applications.offers.est': 'Est. annual cash',
|
|
6
|
+
'applications.offers.unit': '만원',
|
|
7
|
+
'applications.offers.noScore': 'No score',
|
|
8
|
+
'applications.offers.acceptBy': 'Accept by {{date}}',
|
|
9
|
+
'applications.offers.expired': 'Deadline passed',
|
|
10
|
+
'applications.offers.past': 'Past offers · {{count}} (accepted/declined)',
|
|
11
|
+
'applications.offers.status.accepted': 'Accepted',
|
|
12
|
+
'applications.offers.status.declined': 'Declined',
|
|
13
|
+
|
|
3
14
|
// deadline D-day chip
|
|
4
15
|
'applications.dday.future': 'Due in {{n}}d',
|
|
5
16
|
'applications.dday.today': 'Due today',
|
|
@@ -16,6 +27,14 @@ export default {
|
|
|
16
27
|
// app row
|
|
17
28
|
'applications.row.score': '{{score}} pts',
|
|
18
29
|
|
|
30
|
+
// Rejection retrospective — which stage the rejection happened at (rejected rows only)
|
|
31
|
+
'applications.rejectedStage.label': 'Rejected at:',
|
|
32
|
+
'applications.rejectedStage.document': 'Screening',
|
|
33
|
+
'applications.rejectedStage.assessment': 'Assessment/AI',
|
|
34
|
+
'applications.rejectedStage.interview': 'Interview',
|
|
35
|
+
'applications.rejectedStage.final': 'Final/offer',
|
|
36
|
+
'applications.rejectedStage.other': 'Other',
|
|
37
|
+
|
|
19
38
|
// status select + toasts
|
|
20
39
|
'applications.statusSelect.title': 'Change status',
|
|
21
40
|
'applications.toast.statusChanged': 'Application status updated.',
|
|
@@ -9,6 +9,16 @@ export default {
|
|
|
9
9
|
'common.delete': 'Delete',
|
|
10
10
|
'common.open': 'Open',
|
|
11
11
|
'common.justNow': 'just now',
|
|
12
|
+
'common.export': 'Export',
|
|
13
|
+
'common.fmtWord': 'Word',
|
|
14
|
+
'common.fmtHtml': 'HTML',
|
|
15
|
+
'common.fmtMarkdown': 'Markdown',
|
|
16
|
+
|
|
17
|
+
// Hiring-schedule stage D-day badge (shared by Home action lane + job detail).
|
|
18
|
+
// Separate from the deadline D-day labels (applications.dday.*).
|
|
19
|
+
'schedule.dday.today': 'D-day',
|
|
20
|
+
'schedule.dday.future': 'D-{{n}}',
|
|
21
|
+
'schedule.dday.past': 'Past',
|
|
12
22
|
|
|
13
23
|
'toast.copied': 'Copied to clipboard.',
|
|
14
24
|
'toast.copyFailed': "Couldn't copy. Please select and copy it manually.",
|
|
@@ -28,10 +28,6 @@ export default {
|
|
|
28
28
|
'documents.cover.primary': 'Primary',
|
|
29
29
|
'documents.cover.open': 'Open',
|
|
30
30
|
'documents.cover.copy': 'Copy',
|
|
31
|
-
'documents.cover.exportMd': 'MD',
|
|
32
|
-
'documents.cover.exportHtml': 'HTML',
|
|
33
|
-
'documents.cover.exportMdTitle': 'Export as Markdown',
|
|
34
|
-
'documents.cover.exportHtmlTitle': 'Export as HTML',
|
|
35
31
|
'documents.cover.setPrimary': 'Set as primary',
|
|
36
32
|
'documents.cover.delete': 'Delete',
|
|
37
33
|
'documents.cover.noContent': 'No content yet.',
|
|
@@ -60,8 +56,6 @@ export default {
|
|
|
60
56
|
'documents.coverCreate.toast': 'Cover letter added.',
|
|
61
57
|
|
|
62
58
|
// cover detail body
|
|
63
|
-
'documents.coverDetail.exportMd': 'Export as Markdown',
|
|
64
|
-
'documents.coverDetail.exportHtml': 'Export as HTML',
|
|
65
59
|
'documents.coverDetail.currentVersion': 'Current version',
|
|
66
60
|
'documents.coverDetail.copy': 'Copy',
|
|
67
61
|
'documents.coverDetail.noContent': 'No content.',
|
|
@@ -101,10 +95,6 @@ export default {
|
|
|
101
95
|
'documents.docDetail.updated': 'Updated {{when}}',
|
|
102
96
|
'documents.docDetail.noContent': 'No content.',
|
|
103
97
|
'documents.docDetail.copy': 'Copy',
|
|
104
|
-
'documents.docDetail.export': 'MD',
|
|
105
|
-
'documents.docDetail.exportTitle': 'Export as Markdown',
|
|
106
|
-
'documents.docDetail.exportHtml': 'HTML',
|
|
107
|
-
'documents.docDetail.exportHtmlTitle': 'Export as HTML',
|
|
108
98
|
'documents.docDetail.delete': 'Delete',
|
|
109
99
|
'documents.docDetail.deleteTitle': 'Delete document',
|
|
110
100
|
'documents.docDetail.deleteConfirm': 'Delete "{{title}}"?',
|
|
@@ -37,6 +37,11 @@ export default {
|
|
|
37
37
|
'home.stat.activeApplications': 'Active applications',
|
|
38
38
|
'home.stat.coverLetters': 'Cover letters',
|
|
39
39
|
'home.stat.interviewPending': 'Interview prep',
|
|
40
|
+
// KPI tile context sub-lines (derived from real counts; omitted when zero)
|
|
41
|
+
'home.stat.jobsSub': '{{count}} to apply',
|
|
42
|
+
'home.stat.subInterview': 'Interview {{count}}',
|
|
43
|
+
'home.stat.subDocPassed': 'Screening {{count}}',
|
|
44
|
+
'home.stat.subApplied': 'Applied {{count}}',
|
|
40
45
|
|
|
41
46
|
// pipeline
|
|
42
47
|
'home.pipeline.title': 'Application pipeline',
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export default {
|
|
3
3
|
// ---- list mode ----
|
|
4
4
|
'jobs.list.empty.title': 'No saved postings yet',
|
|
5
|
-
'jobs.list.empty.body': 'Add a posting you are interested in to track its fit and your progress.',
|
|
5
|
+
'jobs.list.empty.body': 'Add a posting you are interested in to track its fit and your progress. Or just tell your connected AI “find backend jobs” and it will fetch postings and save them here.',
|
|
6
6
|
'jobs.list.addJob': 'Add posting',
|
|
7
7
|
'jobs.list.searchPlaceholder': 'Search company or role',
|
|
8
8
|
'jobs.list.searchAria': 'Search postings',
|
|
@@ -73,6 +73,11 @@ export default {
|
|
|
73
73
|
'jobs.detail.openPosting': 'Original posting',
|
|
74
74
|
|
|
75
75
|
// ---- posting card ----
|
|
76
|
+
'jobs.company.title': 'Company research',
|
|
77
|
+
'jobs.company.overview': 'Overview',
|
|
78
|
+
'jobs.company.talent': 'Ideal candidate',
|
|
79
|
+
'jobs.company.values': 'Core values',
|
|
80
|
+
'jobs.company.reputation': 'Reputation',
|
|
76
81
|
'jobs.posting.title': 'Posting details',
|
|
77
82
|
'jobs.posting.location': 'Location',
|
|
78
83
|
'jobs.posting.employment': 'Employment type',
|
|
@@ -85,6 +90,18 @@ export default {
|
|
|
85
90
|
'jobs.posting.requirements': 'Requirements · Preferred',
|
|
86
91
|
'jobs.posting.rawText': 'Original posting',
|
|
87
92
|
|
|
93
|
+
// ---- cover letter questions (문항형 자소서) ----
|
|
94
|
+
'jobs.questions.title': 'Cover letter questions',
|
|
95
|
+
'jobs.questions.min': 'min {{n}}{{unit}}',
|
|
96
|
+
'jobs.questions.max': 'max {{n}}{{unit}}',
|
|
97
|
+
'jobs.questions.unitChar': ' chars',
|
|
98
|
+
'jobs.questions.unitByte': ' bytes',
|
|
99
|
+
'jobs.questions.modeWithSpace': ' (incl. spaces)',
|
|
100
|
+
'jobs.questions.modeNoSpace': ' (excl. spaces)',
|
|
101
|
+
|
|
102
|
+
// ---- hiring schedule (전형 일정) ---- (D-day badge uses shared schedule.dday.*)
|
|
103
|
+
'jobs.schedule.title': 'Hiring schedule',
|
|
104
|
+
|
|
88
105
|
// ---- fit card ----
|
|
89
106
|
'jobs.fit.title': 'Fit analysis',
|
|
90
107
|
'jobs.fit.emptyBody': 'Not analyzed yet. The comparison between this posting and your profile will appear here.',
|
|
@@ -11,11 +11,6 @@ export default {
|
|
|
11
11
|
'profile.completeness.title': 'Profile completeness',
|
|
12
12
|
'profile.completeness.percent': '{{pct}}%',
|
|
13
13
|
|
|
14
|
-
// export profile as a resume
|
|
15
|
-
'profile.export.md': 'MD',
|
|
16
|
-
'profile.export.html': 'HTML',
|
|
17
|
-
'profile.export.mdTitle': 'Export resume as Markdown',
|
|
18
|
-
'profile.export.htmlTitle': 'Export resume as HTML',
|
|
19
14
|
|
|
20
15
|
// basic info card
|
|
21
16
|
'profile.basic.title': 'Basic info',
|
|
@@ -105,18 +105,21 @@ export default {
|
|
|
105
105
|
'settings.import.confirm': 'Import',
|
|
106
106
|
'settings.import.doneToast': 'Data imported.',
|
|
107
107
|
|
|
108
|
+
// language
|
|
109
|
+
'settings.lang.sub': 'Dashboard display language',
|
|
110
|
+
|
|
108
111
|
// danger zone
|
|
109
112
|
'settings.reset.gateWord': 'RESET',
|
|
110
113
|
'settings.reset.title': 'Reset all data',
|
|
111
114
|
'settings.reset.calloutTitle': "This can't be undone",
|
|
112
|
-
'settings.reset.calloutBody': 'All data, including your profile, postings, applications, documents, and interview prep, will be permanently deleted. For safety, a backup is created automatically right before the reset.',
|
|
115
|
+
'settings.reset.calloutBody': 'All data, including your profile, postings, applications, documents, and interview prep, will be permanently deleted. For safety, a backup is created automatically right before the reset — that backup file remains in the backups folder inside your data directory, so delete it too if you want no trace left.',
|
|
113
116
|
'settings.reset.instruction': 'To continue, type {{word}} in the field below.',
|
|
114
117
|
'settings.reset.confirm': 'Reset all data',
|
|
115
118
|
'settings.reset.doneToast': 'All data has been reset.',
|
|
116
119
|
'settings.danger.title': 'Danger zone',
|
|
117
120
|
'settings.danger.sub': "This action can't be undone",
|
|
118
121
|
'settings.danger.resetTitle': 'Reset all data',
|
|
119
|
-
'settings.danger.resetBody': 'Deletes all CareerMate data stored on this computer.
|
|
122
|
+
'settings.danger.resetBody': 'Deletes all CareerMate data stored on this computer. An automatic backup is created before the reset and remains in the backups folder.',
|
|
120
123
|
|
|
121
124
|
// help / report a problem
|
|
122
125
|
'settings.support.title': 'Help & report a problem',
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
// 지원 현황 페이지.
|
|
2
2
|
export default {
|
|
3
|
+
// offers comparison
|
|
4
|
+
'applications.offers.title': '오퍼 비교',
|
|
5
|
+
'applications.offers.est': '추정 연 현금성',
|
|
6
|
+
'applications.offers.unit': '만원',
|
|
7
|
+
'applications.offers.noScore': '점수 미정',
|
|
8
|
+
'applications.offers.acceptBy': '수락 마감 {{date}}',
|
|
9
|
+
'applications.offers.expired': '수락 마감 지남',
|
|
10
|
+
'applications.offers.past': '지난 오퍼 {{count}}건 (수락·거절)',
|
|
11
|
+
'applications.offers.status.accepted': '수락',
|
|
12
|
+
'applications.offers.status.declined': '거절',
|
|
13
|
+
|
|
3
14
|
// deadline D-day chip
|
|
4
15
|
'applications.dday.future': '마감 D-{{n}}',
|
|
5
16
|
'applications.dday.today': '마감 D-day',
|
|
@@ -16,6 +27,14 @@ export default {
|
|
|
16
27
|
// app row
|
|
17
28
|
'applications.row.score': '{{score}}점',
|
|
18
29
|
|
|
30
|
+
// 탈락 회고 — 어느 단계에서 떨어졌는지 병기(불합격 행에만 표시)
|
|
31
|
+
'applications.rejectedStage.label': '탈락 단계:',
|
|
32
|
+
'applications.rejectedStage.document': '서류',
|
|
33
|
+
'applications.rejectedStage.assessment': '인적성·AI역검',
|
|
34
|
+
'applications.rejectedStage.interview': '면접',
|
|
35
|
+
'applications.rejectedStage.final': '최종·처우',
|
|
36
|
+
'applications.rejectedStage.other': '기타',
|
|
37
|
+
|
|
19
38
|
// status select + toasts
|
|
20
39
|
'applications.statusSelect.title': '상태 변경',
|
|
21
40
|
'applications.toast.statusChanged': '지원 상태를 변경했어요.',
|