@kisev/agentomatic 11.0.0-dev.54.g26e86b0b9fcd → 11.0.0-dev.55.g6d90f51aeff6
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 +3 -2
- package/README.ru.md +2 -1
- package/dist/agent-profiles.d.ts +2 -9
- package/dist/agent-profiles.js +6 -45
- package/dist/cli-output.d.ts +3 -3
- package/dist/cli-output.js +8 -37
- package/dist/cli.js +96 -75
- package/dist/config-setup.d.ts +2 -7
- package/dist/config-setup.js +5 -23
- package/dist/installer.d.ts +2 -7
- package/dist/installer.js +4 -25
- package/dist/lifecycle.d.ts +0 -21
- package/dist/lifecycle.js +1 -196
- package/dist/reconcile.d.ts +2 -7
- package/dist/reconcile.js +5 -30
- package/package.json +3 -3
package/dist/lifecycle.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
export declare const RECEIPT_TTL_MS: number;
|
|
2
1
|
export { LifecycleError, assertSafePath, readRegular, writeAtomic } from "@kisev/safe-fs";
|
|
3
2
|
export type Scope = "global" | "project";
|
|
4
3
|
export type FileExpectation = {
|
|
@@ -30,12 +29,6 @@ export type FileMutation = {
|
|
|
30
29
|
operation: "external-remove";
|
|
31
30
|
expected: FileExpectation;
|
|
32
31
|
};
|
|
33
|
-
export type SupersededPlan = {
|
|
34
|
-
kind: string;
|
|
35
|
-
confirmation_digest: string;
|
|
36
|
-
created_at: string;
|
|
37
|
-
expires_at: string;
|
|
38
|
-
};
|
|
39
32
|
export declare function stable(value: unknown): string;
|
|
40
33
|
export declare function sha256(value: Buffer | string): string;
|
|
41
34
|
export declare function digest(value: unknown): string;
|
|
@@ -47,20 +40,6 @@ export declare function migrateLegacyDeploymentNamespace(root: string): Promise<
|
|
|
47
40
|
export declare function migrateLegacyNamespaces(home?: string): Promise<string[]>;
|
|
48
41
|
export declare function archiveRoot(scope: Scope, cwd?: string, home?: string): string;
|
|
49
42
|
export declare function withLifecycleLock<T>(stateRoot: string, callback: () => Promise<T>): Promise<T>;
|
|
50
|
-
export declare function saveReceipt(stateRoot: string, kind: string, scope: Scope, root: string, payload: unknown, now?: number, planDigest?: string): Promise<{
|
|
51
|
-
digest: string;
|
|
52
|
-
plan_digest: string;
|
|
53
|
-
expires_at: string;
|
|
54
|
-
superseded_plan?: SupersededPlan;
|
|
55
|
-
}>;
|
|
56
|
-
export declare function consumeReceipt(stateRoot: string, expected: {
|
|
57
|
-
digest: string;
|
|
58
|
-
kind: string;
|
|
59
|
-
scope: Scope;
|
|
60
|
-
root: string;
|
|
61
|
-
}, now?: number): Promise<unknown>;
|
|
62
|
-
/** Invalidate an active receipt when a preview is blocked before a replacement exists. */
|
|
63
|
-
export declare function supersedeReceipt(stateRoot: string, now?: number): Promise<void>;
|
|
64
43
|
export declare function recoverTransaction(root: string, stateRoot: string, allowedRoots?: readonly string[]): Promise<boolean>;
|
|
65
44
|
export type TransactionOptions = {
|
|
66
45
|
beforePublish?: (index: number) => void;
|
package/dist/lifecycle.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { createHash
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
2
|
import { constants } from "node:fs";
|
|
3
3
|
import { lstat, mkdir, open, readFile, readdir, rename, rm, rmdir, stat, unlink, } from "node:fs/promises";
|
|
4
4
|
import { homedir } from "node:os";
|
|
5
5
|
import { dirname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
|
|
6
|
-
export const RECEIPT_TTL_MS = 10 * 60 * 1000;
|
|
7
6
|
export { LifecycleError, assertSafePath, readRegular, writeAtomic } from "@kisev/safe-fs";
|
|
8
7
|
import { LifecycleError, assertSafePath, ensureDirectory, lstatSafe, readRegular, writeAtomic, } from "@kisev/safe-fs";
|
|
9
8
|
export function stable(value) {
|
|
@@ -179,200 +178,6 @@ export async function withLifecycleLock(stateRoot, callback) {
|
|
|
179
178
|
}
|
|
180
179
|
throw new LifecycleError("lifecycle_locked", "Cannot acquire lifecycle lock");
|
|
181
180
|
}
|
|
182
|
-
function receiptPath(stateRoot) {
|
|
183
|
-
return join(stateRoot, "receipt.json");
|
|
184
|
-
}
|
|
185
|
-
export async function saveReceipt(stateRoot, kind, scope, root, payload, now = Date.now(), planDigest = digest(payload)) {
|
|
186
|
-
const existingRaw = await readRegular(receiptPath(stateRoot));
|
|
187
|
-
let superseded;
|
|
188
|
-
if (existingRaw) {
|
|
189
|
-
const existing = parseReceipt(existingRaw);
|
|
190
|
-
if (!existing.consumed && Date.parse(existing.expires_at) >= now) {
|
|
191
|
-
superseded = existing;
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
const confirmationDigest = sha256(randomBytes(32));
|
|
195
|
-
const receipt = {
|
|
196
|
-
schema_version: 1,
|
|
197
|
-
digest: confirmationDigest,
|
|
198
|
-
plan_digest: planDigest,
|
|
199
|
-
nonce: randomBytes(32).toString("base64url"),
|
|
200
|
-
created_at: new Date(now).toISOString(),
|
|
201
|
-
expires_at: new Date(now + RECEIPT_TTL_MS).toISOString(),
|
|
202
|
-
consumed: false,
|
|
203
|
-
kind,
|
|
204
|
-
scope,
|
|
205
|
-
root,
|
|
206
|
-
payload,
|
|
207
|
-
...(superseded
|
|
208
|
-
? {
|
|
209
|
-
superseded_digests: [superseded.digest, ...(superseded.superseded_digests ?? [])],
|
|
210
|
-
}
|
|
211
|
-
: {}),
|
|
212
|
-
integrity: "",
|
|
213
|
-
};
|
|
214
|
-
receipt.integrity = receiptIntegrity(receipt);
|
|
215
|
-
await writeAtomic(receiptPath(stateRoot), Buffer.from(`${stable(receipt)}\n`), 0o600);
|
|
216
|
-
return {
|
|
217
|
-
digest: receipt.digest,
|
|
218
|
-
plan_digest: receipt.plan_digest,
|
|
219
|
-
expires_at: receipt.expires_at,
|
|
220
|
-
...(superseded
|
|
221
|
-
? {
|
|
222
|
-
superseded_plan: {
|
|
223
|
-
kind: superseded.kind,
|
|
224
|
-
confirmation_digest: superseded.digest.slice(0, 12),
|
|
225
|
-
created_at: superseded.created_at,
|
|
226
|
-
expires_at: superseded.expires_at,
|
|
227
|
-
},
|
|
228
|
-
}
|
|
229
|
-
: {}),
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
function parseReceipt(raw) {
|
|
233
|
-
let value;
|
|
234
|
-
try {
|
|
235
|
-
value = JSON.parse(raw.toString("utf8"));
|
|
236
|
-
}
|
|
237
|
-
catch {
|
|
238
|
-
throw new LifecycleError("invalid_receipt", "Receipt is not valid JSON");
|
|
239
|
-
}
|
|
240
|
-
const receipt = value;
|
|
241
|
-
if (receipt &&
|
|
242
|
-
receipt.schema_version === 1 &&
|
|
243
|
-
typeof receipt.digest === "string" &&
|
|
244
|
-
/^[a-f0-9]{64}$/.test(receipt.digest) &&
|
|
245
|
-
typeof receipt.nonce === "string" &&
|
|
246
|
-
typeof receipt.expires_at === "string" &&
|
|
247
|
-
typeof receipt.consumed === "boolean" &&
|
|
248
|
-
typeof receipt.kind === "string" &&
|
|
249
|
-
(receipt.scope === "global" || receipt.scope === "project") &&
|
|
250
|
-
typeof receipt.root === "string" &&
|
|
251
|
-
typeof receipt.integrity === "string" &&
|
|
252
|
-
receipt.plan_digest === undefined) {
|
|
253
|
-
const legacyDocument = {
|
|
254
|
-
schema_version: 1,
|
|
255
|
-
digest: receipt.digest,
|
|
256
|
-
nonce: receipt.nonce,
|
|
257
|
-
expires_at: receipt.expires_at,
|
|
258
|
-
consumed: receipt.consumed,
|
|
259
|
-
kind: receipt.kind,
|
|
260
|
-
scope: receipt.scope,
|
|
261
|
-
root: receipt.root,
|
|
262
|
-
payload: receipt.payload,
|
|
263
|
-
integrity: receipt.integrity,
|
|
264
|
-
};
|
|
265
|
-
if (receipt.digest !==
|
|
266
|
-
digest({
|
|
267
|
-
schema_version: 1,
|
|
268
|
-
kind: receipt.kind,
|
|
269
|
-
scope: receipt.scope,
|
|
270
|
-
root: receipt.root,
|
|
271
|
-
payload: receipt.payload,
|
|
272
|
-
}) ||
|
|
273
|
-
receipt.integrity !==
|
|
274
|
-
digest({
|
|
275
|
-
schema_version: 1,
|
|
276
|
-
digest: receipt.digest,
|
|
277
|
-
nonce: receipt.nonce,
|
|
278
|
-
expires_at: receipt.expires_at,
|
|
279
|
-
consumed: receipt.consumed,
|
|
280
|
-
kind: receipt.kind,
|
|
281
|
-
scope: receipt.scope,
|
|
282
|
-
root: receipt.root,
|
|
283
|
-
payload: receipt.payload,
|
|
284
|
-
})) {
|
|
285
|
-
throw new LifecycleError("invalid_receipt", "Receipt integrity check failed");
|
|
286
|
-
}
|
|
287
|
-
const payloadRecord = receipt.payload;
|
|
288
|
-
const planDigest = payloadRecord &&
|
|
289
|
-
typeof payloadRecord === "object" &&
|
|
290
|
-
typeof payloadRecord.digest === "string" &&
|
|
291
|
-
/^[a-f0-9]{64}$/.test(payloadRecord.digest)
|
|
292
|
-
? payloadRecord.digest
|
|
293
|
-
: digest(receipt.payload);
|
|
294
|
-
return {
|
|
295
|
-
...legacyDocument,
|
|
296
|
-
plan_digest: planDigest,
|
|
297
|
-
created_at: new Date(Date.parse(receipt.expires_at) - RECEIPT_TTL_MS).toISOString(),
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
if (!receipt ||
|
|
301
|
-
receipt.schema_version !== 1 ||
|
|
302
|
-
typeof receipt.digest !== "string" ||
|
|
303
|
-
!/^[a-f0-9]{64}$/.test(receipt.digest) ||
|
|
304
|
-
typeof receipt.plan_digest !== "string" ||
|
|
305
|
-
!/^[a-f0-9]{64}$/.test(receipt.plan_digest) ||
|
|
306
|
-
typeof receipt.nonce !== "string" ||
|
|
307
|
-
typeof receipt.created_at !== "string" ||
|
|
308
|
-
typeof receipt.expires_at !== "string" ||
|
|
309
|
-
typeof receipt.consumed !== "boolean" ||
|
|
310
|
-
(receipt.superseded !== undefined && typeof receipt.superseded !== "boolean") ||
|
|
311
|
-
typeof receipt.kind !== "string" ||
|
|
312
|
-
(receipt.scope !== "global" && receipt.scope !== "project") ||
|
|
313
|
-
typeof receipt.root !== "string" ||
|
|
314
|
-
(receipt.superseded_digests !== undefined &&
|
|
315
|
-
(!Array.isArray(receipt.superseded_digests) ||
|
|
316
|
-
!receipt.superseded_digests.every((value) => typeof value === "string" && /^[a-f0-9]{64}$/.test(value)))) ||
|
|
317
|
-
typeof receipt.integrity !== "string") {
|
|
318
|
-
throw new LifecycleError("invalid_receipt", "Receipt has an unsupported schema");
|
|
319
|
-
}
|
|
320
|
-
const payloadRecord = receipt.payload;
|
|
321
|
-
const payloadPlanDigest = payloadRecord &&
|
|
322
|
-
typeof payloadRecord === "object" &&
|
|
323
|
-
typeof payloadRecord.plan_digest === "string"
|
|
324
|
-
? payloadRecord.plan_digest
|
|
325
|
-
: digest(receipt.payload);
|
|
326
|
-
if (receipt.plan_digest !== payloadPlanDigest) {
|
|
327
|
-
throw new LifecycleError("invalid_receipt", "Receipt digest does not match its payload");
|
|
328
|
-
}
|
|
329
|
-
if (receipt.integrity !== receiptIntegrity(receipt))
|
|
330
|
-
throw new LifecycleError("invalid_receipt", "Receipt integrity check failed");
|
|
331
|
-
return receipt;
|
|
332
|
-
}
|
|
333
|
-
function receiptIntegrity(receipt) {
|
|
334
|
-
const { integrity: _integrity, ...document } = receipt;
|
|
335
|
-
return digest(document);
|
|
336
|
-
}
|
|
337
|
-
export async function consumeReceipt(stateRoot, expected, now = Date.now()) {
|
|
338
|
-
if (!/^[a-f0-9]{64}$/.test(expected.digest))
|
|
339
|
-
throw new LifecycleError("invalid_digest", "Confirmation digest must be a SHA-256 value");
|
|
340
|
-
const raw = await readRegular(receiptPath(stateRoot));
|
|
341
|
-
if (!raw)
|
|
342
|
-
throw new LifecycleError("confirmation_unknown", "Confirmation receipt is missing");
|
|
343
|
-
const receipt = parseReceipt(raw);
|
|
344
|
-
if (receipt.digest !== expected.digest ||
|
|
345
|
-
receipt.kind !== expected.kind ||
|
|
346
|
-
receipt.scope !== expected.scope ||
|
|
347
|
-
receipt.root !== expected.root) {
|
|
348
|
-
if (receipt.superseded_digests?.includes(expected.digest))
|
|
349
|
-
throw new LifecycleError("superseded_plan", "Confirmation receipt was superseded by a newer plan");
|
|
350
|
-
throw new LifecycleError("confirmation_unknown", "Confirmation does not match the saved plan");
|
|
351
|
-
}
|
|
352
|
-
if (receipt.superseded)
|
|
353
|
-
throw new LifecycleError("superseded_plan", "Confirmation receipt was superseded by a newer plan");
|
|
354
|
-
if (receipt.consumed)
|
|
355
|
-
throw new LifecycleError("confirmation_consumed", "Confirmation receipt was already consumed");
|
|
356
|
-
if (Date.parse(receipt.expires_at) < now)
|
|
357
|
-
throw new LifecycleError("confirmation_expired", "Confirmation receipt expired; request a fresh plan");
|
|
358
|
-
const consumed = { ...receipt, consumed: true, integrity: "" };
|
|
359
|
-
consumed.integrity = receiptIntegrity(consumed);
|
|
360
|
-
await writeAtomic(receiptPath(stateRoot), Buffer.from(`${stable(consumed)}\n`), 0o600);
|
|
361
|
-
return receipt.payload;
|
|
362
|
-
}
|
|
363
|
-
/** Invalidate an active receipt when a preview is blocked before a replacement exists. */
|
|
364
|
-
export async function supersedeReceipt(stateRoot, now = Date.now()) {
|
|
365
|
-
const path = receiptPath(stateRoot);
|
|
366
|
-
const raw = await readRegular(path);
|
|
367
|
-
if (!raw)
|
|
368
|
-
return;
|
|
369
|
-
const receipt = parseReceipt(raw);
|
|
370
|
-
if (receipt.consumed || receipt.superseded || Date.parse(receipt.expires_at) < now)
|
|
371
|
-
return;
|
|
372
|
-
const superseded = { ...receipt, consumed: true, superseded: true, integrity: "" };
|
|
373
|
-
superseded.integrity = receiptIntegrity(superseded);
|
|
374
|
-
await writeAtomic(path, Buffer.from(`${stable(superseded)}\n`), 0o600);
|
|
375
|
-
}
|
|
376
181
|
function journalPath(stateRoot) {
|
|
377
182
|
return join(stateRoot, "transaction-journal.json");
|
|
378
183
|
}
|
package/dist/reconcile.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LifecycleError, type
|
|
1
|
+
import { LifecycleError, type Scope, type TransactionOptions } from "./lifecycle.js";
|
|
2
2
|
export type ReconcileStatus = "current" | "retired" | "renamed" | "modified-managed" | "user-owned" | "unknown" | "conflict" | "diagnostic-state-only";
|
|
3
3
|
export type ReconcileItem = {
|
|
4
4
|
path: string;
|
|
@@ -26,12 +26,7 @@ export type ReconcilePlan = {
|
|
|
26
26
|
operation: "archive" | "remove" | "write";
|
|
27
27
|
sha256?: string;
|
|
28
28
|
}>;
|
|
29
|
-
plan_digest: string;
|
|
30
|
-
confirmation_digest?: string;
|
|
31
|
-
superseded_plan?: SupersededPlan;
|
|
32
29
|
confirmable: boolean;
|
|
33
|
-
digest?: string;
|
|
34
|
-
receipt_expires_at?: string;
|
|
35
30
|
};
|
|
36
31
|
export type ReconcileResult = {
|
|
37
32
|
status: "ok";
|
|
@@ -44,4 +39,4 @@ export declare class ReconcileError extends LifecycleError {
|
|
|
44
39
|
export declare function previewReconcile(scope: Scope, cwd?: string, home?: string): Promise<ReconcilePlan>;
|
|
45
40
|
/** Build the ownership classification without receipts, locks, or recovery. */
|
|
46
41
|
export declare function inspectReconcile(scope: Scope, cwd?: string, home?: string): Promise<ReconcilePlan>;
|
|
47
|
-
export declare function applyReconcile(scope: Scope,
|
|
42
|
+
export declare function applyReconcile(scope: Scope, cwd?: string, home?: string, options?: ReconcileOptions): Promise<ReconcileResult>;
|
package/dist/reconcile.js
CHANGED
|
@@ -3,7 +3,7 @@ import { lstat, readdir, readFile } from "node:fs/promises";
|
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { applyTransaction, archiveRoot, assertSafePath,
|
|
6
|
+
import { applyTransaction, archiveRoot, assertSafePath, destination, LifecycleError, lifecycleRoot, recoverTransaction, sha256, stable, withLifecycleLock, } from "./lifecycle.js";
|
|
7
7
|
import { archiveMutations } from "./installer.js";
|
|
8
8
|
const PACKAGE_NAME = "@kisev/agentomatic";
|
|
9
9
|
const GENERIC_MANIFEST = ".agentomatic-manifest.json";
|
|
@@ -394,12 +394,11 @@ async function build(scope, cwd = process.cwd(), home = homedir()) {
|
|
|
394
394
|
diagnostic_state_only: await diagnostic(home),
|
|
395
395
|
operations: operations.sort((left, right) => left.path.localeCompare(right.path)),
|
|
396
396
|
};
|
|
397
|
-
const planDigest = digest(base);
|
|
398
397
|
const confirmable = operations.length > 0 &&
|
|
399
398
|
groups["modified-managed"].length === 0 &&
|
|
400
399
|
groups.conflict.length === 0;
|
|
401
400
|
return {
|
|
402
|
-
plan: { ...base,
|
|
401
|
+
plan: { ...base, confirmable },
|
|
403
402
|
mutations,
|
|
404
403
|
};
|
|
405
404
|
}
|
|
@@ -413,23 +412,7 @@ export async function previewReconcile(scope, cwd = process.cwd(), home = homedi
|
|
|
413
412
|
const built = await build(scope, cwd, home);
|
|
414
413
|
const blocked = built.plan.modified_managed.length > 0 || built.plan.conflicts.length > 0;
|
|
415
414
|
const actionable = built.plan.operations.length > 0;
|
|
416
|
-
|
|
417
|
-
await supersedeReceipt(stateRoot);
|
|
418
|
-
const { digest: _digest, ...withoutReceipt } = built.plan;
|
|
419
|
-
return { ...withoutReceipt, confirmable: false };
|
|
420
|
-
}
|
|
421
|
-
const receipt = await saveReceipt(stateRoot, "reconcile", scope, root, {
|
|
422
|
-
plan_digest: built.plan.plan_digest,
|
|
423
|
-
}, Date.now(), built.plan.plan_digest);
|
|
424
|
-
return {
|
|
425
|
-
...built.plan,
|
|
426
|
-
plan_digest: built.plan.plan_digest,
|
|
427
|
-
confirmation_digest: receipt.digest,
|
|
428
|
-
digest: receipt.digest,
|
|
429
|
-
confirmable: true,
|
|
430
|
-
receipt_expires_at: receipt.expires_at,
|
|
431
|
-
...(receipt.superseded_plan ? { superseded_plan: receipt.superseded_plan } : {}),
|
|
432
|
-
};
|
|
415
|
+
return { ...built.plan, confirmable: !blocked && actionable };
|
|
433
416
|
});
|
|
434
417
|
}
|
|
435
418
|
catch (error) {
|
|
@@ -444,22 +427,14 @@ export async function previewReconcile(scope, cwd = process.cwd(), home = homedi
|
|
|
444
427
|
export async function inspectReconcile(scope, cwd = process.cwd(), home = homedir()) {
|
|
445
428
|
return (await build(scope, cwd, home)).plan;
|
|
446
429
|
}
|
|
447
|
-
export async function applyReconcile(scope,
|
|
430
|
+
export async function applyReconcile(scope, cwd = process.cwd(), home = homedir(), options = {}) {
|
|
448
431
|
const stateRoot = lifecycleRoot(scope, cwd, home);
|
|
449
432
|
const root = scopeRoot(scope, cwd, home);
|
|
450
433
|
try {
|
|
451
434
|
return await withLifecycleLock(stateRoot, async () => {
|
|
452
435
|
if (await recoverTransaction(root, stateRoot, reconcileAllowedRoots(scope, cwd, home)))
|
|
453
436
|
throw new ReconcileError("recovered_transaction", "Recovered an interrupted transaction; request a fresh plan");
|
|
454
|
-
const payload = (await consumeReceipt(stateRoot, {
|
|
455
|
-
digest: confirmationDigest,
|
|
456
|
-
kind: "reconcile",
|
|
457
|
-
scope,
|
|
458
|
-
root,
|
|
459
|
-
}));
|
|
460
437
|
const built = await build(scope, cwd, home);
|
|
461
|
-
if (built.plan.plan_digest !== (payload.plan_digest ?? payload.digest))
|
|
462
|
-
throw new ReconcileError("stale_plan", "Reconcile inventory changed after preview");
|
|
463
438
|
if (built.plan.conflicts.length || built.plan.modified_managed.length)
|
|
464
439
|
throw new ReconcileError("conflict", "Reconcile contains unsafe ownership conflicts");
|
|
465
440
|
await applyTransaction(root, stateRoot, built.mutations, {
|
|
@@ -476,7 +451,7 @@ export async function applyReconcile(scope, confirmationDigest, cwd = process.cw
|
|
|
476
451
|
return {
|
|
477
452
|
status: "ok",
|
|
478
453
|
applied: true,
|
|
479
|
-
plan:
|
|
454
|
+
plan: built.plan,
|
|
480
455
|
};
|
|
481
456
|
});
|
|
482
457
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kisev/agentomatic",
|
|
3
|
-
"version": "11.0.0-dev.
|
|
3
|
+
"version": "11.0.0-dev.55.g6d90f51aeff6",
|
|
4
4
|
"description": "OpenCode integration and opt-in installer for portable Agent Skills.",
|
|
5
5
|
"homepage": "https://github.com/kisev/skills#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -49,8 +49,8 @@
|
|
|
49
49
|
"pack:check": "node test/pack-allowlist.mjs"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@kisev/memomatic": "1.0.0-dev.
|
|
53
|
-
"@kisev/safe-fs": "1.0.0-dev.
|
|
52
|
+
"@kisev/memomatic": "1.0.0-dev.55.g6d90f51aeff6",
|
|
53
|
+
"@kisev/safe-fs": "1.0.0-dev.55.g6d90f51aeff6"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@opencode-ai/plugin": "1.18.29",
|