careermate 0.0.8 → 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 +78 -81
- package/bin/careermate.mjs +11 -2
- package/dist/career-os/eop/cover-letter.md +10 -4
- package/dist/career-os/eop/interview-prep.md +1 -0
- package/dist/career-os/knowledge/cover-letter.md +4 -0
- package/dist/career-os/knowledge/verifiers/human-voice.md +7 -2
- package/dist/doctor.mjs +888 -340
- package/dist/mcp.mjs +904 -350
- package/dist/migrate.mjs +208 -16
- package/dist/public/i18n/en/applications.js +19 -0
- package/dist/public/i18n/en/common.js +6 -0
- package/dist/public/i18n/en/jobs.js +17 -0
- 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 +5 -0
- package/dist/public/i18n/ko/jobs.js +17 -0
- package/dist/public/i18n/ko/settings.js +5 -2
- package/dist/public/lib.js +29 -0
- package/dist/public/pages/applications.js +86 -10
- package/dist/public/pages/documents.js +16 -7
- package/dist/public/pages/home.js +12 -0
- package/dist/public/pages/interview.js +11 -4
- package/dist/public/pages/jobs.js +71 -1
- package/dist/public/pages/settings.js +2 -2
- package/dist/public/styles.css +13 -0
- package/dist/web.mjs +544 -199
- package/docs/FAQ.md +13 -3
- package/docs/MCP_TOOLS.md +22 -9
- package/docs/career-os/eop/cover-letter.md +10 -4
- package/docs/career-os/eop/interview-prep.md +1 -0
- package/docs/career-os/knowledge/cover-letter.md +4 -0
- package/docs/career-os/knowledge/verifiers/human-voice.md +7 -2
- package/package.json +3 -1
- package/packages/core/src/index.ts +1 -0
- package/packages/core/src/jobsearch.ts +6 -2
- package/packages/core/src/offers.ts +41 -0
- package/packages/core/src/services.ts +5 -1
- package/packages/core/src/summary.ts +245 -19
- package/packages/db/src/connection.ts +70 -2
- package/packages/db/src/index.ts +1 -0
- package/packages/db/src/repositories.ts +140 -8
- package/packages/db/src/schema.ts +140 -8
- package/packages/mcp-tools/src/result.ts +9 -0
- package/packages/mcp-tools/src/tools.ts +143 -20
- package/packages/parsers/src/documents.ts +7 -1
- package/packages/prompts/src/humanize.ts +4 -0
- package/packages/shared/src/schemas.ts +134 -0
- package/scripts/init.ts +2 -0
package/dist/mcp.mjs
CHANGED
|
@@ -3244,8 +3244,8 @@ var require_utils = __commonJS({
|
|
|
3244
3244
|
}
|
|
3245
3245
|
return ind;
|
|
3246
3246
|
}
|
|
3247
|
-
function removeDotSegments(
|
|
3248
|
-
let input =
|
|
3247
|
+
function removeDotSegments(path9) {
|
|
3248
|
+
let input = path9;
|
|
3249
3249
|
const output = [];
|
|
3250
3250
|
let nextSlash = -1;
|
|
3251
3251
|
let len = 0;
|
|
@@ -3497,8 +3497,8 @@ var require_schemes = __commonJS({
|
|
|
3497
3497
|
wsComponent.secure = void 0;
|
|
3498
3498
|
}
|
|
3499
3499
|
if (wsComponent.resourceName) {
|
|
3500
|
-
const [
|
|
3501
|
-
wsComponent.path =
|
|
3500
|
+
const [path9, query] = wsComponent.resourceName.split("?");
|
|
3501
|
+
wsComponent.path = path9 && path9 !== "/" ? path9 : void 0;
|
|
3502
3502
|
wsComponent.query = query;
|
|
3503
3503
|
wsComponent.resourceName = void 0;
|
|
3504
3504
|
}
|
|
@@ -6891,12 +6891,12 @@ var require_dist = __commonJS({
|
|
|
6891
6891
|
throw new Error(`Unknown format "${name}"`);
|
|
6892
6892
|
return f;
|
|
6893
6893
|
};
|
|
6894
|
-
function addFormats(ajv, list,
|
|
6894
|
+
function addFormats(ajv, list, fs9, exportName2) {
|
|
6895
6895
|
var _a2;
|
|
6896
6896
|
var _b2;
|
|
6897
6897
|
(_a2 = (_b2 = ajv.opts.code).formats) !== null && _a2 !== void 0 ? _a2 : _b2.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName2}`;
|
|
6898
6898
|
for (const f of list)
|
|
6899
|
-
ajv.addFormat(f,
|
|
6899
|
+
ajv.addFormat(f, fs9[f]);
|
|
6900
6900
|
}
|
|
6901
6901
|
module2.exports = exports2 = formatsPlugin;
|
|
6902
6902
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -7832,8 +7832,8 @@ var init_tap = __esm({
|
|
|
7832
7832
|
});
|
|
7833
7833
|
|
|
7834
7834
|
// node_modules/underscore/modules/toPath.js
|
|
7835
|
-
function toPath(
|
|
7836
|
-
return isArray_default(
|
|
7835
|
+
function toPath(path9) {
|
|
7836
|
+
return isArray_default(path9) ? path9 : [path9];
|
|
7837
7837
|
}
|
|
7838
7838
|
var init_toPath = __esm({
|
|
7839
7839
|
"node_modules/underscore/modules/toPath.js"() {
|
|
@@ -7845,8 +7845,8 @@ var init_toPath = __esm({
|
|
|
7845
7845
|
});
|
|
7846
7846
|
|
|
7847
7847
|
// node_modules/underscore/modules/_toPath.js
|
|
7848
|
-
function toPath2(
|
|
7849
|
-
return _.toPath(
|
|
7848
|
+
function toPath2(path9) {
|
|
7849
|
+
return _.toPath(path9);
|
|
7850
7850
|
}
|
|
7851
7851
|
var init_toPath2 = __esm({
|
|
7852
7852
|
"node_modules/underscore/modules/_toPath.js"() {
|
|
@@ -7857,11 +7857,11 @@ var init_toPath2 = __esm({
|
|
|
7857
7857
|
});
|
|
7858
7858
|
|
|
7859
7859
|
// node_modules/underscore/modules/_deepGet.js
|
|
7860
|
-
function deepGet(obj2,
|
|
7861
|
-
var length =
|
|
7860
|
+
function deepGet(obj2, path9) {
|
|
7861
|
+
var length = path9.length;
|
|
7862
7862
|
for (var i2 = 0; i2 < length; i2++) {
|
|
7863
7863
|
if (obj2 == null) return void 0;
|
|
7864
|
-
obj2 = obj2[
|
|
7864
|
+
obj2 = obj2[path9[i2]];
|
|
7865
7865
|
}
|
|
7866
7866
|
return length ? obj2 : void 0;
|
|
7867
7867
|
}
|
|
@@ -7872,8 +7872,8 @@ var init_deepGet = __esm({
|
|
|
7872
7872
|
});
|
|
7873
7873
|
|
|
7874
7874
|
// node_modules/underscore/modules/get.js
|
|
7875
|
-
function get(object4,
|
|
7876
|
-
var value = deepGet(object4, toPath2(
|
|
7875
|
+
function get(object4, path9, defaultValue) {
|
|
7876
|
+
var value = deepGet(object4, toPath2(path9));
|
|
7877
7877
|
return isUndefined(value) ? defaultValue : value;
|
|
7878
7878
|
}
|
|
7879
7879
|
var init_get = __esm({
|
|
@@ -7886,11 +7886,11 @@ var init_get = __esm({
|
|
|
7886
7886
|
});
|
|
7887
7887
|
|
|
7888
7888
|
// node_modules/underscore/modules/has.js
|
|
7889
|
-
function has2(obj2,
|
|
7890
|
-
|
|
7891
|
-
var length =
|
|
7889
|
+
function has2(obj2, path9) {
|
|
7890
|
+
path9 = toPath2(path9);
|
|
7891
|
+
var length = path9.length;
|
|
7892
7892
|
for (var i2 = 0; i2 < length; i2++) {
|
|
7893
|
-
var key =
|
|
7893
|
+
var key = path9[i2];
|
|
7894
7894
|
if (!has(obj2, key)) return false;
|
|
7895
7895
|
obj2 = obj2[key];
|
|
7896
7896
|
}
|
|
@@ -7930,10 +7930,10 @@ var init_matcher = __esm({
|
|
|
7930
7930
|
});
|
|
7931
7931
|
|
|
7932
7932
|
// node_modules/underscore/modules/property.js
|
|
7933
|
-
function property(
|
|
7934
|
-
|
|
7933
|
+
function property(path9) {
|
|
7934
|
+
path9 = toPath2(path9);
|
|
7935
7935
|
return function(obj2) {
|
|
7936
|
-
return deepGet(obj2,
|
|
7936
|
+
return deepGet(obj2, path9);
|
|
7937
7937
|
};
|
|
7938
7938
|
}
|
|
7939
7939
|
var init_property = __esm({
|
|
@@ -8049,8 +8049,8 @@ var init_noop = __esm({
|
|
|
8049
8049
|
// node_modules/underscore/modules/propertyOf.js
|
|
8050
8050
|
function propertyOf(obj2) {
|
|
8051
8051
|
if (obj2 == null) return noop2;
|
|
8052
|
-
return function(
|
|
8053
|
-
return get(obj2,
|
|
8052
|
+
return function(path9) {
|
|
8053
|
+
return get(obj2, path9);
|
|
8054
8054
|
};
|
|
8055
8055
|
}
|
|
8056
8056
|
var init_propertyOf = __esm({
|
|
@@ -8198,7 +8198,7 @@ function template(text, settings, oldSettings) {
|
|
|
8198
8198
|
var index = 0;
|
|
8199
8199
|
var source = "__p+='";
|
|
8200
8200
|
text.replace(matcher2, function(match, escape2, interpolate, evaluate, offset) {
|
|
8201
|
-
source += text.slice(index, offset).replace(
|
|
8201
|
+
source += text.slice(index, offset).replace(escapeRegExp2, escapeChar);
|
|
8202
8202
|
index = offset + match.length;
|
|
8203
8203
|
if (escape2) {
|
|
8204
8204
|
source += "'+\n((__t=(" + escape2 + "))==null?'':_.escape(__t))+\n'";
|
|
@@ -8233,7 +8233,7 @@ function template(text, settings, oldSettings) {
|
|
|
8233
8233
|
template2.source = "function(" + argument + "){\n" + source + "}";
|
|
8234
8234
|
return template2;
|
|
8235
8235
|
}
|
|
8236
|
-
var noMatch, escapes,
|
|
8236
|
+
var noMatch, escapes, escapeRegExp2, bareIdentifier;
|
|
8237
8237
|
var init_template = __esm({
|
|
8238
8238
|
"node_modules/underscore/modules/template.js"() {
|
|
8239
8239
|
"use strict";
|
|
@@ -8249,20 +8249,20 @@ var init_template = __esm({
|
|
|
8249
8249
|
"\u2028": "u2028",
|
|
8250
8250
|
"\u2029": "u2029"
|
|
8251
8251
|
};
|
|
8252
|
-
|
|
8252
|
+
escapeRegExp2 = /\\|'|\r|\n|\u2028|\u2029/g;
|
|
8253
8253
|
bareIdentifier = /^\s*(\w|\$)+\s*$/;
|
|
8254
8254
|
}
|
|
8255
8255
|
});
|
|
8256
8256
|
|
|
8257
8257
|
// node_modules/underscore/modules/result.js
|
|
8258
|
-
function result(obj2,
|
|
8259
|
-
|
|
8260
|
-
var length =
|
|
8258
|
+
function result(obj2, path9, fallback) {
|
|
8259
|
+
path9 = toPath2(path9);
|
|
8260
|
+
var length = path9.length;
|
|
8261
8261
|
if (!length) {
|
|
8262
8262
|
return isFunction_default(fallback) ? fallback.call(obj2) : fallback;
|
|
8263
8263
|
}
|
|
8264
8264
|
for (var i2 = 0; i2 < length; i2++) {
|
|
8265
|
-
var prop = obj2 == null ? void 0 : obj2[
|
|
8265
|
+
var prop = obj2 == null ? void 0 : obj2[path9[i2]];
|
|
8266
8266
|
if (prop === void 0) {
|
|
8267
8267
|
prop = fallback;
|
|
8268
8268
|
i2 = length;
|
|
@@ -8986,14 +8986,14 @@ var init_invoke = __esm({
|
|
|
8986
8986
|
init_map();
|
|
8987
8987
|
init_deepGet();
|
|
8988
8988
|
init_toPath2();
|
|
8989
|
-
invoke_default = restArguments(function(obj2,
|
|
8989
|
+
invoke_default = restArguments(function(obj2, path9, args) {
|
|
8990
8990
|
var contextPath, func;
|
|
8991
|
-
if (isFunction_default(
|
|
8992
|
-
func =
|
|
8991
|
+
if (isFunction_default(path9)) {
|
|
8992
|
+
func = path9;
|
|
8993
8993
|
} else {
|
|
8994
|
-
|
|
8995
|
-
contextPath =
|
|
8996
|
-
|
|
8994
|
+
path9 = toPath2(path9);
|
|
8995
|
+
contextPath = path9.slice(0, -1);
|
|
8996
|
+
path9 = path9[path9.length - 1];
|
|
8997
8997
|
}
|
|
8998
8998
|
return map(obj2, function(context) {
|
|
8999
8999
|
var method = func;
|
|
@@ -9002,7 +9002,7 @@ var init_invoke = __esm({
|
|
|
9002
9002
|
context = deepGet(context, contextPath);
|
|
9003
9003
|
}
|
|
9004
9004
|
if (context == null) return void 0;
|
|
9005
|
-
method = context[
|
|
9005
|
+
method = context[path9];
|
|
9006
9006
|
}
|
|
9007
9007
|
return method == null ? method : method.apply(context, args);
|
|
9008
9008
|
});
|
|
@@ -18520,8 +18520,8 @@ var require_utils3 = __commonJS({
|
|
|
18520
18520
|
var result2 = transform2[inputType][outputType](input);
|
|
18521
18521
|
return result2;
|
|
18522
18522
|
};
|
|
18523
|
-
exports2.resolve = function(
|
|
18524
|
-
var parts =
|
|
18523
|
+
exports2.resolve = function(path9) {
|
|
18524
|
+
var parts = path9.split("/");
|
|
18525
18525
|
var result2 = [];
|
|
18526
18526
|
for (var index = 0; index < parts.length; index++) {
|
|
18527
18527
|
var part = parts[index];
|
|
@@ -24374,18 +24374,18 @@ var require_object = __commonJS({
|
|
|
24374
24374
|
var object4 = new ZipObject(name, zipObjectContent, o);
|
|
24375
24375
|
this.files[name] = object4;
|
|
24376
24376
|
};
|
|
24377
|
-
var parentFolder = function(
|
|
24378
|
-
if (
|
|
24379
|
-
|
|
24377
|
+
var parentFolder = function(path9) {
|
|
24378
|
+
if (path9.slice(-1) === "/") {
|
|
24379
|
+
path9 = path9.substring(0, path9.length - 1);
|
|
24380
24380
|
}
|
|
24381
|
-
var lastSlash =
|
|
24382
|
-
return lastSlash > 0 ?
|
|
24381
|
+
var lastSlash = path9.lastIndexOf("/");
|
|
24382
|
+
return lastSlash > 0 ? path9.substring(0, lastSlash) : "";
|
|
24383
24383
|
};
|
|
24384
|
-
var forceTrailingSlash = function(
|
|
24385
|
-
if (
|
|
24386
|
-
|
|
24384
|
+
var forceTrailingSlash = function(path9) {
|
|
24385
|
+
if (path9.slice(-1) !== "/") {
|
|
24386
|
+
path9 += "/";
|
|
24387
24387
|
}
|
|
24388
|
-
return
|
|
24388
|
+
return path9;
|
|
24389
24389
|
};
|
|
24390
24390
|
var folderAdd = function(name, createFolders) {
|
|
24391
24391
|
createFolders = typeof createFolders !== "undefined" ? createFolders : defaults.createFolders;
|
|
@@ -25424,27 +25424,27 @@ var require_zipfile = __commonJS({
|
|
|
25424
25424
|
};
|
|
25425
25425
|
});
|
|
25426
25426
|
}
|
|
25427
|
-
function splitPath(
|
|
25428
|
-
var lastIndex =
|
|
25427
|
+
function splitPath(path9) {
|
|
25428
|
+
var lastIndex = path9.lastIndexOf("/");
|
|
25429
25429
|
if (lastIndex === -1) {
|
|
25430
|
-
return { dirname: "", basename:
|
|
25430
|
+
return { dirname: "", basename: path9 };
|
|
25431
25431
|
} else {
|
|
25432
25432
|
return {
|
|
25433
|
-
dirname:
|
|
25434
|
-
basename:
|
|
25433
|
+
dirname: path9.substring(0, lastIndex),
|
|
25434
|
+
basename: path9.substring(lastIndex + 1)
|
|
25435
25435
|
};
|
|
25436
25436
|
}
|
|
25437
25437
|
}
|
|
25438
25438
|
function joinPath() {
|
|
25439
|
-
var nonEmptyPaths = Array.prototype.filter.call(arguments, function(
|
|
25440
|
-
return
|
|
25439
|
+
var nonEmptyPaths = Array.prototype.filter.call(arguments, function(path9) {
|
|
25440
|
+
return path9;
|
|
25441
25441
|
});
|
|
25442
25442
|
var relevantPaths = [];
|
|
25443
|
-
nonEmptyPaths.forEach(function(
|
|
25444
|
-
if (/^\//.test(
|
|
25445
|
-
relevantPaths = [
|
|
25443
|
+
nonEmptyPaths.forEach(function(path9) {
|
|
25444
|
+
if (/^\//.test(path9)) {
|
|
25445
|
+
relevantPaths = [path9];
|
|
25446
25446
|
} else {
|
|
25447
|
-
relevantPaths.push(
|
|
25447
|
+
relevantPaths.push(path9);
|
|
25448
25448
|
}
|
|
25449
25449
|
});
|
|
25450
25450
|
return relevantPaths.join("/");
|
|
@@ -32869,9 +32869,9 @@ var require_office_xml_reader = __commonJS({
|
|
|
32869
32869
|
return collapseAlternateContent(document2)[0];
|
|
32870
32870
|
});
|
|
32871
32871
|
}
|
|
32872
|
-
function readXmlFromZipFile(docxFile,
|
|
32873
|
-
if (docxFile.exists(
|
|
32874
|
-
return docxFile.read(
|
|
32872
|
+
function readXmlFromZipFile(docxFile, path9) {
|
|
32873
|
+
if (docxFile.exists(path9)) {
|
|
32874
|
+
return docxFile.read(path9, "utf-8").then(stripUtf8Bom).then(read);
|
|
32875
32875
|
} else {
|
|
32876
32876
|
return promises.resolve(null);
|
|
32877
32877
|
}
|
|
@@ -34638,10 +34638,10 @@ var require_body_reader = __commonJS({
|
|
|
34638
34638
|
}
|
|
34639
34639
|
}
|
|
34640
34640
|
function findEmbeddedImageFile(relationshipId) {
|
|
34641
|
-
var
|
|
34641
|
+
var path9 = uris.uriToZipEntryName("word", relationships.findTargetByRelationshipId(relationshipId));
|
|
34642
34642
|
return {
|
|
34643
|
-
path:
|
|
34644
|
-
read: docxFile.read.bind(docxFile,
|
|
34643
|
+
path: path9,
|
|
34644
|
+
read: docxFile.read.bind(docxFile, path9)
|
|
34645
34645
|
};
|
|
34646
34646
|
}
|
|
34647
34647
|
function readImage(imageFile, altText) {
|
|
@@ -34881,12 +34881,12 @@ var require_content_types_reader = __commonJS({
|
|
|
34881
34881
|
}
|
|
34882
34882
|
function contentTypes(overrides, extensionDefaults) {
|
|
34883
34883
|
return {
|
|
34884
|
-
findContentType: function(
|
|
34885
|
-
var overrideContentType = overrides[
|
|
34884
|
+
findContentType: function(path9) {
|
|
34885
|
+
var overrideContentType = overrides[path9];
|
|
34886
34886
|
if (overrideContentType) {
|
|
34887
34887
|
return overrideContentType;
|
|
34888
34888
|
} else {
|
|
34889
|
-
var pathParts =
|
|
34889
|
+
var pathParts = path9.split(".");
|
|
34890
34890
|
var extension = pathParts[pathParts.length - 1];
|
|
34891
34891
|
if (extensionDefaults.hasOwnProperty(extension)) {
|
|
34892
34892
|
return extensionDefaults[extension];
|
|
@@ -35133,12 +35133,12 @@ var require_comments_reader = __commonJS({
|
|
|
35133
35133
|
var require_path_is_absolute = __commonJS({
|
|
35134
35134
|
"node_modules/path-is-absolute/index.js"(exports2, module2) {
|
|
35135
35135
|
"use strict";
|
|
35136
|
-
function posix(
|
|
35137
|
-
return
|
|
35136
|
+
function posix(path9) {
|
|
35137
|
+
return path9.charAt(0) === "/";
|
|
35138
35138
|
}
|
|
35139
|
-
function win32(
|
|
35139
|
+
function win32(path9) {
|
|
35140
35140
|
var splitDeviceRe = /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/]+[^\\\/]+)?([\\\/])?([\s\S]*?)$/;
|
|
35141
|
-
var result2 = splitDeviceRe.exec(
|
|
35141
|
+
var result2 = splitDeviceRe.exec(path9);
|
|
35142
35142
|
var device = result2[1] || "";
|
|
35143
35143
|
var isUnc = Boolean(device && device.charAt(1) !== ":");
|
|
35144
35144
|
return Boolean(result2[2] || isUnc);
|
|
@@ -35153,7 +35153,7 @@ var require_path_is_absolute = __commonJS({
|
|
|
35153
35153
|
var require_files = __commonJS({
|
|
35154
35154
|
"node_modules/mammoth/lib/docx/files.js"(exports2) {
|
|
35155
35155
|
"use strict";
|
|
35156
|
-
var
|
|
35156
|
+
var fs9 = __require("fs");
|
|
35157
35157
|
var url = __require("url");
|
|
35158
35158
|
var os3 = __require("os");
|
|
35159
35159
|
var dirname = __require("path").dirname;
|
|
@@ -35173,19 +35173,19 @@ var require_files = __commonJS({
|
|
|
35173
35173
|
}
|
|
35174
35174
|
var base = options.relativeToFile ? dirname(options.relativeToFile) : null;
|
|
35175
35175
|
function read(uri, encoding) {
|
|
35176
|
-
return resolveUri(uri).then(function(
|
|
35177
|
-
return readFile(
|
|
35176
|
+
return resolveUri(uri).then(function(path9) {
|
|
35177
|
+
return readFile(path9, encoding).caught(function(error2) {
|
|
35178
35178
|
var message = "could not open external image: '" + uri + "' (document directory: '" + base + "')\n" + error2.message;
|
|
35179
35179
|
return promises.reject(new Error(message));
|
|
35180
35180
|
});
|
|
35181
35181
|
});
|
|
35182
35182
|
}
|
|
35183
35183
|
function resolveUri(uri) {
|
|
35184
|
-
var
|
|
35185
|
-
if (isAbsolutePath(
|
|
35186
|
-
return promises.resolve(
|
|
35184
|
+
var path9 = uriToPath(uri);
|
|
35185
|
+
if (isAbsolutePath(path9)) {
|
|
35186
|
+
return promises.resolve(path9);
|
|
35187
35187
|
} else if (base) {
|
|
35188
|
-
return promises.resolve(resolvePath(base,
|
|
35188
|
+
return promises.resolve(resolvePath(base, path9));
|
|
35189
35189
|
} else {
|
|
35190
35190
|
return promises.reject(new Error("could not find external image '" + uri + "', path of input document is unknown"));
|
|
35191
35191
|
}
|
|
@@ -35194,18 +35194,18 @@ var require_files = __commonJS({
|
|
|
35194
35194
|
read
|
|
35195
35195
|
};
|
|
35196
35196
|
}
|
|
35197
|
-
var readFile = promises.promisify(
|
|
35197
|
+
var readFile = promises.promisify(fs9.readFile.bind(fs9));
|
|
35198
35198
|
function uriToPath(uriString, platform) {
|
|
35199
35199
|
if (!platform) {
|
|
35200
35200
|
platform = os3.platform();
|
|
35201
35201
|
}
|
|
35202
35202
|
var uri = url.parse(uriString);
|
|
35203
35203
|
if (isLocalFileUri(uri) || isRelativeUri(uri)) {
|
|
35204
|
-
var
|
|
35205
|
-
if (platform === "win32" && /^\/[a-z]:/i.test(
|
|
35206
|
-
return
|
|
35204
|
+
var path9 = decodeURIComponent(uri.path);
|
|
35205
|
+
if (platform === "win32" && /^\/[a-z]:/i.test(path9)) {
|
|
35206
|
+
return path9.slice(1);
|
|
35207
35207
|
} else {
|
|
35208
|
-
return
|
|
35208
|
+
return path9;
|
|
35209
35209
|
}
|
|
35210
35210
|
} else {
|
|
35211
35211
|
throw new Error("Could not convert URI to path: " + uriString);
|
|
@@ -35406,18 +35406,18 @@ var require_docx_reader = __commonJS({
|
|
|
35406
35406
|
readElement: contentTypesReader.readContentTypesFromXml,
|
|
35407
35407
|
defaultValue: contentTypesReader.defaultContentTypes
|
|
35408
35408
|
});
|
|
35409
|
-
function readNumberingFromZipFile(zipFile,
|
|
35409
|
+
function readNumberingFromZipFile(zipFile, path9, styles) {
|
|
35410
35410
|
return xmlFileReader({
|
|
35411
|
-
filename:
|
|
35411
|
+
filename: path9,
|
|
35412
35412
|
readElement: function(element) {
|
|
35413
35413
|
return numberingXml.readNumberingXml(element, { styles });
|
|
35414
35414
|
},
|
|
35415
35415
|
defaultValue: numberingXml.defaultNumbering
|
|
35416
35416
|
})(zipFile);
|
|
35417
35417
|
}
|
|
35418
|
-
function readStylesFromZipFile(zipFile,
|
|
35418
|
+
function readStylesFromZipFile(zipFile, path9) {
|
|
35419
35419
|
return xmlFileReader({
|
|
35420
|
-
filename:
|
|
35420
|
+
filename: path9,
|
|
35421
35421
|
readElement: stylesReader.readStylesXml,
|
|
35422
35422
|
defaultValue: stylesReader.defaultStyles
|
|
35423
35423
|
})(zipFile);
|
|
@@ -35449,10 +35449,10 @@ var require_style_map = __commonJS({
|
|
|
35449
35449
|
});
|
|
35450
35450
|
}
|
|
35451
35451
|
function updateRelationships(docxFile) {
|
|
35452
|
-
var
|
|
35452
|
+
var path9 = "word/_rels/document.xml.rels";
|
|
35453
35453
|
var relationshipsUri = "http://schemas.openxmlformats.org/package/2006/relationships";
|
|
35454
35454
|
var relationshipElementName = "{" + relationshipsUri + "}Relationship";
|
|
35455
|
-
return docxFile.read(
|
|
35455
|
+
return docxFile.read(path9, "utf8").then(xml.readString).then(function(relationshipsContainer) {
|
|
35456
35456
|
var relationships = relationshipsContainer.children;
|
|
35457
35457
|
addOrUpdateElement(relationships, relationshipElementName, "Id", {
|
|
35458
35458
|
"Id": "rMammothStyleMap",
|
|
@@ -35460,21 +35460,21 @@ var require_style_map = __commonJS({
|
|
|
35460
35460
|
"Target": styleMapAbsolutePath
|
|
35461
35461
|
});
|
|
35462
35462
|
var namespaces = { "": relationshipsUri };
|
|
35463
|
-
return docxFile.write(
|
|
35463
|
+
return docxFile.write(path9, xml.writeString(relationshipsContainer, namespaces));
|
|
35464
35464
|
});
|
|
35465
35465
|
}
|
|
35466
35466
|
function updateContentTypes(docxFile) {
|
|
35467
|
-
var
|
|
35467
|
+
var path9 = "[Content_Types].xml";
|
|
35468
35468
|
var contentTypesUri = "http://schemas.openxmlformats.org/package/2006/content-types";
|
|
35469
35469
|
var overrideName = "{" + contentTypesUri + "}Override";
|
|
35470
|
-
return docxFile.read(
|
|
35470
|
+
return docxFile.read(path9, "utf8").then(xml.readString).then(function(typesElement) {
|
|
35471
35471
|
var children = typesElement.children;
|
|
35472
35472
|
addOrUpdateElement(children, overrideName, "PartName", {
|
|
35473
35473
|
"PartName": styleMapAbsolutePath,
|
|
35474
35474
|
"ContentType": "text/prs.mammoth.style-map"
|
|
35475
35475
|
});
|
|
35476
35476
|
var namespaces = { "": contentTypesUri };
|
|
35477
|
-
return docxFile.write(
|
|
35477
|
+
return docxFile.write(path9, xml.writeString(typesElement, namespaces));
|
|
35478
35478
|
});
|
|
35479
35479
|
}
|
|
35480
35480
|
function addOrUpdateElement(elements, name, identifyingAttribute, attributes) {
|
|
@@ -36171,9 +36171,9 @@ var require_document_to_html = __commonJS({
|
|
|
36171
36171
|
};
|
|
36172
36172
|
var paths = [];
|
|
36173
36173
|
if (run.highlight !== null) {
|
|
36174
|
-
var
|
|
36175
|
-
if (
|
|
36176
|
-
paths.push(
|
|
36174
|
+
var path9 = findHtmlPath({ type: "highlight", color: run.highlight });
|
|
36175
|
+
if (path9) {
|
|
36176
|
+
paths.push(path9);
|
|
36177
36177
|
}
|
|
36178
36178
|
}
|
|
36179
36179
|
if (run.isSmallCaps) {
|
|
@@ -36208,15 +36208,15 @@ var require_document_to_html = __commonJS({
|
|
|
36208
36208
|
messages.push(unrecognisedStyleWarning("run", run));
|
|
36209
36209
|
}
|
|
36210
36210
|
paths.push(stylePath);
|
|
36211
|
-
paths.forEach(function(
|
|
36212
|
-
nodes =
|
|
36211
|
+
paths.forEach(function(path10) {
|
|
36212
|
+
nodes = path10.wrap.bind(path10, nodes);
|
|
36213
36213
|
});
|
|
36214
36214
|
return nodes();
|
|
36215
36215
|
}
|
|
36216
36216
|
function findHtmlPathForRunProperty(elementType, defaultTagName) {
|
|
36217
|
-
var
|
|
36218
|
-
if (
|
|
36219
|
-
return
|
|
36217
|
+
var path9 = findHtmlPath({ type: elementType });
|
|
36218
|
+
if (path9) {
|
|
36219
|
+
return path9;
|
|
36220
36220
|
} else if (defaultTagName) {
|
|
36221
36221
|
return htmlPaths.element(defaultTagName, {}, { fresh: false });
|
|
36222
36222
|
} else {
|
|
@@ -37936,11 +37936,11 @@ var require_options_reader = __commonJS({
|
|
|
37936
37936
|
var require_unzip = __commonJS({
|
|
37937
37937
|
"node_modules/mammoth/lib/unzip.js"(exports2) {
|
|
37938
37938
|
"use strict";
|
|
37939
|
-
var
|
|
37939
|
+
var fs9 = __require("fs");
|
|
37940
37940
|
var promises = require_promises();
|
|
37941
37941
|
var zipfile = require_zipfile();
|
|
37942
37942
|
exports2.openZip = openZip;
|
|
37943
|
-
var readFile = promises.promisify(
|
|
37943
|
+
var readFile = promises.promisify(fs9.readFile);
|
|
37944
37944
|
function openZip(options) {
|
|
37945
37945
|
if (options.path) {
|
|
37946
37946
|
return readFile(options.path).then(zipfile.openArrayBuffer);
|
|
@@ -38257,8 +38257,8 @@ var require_cjs = __commonJS({
|
|
|
38257
38257
|
return module3 = {
|
|
38258
38258
|
path: basedir,
|
|
38259
38259
|
exports: {},
|
|
38260
|
-
require: function(
|
|
38261
|
-
return commonjsRequire(
|
|
38260
|
+
require: function(path9, base) {
|
|
38261
|
+
return commonjsRequire(path9, base === void 0 || base === null ? module3.path : base);
|
|
38262
38262
|
}
|
|
38263
38263
|
}, fn(module3, module3.exports), module3.exports;
|
|
38264
38264
|
}
|
|
@@ -38665,9 +38665,9 @@ var require_cjs = __commonJS({
|
|
|
38665
38665
|
}
|
|
38666
38666
|
return o;
|
|
38667
38667
|
}
|
|
38668
|
-
var
|
|
38668
|
+
var fs9;
|
|
38669
38669
|
function get_fs() {
|
|
38670
|
-
return
|
|
38670
|
+
return fs9 || (fs9 = require$$0__default["default"]);
|
|
38671
38671
|
}
|
|
38672
38672
|
function parse4(file, options) {
|
|
38673
38673
|
if (file[0] == 80 && file[1] == 75) return parse_zip(file, options);
|
|
@@ -38952,7 +38952,7 @@ var require_cjs = __commonJS({
|
|
|
38952
38952
|
}
|
|
38953
38953
|
function read_file(filename2, options) {
|
|
38954
38954
|
get_fs();
|
|
38955
|
-
return parse4(
|
|
38955
|
+
return parse4(fs9.readFileSync(filename2), options);
|
|
38956
38956
|
}
|
|
38957
38957
|
function read(blob, options) {
|
|
38958
38958
|
switch (options && options.type || "base64") {
|
|
@@ -39218,7 +39218,7 @@ var require_cjs = __commonJS({
|
|
|
39218
39218
|
while (o.l < o.length) o.write_shift(1, 0);
|
|
39219
39219
|
return o;
|
|
39220
39220
|
}
|
|
39221
|
-
function find2(cfb2,
|
|
39221
|
+
function find2(cfb2, path9) {
|
|
39222
39222
|
var UCFullPaths = cfb2.FullPaths.map(function(x2) {
|
|
39223
39223
|
return x2.toUpperCase();
|
|
39224
39224
|
});
|
|
@@ -39227,11 +39227,11 @@ var require_cjs = __commonJS({
|
|
|
39227
39227
|
return y[y.length - (x2.slice(-1) == "/" ? 2 : 1)];
|
|
39228
39228
|
});
|
|
39229
39229
|
var k = false;
|
|
39230
|
-
if (
|
|
39230
|
+
if (path9.charCodeAt(0) === 47) {
|
|
39231
39231
|
k = true;
|
|
39232
|
-
|
|
39233
|
-
} else k =
|
|
39234
|
-
var UCPath =
|
|
39232
|
+
path9 = UCFullPaths[0].slice(0, -1) + path9;
|
|
39233
|
+
} else k = path9.indexOf("/") !== -1;
|
|
39234
|
+
var UCPath = path9.toUpperCase();
|
|
39235
39235
|
var w = k === true ? UCFullPaths.indexOf(UCPath) : UCPaths.indexOf(UCPath);
|
|
39236
39236
|
if (w !== -1) return cfb2.FileIndex[w];
|
|
39237
39237
|
var m = !UCPath.match(chr1);
|
|
@@ -39267,7 +39267,7 @@ var require_cjs = __commonJS({
|
|
|
39267
39267
|
function write_file(cfb2, filename2, options) {
|
|
39268
39268
|
get_fs();
|
|
39269
39269
|
var o = _write(cfb2, options);
|
|
39270
|
-
|
|
39270
|
+
fs9.writeFileSync(filename2, o);
|
|
39271
39271
|
}
|
|
39272
39272
|
function a2s(o) {
|
|
39273
39273
|
var out = new Array(o.length);
|
|
@@ -39279,7 +39279,7 @@ var require_cjs = __commonJS({
|
|
|
39279
39279
|
switch (options && options.type || "buffer") {
|
|
39280
39280
|
case "file":
|
|
39281
39281
|
get_fs();
|
|
39282
|
-
|
|
39282
|
+
fs9.writeFileSync(options.filename, o);
|
|
39283
39283
|
return o;
|
|
39284
39284
|
case "binary":
|
|
39285
39285
|
return typeof o == "string" ? o : a2s(o);
|
|
@@ -44704,8 +44704,8 @@ var require_cjs = __commonJS({
|
|
|
44704
44704
|
reader.readUInt16();
|
|
44705
44705
|
var id2 = reader.readUInt16();
|
|
44706
44706
|
var extension = reader.readString();
|
|
44707
|
-
var
|
|
44708
|
-
var payload = cfb.find(this.container,
|
|
44707
|
+
var path9 = "Root Entry/BinData/BIN".concat("".concat(id2.toString(16).toUpperCase()).padStart(4, "0"), ".").concat(extension);
|
|
44708
|
+
var payload = cfb.find(this.container, path9).content;
|
|
44709
44709
|
this.result.binData.push(new BinData(extension, pako_1.inflate(payload, {
|
|
44710
44710
|
windowBits: -15
|
|
44711
44711
|
})));
|
|
@@ -46838,33 +46838,33 @@ function renderRichText({
|
|
|
46838
46838
|
container.append(fragment);
|
|
46839
46839
|
}
|
|
46840
46840
|
function makePathFromDrawOPS(data) {
|
|
46841
|
-
const
|
|
46841
|
+
const path9 = new Path2D();
|
|
46842
46842
|
if (!data) {
|
|
46843
|
-
return
|
|
46843
|
+
return path9;
|
|
46844
46844
|
}
|
|
46845
46845
|
for (let i2 = 0, ii = data.length; i2 < ii; ) {
|
|
46846
46846
|
switch (data[i2++]) {
|
|
46847
46847
|
case DrawOPS.moveTo:
|
|
46848
|
-
|
|
46848
|
+
path9.moveTo(data[i2++], data[i2++]);
|
|
46849
46849
|
break;
|
|
46850
46850
|
case DrawOPS.lineTo:
|
|
46851
|
-
|
|
46851
|
+
path9.lineTo(data[i2++], data[i2++]);
|
|
46852
46852
|
break;
|
|
46853
46853
|
case DrawOPS.curveTo:
|
|
46854
|
-
|
|
46854
|
+
path9.bezierCurveTo(data[i2++], data[i2++], data[i2++], data[i2++], data[i2++], data[i2++]);
|
|
46855
46855
|
break;
|
|
46856
46856
|
case DrawOPS.quadraticCurveTo:
|
|
46857
|
-
|
|
46857
|
+
path9.quadraticCurveTo(data[i2++], data[i2++], data[i2++], data[i2++]);
|
|
46858
46858
|
break;
|
|
46859
46859
|
case DrawOPS.closePath:
|
|
46860
|
-
|
|
46860
|
+
path9.closePath();
|
|
46861
46861
|
break;
|
|
46862
46862
|
default:
|
|
46863
46863
|
warn(`Unrecognized drawing path operator: ${data[i2 - 1]}`);
|
|
46864
46864
|
break;
|
|
46865
46865
|
}
|
|
46866
46866
|
}
|
|
46867
|
-
return
|
|
46867
|
+
return path9;
|
|
46868
46868
|
}
|
|
46869
46869
|
function bindEvents(obj2, element, names) {
|
|
46870
46870
|
for (const name of names) {
|
|
@@ -46972,8 +46972,8 @@ function blend(fg, bg, alpha) {
|
|
|
46972
46972
|
return Math.round(alpha * fg + (1 - alpha) * bg);
|
|
46973
46973
|
}
|
|
46974
46974
|
async function node_utils_fetchData(url) {
|
|
46975
|
-
const
|
|
46976
|
-
const data = await
|
|
46975
|
+
const fs9 = process.getBuiltinModule("fs/promises");
|
|
46976
|
+
const data = await fs9.readFile(url);
|
|
46977
46977
|
return new Uint8Array(data);
|
|
46978
46978
|
}
|
|
46979
46979
|
function initGPU() {
|
|
@@ -47602,11 +47602,11 @@ function network_getArrayBuffer(val) {
|
|
|
47602
47602
|
return typeof val !== "string" ? val : stringToBytes(val).buffer;
|
|
47603
47603
|
}
|
|
47604
47604
|
function getReadableStream(url, opts = null) {
|
|
47605
|
-
const
|
|
47605
|
+
const fs9 = process.getBuiltinModule("fs");
|
|
47606
47606
|
const {
|
|
47607
47607
|
Readable
|
|
47608
47608
|
} = process.getBuiltinModule("stream");
|
|
47609
|
-
const readStream =
|
|
47609
|
+
const readStream = fs9.createReadStream(url, opts);
|
|
47610
47610
|
return Readable.toWeb(readStream);
|
|
47611
47611
|
}
|
|
47612
47612
|
function getNetworkStream(url) {
|
|
@@ -59410,11 +59410,11 @@ var init_pdf = __esm({
|
|
|
59410
59410
|
} catch (ex) {
|
|
59411
59411
|
warn(`getPathGenerator - ignoring character: "${ex}".`);
|
|
59412
59412
|
}
|
|
59413
|
-
const
|
|
59413
|
+
const path9 = makePathFromDrawOPS(cmds?.path);
|
|
59414
59414
|
if (!this.fontExtraProperties) {
|
|
59415
59415
|
objs.delete(objId);
|
|
59416
59416
|
}
|
|
59417
|
-
return this.compiledGlyphs[character] =
|
|
59417
|
+
return this.compiledGlyphs[character] = path9;
|
|
59418
59418
|
}
|
|
59419
59419
|
get black() {
|
|
59420
59420
|
return this.#fontData.black;
|
|
@@ -61312,7 +61312,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
61312
61312
|
Util.singularValueDecompose2dScale(this.baseTransform, scale);
|
|
61313
61313
|
return [matrixScaleX * scale[0], matrixScaleY * scale[1]];
|
|
61314
61314
|
}
|
|
61315
|
-
drawPattern(owner,
|
|
61315
|
+
drawPattern(owner, path9, useEOFill = false, [n, m], opIdx) {
|
|
61316
61316
|
const [x0, y0, x1, y1] = this.bbox;
|
|
61317
61317
|
const dependencyTracker = owner.dependencyTracker;
|
|
61318
61318
|
if (dependencyTracker) {
|
|
@@ -61320,9 +61320,9 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
61320
61320
|
}
|
|
61321
61321
|
owner.save();
|
|
61322
61322
|
if (useEOFill) {
|
|
61323
|
-
owner.ctx.clip(
|
|
61323
|
+
owner.ctx.clip(path9, "evenodd");
|
|
61324
61324
|
} else {
|
|
61325
|
-
owner.ctx.clip(
|
|
61325
|
+
owner.ctx.clip(path9);
|
|
61326
61326
|
}
|
|
61327
61327
|
owner.ctx.setTransform(...this.patternBaseMatrix);
|
|
61328
61328
|
owner.ctx.translate(n * this.xstep, m * this.ystep);
|
|
@@ -62417,15 +62417,15 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
62417
62417
|
if (hasInnerCutout && maskX0 === layerOffsetX && maskY0 === layerOffsetY && maskX1 === layerOffsetX + layerWidth && maskY1 === layerOffsetY + layerHeight) {
|
|
62418
62418
|
return;
|
|
62419
62419
|
}
|
|
62420
|
-
const
|
|
62421
|
-
|
|
62420
|
+
const path9 = new Path2D();
|
|
62421
|
+
path9.rect(layerOffsetX, layerOffsetY, layerWidth, layerHeight);
|
|
62422
62422
|
if (hasInnerCutout) {
|
|
62423
|
-
|
|
62423
|
+
path9.rect(maskX0, maskY0, maskX1 - maskX0, maskY1 - maskY0);
|
|
62424
62424
|
}
|
|
62425
62425
|
layerCtx.save();
|
|
62426
62426
|
layerCtx.globalAlpha = alpha / 255;
|
|
62427
62427
|
layerCtx.setTransform(1, 0, 0, 1, 0, 0);
|
|
62428
|
-
layerCtx.clip(
|
|
62428
|
+
layerCtx.clip(path9, "evenodd");
|
|
62429
62429
|
layerCtx.globalCompositeOperation = "destination-in";
|
|
62430
62430
|
layerCtx.fillStyle = "#000000";
|
|
62431
62431
|
layerCtx.fillRect(layerOffsetX, layerOffsetY, layerWidth, layerHeight);
|
|
@@ -62483,21 +62483,21 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
62483
62483
|
this._cachedGetSinglePixelWidth = null;
|
|
62484
62484
|
}
|
|
62485
62485
|
constructPath(opIdx, op, data, minMax) {
|
|
62486
|
-
let [
|
|
62486
|
+
let [path9] = data;
|
|
62487
62487
|
if (!minMax) {
|
|
62488
|
-
|
|
62488
|
+
path9 ||= data[0] = new Path2D();
|
|
62489
62489
|
if (op !== OPS.stroke && op !== OPS.closeStroke) {
|
|
62490
62490
|
this.current.tilingPatternDims = null;
|
|
62491
62491
|
}
|
|
62492
|
-
this[op](opIdx,
|
|
62492
|
+
this[op](opIdx, path9);
|
|
62493
62493
|
return;
|
|
62494
62494
|
}
|
|
62495
62495
|
if (this.dependencyTracker !== null) {
|
|
62496
62496
|
const outerExtraSize = op === OPS.stroke ? this.current.lineWidth / 2 : 0;
|
|
62497
62497
|
this.dependencyTracker.resetBBox(opIdx).recordBBox(opIdx, this.ctx, minMax[0] - outerExtraSize, minMax[2] + outerExtraSize, minMax[1] - outerExtraSize, minMax[3] + outerExtraSize).recordDependencies(opIdx, ["transform"]);
|
|
62498
62498
|
}
|
|
62499
|
-
if (!(
|
|
62500
|
-
|
|
62499
|
+
if (!(path9 instanceof Path2D)) {
|
|
62500
|
+
path9 = data[0] = makePathFromDrawOPS(path9);
|
|
62501
62501
|
}
|
|
62502
62502
|
Util.axialAlignedBoundingBox(minMax, getCurrentTransform(this.ctx), this.current.minMax);
|
|
62503
62503
|
const tilingDims = this.current.tilingPatternDims;
|
|
@@ -62509,13 +62509,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
62509
62509
|
this.current.fillColor.updatePatternDims(clippedBBox, tilingDims);
|
|
62510
62510
|
}
|
|
62511
62511
|
}
|
|
62512
|
-
this[op](opIdx,
|
|
62512
|
+
this[op](opIdx, path9);
|
|
62513
62513
|
this._pathStartIdx = opIdx;
|
|
62514
62514
|
}
|
|
62515
62515
|
closePath(opIdx) {
|
|
62516
62516
|
this.ctx.closePath();
|
|
62517
62517
|
}
|
|
62518
|
-
stroke(opIdx,
|
|
62518
|
+
stroke(opIdx, path9, consumePath = true) {
|
|
62519
62519
|
const started = consumePath && this.#beginKnockoutElement(this.current.strokeAlpha);
|
|
62520
62520
|
const ctx = this.ctx;
|
|
62521
62521
|
const strokeColor = this.current.strokeColor;
|
|
@@ -62527,26 +62527,26 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
62527
62527
|
ctx.strokeStyle = strokeColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.STROKE, opIdx);
|
|
62528
62528
|
if (baseTransform) {
|
|
62529
62529
|
const newPath = new Path2D();
|
|
62530
|
-
newPath.addPath(
|
|
62531
|
-
|
|
62530
|
+
newPath.addPath(path9, ctx.getTransform().invertSelf().multiplySelf(baseTransform));
|
|
62531
|
+
path9 = newPath;
|
|
62532
62532
|
}
|
|
62533
|
-
this.rescaleAndStroke(
|
|
62533
|
+
this.rescaleAndStroke(path9, false);
|
|
62534
62534
|
ctx.restore();
|
|
62535
62535
|
} else {
|
|
62536
|
-
this.rescaleAndStroke(
|
|
62536
|
+
this.rescaleAndStroke(path9, true);
|
|
62537
62537
|
}
|
|
62538
62538
|
}
|
|
62539
62539
|
this.dependencyTracker?.recordDependencies(opIdx, Dependencies.stroke);
|
|
62540
62540
|
if (consumePath) {
|
|
62541
|
-
this.consumePath(opIdx,
|
|
62541
|
+
this.consumePath(opIdx, path9, this.current.getClippedPathBoundingBox(PathType.STROKE, getCurrentTransform(this.ctx)));
|
|
62542
62542
|
}
|
|
62543
62543
|
ctx.globalAlpha = this.current.fillAlpha;
|
|
62544
62544
|
this.#endKnockoutElement(started);
|
|
62545
62545
|
}
|
|
62546
|
-
closeStroke(opIdx,
|
|
62547
|
-
this.stroke(opIdx,
|
|
62546
|
+
closeStroke(opIdx, path9) {
|
|
62547
|
+
this.stroke(opIdx, path9);
|
|
62548
62548
|
}
|
|
62549
|
-
fill(opIdx,
|
|
62549
|
+
fill(opIdx, path9, consumePath = true) {
|
|
62550
62550
|
const started = consumePath && this.#beginKnockoutElement(this.current.fillAlpha);
|
|
62551
62551
|
const ctx = this.ctx;
|
|
62552
62552
|
const fillColor = this.current.fillColor;
|
|
@@ -62558,10 +62558,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
62558
62558
|
const dims = this.current.tilingPatternDims;
|
|
62559
62559
|
const tileIdx = dims && fillColor.canSkipPatternCanvas(dims);
|
|
62560
62560
|
if (tileIdx) {
|
|
62561
|
-
fillColor.drawPattern(this,
|
|
62561
|
+
fillColor.drawPattern(this, path9, this.pendingEOFill, tileIdx, opIdx);
|
|
62562
62562
|
this.pendingEOFill = false;
|
|
62563
62563
|
if (consumePath) {
|
|
62564
|
-
this.consumePath(opIdx,
|
|
62564
|
+
this.consumePath(opIdx, path9, intersect);
|
|
62565
62565
|
}
|
|
62566
62566
|
this.current.tilingPatternDims = null;
|
|
62567
62567
|
this.#endKnockoutElement(started);
|
|
@@ -62573,17 +62573,17 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
62573
62573
|
ctx.fillStyle = fillColor.getPattern(ctx, this, getCurrentTransformInverse(ctx), PathType.FILL, opIdx);
|
|
62574
62574
|
if (baseTransform) {
|
|
62575
62575
|
const newPath = new Path2D();
|
|
62576
|
-
newPath.addPath(
|
|
62577
|
-
|
|
62576
|
+
newPath.addPath(path9, ctx.getTransform().invertSelf().multiplySelf(baseTransform));
|
|
62577
|
+
path9 = newPath;
|
|
62578
62578
|
}
|
|
62579
62579
|
needRestore = true;
|
|
62580
62580
|
}
|
|
62581
62581
|
if (this.contentVisible && intersect !== null) {
|
|
62582
62582
|
if (this.pendingEOFill) {
|
|
62583
|
-
ctx.fill(
|
|
62583
|
+
ctx.fill(path9, "evenodd");
|
|
62584
62584
|
this.pendingEOFill = false;
|
|
62585
62585
|
} else {
|
|
62586
|
-
ctx.fill(
|
|
62586
|
+
ctx.fill(path9);
|
|
62587
62587
|
}
|
|
62588
62588
|
}
|
|
62589
62589
|
if (needRestore) {
|
|
@@ -62591,38 +62591,38 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
62591
62591
|
this.dependencyTracker?.restore(opIdx);
|
|
62592
62592
|
}
|
|
62593
62593
|
if (consumePath) {
|
|
62594
|
-
this.consumePath(opIdx,
|
|
62594
|
+
this.consumePath(opIdx, path9, intersect);
|
|
62595
62595
|
}
|
|
62596
62596
|
this.#endKnockoutElement(started);
|
|
62597
62597
|
}
|
|
62598
|
-
eoFill(opIdx,
|
|
62598
|
+
eoFill(opIdx, path9) {
|
|
62599
62599
|
this.pendingEOFill = true;
|
|
62600
|
-
this.fill(opIdx,
|
|
62600
|
+
this.fill(opIdx, path9);
|
|
62601
62601
|
}
|
|
62602
|
-
fillStroke(opIdx,
|
|
62602
|
+
fillStroke(opIdx, path9) {
|
|
62603
62603
|
const started = this.#beginKnockoutElement(Math.min(this.current.fillAlpha, this.current.strokeAlpha));
|
|
62604
|
-
this.fill(opIdx,
|
|
62605
|
-
this.stroke(opIdx,
|
|
62606
|
-
this.consumePath(opIdx,
|
|
62604
|
+
this.fill(opIdx, path9, false);
|
|
62605
|
+
this.stroke(opIdx, path9, false);
|
|
62606
|
+
this.consumePath(opIdx, path9);
|
|
62607
62607
|
this.#endKnockoutElement(started);
|
|
62608
62608
|
}
|
|
62609
|
-
eoFillStroke(opIdx,
|
|
62609
|
+
eoFillStroke(opIdx, path9) {
|
|
62610
62610
|
this.pendingEOFill = true;
|
|
62611
|
-
this.fillStroke(opIdx,
|
|
62611
|
+
this.fillStroke(opIdx, path9);
|
|
62612
62612
|
}
|
|
62613
|
-
closeFillStroke(opIdx,
|
|
62614
|
-
this.fillStroke(opIdx,
|
|
62613
|
+
closeFillStroke(opIdx, path9) {
|
|
62614
|
+
this.fillStroke(opIdx, path9);
|
|
62615
62615
|
}
|
|
62616
|
-
closeEOFillStroke(opIdx,
|
|
62616
|
+
closeEOFillStroke(opIdx, path9) {
|
|
62617
62617
|
this.pendingEOFill = true;
|
|
62618
|
-
this.fillStroke(opIdx,
|
|
62618
|
+
this.fillStroke(opIdx, path9);
|
|
62619
62619
|
}
|
|
62620
|
-
endPath(opIdx,
|
|
62621
|
-
this.consumePath(opIdx,
|
|
62620
|
+
endPath(opIdx, path9) {
|
|
62621
|
+
this.consumePath(opIdx, path9);
|
|
62622
62622
|
}
|
|
62623
|
-
rawFillPath(opIdx,
|
|
62623
|
+
rawFillPath(opIdx, path9) {
|
|
62624
62624
|
const started = this.#beginKnockoutElement(this.current.fillAlpha);
|
|
62625
|
-
this.ctx.fill(
|
|
62625
|
+
this.ctx.fill(path9);
|
|
62626
62626
|
this.dependencyTracker?.recordDependencies(opIdx, Dependencies.rawFillPath).recordOperation(opIdx);
|
|
62627
62627
|
this.#endKnockoutElement(started);
|
|
62628
62628
|
}
|
|
@@ -62661,12 +62661,12 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
62661
62661
|
x: x2,
|
|
62662
62662
|
y,
|
|
62663
62663
|
fontSize,
|
|
62664
|
-
path:
|
|
62664
|
+
path: path9
|
|
62665
62665
|
} of paths) {
|
|
62666
|
-
if (!
|
|
62666
|
+
if (!path9) {
|
|
62667
62667
|
continue;
|
|
62668
62668
|
}
|
|
62669
|
-
newPath.addPath(
|
|
62669
|
+
newPath.addPath(path9, new DOMMatrix(transform2).preMultiplySelf(invTransf).translate(x2, y).scale(fontSize, -fontSize));
|
|
62670
62670
|
}
|
|
62671
62671
|
ctx.clip(newPath);
|
|
62672
62672
|
}
|
|
@@ -62759,9 +62759,9 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
62759
62759
|
this.moveText(opIdx, 0, this.current.leading);
|
|
62760
62760
|
this.dependencyTracker?.recordIncrementalData("moveText", this.dependencyTracker.getSimpleIndex("leading") ?? opIdx);
|
|
62761
62761
|
}
|
|
62762
|
-
#getScaledPath(
|
|
62762
|
+
#getScaledPath(path9, currentTransform, transform2) {
|
|
62763
62763
|
const newPath = new Path2D();
|
|
62764
|
-
newPath.addPath(
|
|
62764
|
+
newPath.addPath(path9, new DOMMatrix(transform2).invertSelf().multiplySelf(currentTransform));
|
|
62765
62765
|
return newPath;
|
|
62766
62766
|
}
|
|
62767
62767
|
paintChar(opIdx, character, x2, y, patternFillTransform, patternStrokeTransform) {
|
|
@@ -62774,11 +62774,11 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
62774
62774
|
const isAddToPathSet = !!(textRenderingMode & TextRenderingMode.ADD_TO_PATH_FLAG);
|
|
62775
62775
|
const patternFill = current.patternFill && !font.missingFile;
|
|
62776
62776
|
const patternStroke = current.patternStroke && !font.missingFile;
|
|
62777
|
-
let
|
|
62777
|
+
let path9;
|
|
62778
62778
|
if ((font.disableFontFace || isAddToPathSet || patternFill || patternStroke) && !font.missingFile) {
|
|
62779
|
-
|
|
62779
|
+
path9 = font.getPathGenerator(this.commonObjs, character);
|
|
62780
62780
|
}
|
|
62781
|
-
if (
|
|
62781
|
+
if (path9 && (font.disableFontFace || patternFill || patternStroke)) {
|
|
62782
62782
|
ctx.save();
|
|
62783
62783
|
ctx.translate(x2, y);
|
|
62784
62784
|
ctx.scale(fontSize, -fontSize);
|
|
@@ -62788,10 +62788,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
62788
62788
|
if (patternFillTransform) {
|
|
62789
62789
|
currentTransform = ctx.getTransform();
|
|
62790
62790
|
ctx.setTransform(...patternFillTransform);
|
|
62791
|
-
const scaledPath = this.#getScaledPath(
|
|
62791
|
+
const scaledPath = this.#getScaledPath(path9, currentTransform, patternFillTransform);
|
|
62792
62792
|
ctx.fill(scaledPath);
|
|
62793
62793
|
} else {
|
|
62794
|
-
ctx.fill(
|
|
62794
|
+
ctx.fill(path9);
|
|
62795
62795
|
}
|
|
62796
62796
|
}
|
|
62797
62797
|
if (fillStrokeMode === TextRenderingMode.STROKE || fillStrokeMode === TextRenderingMode.FILL_STROKE) {
|
|
@@ -62808,10 +62808,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
62808
62808
|
const transf = Util.transform([a, b, c, d, 0, 0], invPatternTransform);
|
|
62809
62809
|
Util.singularValueDecompose2dScale(transf, XY);
|
|
62810
62810
|
ctx.lineWidth *= Math.max(XY[0], XY[1]) / fontSize;
|
|
62811
|
-
ctx.stroke(this.#getScaledPath(
|
|
62811
|
+
ctx.stroke(this.#getScaledPath(path9, currentTransform, patternStrokeTransform));
|
|
62812
62812
|
} else {
|
|
62813
62813
|
ctx.lineWidth /= fontSize;
|
|
62814
|
-
ctx.stroke(
|
|
62814
|
+
ctx.stroke(path9);
|
|
62815
62815
|
}
|
|
62816
62816
|
}
|
|
62817
62817
|
ctx.restore();
|
|
@@ -62834,7 +62834,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
62834
62834
|
x: x2,
|
|
62835
62835
|
y,
|
|
62836
62836
|
fontSize,
|
|
62837
|
-
path:
|
|
62837
|
+
path: path9
|
|
62838
62838
|
});
|
|
62839
62839
|
this.dependencyTracker?.recordCharacterBBox(opIdx, ctx, font, fontSize, x2, y);
|
|
62840
62840
|
}
|
|
@@ -63230,9 +63230,9 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
63230
63230
|
const [x0, y0, x1, y1] = group2.bbox;
|
|
63231
63231
|
clip.rect(x0, y0, x1 - x0, y1 - y0);
|
|
63232
63232
|
if (group2.matrix) {
|
|
63233
|
-
const
|
|
63234
|
-
|
|
63235
|
-
clip =
|
|
63233
|
+
const path9 = new Path2D();
|
|
63234
|
+
path9.addPath(clip, new DOMMatrix(group2.matrix));
|
|
63235
|
+
clip = path9;
|
|
63236
63236
|
}
|
|
63237
63237
|
currentCtx.clip(clip);
|
|
63238
63238
|
}
|
|
@@ -63286,9 +63286,9 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
63286
63286
|
const [x0, y0, x1, y1] = group2.bbox;
|
|
63287
63287
|
clip.rect(x0, y0, x1 - x0, y1 - y0);
|
|
63288
63288
|
if (group2.matrix) {
|
|
63289
|
-
const
|
|
63290
|
-
|
|
63291
|
-
clip =
|
|
63289
|
+
const path9 = new Path2D();
|
|
63290
|
+
path9.addPath(clip, new DOMMatrix(group2.matrix));
|
|
63291
|
+
clip = path9;
|
|
63292
63292
|
}
|
|
63293
63293
|
groupCtx.clip(clip);
|
|
63294
63294
|
}
|
|
@@ -63767,7 +63767,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
63767
63767
|
}
|
|
63768
63768
|
endCompat(opIdx) {
|
|
63769
63769
|
}
|
|
63770
|
-
consumePath(opIdx,
|
|
63770
|
+
consumePath(opIdx, path9, clipBox) {
|
|
63771
63771
|
const isEmpty2 = this.current.isEmptyClip();
|
|
63772
63772
|
if (this.pendingClip) {
|
|
63773
63773
|
this.current.updateClipFromPath();
|
|
@@ -63779,9 +63779,9 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
63779
63779
|
if (this.pendingClip) {
|
|
63780
63780
|
if (!isEmpty2) {
|
|
63781
63781
|
if (this.pendingClip === EO_CLIP) {
|
|
63782
|
-
ctx.clip(
|
|
63782
|
+
ctx.clip(path9, "evenodd");
|
|
63783
63783
|
} else {
|
|
63784
|
-
ctx.clip(
|
|
63784
|
+
ctx.clip(path9);
|
|
63785
63785
|
}
|
|
63786
63786
|
}
|
|
63787
63787
|
this.pendingClip = null;
|
|
@@ -63854,7 +63854,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
63854
63854
|
}
|
|
63855
63855
|
return this._cachedScaleForStroking;
|
|
63856
63856
|
}
|
|
63857
|
-
rescaleAndStroke(
|
|
63857
|
+
rescaleAndStroke(path9, saveRestore) {
|
|
63858
63858
|
const {
|
|
63859
63859
|
ctx,
|
|
63860
63860
|
current: {
|
|
@@ -63864,7 +63864,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
63864
63864
|
const [scaleX, scaleY] = this.getScaleForStroking();
|
|
63865
63865
|
if (scaleX === scaleY) {
|
|
63866
63866
|
ctx.lineWidth = (lineWidth || 1) * scaleX;
|
|
63867
|
-
ctx.stroke(
|
|
63867
|
+
ctx.stroke(path9);
|
|
63868
63868
|
return;
|
|
63869
63869
|
}
|
|
63870
63870
|
const dashes = ctx.getLineDash();
|
|
@@ -63875,7 +63875,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
63875
63875
|
SCALE_MATRIX.a = 1 / scaleX;
|
|
63876
63876
|
SCALE_MATRIX.d = 1 / scaleY;
|
|
63877
63877
|
const newPath = new Path2D();
|
|
63878
|
-
newPath.addPath(
|
|
63878
|
+
newPath.addPath(path9, SCALE_MATRIX);
|
|
63879
63879
|
if (dashes.length > 0) {
|
|
63880
63880
|
const scale = Math.max(scaleX, scaleY);
|
|
63881
63881
|
ctx.setLineDash(dashes.map((x2) => x2 / scale));
|
|
@@ -64603,8 +64603,8 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
64603
64603
|
url
|
|
64604
64604
|
} = stream._source;
|
|
64605
64605
|
this._isStreamingSupported = !disableStream;
|
|
64606
|
-
const
|
|
64607
|
-
|
|
64606
|
+
const fs9 = process.getBuiltinModule("fs/promises");
|
|
64607
|
+
fs9.lstat(url).then((stat) => {
|
|
64608
64608
|
const readableStream = getReadableStream(url);
|
|
64609
64609
|
this._reader = readableStream.getReader();
|
|
64610
64610
|
const {
|
|
@@ -74798,11 +74798,11 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
74798
74798
|
};
|
|
74799
74799
|
ContourDrawOutline = class extends InkDrawOutline {
|
|
74800
74800
|
toSVGPath() {
|
|
74801
|
-
let
|
|
74802
|
-
if (!
|
|
74803
|
-
|
|
74801
|
+
let path9 = super.toSVGPath();
|
|
74802
|
+
if (!path9.endsWith("Z")) {
|
|
74803
|
+
path9 += "Z";
|
|
74804
74804
|
}
|
|
74805
|
-
return
|
|
74805
|
+
return path9;
|
|
74806
74806
|
}
|
|
74807
74807
|
};
|
|
74808
74808
|
es_uint8_array_from_base64 = __webpack_require__(5213);
|
|
@@ -77507,7 +77507,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
77507
77507
|
}
|
|
77508
77508
|
const drawLayer = textLayerData.drawLayer;
|
|
77509
77509
|
let div = textLayerData.selectionDiv;
|
|
77510
|
-
let
|
|
77510
|
+
let path9 = textLayerData.path;
|
|
77511
77511
|
if (!div) {
|
|
77512
77512
|
const clipPathId = `clip_selection_${_DrawLayer.#selectionId++}`;
|
|
77513
77513
|
div = document.createElement("div");
|
|
@@ -77526,18 +77526,18 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
77526
77526
|
const clipPath = _DrawLayer._svgFactory.createElement("clipPath");
|
|
77527
77527
|
clipPath.setAttribute("id", clipPathId);
|
|
77528
77528
|
clipPath.setAttribute("clipPathUnits", "objectBoundingBox");
|
|
77529
|
-
|
|
77530
|
-
clipPath.append(
|
|
77529
|
+
path9 = _DrawLayer._svgFactory.createElement("path");
|
|
77530
|
+
clipPath.append(path9);
|
|
77531
77531
|
svg.append(clipPath);
|
|
77532
77532
|
div.append(svg);
|
|
77533
|
-
textLayerData.path =
|
|
77533
|
+
textLayerData.path = path9;
|
|
77534
77534
|
textLayerData.selectionDiv = div;
|
|
77535
77535
|
}
|
|
77536
77536
|
if (!div.parentNode && drawLayer.#parent) {
|
|
77537
77537
|
drawLayer.#parent.append(div);
|
|
77538
77538
|
this.#selections.add(div);
|
|
77539
77539
|
}
|
|
77540
|
-
|
|
77540
|
+
path9.setAttribute("d", boxes.join(" "));
|
|
77541
77541
|
}
|
|
77542
77542
|
}
|
|
77543
77543
|
static get _svgFactory() {
|
|
@@ -77584,13 +77584,13 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
77584
77584
|
const root2 = this.#createSVG();
|
|
77585
77585
|
const defs = _DrawLayer._svgFactory.createElement("defs");
|
|
77586
77586
|
root2.append(defs);
|
|
77587
|
-
const
|
|
77588
|
-
defs.append(
|
|
77587
|
+
const path9 = _DrawLayer._svgFactory.createElement("path");
|
|
77588
|
+
defs.append(path9);
|
|
77589
77589
|
const pathId = `path_${id2}`;
|
|
77590
|
-
|
|
77591
|
-
|
|
77590
|
+
path9.setAttribute("id", pathId);
|
|
77591
|
+
path9.setAttribute("vector-effect", "non-scaling-stroke");
|
|
77592
77592
|
if (isPathUpdatable) {
|
|
77593
|
-
this.#toUpdate.set(id2,
|
|
77593
|
+
this.#toUpdate.set(id2, path9);
|
|
77594
77594
|
}
|
|
77595
77595
|
const clipPathId = hasClip ? this.#createClipPath(defs, pathId) : null;
|
|
77596
77596
|
const use = _DrawLayer._svgFactory.createElement("use");
|
|
@@ -77608,11 +77608,11 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
77608
77608
|
const root2 = this.#createSVG();
|
|
77609
77609
|
const defs = _DrawLayer._svgFactory.createElement("defs");
|
|
77610
77610
|
root2.append(defs);
|
|
77611
|
-
const
|
|
77612
|
-
defs.append(
|
|
77611
|
+
const path9 = _DrawLayer._svgFactory.createElement("path");
|
|
77612
|
+
defs.append(path9);
|
|
77613
77613
|
const pathId = `path_${id2}`;
|
|
77614
|
-
|
|
77615
|
-
|
|
77614
|
+
path9.setAttribute("id", pathId);
|
|
77615
|
+
path9.setAttribute("vector-effect", "non-scaling-stroke");
|
|
77616
77616
|
let maskId;
|
|
77617
77617
|
if (mustRemoveSelfIntersections) {
|
|
77618
77618
|
const mask = _DrawLayer._svgFactory.createElement("mask");
|
|
@@ -77659,7 +77659,7 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
77659
77659
|
root: root2,
|
|
77660
77660
|
bbox,
|
|
77661
77661
|
rootClass,
|
|
77662
|
-
path:
|
|
77662
|
+
path: path9
|
|
77663
77663
|
} = properties;
|
|
77664
77664
|
const element = typeof elementOrId === "number" ? this.#mapping.get(elementOrId) : elementOrId;
|
|
77665
77665
|
if (!element) {
|
|
@@ -77679,10 +77679,10 @@ fn fs_main(in : VertexOutput) -> @location(0) vec4<f32> {
|
|
|
77679
77679
|
classList.toggle(className, value);
|
|
77680
77680
|
}
|
|
77681
77681
|
}
|
|
77682
|
-
if (
|
|
77682
|
+
if (path9) {
|
|
77683
77683
|
const defs = element.firstElementChild;
|
|
77684
77684
|
const pathElement = defs.firstElementChild;
|
|
77685
|
-
this.#updateProperties(pathElement,
|
|
77685
|
+
this.#updateProperties(pathElement, path9);
|
|
77686
77686
|
}
|
|
77687
77687
|
}
|
|
77688
77688
|
updateParent(id2, layer) {
|
|
@@ -78373,8 +78373,8 @@ function getErrorMap() {
|
|
|
78373
78373
|
|
|
78374
78374
|
// node_modules/zod/v3/helpers/parseUtil.js
|
|
78375
78375
|
var makeIssue = (params) => {
|
|
78376
|
-
const { data, path:
|
|
78377
|
-
const fullPath = [...
|
|
78376
|
+
const { data, path: path9, errorMaps, issueData } = params;
|
|
78377
|
+
const fullPath = [...path9, ...issueData.path || []];
|
|
78378
78378
|
const fullIssue = {
|
|
78379
78379
|
...issueData,
|
|
78380
78380
|
path: fullPath
|
|
@@ -78490,11 +78490,11 @@ var errorUtil;
|
|
|
78490
78490
|
|
|
78491
78491
|
// node_modules/zod/v3/types.js
|
|
78492
78492
|
var ParseInputLazyPath = class {
|
|
78493
|
-
constructor(parent, value,
|
|
78493
|
+
constructor(parent, value, path9, key) {
|
|
78494
78494
|
this._cachedPath = [];
|
|
78495
78495
|
this.parent = parent;
|
|
78496
78496
|
this.data = value;
|
|
78497
|
-
this._path =
|
|
78497
|
+
this._path = path9;
|
|
78498
78498
|
this._key = key;
|
|
78499
78499
|
}
|
|
78500
78500
|
get path() {
|
|
@@ -82131,10 +82131,10 @@ function assignProp(target, prop, value) {
|
|
|
82131
82131
|
configurable: true
|
|
82132
82132
|
});
|
|
82133
82133
|
}
|
|
82134
|
-
function getElementAtPath(obj2,
|
|
82135
|
-
if (!
|
|
82134
|
+
function getElementAtPath(obj2, path9) {
|
|
82135
|
+
if (!path9)
|
|
82136
82136
|
return obj2;
|
|
82137
|
-
return
|
|
82137
|
+
return path9.reduce((acc, key) => acc?.[key], obj2);
|
|
82138
82138
|
}
|
|
82139
82139
|
function promiseAllObject(promisesObj) {
|
|
82140
82140
|
const keys2 = Object.keys(promisesObj);
|
|
@@ -82454,11 +82454,11 @@ function aborted(x2, startIndex = 0) {
|
|
|
82454
82454
|
}
|
|
82455
82455
|
return false;
|
|
82456
82456
|
}
|
|
82457
|
-
function prefixIssues(
|
|
82457
|
+
function prefixIssues(path9, issues) {
|
|
82458
82458
|
return issues.map((iss) => {
|
|
82459
82459
|
var _a2;
|
|
82460
82460
|
(_a2 = iss).path ?? (_a2.path = []);
|
|
82461
|
-
iss.path.unshift(
|
|
82461
|
+
iss.path.unshift(path9);
|
|
82462
82462
|
return iss;
|
|
82463
82463
|
});
|
|
82464
82464
|
}
|
|
@@ -92130,6 +92130,11 @@ function getInboxDir() {
|
|
|
92130
92130
|
fs.mkdirSync(dir, { recursive: true });
|
|
92131
92131
|
return dir;
|
|
92132
92132
|
}
|
|
92133
|
+
function getBackupsDir() {
|
|
92134
|
+
const dir = path.join(getDataDir(), "backups");
|
|
92135
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
92136
|
+
return dir;
|
|
92137
|
+
}
|
|
92133
92138
|
|
|
92134
92139
|
// packages/db/src/runtime.ts
|
|
92135
92140
|
import fs2 from "node:fs";
|
|
@@ -92155,6 +92160,8 @@ function isProcessAlive(pid) {
|
|
|
92155
92160
|
}
|
|
92156
92161
|
|
|
92157
92162
|
// packages/db/src/connection.ts
|
|
92163
|
+
import fs3 from "node:fs";
|
|
92164
|
+
import path3 from "node:path";
|
|
92158
92165
|
import { DatabaseSync } from "node:sqlite";
|
|
92159
92166
|
|
|
92160
92167
|
// packages/db/src/schema.ts
|
|
@@ -92473,33 +92480,155 @@ var MIGRATIONS = [
|
|
|
92473
92480
|
// idempotent. Feeds next-round prep and consistency (lessons carry into later interviews).
|
|
92474
92481
|
`
|
|
92475
92482
|
ALTER TABLE interview_preps ADD COLUMN debrief TEXT NOT NULL DEFAULT '{}';
|
|
92483
|
+
`,
|
|
92484
|
+
// v7 — offer comparison (한국 총보상 필드) + company reputation research field on jobs.
|
|
92485
|
+
// offers: one per job (UNIQUE job_id, mirrors interview_preps). Cash pieces are numeric (만원) so
|
|
92486
|
+
// the server can deterministically sum an annual estimate; equity/other stay free-text (comp is
|
|
92487
|
+
// messy). ai_score/verdict are written by the connected AI at save time (no LLM here) and rendered
|
|
92488
|
+
// by the dashboard, so it never needs to call an LLM. jobs.reputation: AI-researched company
|
|
92489
|
+
// reputation summary (same pattern as company_overview) — feeds offer verdicts + offer-evaluation.
|
|
92490
|
+
`
|
|
92491
|
+
CREATE TABLE IF NOT EXISTS offers (
|
|
92492
|
+
id TEXT PRIMARY KEY,
|
|
92493
|
+
job_id TEXT NOT NULL UNIQUE REFERENCES jobs(id) ON DELETE CASCADE,
|
|
92494
|
+
base_salary INTEGER,
|
|
92495
|
+
bonus_amount INTEGER,
|
|
92496
|
+
welfare_amount INTEGER,
|
|
92497
|
+
signing_amount INTEGER,
|
|
92498
|
+
equity_note TEXT,
|
|
92499
|
+
comp_note TEXT,
|
|
92500
|
+
work_arrangement TEXT,
|
|
92501
|
+
contract_type TEXT,
|
|
92502
|
+
accept_deadline TEXT,
|
|
92503
|
+
ai_score INTEGER,
|
|
92504
|
+
verdict TEXT,
|
|
92505
|
+
notes TEXT,
|
|
92506
|
+
created_at TEXT NOT NULL,
|
|
92507
|
+
updated_at TEXT NOT NULL
|
|
92508
|
+
);
|
|
92509
|
+
CREATE INDEX IF NOT EXISTS idx_offers_job ON offers(job_id);
|
|
92510
|
+
ALTER TABLE jobs ADD COLUMN reputation TEXT;
|
|
92511
|
+
`,
|
|
92512
|
+
// v8 — offer lifecycle status. 지원 상태(전형 깔때기 = 회사의 프로세스)와 직교하는
|
|
92513
|
+
// "내 응답" 축: open(진행)/accepted(수락)/declined(거절). declined여도 행을 지우지
|
|
92514
|
+
// 않는다 — 조건(연봉·처우) 히스토리는 다음 협상의 자산이라, 대시보드가 접힌
|
|
92515
|
+
// '지난 오퍼'로 강등해 보여줄 뿐이다. Additive ALTER (runner가 멱등 처리).
|
|
92516
|
+
`
|
|
92517
|
+
ALTER TABLE offers ADD COLUMN offer_status TEXT NOT NULL DEFAULT 'open';
|
|
92518
|
+
`,
|
|
92519
|
+
// v9 — 한국 문항형 자소서: 회사가 지정한 문항·글자수를 공고에 구조화 보관. 한국 자소서는
|
|
92520
|
+
// 회사별 문항형(항목·글자수 제한)이 지배적이라, AI가 문항별로 답변을 쓰고 글자수를 점검할 때
|
|
92521
|
+
// 참조할 원본을 공고 옆에 둔다(별도 엔티티가 아니라 job 컨텍스트에 함께 실린다). JSON 배열을
|
|
92522
|
+
// TEXT에 저장(다른 JSON 필드와 동일). Additive ALTER (runner가 멱등 처리).
|
|
92523
|
+
`
|
|
92524
|
+
ALTER TABLE jobs ADD COLUMN questions TEXT NOT NULL DEFAULT '[]';
|
|
92525
|
+
`,
|
|
92526
|
+
// v10 — 탈락 회고: 어느 전형 단계에서 떨어졌는지 자가 기록. 탈락 사유를 고지하는 기업은 6%뿐이고
|
|
92527
|
+
// 지원자 83%가 알고 싶어하므로, 이 자가 기록이 "서류는 붙는데 면접에서 떨어진다" 같은 패턴을 로컬
|
|
92528
|
+
// 데이터로 드러내는 유일한 신호다. 탈락이 아니거나 미기록이면 NULL. Additive ALTER (runner가 멱등 처리).
|
|
92529
|
+
`
|
|
92530
|
+
ALTER TABLE applications ADD COLUMN rejected_stage TEXT;
|
|
92531
|
+
`,
|
|
92532
|
+
// v11 — 전형 일정: 서류마감→인적성·AI역검→1·2차 면접→발표로 이어지는 단계별 날짜를 공고에
|
|
92533
|
+
// 구조화 보관. 일정을 jobs에 두는 이유: 서류마감(deadline)이 이미 jobs에 있고, save_job_posting
|
|
92534
|
+
// 업서트를 그대로 재사용해 도구 신설 없이 갱신할 수 있다. 면접초대 메일·발표 공지를 사용자가
|
|
92535
|
+
// 붙여넣으면 AI가 날짜를 추출해 저장하고, 서버가 D-day·같은 날짜 충돌을 결정론으로 계산한다.
|
|
92536
|
+
// JSON 배열을 TEXT에 저장(다른 JSON 필드와 동일). Additive ALTER (runner가 멱등 처리).
|
|
92537
|
+
`
|
|
92538
|
+
ALTER TABLE jobs ADD COLUMN schedule TEXT NOT NULL DEFAULT '[]';
|
|
92476
92539
|
`
|
|
92477
92540
|
];
|
|
92478
92541
|
function migrate(db) {
|
|
92479
92542
|
db.exec(`CREATE TABLE IF NOT EXISTS _meta (key TEXT PRIMARY KEY, value TEXT NOT NULL);`);
|
|
92480
92543
|
const row = db.prepare(`SELECT value FROM _meta WHERE key = 'schema_version'`).get();
|
|
92481
92544
|
const from = row ? Number(row.value) : 0;
|
|
92545
|
+
if (from >= MIGRATIONS.length) return { from, to: from };
|
|
92482
92546
|
for (let v = from; v < MIGRATIONS.length; v++) {
|
|
92483
|
-
db
|
|
92547
|
+
applyMigration(db, v);
|
|
92548
|
+
}
|
|
92549
|
+
return { from, to: MIGRATIONS.length };
|
|
92550
|
+
}
|
|
92551
|
+
function stampVersion(db, version3) {
|
|
92552
|
+
db.prepare(
|
|
92553
|
+
`INSERT INTO _meta (key, value) VALUES ('schema_version', ?)
|
|
92554
|
+
ON CONFLICT(key) DO UPDATE SET value = excluded.value`
|
|
92555
|
+
).run(String(version3));
|
|
92556
|
+
}
|
|
92557
|
+
function columnExists(db, table, column) {
|
|
92558
|
+
const rows = db.prepare(`PRAGMA table_info("${table.replaceAll('"', '""')}")`).all();
|
|
92559
|
+
return rows.some((r) => r.name === column);
|
|
92560
|
+
}
|
|
92561
|
+
var SELF_TRANSACTIONAL_MIGRATIONS = /* @__PURE__ */ new Set([1]);
|
|
92562
|
+
var ALTER_ADD_COLUMN_RE = /^[ \t]*ALTER TABLE\s+(\w+)\s+ADD COLUMN\s+(\w+)[^;]*;[ \t]*$/gm;
|
|
92563
|
+
function skipExistingColumns(db, sql) {
|
|
92564
|
+
return sql.replace(
|
|
92565
|
+
ALTER_ADD_COLUMN_RE,
|
|
92566
|
+
(stmt, table, column) => columnExists(db, table, column) ? "" : stmt
|
|
92567
|
+
);
|
|
92568
|
+
}
|
|
92569
|
+
function applyMigration(db, v) {
|
|
92570
|
+
const sql = MIGRATIONS[v];
|
|
92571
|
+
if (SELF_TRANSACTIONAL_MIGRATIONS.has(v)) {
|
|
92572
|
+
db.exec(sql);
|
|
92573
|
+
stampVersion(db, v + 1);
|
|
92574
|
+
return;
|
|
92484
92575
|
}
|
|
92485
|
-
|
|
92486
|
-
|
|
92487
|
-
db.
|
|
92488
|
-
|
|
92489
|
-
|
|
92490
|
-
|
|
92576
|
+
db.exec("BEGIN");
|
|
92577
|
+
try {
|
|
92578
|
+
db.exec(skipExistingColumns(db, sql));
|
|
92579
|
+
stampVersion(db, v + 1);
|
|
92580
|
+
db.exec("COMMIT");
|
|
92581
|
+
} catch (err2) {
|
|
92582
|
+
try {
|
|
92583
|
+
db.exec("ROLLBACK");
|
|
92584
|
+
} catch {
|
|
92585
|
+
}
|
|
92586
|
+
throw err2;
|
|
92491
92587
|
}
|
|
92492
|
-
return { from, to };
|
|
92493
92588
|
}
|
|
92494
92589
|
|
|
92495
92590
|
// packages/db/src/connection.ts
|
|
92496
92591
|
var _db = null;
|
|
92592
|
+
var PRE_MIGRATE_KEEP = 5;
|
|
92593
|
+
function vacuumInto(db, destPath) {
|
|
92594
|
+
if (/[\0\n\r]/.test(destPath)) throw new Error("backup path not safe for SQL literal");
|
|
92595
|
+
db.exec(`VACUUM INTO '${destPath.replace(/'/g, "''")}'`);
|
|
92596
|
+
}
|
|
92597
|
+
function preMigrationBackup(db) {
|
|
92598
|
+
try {
|
|
92599
|
+
const hasMeta = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name='_meta'`).get();
|
|
92600
|
+
if (!hasMeta) return;
|
|
92601
|
+
const row = db.prepare(`SELECT value FROM _meta WHERE key = 'schema_version'`).get();
|
|
92602
|
+
const from = row ? Number(row.value) : 0;
|
|
92603
|
+
if (from === 0 || from >= MIGRATIONS.length) return;
|
|
92604
|
+
const dir = getBackupsDir();
|
|
92605
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
92606
|
+
const dest = path3.join(dir, `pre-migrate-v${from}-${stamp}.sqlite`);
|
|
92607
|
+
try {
|
|
92608
|
+
vacuumInto(db, dest);
|
|
92609
|
+
} catch {
|
|
92610
|
+
fs3.copyFileSync(getDbPath(), dest);
|
|
92611
|
+
}
|
|
92612
|
+
const stale = fs3.readdirSync(dir).filter((f) => f.startsWith("pre-migrate-") && f.endsWith(".sqlite")).sort().reverse().slice(PRE_MIGRATE_KEEP);
|
|
92613
|
+
for (const f of stale) {
|
|
92614
|
+
try {
|
|
92615
|
+
fs3.unlinkSync(path3.join(dir, f));
|
|
92616
|
+
} catch {
|
|
92617
|
+
}
|
|
92618
|
+
}
|
|
92619
|
+
} catch (err2) {
|
|
92620
|
+
console.error(
|
|
92621
|
+
`[careermate] \uC5C5\uADF8\uB808\uC774\uB4DC \uC804 \uC790\uB3D9 \uBC31\uC5C5 \uC2E4\uD328(\uB9C8\uC774\uADF8\uB808\uC774\uC158\uC740 \uACC4\uC18D \uC9C4\uD589): ${err2 instanceof Error ? err2.message : String(err2)}`
|
|
92622
|
+
);
|
|
92623
|
+
}
|
|
92624
|
+
}
|
|
92497
92625
|
function getDb() {
|
|
92498
92626
|
if (_db) return _db;
|
|
92499
92627
|
const db = new DatabaseSync(getDbPath());
|
|
92500
92628
|
db.exec("PRAGMA journal_mode = WAL;");
|
|
92501
92629
|
db.exec("PRAGMA foreign_keys = ON;");
|
|
92502
92630
|
db.exec("PRAGMA busy_timeout = 5000;");
|
|
92631
|
+
preMigrationBackup(db);
|
|
92503
92632
|
migrate(db);
|
|
92504
92633
|
_db = db;
|
|
92505
92634
|
return db;
|
|
@@ -92911,6 +93040,22 @@ var CoverLetterRecordSchema = external_exports.object({
|
|
|
92911
93040
|
current_content: external_exports.string().nullable(),
|
|
92912
93041
|
versions: external_exports.array(CoverLetterVersionRecordSchema).optional()
|
|
92913
93042
|
});
|
|
93043
|
+
var JobQuestionSchema = external_exports.object({
|
|
93044
|
+
no: external_exports.number().int().positive().optional().describe("\uBB38\uD56D \uBC88\uD638(\uC788\uC73C\uBA74)"),
|
|
93045
|
+
question: external_exports.string().max(MAX_BODY).describe("\uBB38\uD56D \uD14D\uC2A4\uD2B8(\uD68C\uC0AC\uAC00 \uC81C\uC2DC\uD55C \uC790\uC18C\uC11C \uD56D\uBAA9)"),
|
|
93046
|
+
min_chars: external_exports.number().int().positive().optional().describe("\uAE00\uC790\uC218 \uD558\uD55C(\uC788\uC73C\uBA74)"),
|
|
93047
|
+
max_chars: external_exports.number().int().positive().optional().describe("\uAE00\uC790\uC218 \uC0C1\uD55C(\uC788\uC73C\uBA74)"),
|
|
93048
|
+
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"),
|
|
93049
|
+
note: optLine.describe('\uBD80\uAC00 \uBA54\uBAA8(\uC608: "\uD544\uC218", "\uACBD\uD5D8 \uC911\uC2EC")')
|
|
93050
|
+
});
|
|
93051
|
+
var SCHEDULE_DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
93052
|
+
var SCHEDULE_TIME_RE = /^([01]\d|2[0-3]):[0-5]\d$/;
|
|
93053
|
+
var JobScheduleItemSchema = external_exports.object({
|
|
93054
|
+
label: reqLine.describe("\uC77C\uC815 \uC774\uB984 (\uC608: 1\uCC28 \uBA74\uC811\xB7AI\uC5ED\uAC80\xB7\uC11C\uB958 \uBC1C\uD45C)"),
|
|
93055
|
+
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"),
|
|
93056
|
+
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)"),
|
|
93057
|
+
note: optLine.describe("\uBD80\uAC00 \uBA54\uBAA8(\uC608: \uC7A5\uC18C\xB7\uC900\uBE44\uBB3C, \uC120\uD0DD)")
|
|
93058
|
+
});
|
|
92914
93059
|
var JobInputSchema = external_exports.object({
|
|
92915
93060
|
company: reqLine,
|
|
92916
93061
|
position: reqLine.describe("\uC9C1\uBB34/\uD3EC\uC9C0\uC158\uBA85"),
|
|
@@ -92924,7 +93069,10 @@ var JobInputSchema = external_exports.object({
|
|
|
92924
93069
|
source: external_exports.string().max(MAX_LINE).optional().describe("\uCD9C\uCC98 (\uC0AC\uB78C\uC778/\uC6D0\uD2F0\uB4DC/\uC9C1\uC811 \uC785\uB825 \uB4F1)"),
|
|
92925
93070
|
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)"),
|
|
92926
93071
|
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)"),
|
|
92927
|
-
core_values: strList.optional().describe("\uD68C\uC0AC \uD575\uC2EC\uAC00\uCE58 (\uD0A4\uC6CC\uB4DC \uBC30\uC5F4)")
|
|
93072
|
+
core_values: strList.optional().describe("\uD68C\uC0AC \uD575\uC2EC\uAC00\uCE58 (\uD0A4\uC6CC\uB4DC \uBC30\uC5F4)"),
|
|
93073
|
+
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)"),
|
|
93074
|
+
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"),
|
|
93075
|
+
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.")
|
|
92928
93076
|
});
|
|
92929
93077
|
var JobRecordSchema = external_exports.object({
|
|
92930
93078
|
...baseRecord,
|
|
@@ -92940,7 +93088,46 @@ var JobRecordSchema = external_exports.object({
|
|
|
92940
93088
|
source: external_exports.string().nullable(),
|
|
92941
93089
|
company_overview: external_exports.string().nullable(),
|
|
92942
93090
|
talent_profile: external_exports.string().nullable(),
|
|
92943
|
-
core_values: external_exports.array(external_exports.string())
|
|
93091
|
+
core_values: external_exports.array(external_exports.string()),
|
|
93092
|
+
reputation: external_exports.string().nullable(),
|
|
93093
|
+
questions: external_exports.array(JobQuestionSchema),
|
|
93094
|
+
schedule: external_exports.array(JobScheduleItemSchema)
|
|
93095
|
+
});
|
|
93096
|
+
var OFFER_STATUSES = ["open", "accepted", "declined"];
|
|
93097
|
+
var OfferInputSchema = external_exports.object({
|
|
93098
|
+
job_id: reqLine,
|
|
93099
|
+
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)"),
|
|
93100
|
+
base_salary: external_exports.number().nonnegative().optional().describe("\uAE30\uBCF8\uAE09/\uC5F0\uBD09 (\uB9CC\uC6D0)"),
|
|
93101
|
+
bonus_amount: external_exports.number().nonnegative().optional().describe("\uC5F0 \uC131\uACFC\uAE09\xB7\uC0C1\uC5EC \uAE30\uB300\uC561 (\uB9CC\uC6D0)"),
|
|
93102
|
+
welfare_amount: external_exports.number().nonnegative().optional().describe("\uBCF5\uC9C0\uD3EC\uC778\uD2B8 \uB4F1 \uC5F0\uD658\uC0B0 (\uB9CC\uC6D0)"),
|
|
93103
|
+
signing_amount: external_exports.number().nonnegative().optional().describe("\uC0AC\uC774\uB2DD\uBCF4\uB108\uC2A4 \uC77C\uC2DC\uAE08 (\uB9CC\uC6D0)"),
|
|
93104
|
+
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)"),
|
|
93105
|
+
comp_note: optBody.describe("\uAE30\uD0C0 \uBCF4\uC0C1 \uC790\uC720 \uC11C\uC220"),
|
|
93106
|
+
work_arrangement: optLine.describe("\uADFC\uBB34\uD615\uD0DC (\uC7AC\uD0DD/\uD558\uC774\uBE0C\uB9AC\uB4DC/\uCD9C\uADFC)"),
|
|
93107
|
+
contract_type: optLine.describe("\uACC4\uC57D\uD615\uD0DC (\uC815\uADDC/\uACC4\uC57D \uB4F1)"),
|
|
93108
|
+
accept_deadline: optLine.describe("\uC218\uB77D \uB9C8\uAC10\uC77C YYYY-MM-DD"),
|
|
93109
|
+
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)"),
|
|
93110
|
+
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)"),
|
|
93111
|
+
notes: optNote
|
|
93112
|
+
});
|
|
93113
|
+
var OfferRecordSchema = external_exports.object({
|
|
93114
|
+
...baseRecord,
|
|
93115
|
+
job_id: external_exports.string(),
|
|
93116
|
+
offer_status: external_exports.enum(OFFER_STATUSES),
|
|
93117
|
+
base_salary: external_exports.number().nullable(),
|
|
93118
|
+
bonus_amount: external_exports.number().nullable(),
|
|
93119
|
+
welfare_amount: external_exports.number().nullable(),
|
|
93120
|
+
signing_amount: external_exports.number().nullable(),
|
|
93121
|
+
equity_note: external_exports.string().nullable(),
|
|
93122
|
+
comp_note: external_exports.string().nullable(),
|
|
93123
|
+
work_arrangement: external_exports.string().nullable(),
|
|
93124
|
+
contract_type: external_exports.string().nullable(),
|
|
93125
|
+
accept_deadline: external_exports.string().nullable(),
|
|
93126
|
+
ai_score: external_exports.number().nullable(),
|
|
93127
|
+
verdict: external_exports.string().nullable(),
|
|
93128
|
+
notes: external_exports.string().nullable(),
|
|
93129
|
+
/** Server-computed annual cash estimate = base + bonus + welfare (signing is one-time, excluded). Null if no numeric pieces. */
|
|
93130
|
+
total_comp_annual_est: external_exports.number().nullable()
|
|
92944
93131
|
});
|
|
92945
93132
|
var FitAnalysisInputSchema = external_exports.object({
|
|
92946
93133
|
job_id: reqLine.describe("\uBD84\uC11D \uB300\uC0C1 \uACF5\uACE0 ID"),
|
|
@@ -92963,6 +93150,14 @@ var FitAnalysisRecordSchema = external_exports.object({
|
|
|
92963
93150
|
missing_keywords: external_exports.array(external_exports.string()),
|
|
92964
93151
|
recommendations: external_exports.array(external_exports.string())
|
|
92965
93152
|
});
|
|
93153
|
+
var REJECTED_STAGES = ["document", "assessment", "interview", "final", "other"];
|
|
93154
|
+
var REJECTED_STAGE_LABELS = {
|
|
93155
|
+
document: "\uC11C\uB958",
|
|
93156
|
+
assessment: "\uC778\uC801\uC131\xB7AI\uC5ED\uAC80",
|
|
93157
|
+
interview: "\uBA74\uC811",
|
|
93158
|
+
final: "\uCD5C\uC885\xB7\uCC98\uC6B0",
|
|
93159
|
+
other: "\uAE30\uD0C0"
|
|
93160
|
+
};
|
|
92966
93161
|
var ApplicationInputSchema = external_exports.object({
|
|
92967
93162
|
job_id: reqLine,
|
|
92968
93163
|
status: external_exports.enum(APPLICATION_STATUSES).optional(),
|
|
@@ -92983,7 +93178,10 @@ var ApplicationStatusUpdateSchema = external_exports.object({
|
|
|
92983
93178
|
application_id: optLine,
|
|
92984
93179
|
status: external_exports.enum(APPLICATION_STATUSES),
|
|
92985
93180
|
note: optNote.describe("\uC0C1\uD0DC \uBCC0\uACBD \uC0AC\uC720/\uBA54\uBAA8"),
|
|
92986
|
-
submission: ApplicationSubmissionSchema.optional().describe("\uC9C0\uC6D0 \uC644\uB8CC \uAE30\uB85D\uC5D0 \uB0A8\uAE38 \uC81C\uCD9C \uC790\uB8CC \uC2A4\uB0C5\uC0F7")
|
|
93181
|
+
submission: ApplicationSubmissionSchema.optional().describe("\uC9C0\uC6D0 \uC644\uB8CC \uAE30\uB85D\uC5D0 \uB0A8\uAE38 \uC81C\uCD9C \uC790\uB8CC \uC2A4\uB0C5\uC0F7"),
|
|
93182
|
+
rejected_stage: external_exports.enum(REJECTED_STAGES).optional().describe(
|
|
93183
|
+
"\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."
|
|
93184
|
+
)
|
|
92987
93185
|
});
|
|
92988
93186
|
var ApplicationRecordSchema = external_exports.object({
|
|
92989
93187
|
...baseRecord,
|
|
@@ -92992,7 +93190,8 @@ var ApplicationRecordSchema = external_exports.object({
|
|
|
92992
93190
|
resume_id: external_exports.string().nullable(),
|
|
92993
93191
|
cover_letter_id: external_exports.string().nullable(),
|
|
92994
93192
|
applied_at: external_exports.string().nullable(),
|
|
92995
|
-
notes: external_exports.string().nullable()
|
|
93193
|
+
notes: external_exports.string().nullable(),
|
|
93194
|
+
rejected_stage: external_exports.enum(REJECTED_STAGES).nullable()
|
|
92996
93195
|
});
|
|
92997
93196
|
var StarGuideSchema = external_exports.object({
|
|
92998
93197
|
question: external_exports.string().max(MAX_NOTE),
|
|
@@ -93096,7 +93295,7 @@ var ApplicationContextSchema = external_exports.object({
|
|
|
93096
93295
|
});
|
|
93097
93296
|
|
|
93098
93297
|
// packages/shared/src/build-info.ts
|
|
93099
|
-
var APP_VERSION = true ? "0.0.
|
|
93298
|
+
var APP_VERSION = true ? "0.0.9" : "0.0.0-dev";
|
|
93100
93299
|
var BUNDLED = true;
|
|
93101
93300
|
|
|
93102
93301
|
// packages/shared/src/index.ts
|
|
@@ -93644,6 +93843,9 @@ function mapJob(r) {
|
|
|
93644
93843
|
company_overview: r.company_overview ?? null,
|
|
93645
93844
|
talent_profile: r.talent_profile ?? null,
|
|
93646
93845
|
core_values: fromJson(r.core_values, []),
|
|
93846
|
+
reputation: r.reputation ?? null,
|
|
93847
|
+
questions: fromJson(r.questions, []),
|
|
93848
|
+
schedule: fromJson(r.schedule, []),
|
|
93647
93849
|
created_at: r.created_at,
|
|
93648
93850
|
updated_at: r.updated_at
|
|
93649
93851
|
};
|
|
@@ -93673,7 +93875,7 @@ var jobRepo = {
|
|
|
93673
93875
|
if (existing) {
|
|
93674
93876
|
const m = { ...existing, ...input };
|
|
93675
93877
|
db.prepare(
|
|
93676
|
-
`UPDATE jobs SET company=?,position=?,url=?,location=?,employment_type=?,description=?,requirements=?,keywords=?,deadline=?,source=?,company_overview=?,talent_profile=?,core_values=?,updated_at=? WHERE id=?`
|
|
93878
|
+
`UPDATE jobs SET company=?,position=?,url=?,location=?,employment_type=?,description=?,requirements=?,keywords=?,deadline=?,source=?,company_overview=?,talent_profile=?,core_values=?,reputation=?,questions=?,schedule=?,updated_at=? WHERE id=?`
|
|
93677
93879
|
).run(
|
|
93678
93880
|
m.company,
|
|
93679
93881
|
m.position,
|
|
@@ -93688,6 +93890,12 @@ var jobRepo = {
|
|
|
93688
93890
|
m.company_overview ?? null,
|
|
93689
93891
|
m.talent_profile ?? null,
|
|
93690
93892
|
toJson(m.core_values ?? []),
|
|
93893
|
+
m.reputation ?? null,
|
|
93894
|
+
// questions omitted from input → m keeps existing.questions (preserved);
|
|
93895
|
+
// provided → replaced. Same merge semantics as the other JSON fields.
|
|
93896
|
+
toJson(m.questions ?? []),
|
|
93897
|
+
// schedule follows the same preserve-on-omit merge (v11 전형 일정).
|
|
93898
|
+
toJson(m.schedule ?? []),
|
|
93691
93899
|
ts,
|
|
93692
93900
|
existing.id
|
|
93693
93901
|
);
|
|
@@ -93695,8 +93903,8 @@ var jobRepo = {
|
|
|
93695
93903
|
}
|
|
93696
93904
|
const newJobId = id2 ?? newId("job_");
|
|
93697
93905
|
db.prepare(
|
|
93698
|
-
`INSERT INTO jobs (id,company,position,url,location,employment_type,description,requirements,keywords,deadline,source,company_overview,talent_profile,core_values,created_at,updated_at)
|
|
93699
|
-
VALUES (
|
|
93906
|
+
`INSERT INTO jobs (id,company,position,url,location,employment_type,description,requirements,keywords,deadline,source,company_overview,talent_profile,core_values,reputation,questions,schedule,created_at,updated_at)
|
|
93907
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`
|
|
93700
93908
|
).run(
|
|
93701
93909
|
newJobId,
|
|
93702
93910
|
input.company,
|
|
@@ -93712,6 +93920,9 @@ var jobRepo = {
|
|
|
93712
93920
|
input.company_overview ?? null,
|
|
93713
93921
|
input.talent_profile ?? null,
|
|
93714
93922
|
toJson(input.core_values ?? []),
|
|
93923
|
+
input.reputation ?? null,
|
|
93924
|
+
toJson(input.questions ?? []),
|
|
93925
|
+
toJson(input.schedule ?? []),
|
|
93715
93926
|
ts,
|
|
93716
93927
|
ts
|
|
93717
93928
|
);
|
|
@@ -93725,6 +93936,7 @@ var jobRepo = {
|
|
|
93725
93936
|
db.prepare(`DELETE FROM applications WHERE job_id=?`).run(id2);
|
|
93726
93937
|
db.prepare(`DELETE FROM interview_preps WHERE job_id=?`).run(id2);
|
|
93727
93938
|
db.prepare(`DELETE FROM application_timeline_events WHERE job_id=?`).run(id2);
|
|
93939
|
+
db.prepare(`DELETE FROM offers WHERE job_id=?`).run(id2);
|
|
93728
93940
|
return db.prepare(`DELETE FROM jobs WHERE id=?`).run(id2).changes > 0;
|
|
93729
93941
|
});
|
|
93730
93942
|
}
|
|
@@ -93799,6 +94011,8 @@ function mapApplication(r) {
|
|
|
93799
94011
|
cover_letter_id: r.cover_letter_id,
|
|
93800
94012
|
applied_at: r.applied_at,
|
|
93801
94013
|
notes: r.notes,
|
|
94014
|
+
// 탈락 회고: 탈락이 아니거나 미기록이면 NULL(v10 이전 DB는 컬럼이 없어 undefined → null 정규화).
|
|
94015
|
+
rejected_stage: r.rejected_stage ?? null,
|
|
93802
94016
|
created_at: r.created_at,
|
|
93803
94017
|
updated_at: r.updated_at
|
|
93804
94018
|
};
|
|
@@ -93835,17 +94049,19 @@ var applicationRepo = {
|
|
|
93835
94049
|
const app = this.ensure(input.job_id, input.status ?? "draft");
|
|
93836
94050
|
if (input.status && input.status !== app.status) assertStatusTransition(app.status, input.status);
|
|
93837
94051
|
const m = { ...app, ...input };
|
|
94052
|
+
const rejectedStageValue = m.status === "rejected" ? m.rejected_stage ?? null : null;
|
|
93838
94053
|
getDb().prepare(
|
|
93839
|
-
`UPDATE applications SET status=?,resume_id=?,cover_letter_id=?,applied_at=?,notes=?,updated_at=? WHERE id=?`
|
|
93840
|
-
).run(m.status, m.resume_id ?? null, m.cover_letter_id ?? null, m.applied_at ?? null, m.notes ?? null, now(), app.id);
|
|
94054
|
+
`UPDATE applications SET status=?,resume_id=?,cover_letter_id=?,applied_at=?,notes=?,rejected_stage=?,updated_at=? WHERE id=?`
|
|
94055
|
+
).run(m.status, m.resume_id ?? null, m.cover_letter_id ?? null, m.applied_at ?? null, m.notes ?? null, rejectedStageValue, now(), app.id);
|
|
93841
94056
|
return this.get(app.id);
|
|
93842
94057
|
},
|
|
93843
|
-
setStatus(jobId, status, note) {
|
|
94058
|
+
setStatus(jobId, status, note, rejectedStage) {
|
|
93844
94059
|
const app = this.ensure(jobId);
|
|
93845
94060
|
assertStatusTransition(app.status, status);
|
|
93846
94061
|
const appliedAt = status === "applied" && !app.applied_at ? now() : app.applied_at;
|
|
93847
94062
|
const notes = note ? [app.notes, note].filter(Boolean).join("\n") : app.notes;
|
|
93848
|
-
|
|
94063
|
+
const rejectedStageValue = status === "rejected" ? rejectedStage ?? app.rejected_stage ?? null : null;
|
|
94064
|
+
getDb().prepare(`UPDATE applications SET status=?, applied_at=?, notes=?, rejected_stage=?, updated_at=? WHERE id=?`).run(status, appliedAt, notes, rejectedStageValue, now(), app.id);
|
|
93849
94065
|
return this.get(app.id);
|
|
93850
94066
|
}
|
|
93851
94067
|
};
|
|
@@ -93965,10 +94181,100 @@ var timelineRepo = {
|
|
|
93965
94181
|
return getDb().prepare(`DELETE FROM application_timeline_events WHERE id=?`).run(id2).changes > 0;
|
|
93966
94182
|
}
|
|
93967
94183
|
};
|
|
94184
|
+
function mapOffer(r) {
|
|
94185
|
+
const base = r.base_salary ?? null;
|
|
94186
|
+
const bonus = r.bonus_amount ?? null;
|
|
94187
|
+
const welfare = r.welfare_amount ?? null;
|
|
94188
|
+
const hasAny = base != null || bonus != null || welfare != null;
|
|
94189
|
+
const total = hasAny ? (base ?? 0) + (bonus ?? 0) + (welfare ?? 0) : null;
|
|
94190
|
+
return {
|
|
94191
|
+
id: r.id,
|
|
94192
|
+
job_id: r.job_id,
|
|
94193
|
+
offer_status: r.offer_status ?? "open",
|
|
94194
|
+
base_salary: base,
|
|
94195
|
+
bonus_amount: bonus,
|
|
94196
|
+
welfare_amount: welfare,
|
|
94197
|
+
signing_amount: r.signing_amount ?? null,
|
|
94198
|
+
equity_note: r.equity_note ?? null,
|
|
94199
|
+
comp_note: r.comp_note ?? null,
|
|
94200
|
+
work_arrangement: r.work_arrangement ?? null,
|
|
94201
|
+
contract_type: r.contract_type ?? null,
|
|
94202
|
+
accept_deadline: r.accept_deadline ?? null,
|
|
94203
|
+
ai_score: r.ai_score ?? null,
|
|
94204
|
+
verdict: r.verdict ?? null,
|
|
94205
|
+
notes: r.notes ?? null,
|
|
94206
|
+
total_comp_annual_est: total,
|
|
94207
|
+
created_at: r.created_at,
|
|
94208
|
+
updated_at: r.updated_at
|
|
94209
|
+
};
|
|
94210
|
+
}
|
|
94211
|
+
var offerRepo = {
|
|
94212
|
+
getByJob(jobId) {
|
|
94213
|
+
const r = getDb().prepare(`SELECT * FROM offers WHERE job_id=?`).get(jobId);
|
|
94214
|
+
return r ? mapOffer(r) : null;
|
|
94215
|
+
},
|
|
94216
|
+
list() {
|
|
94217
|
+
return getDb().prepare(`SELECT * FROM offers ORDER BY ai_score IS NULL, ai_score DESC, updated_at DESC`).all().map(mapOffer);
|
|
94218
|
+
},
|
|
94219
|
+
/** Upsert by job_id (one offer per job). Missing fields are preserved on update (partial-safe). */
|
|
94220
|
+
save(input) {
|
|
94221
|
+
const db = getDb();
|
|
94222
|
+
const existing = this.getByJob(input.job_id);
|
|
94223
|
+
const ts = now();
|
|
94224
|
+
const n = (v, prev) => v ?? prev ?? null;
|
|
94225
|
+
const s = (v, prev) => v ?? prev ?? null;
|
|
94226
|
+
if (existing) {
|
|
94227
|
+
db.prepare(
|
|
94228
|
+
`UPDATE offers SET offer_status=?,base_salary=?,bonus_amount=?,welfare_amount=?,signing_amount=?,equity_note=?,comp_note=?,work_arrangement=?,contract_type=?,accept_deadline=?,ai_score=?,verdict=?,notes=?,updated_at=? WHERE id=?`
|
|
94229
|
+
).run(
|
|
94230
|
+
input.offer_status ?? existing.offer_status,
|
|
94231
|
+
n(input.base_salary, existing.base_salary),
|
|
94232
|
+
n(input.bonus_amount, existing.bonus_amount),
|
|
94233
|
+
n(input.welfare_amount, existing.welfare_amount),
|
|
94234
|
+
n(input.signing_amount, existing.signing_amount),
|
|
94235
|
+
s(input.equity_note, existing.equity_note),
|
|
94236
|
+
s(input.comp_note, existing.comp_note),
|
|
94237
|
+
s(input.work_arrangement, existing.work_arrangement),
|
|
94238
|
+
s(input.contract_type, existing.contract_type),
|
|
94239
|
+
s(input.accept_deadline, existing.accept_deadline),
|
|
94240
|
+
n(input.ai_score, existing.ai_score),
|
|
94241
|
+
s(input.verdict, existing.verdict),
|
|
94242
|
+
s(input.notes, existing.notes),
|
|
94243
|
+
ts,
|
|
94244
|
+
existing.id
|
|
94245
|
+
);
|
|
94246
|
+
return this.getByJob(input.job_id);
|
|
94247
|
+
}
|
|
94248
|
+
const id2 = newId("ofr_");
|
|
94249
|
+
db.prepare(
|
|
94250
|
+
`INSERT INTO offers (id,job_id,offer_status,base_salary,bonus_amount,welfare_amount,signing_amount,equity_note,comp_note,work_arrangement,contract_type,accept_deadline,ai_score,verdict,notes,created_at,updated_at)
|
|
94251
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`
|
|
94252
|
+
).run(
|
|
94253
|
+
id2,
|
|
94254
|
+
input.job_id,
|
|
94255
|
+
input.offer_status ?? "open",
|
|
94256
|
+
input.base_salary ?? null,
|
|
94257
|
+
input.bonus_amount ?? null,
|
|
94258
|
+
input.welfare_amount ?? null,
|
|
94259
|
+
input.signing_amount ?? null,
|
|
94260
|
+
input.equity_note ?? null,
|
|
94261
|
+
input.comp_note ?? null,
|
|
94262
|
+
input.work_arrangement ?? null,
|
|
94263
|
+
input.contract_type ?? null,
|
|
94264
|
+
input.accept_deadline ?? null,
|
|
94265
|
+
input.ai_score ?? null,
|
|
94266
|
+
input.verdict ?? null,
|
|
94267
|
+
input.notes ?? null,
|
|
94268
|
+
ts,
|
|
94269
|
+
ts
|
|
94270
|
+
);
|
|
94271
|
+
return this.getByJob(input.job_id);
|
|
94272
|
+
}
|
|
94273
|
+
};
|
|
93968
94274
|
|
|
93969
94275
|
// packages/mcp-tools/src/tools.ts
|
|
93970
|
-
import
|
|
93971
|
-
import
|
|
94276
|
+
import fs8 from "node:fs";
|
|
94277
|
+
import path8 from "node:path";
|
|
93972
94278
|
|
|
93973
94279
|
// packages/core/src/onboarding.ts
|
|
93974
94280
|
function profileCompleteness(p) {
|
|
@@ -94593,12 +94899,12 @@ function saveCoverLetterVersion(input) {
|
|
|
94593
94899
|
}
|
|
94594
94900
|
return { coverLetter, version: version3, verification, forced };
|
|
94595
94901
|
}
|
|
94596
|
-
function updateApplicationStatus(jobId, status, note, submission) {
|
|
94902
|
+
function updateApplicationStatus(jobId, status, note, submission, rejectedStage) {
|
|
94597
94903
|
const job = jobRepo.get(jobId);
|
|
94598
94904
|
if (!job) throw notFound("\uACF5\uACE0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.");
|
|
94599
94905
|
const before2 = applicationRepo.getByJob(jobId);
|
|
94600
94906
|
const application = tx(() => {
|
|
94601
|
-
let application2 = applicationRepo.setStatus(jobId, status, note);
|
|
94907
|
+
let application2 = applicationRepo.setStatus(jobId, status, note, rejectedStage);
|
|
94602
94908
|
const submittedDocs = (submission?.document_ids ?? []).map((docId) => documentRepo.get(docId)).filter((doc) => !!doc);
|
|
94603
94909
|
const submittedCoverLetter = submission?.cover_letter_id ? coverLetterRepo.get(submission.cover_letter_id, true) : null;
|
|
94604
94910
|
if (status === "applied" && submission) {
|
|
@@ -94634,7 +94940,9 @@ function updateApplicationStatus(jobId, status, note, submission) {
|
|
|
94634
94940
|
status,
|
|
94635
94941
|
status_label: APPLICATION_STATUS_LABELS[status],
|
|
94636
94942
|
note: note ?? null,
|
|
94637
|
-
submission: submissionPayload
|
|
94943
|
+
submission: submissionPayload,
|
|
94944
|
+
// 탈락 회고: rejected로 넘어갈 때 실제 저장된 단계(setStatus가 정합성 처리한 값)를 타임라인에도 남긴다.
|
|
94945
|
+
rejected_stage: application2.rejected_stage
|
|
94638
94946
|
},
|
|
94639
94947
|
occurred_at: submittedAtToOccurrence(submittedAt)
|
|
94640
94948
|
});
|
|
@@ -94667,8 +94975,21 @@ function saveInterviewPrep(input) {
|
|
|
94667
94975
|
// packages/core/src/summary.ts
|
|
94668
94976
|
var DEADLINE_ACTIONABLE = ["draft", "planned"];
|
|
94669
94977
|
var DEADLINE_SOON_DAYS = 14;
|
|
94670
|
-
var
|
|
94978
|
+
var SCHEDULE_SOON_DAYS = 7;
|
|
94671
94979
|
var DAY_MS = 864e5;
|
|
94980
|
+
function collectFutureSchedule(jobs, now2) {
|
|
94981
|
+
const items = [];
|
|
94982
|
+
for (const job of jobs) {
|
|
94983
|
+
for (const s of job.schedule ?? []) {
|
|
94984
|
+
const d_day = daysUntilDate(s.date, now2);
|
|
94985
|
+
if (d_day == null || d_day < 0) continue;
|
|
94986
|
+
items.push({ job, label: s.label, date: s.date, time: s.time, d_day });
|
|
94987
|
+
}
|
|
94988
|
+
}
|
|
94989
|
+
return items.sort(
|
|
94990
|
+
(a, b) => a.date < b.date ? -1 : a.date > b.date ? 1 : (a.time || "99:99").localeCompare(b.time || "99:99")
|
|
94991
|
+
);
|
|
94992
|
+
}
|
|
94672
94993
|
function daysUntilDate(dateStr, now2) {
|
|
94673
94994
|
if (!dateStr) return null;
|
|
94674
94995
|
const d = /* @__PURE__ */ new Date(`${dateStr}T00:00:00`);
|
|
@@ -94683,6 +95004,24 @@ function daysSinceTimestamp(iso, now2) {
|
|
|
94683
95004
|
if (isNaN(d.getTime())) return null;
|
|
94684
95005
|
return Math.floor((now2.getTime() - d.getTime()) / DAY_MS);
|
|
94685
95006
|
}
|
|
95007
|
+
function businessDaysSince(iso, now2) {
|
|
95008
|
+
if (!iso) return null;
|
|
95009
|
+
const start = new Date(iso);
|
|
95010
|
+
if (isNaN(start.getTime())) return null;
|
|
95011
|
+
const s = new Date(start);
|
|
95012
|
+
s.setHours(0, 0, 0, 0);
|
|
95013
|
+
const e = new Date(now2);
|
|
95014
|
+
e.setHours(0, 0, 0, 0);
|
|
95015
|
+
if (e.getTime() <= s.getTime()) return 0;
|
|
95016
|
+
let count = 0;
|
|
95017
|
+
const cursor = new Date(s);
|
|
95018
|
+
while (cursor.getTime() < e.getTime()) {
|
|
95019
|
+
cursor.setDate(cursor.getDate() + 1);
|
|
95020
|
+
const dow = cursor.getDay();
|
|
95021
|
+
if (dow !== 0 && dow !== 6) count++;
|
|
95022
|
+
}
|
|
95023
|
+
return count;
|
|
95024
|
+
}
|
|
94686
95025
|
function jobWithMeta(job) {
|
|
94687
95026
|
const app = applicationRepo.getByJob(job.id);
|
|
94688
95027
|
const fit = fitRepo.getByJob(job.id);
|
|
@@ -94694,18 +95033,36 @@ function listRecentActivity(limit = 20) {
|
|
|
94694
95033
|
}
|
|
94695
95034
|
var POST_PASS_STALE_DAYS = 7;
|
|
94696
95035
|
var POST_INTERVIEW_STALE_DAYS = 7;
|
|
95036
|
+
var FOLLOWUP_DUE_BIZ_DAYS = 5;
|
|
95037
|
+
var FOLLOWUP_OVERDUE_BIZ_DAYS = 8;
|
|
95038
|
+
var FOLLOWUP_ONHOLD_CAL_DAYS = 45;
|
|
94697
95039
|
function getActionDigest(now2 = /* @__PURE__ */ new Date()) {
|
|
94698
95040
|
const applications = applicationRepo.list();
|
|
94699
95041
|
const jobs = jobRepo.list();
|
|
94700
95042
|
const statusByJob = new Map(applications.map((a) => [a.job_id, a]));
|
|
95043
|
+
const jobById = new Map(jobs.map((j) => [j.id, j]));
|
|
95044
|
+
const preppedJobIds = new Set(interviewRepo.list().map((p) => p.job_id));
|
|
94701
95045
|
const followups = [];
|
|
94702
95046
|
for (const a of applications) {
|
|
94703
|
-
const job =
|
|
95047
|
+
const job = jobById.get(a.job_id);
|
|
94704
95048
|
if (!job) continue;
|
|
94705
95049
|
if (a.status === "applied") {
|
|
94706
|
-
const
|
|
94707
|
-
|
|
94708
|
-
|
|
95050
|
+
const cal = daysSinceTimestamp(a.applied_at, now2);
|
|
95051
|
+
const biz = businessDaysSince(a.applied_at, now2);
|
|
95052
|
+
if (biz != null && biz >= FOLLOWUP_DUE_BIZ_DAYS) {
|
|
95053
|
+
const overdue = biz >= FOLLOWUP_OVERDUE_BIZ_DAYS;
|
|
95054
|
+
const item = {
|
|
95055
|
+
job,
|
|
95056
|
+
status: a.status,
|
|
95057
|
+
status_label: APPLICATION_STATUS_LABELS[a.status],
|
|
95058
|
+
days_since: cal ?? 0,
|
|
95059
|
+
business_days_since: biz,
|
|
95060
|
+
followup_timing: overdue ? "overdue" : "due",
|
|
95061
|
+
reason: overdue ? `\uC9C0\uC6D0 \uD6C4 ${biz}\uC601\uC5C5\uC77C \uACBD\uACFC \u2014 \uD6C4\uC18D \uBB38\uC758 \uC801\uAE30\uAC00 \uC9C0\uB0AC\uC2B5\uB2C8\uB2E4(\uBB34\uB9AC\uD55C \uB3C5\uCD09\uC740 \uC5ED\uD6A8\uACFC\uC774\uB2C8 \uC544\uC9C1 \uC548 \uD588\uB2E4\uBA74 \uC815\uC911\uD788 1\uD68C\uB9CC)` : `\uC9C0\uC6D0 \uD6C4 ${biz}\uC601\uC5C5\uC77C \u2014 \uD314\uB85C\uC5C5 \uC801\uAE30(\uBB38\uC758\uB294 \uC815\uC911\uD788 1\uD68C)`
|
|
95062
|
+
};
|
|
95063
|
+
if (cal != null && cal >= FOLLOWUP_ONHOLD_CAL_DAYS) item.suggest_on_hold = true;
|
|
95064
|
+
followups.push(item);
|
|
95065
|
+
}
|
|
94709
95066
|
} else if (a.status === "document_passed") {
|
|
94710
95067
|
const days = daysSinceTimestamp(a.updated_at, now2);
|
|
94711
95068
|
if (days != null && days >= POST_PASS_STALE_DAYS)
|
|
@@ -94724,14 +95081,52 @@ function getActionDigest(now2 = /* @__PURE__ */ new Date()) {
|
|
|
94724
95081
|
if (days_left == null || days_left > DEADLINE_SOON_DAYS) return null;
|
|
94725
95082
|
return { job, status, status_label: APPLICATION_STATUS_LABELS[status], days_left };
|
|
94726
95083
|
}).filter((x2) => x2 !== null).sort((a, b) => a.days_left - b.days_left);
|
|
94727
|
-
const interview_todo = applications.filter((a) => INTERVIEW_UNLOCK_STATUSES.includes(a.status) && !
|
|
94728
|
-
const job =
|
|
95084
|
+
const interview_todo = applications.filter((a) => INTERVIEW_UNLOCK_STATUSES.includes(a.status) && !preppedJobIds.has(a.job_id)).map((a) => {
|
|
95085
|
+
const job = jobById.get(a.job_id);
|
|
94729
95086
|
return job ? { job, status_label: APPLICATION_STATUS_LABELS[a.status] } : null;
|
|
94730
95087
|
}).filter((x2) => x2 !== null);
|
|
95088
|
+
const futureSchedule = collectFutureSchedule(jobs, now2);
|
|
95089
|
+
const upcoming_schedule = futureSchedule.filter((x2) => x2.d_day <= SCHEDULE_SOON_DAYS).map((x2) => ({
|
|
95090
|
+
job_id: x2.job.id,
|
|
95091
|
+
company: x2.job.company,
|
|
95092
|
+
position: x2.job.position,
|
|
95093
|
+
label: x2.label,
|
|
95094
|
+
...x2.time ? { time: x2.time } : {},
|
|
95095
|
+
date: x2.date,
|
|
95096
|
+
d_day: x2.d_day
|
|
95097
|
+
}));
|
|
95098
|
+
const byDate = /* @__PURE__ */ new Map();
|
|
95099
|
+
for (const x2 of futureSchedule) {
|
|
95100
|
+
const arr = byDate.get(x2.date) ?? [];
|
|
95101
|
+
arr.push(x2);
|
|
95102
|
+
byDate.set(x2.date, arr);
|
|
95103
|
+
}
|
|
95104
|
+
const schedule_conflicts = [];
|
|
95105
|
+
for (const [date3, items] of byDate) {
|
|
95106
|
+
const distinctJobs = new Set(items.map((x2) => x2.job.id));
|
|
95107
|
+
if (distinctJobs.size < 2) continue;
|
|
95108
|
+
schedule_conflicts.push({
|
|
95109
|
+
date: date3,
|
|
95110
|
+
items: items.map((x2) => ({
|
|
95111
|
+
job_id: x2.job.id,
|
|
95112
|
+
company: x2.job.company,
|
|
95113
|
+
position: x2.job.position,
|
|
95114
|
+
label: x2.label,
|
|
95115
|
+
...x2.time ? { time: x2.time } : {}
|
|
95116
|
+
}))
|
|
95117
|
+
});
|
|
95118
|
+
}
|
|
95119
|
+
schedule_conflicts.sort((a, b) => a.date < b.date ? -1 : a.date > b.date ? 1 : 0);
|
|
94731
95120
|
const today = `${now2.getFullYear()}-${String(now2.getMonth() + 1).padStart(2, "0")}-${String(now2.getDate()).padStart(2, "0")}`;
|
|
94732
|
-
return { today, followups, deadlines, interview_todo };
|
|
95121
|
+
return { today, followups, deadlines, interview_todo, upcoming_schedule, schedule_conflicts };
|
|
94733
95122
|
}
|
|
94734
95123
|
var normToken = (s) => s.toLowerCase().trim().replace(/^[.,/()\s]+|[.,/()\s]+$/g, "");
|
|
95124
|
+
var ASCII_TOKEN_RE = /^[a-z0-9+#.]+$/;
|
|
95125
|
+
var escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
95126
|
+
function resumeBodyHasToken(text, token) {
|
|
95127
|
+
if (!ASCII_TOKEN_RE.test(token)) return text.includes(token);
|
|
95128
|
+
return new RegExp(`(?<![a-z0-9])${escapeRegExp(token)}(?![a-z0-9])`, "i").test(text);
|
|
95129
|
+
}
|
|
94735
95130
|
function prescreenJob(jobId) {
|
|
94736
95131
|
const job = jobRepo.get(jobId);
|
|
94737
95132
|
if (!job) return null;
|
|
@@ -94740,17 +95135,36 @@ function prescreenJob(jobId) {
|
|
|
94740
95135
|
for (const e of experienceRepo.list()) for (const t of e.tech ?? []) userTokens.add(normToken(t));
|
|
94741
95136
|
for (const p of projectRepo.list()) for (const t of p.tech ?? []) userTokens.add(normToken(t));
|
|
94742
95137
|
userTokens.delete("");
|
|
95138
|
+
const resume = documentRepo.primary("resume");
|
|
95139
|
+
const resume_checked = resume != null;
|
|
95140
|
+
const resumeText = (resume?.content ?? "").toLowerCase();
|
|
94743
95141
|
const keywords = (job.keywords ?? []).filter((k) => k && k.trim());
|
|
94744
95142
|
const matched = [];
|
|
94745
95143
|
const missing = [];
|
|
95144
|
+
const resume_matched = [];
|
|
94746
95145
|
for (const kw of keywords) {
|
|
94747
95146
|
const n = normToken(kw);
|
|
94748
|
-
const
|
|
95147
|
+
const skillHit = userTokens.has(n) || // substring match only for tokens ≥3 chars (avoid "c"/"r" matching everything).
|
|
94749
95148
|
n.length >= 3 && [...userTokens].some((u) => u.length >= 3 && (u.includes(n) || n.includes(u)));
|
|
94750
|
-
(
|
|
95149
|
+
(skillHit ? matched : missing).push(kw);
|
|
95150
|
+
if (resume_checked && n.length >= 2 && resumeBodyHasToken(resumeText, n)) resume_matched.push(kw);
|
|
94751
95151
|
}
|
|
94752
95152
|
const coverage = keywords.length ? matched.length / keywords.length : null;
|
|
94753
|
-
|
|
95153
|
+
const combinedSet = /* @__PURE__ */ new Set([...matched, ...resume_matched]);
|
|
95154
|
+
const combined_matched = keywords.filter((k) => combinedSet.has(k));
|
|
95155
|
+
const combined_coverage = keywords.length ? combined_matched.length / keywords.length : null;
|
|
95156
|
+
return {
|
|
95157
|
+
job_id: jobId,
|
|
95158
|
+
job_keywords: keywords,
|
|
95159
|
+
matched,
|
|
95160
|
+
missing,
|
|
95161
|
+
coverage,
|
|
95162
|
+
user_skill_count: userTokens.size,
|
|
95163
|
+
resume_matched,
|
|
95164
|
+
combined_matched,
|
|
95165
|
+
combined_coverage,
|
|
95166
|
+
resume_checked
|
|
95167
|
+
};
|
|
94754
95168
|
}
|
|
94755
95169
|
var PROGRESSION = ["applied", "document_passed", "interview", "final_passed"];
|
|
94756
95170
|
function getPipelineStats() {
|
|
@@ -94779,6 +95193,12 @@ function getPipelineStats() {
|
|
|
94779
95193
|
}
|
|
94780
95194
|
const pct = (n, d) => d > 0 ? Math.round(n / d * 1e3) / 10 : null;
|
|
94781
95195
|
const cur = (s) => applications.filter((a) => a.status === s).length;
|
|
95196
|
+
const rejectedApps = applications.filter((a) => a.status === "rejected");
|
|
95197
|
+
const rejected_by_stage = REJECTED_STAGES.map((stage) => ({
|
|
95198
|
+
stage,
|
|
95199
|
+
count: rejectedApps.filter((a) => a.rejected_stage === stage).length
|
|
95200
|
+
})).filter((s) => s.count > 0);
|
|
95201
|
+
const rejected_unrecorded = rejectedApps.filter((a) => !a.rejected_stage).length;
|
|
94782
95202
|
return {
|
|
94783
95203
|
total: applications.length,
|
|
94784
95204
|
by_status,
|
|
@@ -94790,12 +95210,14 @@ function getPipelineStats() {
|
|
|
94790
95210
|
in_progress: cur("applied") + cur("document_passed") + cur("interview"),
|
|
94791
95211
|
on_hold: cur("on_hold")
|
|
94792
95212
|
},
|
|
95213
|
+
rejected_by_stage,
|
|
95214
|
+
rejected_unrecorded,
|
|
94793
95215
|
note: "\uB2E8\uACC4\uBCC4 \uB3C4\uB2EC \uAE54\uB54C\uAE30\uB294 \uC0C1\uD0DC \uBCC0\uACBD \uC774\uB825(\uD0C0\uC784\uB77C\uC778)\uC73C\uB85C \uBCF5\uC6D0\uD55C \uC2E4\uCE21\uCE58\uC785\uB2C8\uB2E4(\uD604\uC7AC rejected\uC5EC\uB3C4 \uAC70\uCCD0\uAC04 \uCD5C\uACE0 \uB2E8\uACC4\uAE4C\uC9C0 \uC9D1\uACC4). \uBE44\uC728\uC740 \uC124\uBA85\uC6A9\uC774\uBA70 \uD45C\uBCF8\uC774 \uC791\uC73C\uBA74 \uC608\uCE21\uB825\uC774 \uB0AE\uC2B5\uB2C8\uB2E4 \u2014 \uCD94\uC138 \uCC38\uACE0\uB85C\uB9CC \uC4F0\uC138\uC694."
|
|
94794
95216
|
};
|
|
94795
95217
|
}
|
|
94796
95218
|
|
|
94797
95219
|
// packages/core/src/jobsearch.ts
|
|
94798
|
-
var UA =
|
|
95220
|
+
var UA = `careermate/${APP_VERSION} (+https://careermate.life)`;
|
|
94799
95221
|
function toYmd(v) {
|
|
94800
95222
|
if (typeof v !== "string" || v.length < 10) return void 0;
|
|
94801
95223
|
const m = v.match(/^(\d{4}-\d{2}-\d{2})/);
|
|
@@ -94885,6 +95307,24 @@ async function searchJobs(query, opts = {}) {
|
|
|
94885
95307
|
};
|
|
94886
95308
|
}
|
|
94887
95309
|
|
|
95310
|
+
// packages/core/src/offers.ts
|
|
95311
|
+
function withJob(offer, job) {
|
|
95312
|
+
return { ...offer, company: job?.company ?? "\u2014", position: job?.position ?? "\u2014" };
|
|
95313
|
+
}
|
|
95314
|
+
function saveOffer(input) {
|
|
95315
|
+
const job = jobRepo.get(input.job_id);
|
|
95316
|
+
if (!job) throw new Error("\uACF5\uACE0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 save_job_posting\uC73C\uB85C \uACF5\uACE0\uB97C \uC800\uC7A5\uD558\uC138\uC694.");
|
|
95317
|
+
return withJob(offerRepo.save(input), job);
|
|
95318
|
+
}
|
|
95319
|
+
function getOffer(jobId) {
|
|
95320
|
+
const offer = offerRepo.getByJob(jobId);
|
|
95321
|
+
if (!offer) return null;
|
|
95322
|
+
return withJob(offer, jobRepo.get(jobId));
|
|
95323
|
+
}
|
|
95324
|
+
function compareOffers() {
|
|
95325
|
+
return offerRepo.list().map((o) => withJob(o, jobRepo.get(o.job_id)));
|
|
95326
|
+
}
|
|
95327
|
+
|
|
94888
95328
|
// packages/prompts/src/humanize.ts
|
|
94889
95329
|
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
|
|
94890
95330
|
|
|
@@ -94913,12 +95353,15 @@ var HUMANIZE_WRITING_GUIDE = `# \uC0AC\uB78C\uC774 \uC4F4 \uAC83\uCC98\uB7FC: \u
|
|
|
94913
95353
|
3. \uAE30\uACC4\uC801 \uBCD1\uB82C\uAD6C\uC870 \u2014 \uC138 \uAC1C\uC529 \uB098\uC5F4(rule of three), \uBAA8\uB4E0 \uBB38\uB2E8\uC774 \uB611\uAC19\uC740 \uACE8\uACA9.
|
|
94914
95354
|
- "\uCCAB\uC9F8\u2026\uB458\uC9F8\u2026\uC14B\uC9F8", "A\uD558\uACE0 B\uD558\uBA70 C\uD558\uB294" \uAC19\uC740 \uADE0\uC77C\uD55C \uB098\uC5F4\uC744 \uBC18\uBCF5\uD558\uC9C0 \uC54A\uB294\uB2E4.
|
|
94915
95355
|
- \uBB38\uB2E8\uB9C8\uB2E4 \uAE38\uC774\uC640 \uC2DC\uC791 \uBC29\uC2DD\uC744 \uC77C\uBD80\uB7EC \uB2E4\uB974\uAC8C \uD55C\uB2E4.
|
|
95356
|
+
- \uAC19\uC740 \uCE90\uCE58\uD504\uB808\uC774\uC988\xB7\uBAA8\uD2F0\uD504(\uC608: "1\uC6D0\uB3C4 \uD2C0\uB9AC\uC9C0 \uC54A\uB294")\uB97C \uBB38\uC11C \uC804\uCCB4\uC5D0\uC11C **\uCD5C\uB300 2\uD68C**\uAE4C\uC9C0\uB9CC \uC4F4\uB2E4. 3\uD68C\uBD80\uD130\uB294 \uC778\uC704\uC801 \uC7A5\uCE58\uB85C \uC77D\uD600 \uC624\uD788\uB824 \uC0AC\uB78C \uB0C4\uC0C8\uB97C \uC9C0\uC6B4\uB2E4 \u2014 \uBC18\uBCF5\uD558\uACE0 \uC2F6\uC73C\uBA74 \uB9E4\uBC88 \uB2E4\uB978 \uB9D0\uB85C \uBC14\uAFD4 \uD45C\uD604\uD55C\uB2E4.
|
|
94916
95357
|
|
|
94917
95358
|
4. \uC0C1\uD22C\uC801 \uC5F0\uACB0\uC5B4 \uB0A8\uBC1C \u2014 "\uB610\uD55C", "\uBFD0\uB9CC \uC544\uB2C8\uB77C", "\uB354 \uB098\uC544\uAC00", "\uC774\uB97C \uD1B5\uD574", "\uACB0\uB860\uC801\uC73C\uB85C".
|
|
94918
95359
|
- \uC811\uC18D\uC5B4 \uC5C6\uC774 \uBB38\uC7A5\uC744 \uC787\uAC70\uB098, \uC0AC\uAC74\uC758 \uD750\uB984 \uC790\uCCB4\uB85C \uC5F0\uACB0\uD55C\uB2E4.
|
|
94919
95360
|
|
|
94920
95361
|
5. \uADE0\uC77C\uD55C \uBB38\uC7A5 \uB9AC\uB4EC \u2014 \uBAA8\uB4E0 \uBB38\uC7A5\uC774 \uBE44\uC2B7\uD55C \uAE38\uC774.
|
|
94921
95362
|
- \uC9E7\uC740 \uBB38\uC7A5\uACFC \uAE34 \uBB38\uC7A5\uC744 \uC11E\uB294\uB2E4. \uAC00\uB054 \uC544\uC8FC \uC9E7\uAC8C \uB04A\uB294\uB2E4. \uC774\uB807\uAC8C.
|
|
95363
|
+
- \uBE44\uC2B7\uD55C \uAE38\uC774\uC758 \uBB38\uC7A5\uC744 \uC138 \uAC1C \uC5F0\uC18D\uC73C\uB85C \uC4F0\uC9C0 \uC54A\uB294\uB2E4. \uD558\uB098\uB294 \uAE38\uAC8C \uD480\uACE0 \uB2E4\uC74C\uC740 \uD22D \uB04A\uB294 \uC2DD\uC73C\uB85C \uD638\uD761\uC744 \uBC14\uAFBC\uB2E4.
|
|
95364
|
+
- \uBB38\uB2E8\uB9C8\uB2E4 \uD55C \uD638\uD761\uC5D0 \uC77D\uD788\uB294 \uC9E7\uC740 \uB2E8\uD0C0 \uBB38\uC7A5(8\uB2E8\uC5B4 \uC548\uD30E \uC774\uD558)\uC744 \uCD5C\uC18C \uD558\uB098 \uB123\uB294\uB2E4.
|
|
94922
95365
|
|
|
94923
95366
|
6. \uACFC\uC7A5\uB41C \uC218\uC2DD\xB7\uC218\uB3D9\uD0DC \u2014 "\uB9E4\uC6B0", "\uC815\uB9D0\uB85C", "\uD0C1\uC6D4\uD55C", "\uC131\uACF5\uC801\uC73C\uB85C", "~\uB418\uC5B4\uC84C\uC2B5\uB2C8\uB2E4".
|
|
94924
95367
|
- \uBD80\uC0AC\uB97C \uBE7C\uACE0 \uB3D9\uC0AC\xB7\uBA85\uC0AC\uB97C \uAD6C\uCCB4\uD654\uD55C\uB2E4. \uB2A5\uB3D9\uD0DC\uB97C \uAE30\uBCF8\uC73C\uB85C \uD55C\uB2E4.
|
|
@@ -94946,6 +95389,7 @@ var STRUCTURED_DOC_WRITING_GUIDE = `# \uAD6C\uC870\uD615 \uBB38\uC11C(\uACBD\uB8
|
|
|
94946
95389
|
- \uAC01 \uBD88\uB9BF\uC740 \uB3D9\uC0AC\uB098 \uC218\uCE58\uB85C \uC2DC\uC791\uD558\uACE0, \uAC80\uC99D \uAC00\uB2A5\uD55C \uC0AC\uC2E4(\uC22B\uC790\xB7\uAE30\uAC04\xB7\uB3C4\uAD6C\xB7\uC5ED\uD560\xB7\uACB0\uACFC)\uC744 \uD55C \uC904\uC5D0 \uB2F4\uB294\uB2E4.
|
|
94947
95390
|
- \uBD88\uB9BF \uC548\uC758 \uBC88\uC5ED\uD22C\xB7\uD074\uB9AC\uC170\xB7\uACF5\uD5C8\uD55C \uC77C\uBC18\uB860\xB7\uC218\uB3D9\uD0DC\uB294 \uC790\uAE30\uC18C\uAC1C\uC11C\uC640 \uB611\uAC19\uC774 \uC81C\uAC70\uD55C\uB2E4. (\uC608: "\uBD84\uC11D\uC744 \uC9C4\uD589\uD558\uC600\uC2B5\uB2C8\uB2E4" \u2192 "\uBD84\uC11D\uD588\uB2E4", "\uB9CE\uC740 \uC131\uACFC\uB97C \uB0C8\uC2B5\uB2C8\uB2E4" \u2192 \uC2E4\uC81C \uC218\uCE58)
|
|
94948
95391
|
- STAR\uC744 \uD55C\uB450 \uC904\uB85C \uC555\uCD95\uD55C\uB2E4: \uBB34\uC5C7\uC744 \uC65C \uD588\uACE0 \uACB0\uACFC \uC218\uCE58\uAC00 \uC5B4\uB5BB\uAC8C \uB410\uB294\uC9C0.
|
|
95392
|
+
- \uC0B0\uBB38\uD615 \uBD88\uB9BF\uC774 \uC5EC\uB7EC \uBB38\uC7A5\uC73C\uB85C \uAE38\uC5B4\uC9C0\uBA74, \uB9E8 \uC55E\uC5D0 "\uBC29\uBC95\u2192\uC131\uACFC"\uB97C \uC555\uCD95\uD55C \uB9AC\uB4DC \uAD6C\uB97C **\uAD75\uAC8C \uD55C \uC904** \uC5B9\uC5B4 30\uCD08 \uC2A4\uCE94\uC5D0\uC11C \uBC29\uBC95\uC774 \uBB38\uC7A5 \uC18D\uC5D0 \uBB3B\uD788\uC9C0 \uC54A\uAC8C \uD55C\uB2E4. (\uC608: **"\uC81C\uD488\uAD70\uBCC4 \uC18C\uC9C4\uC8FC\uAE30 \uCC28\uB4F1 \u2192 90\uC77C \uC7AC\uAD6C\uB9E4 18%\u219227%"** \u2014 \uC774\uC5B4\uC11C \uC0C1\uC138 \uC124\uBA85.) \uB2E8 \uC815\uC9C1 \uC7A5\uCE58(\uADC0\uC18D \uB2E8\uC11C\xB7\uACFC\uC7A5 \uC5C6\uB294 \uD558\uD5A5 \uC815\uB82C)\uB294 \uB9AC\uB4DC \uAD6C\uC5D0\uC11C\uB3C4 \uADF8\uB300\uB85C \uC720\uC9C0\uD55C\uB2E4 \u2014 \uB9AC\uB4DC \uAD6C\uAC00 \uC131\uACFC\uB97C \uBD80\uD480\uB9AC\uB294 \uD5E4\uB4DC\uB77C\uC778\uC774 \uB418\uBA74 \uC548 \uB41C\uB2E4.
|
|
94949
95393
|
|
|
94950
95394
|
## Do / Don't
|
|
94951
95395
|
- Do: \uB450\uAD04\uC2DD \uBD88\uB9BF(\uACB0\uACFC\xB7\uC218\uCE58\uB97C \uC55E\uC138\uC6C0), \uC9C1\uBB34\xB7\uAE30\uAC04\xB7\uC5ED\uD560 \uAD6C\uBD84, \uC131\uACFC\uB97C \uC22B\uC790\uB85C.
|
|
@@ -95097,11 +95541,11 @@ function renderWorkflowMarkdown(id2) {
|
|
|
95097
95541
|
}
|
|
95098
95542
|
|
|
95099
95543
|
// packages/knowledge/src/index.ts
|
|
95100
|
-
import
|
|
95101
|
-
import
|
|
95544
|
+
import fs4 from "node:fs";
|
|
95545
|
+
import path4 from "node:path";
|
|
95102
95546
|
import { fileURLToPath } from "node:url";
|
|
95103
|
-
var here =
|
|
95104
|
-
var CAREER_OS_DIR = BUNDLED ?
|
|
95547
|
+
var here = path4.dirname(fileURLToPath(import.meta.url));
|
|
95548
|
+
var CAREER_OS_DIR = BUNDLED ? path4.join(here, "career-os") : path4.resolve(here, "..", "..", "..", "docs", "career-os");
|
|
95105
95549
|
var EXPERT_DOMAINS = [
|
|
95106
95550
|
"resume",
|
|
95107
95551
|
"ats",
|
|
@@ -95133,7 +95577,7 @@ var cache = /* @__PURE__ */ new Map();
|
|
|
95133
95577
|
function readDoc(rel) {
|
|
95134
95578
|
let cached2 = cache.get(rel);
|
|
95135
95579
|
if (cached2 === void 0) {
|
|
95136
|
-
cached2 =
|
|
95580
|
+
cached2 = fs4.readFileSync(path4.join(CAREER_OS_DIR, rel), "utf8");
|
|
95137
95581
|
cache.set(rel, cached2);
|
|
95138
95582
|
}
|
|
95139
95583
|
return cached2;
|
|
@@ -95142,7 +95586,7 @@ function getPlaybook(domain) {
|
|
|
95142
95586
|
return readDoc(`knowledge/${domain}.md`);
|
|
95143
95587
|
}
|
|
95144
95588
|
function getVerifier(id2) {
|
|
95145
|
-
return readDoc(
|
|
95589
|
+
return readDoc(path4.join("knowledge", "verifiers", `${id2}.md`));
|
|
95146
95590
|
}
|
|
95147
95591
|
function getEop(feature) {
|
|
95148
95592
|
return readDoc(`eop/${feature}.md`);
|
|
@@ -112765,16 +113209,16 @@ var replacer = ({ json, patch, patchText, context, keepOriginalStyles = true })
|
|
|
112765
113209
|
didFindOccurrence: true
|
|
112766
113210
|
};
|
|
112767
113211
|
};
|
|
112768
|
-
var goToElementFromPath = (json,
|
|
113212
|
+
var goToElementFromPath = (json, path9) => {
|
|
112769
113213
|
let element = json;
|
|
112770
|
-
for (let i2 = 1; i2 <
|
|
112771
|
-
const index =
|
|
113214
|
+
for (let i2 = 1; i2 < path9.length; i2++) {
|
|
113215
|
+
const index = path9[i2];
|
|
112772
113216
|
element = element.elements[index];
|
|
112773
113217
|
}
|
|
112774
113218
|
return element;
|
|
112775
113219
|
};
|
|
112776
|
-
var goToParentElementFromPath = (json,
|
|
112777
|
-
var getLastElementIndexFromPath = (
|
|
113220
|
+
var goToParentElementFromPath = (json, path9) => goToElementFromPath(json, path9.slice(0, path9.length - 1));
|
|
113221
|
+
var getLastElementIndexFromPath = (path9) => path9[path9.length - 1];
|
|
112778
113222
|
var PatchType = {
|
|
112779
113223
|
/** Replace entire file-level elements (e.g., whole paragraphs) */
|
|
112780
113224
|
DOCUMENT: "file",
|
|
@@ -113334,8 +113778,8 @@ function decodeEntities(input) {
|
|
|
113334
113778
|
}
|
|
113335
113779
|
|
|
113336
113780
|
// packages/parsers/src/documents.ts
|
|
113337
|
-
import
|
|
113338
|
-
import
|
|
113781
|
+
import fs5 from "node:fs";
|
|
113782
|
+
import path5 from "node:path";
|
|
113339
113783
|
import os2 from "node:os";
|
|
113340
113784
|
|
|
113341
113785
|
// node_modules/fflate/esm/index.mjs
|
|
@@ -113826,7 +114270,7 @@ var import_mammoth = __toESM(require_lib6(), 1);
|
|
|
113826
114270
|
var import_hwp = __toESM(require_cjs(), 1);
|
|
113827
114271
|
var parseHwp = import_hwp.default?.parse ?? import_hwp.default?.default?.parse;
|
|
113828
114272
|
var MAX_BYTES = 25 * 1024 * 1024;
|
|
113829
|
-
var SENSITIVE_PATH_RE = /(^|[/\\])\.(ssh|aws|gnupg)([/\\]|$)|(^|[/\\])id_(rsa|dsa|ecdsa|ed25519)(\.[\w]+)?$|\.(pem|ppk)$|(^|[/\\])\.env(\.[\w-]+)?$|(^|[/\\])\.(npmrc|netrc|git-credentials)$/i;
|
|
114273
|
+
var SENSITIVE_PATH_RE = /(^|[/\\])\.(ssh|aws|gnupg|kube|docker|azure|boto)([/\\]|$)|[/\\]\.config[/\\]gcloud([/\\]|$)|(^|[/\\])id_(rsa|dsa|ecdsa|ed25519)(\.[\w]+)?$|\.(pem|ppk)$|(^|[/\\])\.env(\.[\w-]+)?$|(^|[/\\])\.(npmrc|netrc|git-credentials)$|(^|[/\\])(login data|web data|cookies|key4\.db|logins\.json|wallet\.dat)$/i;
|
|
113830
114274
|
var MAX_HWPX_ENTRY_BYTES = 40 * 1024 * 1024;
|
|
113831
114275
|
var MAX_HWPX_TOTAL_BYTES = 80 * 1024 * 1024;
|
|
113832
114276
|
var MAX_PDF_PAGES = 300;
|
|
@@ -113840,8 +114284,8 @@ var MD_RE = /\.(md|markdown|mdown|mkd)$/i;
|
|
|
113840
114284
|
var LEGACY_BINARY_RE = /\.(docm?|dot[xm]?|pptx?|ppt|xlsx?|xls|odt|ods|odp|rtf|pages|key|numbers)$/i;
|
|
113841
114285
|
function resolveDocumentPath(input, baseDir) {
|
|
113842
114286
|
let p = (input ?? "").trim().replace(/^["']|["']$/g, "");
|
|
113843
|
-
if (p === "~" || p.startsWith("~/") || p.startsWith("~\\")) p =
|
|
113844
|
-
if (!
|
|
114287
|
+
if (p === "~" || p.startsWith("~/") || p.startsWith("~\\")) p = path5.join(os2.homedir(), p.slice(1));
|
|
114288
|
+
if (!path5.isAbsolute(p)) p = path5.resolve(baseDir ?? process.cwd(), p);
|
|
113845
114289
|
return p;
|
|
113846
114290
|
}
|
|
113847
114291
|
async function extractDocument(input, baseDir) {
|
|
@@ -113858,7 +114302,7 @@ async function extractDocument(input, baseDir) {
|
|
|
113858
114302
|
});
|
|
113859
114303
|
let realPath = filePath;
|
|
113860
114304
|
try {
|
|
113861
|
-
realPath =
|
|
114305
|
+
realPath = fs5.realpathSync.native(filePath);
|
|
113862
114306
|
} catch {
|
|
113863
114307
|
}
|
|
113864
114308
|
if (SENSITIVE_PATH_RE.test(filePath) || SENSITIVE_PATH_RE.test(realPath)) {
|
|
@@ -113872,7 +114316,7 @@ async function extractDocument(input, baseDir) {
|
|
|
113872
114316
|
}
|
|
113873
114317
|
let stat;
|
|
113874
114318
|
try {
|
|
113875
|
-
stat =
|
|
114319
|
+
stat = fs5.statSync(filePath);
|
|
113876
114320
|
} catch {
|
|
113877
114321
|
return base("unsupported", { warnings: [`\uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: ${filePath}`], unsupported: true, errored: true });
|
|
113878
114322
|
}
|
|
@@ -113891,7 +114335,7 @@ async function extractDocument(input, baseDir) {
|
|
|
113891
114335
|
warnings: ["\uD30C\uC77C\uC774 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4(0\uBC14\uC774\uD2B8). \uB0B4\uC6A9\uC774 \uC788\uB294 \uD30C\uC77C\uC744 \uC9C0\uC815\uD574 \uC8FC\uC138\uC694."],
|
|
113892
114336
|
unsupported: true
|
|
113893
114337
|
});
|
|
113894
|
-
const name =
|
|
114338
|
+
const name = path5.basename(filePath);
|
|
113895
114339
|
const bytes = stat.size;
|
|
113896
114340
|
if (IMAGE_RE.test(name)) {
|
|
113897
114341
|
return base("image", {
|
|
@@ -113905,7 +114349,7 @@ async function extractDocument(input, baseDir) {
|
|
|
113905
114349
|
if (TEXT_RE.test(name) || MD_RE.test(name)) {
|
|
113906
114350
|
let textBuf;
|
|
113907
114351
|
try {
|
|
113908
|
-
textBuf =
|
|
114352
|
+
textBuf = fs5.readFileSync(filePath);
|
|
113909
114353
|
} catch (e) {
|
|
113910
114354
|
return base("unsupported", { bytes, warnings: [`\uD14D\uC2A4\uD2B8 \uD30C\uC77C\uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${errMsg(e)}`], unsupported: true, errored: true });
|
|
113911
114355
|
}
|
|
@@ -113920,7 +114364,7 @@ async function extractDocument(input, baseDir) {
|
|
|
113920
114364
|
}
|
|
113921
114365
|
let buf;
|
|
113922
114366
|
try {
|
|
113923
|
-
buf =
|
|
114367
|
+
buf = fs5.readFileSync(filePath);
|
|
113924
114368
|
} catch (e) {
|
|
113925
114369
|
return base("unsupported", { bytes, warnings: [`\uD30C\uC77C\uC744 \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${errMsg(e)}`], unsupported: true, errored: true });
|
|
113926
114370
|
}
|
|
@@ -113932,7 +114376,7 @@ async function extractDocument(input, baseDir) {
|
|
|
113932
114376
|
return base("unsupported", {
|
|
113933
114377
|
bytes,
|
|
113934
114378
|
warnings: [
|
|
113935
|
-
`${
|
|
114379
|
+
`${path5.extname(name) || "\uC774 \uD615\uC2DD"}\uC740 \uC790\uB3D9 \uCD94\uCD9C\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. PDF \uB610\uB294 .docx/.hwp/.hwpx\uB85C \uB2E4\uC2DC \uC800\uC7A5\uD558\uAC70\uB098, \uB0B4\uC6A9\uC744 \uD14D\uC2A4\uD2B8\uB85C \uBCF5\uC0AC\uD574 \uBD99\uC5EC\uB123\uC5B4 \uC8FC\uC138\uC694.`
|
|
113936
114380
|
],
|
|
113937
114381
|
unsupported: true
|
|
113938
114382
|
});
|
|
@@ -114199,18 +114643,18 @@ function toCallToolResult(r) {
|
|
|
114199
114643
|
|
|
114200
114644
|
// packages/mcp-tools/src/bridge.ts
|
|
114201
114645
|
import { spawn, spawnSync } from "node:child_process";
|
|
114202
|
-
import
|
|
114203
|
-
import
|
|
114646
|
+
import fs6 from "node:fs";
|
|
114647
|
+
import path6 from "node:path";
|
|
114204
114648
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
114205
|
-
var __dirname =
|
|
114206
|
-
var REPO_ROOT =
|
|
114649
|
+
var __dirname = path6.dirname(fileURLToPath2(import.meta.url));
|
|
114650
|
+
var REPO_ROOT = path6.resolve(__dirname, "..", "..", "..");
|
|
114207
114651
|
var HEALTH_TIMEOUT_MS = 800;
|
|
114208
114652
|
var pendingStart = null;
|
|
114209
114653
|
function dashboardLogPath() {
|
|
114210
|
-
return
|
|
114654
|
+
return path6.join(getDataDir(), "server.log");
|
|
114211
114655
|
}
|
|
114212
114656
|
function launchdPlistPath() {
|
|
114213
|
-
return
|
|
114657
|
+
return path6.join(getDataDir(), "dashboard.launchd.plist");
|
|
114214
114658
|
}
|
|
114215
114659
|
function launchdLabel() {
|
|
114216
114660
|
let hash = 5381;
|
|
@@ -114306,18 +114750,18 @@ function spawnViaLaunchd(bin, args, cwd, log) {
|
|
|
114306
114750
|
const label = launchdLabel();
|
|
114307
114751
|
const plist = launchdPlistPath();
|
|
114308
114752
|
try {
|
|
114309
|
-
|
|
114753
|
+
fs6.writeFileSync(plist, renderLaunchdPlist(bin, args, cwd, log), "utf8");
|
|
114310
114754
|
spawnSync("launchctl", ["bootout", `${domain}/${label}`], { stdio: "ignore" });
|
|
114311
114755
|
const res = spawnSync("launchctl", ["bootstrap", domain, plist], {
|
|
114312
114756
|
encoding: "utf8",
|
|
114313
114757
|
timeout: 5e3
|
|
114314
114758
|
});
|
|
114315
114759
|
if (res.status === 0) return true;
|
|
114316
|
-
|
|
114760
|
+
fs6.appendFileSync(log, `[${(/* @__PURE__ */ new Date()).toISOString()}] launchctl bootstrap failed: ${res.stderr || res.stdout || res.status}
|
|
114317
114761
|
`);
|
|
114318
114762
|
} catch (e) {
|
|
114319
114763
|
try {
|
|
114320
|
-
|
|
114764
|
+
fs6.appendFileSync(log, `[${(/* @__PURE__ */ new Date()).toISOString()}] launchctl launch failed: ${e instanceof Error ? e.message : String(e)}
|
|
114321
114765
|
`);
|
|
114322
114766
|
} catch {
|
|
114323
114767
|
}
|
|
@@ -114343,16 +114787,16 @@ async function ensureServer(timeoutMs = 12e3) {
|
|
|
114343
114787
|
}
|
|
114344
114788
|
}
|
|
114345
114789
|
async function startServerBackground(timeoutMs) {
|
|
114346
|
-
const [bin, args, cwd] = BUNDLED ? [process.execPath, ["--experimental-sqlite",
|
|
114790
|
+
const [bin, args, cwd] = BUNDLED ? [process.execPath, ["--experimental-sqlite", path6.join(__dirname, "web.mjs")], __dirname] : [
|
|
114347
114791
|
process.execPath,
|
|
114348
|
-
["--no-warnings", "--experimental-sqlite", "--import", "tsx",
|
|
114792
|
+
["--no-warnings", "--experimental-sqlite", "--import", "tsx", path6.join(REPO_ROOT, "apps/web/src/index.ts")],
|
|
114349
114793
|
REPO_ROOT
|
|
114350
114794
|
];
|
|
114351
114795
|
const log = dashboardLogPath();
|
|
114352
114796
|
let logFd = null;
|
|
114353
114797
|
try {
|
|
114354
|
-
logFd =
|
|
114355
|
-
|
|
114798
|
+
logFd = fs6.openSync(log, "a");
|
|
114799
|
+
fs6.writeSync(logFd, `
|
|
114356
114800
|
[${(/* @__PURE__ */ new Date()).toISOString()}] CareerMate dashboard background launch
|
|
114357
114801
|
`);
|
|
114358
114802
|
} catch {
|
|
@@ -114365,7 +114809,7 @@ async function startServerBackground(timeoutMs) {
|
|
|
114365
114809
|
} finally {
|
|
114366
114810
|
if (logFd !== null) {
|
|
114367
114811
|
try {
|
|
114368
|
-
|
|
114812
|
+
fs6.closeSync(logFd);
|
|
114369
114813
|
} catch {
|
|
114370
114814
|
}
|
|
114371
114815
|
}
|
|
@@ -114378,7 +114822,7 @@ async function startServerBackground(timeoutMs) {
|
|
|
114378
114822
|
}
|
|
114379
114823
|
if (launchedViaLaunchd) {
|
|
114380
114824
|
try {
|
|
114381
|
-
|
|
114825
|
+
fs6.appendFileSync(log, `[${(/* @__PURE__ */ new Date()).toISOString()}] launchd did not produce a healthy server; falling back to detached spawn
|
|
114382
114826
|
`);
|
|
114383
114827
|
} catch {
|
|
114384
114828
|
}
|
|
@@ -114420,8 +114864,8 @@ async function resolveDashboardUrl(hash = "") {
|
|
|
114420
114864
|
}
|
|
114421
114865
|
|
|
114422
114866
|
// packages/mcp-tools/src/update.ts
|
|
114423
|
-
import
|
|
114424
|
-
import
|
|
114867
|
+
import fs7 from "node:fs";
|
|
114868
|
+
import path7 from "node:path";
|
|
114425
114869
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
114426
114870
|
import { spawn as spawn2 } from "node:child_process";
|
|
114427
114871
|
var REGISTRY_URL = "https://registry.npmjs.org/careermate/latest";
|
|
@@ -114429,7 +114873,7 @@ var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
|
114429
114873
|
var NULL_CACHE_TTL_MS = 30 * 60 * 1e3;
|
|
114430
114874
|
var FETCH_TIMEOUT_MS = 1500;
|
|
114431
114875
|
var INSTALL_TIMEOUT_MS = 12e4;
|
|
114432
|
-
var cacheFile = () =>
|
|
114876
|
+
var cacheFile = () => path7.join(getDataDir(), ".update-check.json");
|
|
114433
114877
|
function checkDisabled() {
|
|
114434
114878
|
const v = process.env.CAREERMATE_NO_UPDATE_CHECK?.trim().toLowerCase();
|
|
114435
114879
|
return v === "1" || v === "true";
|
|
@@ -114477,14 +114921,14 @@ function comparePrerelease(a, b) {
|
|
|
114477
114921
|
}
|
|
114478
114922
|
function readCache() {
|
|
114479
114923
|
try {
|
|
114480
|
-
return JSON.parse(
|
|
114924
|
+
return JSON.parse(fs7.readFileSync(cacheFile(), "utf8"));
|
|
114481
114925
|
} catch {
|
|
114482
114926
|
return null;
|
|
114483
114927
|
}
|
|
114484
114928
|
}
|
|
114485
114929
|
function writeCache(c) {
|
|
114486
114930
|
try {
|
|
114487
|
-
|
|
114931
|
+
fs7.writeFileSync(cacheFile(), JSON.stringify(c), "utf8");
|
|
114488
114932
|
} catch {
|
|
114489
114933
|
}
|
|
114490
114934
|
}
|
|
@@ -114515,13 +114959,13 @@ function refreshInBackground() {
|
|
|
114515
114959
|
refreshing = false;
|
|
114516
114960
|
});
|
|
114517
114961
|
}
|
|
114518
|
-
var __dirname2 =
|
|
114962
|
+
var __dirname2 = path7.dirname(fileURLToPath3(import.meta.url));
|
|
114519
114963
|
function installPrefix() {
|
|
114520
114964
|
if (!BUNDLED) return null;
|
|
114521
|
-
const pkgRoot =
|
|
114522
|
-
const parent =
|
|
114523
|
-
if (
|
|
114524
|
-
return
|
|
114965
|
+
const pkgRoot = path7.resolve(__dirname2, "..");
|
|
114966
|
+
const parent = path7.dirname(pkgRoot);
|
|
114967
|
+
if (path7.basename(parent) !== "node_modules") return null;
|
|
114968
|
+
return path7.dirname(parent);
|
|
114525
114969
|
}
|
|
114526
114970
|
function manualCommand() {
|
|
114527
114971
|
const prefix = installPrefix();
|
|
@@ -114654,13 +115098,13 @@ var DASHBOARD_URL = "http://127.0.0.1:4319";
|
|
|
114654
115098
|
function listInboxFiles(dir) {
|
|
114655
115099
|
let names;
|
|
114656
115100
|
try {
|
|
114657
|
-
names =
|
|
115101
|
+
names = fs8.readdirSync(dir);
|
|
114658
115102
|
} catch {
|
|
114659
115103
|
return [];
|
|
114660
115104
|
}
|
|
114661
115105
|
let realDir;
|
|
114662
115106
|
try {
|
|
114663
|
-
realDir =
|
|
115107
|
+
realDir = fs8.realpathSync.native(dir);
|
|
114664
115108
|
} catch {
|
|
114665
115109
|
realDir = dir;
|
|
114666
115110
|
}
|
|
@@ -114668,12 +115112,12 @@ function listInboxFiles(dir) {
|
|
|
114668
115112
|
const out = [];
|
|
114669
115113
|
for (const name of names) {
|
|
114670
115114
|
if (SKIP.test(name)) continue;
|
|
114671
|
-
const p =
|
|
115115
|
+
const p = path8.join(dir, name);
|
|
114672
115116
|
try {
|
|
114673
|
-
if (!
|
|
114674
|
-
const real =
|
|
114675
|
-
const rel =
|
|
114676
|
-
if (rel.startsWith("..") ||
|
|
115117
|
+
if (!fs8.statSync(p).isFile()) continue;
|
|
115118
|
+
const real = fs8.realpathSync.native(p);
|
|
115119
|
+
const rel = path8.relative(realDir, real);
|
|
115120
|
+
if (rel.startsWith("..") || path8.isAbsolute(rel)) continue;
|
|
114677
115121
|
out.push({ name, path: p });
|
|
114678
115122
|
} catch {
|
|
114679
115123
|
}
|
|
@@ -114701,10 +115145,10 @@ function pickRoute(ctx) {
|
|
|
114701
115145
|
return "write_cover_letter";
|
|
114702
115146
|
}
|
|
114703
115147
|
function writeExport(result2) {
|
|
114704
|
-
const filePath =
|
|
115148
|
+
const filePath = path8.join(getExportsDir(), result2.filename);
|
|
114705
115149
|
try {
|
|
114706
|
-
if (result2.bytes)
|
|
114707
|
-
else
|
|
115150
|
+
if (result2.bytes) fs8.writeFileSync(filePath, result2.bytes);
|
|
115151
|
+
else fs8.writeFileSync(filePath, result2.content, "utf8");
|
|
114708
115152
|
return { path: filePath };
|
|
114709
115153
|
} catch (e) {
|
|
114710
115154
|
return { error: `\uD30C\uC77C \uC800\uC7A5 \uC2E4\uD328: ${e instanceof Error ? e.message : e}` };
|
|
@@ -114724,11 +115168,11 @@ var TOOLS = [
|
|
|
114724
115168
|
handler: async (args) => {
|
|
114725
115169
|
const r = await extractDocument(args.path);
|
|
114726
115170
|
if (r.errored) {
|
|
114727
|
-
return fail(`'${
|
|
115171
|
+
return fail(`'${path8.basename(r.path)}'\uC744(\uB97C) \uC77D\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4.
|
|
114728
115172
|
${r.warnings.join("\n")}`);
|
|
114729
115173
|
}
|
|
114730
115174
|
if (r.unsupported) {
|
|
114731
|
-
return ok(`'${
|
|
115175
|
+
return ok(`'${path8.basename(r.path)}'\uC740(\uB294) \uD14D\uC2A4\uD2B8\uB85C \uCD94\uCD9C\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.
|
|
114732
115176
|
${r.warnings.join("\n")}`, {
|
|
114733
115177
|
path: r.path,
|
|
114734
115178
|
format: r.format,
|
|
@@ -114743,7 +115187,7 @@ ${r.warnings.join("\n")}`, {
|
|
|
114743
115187
|
truncated = true;
|
|
114744
115188
|
}
|
|
114745
115189
|
const head = [
|
|
114746
|
-
`'${
|
|
115190
|
+
`'${path8.basename(r.path)}'\uC5D0\uC11C \uD14D\uC2A4\uD2B8\uB97C \uCD94\uCD9C\uD588\uC2B5\uB2C8\uB2E4 (${r.format.toUpperCase()}, ${text.length.toLocaleString()}\uC790${truncated ? ", \uC798\uB9BC" : ""}).`,
|
|
114747
115191
|
...r.warnings,
|
|
114748
115192
|
"\uC774 \uB0B4\uC6A9\uC744 \uADFC\uAC70\uB85C \uC791\uC5C5\uD55C \uB4A4 \uACB0\uACFC\uB97C \uC54C\uB9DE\uC740 CareerMate \uB3C4\uAD6C\uB85C \uC800\uC7A5\uD558\uC138\uC694."
|
|
114749
115193
|
].join("\n");
|
|
@@ -114873,6 +115317,8 @@ ${lines}`;
|
|
|
114873
115317
|
},
|
|
114874
115318
|
{
|
|
114875
115319
|
name: "save_profile",
|
|
115320
|
+
idempotent: true,
|
|
115321
|
+
// 부분 업서트 — 같은 인자 재호출은 같은 결과
|
|
114876
115322
|
title: "\uD504\uB85C\uD544 \uC800\uC7A5",
|
|
114877
115323
|
description: "\uC0AC\uC6A9\uC790 \uD504\uB85C\uD544\uC744 \uC800\uC7A5\uD569\uB2C8\uB2E4. \uC804\uB2EC\uD55C \uD544\uB4DC\uB9CC \uAC31\uC2E0\uB418\uACE0 \uB098\uBA38\uC9C0\uB294 \uC720\uC9C0\uB429\uB2C8\uB2E4(\uBD80\uBD84 \uC800\uC7A5 \uC548\uC804). \uC774\uB825\uC11C\uB97C \uAD6C\uC870\uD654\uD55C \uB4A4 \uC774\uB984/\uD55C \uC904 \uC18C\uAC1C/\uD76C\uB9DD \uC9C1\uBB34/\uC120\uD638 \uBB38\uCCB4/\uAC15\uC870 \uD3EC\uC778\uD2B8 \uB4F1\uC744 \uCC44\uC6CC \uC800\uC7A5\uD558\uC138\uC694. \uC120\uD638 \uBB38\uCCB4(preferred_tone)\uC640 \uAC15\uC870 \uD3EC\uC778\uD2B8(emphasis_points)\uB294 \uC774\uD6C4 \uC790\uAE30\uC18C\uAC1C\uC11C \uC791\uC131 \uD488\uC9C8\uC5D0 \uC9C1\uC811 \uC601\uD5A5\uC744 \uC90D\uB2C8\uB2E4. \uD559\uB825(education)\xB7\uC790\uACA9\uC99D(certifications)\xB7\uC5B4\uD559\uC810\uC218(language_scores: \uD1A0\uC775\xB7\uC624\uD53D \uB4F1)\xB7\uC218\uC0C1(awards)\uC774 \uC774\uB825\uC11C\uC5D0 \uC788\uC73C\uBA74 \uAD6C\uC870\uD654\uD574 \uC800\uC7A5\uD558\uC138\uC694 \u2014 \uD55C\uAD6D \uC774\uB825\uC11C \uD575\uC2EC \uC2A4\uD399\uC774\uACE0, \uC800\uC7A5\uD558\uBA74 \uC774\uD6C4 \uC790\uC18C\uC11C\xB7\uC774\uB825\uC11C\uC5D0\uC11C \uC815\uD655\uD55C \uC218\uCE58(\uD559\uC810 3.8, \uD1A0\uC775 920)\uB97C \uC9C0\uC5B4\uB0B4\uC9C0 \uC54A\uACE0 \uADF8\uB300\uB85C \uC778\uC6A9\uD569\uB2C8\uB2E4.",
|
|
114878
115324
|
inputSchema: ProfileInputSchema.shape,
|
|
@@ -114911,6 +115357,7 @@ ${lines}`;
|
|
|
114911
115357
|
},
|
|
114912
115358
|
{
|
|
114913
115359
|
name: "delete_resume",
|
|
115360
|
+
destructive: true,
|
|
114914
115361
|
title: "\uC774\uB825\uC11C/\uBB38\uC11C \uC0AD\uC81C",
|
|
114915
115362
|
description: "\uC800\uC7A5\uB41C \uC774\uB825\uC11C\xB7\uACBD\uB825\uAE30\uC220\uC11C\xB7\uD3EC\uD2B8\uD3F4\uB9AC\uC624 \uB4F1 \uBB38\uC11C\uB97C \uC0AD\uC81C\uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uAC00 \uBA85\uD655\uD788 \uC0AD\uC81C\uB97C \uC694\uCCAD\uD588\uC744 \uB54C\uB9CC \uC0AC\uC6A9\uD558\uC138\uC694. \uBA3C\uC800 get_resumes\uB85C \uBAA9\uB85D\uC744 \uD655\uC778\uD558\uACE0 \uC5B4\uB5A4 \uBB38\uC11C\uC778\uC9C0 \uC0AC\uC6A9\uC790\uC640 \uD655\uC778\uD55C \uB4A4 \uD638\uCD9C\uD569\uB2C8\uB2E4. confirm\uC5D0\uB294 DELETE\uB97C \uB123\uC73C\uC138\uC694.",
|
|
114916
115363
|
inputSchema: {
|
|
@@ -114929,6 +115376,8 @@ ${lines}`;
|
|
|
114929
115376
|
/* ----------------------------------------------------------- experiences */
|
|
114930
115377
|
{
|
|
114931
115378
|
name: "add_experience",
|
|
115379
|
+
idempotent: true,
|
|
115380
|
+
// 회사·직무·입사일 키 업서트(adr_0003) — 재호출 안전
|
|
114932
115381
|
title: "\uACBD\uB825 \uCD94\uAC00",
|
|
114933
115382
|
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.",
|
|
114934
115383
|
inputSchema: ExperienceBatchInputSchema.shape,
|
|
@@ -114952,6 +115401,8 @@ ${lines}`;
|
|
|
114952
115401
|
/* -------------------------------------------------------------- projects */
|
|
114953
115402
|
{
|
|
114954
115403
|
name: "add_project",
|
|
115404
|
+
idempotent: true,
|
|
115405
|
+
// 이름 키 업서트 — 재호출 안전
|
|
114955
115406
|
title: "\uD504\uB85C\uC81D\uD2B8 \uCD94\uAC00",
|
|
114956
115407
|
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.",
|
|
114957
115408
|
inputSchema: ProjectBatchInputSchema.shape,
|
|
@@ -114975,6 +115426,8 @@ ${lines}`;
|
|
|
114975
115426
|
/* ---------------------------------------------------------------- skills */
|
|
114976
115427
|
{
|
|
114977
115428
|
name: "add_skill",
|
|
115429
|
+
idempotent: true,
|
|
115430
|
+
// 이름 키 업서트 — 재호출 안전
|
|
114978
115431
|
title: "\uAE30\uC220\uC2A4\uD0DD \uCD94\uAC00",
|
|
114979
115432
|
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.",
|
|
114980
115433
|
inputSchema: SkillBatchInputSchema.shape,
|
|
@@ -114997,6 +115450,7 @@ ${lines}`;
|
|
|
114997
115450
|
},
|
|
114998
115451
|
{
|
|
114999
115452
|
name: "delete_experience",
|
|
115453
|
+
destructive: true,
|
|
115000
115454
|
title: "\uACBD\uB825 \uD56D\uBAA9 \uC0AD\uC81C",
|
|
115001
115455
|
description: "\uAD6C\uC870\uD654\uB41C \uACBD\uB825(\uC9C1\uC7A5) \uD56D\uBAA9 \uD558\uB098\uB97C \uC0AD\uC81C\uD569\uB2C8\uB2E4. \uC798\uBABB \uCD94\uCD9C/\uC785\uB825\uB41C \uACBD\uB825\uC744 \uC9C0\uC6B8 \uB54C \uC0AC\uC6A9\uD558\uC138\uC694. \uBA3C\uC800 get_experiences\uB85C \uBAA9\uB85D\uACFC id\uB97C \uD655\uC778\uD558\uACE0 \uC0AC\uC6A9\uC790\uC640 \uD655\uC778\uD55C \uB4A4 \uD638\uCD9C\uD569\uB2C8\uB2E4. (\uB0B4\uC6A9 \uC218\uC815\uC740 add_experience\uB85C \uAC19\uC740 \uD56D\uBAA9\uC744 \uB2E4\uC2DC \uC800\uC7A5\uD558\uBA74 \uAC31\uC2E0\uB429\uB2C8\uB2E4.) confirm\uC5D0\uB294 DELETE\uB97C \uB123\uC73C\uC138\uC694.",
|
|
115002
115456
|
inputSchema: {
|
|
@@ -115014,6 +115468,7 @@ ${lines}`;
|
|
|
115014
115468
|
},
|
|
115015
115469
|
{
|
|
115016
115470
|
name: "delete_project",
|
|
115471
|
+
destructive: true,
|
|
115017
115472
|
title: "\uD504\uB85C\uC81D\uD2B8 \uD56D\uBAA9 \uC0AD\uC81C",
|
|
115018
115473
|
description: "\uAD6C\uC870\uD654\uB41C \uD504\uB85C\uC81D\uD2B8 \uD56D\uBAA9 \uD558\uB098\uB97C \uC0AD\uC81C\uD569\uB2C8\uB2E4. \uC798\uBABB \uCD94\uCD9C/\uC785\uB825\uB41C \uD504\uB85C\uC81D\uD2B8\uB97C \uC9C0\uC6B8 \uB54C \uC0AC\uC6A9\uD558\uC138\uC694. \uBA3C\uC800 get_projects\uB85C \uBAA9\uB85D\uACFC id\uB97C \uD655\uC778\uD558\uACE0 \uC0AC\uC6A9\uC790\uC640 \uD655\uC778\uD55C \uB4A4 \uD638\uCD9C\uD569\uB2C8\uB2E4. (\uB0B4\uC6A9 \uC218\uC815\uC740 add_project\uB85C \uAC19\uC740 \uD56D\uBAA9\uC744 \uB2E4\uC2DC \uC800\uC7A5\uD558\uBA74 \uAC31\uC2E0\uB429\uB2C8\uB2E4.) confirm\uC5D0\uB294 DELETE\uB97C \uB123\uC73C\uC138\uC694.",
|
|
115019
115474
|
inputSchema: {
|
|
@@ -115031,6 +115486,7 @@ ${lines}`;
|
|
|
115031
115486
|
},
|
|
115032
115487
|
{
|
|
115033
115488
|
name: "delete_skill",
|
|
115489
|
+
destructive: true,
|
|
115034
115490
|
title: "\uAE30\uC220\uC2A4\uD0DD \uD56D\uBAA9 \uC0AD\uC81C",
|
|
115035
115491
|
description: "\uAD6C\uC870\uD654\uB41C \uAE30\uC220\uC2A4\uD0DD \uD56D\uBAA9 \uD558\uB098\uB97C \uC0AD\uC81C\uD569\uB2C8\uB2E4. \uC798\uBABB \uCD94\uCD9C/\uC785\uB825\uB41C \uAE30\uC220\uC744 \uC9C0\uC6B8 \uB54C \uC0AC\uC6A9\uD558\uC138\uC694. \uBA3C\uC800 get_skills\uB85C \uBAA9\uB85D\uACFC id\uB97C \uD655\uC778\uD558\uACE0 \uC0AC\uC6A9\uC790\uC640 \uD655\uC778\uD55C \uB4A4 \uD638\uCD9C\uD569\uB2C8\uB2E4. (\uB0B4\uC6A9 \uC218\uC815\uC740 add_skill\uB85C \uAC19\uC740 \uD56D\uBAA9\uC744 \uB2E4\uC2DC \uC800\uC7A5\uD558\uBA74 \uAC31\uC2E0\uB429\uB2C8\uB2E4.) confirm\uC5D0\uB294 DELETE\uB97C \uB123\uC73C\uC138\uC694.",
|
|
115036
115492
|
inputSchema: {
|
|
@@ -115079,6 +115535,7 @@ ${lines}`;
|
|
|
115079
115535
|
},
|
|
115080
115536
|
{
|
|
115081
115537
|
name: "delete_cover_letter",
|
|
115538
|
+
destructive: true,
|
|
115082
115539
|
title: "\uC790\uAE30\uC18C\uAC1C\uC11C \uC0AD\uC81C",
|
|
115083
115540
|
description: "\uC0AC\uC6A9\uC790\uAC00 \uC800\uC7A5\uB41C \uC790\uAE30\uC18C\uAC1C\uC11C \uC0AD\uC81C\uB97C \uBA85\uD655\uD788 \uC694\uCCAD\uD588\uC744 \uB54C\uB9CC \uC0AC\uC6A9\uD569\uB2C8\uB2E4. \uBA3C\uC800 get_cover_letters\uB85C \uC804\uCCB4 \uBAA9\uB85D \uB610\uB294 \uACF5\uACE0\uBCC4 \uBAA9\uB85D\uC744 \uD655\uC778\uD558\uACE0, \uC0AD\uC81C\uD560 \uD56D\uBAA9\uC744 \uC0AC\uC6A9\uC790\uAC00 \uD655\uC778\uD55C \uB4A4 \uD638\uCD9C\uD558\uC138\uC694. \uC0AD\uC81C\uD558\uBA74 \uD574\uB2F9 \uC790\uAE30\uC18C\uAC1C\uC11C\uC758 \uBAA8\uB4E0 \uBC84\uC804\uC774 \uD568\uAED8 \uC0AD\uC81C\uB418\uBA70 \uB418\uB3CC\uB9B4 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. confirm\uC5D0\uB294 DELETE\uB97C \uB123\uC73C\uC138\uC694.",
|
|
115084
115541
|
inputSchema: {
|
|
@@ -115105,8 +115562,10 @@ ${lines}`;
|
|
|
115105
115562
|
/* ------------------------------------------------------------------ jobs */
|
|
115106
115563
|
{
|
|
115107
115564
|
name: "save_job_posting",
|
|
115565
|
+
idempotent: true,
|
|
115566
|
+
// 같은 url 업서트 — 재호출 안전
|
|
115108
115567
|
title: "\uCC44\uC6A9\uACF5\uACE0 \uC800\uC7A5",
|
|
115109
|
-
description: "\uCC44\uC6A9\uACF5\uACE0\uB97C \uC800\uC7A5\uD569\uB2C8\uB2E4(\uC788\uC73C\uBA74 \uAC31\uC2E0). company\uC640 position\uC740 \uD544\uC218\uC785\uB2C8\uB2E4. \uACF5\uACE0 \uC6D0\uBB38\uC740 description\uC5D0, \uD575\uC2EC \uC790\uACA9\uC694\uAC74/\uC6B0\uB300\uC0AC\uD56D\uC740 requirements \uBC30\uC5F4\uC5D0, \uD575\uC2EC \uD0A4\uC6CC\uB4DC\uB294 keywords\uC5D0 \uC815\uB9AC\uD574 \uB123\uC73C\uBA74 \uC774\uD6C4 \uC801\uD569\uB3C4 \uBD84\uC11D/\uC790\uC18C\uC11C \uC791\uC131\uC5D0 \uD65C\uC6A9\uB429\uB2C8\uB2E4. \uD68C\uC0AC\uB97C \uB9AC\uC11C\uCE58\uD588\uB2E4\uBA74 \uC0AC\uC5C5\uAC1C\uC694\xB7\uBBF8\uC158\uC740 company_overview, \uD68C\uC0AC\uAC00 \uAC15\uC870\uD558\uB294 \uC778\uC7AC\uC0C1\uC740 talent_profile, \uD575\uC2EC\uAC00\uCE58\uB294 core_values\uC5D0 \uB123\uC73C\uC138\uC694 \u2014 \uD55C\uAD6D \uC790\uC18C\uC11C\xB7\uBA74\uC811\uC740 \uC778\uC7AC\uC0C1/\uD575\uC2EC\uAC00\uCE58 \uC815\uB82C\uC774 \uD575\uC2EC\uC774\uB77C \uC800\uC7A5\uD574\uB450\uBA74 \uC774\uD6C4 \uC791\uC131\xB7\uBA74\uC811 \uC900\uBE44\uC5D0\uC11C \uADF8\uB300\uB85C \uB04C\uC5B4\uB2E4 \uC501\uB2C8\uB2E4. \uAC19\uC740 url\uC774\uBA74 \uC911\uBCF5 \uC0DD\uC131 \uC5C6\uC774 \uAC31\uC2E0\uB429\uB2C8\uB2E4. \uC800\uC7A5 \uC2DC \uC9C0\uC6D0(application) \uD56D\uBAA9\uC774 \uC790\uB3D9\uC73C\uB85C \uC0DD\uC131\uB429\uB2C8\uB2E4.",
|
|
115568
|
+
description: "\uCC44\uC6A9\uACF5\uACE0\uB97C \uC800\uC7A5\uD569\uB2C8\uB2E4(\uC788\uC73C\uBA74 \uAC31\uC2E0). company\uC640 position\uC740 \uD544\uC218\uC785\uB2C8\uB2E4. \uACF5\uACE0 \uC6D0\uBB38\uC740 description\uC5D0, \uD575\uC2EC \uC790\uACA9\uC694\uAC74/\uC6B0\uB300\uC0AC\uD56D\uC740 requirements \uBC30\uC5F4\uC5D0, \uD575\uC2EC \uD0A4\uC6CC\uB4DC\uB294 keywords\uC5D0 \uC815\uB9AC\uD574 \uB123\uC73C\uBA74 \uC774\uD6C4 \uC801\uD569\uB3C4 \uBD84\uC11D/\uC790\uC18C\uC11C \uC791\uC131\uC5D0 \uD65C\uC6A9\uB429\uB2C8\uB2E4. \uD68C\uC0AC\uB97C \uB9AC\uC11C\uCE58\uD588\uB2E4\uBA74 \uC0AC\uC5C5\uAC1C\uC694\xB7\uBBF8\uC158\uC740 company_overview, \uD68C\uC0AC\uAC00 \uAC15\uC870\uD558\uB294 \uC778\uC7AC\uC0C1\uC740 talent_profile, \uD575\uC2EC\uAC00\uCE58\uB294 core_values\uC5D0 \uB123\uC73C\uC138\uC694 \u2014 \uD55C\uAD6D \uC790\uC18C\uC11C\xB7\uBA74\uC811\uC740 \uC778\uC7AC\uC0C1/\uD575\uC2EC\uAC00\uCE58 \uC815\uB82C\uC774 \uD575\uC2EC\uC774\uB77C \uC800\uC7A5\uD574\uB450\uBA74 \uC774\uD6C4 \uC791\uC131\xB7\uBA74\uC811 \uC900\uBE44\uC5D0\uC11C \uADF8\uB300\uB85C \uB04C\uC5B4\uB2E4 \uC501\uB2C8\uB2E4. \uD68C\uC0AC \uD3C9\uD310(\uD3C9\uC810\xB7\uC6CC\uB77C\uBC38\xB7\uBB38\uD654 \uB9AC\uC2A4\uD06C \uB4F1)\uC744 \uB9AC\uC11C\uCE58\uD588\uB2E4\uBA74 reputation\uC5D0 \uC694\uC57D(\uCD9C\uCC98\xB7\uCD5C\uADFC\uC131 \uD45C\uAE30)\uC744 \uB123\uC73C\uBA74 \uC624\uD37C \uD310\uB2E8\xB7\uBA74\uC811\uC5D0 \uD65C\uC6A9\uB429\uB2C8\uB2E4. \uD68C\uC0AC \uC9C0\uC815 \uC790\uC18C\uC11C \uBB38\uD56D\xB7\uAE00\uC790\uC218\uAC00 \uC788\uC73C\uBA74 questions \uBC30\uC5F4\uC5D0 \uAD6C\uC870\uD654 \uC800\uC7A5\uD558\uC138\uC694(question \uD544\uC218, max_chars/min_chars/count_mode). \uC774\uD6C4 \uC790\uC18C\uC11C \uC791\uC131 \uC2DC \uBB38\uD56D\uBCC4\uB85C validate_cover_letter(min_chars/max_chars/count_mode)\uB85C \uD55C\uB3C4\uB97C \uC810\uAC80\uD569\uB2C8\uB2E4. \uBA74\uC811\xB7\uC778\uC801\uC131\xB7\uBC1C\uD45C \uB4F1 \uC804\uD615 \uC77C\uC815\uC744 \uBC1B\uC73C\uBA74 schedule \uBC30\uC5F4\uC5D0 \uAD6C\uC870\uD654 \uC800\uC7A5\uD558\uC138\uC694(label\xB7date \uD544\uC218, time \uC120\uD0DD; \uC11C\uB958 \uB9C8\uAC10\uC740 deadline \uD544\uB4DC). \uBA74\uC811\uCD08\uB300 \uBA54\uC77C\uC744 \uC0AC\uC6A9\uC790\uAC00 \uBD99\uC5EC\uB123\uC73C\uBA74 \uB0A0\uC9DC\xB7\uC2DC\uAC04\uC744 \uCD94\uCD9C\uD574 \uC800\uC7A5\uD558\uACE0, \uAC19\uC740 \uB0A0 \uB2E4\uB978 \uC77C\uC815\uACFC \uACB9\uCE58\uBA74 \uC54C\uB824\uC8FC\uC138\uC694. \uAC19\uC740 url\uC774\uBA74 \uC911\uBCF5 \uC0DD\uC131 \uC5C6\uC774 \uAC31\uC2E0\uB429\uB2C8\uB2E4. \uC800\uC7A5 \uC2DC \uC9C0\uC6D0(application) \uD56D\uBAA9\uC774 \uC790\uB3D9\uC73C\uB85C \uC0DD\uC131\uB429\uB2C8\uB2E4.",
|
|
115110
115569
|
inputSchema: JobInputSchema.shape,
|
|
115111
115570
|
handler: (args) => {
|
|
115112
115571
|
const { job } = saveJobPosting(args);
|
|
@@ -115152,6 +115611,7 @@ ${lines}`;
|
|
|
115152
115611
|
},
|
|
115153
115612
|
{
|
|
115154
115613
|
name: "delete_job_posting",
|
|
115614
|
+
destructive: true,
|
|
115155
115615
|
title: "\uCC44\uC6A9\uACF5\uACE0 \uC0AD\uC81C",
|
|
115156
115616
|
description: "\uC0AC\uC6A9\uC790\uAC00 \uC800\uC7A5\uB41C \uCC44\uC6A9\uACF5\uACE0 \uC0AD\uC81C\uB97C \uBA85\uD655\uD788 \uC694\uCCAD\uD588\uC744 \uB54C\uB9CC \uC0AC\uC6A9\uD569\uB2C8\uB2E4. \uBA3C\uC800 list_jobs\uB85C \uC804\uCCB4 \uACF5\uACE0 \uBAA9\uB85D\uC744 \uD655\uC778\uD558\uACE0, \uC0AD\uC81C\uD560 \uACF5\uACE0\uB97C \uC0AC\uC6A9\uC790\uAC00 \uD655\uC778\uD55C \uB4A4 \uD638\uCD9C\uD558\uC138\uC694. \uC0AD\uC81C\uD558\uBA74 \uC5F0\uACB0\uB41C \uC9C0\uC6D0 \uC0C1\uD0DC\xB7\uC801\uD569\uB3C4 \uBD84\uC11D\xB7\uBA74\uC811 \uC900\uBE44\uAC00 \uD568\uAED8 \uC0AD\uC81C\uB429\uB2C8\uB2E4. \uC5F0\uACB0\uB41C \uC790\uAE30\uC18C\uAC1C\uC11C\uB294 \uC0AD\uC81C\uD558\uC9C0 \uC54A\uACE0 \uACF5\uACE0 \uC5F0\uACB0\uB9CC \uD574\uC81C\uD569\uB2C8\uB2E4. confirm\uC5D0\uB294 DELETE\uB97C \uB123\uC73C\uC138\uC694.",
|
|
115157
115617
|
inputSchema: {
|
|
@@ -115237,6 +115697,8 @@ ${lines}`;
|
|
|
115237
115697
|
},
|
|
115238
115698
|
{
|
|
115239
115699
|
name: "save_fit_analysis",
|
|
115700
|
+
idempotent: true,
|
|
115701
|
+
// 공고당 1건 업서트
|
|
115240
115702
|
title: "\uC801\uD569\uB3C4 \uBD84\uC11D \uACB0\uACFC \uC800\uC7A5",
|
|
115241
115703
|
description: "\uACF5\uACE0\uC640 \uC0AC\uC6A9\uC790 \uC815\uBCF4\uB97C \uBE44\uAD50\uD574 \uB2F9\uC2E0(AI)\uC774 \uB3C4\uCD9C\uD55C \uC801\uD569\uB3C4 \uBD84\uC11D\uC744 \uC800\uC7A5\uD569\uB2C8\uB2E4. job_id\uB294 \uD544\uC218\uC774\uBA70 \uBA3C\uC800 save_job_posting\uC73C\uB85C \uACF5\uACE0\uAC00 \uC800\uC7A5\uB418\uC5B4 \uC788\uC5B4\uC57C \uD569\uB2C8\uB2E4. score(0~100), summary, strengths(\uAC15\uC810), gaps(\uBCF4\uC644 \uD544\uC694), matched/missing_keywords, recommendations(\uC790\uC18C\uC11C\xB7\uC9C0\uC6D0 \uC804\uB7B5 \uC81C\uC548)\uB97C \uCC44\uC6CC \uC800\uC7A5\uD558\uC138\uC694. \uAC19\uC740 \uACF5\uACE0\uC5D0 \uB2E4\uC2DC \uC800\uC7A5\uD558\uBA74 \uAC31\uC2E0\uB429\uB2C8\uB2E4.",
|
|
115242
115704
|
inputSchema: FitAnalysisInputSchema.shape,
|
|
@@ -115281,27 +115743,41 @@ ${lines}`;
|
|
|
115281
115743
|
{
|
|
115282
115744
|
name: "update_application_status",
|
|
115283
115745
|
title: "\uC9C0\uC6D0 \uC0C1\uD0DC \uBCC0\uACBD",
|
|
115284
|
-
description: `\uC9C0\uC6D0 \uC0C1\uD0DC\uB97C \uBCC0\uACBD\uD569\uB2C8\uB2E4. \uAC00\uB2A5\uD55C \uC0C1\uD0DC: ${STATUS_LIST}. '\uC11C\uB958 \uD569\uACA9(document_passed)' \uC774\uC0C1\uC73C\uB85C \uBC14\uB00C\uBA74 \uBA74\uC811 \uC900\uBE44\uB97C \uC81C\uC548\uD558\uB294 \uD78C\uD2B8\uB97C \uD568\uAED8 \uB3CC\uB824\uC90D\uB2C8\uB2E4. note\uC5D0 \uBCC0\uACBD \uC0AC\uC720\uB97C \uB0A8\uAE38 \uC218 \uC788\uC2B5\uB2C8\uB2E4.`,
|
|
115746
|
+
description: `\uC9C0\uC6D0 \uC0C1\uD0DC\uB97C \uBCC0\uACBD\uD569\uB2C8\uB2E4. \uAC00\uB2A5\uD55C \uC0C1\uD0DC: ${STATUS_LIST}. '\uC11C\uB958 \uD569\uACA9(document_passed)' \uC774\uC0C1\uC73C\uB85C \uBC14\uB00C\uBA74 \uBA74\uC811 \uC900\uBE44\uB97C \uC81C\uC548\uD558\uB294 \uD78C\uD2B8\uB97C \uD568\uAED8 \uB3CC\uB824\uC90D\uB2C8\uB2E4. note\uC5D0 \uBCC0\uACBD \uC0AC\uC720\uB97C \uB0A8\uAE38 \uC218 \uC788\uC2B5\uB2C8\uB2E4. '\uBD88\uD569\uACA9(rejected)'\uC73C\uB85C \uBC14\uAFC0 \uB54C\uB294 rejected_stage\uC5D0 \uC5B4\uB290 \uB2E8\uACC4\uC5D0\uC11C \uC544\uC27D\uAC8C \uB410\uB294\uC9C0 \uD568\uAED8 \uB0A8\uAE30\uC138\uC694 \u2014 \uC11C\uB958=document, \uC778\uC801\uC131\xB7AI\uC5ED\uAC80=assessment, \uBA74\uC811=interview, \uCD5C\uC885\xB7\uCC98\uC6B0=final, \uAE30\uD0C0=other. \uD0C8\uB77D \uC0AC\uC720\uB97C \uC54C\uB824\uC8FC\uB294 \uAE30\uC5C5\uC740 \uB4DC\uBB3C\uC5B4, \uC774 \uC790\uAC00 \uAE30\uB85D\uC774 \uC313\uC774\uBA74 '\uC11C\uB958\uB294 \uBD99\uB294\uB370 \uBA74\uC811\uC5D0\uC11C \uB5A8\uC5B4\uC9C4\uB2E4' \uAC19\uC740 \uD328\uD134\uC774 \uB85C\uCEEC \uB370\uC774\uD130\uB85C \uB4DC\uB7EC\uB0A9\uB2C8\uB2E4(get_pipeline_stats).`,
|
|
115285
115747
|
inputSchema: {
|
|
115286
115748
|
job_id: external_exports.string(),
|
|
115287
115749
|
status: external_exports.enum(APPLICATION_STATUSES),
|
|
115288
115750
|
note: external_exports.string().optional(),
|
|
115289
|
-
submission: ApplicationSubmissionSchema.optional()
|
|
115751
|
+
submission: ApplicationSubmissionSchema.optional(),
|
|
115752
|
+
rejected_stage: external_exports.enum(REJECTED_STAGES).optional().describe(
|
|
115753
|
+
"\uD0C8\uB77D \uD68C\uACE0 \u2014 'rejected'\uB85C \uBC14\uAFC0 \uB54C \uC5B4\uB290 \uB2E8\uACC4\uC5D0\uC11C \uD0C8\uB77D\uD588\uB294\uC9C0: \uC11C\uB958=document, \uC778\uC801\uC131\xB7AI\uC5ED\uAC80=assessment, \uBA74\uC811=interview, \uCD5C\uC885\xB7\uCC98\uC6B0=final, \uAE30\uD0C0=other"
|
|
115754
|
+
)
|
|
115290
115755
|
},
|
|
115291
115756
|
handler: (args) => {
|
|
115292
115757
|
try {
|
|
115293
|
-
const res = updateApplicationStatus(args.job_id, args.status, args.note, args.submission);
|
|
115294
|
-
const
|
|
115758
|
+
const res = updateApplicationStatus(args.job_id, args.status, args.note, args.submission, args.rejected_stage);
|
|
115759
|
+
const needsRetro = args.status === "rejected" && !res.application.rejected_stage;
|
|
115760
|
+
const retro_prompt = "\uC5B4\uB290 \uB2E8\uACC4\uC5D0\uC11C \uC544\uC27D\uAC8C \uB410\uB294\uC9C0(\uC11C\uB958/\uC778\uC801\uC131/\uBA74\uC811/\uCD5C\uC885)\uC640 \uBC30\uC6B4 \uC810\uC744 \uB0A8\uACA8\uB450\uBA74 \uB2E4\uC74C \uC9C0\uC6D0 \uC804\uB7B5\uC5D0 \uC4F8 \uC218 \uC788\uC5B4\uC694. \uAE30\uB85D\uD560\uAE4C\uC694?";
|
|
115761
|
+
const base = `\uC9C0\uC6D0 \uC0C1\uD0DC\uB97C '${APPLICATION_STATUS_LABELS[args.status]}'(\uC73C)\uB85C \uBC14\uAFE8\uC5B4\uC694.`;
|
|
115762
|
+
const user_message = base + (res.hint ? `
|
|
115763
|
+
|
|
115764
|
+
${res.hint}` : needsRetro ? `
|
|
115295
115765
|
|
|
115296
|
-
${
|
|
115766
|
+
${retro_prompt}` : "");
|
|
115767
|
+
const text = needsRetro ? `${user_message}
|
|
115768
|
+
|
|
115769
|
+
(AI \uC548\uB0B4: \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC5B4\uB290 \uB2E8\uACC4\uC5D0\uC11C \uB5A8\uC5B4\uC84C\uB294\uC9C0\uC640 \uBC30\uC6B4 \uC810\uC744 \uBB3C\uC5B4, rejected_stage\uC640 note\uB85C \uD568\uAED8 \uAE30\uB85D\uD558\uB3C4\uB85D \uC81C\uC548\uD558\uC138\uC694.)` : user_message;
|
|
115297
115770
|
return ok(
|
|
115298
|
-
|
|
115771
|
+
text,
|
|
115299
115772
|
{
|
|
115300
115773
|
...res,
|
|
115301
115774
|
user_message,
|
|
115302
115775
|
suggested_next_action: res.hint ? {
|
|
115303
115776
|
prompt: res.hint,
|
|
115304
115777
|
next_workflow: "prepare_interview"
|
|
115778
|
+
} : needsRetro ? {
|
|
115779
|
+
prompt: retro_prompt,
|
|
115780
|
+
next_tool: "update_application_status"
|
|
115305
115781
|
} : null
|
|
115306
115782
|
}
|
|
115307
115783
|
);
|
|
@@ -115313,6 +115789,8 @@ ${res.hint}` : "");
|
|
|
115313
115789
|
/* ---------------------------------------------------------- interview prep */
|
|
115314
115790
|
{
|
|
115315
115791
|
name: "save_interview_prep",
|
|
115792
|
+
idempotent: true,
|
|
115793
|
+
// 공고당 1건 업서트(debrief는 병합)
|
|
115316
115794
|
title: "\uBA74\uC811 \uC900\uBE44 \uC790\uB8CC \uC800\uC7A5",
|
|
115317
115795
|
description: "\uC608\uC0C1 \uBA74\uC811 \uC9C8\uBB38, \uAF2C\uB9AC \uC9C8\uBB38, STAR \uB2F5\uBCC0 \uAC00\uC774\uB4DC, 1\uBD84 \uC790\uAE30\uC18C\uAC1C \uCD08\uC548 \uB4F1 \uD574\uB2F9 \uACF5\uACE0 \uAE30\uC900 \uBA74\uC811 \uC900\uBE44 \uC790\uB8CC\uB97C \uC800\uC7A5\uD569\uB2C8\uB2E4. \uACF5\uACE0/\uC9C1\uBB34/\uC790\uAE30\uC18C\uAC1C\uC11C\uB97C \uADFC\uAC70\uB85C \uB2F9\uC2E0(AI)\uC774 \uC0DD\uC131\uD55C \uC790\uB8CC\uB97C \uC800\uC7A5\uD558\uB294 \uB370 \uC0AC\uC6A9\uD569\uB2C8\uB2E4. \uC9C8\uBB38\uC740 \uB450 \uAC08\uB798\uB85C \uC900\uBE44\uD558\uC138\uC694 \u2014 \uAC01 \uC9C8\uBB38\uC758 category\uB97C 'technical'(\uAE30\uC220\xB7\uC9C1\uBB34 1\uCC28 \uBA74\uC811) \uB610\uB294 'behavioral'(\uC778\uC131\xB7\uCEEC\uCC98\uD54F\xB7\uC784\uC6D0 2\uCC28 \uBA74\uC811, \uC790\uAE30\uC18C\uAC1C\uC11C\xB7\uD504\uB85C\uD544 \uAE30\uBC18)\uB85C \uC9C0\uC815\uD569\uB2C8\uB2E4. \uAC00\uB2A5\uD558\uBA74 \uB450 \uAC08\uB798 \uBAA8\uB450 \uCC44\uC6CC \uD55C \uBC88\uC5D0 \uC800\uC7A5\uD558\uC138\uC694(\uB300\uC2DC\uBCF4\uB4DC\uAC00 \uAE30\uC220/\uC778\uC131\xB7\uCEEC\uCC98\uD54F \uD0ED\uC73C\uB85C \uB098\uB220 \uBCF4\uC5EC\uC90D\uB2C8\uB2E4). \uBA74\uC811\uC744 \uBCF8 \uB4A4\uC5D0\uB294 \uAC19\uC740 \uB3C4\uAD6C\uC5D0 debrief(\uBC1B\uC740 \uC9C8\uBB38 asked_questions\xB7\uC798\uB41C \uC810 went_well\xB7\uAC1C\uC120\uC810 to_improve\xB7\uB2E4\uC74C \uB77C\uC6B4\uB4DC \uD3EC\uCEE4\uC2A4 next_round_focus\xB7\uCCB4\uAC10 \uBD84\uC704\uAE30 sentiment)\uB97C \uCC44\uC6CC \uC800\uC7A5\uD558\uBA74 \uB2E4\uC74C \uB77C\uC6B4\uB4DC \uC900\uBE44\uC640 \uC77C\uAD00\uC131 \uC810\uAC80\uC5D0 \uADF8\uB300\uB85C \uC774\uC5B4\uC9D1\uB2C8\uB2E4(\uBA74\uC811 \uC804 \uC900\uBE44\uC640 \uBA74\uC811 \uD6C4 \uB514\uBE0C\uB9AC\uD504\uAC00 \uD55C \uACF5\uACE0\uC5D0 \uD568\uAED8 \uC313\uC785\uB2C8\uB2E4). job_id\uB294 \uD544\uC218\uC785\uB2C8\uB2E4. \uAC19\uC740 \uACF5\uACE0\uC5D0 \uB2E4\uC2DC \uC800\uC7A5\uD558\uBA74 \uAC31\uC2E0\uB429\uB2C8\uB2E4(debrief\uB294 \uAE30\uC874 \uAC12\uACFC \uBCD1\uD569\uB418\uC5B4 \uAE30\uC874 \uD544\uB4DC\uB97C \uC9C0\uC6B0\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4).",
|
|
115318
115796
|
inputSchema: InterviewPrepInputSchema.shape,
|
|
@@ -115446,20 +115924,22 @@ ${res.hint}` : "");
|
|
|
115446
115924
|
{
|
|
115447
115925
|
name: "get_followups",
|
|
115448
115926
|
title: "\uD6C4\uC18D \uC870\uCE58 \uC54C\uB9BC(\uB193\uCE5C \uC9C0\uC6D0\xB7\uB9C8\uAC10\xB7\uBA74\uC811\uC900\uBE44)",
|
|
115449
|
-
description: '\uC9C0\uAE08 \uCC59\uACA8\uC57C \uD560 \uAC83\uB4E4\uC744 \uD55C \uBC88\uC5D0 \uB3CC\uB824\uC90D\uB2C8\uB2E4: \u2460 \uC751\uB2F5 \uC5C6\uC774 \uC624\uB798\uB41C \uC9C0\uC6D0(\uC9C0\uC6D0 \uD6C4 \uBB34\uC751\uB2F5\xB7\uC11C\uB958\uD569\uACA9 \uD6C4 \uC77C\uC815\uB300\uAE30\xB7\uBA74\uC811 \uD6C4 \uACB0\uACFC\uB300\uAE30) \u2461 \uC784\uBC15\uD588\uAC70\uB098 \uC9C0\uB09C \uC9C0\uC6D0 \uB9C8\uAC10(\uC9C0\uC6D0 \uC804 \uB2E8\uACC4) \u2462 \uD569\uACA9\uD588\uB294\uB370 \uC544\uC9C1 \uBA74\uC811 \uC900\uBE44\uAC00 \uC5C6\uB294 \uACF5\uACE0. \uC0AC\uC6A9\uC790\uAC00 "\uB0B4 \uC9C0\uC6D0 \uD604\uD669 \uC5B4\uB54C?", "\uBB50 \uCC59\uACA8\uC57C \uD574?", "\uD6C4\uC18D \uC5F0\uB77D\uD560 \uAC70 \uC788\uC5B4?"\uB77C\uACE0 \uBB3B\uAC70\uB098, \uC138\uC158\uC744 \uC774\uC5B4\uAC00\uBA70 \uB193\uCE5C \uAC8C \uC5C6\uB294\uC9C0 \uBA3C\uC800 \uC810\uAC80\uD560 \uB54C \uC0AC\uC6A9\uD558\uC138\uC694. \uC77D\uAE30 \uC804\uC6A9\uC785\uB2C8\uB2E4. \uC751\uB2F5\uC758 reason\uC740 \uC0AC\uC6A9\uC790 \uC5B8\uC5B4\uB85C \uD480\uC5B4 \uC804\uD558\uACE0, \uD6C4\uC18D \uBB38\uC758\uB294 \uAC15\uC694\uD558\uC9C0 \uB9D0\uACE0 \uC120\uD0DD\uC9C0\uB85C \uC81C\uC548\uD558\uC138\uC694(\uCC44\uC6A9 \uAD00\uD589\uC0C1 \uACFC\uD55C \uB3C5\uCD09\uC740 \uC5ED\uD6A8\uACFC).',
|
|
115927
|
+
description: '\uC9C0\uAE08 \uCC59\uACA8\uC57C \uD560 \uAC83\uB4E4\uC744 \uD55C \uBC88\uC5D0 \uB3CC\uB824\uC90D\uB2C8\uB2E4: \u2460 \uC751\uB2F5 \uC5C6\uC774 \uC624\uB798\uB41C \uC9C0\uC6D0(\uC9C0\uC6D0 \uD6C4 \uBB34\uC751\uB2F5\xB7\uC11C\uB958\uD569\uACA9 \uD6C4 \uC77C\uC815\uB300\uAE30\xB7\uBA74\uC811 \uD6C4 \uACB0\uACFC\uB300\uAE30) \u2461 \uC784\uBC15\uD588\uAC70\uB098 \uC9C0\uB09C \uC9C0\uC6D0 \uB9C8\uAC10(\uC9C0\uC6D0 \uC804 \uB2E8\uACC4) \u2462 \uD569\uACA9\uD588\uB294\uB370 \uC544\uC9C1 \uBA74\uC811 \uC900\uBE44\uAC00 \uC5C6\uB294 \uACF5\uACE0 \u2463 \uC624\uB298~7\uC77C \uB0B4 \uB2E4\uAC00\uC624\uB294 \uC804\uD615 \uC77C\uC815(\uBA74\uC811\xB7\uC778\uC801\uC131\xB7\uBC1C\uD45C; `upcoming_schedule`\uC5D0 \uAC01 \uC77C\uC815\uC758 D-day) \u2464 \uC11C\uB85C \uB2E4\uB978 \uACF5\uACE0\uC758 \uC77C\uC815\uC774 \uAC19\uC740 \uB0A0\uC9DC\uC5D0 \uACB9\uCE60 \uB54C(`schedule_conflicts` \u2014 \uAC19\uC740 \uACF5\uACE0\uC758 \uC5F0\uC18D \uB2E8\uACC4\uB294 \uCDA9\uB3CC\uC774 \uC544\uB2C8\uACE0, \uC11C\uB85C \uB2E4\uB978 \uACF5\uACE0 2\uAC74 \uC774\uC0C1\uC774 \uD55C \uB0A0\uC5D0 \uBAB0\uB9B4 \uB54C\uB9CC; \uC788\uC73C\uBA74 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC54C\uB824 \uC870\uC815 \uC81C\uC548). \uC0AC\uC6A9\uC790\uAC00 "\uB0B4 \uC9C0\uC6D0 \uD604\uD669 \uC5B4\uB54C?", "\uBB50 \uCC59\uACA8\uC57C \uD574?", "\uC774\uBC88 \uC8FC \uC77C\uC815 \uBB50 \uC788\uC5B4?", "\uD6C4\uC18D \uC5F0\uB77D\uD560 \uAC70 \uC788\uC5B4?"\uB77C\uACE0 \uBB3B\uAC70\uB098, \uC138\uC158\uC744 \uC774\uC5B4\uAC00\uBA70 \uB193\uCE5C \uAC8C \uC5C6\uB294\uC9C0 \uBA3C\uC800 \uC810\uAC80\uD560 \uB54C \uC0AC\uC6A9\uD558\uC138\uC694. \uC77D\uAE30 \uC804\uC6A9\uC785\uB2C8\uB2E4. \uC9C0\uC6D0(applied) \uD56D\uBAA9\uC5D0\uB294 \uACB0\uC815\uB860 \uD314\uB85C\uC5C5 \uD0C0\uC774\uBC0D\uC774 \uBD99\uC2B5\uB2C8\uB2E4: `followup_timing="due"`\uB294 \uC9C0\uC6D0 \uD6C4 5~7\uC601\uC5C5\uC77C(\uC8FC\uB9D0 \uC81C\uC678)\uB85C \uC815\uC911\uD55C \uD6C4\uC18D \uBB38\uC758 \uC801\uAE30, `"overdue"`\uB294 8\uC601\uC5C5\uC77C \uC774\uC0C1\uC73C\uB85C \uC801\uAE30\uAC00 \uC9C0\uB0AC\uB2E4\uB294 \uB73B\uC774\uBA70, `business_days_since`\uB294 \uACBD\uACFC \uC601\uC5C5\uC77C \uC218\uC785\uB2C8\uB2E4. \uB2EC\uB825\uC77C 45\uC77C \uC774\uC0C1 \uBB34\uC751\uB2F5\uC774\uBA74 `suggest_on_hold=true`\uAC00 \uBD99\uC73C\uB2C8 "\uBCF4\uB958(on_hold)\uB85C \uC62E\uAE38\uAE4C\uC694?"\uB77C\uACE0 \uC81C\uC548\uD558\uC138\uC694. \uC751\uB2F5\uC758 reason\uC740 \uC0AC\uC6A9\uC790 \uC5B8\uC5B4\uB85C \uD480\uC5B4 \uC804\uD558\uACE0, \uD6C4\uC18D \uBB38\uC758\uB294 \uAC15\uC694\uD558\uC9C0 \uB9D0\uACE0 \uC120\uD0DD\uC9C0\uB85C \uC81C\uC548\uD558\uC138\uC694(\uCC44\uC6A9 \uAD00\uD589\uC0C1 \uACFC\uD55C \uB3C5\uCD09\uC740 \uC5ED\uD6A8\uACFC \u2014 \uBB38\uC758\uB294 \uC815\uC911\uD788 1\uD68C).',
|
|
115450
115928
|
inputSchema: {},
|
|
115451
115929
|
readOnly: true,
|
|
115452
115930
|
handler: () => {
|
|
115453
115931
|
const d = getActionDigest();
|
|
115454
|
-
const n = d.followups.length + d.deadlines.length + d.interview_todo.length;
|
|
115455
|
-
const
|
|
115932
|
+
const n = d.followups.length + d.deadlines.length + d.interview_todo.length + d.upcoming_schedule.length;
|
|
115933
|
+
const parts = [`\uD6C4\uC18D ${d.followups.length}`, `\uB9C8\uAC10 ${d.deadlines.length}`, `\uBA74\uC811\uC900\uBE44 ${d.interview_todo.length}`, `\uC77C\uC815 ${d.upcoming_schedule.length}`];
|
|
115934
|
+
if (d.schedule_conflicts.length) parts.push(`\uC77C\uC815\uCDA9\uB3CC ${d.schedule_conflicts.length}`);
|
|
115935
|
+
const msg = n === 0 && d.schedule_conflicts.length === 0 ? "\uC9C0\uAE08 \uB2F9\uC7A5 \uCC59\uAE38 \uD6C4\uC18D \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4(\uBB34\uC751\uB2F5 \uC9C0\uC6D0\xB7\uC784\uBC15 \uB9C8\uAC10\xB7\uBA74\uC811 \uC900\uBE44 \uB300\uAE30\xB7\uB2E4\uAC00\uC624\uB294 \uC77C\uC815 \uC5C6\uC74C)." : `\uCC59\uAE38 \uD56D\uBAA9: ${parts.join(" \xB7 ")}`;
|
|
115456
115936
|
return ok(msg, d);
|
|
115457
115937
|
}
|
|
115458
115938
|
},
|
|
115459
115939
|
{
|
|
115460
115940
|
name: "get_pipeline_stats",
|
|
115461
115941
|
title: "\uC9C0\uC6D0 \uD30C\uC774\uD504\uB77C\uC778 \uBD84\uC11D(\uAE54\uB54C\uAE30\xB7\uD569\uACA9\uB960)",
|
|
115462
|
-
description: '\uC804\uCCB4 \uC9C0\uC6D0 \uD604\uD669\uC744 \uBD84\uC11D\uD574 \uB3CC\uB824\uC90D\uB2C8\uB2E4: \uD604\uC7AC \uC0C1\uD0DC \uBD84\uD3EC(by_status), \uB2E8\uACC4\uBCC4 \uB3C4\uB2EC \uAE54\uB54C\uAE30(funnel: \uC9C0\uC6D0\u2192\uC11C\uB958\uD569\uACA9\u2192\uBA74\uC811\u2192\uCD5C\uC885, \uC0C1\uD0DC \uBCC0\uACBD \uC774\uB825\uC73C\uB85C \uBCF5\uC6D0\uD55C \uC2E4\uCE21\uCE58\uB77C \uD604\uC7AC \uBD88\uD569\uACA9\uC774\uC5B4\uB3C4 \uAC70\uCCD0\uAC04 \uCD5C\uACE0 \uB2E8\uACC4\uAE4C\uC9C0 \uC9D1\uACC4), \uD1B5\uACFC\uC728(rates: \uC11C\uB958\xB7\uBA74\uC811\xB7\uCD5C\uC885, \uC9C0\uC6D0 \uB300\uBE44 %), \uACB0\uACFC \uC694\uC57D(outcomes). \uC0AC\uC6A9\uC790\uAC00 "\uB0B4 \uD569\uACA9\uB960 \uC5B4\uB54C?", "\uC9C0\uC6D0 \uD1B5\uACC4 \uBCF4\uC5EC\uC918", "\uC5B4\uB290 \uB2E8\uACC4\uC5D0\uC11C \uB9CE\uC774 \uB5A8\uC5B4\uC838?"\uB77C\uACE0 \uBB3C\uC744 \uB54C \uC0AC\uC6A9\uD558\uC138\uC694. \uBE44\uC728\uC740 \uC124\uBA85\uC6A9\uC774\uBA70 \uD45C\uBCF8\uC774 \uC791\uC73C\uBA74 \uC608\uCE21\uB825\uC774 \uB0AE\uB2E4\uB294 \uC810\uC744 \uD568\uAED8 \uC804\uD558\uC138\uC694(note \uCC38\uACE0). \uC77D\uAE30 \uC804\uC6A9\uC785\uB2C8\uB2E4.',
|
|
115942
|
+
description: '\uC804\uCCB4 \uC9C0\uC6D0 \uD604\uD669\uC744 \uBD84\uC11D\uD574 \uB3CC\uB824\uC90D\uB2C8\uB2E4: \uD604\uC7AC \uC0C1\uD0DC \uBD84\uD3EC(by_status), \uB2E8\uACC4\uBCC4 \uB3C4\uB2EC \uAE54\uB54C\uAE30(funnel: \uC9C0\uC6D0\u2192\uC11C\uB958\uD569\uACA9\u2192\uBA74\uC811\u2192\uCD5C\uC885, \uC0C1\uD0DC \uBCC0\uACBD \uC774\uB825\uC73C\uB85C \uBCF5\uC6D0\uD55C \uC2E4\uCE21\uCE58\uB77C \uD604\uC7AC \uBD88\uD569\uACA9\uC774\uC5B4\uB3C4 \uAC70\uCCD0\uAC04 \uCD5C\uACE0 \uB2E8\uACC4\uAE4C\uC9C0 \uC9D1\uACC4), \uD1B5\uACFC\uC728(rates: \uC11C\uB958\xB7\uBA74\uC811\xB7\uCD5C\uC885, \uC9C0\uC6D0 \uB300\uBE44 %), \uACB0\uACFC \uC694\uC57D(outcomes), \uD0C8\uB77D \uB2E8\uACC4 \uBD84\uD3EC(rejected_by_stage: \uC11C\uB958\xB7\uC778\uC801\uC131\xB7\uBA74\uC811\xB7\uCD5C\uC885\xB7\uAE30\uD0C0\uBCC4 \uD0C8\uB77D \uAC74\uC218 + rejected_unrecorded: \uB2E8\uACC4 \uBBF8\uAE30\uB85D \uC218). \uC0AC\uC6A9\uC790\uAC00 "\uB0B4 \uD569\uACA9\uB960 \uC5B4\uB54C?", "\uC9C0\uC6D0 \uD1B5\uACC4 \uBCF4\uC5EC\uC918", "\uC5B4\uB290 \uB2E8\uACC4\uC5D0\uC11C \uB9CE\uC774 \uB5A8\uC5B4\uC838?"\uB77C\uACE0 \uBB3C\uC744 \uB54C \uC0AC\uC6A9\uD558\uC138\uC694. \uBE44\uC728\uC740 \uC124\uBA85\uC6A9\uC774\uBA70 \uD45C\uBCF8\uC774 \uC791\uC73C\uBA74 \uC608\uCE21\uB825\uC774 \uB0AE\uB2E4\uB294 \uC810\uC744 \uD568\uAED8 \uC804\uD558\uC138\uC694(note \uCC38\uACE0). \uC77D\uAE30 \uC804\uC6A9\uC785\uB2C8\uB2E4.',
|
|
115463
115943
|
inputSchema: {},
|
|
115464
115944
|
readOnly: true,
|
|
115465
115945
|
handler: () => {
|
|
@@ -115467,14 +115947,19 @@ ${res.hint}` : "");
|
|
|
115467
115947
|
if (s.total === 0) return ok("\uC544\uC9C1 \uC9C0\uC6D0 \uB0B4\uC5ED\uC774 \uC5C6\uC5B4 \uBD84\uC11D\uD560 \uD1B5\uACC4\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.", s);
|
|
115468
115948
|
const r = s.rates;
|
|
115469
115949
|
const fmt = (v) => v == null ? "\u2014" : `${v}%`;
|
|
115950
|
+
const rejParts = s.rejected_by_stage.map((x2) => `${REJECTED_STAGE_LABELS[x2.stage]} ${x2.count}`);
|
|
115951
|
+
if (s.rejected_unrecorded > 0) rejParts.push(`\uBBF8\uAE30\uB85D ${s.rejected_unrecorded}\uAC74 \u2014 \uAE30\uB85D\uD558\uBA74 \uD328\uD134\uC774 \uBCF4\uC785\uB2C8\uB2E4`);
|
|
115952
|
+
const rejLine = rejParts.length ? ` \xB7 \uD0C8\uB77D \uBD84\uD3EC: ${rejParts.join("\xB7")}` : "";
|
|
115470
115953
|
return ok(
|
|
115471
|
-
`\uC9C0\uC6D0 ${s.total}\uAC74 \xB7 \uAE54\uB54C\uAE30 \uC9C0\uC6D0 ${s.funnel.applied}\u2192\uC11C\uB958 ${s.funnel.document_passed}\u2192\uBA74\uC811 ${s.funnel.interview}\u2192\uCD5C\uC885 ${s.funnel.final_passed} \xB7 \uD1B5\uACFC\uC728 \uC11C\uB958 ${fmt(r.document_pass)}\xB7\uBA74\uC811 ${fmt(r.interview)}\xB7\uCD5C\uC885 ${fmt(r.offer)} (\uD45C\uBCF8 \uC791\uC73C\uBA74 \uCD94\uC138 \uCC38\uACE0\uB85C\uB9CC)`,
|
|
115954
|
+
`\uC9C0\uC6D0 ${s.total}\uAC74 \xB7 \uAE54\uB54C\uAE30 \uC9C0\uC6D0 ${s.funnel.applied}\u2192\uC11C\uB958 ${s.funnel.document_passed}\u2192\uBA74\uC811 ${s.funnel.interview}\u2192\uCD5C\uC885 ${s.funnel.final_passed} \xB7 \uD1B5\uACFC\uC728 \uC11C\uB958 ${fmt(r.document_pass)}\xB7\uBA74\uC811 ${fmt(r.interview)}\xB7\uCD5C\uC885 ${fmt(r.offer)}${rejLine} (\uD45C\uBCF8 \uC791\uC73C\uBA74 \uCD94\uC138 \uCC38\uACE0\uB85C\uB9CC)`,
|
|
115472
115955
|
s
|
|
115473
115956
|
);
|
|
115474
115957
|
}
|
|
115475
115958
|
},
|
|
115476
115959
|
{
|
|
115477
115960
|
name: "search_jobs",
|
|
115961
|
+
// 외부 공개 잡보드(원티드·점핏)로 검색어가 나간다 — openWorld를 정직하게 표시.
|
|
115962
|
+
openWorld: true,
|
|
115478
115963
|
title: "\uACF5\uACE0 \uAC80\uC0C9\xB7\uAC00\uC838\uC624\uAE30(\uD0A4\uC6CC\uB4DC)",
|
|
115479
115964
|
description: `\uD0A4\uC6CC\uB4DC\uB85C \uBB34\uC778\uC99D \uACF5\uAC1C \uCC44\uC6A9 \uC0AC\uC774\uD2B8(${JOB_SEARCH_SOURCES.join("\xB7")})\uC5D0\uC11C \uCC44\uC6A9 \uACF5\uACE0\uB97C \uAC00\uC838\uC635\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uAC00 "\uBC31\uC5D4\uB4DC \uC2E0\uC785 \uACF5\uACE0 \uCC3E\uC544\uC918", "React \uACF5\uACE0 \uAC00\uC838\uC640"\uCC98\uB7FC \uACF5\uACE0\uB97C \uCC3E\uC544 \uB2EC\uB77C\uACE0 \uD560 \uB54C \uC0AC\uC6A9\uD558\uC138\uC694. \uACB0\uACFC(\uD68C\uC0AC\xB7\uC9C1\uBB34\xB7\uB9C1\uD06C\xB7\uC9C0\uC5ED\xB7\uACBD\uB825\xB7\uAE30\uC220\uC2A4\uD0DD\xB7\uB9C8\uAC10)\uB97C \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uBCF4\uAE30 \uC88B\uAC8C \uBCF4\uC5EC \uC8FC\uACE0, **\uC0AC\uC6A9\uC790\uAC00 \uAD00\uC2EC \uC788\uB2E4\uACE0 \uACE0\uB978 \uAC83\uB9CC** save_job_posting\uC73C\uB85C \uC800\uC7A5\uD558\uC138\uC694(\uC804\uBD80 \uC790\uB3D9 \uC800\uC7A5\uD558\uC9C0 \uB9C8\uC138\uC694). \uC800\uC7A5\uD55C \uACF5\uACE0\uB294 \uC774\uC5B4\uC11C get_application_context\uB85C \uBD84\uC11D\xB7\uC790\uC18C\uC11C\uB85C \uC5F0\uACB0\uB429\uB2C8\uB2E4. \uCC38\uACE0: \uC774 \uB3C4\uAD6C\uB294 \uC678\uBD80 \uACF5\uAC1C \uD398\uC774\uC9C0\uC5D0\uC11C \uACF5\uACE0\uB97C \uAC00\uC838\uC624\uAE30\uB9CC \uD558\uBA70(\uBCF4\uB0B4\uB294 \uAC83\uC740 \uAC80\uC0C9 \uD0A4\uC6CC\uB4DC\uBFD0, \uC0AC\uC6A9\uC790 \uB370\uC774\uD130\uB294 \uC808\uB300 \uC804\uC1A1\uD558\uC9C0 \uC54A\uC74C), \uBD07 \uCC28\uB2E8 \uC6B0\uD68C\uB294 \uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC0AC\uB78C\uC778\xB7\uC7A1\uCF54\uB9AC\uC544\uB294 \uD0A4 \uBC1C\uAE09 \uB610\uB294 \uC57D\uAD00 \uC81C\uC57D\uC73C\uB85C \uC5EC\uAE30 \uD3EC\uD568\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uACB0\uACFC\uAC00 \uBE44\uC5B4 \uC788\uC73C\uBA74 \uD0A4\uC6CC\uB4DC\uB97C \uBC14\uAFB8\uAC70\uB098 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uACF5\uACE0 URL/\uBCF8\uBB38\uC744 \uBC1B\uC544 save_job_posting\uC73C\uB85C \uC800\uC7A5\uD558\uC138\uC694.`,
|
|
115480
115965
|
inputSchema: {
|
|
@@ -115496,16 +115981,72 @@ ${res.hint}` : "");
|
|
|
115496
115981
|
{
|
|
115497
115982
|
name: "prescreen_job",
|
|
115498
115983
|
title: "\uACF5\uACE0 \uC0AC\uC804 \uD504\uB9AC\uC2A4\uD06C\uB9B0(\uD0A4\uC6CC\uB4DC \uACB9\uCE68)",
|
|
115499
|
-
description: '\uC800\uC7A5\uB41C \uACF5\uACE0\uC758 \uD575\uC2EC \uD0A4\uC6CC\uB4DC\uB97C
|
|
115984
|
+
description: '\uC800\uC7A5\uB41C \uACF5\uACE0\uC758 \uD575\uC2EC \uD0A4\uC6CC\uB4DC\uB97C **\uC0AC\uC6A9\uC790\uC758 \uBCF4\uC720 \uAE30\uC220\xB7\uD504\uB85C\uC81D\uD2B8/\uACBD\uB825 \uAE30\uC220\uC2A4\uD0DD(\uAD6C\uC870\uD654 \uC2A4\uD0AC)\uACFC \uB300\uD45C \uC774\uB825\uC11C \uBCF8\uBB38 \uC591\uCABD**\uC5D0 \uB300\uC870\uD574 "\uC774 \uACF5\uACE0\uB97C \uAE4A\uAC8C \uBCFC \uAC00\uCE58\uAC00 \uC788\uB294\uC9C0"\uB97C \uBE60\uB974\uAC8C \uAC00\uB2A0\uD569\uB2C8\uB2E4. LLM \uC5C6\uC774 \uC140 \uC218 \uC788\uB294 \uD0A4\uC6CC\uB4DC \uACB9\uCE68\uB9CC \uB3CC\uB824\uC8FC\uB294 \uAC12\uC2FC \uC0AC\uC804 \uD544\uD130\uC785\uB2C8\uB2E4: `matched`(\uC2A4\uD0AC \uBAA9\uB85D\uC5D0\uC11C \uBC1C\uACAC)\xB7`resume_matched`(\uC774\uB825\uC11C \uBCF8\uBB38\uC5D0\uC11C \uBC1C\uACAC)\xB7`combined_matched`(\uB458\uC758 \uD569\uC9D1\uD569)\xB7`combined_coverage`(\uD569\uC9D1\uD569 \uCEE4\uBC84\uB9AC\uC9C0 0~1)\xB7`resume_checked`(\uB300\uD45C \uC774\uB825\uC11C \uC874\uC7AC \uC5EC\uBD80). **\uC9C4\uC9DC \uC801\uD569\uB3C4 \uD310\uB2E8\uC740 \uB2F9\uC2E0(AI)\uC774 get_application_context\uB85C \uB9E5\uB77D\uC744 \uBC1B\uC544 \uC9C1\uC811 \uC218\uD589**\uD569\uB2C8\uB2E4(\uC774 \uB3C4\uAD6C\uB294 \uADF8 \uB300\uCCB4\uAC00 \uC544\uB2D9\uB2C8\uB2E4). \uC0AC\uC6A9\uC790\uAC00 \uACF5\uACE0\uB97C \uC5EC\uB7EC \uAC1C \uD6D1\uC73C\uBA70 \uC6B0\uC120\uC21C\uC704\uB97C \uC815\uD558\uAC70\uB098 "\uC774\uAC70 \uC9C0\uC6D0\uD560 \uB9CC\uD574?"\uB77C\uACE0 \uBB3C\uC744 \uB54C \uBCF8\uACA9 \uBD84\uC11D \uC804\uC5D0 \uAC00\uBCCD\uAC8C \uD638\uCD9C\uD558\uC138\uC694. **combined_coverage\uAC00 \uB0AE\uC740\uB370 \uC2E4\uC81C\uB85C\uB294 \uBCF4\uC720\uD55C \uC5ED\uB7C9\uC774\uB77C\uBA74, \uC774\uB825\uC11C \uBCF8\uBB38\uC5D0 \uADF8 \uD0A4\uC6CC\uB4DC\uAC00 \uC548 \uB4DC\uB7EC\uB098\uB294 \uAC83\uC774\uB2C8 \uC774\uB825\uC11C \uBCF4\uAC15(\uD574\uB2F9 \uD0A4\uC6CC\uB4DC \uB178\uCD9C)\uC744 \uC81C\uC548\uD558\uC138\uC694**(ATS \uD0A4\uC6CC\uB4DC \uB9E4\uCE6D\uC5D0 \uC720\uD6A8). coverage\uAC00 \uB0AE\uC544\uB3C4 \uD0A4\uC6CC\uB4DC \uBBF8\uAE30\uC7AC\uC77C \uC218 \uC788\uC73C\uB2C8 \uB2E8\uC815\uD558\uC9C0 \uB9D0\uACE0, \uD45C\uAE30\uB418\uC9C0 \uC54A\uC740 \uC5ED\uB7C9\uC740 \uC0AC\uC6A9\uC790\uC5D0\uAC8C \uD655\uC778\uD558\uC138\uC694. \uC77D\uAE30 \uC804\uC6A9\uC785\uB2C8\uB2E4.',
|
|
115500
115985
|
inputSchema: { job_id: external_exports.string() },
|
|
115501
115986
|
readOnly: true,
|
|
115502
115987
|
handler: (args) => {
|
|
115503
115988
|
const r = prescreenJob(args.job_id);
|
|
115504
115989
|
if (!r) return fail("\uACF5\uACE0\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uBA3C\uC800 save_job_posting\uC73C\uB85C \uC800\uC7A5\uD558\uC138\uC694.");
|
|
115505
|
-
if (r.
|
|
115990
|
+
if (r.combined_coverage == null)
|
|
115506
115991
|
return ok("\uC774 \uACF5\uACE0\uC5D0 \uC800\uC7A5\uB41C \uD575\uC2EC \uD0A4\uC6CC\uB4DC\uAC00 \uC5C6\uC5B4 \uACB9\uCE68\uC744 \uC140 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. save_job_posting\uC758 keywords\uC5D0 \uD575\uC2EC \uD0A4\uC6CC\uB4DC\uB97C \uC815\uB9AC\uD574 \uB123\uC73C\uBA74 \uD504\uB9AC\uC2A4\uD06C\uB9B0\uC774 \uAC00\uB2A5\uD569\uB2C8\uB2E4.", r);
|
|
115507
|
-
const pct = Math.round(r.
|
|
115508
|
-
|
|
115992
|
+
const pct = Math.round(r.combined_coverage * 100);
|
|
115993
|
+
const combinedMissing = r.job_keywords.filter((k) => !r.combined_matched.includes(k));
|
|
115994
|
+
const resumeNote = r.resume_checked ? "" : " (\uB300\uD45C \uC774\uB825\uC11C\uAC00 \uC5C6\uC5B4 \uC2A4\uD0AC \uBAA9\uB85D\uB9CC \uB300\uC870\uD588\uC5B4\uC694 \u2014 \uC774\uB825\uC11C\uB97C \uC800\uC7A5\uD558\uBA74 \uBCF8\uBB38 \uD0A4\uC6CC\uB4DC\uAE4C\uC9C0 \uB300\uC870\uD569\uB2C8\uB2E4.)";
|
|
115995
|
+
return ok(
|
|
115996
|
+
`\uD0A4\uC6CC\uB4DC \uCEE4\uBC84\uB9AC\uC9C0 ${pct}% \u2014 \uC2A4\uD0AC+\uB300\uD45C \uC774\uB825\uC11C \uBCF8\uBB38\uC5D0\uC11C ${r.combined_matched.length}/${r.job_keywords.length}\uAC1C \uD655\uC778.${resumeNote} \uC544\uC9C1 \uC548 \uB4DC\uB7EC\uB09C \uD0A4\uC6CC\uB4DC: ${combinedMissing.join(", ") || "\uC5C6\uC74C"}. (\uC140 \uC218 \uC788\uB294 \uACB9\uCE68\uC77C \uBFD0 \uC2E4\uC81C \uC801\uD569\uB3C4\uB294 \uC9C1\uC811 \uD310\uB2E8\uD558\uC138\uC694. \uBCF4\uC720 \uC5ED\uB7C9\uC778\uB370 \uC548 \uB4DC\uB7EC\uB0AC\uB2E4\uBA74 \uC774\uB825\uC11C \uBCF4\uAC15\uC744 \uC81C\uC548\uD558\uC138\uC694.)`,
|
|
115997
|
+
r
|
|
115998
|
+
);
|
|
115999
|
+
}
|
|
116000
|
+
},
|
|
116001
|
+
{
|
|
116002
|
+
name: "save_offer",
|
|
116003
|
+
idempotent: true,
|
|
116004
|
+
// 공고당 1건 업서트
|
|
116005
|
+
title: "\uC624\uD37C(\uC81C\uC548) \uC800\uC7A5",
|
|
116006
|
+
description: '\uBC1B\uC740 \uCC44\uC6A9 \uC81C\uC548(\uC624\uD37C)\uC744 \uACF5\uACE0\uC5D0 \uC5F0\uACB0\uD574 \uC800\uC7A5\uD569\uB2C8\uB2E4(\uACF5\uACE0\uB2F9 1\uAC74, \uB2E4\uC2DC \uC800\uC7A5\uD558\uBA74 \uAC31\uC2E0). \uD604\uAE08\uC131 \uD56D\uBAA9\uC740 **\uB9CC\uC6D0 \uB2E8\uC704 \uC22B\uC790**\uB85C \u2014 base_salary(\uAE30\uBCF8\uAE09/\uC5F0\uBD09)\xB7bonus_amount(\uC5F0 \uC131\uACFC\uAE09\xB7\uC0C1\uC5EC \uAE30\uB300\uC561)\xB7welfare_amount(\uBCF5\uC9C0\uD3EC\uC778\uD2B8 \uB4F1 \uC5F0\uD658\uC0B0)\xB7signing_amount(\uC0AC\uC774\uB2DD \uC77C\uC2DC\uAE08). \uC8FC\uC2DD/\uC2A4\uD1A1\uC635\uC158\uC740 \uAC00\uCE58\uD3C9\uAC00\uAC00 \uBAA8\uD638\uD558\uB2C8 equity_note\uC5D0 \uD14D\uC2A4\uD2B8\uB85C, \uADF8 \uC678 \uBCF4\uC0C1\uC740 comp_note\uC5D0. \uADFC\uBB34\uD615\uD0DC\xB7\uACC4\uC57D\uD615\uD0DC\xB7\uC218\uB77D \uB9C8\uAC10\uC77C(accept_deadline)\uB3C4 \uC800\uC7A5\uD558\uC138\uC694. **\uB2F9\uC2E0(AI)\uC774 \uC774 \uC624\uD37C\uB97C \uC885\uD569 \uD3C9\uAC00\uD574 ai_score(0~100)\uC640 verdict(\uCD5C\uC885\uD3C9 \u2014 "\uC5B4\uB5A4 \uC0C1\uD669\uC774\uBA74 \uC774 \uD68C\uC0AC\uAC00 \uC88B\uB2E4" \uC2DD \uD55C\uB450 \uBB38\uC7A5)\uB97C \uD568\uAED8 \uCC44\uC6CC \uC800\uC7A5\uD558\uC138\uC694** \u2014 CareerMate\uC5D4 LLM\uC774 \uC5C6\uC5B4 \uC774 \uC810\uC218\xB7\uD3C9\uC774 \uB300\uC2DC\uBCF4\uB4DC\uC5D0 \uADF8\uB300\uB85C \uD45C\uC2DC\uB429\uB2C8\uB2E4. \uD68C\uC0AC \uD3C9\uD310\uC774 \uD310\uB2E8\uC5D0 \uD544\uC694\uD558\uBA74 \uACF5\uACE0\uC758 reputation\uC744 \uBA3C\uC800 \uCC44\uC6CC\uB450\uC138\uC694. \uC5EC\uB7EC \uC624\uD37C\uC758 \uC815\uBC00 \uBE44\uAD50\uB294 compare_offers\uB85C \uB370\uC774\uD130\uB97C \uBC1B\uC544 \uB2F9\uC2E0\uC774 \uC9C1\uC811 \uD558\uC138\uC694(\uCD1D\uBCF4\uC0C1\xB7\uC131\uC7A5\xB7\uC548\uC815\uC131\xB7\uC6CC\uB77C\uBC38). **\uC624\uD37C\uC758 \uC9C4\uD589 \uC0C1\uD0DC\uB294 offer_status\uB85C \uAE30\uB85D\uD558\uC138\uC694** \u2014 open(\uAE30\uBCF8, \uC9C4\uD589 \uC911)/accepted(\uC218\uB77D)/declined(\uAC70\uC808). \uC0AC\uC6A9\uC790\uAC00 "\uADF8 \uC624\uD37C \uAC70\uC808\uD588\uC5B4/\uC218\uB77D\uD558\uAE30\uB85C \uD588\uC5B4"\uB77C\uACE0 \uD558\uBA74 \uC774 \uB3C4\uAD6C\uB85C offer_status\uB9CC \uAC31\uC2E0\uD558\uBA74 \uB429\uB2C8\uB2E4 \u2014 \uC0AD\uC81C\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(\uC5F0\uBD09\xB7\uC870\uAC74 \uAE30\uB85D\uC740 \uB2E4\uC74C \uD611\uC0C1\uC758 \uC790\uC0B0\uC774\uACE0, \uB300\uC2DC\uBCF4\uB4DC\uAC00 \uC9C0\uB09C \uC624\uD37C\uB85C \uC811\uC5B4\uC11C \uBCF4\uC5EC\uC90D\uB2C8\uB2E4). accepted\uB85C \uC800\uC7A5\uD558\uBA74 \uC9C0\uC6D0 \uC0C1\uD0DC(\uCD5C\uC885 \uD569\uACA9) \uAC31\uC2E0\uB3C4 \uD568\uAED8 \uC81C\uC548\uD558\uC138\uC694.',
|
|
116007
|
+
inputSchema: OfferInputSchema.shape,
|
|
116008
|
+
handler: (args) => {
|
|
116009
|
+
try {
|
|
116010
|
+
const offer = saveOffer(args);
|
|
116011
|
+
const total = offer.total_comp_annual_est;
|
|
116012
|
+
const statusLabel = offer.offer_status === "accepted" ? " \xB7 \uC218\uB77D" : offer.offer_status === "declined" ? " \xB7 \uAC70\uC808" : "";
|
|
116013
|
+
const user_message = `'${offer.company}' \uC624\uD37C\uB97C \uC800\uC7A5\uD588\uC5B4\uC694` + (offer.ai_score != null ? ` (\uC810\uC218 ${offer.ai_score})` : "") + (total != null ? ` \xB7 \uCD94\uC815 \uC5F0 \uD604\uAE08\uC131 ${total.toLocaleString()}\uB9CC\uC6D0` : "") + statusLabel + ".";
|
|
116014
|
+
const app = applicationRepo.getByJob(offer.job_id);
|
|
116015
|
+
const suggested_next_action = offer.offer_status === "accepted" && app?.status !== "final_passed" ? {
|
|
116016
|
+
prompt: "\uC9C0\uC6D0 \uC0C1\uD0DC\uB3C4 '\uCD5C\uC885 \uD569\uACA9'\uC73C\uB85C \uBC14\uAFC0\uAE4C\uC694?",
|
|
116017
|
+
next_tool: "update_application_status"
|
|
116018
|
+
} : null;
|
|
116019
|
+
const msg = suggested_next_action ? `${user_message}
|
|
116020
|
+
|
|
116021
|
+
\uC0AC\uC6A9\uC790\uC5D0\uAC8C \uC9C0\uC6D0 \uC0C1\uD0DC\uB97C '\uCD5C\uC885 \uD569\uACA9'\uC73C\uB85C \uD568\uAED8 \uBC14\uAFC0\uC9C0 \uBB3C\uC5B4\uBCF4\uC138\uC694.` : user_message;
|
|
116022
|
+
return ok(msg, { ...offer, user_message, suggested_next_action });
|
|
116023
|
+
} catch (e) {
|
|
116024
|
+
return fail(e instanceof Error ? e.message : "\uC800\uC7A5 \uC2E4\uD328");
|
|
116025
|
+
}
|
|
116026
|
+
}
|
|
116027
|
+
},
|
|
116028
|
+
{
|
|
116029
|
+
name: "compare_offers",
|
|
116030
|
+
title: "\uC624\uD37C \uBE44\uAD50",
|
|
116031
|
+
description: '\uC800\uC7A5\uB41C \uBAA8\uB4E0 \uC624\uD37C\uB97C **\uC810\uC218\uC21C(\uB2F9\uC2E0\uC774 \uB9E4\uAE34 ai_score)** \uC73C\uB85C \uD68C\uC0AC\xB7\uC9C1\uBB34\xB7\uCD94\uC815 \uC5F0 \uD604\uAE08\uC131 \uCD1D\uC561\xB7\uADFC\uBB34\uD615\uD0DC\xB7\uC218\uB77D\uB9C8\uAC10\xB7\uCD5C\uC885\uD3C9\uACFC \uD568\uAED8 \uB3CC\uB824\uC90D\uB2C8\uB2E4. total_comp_annual_est\uB294 CareerMate\uAC00 \uACB0\uC815\uB860\uC73C\uB85C \uD569\uC0B0\uD55C \uCD94\uC815\uCE58(\uAE30\uBCF8\uAE09+\uC131\uACFC\uAE09+\uBCF5\uC9C0, \uC77C\uC2DC\uAE08 \uC81C\uC678)\uC785\uB2C8\uB2E4. \uAC01 \uC624\uD37C\uC5D0\uB294 offer_status(open/accepted/declined)\uAC00 \uD3EC\uD568\uB418\uB2C8 **\uBE44\uAD50\uB294 \uC9C4\uD589 \uC911(open) \uC624\uD37C \uC704\uC8FC\uB85C** \uD558\uACE0, \uC218\uB77D\xB7\uAC70\uC808\uB41C \uC9C0\uB09C \uC624\uD37C\uB294 \uAE30\uC900\uC810(\uACFC\uAC70 \uC870\uAC74)\uC73C\uB85C\uB9CC \uCC38\uACE0\uD558\uC138\uC694. "\uC5B4\uB290 \uC624\uD37C\uAC00 \uB098\uC740\uC9C0"\uC758 \uC815\uBC00 \uD310\uB2E8\uC740 \uC774 \uB370\uC774\uD130\uB97C \uBC1B\uC544 \uB2F9\uC2E0\uC774 offer-evaluation\xB7salary-negotiation \uAD00\uC810(\uCD1D\uBCF4\uC0C1\xB7\uC131\uC7A5\xB7\uC548\uC815\uC131\xB7\uC6CC\uB77C\uBC38\xB7\uD68C\uC0AC \uD3C9\uD310)\uC73C\uB85C \uC9C1\uC811 \uD558\uC138\uC694. \uC0AC\uC6A9\uC790\uAC00 "\uC624\uD37C \uBE44\uAD50\uD574\uC918"\uB77C\uACE0 \uD560 \uB54C \uC0AC\uC6A9\uD569\uB2C8\uB2E4. \uC77D\uAE30 \uC804\uC6A9\uC785\uB2C8\uB2E4.',
|
|
116032
|
+
inputSchema: {},
|
|
116033
|
+
readOnly: true,
|
|
116034
|
+
handler: () => {
|
|
116035
|
+
const offers = compareOffers();
|
|
116036
|
+
if (offers.length === 0) return ok("\uC800\uC7A5\uB41C \uC624\uD37C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. save_offer\uB85C \uBA3C\uC800 \uC800\uC7A5\uD558\uC138\uC694.", offers);
|
|
116037
|
+
return ok(`\uC624\uD37C ${offers.length}\uAC74(\uC810\uC218\uC21C).`, offers);
|
|
116038
|
+
}
|
|
116039
|
+
},
|
|
116040
|
+
{
|
|
116041
|
+
name: "get_offer",
|
|
116042
|
+
title: "\uC624\uD37C \uC870\uD68C(\uACF5\uACE0\uBCC4)",
|
|
116043
|
+
description: "\uD2B9\uC815 \uACF5\uACE0\uC5D0 \uC800\uC7A5\uB41C \uC624\uD37C 1\uAC74\uC744 \uB3CC\uB824\uC90D\uB2C8\uB2E4(\uC5C6\uC73C\uBA74 null). \uC77D\uAE30 \uC804\uC6A9\uC785\uB2C8\uB2E4.",
|
|
116044
|
+
inputSchema: { job_id: external_exports.string() },
|
|
116045
|
+
readOnly: true,
|
|
116046
|
+
handler: (args) => {
|
|
116047
|
+
const offer = getOffer(args.job_id);
|
|
116048
|
+
if (!offer) return ok("\uC774 \uACF5\uACE0\uC5D0 \uC800\uC7A5\uB41C \uC624\uD37C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.", null);
|
|
116049
|
+
return ok(`'${offer.company}' \uC624\uD37C.`, offer);
|
|
115509
116050
|
}
|
|
115510
116051
|
},
|
|
115511
116052
|
/* ------------------------------------------------------- workflow guide */
|
|
@@ -115579,7 +116120,7 @@ ${res.hint}` : "");
|
|
|
115579
116120
|
{
|
|
115580
116121
|
name: "validate_cover_letter",
|
|
115581
116122
|
title: "\uC790\uAE30\uC18C\uAC1C\uC11C \uC790\uB3D9 \uC810\uAC80 (\uC800\uC7A5 \uC804 \uBBF8\uB9AC\uBCF4\uAE30)",
|
|
115582
|
-
description: "\uC790\uAE30\uC18C\uAC1C\uC11C\uB97C save_cover_letter_version\uC73C\uB85C \uC800\uC7A5\uD558\uAE30 \uC9C1\uC804\uC5D0 \uD638\uCD9C\uD558\uBA74, \uC800\uC7A5\uD558\uC9C0 \uC54A\uACE0 \uBBF8\uB9AC \uC810\uAC80\uB9CC \uD569\uB2C8\uB2E4. CareerMate\uAC00 LLM \uC5C6\uC774 \uACB0\uC815\uB860\uC73C\uB85C (1) \uBCF8\uBB38\uC758 \uC815\uB7C9 \uC218\uCE58\uAC00 \uC800\uC7A5\uB41C \uACBD\uB825\xB7\uC774\uB825\uC11C\xB7\uD504\uB85C\uC81D\uD2B8\uC5D0 \uADFC\uAC70\uAC00 \uC788\uB294\uC9C0(\uC5C6\uC73C\uBA74 \uD658\uAC01 \uC758\uC2EC \u2192 \uC800\uC7A5 \uC2DC \uCC28\uB2E8\uB428), (2) \uACF5\uACE0\uC5D0\uC11C \uAC00\uC838\uC628 \uC218\uCE58\uB97C \uBCF8\uC778 \uC131\uACFC\uCC98\uB7FC \uC4F0\uC9C0 \uC54A\uC558\uB294\uC9C0, (3) \uBC88\uC5ED\uD22C\xB7\uC81C\uB108\uB9AD \uB3C4\uC785\xB7\uBE48 \uD615\uC6A9\uC0AC\xB7\uBE14\uB77C\uC778\uB4DC \uC704\uBC18 \uAC19\uC740 \uBB38\uCCB4 \uC2E0\uD638\uB97C \uC138\uC5B4 \uB3CC\uB824\uC90D\uB2C8\uB2E4. \uB610 (4) \uAE00\uC790\uC218\uB97C \uACF5\uBC31\uD3EC\uD568\xB7\uACF5\uBC31\uC81C\uC678\xB7UTF-8 byte \uC138 \uAE30\uC900\uC73C\uB85C \uC815\uD655\uD788 \uC138\uACE0, min_chars/max_chars\uB97C \uC8FC\uBA74 \uC0C1\xB7\uD558\uD55C \uCDA9\uC871 \uC5EC\uBD80\uAE4C\uC9C0 \uB3CC\uB824\uC90D\uB2C8\uB2E4(LLM\uC740 \uAE00\uC790\uC218\uB97C \uC815\uD655\uD788 \uBABB \uC138\uBBC0\uB85C \uC774 \uAE30\uB2A5\uC744 \uC4F0\uC138\uC694). \uC810\uAC80\uC740 \uC140 \uC218 \uC788\uB294 \uAC83\uB9CC \uBD05\uB2C8\uB2E4 \u2014 \uC0AC\uC2E4\uC131\xB7\uB3D9\uBB38\uC11C\uB2F5 \uAC19\uC740 \uC758\uBBF8 \uD310\uB2E8\uC740 \uB2F9\uC2E0(AI)\uC774 \uC9C1\uC811 \uD558\uC138\uC694. \uD55C\uAD6D \uBB38\uD56D\uD615 \uC790\uC18C\uC11C\uB294 \uBB38\uD56D\uB9C8\uB2E4 \uAE00\uC790\uC218 \uD55C\uB3C4\uAC00 \uB2E4\uB974\uB2C8 \uAC01 \uBB38\uD56D \uBCF8\uBB38\uC744 \uADF8 \uBB38\uD56D\uC758 \uD55C\uB3C4\uB85C \uB530\uB85C \uC810\uAC80\uD558\uC138\uC694. job_id\uB97C \uC8FC\uBA74 \uACF5\uACE0 \uC218\uCE58\uAE4C\uC9C0 \uBE44\uAD50\uD569\uB2C8\uB2E4.",
|
|
116123
|
+
description: "\uC790\uAE30\uC18C\uAC1C\uC11C\uB97C save_cover_letter_version\uC73C\uB85C \uC800\uC7A5\uD558\uAE30 \uC9C1\uC804\uC5D0 \uD638\uCD9C\uD558\uBA74, \uC800\uC7A5\uD558\uC9C0 \uC54A\uACE0 \uBBF8\uB9AC \uC810\uAC80\uB9CC \uD569\uB2C8\uB2E4. CareerMate\uAC00 LLM \uC5C6\uC774 \uACB0\uC815\uB860\uC73C\uB85C (1) \uBCF8\uBB38\uC758 \uC815\uB7C9 \uC218\uCE58\uAC00 \uC800\uC7A5\uB41C \uACBD\uB825\xB7\uC774\uB825\uC11C\xB7\uD504\uB85C\uC81D\uD2B8\uC5D0 \uADFC\uAC70\uAC00 \uC788\uB294\uC9C0(\uC5C6\uC73C\uBA74 \uD658\uAC01 \uC758\uC2EC \u2192 \uC800\uC7A5 \uC2DC \uCC28\uB2E8\uB428), (2) \uACF5\uACE0\uC5D0\uC11C \uAC00\uC838\uC628 \uC218\uCE58\uB97C \uBCF8\uC778 \uC131\uACFC\uCC98\uB7FC \uC4F0\uC9C0 \uC54A\uC558\uB294\uC9C0, (3) \uBC88\uC5ED\uD22C\xB7\uC81C\uB108\uB9AD \uB3C4\uC785\xB7\uBE48 \uD615\uC6A9\uC0AC\xB7\uBE14\uB77C\uC778\uB4DC \uC704\uBC18 \uAC19\uC740 \uBB38\uCCB4 \uC2E0\uD638\uB97C \uC138\uC5B4 \uB3CC\uB824\uC90D\uB2C8\uB2E4. \uB610 (4) \uAE00\uC790\uC218\uB97C \uACF5\uBC31\uD3EC\uD568\xB7\uACF5\uBC31\uC81C\uC678\xB7UTF-8 byte \uC138 \uAE30\uC900\uC73C\uB85C \uC815\uD655\uD788 \uC138\uACE0, min_chars/max_chars\uB97C \uC8FC\uBA74 \uC0C1\xB7\uD558\uD55C \uCDA9\uC871 \uC5EC\uBD80\uAE4C\uC9C0 \uB3CC\uB824\uC90D\uB2C8\uB2E4(LLM\uC740 \uAE00\uC790\uC218\uB97C \uC815\uD655\uD788 \uBABB \uC138\uBBC0\uB85C \uC774 \uAE30\uB2A5\uC744 \uC4F0\uC138\uC694). \uC810\uAC80\uC740 \uC140 \uC218 \uC788\uB294 \uAC83\uB9CC \uBD05\uB2C8\uB2E4 \u2014 \uC0AC\uC2E4\uC131\xB7\uB3D9\uBB38\uC11C\uB2F5 \uAC19\uC740 \uC758\uBBF8 \uD310\uB2E8\uC740 \uB2F9\uC2E0(AI)\uC774 \uC9C1\uC811 \uD558\uC138\uC694. \uD55C\uAD6D \uBB38\uD56D\uD615 \uC790\uC18C\uC11C\uB294 \uBB38\uD56D\uB9C8\uB2E4 \uAE00\uC790\uC218 \uD55C\uB3C4\uAC00 \uB2E4\uB974\uB2C8 \uAC01 \uBB38\uD56D \uBCF8\uBB38\uC744 \uADF8 \uBB38\uD56D\uC758 \uD55C\uB3C4\uB85C \uB530\uB85C \uC810\uAC80\uD558\uC138\uC694. \uACF5\uACE0\uC5D0 questions\uAC00 \uC800\uC7A5\uB3FC \uC788\uC73C\uBA74 \uADF8 \uBB38\uD56D\uC758 \uD55C\uB3C4\uB97C min_chars/max_chars/count_mode\uB85C \uB118\uACA8 \uC810\uAC80\uD558\uC138\uC694. job_id\uB97C \uC8FC\uBA74 \uACF5\uACE0 \uC218\uCE58\uAE4C\uC9C0 \uBE44\uAD50\uD569\uB2C8\uB2E4.",
|
|
115583
116124
|
inputSchema: {
|
|
115584
116125
|
text: external_exports.string().max(2e5).describe("\uC810\uAC80\uD560 \uC790\uAE30\uC18C\uAC1C\uC11C \uBCF8\uBB38(\uBB38\uD56D\uD615\uC774\uBA74 \uD55C \uBB38\uD56D \uBCF8\uBB38)"),
|
|
115585
116126
|
job_id: external_exports.string().optional().describe("\uC5F0\uACB0\uD560 \uACF5\uACE0(\uC788\uC73C\uBA74 \uACF5\uACE0 \uC218\uCE58\uAE4C\uC9C0 \uBE44\uAD50)"),
|
|
@@ -115623,6 +116164,8 @@ ${report.disclaimer}`, {
|
|
|
115623
116164
|
},
|
|
115624
116165
|
{
|
|
115625
116166
|
name: "set_verify_mode",
|
|
116167
|
+
idempotent: true,
|
|
116168
|
+
// 같은 값 재설정은 무해
|
|
115626
116169
|
title: "\uC810\uAC80 \uBAA8\uB4DC \uC124\uC815 (\uAE30\uBCF8/\uC5C4\uACA9)",
|
|
115627
116170
|
description: '\uC800\uC7A5 \uC804 \uC790\uB3D9 \uC810\uAC80\uC758 \uC5C4\uACA9\uB3C4\uB97C \uBC14\uAFC9\uB2C8\uB2E4. \uC5C4\uACA9 \uBAA8\uB4DC(strict=true)\uB97C \uCF1C\uBA74, \uC774\uD6C4 \uBAA8\uB4E0 \uC790\uC18C\uC11C \uC800\uC7A5\uC5D0\uC11C "\uC774\uB825\uC11C \uBCF8\uBB38\uC5D0 \uADFC\uAC70 \uC5C6\uB294 \uC218\uCE58"(\uAD6C\uC870\uD654 \uACBD\uB825 \uD56D\uBAA9\uC5D0\uB9CC \uC788\uB294 \uAC12)\uAE4C\uC9C0 \uCC28\uB2E8\uD569\uB2C8\uB2E4. \uAE30\uBCF8 \uBAA8\uB4DC\uB294 \uCD9C\uCC98\uAC00 \uC544\uC608 \uC5C6\uB294 \uC218\uCE58\uB9CC \uCC28\uB2E8\uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uAC00 "\uC5C4\uACA9\uD558\uAC8C \uBD10\uC918"\uB77C\uACE0 \uD558\uBA74 \uBC14\uB85C \uCF1C\uC9C0 \uB9D0\uACE0 "\uC55E\uC73C\uB85C \uD56D\uC0C1 \uC5C4\uACA9\uD558\uAC8C \uBCFC\uAE4C\uC694?"\uB77C\uACE0 \uBA3C\uC800 \uD655\uC778\uD55C \uB4A4 \uB3D9\uC758\uD558\uBA74 strict=true\uB85C \uD638\uCD9C\uD558\uC138\uC694. \uB044\uAE30(strict=false)\uB294 \uC548\uC804\uC7A5\uCE58\uB97C \uC57D\uD558\uAC8C \uB9CC\uB4DC\uB294 \uAC83\uC774\uBBC0\uB85C, \uC0AC\uC6A9\uC790\uAC00 \uBA85\uD655\uD788 \uB044\uACA0\uB2E4\uACE0 \uD560 \uB54C\uB9CC \uD638\uCD9C\uD558\uC138\uC694. \uC774\uBC88 \uD55C \uAC74\uB9CC \uC5C4\uACA9\uD558\uAC8C \uBCF4\uB824\uBA74 \uBAA8\uB4DC\uB97C \uBC14\uAFB8\uC9C0 \uB9D0\uACE0 validate_cover_letter / save_cover_letter_version\uC5D0 strict:true\uB97C \uD55C \uBC88\uB9CC \uB118\uAE30\uC138\uC694.',
|
|
115628
116171
|
inputSchema: {
|
|
@@ -115661,6 +116204,8 @@ ${report.disclaimer}`, {
|
|
|
115661
116204
|
/* ----------------------------------------------------------------- update */
|
|
115662
116205
|
{
|
|
115663
116206
|
name: "check_for_update",
|
|
116207
|
+
// npm 레지스트리로 버전 조회가 나간다(사용자 데이터 미전송).
|
|
116208
|
+
openWorld: true,
|
|
115664
116209
|
title: "\uC5C5\uB370\uC774\uD2B8 \uD655\uC778",
|
|
115665
116210
|
description: 'CareerMate\uC5D0 \uC0C8 \uBC84\uC804\uC774 \uC788\uB294\uC9C0 npm \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0\uC11C \uC9C0\uAE08 \uD655\uC778\uD569\uB2C8\uB2E4(\uACF5\uAC1C \uBC84\uC804 \uC815\uBCF4\uB9CC GET\uD558\uBA70 \uC0AC\uC6A9\uC790 \uB370\uC774\uD130\uB294 \uC804\uC1A1\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4). \uD604\uC7AC \uBC84\uC804\xB7\uCD5C\uC2E0 \uBC84\uC804\xB7\uC5C5\uB370\uC774\uD2B8 \uAC00\uB2A5 \uC5EC\uBD80\uB97C \uB3CC\uB824\uC90D\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uAC00 "\uCD5C\uC2E0\uC774\uC57C?/\uC5C5\uB370\uC774\uD2B8 \uC788\uC5B4?"\uB77C\uACE0 \uBB3B\uAC70\uB098, get_onboarding_status\uAC00 \uC0C8 \uBC84\uC804\uC744 \uC54C\uB9B4 \uB54C \uD638\uCD9C\uD558\uC138\uC694. \uD655\uC778\uB9CC \uD558\uACE0 \uC124\uCE58\uB294 \uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. \uC0AC\uC6A9\uC790\uAC00 "\uC5C5\uB370\uC774\uD2B8\uD574\uC918/\uCD5C\uC2E0\uC73C\uB85C \uC62C\uB824\uC918"\uCC98\uB7FC \uBA85\uC2DC\uC801\uC73C\uB85C \uC694\uCCAD\uD558\uBA74 update_careermate\uB97C \uD638\uCD9C\uD558\uC138\uC694.',
|
|
115666
116211
|
inputSchema: {},
|
|
@@ -115684,6 +116229,9 @@ ${report.disclaimer}`, {
|
|
|
115684
116229
|
},
|
|
115685
116230
|
{
|
|
115686
116231
|
name: "update_careermate",
|
|
116232
|
+
// npm에서 패키지를 내려받아 설치 폴더의 코드를 교체한다.
|
|
116233
|
+
openWorld: true,
|
|
116234
|
+
destructive: true,
|
|
115687
116235
|
title: "CareerMate \uC5C5\uB370\uC774\uD2B8",
|
|
115688
116236
|
description: 'CareerMate\uB97C \uCD5C\uC2E0 \uBC84\uC804\uC73C\uB85C \uC5C5\uB370\uC774\uD2B8\uD569\uB2C8\uB2E4(\uC124\uCE58 \uD3F4\uB354\uC5D0 npm\uC73C\uB85C careermate@latest \uC124\uCE58). \uC0AC\uC6A9\uC790\uAC00 \uBA85\uC2DC\uC801\uC73C\uB85C "\uC5C5\uB370\uC774\uD2B8\uD574\uC918", "CareerMate \uC5C5\uB370\uC774\uD2B8\uD574\uC918", "\uCD5C\uC2E0\uC73C\uB85C \uC62C\uB824\uC918"\uB77C\uACE0 \uD560 \uB54C \uD638\uCD9C\uD558\uC138\uC694. \uC774 \uB3C4\uAD6C\uAC00 \uCD5C\uC2E0 \uBC84\uC804 \uD655\uC778\uB3C4 \uD568\uAED8 \uD558\uBBC0\uB85C \uBCC4\uB3C4 \uD655\uC778 \uC9C8\uBB38 \uC5C6\uC774 \uC2E4\uD589\uD574\uB3C4 \uB429\uB2C8\uB2E4. \uC131\uACF5\uD558\uBA74 \uC801\uC6A9\uC744 \uC704\uD574 AI \uC571(\uB610\uB294 MCP \uC5F0\uACB0) \uC7AC\uC2DC\uC791\uC774 \uD544\uC694\uD558\uBA70, \uC7AC\uC2DC\uC791 \uC2DC \uB370\uC774\uD130\uBCA0\uC774\uC2A4\uB294 \uC790\uB3D9 \uB9C8\uC774\uADF8\uB808\uC774\uC158\uB418\uC5B4 \uAE30\uC874 \uB370\uC774\uD130\uB294 \uBCF4\uC874\uB429\uB2C8\uB2E4. \uC790\uB3D9 \uC124\uCE58\uAC00 \uB9C9\uD788\uBA74(\uAC1C\uBC1C \uBAA8\uB4DC\xB7\uBE44\uD45C\uC900 \uC124\uCE58) \uC9C1\uC811 \uCE60 \uBA85\uB839\uC744 \uC548\uB0B4\uD569\uB2C8\uB2E4.',
|
|
115689
116237
|
inputSchema: {},
|
|
@@ -115713,10 +116261,16 @@ async function main() {
|
|
|
115713
116261
|
title: tool.title,
|
|
115714
116262
|
description: tool.description,
|
|
115715
116263
|
inputSchema: tool.inputSchema,
|
|
116264
|
+
// 어노테이션은 도구 정의(ToolDef)의 플래그를 그대로 반영한다 — 정직해야 한다.
|
|
116265
|
+
// openWorldHint: search_jobs(잡보드)·check_for_update/update_careermate(npm)처럼
|
|
116266
|
+
// 실제로 외부에 나가는 도구만 true. destructiveHint: 스펙 기본값이 true라
|
|
116267
|
+
// 업서트가 파괴적으로 오분류되지 않도록 비파괴 쓰기에는 명시적 false를 방출한다.
|
|
115716
116268
|
annotations: {
|
|
115717
116269
|
title: tool.title,
|
|
115718
116270
|
readOnlyHint: tool.readOnly ?? false,
|
|
115719
|
-
openWorldHint: false
|
|
116271
|
+
openWorldHint: tool.openWorld ?? false,
|
|
116272
|
+
destructiveHint: tool.destructive ?? false,
|
|
116273
|
+
idempotentHint: tool.idempotent ?? false
|
|
115720
116274
|
}
|
|
115721
116275
|
},
|
|
115722
116276
|
async (args) => {
|