@ttctl/mcp 0.0.0 → 0.1.0-rc.2
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/README.md +72 -9
- package/dist/auth.d.ts +40 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +69 -0
- package/dist/auth.js.map +1 -0
- package/dist/data-handling.d.ts +91 -0
- package/dist/data-handling.d.ts.map +1 -0
- package/dist/data-handling.js +129 -0
- package/dist/data-handling.js.map +1 -0
- package/dist/diagnostic.d.ts +262 -0
- package/dist/diagnostic.d.ts.map +1 -0
- package/dist/diagnostic.js +362 -0
- package/dist/diagnostic.js.map +1 -0
- package/dist/errors.d.ts +54 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +48 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/kill-switch-hook.d.ts +67 -0
- package/dist/kill-switch-hook.d.ts.map +1 -0
- package/dist/kill-switch-hook.js +61 -0
- package/dist/kill-switch-hook.js.map +1 -0
- package/dist/server.d.ts +100 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +157 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/_shared.d.ts +227 -0
- package/dist/tools/_shared.d.ts.map +1 -0
- package/dist/tools/_shared.js +238 -0
- package/dist/tools/_shared.js.map +1 -0
- package/dist/tools/applications.d.ts +27 -0
- package/dist/tools/applications.d.ts.map +1 -0
- package/dist/tools/applications.js +192 -0
- package/dist/tools/applications.js.map +1 -0
- package/dist/tools/availability.d.ts +33 -0
- package/dist/tools/availability.d.ts.map +1 -0
- package/dist/tools/availability.js +272 -0
- package/dist/tools/availability.js.map +1 -0
- package/dist/tools/contracts.d.ts +29 -0
- package/dist/tools/contracts.d.ts.map +1 -0
- package/dist/tools/contracts.js +157 -0
- package/dist/tools/contracts.js.map +1 -0
- package/dist/tools/engagements.d.ts +36 -0
- package/dist/tools/engagements.d.ts.map +1 -0
- package/dist/tools/engagements.js +408 -0
- package/dist/tools/engagements.js.map +1 -0
- package/dist/tools/file-upload.d.ts +133 -0
- package/dist/tools/file-upload.d.ts.map +1 -0
- package/dist/tools/file-upload.js +247 -0
- package/dist/tools/file-upload.js.map +1 -0
- package/dist/tools/index.d.ts +28 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +133 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/jobs.d.ts +37 -0
- package/dist/tools/jobs.d.ts.map +1 -0
- package/dist/tools/jobs.js +505 -0
- package/dist/tools/jobs.js.map +1 -0
- package/dist/tools/output-schemas.d.ts +129 -0
- package/dist/tools/output-schemas.d.ts.map +1 -0
- package/dist/tools/output-schemas.js +138 -0
- package/dist/tools/output-schemas.js.map +1 -0
- package/dist/tools/payments.d.ts +36 -0
- package/dist/tools/payments.d.ts.map +1 -0
- package/dist/tools/payments.js +373 -0
- package/dist/tools/payments.js.map +1 -0
- package/dist/tools/profile/certifications.d.ts +18 -0
- package/dist/tools/profile/certifications.d.ts.map +1 -0
- package/dist/tools/profile/certifications.js +219 -0
- package/dist/tools/profile/certifications.js.map +1 -0
- package/dist/tools/profile/education.d.ts +23 -0
- package/dist/tools/profile/education.d.ts.map +1 -0
- package/dist/tools/profile/education.js +222 -0
- package/dist/tools/profile/education.js.map +1 -0
- package/dist/tools/profile/employment.d.ts +23 -0
- package/dist/tools/profile/employment.d.ts.map +1 -0
- package/dist/tools/profile/employment.js +254 -0
- package/dist/tools/profile/employment.js.map +1 -0
- package/dist/tools/profile/industries.d.ts +30 -0
- package/dist/tools/profile/industries.d.ts.map +1 -0
- package/dist/tools/profile/industries.js +196 -0
- package/dist/tools/profile/industries.js.map +1 -0
- package/dist/tools/profile/portfolio.d.ts +22 -0
- package/dist/tools/profile/portfolio.d.ts.map +1 -0
- package/dist/tools/profile/portfolio.js +341 -0
- package/dist/tools/profile/portfolio.js.map +1 -0
- package/dist/tools/profile/resume.d.ts +16 -0
- package/dist/tools/profile/resume.d.ts.map +1 -0
- package/dist/tools/profile/resume.js +107 -0
- package/dist/tools/profile/resume.js.map +1 -0
- package/dist/tools/profile/shared.d.ts +85 -0
- package/dist/tools/profile/shared.d.ts.map +1 -0
- package/dist/tools/profile/shared.js +128 -0
- package/dist/tools/profile/shared.js.map +1 -0
- package/dist/tools/profile/visas.d.ts +15 -0
- package/dist/tools/profile/visas.d.ts.map +1 -0
- package/dist/tools/profile/visas.js +170 -0
- package/dist/tools/profile/visas.js.map +1 -0
- package/dist/tools/profile_basic_photo_show.d.ts +14 -0
- package/dist/tools/profile_basic_photo_show.d.ts.map +1 -0
- package/dist/tools/profile_basic_photo_show.js +59 -0
- package/dist/tools/profile_basic_photo_show.js.map +1 -0
- package/dist/tools/profile_basic_photo_upload.d.ts +24 -0
- package/dist/tools/profile_basic_photo_upload.d.ts.map +1 -0
- package/dist/tools/profile_basic_photo_upload.js +90 -0
- package/dist/tools/profile_basic_photo_upload.js.map +1 -0
- package/dist/tools/profile_basic_show.d.ts +64 -0
- package/dist/tools/profile_basic_show.d.ts.map +1 -0
- package/dist/tools/profile_basic_show.js +108 -0
- package/dist/tools/profile_basic_show.js.map +1 -0
- package/dist/tools/profile_basic_update.d.ts +37 -0
- package/dist/tools/profile_basic_update.d.ts.map +1 -0
- package/dist/tools/profile_basic_update.js +97 -0
- package/dist/tools/profile_basic_update.js.map +1 -0
- package/dist/tools/profile_external_advanced_wizard_show.d.ts +14 -0
- package/dist/tools/profile_external_advanced_wizard_show.d.ts.map +1 -0
- package/dist/tools/profile_external_advanced_wizard_show.js +56 -0
- package/dist/tools/profile_external_advanced_wizard_show.js.map +1 -0
- package/dist/tools/profile_external_custom_requirements_set.d.ts +13 -0
- package/dist/tools/profile_external_custom_requirements_set.d.ts.map +1 -0
- package/dist/tools/profile_external_custom_requirements_set.js +75 -0
- package/dist/tools/profile_external_custom_requirements_set.js.map +1 -0
- package/dist/tools/profile_external_custom_requirements_show.d.ts +14 -0
- package/dist/tools/profile_external_custom_requirements_show.d.ts.map +1 -0
- package/dist/tools/profile_external_custom_requirements_show.js +56 -0
- package/dist/tools/profile_external_custom_requirements_show.js.map +1 -0
- package/dist/tools/profile_external_readiness.d.ts +12 -0
- package/dist/tools/profile_external_readiness.d.ts.map +1 -0
- package/dist/tools/profile_external_readiness.js +54 -0
- package/dist/tools/profile_external_readiness.js.map +1 -0
- package/dist/tools/profile_external_recommendations.d.ts +15 -0
- package/dist/tools/profile_external_recommendations.d.ts.map +1 -0
- package/dist/tools/profile_external_recommendations.js +57 -0
- package/dist/tools/profile_external_recommendations.js.map +1 -0
- package/dist/tools/profile_external_show.d.ts +15 -0
- package/dist/tools/profile_external_show.d.ts.map +1 -0
- package/dist/tools/profile_external_show.js +59 -0
- package/dist/tools/profile_external_show.js.map +1 -0
- package/dist/tools/profile_external_update.d.ts +14 -0
- package/dist/tools/profile_external_update.d.ts.map +1 -0
- package/dist/tools/profile_external_update.js +79 -0
- package/dist/tools/profile_external_update.js.map +1 -0
- package/dist/tools/profile_reviews_approve_item.d.ts +17 -0
- package/dist/tools/profile_reviews_approve_item.d.ts.map +1 -0
- package/dist/tools/profile_reviews_approve_item.js +77 -0
- package/dist/tools/profile_reviews_approve_item.js.map +1 -0
- package/dist/tools/profile_reviews_approve_section.d.ts +15 -0
- package/dist/tools/profile_reviews_approve_section.d.ts.map +1 -0
- package/dist/tools/profile_reviews_approve_section.js +70 -0
- package/dist/tools/profile_reviews_approve_section.js.map +1 -0
- package/dist/tools/profile_reviews_list.d.ts +16 -0
- package/dist/tools/profile_reviews_list.d.ts.map +1 -0
- package/dist/tools/profile_reviews_list.js +58 -0
- package/dist/tools/profile_reviews_list.js.map +1 -0
- package/dist/tools/profile_reviews_submit_for_review.d.ts +14 -0
- package/dist/tools/profile_reviews_submit_for_review.d.ts.map +1 -0
- package/dist/tools/profile_reviews_submit_for_review.js +56 -0
- package/dist/tools/profile_reviews_submit_for_review.js.map +1 -0
- package/dist/tools/profile_skills_add.d.ts +4 -0
- package/dist/tools/profile_skills_add.d.ts.map +1 -0
- package/dist/tools/profile_skills_add.js +52 -0
- package/dist/tools/profile_skills_add.js.map +1 -0
- package/dist/tools/profile_skills_autocomplete.d.ts +4 -0
- package/dist/tools/profile_skills_autocomplete.d.ts.map +1 -0
- package/dist/tools/profile_skills_autocomplete.js +78 -0
- package/dist/tools/profile_skills_autocomplete.js.map +1 -0
- package/dist/tools/profile_skills_list.d.ts +16 -0
- package/dist/tools/profile_skills_list.d.ts.map +1 -0
- package/dist/tools/profile_skills_list.js +65 -0
- package/dist/tools/profile_skills_list.js.map +1 -0
- package/dist/tools/profile_skills_readiness.d.ts +4 -0
- package/dist/tools/profile_skills_readiness.d.ts.map +1 -0
- package/dist/tools/profile_skills_readiness.js +53 -0
- package/dist/tools/profile_skills_readiness.js.map +1 -0
- package/dist/tools/profile_skills_remove.d.ts +4 -0
- package/dist/tools/profile_skills_remove.d.ts.map +1 -0
- package/dist/tools/profile_skills_remove.js +53 -0
- package/dist/tools/profile_skills_remove.js.map +1 -0
- package/dist/tools/profile_skills_show.d.ts +4 -0
- package/dist/tools/profile_skills_show.d.ts.map +1 -0
- package/dist/tools/profile_skills_show.js +51 -0
- package/dist/tools/profile_skills_show.js.map +1 -0
- package/dist/tools/profile_skills_update.d.ts +11 -0
- package/dist/tools/profile_skills_update.d.ts.map +1 -0
- package/dist/tools/profile_skills_update.js +97 -0
- package/dist/tools/profile_skills_update.js.map +1 -0
- package/dist/tools/timesheet.d.ts +29 -0
- package/dist/tools/timesheet.d.ts.map +1 -0
- package/dist/tools/timesheet.js +257 -0
- package/dist/tools/timesheet.js.map +1 -0
- package/package.json +33 -13
- package/index.js +0 -7
|
@@ -0,0 +1,505 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-only
|
|
2
|
+
// Copyright (C) 2026 Oleksii PELYKH
|
|
3
|
+
import { jobs } from "@ttctl/core";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { ttctlErrorToToolResponseOrNull } from "../errors.js";
|
|
6
|
+
import { buildMcpDryRunPreview, dryRunResponse } from "./_shared.js";
|
|
7
|
+
const DRY_RUN_FIELD = z
|
|
8
|
+
.boolean()
|
|
9
|
+
.optional()
|
|
10
|
+
.describe("Preview the request without executing. Returns `{ ok: true, dryRun: true, preview }` with operationName + variables + redacted bearer header. Default: false.");
|
|
11
|
+
/**
|
|
12
|
+
* Build the variables payload `core.jobs` (`buildListVariables` in
|
|
13
|
+
* `core/services/jobs/index.ts`) sends to `JobsList` so a dry-run
|
|
14
|
+
* preview from the MCP layer matches the apply path's wire shape.
|
|
15
|
+
* Mirrors the apply-path "empty/undefined → null" coercion so listed
|
|
16
|
+
* filters render the same way as the actual wire call.
|
|
17
|
+
*/
|
|
18
|
+
function buildJobsListVariables(opts, extras) {
|
|
19
|
+
const variables = {
|
|
20
|
+
skills: opts.skills && opts.skills.length > 0 ? opts.skills : null,
|
|
21
|
+
keywords: opts.keywords && opts.keywords.length > 0 ? opts.keywords : null,
|
|
22
|
+
excludeSkills: opts.excludeSkills && opts.excludeSkills.length > 0 ? opts.excludeSkills : null,
|
|
23
|
+
excludeKeywords: opts.excludeKeywords && opts.excludeKeywords.length > 0 ? opts.excludeKeywords : null,
|
|
24
|
+
commitments: opts.commitments && opts.commitments.length > 0 ? opts.commitments : null,
|
|
25
|
+
workTypes: opts.workTypes && opts.workTypes.length > 0 ? opts.workTypes : null,
|
|
26
|
+
estimatedLengths: opts.estimatedLengths && opts.estimatedLengths.length > 0 ? opts.estimatedLengths : null,
|
|
27
|
+
sortTarget: opts.sortTarget ?? null,
|
|
28
|
+
saved: extras.saved !== undefined ? { eq: extras.saved } : null,
|
|
29
|
+
notInterested: extras.notInterested !== undefined ? { eq: extras.notInterested } : null,
|
|
30
|
+
};
|
|
31
|
+
return variables;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Register the `ttctl_jobs_*` MCP tools per #148. Tool names use the
|
|
35
|
+
* `ttctl_` prefix and the canonical CLI path joined with `_`. Per the
|
|
36
|
+
* AC, MCP tools use the canonical `jobs_*` prefix only — no
|
|
37
|
+
* `opportunities_*` aliasing (MCP tool names must be deterministic for
|
|
38
|
+
* LLM clients).
|
|
39
|
+
*
|
|
40
|
+
* Tool surface (13 tools):
|
|
41
|
+
* - `ttctl_jobs_list`
|
|
42
|
+
* - `ttctl_jobs_show`
|
|
43
|
+
* - `ttctl_jobs_save`
|
|
44
|
+
* - `ttctl_jobs_unsave`
|
|
45
|
+
* - `ttctl_jobs_saved`
|
|
46
|
+
* - `ttctl_jobs_viewed`
|
|
47
|
+
* - `ttctl_jobs_mark_viewed`
|
|
48
|
+
* - `ttctl_jobs_not_interested`
|
|
49
|
+
* - `ttctl_jobs_not_interested_list`
|
|
50
|
+
* - `ttctl_jobs_clear_interest`
|
|
51
|
+
* - `ttctl_jobs_search_list`
|
|
52
|
+
* - `ttctl_jobs_search_save`
|
|
53
|
+
* - `ttctl_jobs_search_remove`
|
|
54
|
+
*
|
|
55
|
+
* **Wire-shape notes** (R1 / R2): `jobs_viewed` is scoped to the first
|
|
56
|
+
* page (≤20 jobs, client-side filter); `jobs_search_*` operates on a
|
|
57
|
+
* single subscription per user. The tool descriptions surface these.
|
|
58
|
+
*
|
|
59
|
+
* Dry-run path (issue #165): every tool accepts `dryRun?: boolean`. Read
|
|
60
|
+
* tools build the preview at the MCP layer; the 7 mutations (save,
|
|
61
|
+
* unsave, mark_viewed, not_interested, clear_interest, search_save,
|
|
62
|
+
* search_remove) passthrough-forward `{ dryRun: true }` to the core
|
|
63
|
+
* (which already supports dryRun per #162) and reformat the
|
|
64
|
+
* `{ kind: "preview", preview }` outcome as the uniform envelope.
|
|
65
|
+
*/
|
|
66
|
+
export function registerJobsTools(server, ctx) {
|
|
67
|
+
// -------- list ---------------------------------------------------------
|
|
68
|
+
server.registerTool("ttctl_jobs_list", {
|
|
69
|
+
title: "Browse current job opportunities",
|
|
70
|
+
description: [
|
|
71
|
+
"Browse the user's current job opportunities on Toptal Talent.",
|
|
72
|
+
"Returns the first page of eligible jobs (≤20).",
|
|
73
|
+
"",
|
|
74
|
+
"Optional filters:",
|
|
75
|
+
" - `skills` / `keywords`: AND-across filter on required skills / free text",
|
|
76
|
+
" - `excludeSkills` / `excludeKeywords`: exclusion filters",
|
|
77
|
+
" - `commitments`: e.g. FULL_TIME, PART_TIME",
|
|
78
|
+
" - `workTypes`: e.g. REMOTE, ONSITE",
|
|
79
|
+
" - `estimatedLengths`: e.g. SHORT_TERM, LONG_TERM",
|
|
80
|
+
" - `sortTarget`: e.g. visible_at, posted_at",
|
|
81
|
+
"",
|
|
82
|
+
"Example user prompts:",
|
|
83
|
+
' - "Show me current Toptal job opportunities."',
|
|
84
|
+
' - "List remote part-time Toptal jobs with React skills."',
|
|
85
|
+
].join("\n"),
|
|
86
|
+
inputSchema: {
|
|
87
|
+
skills: z.array(z.string()).optional().describe("Required skill names (AND across)"),
|
|
88
|
+
keywords: z.array(z.string()).optional().describe("Free-text keywords (AND across)"),
|
|
89
|
+
excludeSkills: z.array(z.string()).optional().describe("Skills to exclude"),
|
|
90
|
+
excludeKeywords: z.array(z.string()).optional().describe("Keywords to exclude"),
|
|
91
|
+
commitments: z.array(z.string()).optional().describe("JobCommitmentFilterEnum values"),
|
|
92
|
+
workTypes: z.array(z.string()).optional().describe("JobWorkTypeSlug values"),
|
|
93
|
+
estimatedLengths: z.array(z.string()).optional().describe("EstimatedLengthFilterEnum values"),
|
|
94
|
+
sortTarget: z.string().optional().describe("Sort target (e.g. visible_at, posted_at)"),
|
|
95
|
+
dryRun: DRY_RUN_FIELD,
|
|
96
|
+
},
|
|
97
|
+
}, async (args) => {
|
|
98
|
+
const auth = await ctx.resolveToolAuth();
|
|
99
|
+
if (!auth.ok)
|
|
100
|
+
return auth.response;
|
|
101
|
+
const opts = {};
|
|
102
|
+
if (args.skills !== undefined)
|
|
103
|
+
opts.skills = args.skills;
|
|
104
|
+
if (args.keywords !== undefined)
|
|
105
|
+
opts.keywords = args.keywords;
|
|
106
|
+
if (args.excludeSkills !== undefined)
|
|
107
|
+
opts.excludeSkills = args.excludeSkills;
|
|
108
|
+
if (args.excludeKeywords !== undefined)
|
|
109
|
+
opts.excludeKeywords = args.excludeKeywords;
|
|
110
|
+
if (args.commitments !== undefined)
|
|
111
|
+
opts.commitments = args.commitments;
|
|
112
|
+
if (args.workTypes !== undefined)
|
|
113
|
+
opts.workTypes = args.workTypes;
|
|
114
|
+
if (args.estimatedLengths !== undefined)
|
|
115
|
+
opts.estimatedLengths = args.estimatedLengths;
|
|
116
|
+
if (args.sortTarget !== undefined)
|
|
117
|
+
opts.sortTarget = args.sortTarget;
|
|
118
|
+
if (args.dryRun === true) {
|
|
119
|
+
return dryRunResponse(buildMcpDryRunPreview("JobsList", "mobile-gateway", buildJobsListVariables(opts, {}), auth.token));
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
// MCP unwraps the JobListPage to items only (issue #138 wires
|
|
123
|
+
// pagination on the CLI surface; MCP pagination is a separate
|
|
124
|
+
// follow-up). The wire still returns totalCount + page/perPage
|
|
125
|
+
// — those are discarded here to preserve the MCP output
|
|
126
|
+
// contract (`JobListItem[]`).
|
|
127
|
+
const page = await jobs.list(auth.token, opts);
|
|
128
|
+
return successResponse(page.items);
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
return mapJobsError(err);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
// -------- show ---------------------------------------------------------
|
|
135
|
+
server.registerTool("ttctl_jobs_show", {
|
|
136
|
+
title: "Show one job by id",
|
|
137
|
+
description: [
|
|
138
|
+
"Fetch a single job's detail view by id.",
|
|
139
|
+
"Returns title, description, skills, client metadata, time-zone, rates, and interest-state flags.",
|
|
140
|
+
"",
|
|
141
|
+
"Example user prompts:",
|
|
142
|
+
' - "Show me Toptal job job_abc123."',
|
|
143
|
+
' - "What\'s the description for that job I just listed?"',
|
|
144
|
+
].join("\n"),
|
|
145
|
+
inputSchema: {
|
|
146
|
+
id: z.string().describe("Job id (from `ttctl_jobs_list`)"),
|
|
147
|
+
dryRun: DRY_RUN_FIELD,
|
|
148
|
+
},
|
|
149
|
+
}, async (args) => {
|
|
150
|
+
const auth = await ctx.resolveToolAuth();
|
|
151
|
+
if (!auth.ok)
|
|
152
|
+
return auth.response;
|
|
153
|
+
if (args.dryRun === true) {
|
|
154
|
+
return dryRunResponse(buildMcpDryRunPreview("JobShow", "mobile-gateway", { id: args.id }, auth.token));
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
const item = await jobs.show(auth.token, args.id);
|
|
158
|
+
return successResponse(item);
|
|
159
|
+
}
|
|
160
|
+
catch (err) {
|
|
161
|
+
return mapJobsError(err);
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
// -------- save ---------------------------------------------------------
|
|
165
|
+
server.registerTool("ttctl_jobs_save", {
|
|
166
|
+
title: "Save a job (bookmark)",
|
|
167
|
+
description: [
|
|
168
|
+
"Mark a Toptal job as saved (bookmark). The job appears in `ttctl_jobs_saved` afterwards.",
|
|
169
|
+
"",
|
|
170
|
+
"If the job was previously marked not-interested, this mutation clears that flag (the wire's interest-status model is one-of-three: saved / not-interested / cleared).",
|
|
171
|
+
].join("\n"),
|
|
172
|
+
inputSchema: { id: z.string().describe("Job id"), dryRun: DRY_RUN_FIELD },
|
|
173
|
+
}, async (args) => {
|
|
174
|
+
const auth = await ctx.resolveToolAuth();
|
|
175
|
+
if (!auth.ok)
|
|
176
|
+
return auth.response;
|
|
177
|
+
try {
|
|
178
|
+
const outcome = await jobs.save(auth.token, args.id, { dryRun: args.dryRun ?? false });
|
|
179
|
+
if (outcome.kind === "preview")
|
|
180
|
+
return dryRunResponse(outcome.preview);
|
|
181
|
+
return successResponse(outcome.result);
|
|
182
|
+
}
|
|
183
|
+
catch (err) {
|
|
184
|
+
return mapJobsError(err);
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
// -------- unsave -------------------------------------------------------
|
|
188
|
+
server.registerTool("ttctl_jobs_unsave", {
|
|
189
|
+
title: "Remove a job from saved",
|
|
190
|
+
description: [
|
|
191
|
+
"Clear interest flags on a Toptal job — the wire's only 'remove saved' path.",
|
|
192
|
+
"Note that this ALSO clears `not-interested` (single wire mutation covers both signals).",
|
|
193
|
+
].join("\n"),
|
|
194
|
+
inputSchema: { id: z.string().describe("Job id"), dryRun: DRY_RUN_FIELD },
|
|
195
|
+
}, async (args) => {
|
|
196
|
+
const auth = await ctx.resolveToolAuth();
|
|
197
|
+
if (!auth.ok)
|
|
198
|
+
return auth.response;
|
|
199
|
+
try {
|
|
200
|
+
const outcome = await jobs.unsave(auth.token, args.id, { dryRun: args.dryRun ?? false });
|
|
201
|
+
if (outcome.kind === "preview")
|
|
202
|
+
return dryRunResponse(outcome.preview);
|
|
203
|
+
return successResponse(outcome.result);
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
return mapJobsError(err);
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
// -------- saved --------------------------------------------------------
|
|
210
|
+
server.registerTool("ttctl_jobs_saved", {
|
|
211
|
+
title: "List saved jobs",
|
|
212
|
+
description: "List the user's saved (bookmarked) Toptal jobs.",
|
|
213
|
+
inputSchema: { dryRun: DRY_RUN_FIELD },
|
|
214
|
+
}, async (args) => {
|
|
215
|
+
const auth = await ctx.resolveToolAuth();
|
|
216
|
+
if (!auth.ok)
|
|
217
|
+
return auth.response;
|
|
218
|
+
if (args.dryRun === true) {
|
|
219
|
+
return dryRunResponse(buildMcpDryRunPreview("JobsList", "mobile-gateway", buildJobsListVariables({}, { saved: true }), auth.token));
|
|
220
|
+
}
|
|
221
|
+
try {
|
|
222
|
+
// MCP unwraps the JobListPage to items only (issue #138; see
|
|
223
|
+
// jobs_list for rationale).
|
|
224
|
+
const page = await jobs.saved(auth.token);
|
|
225
|
+
return successResponse(page.items);
|
|
226
|
+
}
|
|
227
|
+
catch (err) {
|
|
228
|
+
return mapJobsError(err);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
// -------- viewed -------------------------------------------------------
|
|
232
|
+
server.registerTool("ttctl_jobs_viewed", {
|
|
233
|
+
title: "List viewed jobs (best-effort, first page only)",
|
|
234
|
+
description: [
|
|
235
|
+
"List Toptal jobs the user has marked as viewed.",
|
|
236
|
+
"",
|
|
237
|
+
"**Limitation (R1)**: the wire has no `viewed` filter on eligibleJobs.",
|
|
238
|
+
"This tool fetches the first page of eligible jobs (≤20) and filters",
|
|
239
|
+
"client-side on the `viewed` boolean. Jobs viewed but on subsequent",
|
|
240
|
+
"pages will not appear.",
|
|
241
|
+
"",
|
|
242
|
+
"Dry-run note: the apply path issues `JobsList` (the same query used by `ttctl_jobs_list`) and filters client-side on `viewed` — the preview reflects the wire call accordingly.",
|
|
243
|
+
].join("\n"),
|
|
244
|
+
inputSchema: { dryRun: DRY_RUN_FIELD },
|
|
245
|
+
}, async (args) => {
|
|
246
|
+
const auth = await ctx.resolveToolAuth();
|
|
247
|
+
if (!auth.ok)
|
|
248
|
+
return auth.response;
|
|
249
|
+
if (args.dryRun === true) {
|
|
250
|
+
return dryRunResponse(buildMcpDryRunPreview("JobsList", "mobile-gateway", buildJobsListVariables({}, {}), auth.token));
|
|
251
|
+
}
|
|
252
|
+
try {
|
|
253
|
+
// MCP unwraps the JobListPage to items only (issue #138; see
|
|
254
|
+
// jobs_list for rationale). totalCount here reflects the
|
|
255
|
+
// underlying eligibleJobs fetch (pre-`viewed` filter), not the
|
|
256
|
+
// returned items.length.
|
|
257
|
+
const page = await jobs.viewedList(auth.token);
|
|
258
|
+
return successResponse(page.items);
|
|
259
|
+
}
|
|
260
|
+
catch (err) {
|
|
261
|
+
return mapJobsError(err);
|
|
262
|
+
}
|
|
263
|
+
});
|
|
264
|
+
// -------- mark_viewed --------------------------------------------------
|
|
265
|
+
server.registerTool("ttctl_jobs_mark_viewed", {
|
|
266
|
+
title: "Explicitly mark a job as viewed",
|
|
267
|
+
description: [
|
|
268
|
+
"Mark a Toptal job as viewed.",
|
|
269
|
+
"The web UI normally auto-marks on detail-page open — this tool exposes the mutation for completeness.",
|
|
270
|
+
].join("\n"),
|
|
271
|
+
inputSchema: { id: z.string().describe("Job id"), dryRun: DRY_RUN_FIELD },
|
|
272
|
+
}, async (args) => {
|
|
273
|
+
const auth = await ctx.resolveToolAuth();
|
|
274
|
+
if (!auth.ok)
|
|
275
|
+
return auth.response;
|
|
276
|
+
try {
|
|
277
|
+
const outcome = await jobs.markViewed(auth.token, args.id, { dryRun: args.dryRun ?? false });
|
|
278
|
+
if (outcome.kind === "preview")
|
|
279
|
+
return dryRunResponse(outcome.preview);
|
|
280
|
+
return successResponse(outcome.result);
|
|
281
|
+
}
|
|
282
|
+
catch (err) {
|
|
283
|
+
return mapJobsError(err);
|
|
284
|
+
}
|
|
285
|
+
});
|
|
286
|
+
// -------- not_interested -----------------------------------------------
|
|
287
|
+
server.registerTool("ttctl_jobs_not_interested", {
|
|
288
|
+
title: "Mark a job as not-interested",
|
|
289
|
+
description: [
|
|
290
|
+
"Mark a Toptal job as not-interested with a reason.",
|
|
291
|
+
"`reason` is required (server rejects empty strings).",
|
|
292
|
+
"",
|
|
293
|
+
"If the job was previously saved, this mutation clears the saved flag.",
|
|
294
|
+
].join("\n"),
|
|
295
|
+
inputSchema: {
|
|
296
|
+
id: z.string().describe("Job id"),
|
|
297
|
+
reason: z.string().min(1).describe("Reason for dismissing (free-text)"),
|
|
298
|
+
dryRun: DRY_RUN_FIELD,
|
|
299
|
+
},
|
|
300
|
+
}, async (args) => {
|
|
301
|
+
const auth = await ctx.resolveToolAuth();
|
|
302
|
+
if (!auth.ok)
|
|
303
|
+
return auth.response;
|
|
304
|
+
try {
|
|
305
|
+
const outcome = await jobs.notInterested(auth.token, args.id, { reason: args.reason }, { dryRun: args.dryRun ?? false });
|
|
306
|
+
if (outcome.kind === "preview")
|
|
307
|
+
return dryRunResponse(outcome.preview);
|
|
308
|
+
return successResponse(outcome.result);
|
|
309
|
+
}
|
|
310
|
+
catch (err) {
|
|
311
|
+
return mapJobsError(err);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
// -------- not_interested_list ------------------------------------------
|
|
315
|
+
server.registerTool("ttctl_jobs_not_interested_list", {
|
|
316
|
+
title: "List jobs marked as not-interested",
|
|
317
|
+
description: "List Toptal jobs the user marked as not-interested.",
|
|
318
|
+
inputSchema: { dryRun: DRY_RUN_FIELD },
|
|
319
|
+
}, async (args) => {
|
|
320
|
+
const auth = await ctx.resolveToolAuth();
|
|
321
|
+
if (!auth.ok)
|
|
322
|
+
return auth.response;
|
|
323
|
+
if (args.dryRun === true) {
|
|
324
|
+
return dryRunResponse(buildMcpDryRunPreview("JobsList", "mobile-gateway", buildJobsListVariables({}, { notInterested: true }), auth.token));
|
|
325
|
+
}
|
|
326
|
+
try {
|
|
327
|
+
// MCP unwraps the JobListPage to items only (issue #138; see
|
|
328
|
+
// jobs_list for rationale).
|
|
329
|
+
const page = await jobs.notInterestedList(auth.token);
|
|
330
|
+
return successResponse(page.items);
|
|
331
|
+
}
|
|
332
|
+
catch (err) {
|
|
333
|
+
return mapJobsError(err);
|
|
334
|
+
}
|
|
335
|
+
});
|
|
336
|
+
// -------- clear_interest -----------------------------------------------
|
|
337
|
+
server.registerTool("ttctl_jobs_clear_interest", {
|
|
338
|
+
title: "Clear interest flags on a job",
|
|
339
|
+
description: [
|
|
340
|
+
"Clear interest flags (both `saved` and `not-interested`) on a job.",
|
|
341
|
+
"Use this to undo a previous `not-interested` mark, or to remove a job from saved.",
|
|
342
|
+
].join("\n"),
|
|
343
|
+
inputSchema: { id: z.string().describe("Job id"), dryRun: DRY_RUN_FIELD },
|
|
344
|
+
}, async (args) => {
|
|
345
|
+
const auth = await ctx.resolveToolAuth();
|
|
346
|
+
if (!auth.ok)
|
|
347
|
+
return auth.response;
|
|
348
|
+
try {
|
|
349
|
+
const outcome = await jobs.clearInterest(auth.token, args.id, { dryRun: args.dryRun ?? false });
|
|
350
|
+
if (outcome.kind === "preview")
|
|
351
|
+
return dryRunResponse(outcome.preview);
|
|
352
|
+
return successResponse(outcome.result);
|
|
353
|
+
}
|
|
354
|
+
catch (err) {
|
|
355
|
+
return mapJobsError(err);
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
// -------- search_list --------------------------------------------------
|
|
359
|
+
server.registerTool("ttctl_jobs_search_list", {
|
|
360
|
+
title: "Show the active job-search subscription",
|
|
361
|
+
description: [
|
|
362
|
+
"Show the user's current job-search subscription state.",
|
|
363
|
+
"",
|
|
364
|
+
"**Cardinality note (R2)**: the platform supports a SINGLE subscription per user — there is no list of named subscriptions.",
|
|
365
|
+
"Returns `{ active: false, filters: null }` when no subscription is active, or the active subscription filters when one is.",
|
|
366
|
+
].join("\n"),
|
|
367
|
+
inputSchema: { dryRun: DRY_RUN_FIELD },
|
|
368
|
+
}, async (args) => {
|
|
369
|
+
const auth = await ctx.resolveToolAuth();
|
|
370
|
+
if (!auth.ok)
|
|
371
|
+
return auth.response;
|
|
372
|
+
if (args.dryRun === true) {
|
|
373
|
+
return dryRunResponse(buildMcpDryRunPreview("JobSearchSubscriptionShow", "mobile-gateway", {}, auth.token));
|
|
374
|
+
}
|
|
375
|
+
try {
|
|
376
|
+
const state = await jobs.searchSubscriptionShow(auth.token);
|
|
377
|
+
return successResponse(state);
|
|
378
|
+
}
|
|
379
|
+
catch (err) {
|
|
380
|
+
return mapJobsError(err);
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
// -------- search_save --------------------------------------------------
|
|
384
|
+
server.registerTool("ttctl_jobs_search_save", {
|
|
385
|
+
title: "Start (or replace) the job-search subscription",
|
|
386
|
+
description: [
|
|
387
|
+
"Start a new job-search subscription with the supplied filters.",
|
|
388
|
+
"If a subscription is already active, it is replaced.",
|
|
389
|
+
"",
|
|
390
|
+
"Returns the post-mutation subscription state.",
|
|
391
|
+
].join("\n"),
|
|
392
|
+
inputSchema: {
|
|
393
|
+
skills: z.array(z.string()).optional(),
|
|
394
|
+
keywords: z.array(z.string()).optional(),
|
|
395
|
+
excludeSkills: z.array(z.string()).optional(),
|
|
396
|
+
excludeKeywords: z.array(z.string()).optional(),
|
|
397
|
+
commitments: z.array(z.string()).optional(),
|
|
398
|
+
workTypes: z.array(z.string()).optional(),
|
|
399
|
+
estimatedLengths: z.array(z.string()).optional(),
|
|
400
|
+
excludeUnspecifiedBudget: z.boolean().optional(),
|
|
401
|
+
dryRun: DRY_RUN_FIELD,
|
|
402
|
+
},
|
|
403
|
+
}, async (args) => {
|
|
404
|
+
const auth = await ctx.resolveToolAuth();
|
|
405
|
+
if (!auth.ok)
|
|
406
|
+
return auth.response;
|
|
407
|
+
try {
|
|
408
|
+
const filters = {};
|
|
409
|
+
if (args.skills !== undefined)
|
|
410
|
+
filters.skills = args.skills;
|
|
411
|
+
if (args.keywords !== undefined)
|
|
412
|
+
filters.keywords = args.keywords;
|
|
413
|
+
if (args.excludeSkills !== undefined)
|
|
414
|
+
filters.excludeSkills = args.excludeSkills;
|
|
415
|
+
if (args.excludeKeywords !== undefined)
|
|
416
|
+
filters.excludeKeywords = args.excludeKeywords;
|
|
417
|
+
if (args.commitments !== undefined)
|
|
418
|
+
filters.commitments = args.commitments;
|
|
419
|
+
if (args.workTypes !== undefined)
|
|
420
|
+
filters.workTypes = args.workTypes;
|
|
421
|
+
if (args.estimatedLengths !== undefined)
|
|
422
|
+
filters.estimatedLengths = args.estimatedLengths;
|
|
423
|
+
if (args.excludeUnspecifiedBudget !== undefined) {
|
|
424
|
+
filters.excludeUnspecifiedBudget = args.excludeUnspecifiedBudget;
|
|
425
|
+
}
|
|
426
|
+
const outcome = await jobs.searchSubscriptionSave(auth.token, filters, { dryRun: args.dryRun ?? false });
|
|
427
|
+
if (outcome.kind === "preview")
|
|
428
|
+
return dryRunResponse(outcome.preview);
|
|
429
|
+
return successResponse(outcome.result);
|
|
430
|
+
}
|
|
431
|
+
catch (err) {
|
|
432
|
+
return mapJobsError(err);
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
// -------- search_remove ------------------------------------------------
|
|
436
|
+
server.registerTool("ttctl_jobs_search_remove", {
|
|
437
|
+
title: "Terminate the active job-search subscription",
|
|
438
|
+
description: [
|
|
439
|
+
"Terminate the user's active job-search subscription.",
|
|
440
|
+
"Idempotent — terminating a non-active subscription returns success.",
|
|
441
|
+
].join("\n"),
|
|
442
|
+
inputSchema: { dryRun: DRY_RUN_FIELD },
|
|
443
|
+
}, async (args) => {
|
|
444
|
+
const auth = await ctx.resolveToolAuth();
|
|
445
|
+
if (!auth.ok)
|
|
446
|
+
return auth.response;
|
|
447
|
+
try {
|
|
448
|
+
const outcome = await jobs.searchSubscriptionRemove(auth.token, { dryRun: args.dryRun ?? false });
|
|
449
|
+
if (outcome.kind === "preview")
|
|
450
|
+
return dryRunResponse(outcome.preview);
|
|
451
|
+
return successResponse(outcome.result);
|
|
452
|
+
}
|
|
453
|
+
catch (err) {
|
|
454
|
+
return mapJobsError(err);
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
function successResponse(data) {
|
|
459
|
+
return {
|
|
460
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
function mapJobsError(err) {
|
|
464
|
+
const typed = ttctlErrorToToolResponseOrNull(err);
|
|
465
|
+
if (typed !== null)
|
|
466
|
+
return typed;
|
|
467
|
+
if (err instanceof jobs.JobsError) {
|
|
468
|
+
return {
|
|
469
|
+
isError: true,
|
|
470
|
+
content: [
|
|
471
|
+
{
|
|
472
|
+
type: "text",
|
|
473
|
+
text: [
|
|
474
|
+
`Error: ${err.message}`,
|
|
475
|
+
"",
|
|
476
|
+
err.code === "NOT_FOUND"
|
|
477
|
+
? "Recovery: Verify the job id (use ttctl_jobs_list to discover it)."
|
|
478
|
+
: err.code === "MUTATION_ERROR"
|
|
479
|
+
? "Recovery: Check the mutation input — the server reported a per-field validation failure."
|
|
480
|
+
: "Recovery: Adjust the tool input or retry; see the code below.",
|
|
481
|
+
"",
|
|
482
|
+
`(Code: ${err.code})`,
|
|
483
|
+
].join("\n"),
|
|
484
|
+
},
|
|
485
|
+
],
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
489
|
+
return {
|
|
490
|
+
isError: true,
|
|
491
|
+
content: [
|
|
492
|
+
{
|
|
493
|
+
type: "text",
|
|
494
|
+
text: [
|
|
495
|
+
`Error: jobs request failed: ${message}`,
|
|
496
|
+
"",
|
|
497
|
+
"Recovery: Retry; if the failure persists, file an issue.",
|
|
498
|
+
"",
|
|
499
|
+
"(Code: UNKNOWN)",
|
|
500
|
+
].join("\n"),
|
|
501
|
+
},
|
|
502
|
+
],
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
//# sourceMappingURL=jobs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/tools/jobs.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* MCP `outputSchema` definitions for the top-10 write-capable tools
|
|
4
|
+
* (#226). Each schema mirrors the TypeScript return type from
|
|
5
|
+
* `@ttctl/core` so LLM clients reading the tool registry can validate
|
|
6
|
+
* the structured payload they receive.
|
|
7
|
+
*
|
|
8
|
+
* Each schema describes the SUCCESS-path payload only. Dry-run responses
|
|
9
|
+
* use the uniform `{ ok, dryRun, preview }` envelope advertised via the
|
|
10
|
+
* tool description (see `_shared.ts` § `dryRunResponse`) and intentionally
|
|
11
|
+
* carry NO `structuredContent` — the SDK skips `outputSchema` validation
|
|
12
|
+
* when `structuredContent` is absent (per `@modelcontextprotocol/sdk`
|
|
13
|
+
* `_validateOutput`), so dry-run paths bypass success-shape validation
|
|
14
|
+
* cleanly.
|
|
15
|
+
*
|
|
16
|
+
* The MCP SDK's `normalizeObjectSchema` accepts only ZodObject shapes for
|
|
17
|
+
* `outputSchema`; unions and discriminated unions are silently dropped.
|
|
18
|
+
* Therefore each schema below is a single `z.object()` describing the
|
|
19
|
+
* apply-path payload — sufficient for the AC ("LLM clients can validate
|
|
20
|
+
* tool output against the schema").
|
|
21
|
+
*/
|
|
22
|
+
/**
|
|
23
|
+
* Shape returned by `profile.basic.set()` on the apply path —
|
|
24
|
+
* mirrors `UpdateProfileResult` from `@ttctl/core`.
|
|
25
|
+
*/
|
|
26
|
+
export declare const profileBasicUpdateOutputSchema: z.ZodObject<{
|
|
27
|
+
profile: z.ZodObject<{
|
|
28
|
+
id: z.ZodString;
|
|
29
|
+
about: z.ZodNullable<z.ZodString>;
|
|
30
|
+
quote: z.ZodNullable<z.ZodString>;
|
|
31
|
+
}, z.core.$strip>;
|
|
32
|
+
notice: z.ZodNullable<z.ZodString>;
|
|
33
|
+
}, z.core.$strip>;
|
|
34
|
+
/**
|
|
35
|
+
* Shape returned by `profile.basic.photoUpload()` — mirrors `PhotoUrl`
|
|
36
|
+
* from `@ttctl/core`.
|
|
37
|
+
*/
|
|
38
|
+
export declare const profileBasicPhotoUploadOutputSchema: z.ZodObject<{
|
|
39
|
+
default: z.ZodNullable<z.ZodString>;
|
|
40
|
+
original: z.ZodNullable<z.ZodString>;
|
|
41
|
+
small: z.ZodNullable<z.ZodString>;
|
|
42
|
+
cropped: z.ZodNullable<z.ZodObject<{
|
|
43
|
+
x: z.ZodNumber;
|
|
44
|
+
y: z.ZodNumber;
|
|
45
|
+
width: z.ZodNumber;
|
|
46
|
+
height: z.ZodNumber;
|
|
47
|
+
}, z.core.$strip>>;
|
|
48
|
+
isResolutionSatisfied: z.ZodBoolean;
|
|
49
|
+
}, z.core.$strip>;
|
|
50
|
+
/**
|
|
51
|
+
* Shape returned by `profile.resume.upload()` — mirrors
|
|
52
|
+
* `UploadResumeResult` from `@ttctl/core`.
|
|
53
|
+
*/
|
|
54
|
+
export declare const profileResumeUploadOutputSchema: z.ZodObject<{
|
|
55
|
+
success: z.ZodBoolean;
|
|
56
|
+
}, z.core.$strip>;
|
|
57
|
+
/**
|
|
58
|
+
* Shape returned by `profile.education.add()` / `update()` — mirrors
|
|
59
|
+
* `Education` from `@ttctl/core`.
|
|
60
|
+
*/
|
|
61
|
+
export declare const profileEducationRowOutputSchema: z.ZodObject<{
|
|
62
|
+
id: z.ZodString;
|
|
63
|
+
institution: z.ZodString;
|
|
64
|
+
degree: z.ZodString;
|
|
65
|
+
fieldOfStudy: z.ZodNullable<z.ZodString>;
|
|
66
|
+
location: z.ZodNullable<z.ZodString>;
|
|
67
|
+
title: z.ZodNullable<z.ZodString>;
|
|
68
|
+
yearFrom: z.ZodNullable<z.ZodNumber>;
|
|
69
|
+
yearTo: z.ZodNullable<z.ZodNumber>;
|
|
70
|
+
highlight: z.ZodBoolean;
|
|
71
|
+
}, z.core.$strip>;
|
|
72
|
+
/**
|
|
73
|
+
* Shape returned by the `*_remove` tools' structured-content slot —
|
|
74
|
+
* `{ id, removed: true }`. The `text` content slot retains the
|
|
75
|
+
* human-readable confirmation; `structuredContent` exposes a typed
|
|
76
|
+
* acknowledgment.
|
|
77
|
+
*/
|
|
78
|
+
export declare const profileRowRemoveOutputSchema: z.ZodObject<{
|
|
79
|
+
id: z.ZodString;
|
|
80
|
+
removed: z.ZodLiteral<true>;
|
|
81
|
+
}, z.core.$strip>;
|
|
82
|
+
/**
|
|
83
|
+
* Shape returned by `profile.employment.add()` / `update()` — mirrors
|
|
84
|
+
* `Employment` from `@ttctl/core`. The last four fields were added in
|
|
85
|
+
* #344 to close the write/read asymmetry; they MUST stay in sync with
|
|
86
|
+
* the `Employment` interface or the `add`/`update` tools' declared
|
|
87
|
+
* output schema would under-report the rows they actually return.
|
|
88
|
+
*/
|
|
89
|
+
export declare const profileEmploymentRowOutputSchema: z.ZodObject<{
|
|
90
|
+
id: z.ZodString;
|
|
91
|
+
company: z.ZodString;
|
|
92
|
+
position: z.ZodString;
|
|
93
|
+
companyWebsite: z.ZodNullable<z.ZodString>;
|
|
94
|
+
noWebsite: z.ZodBoolean;
|
|
95
|
+
startDate: z.ZodNullable<z.ZodNumber>;
|
|
96
|
+
endDate: z.ZodNullable<z.ZodNumber>;
|
|
97
|
+
experienceItems: z.ZodNullable<z.ZodArray<z.ZodString>>;
|
|
98
|
+
highlight: z.ZodBoolean;
|
|
99
|
+
showViaToptal: z.ZodBoolean;
|
|
100
|
+
toptalRelated: z.ZodBoolean;
|
|
101
|
+
publicationPermit: z.ZodNullable<z.ZodBoolean>;
|
|
102
|
+
reportingTo: z.ZodNullable<z.ZodString>;
|
|
103
|
+
industries: z.ZodArray<z.ZodObject<{
|
|
104
|
+
id: z.ZodString;
|
|
105
|
+
name: z.ZodString;
|
|
106
|
+
}, z.core.$strip>>;
|
|
107
|
+
primaryGeography: z.ZodNullable<z.ZodObject<{
|
|
108
|
+
id: z.ZodString;
|
|
109
|
+
code: z.ZodNullable<z.ZodString>;
|
|
110
|
+
name: z.ZodNullable<z.ZodString>;
|
|
111
|
+
}, z.core.$strip>>;
|
|
112
|
+
}, z.core.$strip>;
|
|
113
|
+
/**
|
|
114
|
+
* Shape returned by `profile.industries.update()` / `show()` — mirrors
|
|
115
|
+
* `IndustryProfile` from `@ttctl/core`.
|
|
116
|
+
*/
|
|
117
|
+
export declare const profileIndustriesRowOutputSchema: z.ZodObject<{
|
|
118
|
+
id: z.ZodString;
|
|
119
|
+
title: z.ZodString;
|
|
120
|
+
about: z.ZodNullable<z.ZodString>;
|
|
121
|
+
domainArea: z.ZodNullable<z.ZodString>;
|
|
122
|
+
}, z.core.$strip>;
|
|
123
|
+
/**
|
|
124
|
+
* Tool names (frozen) that the test suite asserts must carry a populated
|
|
125
|
+
* `outputSchema`. Adding a new write-capable tool: append its name here
|
|
126
|
+
* and define the schema above.
|
|
127
|
+
*/
|
|
128
|
+
export declare const TOOLS_WITH_OUTPUT_SCHEMA: readonly ["ttctl_profile_basic_update", "ttctl_profile_basic_photo_upload", "ttctl_profile_resume_upload", "ttctl_profile_education_add", "ttctl_profile_education_update", "ttctl_profile_education_remove", "ttctl_profile_employment_add", "ttctl_profile_employment_update", "ttctl_profile_employment_remove", "ttctl_profile_industries_update", "ttctl_profile_industries_show"];
|
|
129
|
+
//# sourceMappingURL=output-schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-schemas.d.ts","sourceRoot":"","sources":["../../src/tools/output-schemas.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;GAGG;AACH,eAAO,MAAM,8BAA8B;;;;;;;iBAOzC,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,mCAAmC;;;;;;;;;;;iBAa9C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,+BAA+B;;iBAE1C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,+BAA+B;;;;;;;;;;iBAU1C,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B;;;iBAGvC,CAAC;AAEH;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;iBAgB3C,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,gCAAgC;;;;;iBAK3C,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,yXAY3B,CAAC"}
|