openworkgraph 0.3.1 → 0.3.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 +64 -64
- package/dist/builtin-skills.d.ts +8 -0
- package/dist/builtin-skills.js +31 -14
- package/dist/cli.js +0 -0
- package/dist/graphs.js +17 -17
- package/dist/persistence/asset-business-schema.js +33 -33
- package/dist/persistence/plugin-schema.js +28 -28
- package/dist/persistence/resource-schema.js +41 -41
- package/dist/persistence/schema.js +216 -216
- package/dist/persistence/workflow-schema.js +16 -16
- package/dist/runs.js +8 -8
- package/dist/skill-configs.d.ts +7 -3
- package/dist/skill-configs.js +123 -65
- package/dist/skill-sessions.d.ts +1 -2
- package/dist/skill-sessions.js +5 -4
- package/dist/skills-management-api.js +7 -3
- package/dist/vendor/protocol/index.d.ts +1 -1
- package/dist/vendor/protocol/index.js +1 -1
- package/package.json +9 -9
package/dist/skill-configs.js
CHANGED
|
@@ -96,7 +96,7 @@ export class SkillConfigs {
|
|
|
96
96
|
if (await powershell(aclCheck, JSON.stringify({ path, sid })) !== 'ok')
|
|
97
97
|
throw Error('Unsafe ACL');
|
|
98
98
|
}
|
|
99
|
-
async directory(skillId) {
|
|
99
|
+
async directory(skillId, writable = true) {
|
|
100
100
|
identifier(skillId);
|
|
101
101
|
if (!['win32', 'darwin', 'linux'].includes(process.platform))
|
|
102
102
|
throw new ServiceError('MODEL_UNAVAILABLE', '当前平台不支持受限技能配置存储。');
|
|
@@ -104,12 +104,36 @@ export class SkillConfigs {
|
|
|
104
104
|
const workspace = join(root, hash(this.serviceId));
|
|
105
105
|
const skill = join(workspace, hash(skillId));
|
|
106
106
|
for (const path of [this.directories.config, root, workspace, skill]) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
107
|
+
if (writable) {
|
|
108
|
+
ensureDirectory(path);
|
|
109
|
+
if (process.platform === 'win32')
|
|
110
|
+
await this.windowsAcl(path, true, true);
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
try {
|
|
114
|
+
const stat = lstatSync(path);
|
|
115
|
+
if (!stat.isDirectory() || stat.isSymbolicLink() || (process.getuid && stat.uid !== process.getuid()))
|
|
116
|
+
throw Error('Unsafe storage');
|
|
117
|
+
}
|
|
118
|
+
catch (error) {
|
|
119
|
+
if (error.code !== 'ENOENT')
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
110
123
|
}
|
|
111
124
|
return skill;
|
|
112
125
|
}
|
|
126
|
+
/** Immutable snapshots and an atomically published manifest need no read lock. */
|
|
127
|
+
async reading(skillId, action) {
|
|
128
|
+
try {
|
|
129
|
+
return await action(await this.directory(skillId, false));
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
if (error instanceof ServiceError)
|
|
133
|
+
throw error;
|
|
134
|
+
throw new ServiceError('MODEL_UNAVAILABLE', '技能配置读取不可用。');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
113
137
|
async locked(skillId, action) {
|
|
114
138
|
try {
|
|
115
139
|
const path = await this.directory(skillId), lock = join(path, '.lock');
|
|
@@ -139,16 +163,52 @@ export class SkillConfigs {
|
|
|
139
163
|
throw new ServiceError('MODEL_UNAVAILABLE', '受限技能配置存储不可用。');
|
|
140
164
|
}
|
|
141
165
|
}
|
|
142
|
-
|
|
166
|
+
/** Coordinate revocation with final validation/dispatch, independently of write locks.
|
|
167
|
+
* Owner metadata contains no configuration values and needs no ACL subprocesses. */
|
|
168
|
+
async withDispatchLock(action) {
|
|
169
|
+
const lock = join(this.directories.config, '.skill-dispatch-' + hash(this.serviceId));
|
|
170
|
+
try {
|
|
171
|
+
ensureDirectory(this.directories.config);
|
|
172
|
+
const deadline = Date.now() + 5000;
|
|
173
|
+
for (;;) {
|
|
174
|
+
if (await this.claim(lock, false))
|
|
175
|
+
break;
|
|
176
|
+
if (await this.recover(lock, 0, false))
|
|
177
|
+
continue;
|
|
178
|
+
if (Date.now() >= deadline)
|
|
179
|
+
throw new ServiceError('CONFLICT', '技能配置正在清除或派发,请稍后重试。', { retryable: true });
|
|
180
|
+
await delay(20);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
if (error instanceof ServiceError)
|
|
185
|
+
throw error;
|
|
186
|
+
throw new ServiceError('MODEL_UNAVAILABLE', '技能配置撤销协调不可用。');
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
return await action();
|
|
190
|
+
}
|
|
191
|
+
finally {
|
|
192
|
+
try {
|
|
193
|
+
const released = join(this.directories.config, '.released-' + randomUUID());
|
|
194
|
+
await rename(lock, released);
|
|
195
|
+
await rm(released, { recursive: true, force: true });
|
|
196
|
+
}
|
|
197
|
+
catch {
|
|
198
|
+
throw new ServiceError('MODEL_UNAVAILABLE', '技能配置撤销协调不可用。');
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
async claim(lock, restrict = true) {
|
|
143
203
|
const prepared = join(dirname(lock), '.owner-' + randomUUID());
|
|
144
204
|
await mkdir(prepared, { mode: 0o700 });
|
|
145
205
|
try {
|
|
146
|
-
if (process.platform === 'win32')
|
|
206
|
+
if (restrict && process.platform === 'win32')
|
|
147
207
|
await this.windowsAcl(prepared, true, true);
|
|
148
208
|
const owner = { pid: process.pid, started: new Date(Date.now() - process.uptime() * 1000).toISOString(), hostname: hostname(), token: randomUUID() };
|
|
149
209
|
// Publish a nonempty directory only after durable owner metadata exists.
|
|
150
210
|
// rename cannot replace another nonempty lock directory, on either OS.
|
|
151
|
-
await this.atomic(prepared, 'owner-' + owner.token + '.json', owner);
|
|
211
|
+
await this.atomic(prepared, 'owner-' + owner.token + '.json', owner, restrict);
|
|
152
212
|
try {
|
|
153
213
|
lstatSync(lock);
|
|
154
214
|
return undefined;
|
|
@@ -218,17 +278,17 @@ export class SkillConfigs {
|
|
|
218
278
|
return error.code === 'ESRCH';
|
|
219
279
|
}
|
|
220
280
|
}
|
|
221
|
-
async recover(lock, depth = 0) {
|
|
281
|
+
async recover(lock, depth = 0, restrict = true) {
|
|
222
282
|
const owner = await this.owner(lock);
|
|
223
283
|
if (!owner || !this.dead(owner) || depth > 4)
|
|
224
284
|
return false;
|
|
225
285
|
const recovery = join(lock, '.recovery');
|
|
226
286
|
let claim;
|
|
227
287
|
try {
|
|
228
|
-
claim = await this.claim(recovery);
|
|
288
|
+
claim = await this.claim(recovery, restrict);
|
|
229
289
|
if (!claim) {
|
|
230
290
|
// A recovery worker can itself crash. Its owner follows the same rule.
|
|
231
|
-
await this.recover(recovery, depth + 1);
|
|
291
|
+
await this.recover(recovery, depth + 1, restrict);
|
|
232
292
|
return false;
|
|
233
293
|
}
|
|
234
294
|
}
|
|
@@ -284,29 +344,34 @@ export class SkillConfigs {
|
|
|
284
344
|
const stat = await file.stat();
|
|
285
345
|
if (!stat.isFile() || stat.nlink !== 1 || (process.platform !== 'win32' && (stat.mode & 0o777) !== 0o600) || stat.size > storageBytes || (process.getuid && stat.uid !== process.getuid()))
|
|
286
346
|
throw Error('Unsafe storage');
|
|
287
|
-
if (process.platform === 'win32')
|
|
288
|
-
await this.windowsAcl(path, false, false);
|
|
289
347
|
return JSON.parse(await file.readFile('utf8'));
|
|
290
348
|
}
|
|
291
349
|
finally {
|
|
292
350
|
await file.close();
|
|
293
351
|
}
|
|
294
352
|
}
|
|
295
|
-
async manifest(path) {
|
|
353
|
+
async manifest(path, writable = true) {
|
|
296
354
|
const raw = await this.load(join(path, 'current.json'));
|
|
297
355
|
if (raw === undefined) {
|
|
298
356
|
// Establish revision zero before a first write. A lost committed manifest
|
|
299
357
|
// must not make old revision numbers eligible for reuse with new secrets.
|
|
300
|
-
|
|
358
|
+
const names = await readdir(path).catch(error => { if (error.code === 'ENOENT')
|
|
359
|
+
return []; throw error; });
|
|
360
|
+
if (names.some(name => /^[0-9]+\.json$/.test(name))) {
|
|
361
|
+
// A first writer may have committed after our initial read.
|
|
362
|
+
if (!writable && await this.load(join(path, 'current.json')) !== undefined)
|
|
363
|
+
return this.manifest(path, false);
|
|
301
364
|
throw Error('Missing revision manifest');
|
|
365
|
+
}
|
|
302
366
|
const manifest = initial();
|
|
303
|
-
|
|
367
|
+
if (writable)
|
|
368
|
+
await this.atomic(path, 'current.json', manifest);
|
|
304
369
|
return manifest;
|
|
305
370
|
}
|
|
306
371
|
const value = raw;
|
|
307
372
|
if (!value || value.version !== 1 || !Number.isSafeInteger(value.revision) || value.revision < 0 || !Number.isSafeInteger(value.minimumRevision) || value.minimumRevision < 0 || value.minimumRevision > value.revision)
|
|
308
373
|
throw Error('Invalid storage');
|
|
309
|
-
if (value.minimumRevision > 0)
|
|
374
|
+
if (writable && value.minimumRevision > 0)
|
|
310
375
|
await this.removeRevoked(path, value.minimumRevision);
|
|
311
376
|
return value;
|
|
312
377
|
}
|
|
@@ -335,15 +400,17 @@ export class SkillConfigs {
|
|
|
335
400
|
}
|
|
336
401
|
return value;
|
|
337
402
|
}
|
|
338
|
-
async atomic(path, name, value) {
|
|
403
|
+
async atomic(path, name, value, restrict = true) {
|
|
339
404
|
const text = JSON.stringify(value);
|
|
340
405
|
if (Buffer.byteLength(text) > storageBytes)
|
|
341
406
|
invalid();
|
|
342
407
|
const temporary = join(path, '.' + randomUUID() + '.tmp');
|
|
343
408
|
const file = await open(temporary, constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
|
|
344
409
|
try {
|
|
345
|
-
if (process.platform === 'win32')
|
|
346
|
-
|
|
410
|
+
if (process.platform === 'win32') {
|
|
411
|
+
if (restrict)
|
|
412
|
+
await this.windowsAcl(temporary, false, true);
|
|
413
|
+
}
|
|
347
414
|
else
|
|
348
415
|
await file.chmod(0o600);
|
|
349
416
|
await file.writeFile(text, 'utf8');
|
|
@@ -387,8 +454,8 @@ export class SkillConfigs {
|
|
|
387
454
|
}
|
|
388
455
|
async read(skillId, schema) {
|
|
389
456
|
const checked = schemaCopy(schema);
|
|
390
|
-
return this.
|
|
391
|
-
const manifest = await this.manifest(path);
|
|
457
|
+
return this.reading(skillId, async (path) => {
|
|
458
|
+
const manifest = await this.manifest(path, false);
|
|
392
459
|
return this.view(skillId, checked, manifest, await this.snapshot(path, manifest, manifest.revision));
|
|
393
460
|
});
|
|
394
461
|
}
|
|
@@ -457,23 +524,23 @@ export class SkillConfigs {
|
|
|
457
524
|
const snapshot = { revision, values: {} };
|
|
458
525
|
const next = { ...manifest, revision, minimumRevision: revision };
|
|
459
526
|
await this.atomic(path, String(revision) + '.json', snapshot);
|
|
460
|
-
await this.atomic(path, 'current.json', next);
|
|
527
|
+
await this.withDispatchLock(() => this.atomic(path, 'current.json', next));
|
|
461
528
|
// Revocation commits before deletion. A crash midway is safe, and the
|
|
462
|
-
// next
|
|
529
|
+
// next write resumes deleting the revoked private files.
|
|
463
530
|
await this.removeRevoked(path, revision);
|
|
464
531
|
return this.view(skillId, emptySchema, next, snapshot);
|
|
465
532
|
});
|
|
466
533
|
}
|
|
467
|
-
async revision(skillId) { return this.
|
|
534
|
+
async revision(skillId) { return this.reading(skillId, async (path) => (await this.manifest(path, false)).revision); }
|
|
468
535
|
async hasRevision(skillId, revision) {
|
|
469
536
|
revisionNumber(revision);
|
|
470
|
-
return this.
|
|
471
|
-
const manifest = await this.manifest(path);
|
|
537
|
+
return this.reading(skillId, async (path) => {
|
|
538
|
+
const manifest = await this.manifest(path, false);
|
|
472
539
|
if (revision < manifest.minimumRevision || revision > manifest.revision)
|
|
473
540
|
return false;
|
|
474
541
|
try {
|
|
475
542
|
await this.snapshot(path, manifest, revision);
|
|
476
|
-
return
|
|
543
|
+
return revision >= (await this.manifest(path, false)).minimumRevision;
|
|
477
544
|
}
|
|
478
545
|
catch (error) {
|
|
479
546
|
if (error instanceof ServiceError && error.code === 'INVALID_REQUEST')
|
|
@@ -485,8 +552,10 @@ export class SkillConfigs {
|
|
|
485
552
|
async environment(skillId, schema, revision) {
|
|
486
553
|
const checked = schemaCopy(schema);
|
|
487
554
|
revisionNumber(revision);
|
|
488
|
-
return this.
|
|
489
|
-
const manifest = await this.manifest(path), snapshot = await this.snapshot(path, manifest, revision);
|
|
555
|
+
return this.reading(skillId, async (path) => {
|
|
556
|
+
const manifest = await this.manifest(path, false), snapshot = await this.snapshot(path, manifest, revision);
|
|
557
|
+
if (revision < (await this.manifest(path, false)).minimumRevision)
|
|
558
|
+
unavailable();
|
|
490
559
|
return this.snapshotEnvironment(checked, snapshot);
|
|
491
560
|
});
|
|
492
561
|
}
|
|
@@ -501,9 +570,8 @@ export class SkillConfigs {
|
|
|
501
570
|
}
|
|
502
571
|
return environment;
|
|
503
572
|
}
|
|
504
|
-
/**
|
|
505
|
-
*
|
|
506
|
-
* methods may be awaited inside dispatch. Never await a returned command. */
|
|
573
|
+
/** Read snapshots without write locks. Only final validation and synchronous
|
|
574
|
+
* dispatch exclude clear's commit, across instances and processes. */
|
|
507
575
|
async withRevisions(requests, dispatch) {
|
|
508
576
|
const unique = new Map();
|
|
509
577
|
for (const request of requests) {
|
|
@@ -515,40 +583,30 @@ export class SkillConfigs {
|
|
|
515
583
|
}
|
|
516
584
|
const ids = [...unique.keys()].sort();
|
|
517
585
|
const paths = new Map();
|
|
518
|
-
|
|
519
|
-
const
|
|
520
|
-
const
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
const
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
throw error;
|
|
541
|
-
}
|
|
542
|
-
})();
|
|
586
|
+
const environments = new Map();
|
|
587
|
+
for (const skillId of ids) {
|
|
588
|
+
const request = unique.get(skillId);
|
|
589
|
+
await this.reading(skillId, async (path) => {
|
|
590
|
+
paths.set(skillId, path);
|
|
591
|
+
const manifest = await this.manifest(path, false);
|
|
592
|
+
const snapshot = await this.snapshot(path, manifest, request.revision);
|
|
593
|
+
if (request.schema)
|
|
594
|
+
environments.set(skillId, this.snapshotEnvironment(request.schema, snapshot));
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
const dispatchChecked = async () => {
|
|
598
|
+
for (const skillId of ids) {
|
|
599
|
+
const request = unique.get(skillId);
|
|
600
|
+
await this.reading(skillId, async () => {
|
|
601
|
+
const manifest = await this.manifest(paths.get(skillId), false);
|
|
602
|
+
if (request.revision < manifest.minimumRevision || request.revision > manifest.revision)
|
|
603
|
+
unavailable();
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
// Keep command promises inside the envelope so the lock ends at dispatch.
|
|
607
|
+
return { value: dispatch(environments) };
|
|
543
608
|
};
|
|
544
|
-
|
|
545
|
-
return await acquire(0);
|
|
546
|
-
}
|
|
547
|
-
catch (error) {
|
|
548
|
-
if (dispatchFailed)
|
|
549
|
-
throw dispatchError;
|
|
550
|
-
throw error;
|
|
551
|
-
}
|
|
609
|
+
return ids.length ? this.withDispatchLock(dispatchChecked) : dispatchChecked();
|
|
552
610
|
}
|
|
553
611
|
}
|
|
554
612
|
//# sourceMappingURL=skill-configs.js.map
|
package/dist/skill-sessions.d.ts
CHANGED
|
@@ -11,8 +11,7 @@ export declare class SkillSessions {
|
|
|
11
11
|
freeze(prompt: string, raw: unknown, cwd: string): Promise<FrozenSkill[]>;
|
|
12
12
|
private references;
|
|
13
13
|
environment(skills: readonly FrozenSkill[], explicitOnly?: boolean): Promise<Record<string, string>>;
|
|
14
|
-
/**
|
|
15
|
-
* Automatic skills with missing required values remain available until used. */
|
|
14
|
+
/** Resolve only skills used at launch or by this activation. */
|
|
16
15
|
withEnvironment<T>(skills: readonly FrozenSkill[], skillId: string | null, dispatch: (environment: Record<string, string>, secrets: Record<string, string>) => T): Promise<{
|
|
17
16
|
value: T;
|
|
18
17
|
}>;
|
package/dist/skill-sessions.js
CHANGED
|
@@ -82,8 +82,7 @@ export class SkillSessions {
|
|
|
82
82
|
async environment(skills, explicitOnly = false) {
|
|
83
83
|
return (await this.withSelectedEnvironment(skills, skill => !explicitOnly || skill.explicit, environment => environment)).value;
|
|
84
84
|
}
|
|
85
|
-
/**
|
|
86
|
-
* Automatic skills with missing required values remain available until used. */
|
|
85
|
+
/** Resolve only skills used at launch or by this activation. */
|
|
87
86
|
async withEnvironment(skills, skillId, dispatch) {
|
|
88
87
|
if (skillId !== null) {
|
|
89
88
|
const skill = skills.find(item => item.skillId === skillId && item.source === 'openworkgraph');
|
|
@@ -98,15 +97,17 @@ export class SkillSessions {
|
|
|
98
97
|
const frozen = structuredClone(skills);
|
|
99
98
|
const requests = [];
|
|
100
99
|
for (const skill of frozen) {
|
|
100
|
+
if (!selected(skill))
|
|
101
|
+
continue;
|
|
101
102
|
if (skill.source === 'codex') {
|
|
102
|
-
if (
|
|
103
|
+
if (!isAbsolute(skill.path) || basename(skill.path) !== 'SKILL.md' || (await fs.stat(skill.path)).size > 128 * 1024)
|
|
103
104
|
throw new ServiceError('INPUT_BLOCKED', '冻结 Codex 技能路径不可用:' + skill.name);
|
|
104
105
|
continue;
|
|
105
106
|
}
|
|
106
107
|
const entry = await this.packages.packageEntry(skill.skillId, skill.packageVersion);
|
|
107
108
|
if (entry.path !== skill.path || skill.configRevision === undefined)
|
|
108
109
|
throw new ServiceError('INPUT_BLOCKED', '冻结技能版本不可用:' + skill.name);
|
|
109
|
-
requests.push({ skillId: skill.skillId, revision: skill.configRevision,
|
|
110
|
+
requests.push({ skillId: skill.skillId, revision: skill.configRevision, schema: entry.config });
|
|
110
111
|
}
|
|
111
112
|
return this.configs.withRevisions(requests, environments => {
|
|
112
113
|
const environment = {};
|
|
@@ -11,7 +11,7 @@ export class SkillsManagementApi {
|
|
|
11
11
|
async decorate(item) {
|
|
12
12
|
if (!item.installed)
|
|
13
13
|
return item;
|
|
14
|
-
const entry = await this.runtime.skills.
|
|
14
|
+
const entry = await this.runtime.skills.packageMetadata(item.skillId, item.packageVersion);
|
|
15
15
|
if (!entry.config.environment.length)
|
|
16
16
|
return { ...item, configuration: 'none' };
|
|
17
17
|
const config = await this.runtime.skillConfigs.read(item.skillId, entry.config);
|
|
@@ -65,7 +65,11 @@ export class SkillsManagementApi {
|
|
|
65
65
|
const query = (url.searchParams.get('query') ?? '').trim().toLocaleLowerCase();
|
|
66
66
|
if (query.length > 1024)
|
|
67
67
|
throw new ServiceError('INVALID_REQUEST', '技能搜索内容过长。');
|
|
68
|
-
|
|
68
|
+
// Installed browsing only reads the host's installation records and schemas.
|
|
69
|
+
// Remote source availability must never delay this view, including refresh.
|
|
70
|
+
const catalog = installed
|
|
71
|
+
? await this.runtime.skills.installedCatalog()
|
|
72
|
+
: await this.runtime.skills.catalog(url.searchParams.get('refresh') === '1');
|
|
69
73
|
const filtered = catalog.items.filter(item => (!installed || item.installed) && (item.name + ' ' + item.description).toLocaleLowerCase().includes(query));
|
|
70
74
|
// Unpaged calls remain compatible with welcome setup and skill suggestions.
|
|
71
75
|
const paged = !installed && (url.searchParams.has('offset') || url.searchParams.has('limit'));
|
|
@@ -104,7 +108,7 @@ export class SkillsManagementApi {
|
|
|
104
108
|
}
|
|
105
109
|
else {
|
|
106
110
|
if (request.method === 'GET') {
|
|
107
|
-
const entry = await this.runtime.skills.
|
|
111
|
+
const entry = await this.runtime.skills.packageMetadata(id);
|
|
108
112
|
result = { ...await this.runtime.skillConfigs.read(id, entry.config), packageVersion: entry.item.packageVersion };
|
|
109
113
|
}
|
|
110
114
|
else {
|
|
@@ -5,7 +5,7 @@ export * from './execution-chain.js';
|
|
|
5
5
|
export * from './graph-title.js';
|
|
6
6
|
export * from './graph-binary.js';
|
|
7
7
|
export declare const PROTOCOL_VERSION: '1.0';
|
|
8
|
-
export declare const SERVICE_VERSION: '0.3.
|
|
8
|
+
export declare const SERVICE_VERSION: '0.3.2';
|
|
9
9
|
/** Work Graph uploads use the UI's binary MB convention. */
|
|
10
10
|
export declare const WORKGRAPH_UPLOAD_MAX_BYTES: number;
|
|
11
11
|
export declare const WORKGRAPH_TRANSFER_TOTAL_BYTES: number;
|
|
@@ -5,7 +5,7 @@ export * from './execution-chain.js';
|
|
|
5
5
|
export * from './graph-title.js';
|
|
6
6
|
export * from './graph-binary.js';
|
|
7
7
|
export const PROTOCOL_VERSION = '1.0';
|
|
8
|
-
export const SERVICE_VERSION = '0.3.
|
|
8
|
+
export const SERVICE_VERSION = '0.3.2';
|
|
9
9
|
/** Work Graph uploads use the UI's binary MB convention. */
|
|
10
10
|
export const WORKGRAPH_UPLOAD_MAX_BYTES = 300 * 1024 * 1024;
|
|
11
11
|
export const WORKGRAPH_TRANSFER_TOTAL_BYTES = 1024 * 1024 * 1024;
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "openworkgraph", "version": "0.3.
|
|
3
|
-
"publishConfig": { "access": "public" },
|
|
4
|
-
"engines": { "node": ">=24.0.0" },
|
|
5
|
-
"bin": { "openworkgraph": "dist/cli.js" },
|
|
6
|
-
"files": ["dist/**/*.js", "dist/**/*.d.ts", "README.md"],
|
|
7
|
-
"scripts": { "prebuild": "node ../scripts/check-versions.mjs --quiet", "build": "tsc -p tsconfig.json && node scripts/vendor-protocol.mjs", "prepack": "node scripts/prepare-pack.mjs", "typecheck": "tsc -p tsconfig.json --noEmit", "start": "node dist/cli.js", "test": "node --test test/*.test.mjs" },
|
|
8
|
-
"dependencies": { "sharp": "^0.35.4", "yaml": "^2.9.1" }
|
|
9
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "openworkgraph", "version": "0.3.2", "type": "module",
|
|
3
|
+
"publishConfig": { "access": "public" },
|
|
4
|
+
"engines": { "node": ">=24.0.0" },
|
|
5
|
+
"bin": { "openworkgraph": "dist/cli.js" },
|
|
6
|
+
"files": ["dist/**/*.js", "dist/**/*.d.ts", "README.md"],
|
|
7
|
+
"scripts": { "prebuild": "node ../scripts/check-versions.mjs --quiet", "build": "tsc -p tsconfig.json && node scripts/vendor-protocol.mjs", "prepack": "node scripts/prepare-pack.mjs", "typecheck": "tsc -p tsconfig.json --noEmit", "start": "node dist/cli.js", "test": "node --test test/*.test.mjs" },
|
|
8
|
+
"dependencies": { "sharp": "^0.35.4", "yaml": "^2.9.1" }
|
|
9
|
+
}
|