intentdocs 0.8.0 → 0.10.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/README.md +2 -1
- package/bin/intentdocs.js +2 -0
- package/dist/{chunk-4OWPN2RE.js → chunk-5USVG4DW.js} +24 -43
- package/dist/{chunk-IKF3ZLHK.js → chunk-EEKEF2FD.js} +65 -101
- package/dist/chunk-HEHHSSUM.js +43 -0
- package/dist/chunk-IDNUBI2P.js +317 -0
- package/dist/chunk-LQTPZL2Y.js +15 -0
- package/dist/chunk-LXQXJULN.js +105 -0
- package/dist/{chunk-6FGYJ3W2.js → chunk-NFIXRIHM.js} +43 -4
- package/dist/{chunk-ICOMMHKG.js → chunk-UF535HZL.js} +12 -1
- package/dist/{chunk-ITQUQYWB.js → chunk-UR73WX5I.js} +1 -1
- package/dist/chunk-UYTVTYNB.js +11 -0
- package/dist/{chunk-WPVDURTJ.js → chunk-WRRUCCVZ.js} +27 -3
- package/dist/chunk-YUW3W43S.js +170 -0
- package/dist/ci-LBOCMRKZ.js +11 -0
- package/dist/{complexity-NSSYVT54.js → complexity-ZOB3BPVD.js} +12 -7
- package/dist/{import-prd-CKV3R67G.js → import-prd-MJUCIMHX.js} +13 -11
- package/dist/index.js +420 -179
- package/dist/{keys-EDWET3WG.js → keys-5PA3D6CX.js} +8 -7
- package/dist/log-EVLWM64C.js +206 -0
- package/dist/{map-extract-I3AACTGL.js → map-extract-W6WJLVOF.js} +2 -1
- package/dist/{map-import-IYUMRASO.js → map-import-LL4AIAQE.js} +12 -10
- package/dist/{map-schema-JVL3O2TJ.js → map-schema-6GL2UKZQ.js} +1 -1
- package/dist/projects-F7GMH66U.js +37 -0
- package/dist/{prompt-WAWCRGHN.js → prompt-GOAFIKBZ.js} +3 -1
- package/dist/{research-6SXJ37TI.js → research-4ASCZSZN.js} +12 -10
- package/dist/scope-S3LZZ3KB.js +11 -0
- package/dist/setup-YLUPBLK6.js +14 -0
- package/package.json +4 -2
- package/dist/chunk-6XKB6RTU.js +0 -123
- package/dist/chunk-PCNDP5SX.js +0 -34
- package/dist/log-TT2UCJP7.js +0 -94
- package/dist/scope-OGKQ472D.js +0 -10
- package/dist/setup-SOI2HQAL.js +0 -11
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ask,
|
|
3
3
|
closePrompt
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WRRUCCVZ.js";
|
|
5
5
|
import {
|
|
6
|
-
|
|
7
|
-
} from "./chunk-
|
|
6
|
+
requireValidAuth
|
|
7
|
+
} from "./chunk-LXQXJULN.js";
|
|
8
|
+
import "./chunk-UYTVTYNB.js";
|
|
8
9
|
|
|
9
10
|
// src/commands/keys.ts
|
|
10
11
|
var KEYS_DOC_URL = "https://console.anthropic.com/settings/keys";
|
|
11
12
|
async function byokRequest(method, body) {
|
|
12
|
-
const auth =
|
|
13
|
+
const auth = await requireValidAuth();
|
|
13
14
|
const res = await fetch(`${auth.apiBase}/api/settings/byok`, {
|
|
14
15
|
method,
|
|
15
16
|
headers: {
|
|
@@ -32,7 +33,7 @@ async function keysSet(key) {
|
|
|
32
33
|
closePrompt();
|
|
33
34
|
}
|
|
34
35
|
if (!value) {
|
|
35
|
-
console.error(" No key provided. Run `
|
|
36
|
+
console.error(" No key provided. Run `intentdocs keys set` to try again.");
|
|
36
37
|
process.exit(1);
|
|
37
38
|
}
|
|
38
39
|
try {
|
|
@@ -59,11 +60,11 @@ async function keysStatus() {
|
|
|
59
60
|
}
|
|
60
61
|
if (data?.enabled) {
|
|
61
62
|
console.log(`
|
|
62
|
-
Anthropic API key: ${data.maskedKey ?? "(stored but unreadable \u2014 re-run `
|
|
63
|
+
Anthropic API key: ${data.maskedKey ?? "(stored but unreadable \u2014 re-run `intentdocs keys set`)"}`);
|
|
63
64
|
console.log(" AI features run on your key.\n");
|
|
64
65
|
} else {
|
|
65
66
|
console.log("\n No Anthropic API key set.");
|
|
66
|
-
console.log(" Add one with `
|
|
67
|
+
console.log(" Add one with `intentdocs keys set` to unlock AI features on any plan.\n");
|
|
67
68
|
}
|
|
68
69
|
} catch {
|
|
69
70
|
console.error(" \u2717 Could not reach intentdocs. Check your connection and try again.");
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appendNoteToContext,
|
|
3
|
+
storyContextPath
|
|
4
|
+
} from "./chunk-NFIXRIHM.js";
|
|
5
|
+
import {
|
|
6
|
+
matchesStoryRef
|
|
7
|
+
} from "./chunk-LQTPZL2Y.js";
|
|
8
|
+
import {
|
|
9
|
+
amendDecision,
|
|
10
|
+
apiFetch,
|
|
11
|
+
listDecisions,
|
|
12
|
+
retractDecision
|
|
13
|
+
} from "./chunk-YUW3W43S.js";
|
|
14
|
+
import {
|
|
15
|
+
requireConfig
|
|
16
|
+
} from "./chunk-UF535HZL.js";
|
|
17
|
+
import {
|
|
18
|
+
ask,
|
|
19
|
+
closePrompt,
|
|
20
|
+
confirm,
|
|
21
|
+
isInteractive
|
|
22
|
+
} from "./chunk-WRRUCCVZ.js";
|
|
23
|
+
import "./chunk-LXQXJULN.js";
|
|
24
|
+
import "./chunk-UYTVTYNB.js";
|
|
25
|
+
|
|
26
|
+
// src/commands/log.ts
|
|
27
|
+
async function logDecision(title, opts) {
|
|
28
|
+
const config = requireConfig();
|
|
29
|
+
if (!title) {
|
|
30
|
+
title = await ask(" Decision title: ");
|
|
31
|
+
}
|
|
32
|
+
let description = opts?.description;
|
|
33
|
+
if (!description) {
|
|
34
|
+
description = await ask(" Description (what was decided and why): ");
|
|
35
|
+
}
|
|
36
|
+
if (!title?.trim() || !description?.trim()) {
|
|
37
|
+
console.log(" Title and description required.");
|
|
38
|
+
closePrompt();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const res = await apiFetch(config, "/decisions", {
|
|
42
|
+
method: "POST",
|
|
43
|
+
headers: { "Content-Type": "application/json" },
|
|
44
|
+
body: JSON.stringify({
|
|
45
|
+
title: title.trim(),
|
|
46
|
+
description: description.trim(),
|
|
47
|
+
category: opts?.category ?? "technical",
|
|
48
|
+
story_id: opts?.story ?? void 0
|
|
49
|
+
})
|
|
50
|
+
});
|
|
51
|
+
if (res.ok) {
|
|
52
|
+
console.log(` \u2713 Decision logged: ${title}`);
|
|
53
|
+
} else {
|
|
54
|
+
console.error(" Failed to log decision.");
|
|
55
|
+
}
|
|
56
|
+
closePrompt();
|
|
57
|
+
}
|
|
58
|
+
async function findDecision(idPrefix) {
|
|
59
|
+
const config = requireConfig();
|
|
60
|
+
const { decisions } = await listDecisions(config);
|
|
61
|
+
const match = decisions.find((d) => d.id.startsWith(idPrefix));
|
|
62
|
+
if (!match) {
|
|
63
|
+
console.error(` No decision found matching "${idPrefix}"`);
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
return { config, match };
|
|
67
|
+
}
|
|
68
|
+
async function listLoggedDecisions() {
|
|
69
|
+
const config = requireConfig();
|
|
70
|
+
const { decisions } = await listDecisions(config);
|
|
71
|
+
if (decisions.length === 0) {
|
|
72
|
+
console.log(" No decisions logged yet. Run `intent decide` to log one.");
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
console.log();
|
|
76
|
+
for (const d of decisions) {
|
|
77
|
+
const status = d.retracted_at ? " (retracted)" : "";
|
|
78
|
+
console.log(` ${d.id.slice(0, 8)} [${d.category}] ${d.title}${status}`);
|
|
79
|
+
}
|
|
80
|
+
console.log();
|
|
81
|
+
}
|
|
82
|
+
async function amendDecision2(idPrefix, opts) {
|
|
83
|
+
const found = await findDecision(idPrefix);
|
|
84
|
+
if (!found) {
|
|
85
|
+
closePrompt();
|
|
86
|
+
process.exitCode = 1;
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const { config, match } = found;
|
|
90
|
+
if (match.retracted_at) {
|
|
91
|
+
console.error(` "${match.title}" has been retracted and can't be amended.`);
|
|
92
|
+
closePrompt();
|
|
93
|
+
process.exitCode = 1;
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
let title = opts?.title;
|
|
97
|
+
let description = opts?.description;
|
|
98
|
+
const category = opts?.category;
|
|
99
|
+
if (!title && !description && !category) {
|
|
100
|
+
if (!isInteractive()) {
|
|
101
|
+
console.error(" Nothing to amend \u2014 pass --title, --description, and/or --category.");
|
|
102
|
+
closePrompt();
|
|
103
|
+
process.exitCode = 1;
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
console.log(` Amending: "${match.title}"`);
|
|
107
|
+
title = await ask(` New title (leave blank to keep current): `);
|
|
108
|
+
description = await ask(` New description (leave blank to keep current): `);
|
|
109
|
+
}
|
|
110
|
+
if (!title?.trim() && !description?.trim() && !category) {
|
|
111
|
+
console.log(" Nothing changed.");
|
|
112
|
+
closePrompt();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
const updated = await amendDecision(config, match.id, {
|
|
116
|
+
...title?.trim() ? { title: title.trim() } : {},
|
|
117
|
+
...description?.trim() ? { description: description.trim() } : {},
|
|
118
|
+
...category ? { category } : {}
|
|
119
|
+
});
|
|
120
|
+
console.log(` \u2713 Decision amended: "${updated.title}"`);
|
|
121
|
+
closePrompt();
|
|
122
|
+
}
|
|
123
|
+
async function deleteDecision(idPrefix, opts) {
|
|
124
|
+
const found = await findDecision(idPrefix);
|
|
125
|
+
if (!found) {
|
|
126
|
+
closePrompt();
|
|
127
|
+
process.exitCode = 1;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const { config, match } = found;
|
|
131
|
+
if (match.retracted_at) {
|
|
132
|
+
console.log(` "${match.title}" is already retracted.`);
|
|
133
|
+
closePrompt();
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
console.log(` Retract: "${match.title}"`);
|
|
137
|
+
console.log(` ${match.description}`);
|
|
138
|
+
if (!opts?.yes) {
|
|
139
|
+
if (!isInteractive()) {
|
|
140
|
+
console.error();
|
|
141
|
+
console.error(` \u2717 Refusing to retract "${match.title}" without confirmation \u2014 no TTY is available to confirm.`);
|
|
142
|
+
console.error(` Re-run with --yes to retract non-interactively, or run interactively to confirm.`);
|
|
143
|
+
closePrompt();
|
|
144
|
+
process.exitCode = 1;
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const proceed = await confirm(" Retract this decision?");
|
|
148
|
+
if (!proceed) {
|
|
149
|
+
console.log(" Not retracted.");
|
|
150
|
+
closePrompt();
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
await retractDecision(config, match.id, opts?.reason);
|
|
155
|
+
console.log(` \u2713 Decision retracted: "${match.title}"`);
|
|
156
|
+
closePrompt();
|
|
157
|
+
}
|
|
158
|
+
async function logNote(storyId, note) {
|
|
159
|
+
const config = requireConfig();
|
|
160
|
+
if (!note) {
|
|
161
|
+
note = await ask(" Note: ");
|
|
162
|
+
}
|
|
163
|
+
if (!note?.trim()) {
|
|
164
|
+
console.log(" Note required.");
|
|
165
|
+
closePrompt();
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const listRes = await apiFetch(config, "/stories");
|
|
169
|
+
if (!listRes.ok) {
|
|
170
|
+
console.error(" Failed to fetch stories.");
|
|
171
|
+
closePrompt();
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const data = await listRes.json();
|
|
175
|
+
const match = data.stories.find((s) => matchesStoryRef(s, storyId));
|
|
176
|
+
if (!match) {
|
|
177
|
+
console.error(` No story found matching "${storyId}"`);
|
|
178
|
+
closePrompt();
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const res = await apiFetch(config, "/stories", {
|
|
182
|
+
method: "PATCH",
|
|
183
|
+
headers: { "Content-Type": "application/json" },
|
|
184
|
+
body: JSON.stringify({
|
|
185
|
+
stories: [{ id: match.id, notes: note.trim() }]
|
|
186
|
+
})
|
|
187
|
+
});
|
|
188
|
+
if (res.ok) {
|
|
189
|
+
console.log(` \u2713 Note added to: ${match.title.slice(0, 60)}`);
|
|
190
|
+
} else {
|
|
191
|
+
console.error(" Failed to add note.");
|
|
192
|
+
}
|
|
193
|
+
const appended = appendNoteToContext(match.id, note.trim());
|
|
194
|
+
if (appended) {
|
|
195
|
+
const relPath = storyContextPath(match.id).replace(process.cwd() + "/", "");
|
|
196
|
+
console.log(` \u2713 Updated local context: ${relPath}`);
|
|
197
|
+
}
|
|
198
|
+
closePrompt();
|
|
199
|
+
}
|
|
200
|
+
export {
|
|
201
|
+
amendDecision2 as amendDecision,
|
|
202
|
+
deleteDecision,
|
|
203
|
+
listLoggedDecisions,
|
|
204
|
+
logDecision,
|
|
205
|
+
logNote
|
|
206
|
+
};
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
closePrompt,
|
|
3
|
-
confirm
|
|
4
|
-
} from "./chunk-WPVDURTJ.js";
|
|
5
1
|
import {
|
|
6
2
|
isPlanGated,
|
|
7
3
|
printUpgradeMessage
|
|
8
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UR73WX5I.js";
|
|
9
5
|
import {
|
|
10
|
-
apiUrl
|
|
11
|
-
|
|
6
|
+
apiUrl,
|
|
7
|
+
syncHeaders
|
|
8
|
+
} from "./chunk-YUW3W43S.js";
|
|
12
9
|
import {
|
|
13
10
|
requireConfig
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import
|
|
11
|
+
} from "./chunk-UF535HZL.js";
|
|
12
|
+
import {
|
|
13
|
+
closePrompt,
|
|
14
|
+
confirm
|
|
15
|
+
} from "./chunk-WRRUCCVZ.js";
|
|
16
|
+
import "./chunk-LXQXJULN.js";
|
|
17
|
+
import "./chunk-UYTVTYNB.js";
|
|
16
18
|
|
|
17
19
|
// src/commands/map-import.ts
|
|
18
20
|
import { readFileSync, existsSync } from "fs";
|
|
@@ -309,7 +311,7 @@ async function mapImport(filePath, opts) {
|
|
|
309
311
|
const uploadSpinner = ora(" Uploading storymap...").start();
|
|
310
312
|
const res = await fetch(apiUrl(config, "/map-import"), {
|
|
311
313
|
method: "POST",
|
|
312
|
-
headers: { "Content-Type": "application/json" },
|
|
314
|
+
headers: syncHeaders({ "Content-Type": "application/json" }),
|
|
313
315
|
body: JSON.stringify(storymap)
|
|
314
316
|
});
|
|
315
317
|
if (!res.ok) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
var SCHEMA = {
|
|
3
3
|
$schema: "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
title: "IntentDocs Story Map",
|
|
5
|
-
description: "Schema for storymap.json files produced by `
|
|
5
|
+
description: "Schema for storymap.json files produced by `intentdocs map extract` and consumed by `intentdocs map import`.",
|
|
6
6
|
type: "object",
|
|
7
7
|
required: ["schema_version", "source", "product_summary", "backbone"],
|
|
8
8
|
additionalProperties: false,
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import {
|
|
2
|
+
authenticatedFetch,
|
|
3
|
+
bindingLabel,
|
|
4
|
+
getAuth
|
|
5
|
+
} from "./chunk-LXQXJULN.js";
|
|
6
|
+
import "./chunk-UYTVTYNB.js";
|
|
7
|
+
|
|
8
|
+
// src/commands/projects.ts
|
|
9
|
+
async function projects() {
|
|
10
|
+
const res = await authenticatedFetch("/api/cli/projects");
|
|
11
|
+
if (!res.ok) {
|
|
12
|
+
const body = await res.json().catch(() => ({}));
|
|
13
|
+
const said = body.message ?? (typeof body.error === "object" && body.error ? body.error.hint ?? body.error.message : void 0);
|
|
14
|
+
console.error(said ?? "Failed to fetch projects. The server returned an error \u2014 try again or check intentdocs.com for status.");
|
|
15
|
+
process.exit(1);
|
|
16
|
+
}
|
|
17
|
+
const data = await res.json();
|
|
18
|
+
console.log(`
|
|
19
|
+
${data.workspace}`);
|
|
20
|
+
console.log(` Token ${bindingLabel(getAuth()?.binding)}
|
|
21
|
+
`);
|
|
22
|
+
if (data.projects.length === 0) {
|
|
23
|
+
console.log(" No projects here yet. Create one at intentdocs.com first.\n");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
for (const p of data.projects) {
|
|
27
|
+
const where = p.workspace ? ` \xB7 ${p.workspace.name ?? "workspace"}` : "";
|
|
28
|
+
console.log(` ${p.id} ${p.name}${where}`);
|
|
29
|
+
if (p.description) console.log(` ${p.description.slice(0, 100)}`);
|
|
30
|
+
}
|
|
31
|
+
console.log(`
|
|
32
|
+
${data.projects.length} ${data.projects.length === 1 ? "project" : "projects"}. Check one out with: intentdocs init
|
|
33
|
+
`);
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
projects
|
|
37
|
+
};
|
|
@@ -4,13 +4,15 @@ import {
|
|
|
4
4
|
choose,
|
|
5
5
|
closePrompt,
|
|
6
6
|
confirm,
|
|
7
|
+
isInteractive,
|
|
7
8
|
pausePrompt
|
|
8
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-WRRUCCVZ.js";
|
|
9
10
|
export {
|
|
10
11
|
ask,
|
|
11
12
|
askMultiline,
|
|
12
13
|
choose,
|
|
13
14
|
closePrompt,
|
|
14
15
|
confirm,
|
|
16
|
+
isInteractive,
|
|
15
17
|
pausePrompt
|
|
16
18
|
};
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ask,
|
|
3
|
-
closePrompt
|
|
4
|
-
} from "./chunk-WPVDURTJ.js";
|
|
5
1
|
import {
|
|
6
2
|
isPlanGated,
|
|
7
3
|
printUpgradeMessage
|
|
8
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-UR73WX5I.js";
|
|
9
5
|
import {
|
|
10
|
-
apiUrl
|
|
11
|
-
|
|
6
|
+
apiUrl,
|
|
7
|
+
syncHeaders
|
|
8
|
+
} from "./chunk-YUW3W43S.js";
|
|
12
9
|
import {
|
|
13
10
|
requireConfig
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import
|
|
11
|
+
} from "./chunk-UF535HZL.js";
|
|
12
|
+
import {
|
|
13
|
+
ask,
|
|
14
|
+
closePrompt
|
|
15
|
+
} from "./chunk-WRRUCCVZ.js";
|
|
16
|
+
import "./chunk-LXQXJULN.js";
|
|
17
|
+
import "./chunk-UYTVTYNB.js";
|
|
16
18
|
|
|
17
19
|
// src/commands/research.ts
|
|
18
20
|
import ora from "ora";
|
|
@@ -31,7 +33,7 @@ async function research(query) {
|
|
|
31
33
|
try {
|
|
32
34
|
const res = await fetch(apiUrl(config, "/research"), {
|
|
33
35
|
method: "POST",
|
|
34
|
-
headers: { "Content-Type": "application/json" },
|
|
36
|
+
headers: syncHeaders({ "Content-Type": "application/json" }),
|
|
35
37
|
body: JSON.stringify({ query })
|
|
36
38
|
});
|
|
37
39
|
if (!res.ok) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {
|
|
2
|
+
setup
|
|
3
|
+
} from "./chunk-EEKEF2FD.js";
|
|
4
|
+
import "./chunk-HEHHSSUM.js";
|
|
5
|
+
import "./chunk-NFIXRIHM.js";
|
|
6
|
+
import "./chunk-LQTPZL2Y.js";
|
|
7
|
+
import "./chunk-YUW3W43S.js";
|
|
8
|
+
import "./chunk-UF535HZL.js";
|
|
9
|
+
import "./chunk-WRRUCCVZ.js";
|
|
10
|
+
import "./chunk-LXQXJULN.js";
|
|
11
|
+
import "./chunk-UYTVTYNB.js";
|
|
12
|
+
export {
|
|
13
|
+
setup
|
|
14
|
+
};
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "intentdocs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "CLI for intentdocs.com — intent-driven development: connect your codebase to your product specs",
|
|
5
5
|
"bin": {
|
|
6
|
+
"intentdocs": "bin/intentdocs.js",
|
|
6
7
|
"intent": "bin/intent.js"
|
|
7
8
|
},
|
|
8
9
|
"scripts": {
|
|
9
|
-
"build": "tsup --clean && chmod +x dist/index.js && chmod +x bin/intent.js",
|
|
10
|
+
"build": "tsup --clean && chmod +x dist/index.js && chmod +x bin/intent.js && chmod +x bin/intentdocs.js",
|
|
11
|
+
"postinstall": "echo '\\n intentdocs installed.\\n Commands: intentdocs (canonical), intent (alias — may collide with other tools)\\n'",
|
|
10
12
|
"dev": "tsup --watch",
|
|
11
13
|
"test": "vitest run",
|
|
12
14
|
"prepublishOnly": "npm run build"
|
package/dist/chunk-6XKB6RTU.js
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
writeConfig
|
|
3
|
-
} from "./chunk-ICOMMHKG.js";
|
|
4
|
-
import {
|
|
5
|
-
getAuth
|
|
6
|
-
} from "./chunk-PCNDP5SX.js";
|
|
7
|
-
|
|
8
|
-
// src/lib/api.ts
|
|
9
|
-
var AuthError = class extends Error {
|
|
10
|
-
constructor(message) {
|
|
11
|
-
super(message);
|
|
12
|
-
this.name = "AuthError";
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
async function refreshSyncToken(config) {
|
|
16
|
-
const auth = getAuth();
|
|
17
|
-
if (!auth || !config.projectId || !config.mapId) return null;
|
|
18
|
-
try {
|
|
19
|
-
const res = await fetch(
|
|
20
|
-
`${auth.apiBase}/api/cli/projects/${config.projectId}/maps`,
|
|
21
|
-
{ headers: { Authorization: `Bearer ${auth.token}`, "Content-Type": "application/json" } }
|
|
22
|
-
);
|
|
23
|
-
if (!res.ok) return null;
|
|
24
|
-
const { maps } = await res.json();
|
|
25
|
-
const map = maps.find((m) => m.id === config.mapId);
|
|
26
|
-
if (!map) return null;
|
|
27
|
-
const updated = { ...config, syncToken: map.syncToken };
|
|
28
|
-
writeConfig(updated);
|
|
29
|
-
return map.syncToken;
|
|
30
|
-
} catch {
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
async function apiFetch(config, path, init) {
|
|
35
|
-
const res = await fetch(apiUrl(config, path), init);
|
|
36
|
-
if (res.status === 401) {
|
|
37
|
-
const newToken = await refreshSyncToken(config);
|
|
38
|
-
if (newToken) {
|
|
39
|
-
const refreshedConfig = { ...config, syncToken: newToken };
|
|
40
|
-
const retry = await fetch(apiUrl(refreshedConfig, path), init);
|
|
41
|
-
if (retry.ok) return retry;
|
|
42
|
-
}
|
|
43
|
-
throw new AuthError(
|
|
44
|
-
"Session expired. Run `intent login` then `intent init` to re-authenticate."
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
if (res.status === 403) {
|
|
48
|
-
throw new AuthError(
|
|
49
|
-
"Access denied. You may not have permission for this project. Run `intent login`."
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
if (!res.ok) throw new Error(`API error: ${res.status}`);
|
|
53
|
-
return res;
|
|
54
|
-
}
|
|
55
|
-
function apiUrl(config, path) {
|
|
56
|
-
return `${config.apiBase}/api/sync/${config.syncToken}${path}`;
|
|
57
|
-
}
|
|
58
|
-
async function listStories(config) {
|
|
59
|
-
const res = await apiFetch(config, "/stories");
|
|
60
|
-
return res.json();
|
|
61
|
-
}
|
|
62
|
-
async function getContext(config) {
|
|
63
|
-
const res = await apiFetch(config, "/context");
|
|
64
|
-
return res.text();
|
|
65
|
-
}
|
|
66
|
-
async function updateStories(config, stories) {
|
|
67
|
-
const res = await apiFetch(config, "/stories", {
|
|
68
|
-
method: "PATCH",
|
|
69
|
-
headers: { "Content-Type": "application/json" },
|
|
70
|
-
body: JSON.stringify({ stories })
|
|
71
|
-
});
|
|
72
|
-
return res.json();
|
|
73
|
-
}
|
|
74
|
-
async function uploadScreenshot(config, storyId, screenshot) {
|
|
75
|
-
try {
|
|
76
|
-
const form = new FormData();
|
|
77
|
-
form.append("story_id", storyId);
|
|
78
|
-
form.append("image", new Blob([screenshot.buffer], { type: screenshot.mimeType }), screenshot.filename);
|
|
79
|
-
const res = await apiFetch(config, "/screenshots", {
|
|
80
|
-
method: "POST",
|
|
81
|
-
body: form
|
|
82
|
-
});
|
|
83
|
-
return await res.json();
|
|
84
|
-
} catch {
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
async function createStories(config, stories) {
|
|
89
|
-
const res = await apiFetch(config, "/stories", {
|
|
90
|
-
method: "POST",
|
|
91
|
-
headers: { "Content-Type": "application/json" },
|
|
92
|
-
body: JSON.stringify({ stories })
|
|
93
|
-
});
|
|
94
|
-
return res.json();
|
|
95
|
-
}
|
|
96
|
-
async function reportCriteria(config, storyId, results) {
|
|
97
|
-
const res = await apiFetch(config, "/criteria", {
|
|
98
|
-
method: "PATCH",
|
|
99
|
-
headers: { "Content-Type": "application/json" },
|
|
100
|
-
body: JSON.stringify({ story_id: storyId, results })
|
|
101
|
-
});
|
|
102
|
-
return res.json();
|
|
103
|
-
}
|
|
104
|
-
async function raiseBlocker(config, payload) {
|
|
105
|
-
const res = await apiFetch(config, "/blocker", {
|
|
106
|
-
method: "POST",
|
|
107
|
-
headers: { "Content-Type": "application/json" },
|
|
108
|
-
body: JSON.stringify(payload)
|
|
109
|
-
});
|
|
110
|
-
return res.json();
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
export {
|
|
114
|
-
apiFetch,
|
|
115
|
-
apiUrl,
|
|
116
|
-
listStories,
|
|
117
|
-
getContext,
|
|
118
|
-
updateStories,
|
|
119
|
-
uploadScreenshot,
|
|
120
|
-
createStories,
|
|
121
|
-
reportCriteria,
|
|
122
|
-
raiseBlocker
|
|
123
|
-
};
|
package/dist/chunk-PCNDP5SX.js
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
// src/lib/auth.ts
|
|
2
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
|
3
|
-
import { join } from "path";
|
|
4
|
-
import { homedir } from "os";
|
|
5
|
-
var AUTH_DIR = join(homedir(), ".intent");
|
|
6
|
-
var AUTH_FILE = join(AUTH_DIR, "auth.json");
|
|
7
|
-
function getAuth() {
|
|
8
|
-
try {
|
|
9
|
-
const raw = readFileSync(AUTH_FILE, "utf-8");
|
|
10
|
-
return JSON.parse(raw);
|
|
11
|
-
} catch {
|
|
12
|
-
return null;
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
function saveAuth(data) {
|
|
16
|
-
if (!existsSync(AUTH_DIR)) mkdirSync(AUTH_DIR, { recursive: true });
|
|
17
|
-
writeFileSync(AUTH_FILE, JSON.stringify(data, null, 2) + "\n", { mode: 384 });
|
|
18
|
-
}
|
|
19
|
-
function requireAuth() {
|
|
20
|
-
const auth = getAuth();
|
|
21
|
-
if (!auth) {
|
|
22
|
-
console.error("Not logged in. Run: intent login");
|
|
23
|
-
process.exit(1);
|
|
24
|
-
}
|
|
25
|
-
return auth;
|
|
26
|
-
}
|
|
27
|
-
var API_BASE = "https://intentdocs.com";
|
|
28
|
-
|
|
29
|
-
export {
|
|
30
|
-
getAuth,
|
|
31
|
-
saveAuth,
|
|
32
|
-
requireAuth,
|
|
33
|
-
API_BASE
|
|
34
|
-
};
|