sdocs-dev 1.15.0 → 1.19.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/bin/sdocs-dev.js +52 -17
- package/lib/agent-block.js +270 -50
- package/lib/agent-files.js +312 -74
- package/lib/cells-verify.js +1 -0
- package/lib/cloud-bindings.js +85 -0
- package/lib/cloud-commands.js +826 -0
- package/lib/cloud-credentials.js +380 -0
- package/lib/commands.js +46 -5
- package/lib/help-text.js +301 -70
- package/lib/io.js +53 -5
- package/lib/library-commands.js +6 -15
- package/lib/library-scan.js +16 -6
- package/lib/library-server.js +4 -12
- package/lib/setup.js +182 -191
- package/lib/short-link.js +38 -1
- package/lib/slides-verify.js +109 -0
- package/package.json +1 -1
- package/shared/sdocs-cells-formula.js +547 -73
- package/shared/sdocs-cells.js +164 -18
- package/shared/sdocs-shapes.js +1044 -0
- package/shared/sdocs-slide-resolve.js +258 -0
- package/shared/sdocs-slide-stdlib.js +180 -0
- package/shared/sdocs-styles.js +1 -1
package/lib/io.js
CHANGED
|
@@ -9,11 +9,12 @@ const codeLangs = require('./code-langs');
|
|
|
9
9
|
|
|
10
10
|
const SUBCOMMANDS = new Set([
|
|
11
11
|
'new', 'share', 'schema', 'defaults', 'help', 'version',
|
|
12
|
-
'charts', 'diagrams', 'videos', 'video', 'cells', 'code', 'comments',
|
|
12
|
+
'charts', 'diagrams', 'videos', 'video', 'apps', 'app', 'cells', 'code', 'comments',
|
|
13
13
|
'setup', 'safe', 'auto-update', 'refresh', 'upgrade',
|
|
14
14
|
'bridge', 'feedback',
|
|
15
15
|
'slides', 'present',
|
|
16
16
|
'library',
|
|
17
|
+
'cloud',
|
|
17
18
|
'color-analysis',
|
|
18
19
|
]);
|
|
19
20
|
|
|
@@ -38,6 +39,8 @@ function parseArgs(argv) {
|
|
|
38
39
|
let url = null;
|
|
39
40
|
let subcommand = null;
|
|
40
41
|
let section = null;
|
|
42
|
+
let sourceFlag = null;
|
|
43
|
+
let placementFlag = null;
|
|
41
44
|
let theme = null;
|
|
42
45
|
let resetFlag = false;
|
|
43
46
|
let shortFlag = false;
|
|
@@ -54,7 +57,25 @@ function parseArgs(argv) {
|
|
|
54
57
|
let helpFlag = false;
|
|
55
58
|
let yesFlag = false;
|
|
56
59
|
let dryRunFlag = false;
|
|
60
|
+
let skillEdition = null;
|
|
57
61
|
let sheetName = null;
|
|
62
|
+
let projectFlag = null;
|
|
63
|
+
let accountFlag = null;
|
|
64
|
+
let outputPath = null;
|
|
65
|
+
let revisionFlag = null;
|
|
66
|
+
let documentFlag = null;
|
|
67
|
+
let baseRevisionFlag = null;
|
|
68
|
+
let limitFlag = null;
|
|
69
|
+
let noOpenFlag = false;
|
|
70
|
+
let noBindFlag = false;
|
|
71
|
+
let forceFlag = false;
|
|
72
|
+
let everyoneFlag = false;
|
|
73
|
+
let onlyYouFlag = false;
|
|
74
|
+
let sharedWithMeFlag = false;
|
|
75
|
+
let noteText = null;
|
|
76
|
+
const memberFlags = [];
|
|
77
|
+
const documentFlags = [];
|
|
78
|
+
const tagFilters = [];
|
|
58
79
|
const addTags = [];
|
|
59
80
|
const annotations = [];
|
|
60
81
|
// Multi-file code walkthrough: every source-code positional is collected
|
|
@@ -97,6 +118,8 @@ function parseArgs(argv) {
|
|
|
97
118
|
|
|
98
119
|
if (arg === '--url') { url = args[++i]; continue; }
|
|
99
120
|
if (arg === '--section' || arg === '-s') { section = args[++i]; continue; }
|
|
121
|
+
if (arg === '--source') { sourceFlag = args[++i]; continue; }
|
|
122
|
+
if (arg === '--placement') { placementFlag = args[++i]; continue; }
|
|
100
123
|
if (arg === '--reset') { resetFlag = true; continue; }
|
|
101
124
|
if (arg === '--short') { shortFlag = true; continue; }
|
|
102
125
|
if (arg === '--json') { jsonFlag = true; continue; }
|
|
@@ -114,7 +137,29 @@ function parseArgs(argv) {
|
|
|
114
137
|
if (arg === '--tags') { tagsFlag = true; continue; }
|
|
115
138
|
if (arg === '--yes' || arg === '-y') { yesFlag = true; continue; }
|
|
116
139
|
if (arg === '--dry-run') { dryRunFlag = true; continue; }
|
|
140
|
+
if (arg === '--cloud') { skillEdition = 'cloud'; continue; }
|
|
141
|
+
if (arg === '--standard') { skillEdition = 'standard'; continue; }
|
|
117
142
|
if (arg === '--sheet') { sheetName = args[++i]; continue; }
|
|
143
|
+
if (arg === '--project') { projectFlag = args[++i]; continue; }
|
|
144
|
+
if (arg === '--account') { accountFlag = args[++i]; continue; }
|
|
145
|
+
if (arg === '--member') { memberFlags.push(args[++i]); continue; }
|
|
146
|
+
if (arg === '--everyone') { everyoneFlag = true; continue; }
|
|
147
|
+
if (arg === '--only-you') { onlyYouFlag = true; continue; }
|
|
148
|
+
if (arg === '--shared-with-me') { sharedWithMeFlag = true; continue; }
|
|
149
|
+
if (arg === '--note') { noteText = args[++i]; continue; }
|
|
150
|
+
if (arg === '--output' || arg === '-o') { outputPath = args[++i]; continue; }
|
|
151
|
+
if (arg === '--revision') { revisionFlag = args[++i]; continue; }
|
|
152
|
+
if (arg === '--document') {
|
|
153
|
+
documentFlag = args[++i];
|
|
154
|
+
documentFlags.push(documentFlag);
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
if (arg === '--base-revision') { baseRevisionFlag = args[++i]; continue; }
|
|
158
|
+
if (arg === '--limit') { limitFlag = Number(args[++i]); continue; }
|
|
159
|
+
if (arg === '--tag') { tagFilters.push(args[++i]); continue; }
|
|
160
|
+
if (arg === '--no-open') { noOpenFlag = true; continue; }
|
|
161
|
+
if (arg === '--no-bind') { noBindFlag = true; continue; }
|
|
162
|
+
if (arg === '--force') { forceFlag = true; continue; }
|
|
118
163
|
|
|
119
164
|
if (!subcommand && SUBCOMMANDS.has(arg)) {
|
|
120
165
|
subcommand = arg;
|
|
@@ -160,11 +205,14 @@ function parseArgs(argv) {
|
|
|
160
205
|
}
|
|
161
206
|
|
|
162
207
|
return {
|
|
163
|
-
file, extra, mode, url, subcommand, section, theme,
|
|
208
|
+
file, extra, mode, url, subcommand, section, sourceFlag, placementFlag, theme,
|
|
164
209
|
resetFlag, shortFlag, jsonFlag, auditFlag, waitFlag,
|
|
165
210
|
messageText, connectTimeoutS, idleTimeoutS, reconnectGraceMs,
|
|
166
211
|
keepOpenFlag, logFile,
|
|
167
|
-
tagsFlag, helpFlag, yesFlag, dryRunFlag, sheetName,
|
|
212
|
+
tagsFlag, helpFlag, yesFlag, dryRunFlag, skillEdition, sheetName,
|
|
213
|
+
projectFlag, accountFlag, outputPath, revisionFlag, documentFlag, baseRevisionFlag,
|
|
214
|
+
limitFlag, noOpenFlag, noBindFlag, forceFlag, tagFilters,
|
|
215
|
+
everyoneFlag, onlyYouFlag, sharedWithMeFlag, noteText, memberFlags, documentFlags,
|
|
168
216
|
addTags, annotations, files,
|
|
169
217
|
};
|
|
170
218
|
}
|
|
@@ -236,13 +284,13 @@ function readCodewalkContent(files) {
|
|
|
236
284
|
return { body: parts.join('\n'), files: tabs };
|
|
237
285
|
}
|
|
238
286
|
|
|
239
|
-
function openBrowser(url) {
|
|
287
|
+
function openBrowser(url, fallback) {
|
|
240
288
|
try {
|
|
241
289
|
if (process.platform === 'darwin') execFileSync('open', [url]);
|
|
242
290
|
else if (process.platform === 'win32') execFileSync('cmd', ['/c', 'start', '', url]);
|
|
243
291
|
else execFileSync('xdg-open', [url]);
|
|
244
292
|
} catch {
|
|
245
|
-
console.log(`Open in browser: ${url}`);
|
|
293
|
+
(fallback || console.log)(`Open in browser: ${url}`);
|
|
246
294
|
}
|
|
247
295
|
}
|
|
248
296
|
|
package/lib/library-commands.js
CHANGED
|
@@ -30,16 +30,8 @@ function libraryDisable() {
|
|
|
30
30
|
function libraryStatus() {
|
|
31
31
|
const s = store.loadState();
|
|
32
32
|
const idx = store.loadIndex();
|
|
33
|
-
const last = s.lastScanAt ? new Date(s.lastScanAt).toISOString() : 'never';
|
|
34
33
|
console.log(`library: ${s.enabled === false ? 'disabled' : 'enabled'}`);
|
|
35
34
|
console.log(`entries: ${idx.entries.length}`);
|
|
36
|
-
console.log(`last scan: ${last}`);
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function libraryRebuild() {
|
|
40
|
-
console.log('library: rebuilding...');
|
|
41
|
-
const result = libIndex.rebuild();
|
|
42
|
-
console.log(`library: scanned ${result.scanned}, added ${result.added}, updated ${result.updated}`);
|
|
43
35
|
}
|
|
44
36
|
|
|
45
37
|
// Walk up from a directory looking for `.git/`. Falls back to the start
|
|
@@ -114,7 +106,7 @@ function libraryLs(opts) {
|
|
|
114
106
|
const tags = libIndex.tagsUnderPrefix(scope);
|
|
115
107
|
if (!tags.length) {
|
|
116
108
|
console.log(`no tagged markdown files indexed under ${scope} yet`);
|
|
117
|
-
console.log(`(tip:
|
|
109
|
+
console.log(`(tip: open a file with \`sdoc <file> +tag\` to add and tag it)`);
|
|
118
110
|
return;
|
|
119
111
|
}
|
|
120
112
|
console.log(`most frequent tags for tagged markdown files under ${scope} (tag - count):`);
|
|
@@ -132,7 +124,7 @@ function libraryLs(opts) {
|
|
|
132
124
|
const entries = entriesUnderScope(scope);
|
|
133
125
|
if (!entries.length) {
|
|
134
126
|
console.log(`library has no markdown indexed under ${scope} yet`);
|
|
135
|
-
console.log(`(tip:
|
|
127
|
+
console.log(`(tip: open a file with \`sdoc <file>\` to add it)`);
|
|
136
128
|
return;
|
|
137
129
|
}
|
|
138
130
|
|
|
@@ -209,8 +201,8 @@ async function libraryOpen() {
|
|
|
209
201
|
const { agentUrl } = await libServer.createServer();
|
|
210
202
|
const pageUrl = `${siteUrl}/library?agent=${encodeURIComponent(agentUrl)}`;
|
|
211
203
|
console.log(`library: ${pageUrl}`);
|
|
212
|
-
console.log(`library: ${idx.entries.length} entries indexed` + (state.enabled === false ? ' (
|
|
213
|
-
if (!idx.entries.length) console.log('library:
|
|
204
|
+
console.log(`library: ${idx.entries.length} entries indexed` + (state.enabled === false ? ' (indexing disabled)' : ''));
|
|
205
|
+
if (!idx.entries.length) console.log('library: open a file with `sdoc <file>` to add it.');
|
|
214
206
|
ensureAutostart();
|
|
215
207
|
console.log(`library: agent at ${agentUrl} (ctrl-c to stop)`);
|
|
216
208
|
openBrowser(pageUrl);
|
|
@@ -263,7 +255,6 @@ async function libraryCommand(opts) {
|
|
|
263
255
|
case 'enable': libraryEnable(); break;
|
|
264
256
|
case 'disable': libraryDisable(); break;
|
|
265
257
|
case 'status': libraryStatus(); break;
|
|
266
|
-
case 'rebuild': libraryRebuild(); break;
|
|
267
258
|
case 'autostart': {
|
|
268
259
|
const action = (opts.extra || '').toLowerCase();
|
|
269
260
|
if (action === 'enable') autostartEnable();
|
|
@@ -278,7 +269,7 @@ async function libraryCommand(opts) {
|
|
|
278
269
|
}
|
|
279
270
|
default:
|
|
280
271
|
console.error(`sdoc library: unknown subcommand "${sub}"`);
|
|
281
|
-
console.error('usage: sdoc library [ls|enable|disable|status|
|
|
272
|
+
console.error('usage: sdoc library [ls|enable|disable|status|autostart|help]');
|
|
282
273
|
process.exit(1);
|
|
283
274
|
}
|
|
284
275
|
}
|
|
@@ -300,7 +291,7 @@ function tapOpen(opts) {
|
|
|
300
291
|
|
|
301
292
|
module.exports = {
|
|
302
293
|
libraryCommand,
|
|
303
|
-
libraryEnable, libraryDisable, libraryStatus,
|
|
294
|
+
libraryEnable, libraryDisable, libraryStatus, libraryOpen,
|
|
304
295
|
libraryLs, libraryHelp,
|
|
305
296
|
resolveProjectRoot, resolveLsScope, entriesUnderScope,
|
|
306
297
|
tapOpen,
|
package/lib/library-scan.js
CHANGED
|
@@ -15,18 +15,13 @@ const paths = require('./library-paths');
|
|
|
15
15
|
const DEFAULT_MAX_SIZE = 1 * 1024 * 1024;
|
|
16
16
|
|
|
17
17
|
const DIRNAME_BLOCKLIST = new Set([
|
|
18
|
-
'node_modules',
|
|
19
18
|
'.git',
|
|
20
19
|
'.svn',
|
|
21
20
|
'.hg',
|
|
22
|
-
'dist',
|
|
23
|
-
'build',
|
|
24
|
-
'vendor',
|
|
25
21
|
'.venv',
|
|
26
22
|
'.next',
|
|
27
23
|
'.cache',
|
|
28
24
|
'__pycache__',
|
|
29
|
-
'target',
|
|
30
25
|
'.gradle',
|
|
31
26
|
'.idea',
|
|
32
27
|
'.vscode',
|
|
@@ -46,6 +41,19 @@ const DIRNAME_BLOCKLIST = new Set([
|
|
|
46
41
|
'.password-store',
|
|
47
42
|
]);
|
|
48
43
|
|
|
44
|
+
// Directories skipped during scanning traversal for speed, but NOT blocked
|
|
45
|
+
// from path-gating when opening an explicitly indexed file.
|
|
46
|
+
const SCAN_SKIP_DIRNAMES = new Set([
|
|
47
|
+
'assets',
|
|
48
|
+
'graphify',
|
|
49
|
+
'node_modules',
|
|
50
|
+
'vendor',
|
|
51
|
+
'target',
|
|
52
|
+
'dist',
|
|
53
|
+
'build',
|
|
54
|
+
'venv',
|
|
55
|
+
]);
|
|
56
|
+
|
|
49
57
|
// File basenames that should never make it into the library, regardless
|
|
50
58
|
// of which directory they live in or what extension they carry. Most of
|
|
51
59
|
// these don't have a markdown extension and so the existing extension
|
|
@@ -129,8 +137,10 @@ function deniedByPattern(absPath) {
|
|
|
129
137
|
}
|
|
130
138
|
|
|
131
139
|
function shouldSkipDir(absDir, base, skipSet, exemptRoots) {
|
|
132
|
-
|
|
140
|
+
// Exempt .sdocs so AI coding agent markdown artifacts are indexed
|
|
141
|
+
if (base.startsWith('.') && base !== '.' && base !== '..' && base !== '.sdocs') return true;
|
|
133
142
|
if (DIRNAME_BLOCKLIST.has(base)) return true;
|
|
143
|
+
if (SCAN_SKIP_DIRNAMES.has(base)) return true;
|
|
134
144
|
if (skipSet.has(absDir)) return true;
|
|
135
145
|
// Skip ephemeral paths during descent unless we're inside a root that
|
|
136
146
|
// the caller explicitly named (in which case they want it scanned).
|
package/lib/library-server.js
CHANGED
|
@@ -35,9 +35,8 @@ try {
|
|
|
35
35
|
// 2. The deny-pattern list (SSH keys, .env, credentials.{json,...}
|
|
36
36
|
// and anything under .ssh/.aws/.gnupg/...).
|
|
37
37
|
// 3. Library-membership: the real path must appear in the index.
|
|
38
|
-
// The index
|
|
39
|
-
//
|
|
40
|
-
// are refused.
|
|
38
|
+
// The index contains files the user explicitly opened with sdoc;
|
|
39
|
+
// arbitrary paths outside that set are refused.
|
|
41
40
|
//
|
|
42
41
|
// Returns { ok: true, realPath } on pass, { ok: false, reason, status }
|
|
43
42
|
// on refusal. Caller picks the HTTP status from `status`.
|
|
@@ -295,12 +294,6 @@ function createServer({ port } = {}) {
|
|
|
295
294
|
return;
|
|
296
295
|
}
|
|
297
296
|
|
|
298
|
-
if (req.method === 'POST' && route === '/api/library/rescan') {
|
|
299
|
-
const result = libIndex.scanAndIndex();
|
|
300
|
-
sendJson(res, 200, result);
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
297
|
// Serve the current contents of a local file. The editor page
|
|
305
298
|
// uses this to refresh content after the URL-hash snapshot goes
|
|
306
299
|
// stale (e.g. after the user edited tags then reloaded). Gated
|
|
@@ -319,9 +312,8 @@ function createServer({ port } = {}) {
|
|
|
319
312
|
}
|
|
320
313
|
|
|
321
314
|
// Re-index a single file. Called by the editor page after a Bridge
|
|
322
|
-
// save so the library catches up immediately
|
|
323
|
-
//
|
|
324
|
-
// the file the path points at.
|
|
315
|
+
// save so the library catches up immediately. Pure read-then-index;
|
|
316
|
+
// never writes the file the path points at.
|
|
325
317
|
if (req.method === 'POST' && route === '/api/library/reindex') {
|
|
326
318
|
const body = await readBody(req);
|
|
327
319
|
const filePath = body && body.path;
|