@uptomic/career-mentor-cli 0.1.0
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/LICENSE +201 -0
- package/README.md +319 -0
- package/dist/auth.d.ts +86 -0
- package/dist/career-mentor.js +13 -0
- package/dist/cli.d.ts +38 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1945 -0
- package/package.json +70 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
ADDED
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# `@uptomic/career-mentor-cli`
|
|
2
|
+
|
|
3
|
+
Official JSON-first command-line client for the hosted Career Mentor Capability API. It is designed
|
|
4
|
+
for people, scripts, coding agents, and MCP-adjacent automation that should not need the web UI.
|
|
5
|
+
|
|
6
|
+
The CLI uses the generated `@uptomic/career-mentor` transport and bundles that runtime into the published
|
|
7
|
+
artifact. It never imports the Career Mentor backend, opens a database connection, or implements a
|
|
8
|
+
second capability path.
|
|
9
|
+
|
|
10
|
+
## Install and run
|
|
11
|
+
|
|
12
|
+
```sh
|
|
13
|
+
npm install --global @uptomic/career-mentor-cli
|
|
14
|
+
cm help
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`career-mentor` is the long alias for `cm`. The package runs on Node.js 20+ and Bun 1.2+.
|
|
18
|
+
Using Bun is also supported: `bun add --global @uptomic/career-mentor-cli`.
|
|
19
|
+
|
|
20
|
+
Without a global install:
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
bunx @uptomic/career-mentor-cli help
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Authentication
|
|
27
|
+
|
|
28
|
+
Authorize the CLI with your Career Mentor account:
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
cm auth login
|
|
32
|
+
cm auth status
|
|
33
|
+
cm doctor
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`auth login` starts a loopback listener on `127.0.0.1`, opens the Career Mentor authorization page,
|
|
37
|
+
and uses PKCE to exchange a one-time authorization code for a scoped capability token. The raw token
|
|
38
|
+
is never placed in a URL, browser history, referrer, stdout, or stderr. Only the authorization code and
|
|
39
|
+
state return through the loopback redirect. The CLI then writes the token atomically to
|
|
40
|
+
`~/.career-mentor/capability-token` with `0600` permissions.
|
|
41
|
+
|
|
42
|
+
Browser authorization is the only CLI workflow that opens the web app. After login, capability
|
|
43
|
+
discovery, invocation, run inspection, and event streaming work without the UI. In a headless
|
|
44
|
+
environment where the browser can reach the same loopback listener, print the authorization URL as a
|
|
45
|
+
structured stderr diagnostic instead of opening a browser:
|
|
46
|
+
|
|
47
|
+
```sh
|
|
48
|
+
cm auth login --no-open
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
For an SSH host, select a fixed `--port` and configure loopback port forwarding before opening the URL;
|
|
52
|
+
the redirect deliberately cannot target a non-loopback host.
|
|
53
|
+
|
|
54
|
+
Request an explicit scope set or expiry when needed; omitting scopes lets Career Mentor apply the
|
|
55
|
+
account-safe defaults. Those defaults deliberately omit `account:write` and `actions:confirm`, so
|
|
56
|
+
request either one explicitly, alongside the exact domain scopes needed, only for access-key
|
|
57
|
+
management or reviewed commit approval:
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
cm auth login --scopes 'profile:read,jobs:read' --expires-in-days 7
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`cm auth status` reports only whether a credential exists and which source won. It never prints the
|
|
64
|
+
token or a token prefix. Credential precedence is `--token`, then
|
|
65
|
+
`CAREER_MENTOR_CAPABILITY_TOKEN`, then the managed file. Override the managed file location with
|
|
66
|
+
`--credential-file` or `CAREER_MENTOR_CAPABILITY_TOKEN_FILE`.
|
|
67
|
+
|
|
68
|
+
`--token` remains available for ephemeral execution, but command arguments can be stored in shell
|
|
69
|
+
history and process listings. To remove the local managed credential without touching neighboring
|
|
70
|
+
files:
|
|
71
|
+
|
|
72
|
+
```sh
|
|
73
|
+
cm auth logout
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Logout is deliberately local-only. Revoke an active token from the Career Mentor agent-access page
|
|
77
|
+
or entirely through the CLI when server-side invalidation is required. Revocation requires a token
|
|
78
|
+
authorized with `account:write`:
|
|
79
|
+
|
|
80
|
+
```sh
|
|
81
|
+
cm invoke list_capability_tokens --input '{}'
|
|
82
|
+
cm invoke revoke_capability_token --input '{"tokenId":"<token-id>"}'
|
|
83
|
+
cm auth logout
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The same privileged CLI session can mint a least-privilege child token. The new secret is returned
|
|
87
|
+
exactly once:
|
|
88
|
+
|
|
89
|
+
```sh
|
|
90
|
+
cm invoke create_capability_token \
|
|
91
|
+
--input '{"name":"job-search-agent","scopes":["capabilities:read","jobs:read"],"expiresInDays":30}'
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The production API origin defaults to `https://app.uptomic.com`. Override it for another environment:
|
|
95
|
+
|
|
96
|
+
```sh
|
|
97
|
+
export CAREER_MENTOR_API_URL='https://staging.uptomic.com'
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The value is an origin or deployment base URL. The SDK appends the canonical `/api/v1` capability
|
|
101
|
+
paths.
|
|
102
|
+
|
|
103
|
+
## Discover capabilities
|
|
104
|
+
|
|
105
|
+
```sh
|
|
106
|
+
cm capabilities list
|
|
107
|
+
cm capabilities describe search_jobs
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
`describe` returns the published manifest, including the exact input and output JSON schemas, scopes,
|
|
111
|
+
risk, explicit destructive behavior, side effects, confirmation policy, idempotency behavior, and
|
|
112
|
+
bounded-sync or durable-run execution contract.
|
|
113
|
+
|
|
114
|
+
## Invoke a capability
|
|
115
|
+
|
|
116
|
+
Inline JSON:
|
|
117
|
+
|
|
118
|
+
```sh
|
|
119
|
+
cm invoke search_jobs \
|
|
120
|
+
--input '{"query":"staff engineer","limit":10}' \
|
|
121
|
+
--request-id 'agent-run-42-search' \
|
|
122
|
+
--agent-session-id 'agent-run-42' \
|
|
123
|
+
--idempotency-key 'agent-run-42-search-attempt-1'
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
An idempotency key names one caller operation. The same key and validated input replay safely; changed
|
|
127
|
+
input under that key exits with the API's conflict result. Do not configure one global key for
|
|
128
|
+
unrelated invocations. Chat and skill-interview commands execute every keyless call as a distinct turn,
|
|
129
|
+
so pass a key only when retrying the same turn. When a manifest sets
|
|
130
|
+
`executionContract.requiresIdempotencyKey` to true, the key is mandatory for non-dry-run execution and
|
|
131
|
+
reconnects request retries to one persisted operation.
|
|
132
|
+
|
|
133
|
+
Read a JSON object from a file or stdin:
|
|
134
|
+
|
|
135
|
+
```sh
|
|
136
|
+
cm invoke save_job --input-file ./save-job.json
|
|
137
|
+
printf '%s' '{"jobId":"job-id","careerPathId":"path-id"}' \
|
|
138
|
+
| cm invoke save_job --input-file -
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
The CLI returns HTTP `202` capability envelopes immediately. It never polls a long-running workflow.
|
|
142
|
+
Use the returned run/event references with the documented event surface.
|
|
143
|
+
|
|
144
|
+
## Upload Career Vault files
|
|
145
|
+
|
|
146
|
+
Upload and register a local file without opening the web UI:
|
|
147
|
+
|
|
148
|
+
```sh
|
|
149
|
+
cm artifacts upload ./resume.pdf
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
The command accepts PDF, DOC, DOCX, JPEG, PNG, WebP, Markdown, and plain-text files up to 10 MiB. It
|
|
153
|
+
uses the published `initiate_artifact_upload` and `register_artifact_upload` capabilities around one
|
|
154
|
+
size- and content-type-bound PUT with a three-minute authorization. `--idempotency-key` identifies the
|
|
155
|
+
authorization attempt; registration and optional artifact creation keep their payload-bound
|
|
156
|
+
identities. Rerunning after the authorization expires therefore obtains a fresh URL and storage key
|
|
157
|
+
without reusing that key against changed registration input. The PUT carries no capability token, and
|
|
158
|
+
stdout never includes the
|
|
159
|
+
temporary upload URL or storage key.
|
|
160
|
+
|
|
161
|
+
File registration does not create a Career Vault artifact implicitly. Request creation and canonical
|
|
162
|
+
Mastra analysis explicitly:
|
|
163
|
+
|
|
164
|
+
```sh
|
|
165
|
+
cm artifacts upload ./resume.pdf --create --type resume --name 'Primary resume'
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Supported artifact types are `resume`, `certificate`, `portfolio`, `recommendation`,
|
|
169
|
+
`performance_review`, `award`, `course_completion`, `project`, `publication`, and `other`. `--name`
|
|
170
|
+
defaults to the filename without its extension. Successful output is one JSON object containing the
|
|
171
|
+
safe registered `file` projection and, only with `--create`, the new `artifact` and queue state.
|
|
172
|
+
|
|
173
|
+
## Manage profile photos and registered files
|
|
174
|
+
|
|
175
|
+
Profile photos attach only from a registered current-user image file. The upload response above
|
|
176
|
+
contains the required `fileId`; no photo command accepts a storage URL or object key.
|
|
177
|
+
|
|
178
|
+
```sh
|
|
179
|
+
cm artifacts upload ./portrait.jpg
|
|
180
|
+
cm photos add <registered-file-id>
|
|
181
|
+
cm photos list
|
|
182
|
+
cm photos default <photo-id>
|
|
183
|
+
cm photos reorder <photo-id-2> <photo-id-1>
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
`photos reorder` replaces the complete order and therefore requires every current photo ID exactly
|
|
187
|
+
once. Repeating `photos add` with the same registered file is idempotent.
|
|
188
|
+
|
|
189
|
+
Photo and standalone registered-file deletion always start with a reviewed proposal:
|
|
190
|
+
|
|
191
|
+
```sh
|
|
192
|
+
cm photos delete <photo-id>
|
|
193
|
+
cm files delete <registered-file-id>
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
These commands do not auto-confirm. Inspect the returned preview, then invoke its named commit
|
|
197
|
+
capability with the exact pending action ID and payload hash. Standalone file deletion is refused
|
|
198
|
+
while a Career Vault artifact, resume parse, onboarding resume run, or profile photo references the
|
|
199
|
+
file. Photo deletion removes the registered object only when no other authoritative reference
|
|
200
|
+
remains.
|
|
201
|
+
|
|
202
|
+
## Observe asynchronous runs
|
|
203
|
+
|
|
204
|
+
Get current status or replay a bounded page of events:
|
|
205
|
+
|
|
206
|
+
```sh
|
|
207
|
+
cm runs get 019f5074-5680-7000-8000-000000000001
|
|
208
|
+
cm runs events 019f5074-5680-7000-8000-000000000001 --after 0-0 --limit 100
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Wait for exactly one terminal event:
|
|
212
|
+
|
|
213
|
+
```sh
|
|
214
|
+
cm runs wait 019f5074-5680-7000-8000-000000000001 \
|
|
215
|
+
--last-event-id 17-0 \
|
|
216
|
+
--timeout-ms 600000
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
`runs wait` prints exactly one terminal JSON document. It never polls. When the server normally closes
|
|
220
|
+
a bounded SSE session before terminal state, it applies bounded backoff and reconnects from the last
|
|
221
|
+
validated event ID. `--timeout-ms` is one overall budget across every stream and reconnect delay;
|
|
222
|
+
Ctrl-C aborts the entire wait. A succeeded terminal event exits `0`, failed exits `8`, and cancelled
|
|
223
|
+
exits `9`. All three terminal envelopes stay on stdout and stderr remains empty.
|
|
224
|
+
|
|
225
|
+
Subscribe without polling:
|
|
226
|
+
|
|
227
|
+
```sh
|
|
228
|
+
cm runs watch 019f5074-5680-7000-8000-000000000001 \
|
|
229
|
+
--last-event-id 17-0 \
|
|
230
|
+
--timeout-ms 30000
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
`runs watch` is the one streaming output exception: it writes one validated event JSON object per
|
|
234
|
+
line (JSON Lines) as SSE frames arrive. It ignores heartbeat comments and stops when the server emits
|
|
235
|
+
a terminal event, the bounded SSE session closes, the timeout expires, or the caller interrupts it.
|
|
236
|
+
Timeout/network failures use exit `6`; Ctrl-C/caller abort uses exit `130` and writes the normal
|
|
237
|
+
sanitized error JSON to stderr.
|
|
238
|
+
|
|
239
|
+
`runs watch` does not reconnect invisibly. Record the last printed `id` and pass it through
|
|
240
|
+
`--last-event-id` to resume; this becomes the HTTP `Last-Event-ID` header. `--after` is the replay
|
|
241
|
+
query cursor and may also seed a watch, while `--last-event-id` takes precedence when both are set.
|
|
242
|
+
A nonterminal bounded-session close exits successfully, so the caller decides if and when to reconnect.
|
|
243
|
+
|
|
244
|
+
## Agent transport controls
|
|
245
|
+
|
|
246
|
+
Every API command supports these flags and environment defaults:
|
|
247
|
+
|
|
248
|
+
| Flag | Environment variable | Purpose |
|
|
249
|
+
|---|---|---|
|
|
250
|
+
| `--endpoint` | `CAREER_MENTOR_API_URL` | Hosted API origin/base URL |
|
|
251
|
+
| `--token` | `CAREER_MENTOR_CAPABILITY_TOKEN` | Scoped user capability token |
|
|
252
|
+
| `--credential-file` | `CAREER_MENTOR_CAPABILITY_TOKEN_FILE` | Managed token file used after flag/environment lookup |
|
|
253
|
+
| `--timeout-ms` | `CAREER_MENTOR_TIMEOUT_MS` | Positive request timeout in milliseconds |
|
|
254
|
+
| `--request-id` | `CAREER_MENTOR_REQUEST_ID` | Per-request correlation ID |
|
|
255
|
+
| `--agent-session-id` | `CAREER_MENTOR_AGENT_SESSION_ID` | Agent-session correlation ID |
|
|
256
|
+
| `--idempotency-key` | `CAREER_MENTOR_IDEMPOTENCY_KEY` | Invocation idempotency key |
|
|
257
|
+
|
|
258
|
+
Flags take precedence over their environment defaults. `--idempotency-key` is accepted by `invoke`,
|
|
259
|
+
`artifacts upload`, `photos`, and `files`. Run event commands additionally accept `--after` and
|
|
260
|
+
`--limit`; `runs wait` and `runs watch` also accept `--last-event-id`.
|
|
261
|
+
|
|
262
|
+
## Output and exit contract
|
|
263
|
+
|
|
264
|
+
Non-streaming command results are one JSON document on stdout. `runs wait` keeps its terminal envelope
|
|
265
|
+
on stdout even when failed or cancelled returns a nonzero outcome code. `runs watch` emits JSON Lines,
|
|
266
|
+
one event per line. Transport, API, configuration, and input errors are one sanitized JSON document on
|
|
267
|
+
stderr. `auth login` additionally emits a structured browser-handoff diagnostic on stderr, and
|
|
268
|
+
`doctor` always emits its complete report on stdout even when a check fails. The CLI emits no
|
|
269
|
+
unstructured banners, progress indicators, or log noise, so agents can parse the declared stream
|
|
270
|
+
directly.
|
|
271
|
+
|
|
272
|
+
```json
|
|
273
|
+
{"ok":false,"error":{"code":"UNAUTHORIZED","message":"Capability token is invalid.","exitCode":3,"status":401,"requestId":"request-id"}}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Exit codes are stable public behavior:
|
|
277
|
+
|
|
278
|
+
| Code | Meaning |
|
|
279
|
+
|---:|---|
|
|
280
|
+
| `0` | Success |
|
|
281
|
+
| `1` | Unexpected internal CLI error |
|
|
282
|
+
| `2` | Invalid command, configuration, or capability input |
|
|
283
|
+
| `3` | Authentication or authorization failure |
|
|
284
|
+
| `4` | Capability/resource not found |
|
|
285
|
+
| `5` | Conflict, in-progress idempotent request, or rate limit |
|
|
286
|
+
| `6` | Network error, timeout, or unavailable service |
|
|
287
|
+
| `7` | Other API error |
|
|
288
|
+
| `8` | Capability run reached terminal `failed` state |
|
|
289
|
+
| `9` | Capability run reached terminal `cancelled` state |
|
|
290
|
+
| `130` | Caller interruption/abort |
|
|
291
|
+
|
|
292
|
+
The token is redacted if any upstream error echoes it. Server payloads, stack traces, and transport
|
|
293
|
+
causes are never printed.
|
|
294
|
+
|
|
295
|
+
## Package development and release
|
|
296
|
+
|
|
297
|
+
From this package directory:
|
|
298
|
+
|
|
299
|
+
```sh
|
|
300
|
+
bun run test
|
|
301
|
+
bun run typecheck
|
|
302
|
+
bun run build
|
|
303
|
+
bun run test:package # pack, install in isolation, run both installed binaries
|
|
304
|
+
bun run release:dry-run
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Publication has one trigger: run `.github/workflows/publish-agentic-packages.yml` from the exact
|
|
308
|
+
`agentic-vX.Y.Z` tag. Its tag-restricted `npm-production` environment gates the publish job, which loads
|
|
309
|
+
the npm credential from Infisical at runtime. The workflow runs the full release gate, publishes the
|
|
310
|
+
already-verified SDK and CLI tarballs in order, and installs the registry artifacts under Node.js 20.
|
|
311
|
+
|
|
312
|
+
The Bun token-publish workflow does not generate npm provenance. Accepting that release explicitly or
|
|
313
|
+
moving to a public-repository npm trusted-publisher workflow is a product-owner decision; neither path
|
|
314
|
+
is inferred by the package build.
|
|
315
|
+
|
|
316
|
+
## License
|
|
317
|
+
|
|
318
|
+
Apache-2.0. Copyright 2026 Uptomic. This grant applies to the published Career Mentor CLI package,
|
|
319
|
+
not to the private Career Mentor backend or the rest of its monorepo.
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export declare const CAPABILITY_TOKEN_ENV = "CAREER_MENTOR_CAPABILITY_TOKEN";
|
|
2
|
+
export declare const CAPABILITY_TOKEN_FILE_ENV = "CAREER_MENTOR_CAPABILITY_TOKEN_FILE";
|
|
3
|
+
export declare const AUTH_APP_URL_ENV = "CAREER_MENTOR_AUTH_APP_URL";
|
|
4
|
+
export declare const DEFAULT_AUTH_APP_URL = "https://app.uptomic.com";
|
|
5
|
+
export declare const DEFAULT_AUTH_EXPIRES_IN_DAYS = 7;
|
|
6
|
+
export declare const DEFAULT_AUTH_TIMEOUT_MS: number;
|
|
7
|
+
export type BrowserAuthErrorCode = 'AUTH_ABORTED' | 'AUTH_BROWSER_OPEN_FAILED' | 'AUTH_CALLBACK_FAILED' | 'AUTH_CREDENTIAL_INVALID' | 'AUTH_FILE_INVALID' | 'AUTH_FILE_PERMISSIONS' | 'AUTH_INPUT_INVALID' | 'AUTH_SERVER_FAILED' | 'AUTH_STATE_MISMATCH' | 'AUTH_TIMEOUT';
|
|
8
|
+
export declare class BrowserAuthError extends Error {
|
|
9
|
+
readonly code: BrowserAuthErrorCode;
|
|
10
|
+
constructor(code: BrowserAuthErrorCode, message: string);
|
|
11
|
+
}
|
|
12
|
+
export type ResolvedCredential = {
|
|
13
|
+
source: '--token' | 'CAREER_MENTOR_CAPABILITY_TOKEN' | 'managed_file';
|
|
14
|
+
token: string;
|
|
15
|
+
};
|
|
16
|
+
type CapturedAuthToken = {
|
|
17
|
+
code: string;
|
|
18
|
+
};
|
|
19
|
+
export type LoopbackCallbackServer = {
|
|
20
|
+
close: () => Promise<void>;
|
|
21
|
+
port: number;
|
|
22
|
+
redirectUri: string;
|
|
23
|
+
waitForCallback: Promise<CapturedAuthToken>;
|
|
24
|
+
};
|
|
25
|
+
export type BrowserAuthLaunch = {
|
|
26
|
+
authorizationUrl: string;
|
|
27
|
+
openBrowser: boolean;
|
|
28
|
+
redirectUri: string;
|
|
29
|
+
};
|
|
30
|
+
export type BrowserAuthLoginOptions = {
|
|
31
|
+
appUrl: string;
|
|
32
|
+
clientName: string;
|
|
33
|
+
credentialFile: string;
|
|
34
|
+
expiresInDays: number;
|
|
35
|
+
onLaunch: (launch: BrowserAuthLaunch) => Promise<void>;
|
|
36
|
+
openBrowser: boolean;
|
|
37
|
+
port?: number;
|
|
38
|
+
scopes: string[];
|
|
39
|
+
signal?: AbortSignal;
|
|
40
|
+
timeoutMs: number;
|
|
41
|
+
};
|
|
42
|
+
export type BrowserAuthLoginResult = {
|
|
43
|
+
credentialFile: string;
|
|
44
|
+
expiresAt: string;
|
|
45
|
+
scopes: string[];
|
|
46
|
+
};
|
|
47
|
+
export type BrowserAuthOverrides = {
|
|
48
|
+
fetch?: typeof globalThis.fetch;
|
|
49
|
+
generateCodeVerifier?: () => string;
|
|
50
|
+
generateState?: () => string;
|
|
51
|
+
openUrl?: (url: string) => Promise<void>;
|
|
52
|
+
};
|
|
53
|
+
export declare function defaultCredentialFile(): string;
|
|
54
|
+
export declare function resolveCredentialFile(explicitPath: string | undefined, environmentPath: string | undefined): string;
|
|
55
|
+
export declare function parseRequestedScopes(value: string | undefined): string[];
|
|
56
|
+
export declare function buildAgentAuthUrl(params: {
|
|
57
|
+
appUrl: string;
|
|
58
|
+
clientName: string;
|
|
59
|
+
codeChallenge: string;
|
|
60
|
+
expiresInDays: number;
|
|
61
|
+
redirectUri: string;
|
|
62
|
+
scopes: readonly string[];
|
|
63
|
+
state: string;
|
|
64
|
+
}): string;
|
|
65
|
+
export declare function resolveCredential(params: {
|
|
66
|
+
credentialFile: string;
|
|
67
|
+
envToken?: string;
|
|
68
|
+
flagToken?: string;
|
|
69
|
+
}): Promise<ResolvedCredential | undefined>;
|
|
70
|
+
export declare function writeCredentialFile(filePath: string, token: string): Promise<void>;
|
|
71
|
+
export declare function logoutCredential(filePath: string): Promise<{
|
|
72
|
+
removed: boolean;
|
|
73
|
+
}>;
|
|
74
|
+
export declare function startLoopbackCallbackServer(params: {
|
|
75
|
+
port?: number;
|
|
76
|
+
signal?: AbortSignal;
|
|
77
|
+
state: string;
|
|
78
|
+
timeoutMs: number;
|
|
79
|
+
}): Promise<LoopbackCallbackServer>;
|
|
80
|
+
export declare function browserLaunchCommand(url: string, platform?: NodeJS.Platform): {
|
|
81
|
+
args: string[];
|
|
82
|
+
command: string;
|
|
83
|
+
};
|
|
84
|
+
export declare function openUrlInBrowser(url: string): Promise<void>;
|
|
85
|
+
export declare function runBrowserAuthLogin(options: BrowserAuthLoginOptions, overrides?: BrowserAuthOverrides): Promise<BrowserAuthLoginResult>;
|
|
86
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { runCli } from './index.js';
|
|
3
|
+
|
|
4
|
+
const controller = new AbortController();
|
|
5
|
+
const abort = () => controller.abort();
|
|
6
|
+
process.once('SIGINT', abort);
|
|
7
|
+
process.once('SIGTERM', abort);
|
|
8
|
+
try {
|
|
9
|
+
process.exitCode = await runCli(process.argv.slice(2), { signal: controller.signal });
|
|
10
|
+
} finally {
|
|
11
|
+
process.removeListener('SIGINT', abort);
|
|
12
|
+
process.removeListener('SIGTERM', abort);
|
|
13
|
+
}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type BrowserAuthOverrides } from './auth.ts';
|
|
2
|
+
export declare const CLI_VERSION = "0.1.0";
|
|
3
|
+
export declare const DEFAULT_API_URL = "https://app.uptomic.com";
|
|
4
|
+
export declare const CLI_EXIT_CODE: Readonly<{
|
|
5
|
+
readonly SUCCESS: 0;
|
|
6
|
+
readonly INTERNAL: 1;
|
|
7
|
+
readonly USAGE: 2;
|
|
8
|
+
readonly AUTH: 3;
|
|
9
|
+
readonly NOT_FOUND: 4;
|
|
10
|
+
readonly CONFLICT_OR_LIMIT: 5;
|
|
11
|
+
readonly UNAVAILABLE: 6;
|
|
12
|
+
readonly API_ERROR: 7;
|
|
13
|
+
readonly RUN_FAILED: 8;
|
|
14
|
+
readonly RUN_CANCELLED: 9;
|
|
15
|
+
readonly INTERRUPTED: 130;
|
|
16
|
+
}>;
|
|
17
|
+
type Env = Record<string, string | undefined>;
|
|
18
|
+
type Write = (text: string) => void;
|
|
19
|
+
type FlagValue = boolean | string;
|
|
20
|
+
type Flags = Record<string, FlagValue>;
|
|
21
|
+
export interface CliOptions {
|
|
22
|
+
browserAuth?: BrowserAuthOverrides;
|
|
23
|
+
env?: Env;
|
|
24
|
+
fetch?: typeof globalThis.fetch;
|
|
25
|
+
readBinaryFile?: (path: string) => Promise<Uint8Array>;
|
|
26
|
+
readFile?: (path: string) => Promise<string>;
|
|
27
|
+
readStdin?: () => Promise<string>;
|
|
28
|
+
signal?: AbortSignal;
|
|
29
|
+
stderr?: Write;
|
|
30
|
+
stdout?: Write;
|
|
31
|
+
}
|
|
32
|
+
export interface ParsedArgs {
|
|
33
|
+
flags: Flags;
|
|
34
|
+
positionals: string[];
|
|
35
|
+
}
|
|
36
|
+
export declare function parseArgs(argv: readonly string[]): ParsedArgs;
|
|
37
|
+
export declare function runCli(argv: readonly string[], options?: CliOptions): Promise<number>;
|
|
38
|
+
export {};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { CLI_EXIT_CODE, CLI_VERSION, DEFAULT_API_URL, parseArgs, runCli, type CliOptions, type ParsedArgs, } from './cli.ts';
|