@ai-ecoverse/slicc-agent 6.17.2 → 6.18.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 +18 -0
- package/dist/control.js +1 -1
- package/dist/control.js.map +2 -2
- package/dist/freezer/index.js +6 -2
- package/dist/freezer/index.js.map +2 -2
- package/dist/freezer/v6-place.js +15 -2
- package/dist/freezer/v6-place.js.map +2 -2
- package/dist/freezer/v6-schema.js +43 -3
- package/dist/freezer/v6-schema.js.map +2 -2
- package/dist/freezer/v6-write.js +68 -0
- package/dist/freezer/v6-write.js.map +2 -2
- package/dist/freezer/v6.js +121 -19
- package/dist/freezer/v6.js.map +2 -2
- package/dist/services.js.map +2 -2
- package/dist/types/freezer/index.d.ts +1 -1
- package/dist/types/freezer/v6-place.d.ts +1 -0
- package/dist/types/freezer/v6-schema.d.ts +5 -1
- package/dist/types/freezer/v6-write.d.ts +3 -0
- package/dist/types/freezer/v6.d.ts +7 -3
- package/dist/types/services.d.ts +1 -0
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/freezer/v6-place.ts"],
|
|
4
|
-
"sourcesContent": ["import { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport { coneSpec } from '../kernel/accounts.ts';\nimport { ROOT_HOME } from '../layout.ts';\nimport type { LickTarget } from '../licks/lick.ts';\nimport { memoryRoot } from '../memory/store.ts';\nimport { GLOBAL_DIR } from '../skills/index.ts';\nimport { validateName } from '../skills/skills.ts';\nimport type { ImportDeps } from './v6.ts';\nimport {\n accountsSplit,\n type Opened,\n type Parsed,\n textOf,\n type Unit,\n type Where,\n whereOf,\n} from './v6.ts';\nimport { lickName, skillName } from './v6-schema.ts';\nimport {\n type CronLine,\n installCrons,\n ownTree,\n remember,\n same,\n userSection,\n type Writer,\n} from './v6-write.ts';\nimport { ImportError } from './zip.ts';\n\nexport const V6_ROOT = `${ROOT_HOME}/v6`;\n\nexport type Notes = {\n lines: string[];\n skipped: string[];\n shadowed: string[];\n tasks: string[];\n sprinkles: Map<string, Set<string>>;\n crons: string[];\n webhooks: string[];\n placed: Map<string, string>;\n};\n\nexport type Run = {\n deps: ImportDeps;\n opened: Opened;\n parsed: Parsed;\n writer: Writer;\n stage: string;\n date: string;\n notes: Notes;\n show: (phase: 'writing', done: number, total: number) => void;\n fresh: Map<string, boolean>;\n ready: Set<Unit>;\n};\n\ntype Source = Uint8Array | { zip: string };\n\nasync function staged(run: Run, zip: string): Promise<Uint8Array> {\n const read = await run.writer.env.readBinaryFile(`${run.stage}/${zip}`, run.writer.context);\n if (!read.ok) throw new ImportError(`the staged copy of ${zip} is gone`);\n return read.value;\n}\n\nasync function prepare(run: Run, unit: Unit): Promise<void> {\n if (run.ready.has(unit)) return;\n run.ready.add(unit);\n const { users, layout, env } = run.deps;\n if (unit.fresh)\n run.writer.later(async () => {\n await users?.remove(unit.cone).catch(() => false);\n await env.remove(unit.home, { recursive: true, force: true }, BACKGROUND_CONTEXT);\n });\n if (layout.users && users) await users.add(coneSpec(unit.cone));\n}\n\nasync function envOf(run: Run, unit: Unit | null): Promise<ExecutionEnv | undefined> {\n if (!unit || unit.fresh || !run.deps.layout.users) return undefined;\n const env = await run.deps.envOf?.(unit.cone);\n if (!env) throw new ImportError(`there is no kernel user ${unit.cone} to write its files as`);\n return env;\n}\n\nasync function putIn(run: Run, unit: Unit | null, root: string, rest: string, source: Source) {\n if (unit) await prepare(run, unit);\n const env = await envOf(run, unit);\n let fresh = run.fresh.get(root);\n if (fresh === undefined) {\n fresh = unit?.fresh || (await run.writer.tree(root, env));\n run.fresh.set(root, fresh);\n }\n if (unit?.fresh) unit.roots.add(root);\n const path = `${root}/${rest}`;\n await run.writer.put(path, 'zip' in source ? await staged(run, source.zip) : source, fresh, env);\n if ('zip' in source && !run.notes.placed.has(source.zip)) run.notes.placed.set(source.zip, path);\n}\n\nconst clean = (name: string) => name.replace(/[^A-Za-z0-9._-]+/g, '_').slice(-80) || 'file';\n\ntype Maps = { byFolder: Map<string, Unit>; owners: Map<string, Unit>; primary?: Unit };\n\nfunction targets(run: Run, maps: Maps, where: Where, zip: string): [Unit, string, string][] {\n if (where.kind === 'cone' || where.kind === 'scoop') {\n const unit = (where.kind === 'cone' ? maps.byFolder : maps.owners).get(where.folder) as Unit;\n const root =\n where.kind === 'cone'\n ? `${unit.home}/workspace${unit.suffix}`\n : `${unit.home}/scoops${unit.suffix}/${where.folder}`;\n return [[unit, root, where.rest]];\n }\n if (where.kind === 'sprinkle') {\n if (!maps.primary)\n run.notes.skipped.push(`the sprinkle ${where.folder}: there is no cone to put it in`);\n return maps.primary\n ? [\n [\n maps.primary,\n `${maps.primary.home}/sprinkles/${lickName(where.folder, 'sprinkle')}`,\n where.rest,\n ],\n ]\n : [];\n }\n if (where.kind !== 'attachment') return [];\n return run.parsed.units.flatMap((unit) =>\n (unit.doc?.attachments ?? [])\n .filter((item) => item.present && item.path === zip)\n .map((item): [Unit, string, string] => {\n const rest = `${item.sha256.slice(0, 12)}-${clean(item.originalName)}`;\n unit.files.set(item.id, `${unit.home}/v6-attachments/${rest}`);\n return [unit, `${unit.home}/v6-attachments`, rest];\n })\n );\n}\n\nfunction sprinkleCalls(run: Run, name: string, bytes: Uint8Array) {\n const found = [...new TextDecoder().decode(bytes).matchAll(/\\bslicc\\.([A-Za-z_$][\\w$]*)/g)]\n .map((match) => `slicc.${match[1]}`)\n .filter((call) => call !== 'slicc.lick');\n if (!found.length) return;\n const known = run.notes.sprinkles.get(name) ?? new Set<string>();\n for (const call of found) known.add(call);\n run.notes.sprinkles.set(name, known);\n}\n\nasync function alike(\n run: Run,\n dir: string,\n six: string,\n rests: readonly string[]\n): Promise<boolean> {\n for (const rest of rests) {\n const old = await run.writer.env.readBinaryFile(`${dir}/${rest}`, run.writer.context);\n if (!old.ok || !same(old.value, await staged(run, `skills/${six}/${rest}`))) return false;\n }\n return true;\n}\n\nasync function placeSkills(run: Run, skills: Map<string, string[]>, primary: Unit | undefined) {\n const seen = new Set<string>();\n for (const [six, rests] of skills) {\n const name = skillName(six);\n if (!name || validateName(name).length || seen.has(name)) {\n run.notes.skipped.push(\n `the skill ${six}: its name doesn't fit seven's rule (a-z, 0-9 and -)`\n );\n continue;\n }\n seen.add(name);\n const global = `${GLOBAL_DIR}/${name}`;\n const exists = await run.writer.exists(global);\n if (exists && (await alike(run, global, six, rests))) {\n run.notes.lines.push(`the skill ${name}: already in ${GLOBAL_DIR}`);\n continue;\n }\n const own = primary && exists ? `${primary.home}/.pi/agent/skills/${name}` : undefined;\n if (exists && !own) {\n run.notes.skipped.push(`the skill ${name}: ${GLOBAL_DIR} has another skill of that name`);\n continue;\n }\n for (const rest of rests)\n await putIn(run, own ? (primary as Unit) : null, own ?? global, rest, {\n zip: `skills/${six}/${rest}`,\n });\n if (own)\n run.notes.shadowed.push(\n `the skill ${name}: ${GLOBAL_DIR} has another skill of that name, so SLICC 6's copy is in ${own}, for ${(primary as Unit).cone} only`\n );\n else run.notes.lines.push(`the skill ${name}, for every agent, in ${global}`);\n }\n}\n\nasync function placeMemory(run: Run) {\n const root = memoryRoot(run.deps.memoryHome);\n const { data, units } = run.parsed;\n const places = [\n { name: 'memory/global.md', file: `${root}/MEMORY.md`, rest: `${V6_ROOT}/memory/global.md` },\n ...units\n .filter((unit) => unit.memory)\n .map((unit) => ({\n name: unit.memory as string,\n file: `${root}/${unit.cone}/MEMORY.md`,\n rest: `${V6_ROOT}/memory/${unit.cone}.md`,\n })),\n ];\n for (const place of places) {\n const bytes = data.get(place.name);\n const done = bytes\n ? await remember(run.writer, place.file, textOf(bytes, place.name), {\n file: place.rest,\n date: run.date,\n })\n : 'none';\n if (done === 'merged')\n run.notes.lines.push(`memory, under \"Imported from SLICC 6 (${run.date})\", in ${place.file}`);\n if (done === 'aside')\n run.notes.lines.push(`memory, in ${place.rest}: ${place.file} has no room left for it`);\n }\n}\n\nfunction earlier(run: Run, unit: Unit, name: string): LickTarget | undefined {\n const found = Object.entries(run.deps.agents.state().scoops).filter(\n ([, record]) => record.cone === unit.cone && record.name === name && !record.removed\n );\n return found.at(-1)?.[0] as LickTarget | undefined;\n}\n\nfunction router(run: Run, maps: Maps) {\n return (folder: string | null | undefined): [Unit, LickTarget] | undefined => {\n const cone = folder ? maps.byFolder.get(folder) : undefined;\n if (cone) return [cone, 'cone'];\n const owner = folder ? maps.owners.get(folder) : undefined;\n const scoop = owner?.scoops.find((item) => item.six === folder);\n const target =\n owner && scoop\n ? owner.record\n ? (`scoop:${scoop.folder}` as LickTarget)\n : earlier(run, owner, scoop.name)\n : undefined;\n if (owner && target) return [owner, target];\n const unit = owner ?? maps.primary;\n return unit ? [unit, 'cone'] : undefined;\n };\n}\n\nconst FIELD = '[0-9A-Za-z*,/-]+';\nconst SCHEDULE = new RegExp(\n `^(@(yearly|annually|monthly|weekly|daily|midnight|hourly|reboot)|${FIELD}( ${FIELD}){4})$`\n);\n\nconst flat = (text: string) => text.replace(/\\s+/g, ' ').trim();\n\nasync function placeLicks(run: Run, maps: Maps) {\n const { licks } = run.parsed;\n const route = router(run, maps);\n const crons = new Map<Unit, CronLine[]>();\n const add = (found: [Unit, LickTarget] | undefined, line: Omit<CronLine, 'target'>) => {\n const why = !SCHEDULE.test(line.schedule)\n ? `\"${line.schedule}\" is not a cron schedule`\n : !found && 'there is no cone to send it to';\n if (why) run.notes.skipped.push(`the cron ${line.name}: ${why}`);\n else if (found)\n crons.set(found[0], [...(crons.get(found[0]) ?? []), { ...line, target: found[1] }]);\n };\n for (const [at, task] of licks.crontasks.entries())\n add(route(task.targetFolder), {\n name: lickName(task.name, `v6-cron-${at + 1}`),\n schedule: flat(task.cron),\n message: '',\n ...(task.filter ? { filter: task.filter } : {}),\n });\n for (const [at, task] of licks.tasks.entries()) {\n if (task.scheduleType === 'cron')\n add(route(task.groupFolder), {\n name: `v6-task-${at + 1}`,\n schedule: flat(task.scheduleValue),\n message: flat(task.prompt),\n });\n else\n run.notes.tasks.push(\n `${task.scheduleType} ${task.scheduleValue}: ${flat(task.prompt).slice(0, 80)}`\n );\n }\n for (const [unit, list] of crons) {\n await prepare(run, unit);\n const user = run.deps.layout.users ? unit.cone : 'root';\n const count = await installCrons(run.writer, user, list, run.date);\n if (count) run.notes.crons.push(`${count} in crontab -u ${user}`);\n }\n for (const [at, hook] of licks.webhooks.entries()) {\n const found = route(hook.targetFolder);\n const name = lickName(hook.name, `v6-webhook-${at + 1}`);\n if (!found) run.notes.skipped.push(`the webhook ${name}: there is no cone to send it to`);\n if (!found) continue;\n const root = `${found[0].home}/.slicc/webhooks`;\n await putIn(\n run,\n found[0],\n root,\n `${name}.json.v6`,\n new TextEncoder().encode(`${JSON.stringify({ target: found[1] }, null, 2)}\\n`)\n );\n run.notes.webhooks.push(`${root}/${name}.json.v6`);\n }\n}\n\nasync function placeGit(run: Run) {\n const name = run.opened.manifest.gitconfig;\n const bytes = name ? run.parsed.data.get(name) : undefined;\n const section = bytes ? userSection(textOf(bytes, name as string)) : '';\n if (!section) return;\n const file = `${ROOT_HOME}/.gitconfig`;\n const read = await run.writer.env.readTextFile(file, run.writer.context);\n const before = read.ok ? read.value.trimEnd() : '';\n if (/^\\s*\\[user\\]/im.test(before)) {\n run.notes.skipped.push(`SLICC 6's git [user]: ${file} already has one`);\n return;\n }\n await run.writer.put(file, `${before ? `${before}\\n` : ''}${section}`, false);\n run.notes.lines.push(`your git name and email, in ${file}`);\n}\n\nexport async function place(run: Run): Promise<void> {\n const { manifest } = run.opened;\n const units = run.parsed.units;\n const byFolder = new Map(\n units.filter((unit) => unit.six).map((unit) => [unit.six as string, unit])\n );\n const owners = new Map(\n units.flatMap((unit) =>\n unit.scoops.filter((scoop) => scoop.six).map((scoop) => [scoop.six as string, unit])\n )\n );\n const maps: Maps = {\n byFolder,\n owners,\n primary: byFolder.get('cone') ?? units.find((unit) => unit.six !== null),\n };\n const skills = new Map<string, string[]>();\n const later: [string, string][] = [];\n for (const [at, file] of manifest.files.entries()) {\n const where = whereOf(manifest, file.path);\n if (where.kind === 'skill')\n skills.set(where.folder, [...(skills.get(where.folder) ?? []), where.rest]);\n if (where.kind === 'home-user') later.push([file.path, where.rest]);\n if (where.kind === 'sprinkle') sprinkleCalls(run, where.folder, await staged(run, file.path));\n for (const [unit, root, rest] of targets(run, maps, where, file.path))\n await putIn(run, unit, root, rest, { zip: file.path });\n run.show('writing', at + 1, manifest.files.length);\n }\n await placeSkills(run, skills, maps.primary);\n await placeMemory(run);\n await placeLicks(run, maps);\n await placeGit(run);\n for (const [zip, rest] of later) await putIn(run, null, `${V6_ROOT}/home-user`, rest, { zip });\n if (run.deps.layout.users)\n for (const unit of units) await ownTree(run.writer, unit.cone, unit.home, unit.roots);\n}\n\nconst WHY: Record<string, string> = {\n env: 'environment file, often holds keys',\n pem: 'PEM file, may be a private key',\n 'git-credentials': 'git credentials in plain text',\n npmrc: 'npm config, may hold an auth token',\n 'slicc-oauth': 'SLICC 6 OAuth state',\n};\n\nconst NEVER: Record<string, string> = {\n 'secrets-env': '~/.slicc/secrets.env, which stays on the host',\n 'github-token': 'the GitHub token',\n 'mcp-tokens': 'MCP tokens',\n 'chrome-storage': \"the extension's chrome.storage secrets\",\n};\n\nconst bullets = (items: readonly string[], none: string) =>\n (items.length ? items : [none]).map((item) => `- ${item}`);\n\nfunction nextSteps(run: Run, mounts: readonly string[]): string[] {\n const { manifest } = run.opened;\n const { notes } = run;\n const sprinkles = [...notes.sprinkles].map(\n ([name, calls]) => `${name} (${[...calls].join(', ')})`\n );\n return [\n 'Re-enter your keys and logins in Settings.',\n ...(mounts.length ? [`Mount these folders again: ${mounts.join(', ')}.`] : []),\n ...(manifest.mcp?.length\n ? [\n `Add these MCP servers again: ${manifest.mcp.map((item) => `${item.name} (${item.url})`).join(', ')}.`,\n ]\n : []),\n ...(notes.crons.length\n ? [\n `Turn crons on with sudo crontab -u <user> -e: remove the leading \"# \" from a job's two lines.`,\n ]\n : []),\n ...(notes.webhooks.length\n ? [\n \"Turn a webhook on by renaming <name>.json.v6 to <name>.json, then point its sender at seven's webhook URL.\",\n ]\n : []),\n ...(sprinkles.length\n ? [\n `These sprinkles call SLICC APIs other than slicc.lick and may need edits: ${sprinkles.join(', ')}.`,\n ]\n : []),\n ];\n}\n\nexport async function reportOf(run: Run, made: readonly string[]): Promise<string> {\n const { manifest } = run.opened;\n const { notes, date, parsed } = run;\n const recorded = parsed.units.filter((unit) => unit.record);\n const imported = [\n ...recorded.map(\n (unit, at) =>\n `${unit.title}: frozen cone ${made[at]}, home ${unit.home}${unit.suffix ? `, new files in ${unit.home}/workspace${unit.suffix}` : ''}${unit.scoops.length ? `, with ${unit.scoops.map((scoop) => scoop.name).join(', ')}` : ''}`\n ),\n ...notes.lines,\n ...notes.crons.map((line) => `crons, imported off: ${line}`),\n ...notes.webhooks.map((path) => `a webhook, imported off: ${path}`),\n ];\n const mounts = manifest.skipped\n .filter((item) => item.reason === 'mount')\n .map((item) => item.path);\n const skipped = [\n ...manifest.skipped.map((item) => `${item.path}: ${item.reason}`),\n ...parsed.units\n .filter((unit) => !unit.record)\n .map((unit) => `${unit.title}: unchanged since the last import`),\n ...notes.skipped,\n ...notes.shadowed,\n ...notes.tasks.map((task) => `a SLICC 6 task that cron can't express: ${task}`),\n ];\n const flagged = manifest.flagged.map(\n (item) => `| ${notes.placed.get(item.path) ?? item.path} | ${item.size} B | ${WHY[item.rule]} |`\n );\n const split = accountsSplit(manifest.providers, run.deps.providers);\n const providers = [\n ...split.again.map((id) => `${split.nameOf(id)}: re-enter in Settings`),\n ...split.missing.map((id) => `${split.nameOf(id)}: SLICC 7 has no such provider`),\n ];\n const never = (manifest.secrets ?? []).map((name) => NEVER[name] ?? name);\n const part = manifest.part ? `, part ${manifest.part.index} of ${manifest.part.of}` : '';\n const text = [\n `# SLICC 6 import, ${date}`,\n '',\n `From ${manifest.producer.origin} (SLICC ${manifest.producer.slicc}), exported ${manifest.createdAt}, export ${manifest.exportId}${part}.`,\n '',\n '## Imported',\n '',\n ...bullets(imported, 'nothing new'),\n '',\n '## Skipped',\n '',\n ...bullets(skipped, 'nothing'),\n '',\n ...(flagged.length\n ? [\n '## Review these files',\n '',\n '| Path | Size | Why |',\n '| --- | --- | --- |',\n ...flagged,\n '',\n \"Delete or move these if you don't need them here.\",\n '',\n ]\n : []),\n '## Re-enter in Settings',\n '',\n ...bullets(providers, 'no providers'),\n ...(never.length ? ['', `These never move: ${never.join(', ')}.`] : []),\n '',\n '## Next steps',\n '',\n ...nextSteps(run, mounts).map((step) => `- ${step}`),\n '',\n ].join('\\n');\n let file = `${ROOT_HOME}/v6-import-${date}.md`;\n for (let n = 2; await run.writer.exists(file); n++)\n file = `${ROOT_HOME}/v6-import-${date}-${n}.md`;\n const written = await run.writer.env.writeFile(file, text, BACKGROUND_CONTEXT);\n if (!written.ok)\n throw new ImportError(`couldn't write the report ${file}: ${written.error.message}`);\n return file;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ExecutionEnv } from '@earendil-works/pi-durable/env';\nimport { coneSpec } from '../kernel/accounts.ts';\nimport { ROOT_HOME } from '../layout.ts';\nimport type { LickTarget } from '../licks/lick.ts';\nimport { memoryRoot } from '../memory/store.ts';\nimport { GLOBAL_DIR } from '../skills/index.ts';\nimport { validateName } from '../skills/skills.ts';\nimport type { ImportDeps } from './v6.ts';\nimport {\n accountsSplit,\n type Opened,\n type Parsed,\n textOf,\n type Unit,\n type Where,\n whereOf,\n} from './v6.ts';\nimport { lickName, skillName } from './v6-schema.ts';\nimport {\n type CronLine,\n installCrons,\n ownTree,\n remember,\n same,\n userSection,\n type Writer,\n} from './v6-write.ts';\nimport { ImportError } from './zip.ts';\n\nexport const V6_ROOT = `${ROOT_HOME}/v6`;\n\nexport type Notes = {\n lines: string[];\n skipped: string[];\n shadowed: string[];\n tasks: string[];\n sprinkles: Map<string, Set<string>>;\n crons: string[];\n webhooks: string[];\n placed: Map<string, string>;\n};\n\nexport type Run = {\n deps: ImportDeps;\n opened: Opened;\n parsed: Parsed;\n writer: Writer;\n stage: string;\n date: string;\n notes: Notes;\n show: (phase: 'writing', done: number, total: number) => void;\n fresh: Map<string, boolean>;\n ready: Set<Unit>;\n at: Map<string, string>;\n};\n\ntype Source = Uint8Array | { zip: string };\n\nasync function staged(run: Run, zip: string): Promise<Uint8Array> {\n const read = await run.writer.env.readBinaryFile(\n run.at.get(zip) ?? `${run.stage}/${zip}`,\n run.writer.context\n );\n if (!read.ok) throw new ImportError(`the staged copy of ${zip} is gone`);\n return read.value;\n}\n\nasync function prepare(run: Run, unit: Unit): Promise<void> {\n if (run.ready.has(unit)) return;\n run.ready.add(unit);\n const { users, layout, env } = run.deps;\n if (unit.fresh)\n run.writer.later(async () => {\n await users?.remove(unit.cone).catch(() => false);\n await env.remove(unit.home, { recursive: true, force: true }, BACKGROUND_CONTEXT);\n });\n if (layout.users && users) await users.add(coneSpec(unit.cone));\n}\n\nasync function envOf(run: Run, unit: Unit | null): Promise<ExecutionEnv | undefined> {\n if (!unit || unit.fresh || !run.deps.layout.users) return undefined;\n const env = await run.deps.envOf?.(unit.cone);\n if (!env) throw new ImportError(`there is no kernel user ${unit.cone} to write its files as`);\n return env;\n}\n\nasync function putIn(run: Run, unit: Unit | null, root: string, rest: string, source: Source) {\n if (unit) await prepare(run, unit);\n const env = await envOf(run, unit);\n let fresh = run.fresh.get(root);\n if (fresh === undefined) {\n fresh = unit?.fresh || (await run.writer.tree(root, env));\n run.fresh.set(root, fresh);\n }\n if (unit?.fresh) unit.roots.add(root);\n const path = `${root}/${rest}`;\n const from = 'zip' in source && !env ? run.at.get(source.zip) : undefined;\n if (from && 'zip' in source) {\n await run.writer.move(from, path, fresh);\n run.at.set(source.zip, path);\n } else\n await run.writer.put(\n path,\n 'zip' in source ? await staged(run, source.zip) : source,\n fresh,\n env\n );\n if ('zip' in source && !run.notes.placed.has(source.zip)) run.notes.placed.set(source.zip, path);\n}\n\nconst clean = (name: string) => name.replace(/[^A-Za-z0-9._-]+/g, '_').slice(-80) || 'file';\n\ntype Maps = { byFolder: Map<string, Unit>; owners: Map<string, Unit>; primary?: Unit };\n\nfunction targets(run: Run, maps: Maps, where: Where, zip: string): [Unit, string, string][] {\n if (where.kind === 'cone' || where.kind === 'scoop') {\n const unit = (where.kind === 'cone' ? maps.byFolder : maps.owners).get(where.folder) as Unit;\n const root =\n where.kind === 'cone'\n ? `${unit.home}/workspace${unit.suffix}`\n : `${unit.home}/scoops${unit.suffix}/${where.folder}`;\n return [[unit, root, where.rest]];\n }\n if (where.kind === 'sprinkle') {\n if (!maps.primary)\n run.notes.skipped.push(`the sprinkle ${where.folder}: there is no cone to put it in`);\n return maps.primary\n ? [\n [\n maps.primary,\n `${maps.primary.home}/sprinkles/${lickName(where.folder, 'sprinkle')}`,\n where.rest,\n ],\n ]\n : [];\n }\n if (where.kind !== 'attachment') return [];\n return run.parsed.units.flatMap((unit) =>\n (unit.doc?.attachments ?? [])\n .filter((item) => item.present && item.path === zip)\n .map((item): [Unit, string, string] => {\n const rest = `${item.sha256.slice(0, 12)}-${clean(item.originalName)}`;\n unit.files.set(item.id, `${unit.home}/v6-attachments/${rest}`);\n return [unit, `${unit.home}/v6-attachments`, rest];\n })\n );\n}\n\nfunction sprinkleCalls(run: Run, name: string, bytes: Uint8Array) {\n const found = [...new TextDecoder().decode(bytes).matchAll(/\\bslicc\\.([A-Za-z_$][\\w$]*)/g)]\n .map((match) => `slicc.${match[1]}`)\n .filter((call) => call !== 'slicc.lick');\n if (!found.length) return;\n const known = run.notes.sprinkles.get(name) ?? new Set<string>();\n for (const call of found) known.add(call);\n run.notes.sprinkles.set(name, known);\n}\n\nasync function alike(\n run: Run,\n dir: string,\n six: string,\n rests: readonly string[]\n): Promise<boolean> {\n for (const rest of rests) {\n const old = await run.writer.env.readBinaryFile(`${dir}/${rest}`, run.writer.context);\n if (!old.ok || !same(old.value, await staged(run, `skills/${six}/${rest}`))) return false;\n }\n return true;\n}\n\nasync function placeSkills(run: Run, skills: Map<string, string[]>, primary: Unit | undefined) {\n const seen = new Set<string>();\n for (const [six, rests] of skills) {\n const name = skillName(six);\n if (!name || validateName(name).length || seen.has(name)) {\n run.notes.skipped.push(\n `the skill ${six}: its name doesn't fit seven's rule (a-z, 0-9 and -)`\n );\n continue;\n }\n seen.add(name);\n const global = `${GLOBAL_DIR}/${name}`;\n const exists = await run.writer.exists(global);\n if (exists && (await alike(run, global, six, rests))) {\n run.notes.lines.push(`the skill ${name}: already in ${GLOBAL_DIR}`);\n continue;\n }\n const own = primary && exists ? `${primary.home}/.pi/agent/skills/${name}` : undefined;\n if (exists && !own) {\n run.notes.skipped.push(`the skill ${name}: ${GLOBAL_DIR} has another skill of that name`);\n continue;\n }\n for (const rest of rests)\n await putIn(run, own ? (primary as Unit) : null, own ?? global, rest, {\n zip: `skills/${six}/${rest}`,\n });\n if (own)\n run.notes.shadowed.push(\n `the skill ${name}: ${GLOBAL_DIR} has another skill of that name, so SLICC 6's copy is in ${own}, for ${(primary as Unit).cone} only`\n );\n else run.notes.lines.push(`the skill ${name}, for every agent, in ${global}`);\n }\n}\n\nasync function placeMemory(run: Run) {\n const root = memoryRoot(run.deps.memoryHome);\n const { data, units } = run.parsed;\n const places = [\n { name: 'memory/global.md', file: `${root}/MEMORY.md`, rest: `${V6_ROOT}/memory/global.md` },\n ...units\n .filter((unit) => unit.memory)\n .map((unit) => ({\n name: unit.memory as string,\n file: `${root}/${unit.cone}/MEMORY.md`,\n rest: `${V6_ROOT}/memory/${unit.cone}.md`,\n })),\n ];\n for (const place of places) {\n const bytes = data.get(place.name);\n const done = bytes\n ? await remember(run.writer, place.file, textOf(bytes, place.name), {\n file: place.rest,\n date: run.date,\n })\n : 'none';\n if (done === 'merged')\n run.notes.lines.push(`memory, under \"Imported from SLICC 6 (${run.date})\", in ${place.file}`);\n if (done === 'aside')\n run.notes.lines.push(`memory, in ${place.rest}: ${place.file} has no room left for it`);\n }\n}\n\nfunction earlier(run: Run, unit: Unit, name: string): LickTarget | undefined {\n const found = Object.entries(run.deps.agents.state().scoops).filter(\n ([, record]) => record.cone === unit.cone && record.name === name && !record.removed\n );\n return found.at(-1)?.[0] as LickTarget | undefined;\n}\n\nfunction router(run: Run, maps: Maps) {\n return (folder: string | null | undefined): [Unit, LickTarget] | undefined => {\n const cone = folder ? maps.byFolder.get(folder) : undefined;\n if (cone) return [cone, 'cone'];\n const owner = folder ? maps.owners.get(folder) : undefined;\n const scoop = owner?.scoops.find((item) => item.six === folder);\n const target =\n owner && scoop\n ? owner.record\n ? (`scoop:${scoop.folder}` as LickTarget)\n : earlier(run, owner, scoop.name)\n : undefined;\n if (owner && target) return [owner, target];\n const unit = owner ?? maps.primary;\n return unit ? [unit, 'cone'] : undefined;\n };\n}\n\nconst FIELD = '[0-9A-Za-z*,/-]+';\nconst SCHEDULE = new RegExp(\n `^(@(yearly|annually|monthly|weekly|daily|midnight|hourly|reboot)|${FIELD}( ${FIELD}){4})$`\n);\n\nconst flat = (text: string) => text.replace(/\\s+/g, ' ').trim();\n\nasync function placeLicks(run: Run, maps: Maps) {\n const { licks } = run.parsed;\n const route = router(run, maps);\n const crons = new Map<Unit, CronLine[]>();\n const add = (found: [Unit, LickTarget] | undefined, line: Omit<CronLine, 'target'>) => {\n const why = !SCHEDULE.test(line.schedule)\n ? `\"${line.schedule}\" is not a cron schedule`\n : !found && 'there is no cone to send it to';\n if (why) run.notes.skipped.push(`the cron ${line.name}: ${why}`);\n else if (found)\n crons.set(found[0], [...(crons.get(found[0]) ?? []), { ...line, target: found[1] }]);\n };\n for (const [at, task] of licks.crontasks.entries())\n add(route(task.targetFolder), {\n name: lickName(task.name, `v6-cron-${at + 1}`),\n schedule: flat(task.cron),\n message: '',\n ...(task.filter ? { filter: task.filter } : {}),\n });\n for (const [at, task] of licks.tasks.entries()) {\n if (task.scheduleType === 'cron')\n add(route(task.groupFolder), {\n name: `v6-task-${at + 1}`,\n schedule: flat(task.scheduleValue),\n message: flat(task.prompt),\n });\n else\n run.notes.tasks.push(\n `${task.scheduleType} ${task.scheduleValue}: ${flat(task.prompt).slice(0, 80)}`\n );\n }\n for (const [unit, list] of crons) {\n await prepare(run, unit);\n const user = run.deps.layout.users ? unit.cone : 'root';\n const count = await installCrons(run.writer, user, list, run.date);\n if (count) run.notes.crons.push(`${count} in crontab -u ${user}`);\n }\n for (const [at, hook] of licks.webhooks.entries()) {\n const found = route(hook.targetFolder);\n const name = lickName(hook.name, `v6-webhook-${at + 1}`);\n if (!found) run.notes.skipped.push(`the webhook ${name}: there is no cone to send it to`);\n if (!found) continue;\n const root = `${found[0].home}/.slicc/webhooks`;\n await putIn(\n run,\n found[0],\n root,\n `${name}.json.v6`,\n new TextEncoder().encode(`${JSON.stringify({ target: found[1] }, null, 2)}\\n`)\n );\n run.notes.webhooks.push(`${root}/${name}.json.v6`);\n }\n}\n\nasync function placeGit(run: Run) {\n const name = run.opened.manifest.gitconfig;\n const bytes = name ? run.parsed.data.get(name) : undefined;\n const section = bytes ? userSection(textOf(bytes, name as string)) : '';\n if (!section) return;\n const file = `${ROOT_HOME}/.gitconfig`;\n const read = await run.writer.env.readTextFile(file, run.writer.context);\n const before = read.ok ? read.value.trimEnd() : '';\n if (/^\\s*\\[user\\]/im.test(before)) {\n run.notes.skipped.push(`SLICC 6's git [user]: ${file} already has one`);\n return;\n }\n await run.writer.put(file, `${before ? `${before}\\n` : ''}${section}`, false);\n run.notes.lines.push(`your git name and email, in ${file}`);\n}\n\nexport async function place(run: Run): Promise<void> {\n const { manifest } = run.opened;\n const units = run.parsed.units;\n const byFolder = new Map(\n units.filter((unit) => unit.six).map((unit) => [unit.six as string, unit])\n );\n const owners = new Map(\n units.flatMap((unit) =>\n unit.scoops.filter((scoop) => scoop.six).map((scoop) => [scoop.six as string, unit])\n )\n );\n const maps: Maps = {\n byFolder,\n owners,\n primary: byFolder.get('cone') ?? units.find((unit) => unit.six !== null),\n };\n const skills = new Map<string, string[]>();\n const later: [string, string][] = [];\n for (const [at, file] of manifest.files.entries()) {\n const where = whereOf(manifest, file.path);\n if (where.kind === 'skill')\n skills.set(where.folder, [...(skills.get(where.folder) ?? []), where.rest]);\n if (where.kind === 'home-user') later.push([file.path, where.rest]);\n if (where.kind === 'sprinkle') sprinkleCalls(run, where.folder, await staged(run, file.path));\n for (const [unit, root, rest] of targets(run, maps, where, file.path))\n await putIn(run, unit, root, rest, { zip: file.path });\n run.show('writing', at + 1, manifest.files.length);\n }\n await placeSkills(run, skills, maps.primary);\n await placeMemory(run);\n await placeLicks(run, maps);\n await placeGit(run);\n for (const [zip, rest] of later) await putIn(run, null, `${V6_ROOT}/home-user`, rest, { zip });\n if (run.deps.layout.users)\n for (const unit of units) await ownTree(run.writer, unit.cone, unit.home, unit.roots);\n}\n\nconst WHY: Record<string, string> = {\n env: 'environment file, often holds keys',\n pem: 'PEM file, may be a private key',\n 'git-credentials': 'git credentials in plain text',\n npmrc: 'npm config, may hold an auth token',\n 'slicc-oauth': 'SLICC 6 OAuth state',\n};\n\nconst NEVER: Record<string, string> = {\n 'secrets-env': '~/.slicc/secrets.env, which stays on the host',\n 'github-token': 'the GitHub token',\n 'mcp-tokens': 'MCP tokens',\n 'chrome-storage': \"the extension's chrome.storage secrets\",\n};\n\nconst bullets = (items: readonly string[], none: string) =>\n (items.length ? items : [none]).map((item) => `- ${item}`);\n\nfunction nextSteps(run: Run, mounts: readonly string[]): string[] {\n const { manifest } = run.opened;\n const { notes } = run;\n const sprinkles = [...notes.sprinkles].map(\n ([name, calls]) => `${name} (${[...calls].join(', ')})`\n );\n return [\n 'Re-enter your keys and logins in Settings.',\n ...(mounts.length ? [`Mount these folders again: ${mounts.join(', ')}.`] : []),\n ...(manifest.mcp?.length\n ? [\n `Add these MCP servers again: ${manifest.mcp.map((item) => `${item.name} (${item.url})`).join(', ')}.`,\n ]\n : []),\n ...(notes.crons.length\n ? [\n `Turn crons on with sudo crontab -u <user> -e: remove the leading \"# \" from a job's two lines.`,\n ]\n : []),\n ...(notes.webhooks.length\n ? [\n \"Turn a webhook on by renaming <name>.json.v6 to <name>.json, then point its sender at seven's webhook URL.\",\n ]\n : []),\n ...(sprinkles.length\n ? [\n `These sprinkles call SLICC APIs other than slicc.lick and may need edits: ${sprinkles.join(', ')}.`,\n ]\n : []),\n ];\n}\n\nexport async function reportOf(run: Run, made: readonly string[]): Promise<string> {\n const { manifest } = run.opened;\n const { notes, date, parsed } = run;\n const recorded = parsed.units.filter((unit) => unit.record);\n const imported = [\n ...recorded.map(\n (unit, at) =>\n `${unit.title}: frozen cone ${made[at]}, home ${unit.home}${unit.suffix ? `, new files in ${unit.home}/workspace${unit.suffix}` : ''}${unit.scoops.length ? `, with ${unit.scoops.map((scoop) => scoop.name).join(', ')}` : ''}`\n ),\n ...notes.lines,\n ...notes.crons.map((line) => `crons, imported off: ${line}`),\n ...notes.webhooks.map((path) => `a webhook, imported off: ${path}`),\n ];\n const mounts = manifest.skipped\n .filter((item) => item.reason === 'mount')\n .map((item) => item.path);\n const skipped = [\n ...manifest.skipped.map((item) => `${item.path}: ${item.reason}`),\n ...parsed.units\n .filter((unit) => !unit.record)\n .map((unit) => `${unit.title}: unchanged since the last import`),\n ...notes.skipped,\n ...notes.shadowed,\n ...notes.tasks.map((task) => `a SLICC 6 task that cron can't express: ${task}`),\n ];\n const flagged = manifest.flagged.map(\n (item) => `| ${notes.placed.get(item.path) ?? item.path} | ${item.size} B | ${WHY[item.rule]} |`\n );\n const split = accountsSplit(manifest.providers, run.deps.providers);\n const providers = [\n ...split.again.map((id) => `${split.nameOf(id)}: re-enter in Settings`),\n ...split.missing.map((id) => `${split.nameOf(id)}: SLICC 7 has no such provider`),\n ];\n const never = (manifest.secrets ?? []).map((name) => NEVER[name] ?? name);\n const part = manifest.part ? `, part ${manifest.part.index} of ${manifest.part.of}` : '';\n const text = [\n `# SLICC 6 import, ${date}`,\n '',\n `From ${manifest.producer.origin} (SLICC ${manifest.producer.slicc}), exported ${manifest.createdAt}, export ${manifest.exportId}${part}.`,\n '',\n '## Imported',\n '',\n ...bullets(imported, 'nothing new'),\n '',\n '## Skipped',\n '',\n ...bullets(skipped, 'nothing'),\n '',\n ...(flagged.length\n ? [\n '## Review these files',\n '',\n '| Path | Size | Why |',\n '| --- | --- | --- |',\n ...flagged,\n '',\n \"Delete or move these if you don't need them here.\",\n '',\n ]\n : []),\n '## Re-enter in Settings',\n '',\n ...bullets(providers, 'no providers'),\n ...(never.length ? ['', `These never move: ${never.join(', ')}.`] : []),\n '',\n '## Next steps',\n '',\n ...nextSteps(run, mounts).map((step) => `- ${step}`),\n '',\n ].join('\\n');\n let file = `${ROOT_HOME}/v6-import-${date}.md`;\n for (let n = 2; await run.writer.exists(file); n++)\n file = `${ROOT_HOME}/v6-import-${date}-${n}.md`;\n const written = await run.writer.env.writeFile(file, text, BACKGROUND_CONTEXT);\n if (!written.ok)\n throw new ImportError(`couldn't write the report ${file}: ${written.error.message}`);\n return file;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["place"]
|
|
7
7
|
}
|
|
@@ -216,6 +216,37 @@ function named(item, path) {
|
|
|
216
216
|
);
|
|
217
217
|
need(maybe(item.conversation, str), `${path}.conversation must be a string`);
|
|
218
218
|
}
|
|
219
|
+
const DIRECTORY_ROOT = "/slicc-v6-upgrade";
|
|
220
|
+
const SOURCE_ROOT = "/slicc-fs/";
|
|
221
|
+
const SIDECAR = "/slicc-fs/.metadata.json";
|
|
222
|
+
const MOVABLE = ["files/", "skills/", "sprinkles/"];
|
|
223
|
+
function safeSource(path) {
|
|
224
|
+
if (!path.startsWith(SOURCE_ROOT) || path === SIDECAR) return false;
|
|
225
|
+
const rest = path.slice(SOURCE_ROOT.length);
|
|
226
|
+
return !/\\|\0/.test(rest) && rest.split("/").every((part) => part !== "" && part !== "." && part !== "..");
|
|
227
|
+
}
|
|
228
|
+
function sources(value, version) {
|
|
229
|
+
const seen = /* @__PURE__ */ new Set();
|
|
230
|
+
for (const [at, file] of value.files.entries()) {
|
|
231
|
+
if (file.source === void 0) continue;
|
|
232
|
+
need(version === 2, `files[${at}].source needs version 2, the directory form`);
|
|
233
|
+
need(
|
|
234
|
+
str(file.source) && safeSource(file.source),
|
|
235
|
+
`files[${at}].source must be a path under ${SOURCE_ROOT}`
|
|
236
|
+
);
|
|
237
|
+
need(
|
|
238
|
+
MOVABLE.some((top) => String(file.path).startsWith(top)),
|
|
239
|
+
`files[${at}] can't stay in place: only ${MOVABLE.join(", ")} entries can`
|
|
240
|
+
);
|
|
241
|
+
need(!seen.has(file.source), `files moves ${file.source} twice`);
|
|
242
|
+
seen.add(file.source);
|
|
243
|
+
}
|
|
244
|
+
if (version === 2)
|
|
245
|
+
need(
|
|
246
|
+
value.skipped.every((item) => item.reason !== "archive-limit"),
|
|
247
|
+
"a directory form has no archive-limit skips"
|
|
248
|
+
);
|
|
249
|
+
}
|
|
219
250
|
function manifestLists(value) {
|
|
220
251
|
list(value.cones, "cones", (cone, path) => {
|
|
221
252
|
named(cone, path);
|
|
@@ -264,13 +295,17 @@ function manifestLists(value) {
|
|
|
264
295
|
`${key} must be strings`
|
|
265
296
|
);
|
|
266
297
|
}
|
|
267
|
-
function checkManifest(value) {
|
|
298
|
+
function checkManifest(value, version = 1) {
|
|
268
299
|
need(obj(value) && value.format === "slicc-profile", "this is not a SLICC 6 profile export");
|
|
269
300
|
need(
|
|
270
|
-
!(typeof value.version === "number" && value.version >
|
|
301
|
+
!(typeof value.version === "number" && value.version > 2),
|
|
271
302
|
"This export is from a newer SLICC 6; update seven."
|
|
272
303
|
);
|
|
273
|
-
need(
|
|
304
|
+
need(
|
|
305
|
+
value.version !== 2 || version === 2,
|
|
306
|
+
"this is SLICC 6's directory form; import it with freezer import --in-place"
|
|
307
|
+
);
|
|
308
|
+
need(value.version === version, `the export version must be ${version}`);
|
|
274
309
|
need(
|
|
275
310
|
str(value.exportId) && /^[A-Za-z0-9-]{1,64}$/.test(value.exportId),
|
|
276
311
|
"exportId must be a UUID"
|
|
@@ -284,11 +319,13 @@ function checkManifest(value) {
|
|
|
284
319
|
"createdAt, licks or gitconfig is malformed"
|
|
285
320
|
);
|
|
286
321
|
const part = value.part;
|
|
322
|
+
need(version === 1 || part === void 0, "a directory form is never split into parts");
|
|
287
323
|
need(
|
|
288
324
|
part === void 0 || obj(part) && count(part.index) && part.index >= 1 && part.index <= part.of,
|
|
289
325
|
"part is malformed"
|
|
290
326
|
);
|
|
291
327
|
manifestLists(value);
|
|
328
|
+
sources(value, version);
|
|
292
329
|
const folders = value.cones.flatMap((cone) => [
|
|
293
330
|
`cone:${cone.folder}`,
|
|
294
331
|
...cone.scoops.map((scoop) => `scoop:${scoop.folder}`)
|
|
@@ -333,11 +370,14 @@ function skillName(name) {
|
|
|
333
370
|
return name.toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "").slice(0, 64).replace(/-+$/, "");
|
|
334
371
|
}
|
|
335
372
|
export {
|
|
373
|
+
DIRECTORY_ROOT,
|
|
336
374
|
FOLDER,
|
|
375
|
+
SOURCE_ROOT,
|
|
337
376
|
checkLicks,
|
|
338
377
|
checkManifest,
|
|
339
378
|
checkTranscript,
|
|
340
379
|
lickName,
|
|
380
|
+
safeSource,
|
|
341
381
|
skillName
|
|
342
382
|
};
|
|
343
383
|
//# sourceMappingURL=v6-schema.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/freezer/v6-schema.ts"],
|
|
4
|
-
"sourcesContent": ["import { ImportError } from './zip.ts';\n\ntype Json = Record<string, unknown>;\n\nexport type Block =\n | { type: 'text'; text: string }\n | { type: 'tool-call'; id: string; name: string; input: unknown }\n | { type: 'attachment-ref'; attachmentId: string };\n\nexport type V6Message = {\n id: string;\n sequence: number;\n role: 'user' | 'assistant' | 'tool-result';\n timestamp: string;\n content: Block[];\n toolCallId?: string;\n isError?: boolean;\n model?: { provider: string; id: string; api?: string };\n usage?: Json;\n stopReason?: string;\n};\n\nexport type V6Conversation = {\n id: string;\n kind: 'cone' | 'scoop';\n name: string;\n folder?: string;\n messages: V6Message[];\n};\n\nexport type V6Attachment = {\n id: string;\n path: string;\n originalName: string;\n sha256: string;\n byteLength: number;\n present: boolean;\n};\n\nexport type Transcript = {\n session: { id: string; title: string; updatedAt?: string; frozenAt?: string; createdAt?: string };\n conversations: V6Conversation[];\n attachments: V6Attachment[];\n};\n\nexport type ManifestScoop = {\n key: string;\n folder: string;\n name: string;\n conversation: string | null;\n};\n\nexport type ManifestCone = ManifestScoop & {\n transcript: string | null;\n memory: string | null;\n scoops: ManifestScoop[];\n};\n\nexport type Manifest = {\n exportId: string;\n producer: { slicc: string; origin: string };\n createdAt: string;\n part?: { index: number; of: number };\n cones: ManifestCone[];\n frozen: { id: string; title: string; frozenAt: string | null; transcript: string }[];\n skills: { name: string; path: string }[];\n sprinkles: { name: string; path: string }[];\n licks: string | null;\n gitconfig?: string | null;\n files: { path: string; size: number; sha256: string }[];\n skipped: { path: string; reason: string }[];\n flagged: { path: string; size: number; rule: string }[];\n providers: string[];\n mcp?: { name: string; url: string }[];\n secrets?: string[];\n};\n\nexport type Licks = {\n crontasks: { name: string; cron: string; targetFolder?: string | null; filter?: string }[];\n tasks: { groupFolder: string; prompt: string; scheduleType: string; scheduleValue: string }[];\n webhooks: { name: string; targetFolder?: string | null; filter?: string }[];\n};\n\nexport const FOLDER = /^[a-z0-9][a-z0-9._-]{0,63}$/;\nconst SHA = /^[0-9a-fA-F]{64}$/;\nconst REASONS = [\n 'canonical-agent-history-unavailable',\n 'tool-data-may-be-truncated',\n 'model-metadata-unavailable',\n 'scoop-history-unavailable',\n 'attachment-file-missing',\n 'attachment-association-unavailable',\n 'complete-snapshot-unavailable',\n];\nconst RULES = ['env', 'pem', 'git-credentials', 'npmrc', 'slicc-oauth'];\n\nconst obj = (value: unknown): value is Json =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\nconst str = (value: unknown): value is string => typeof value === 'string';\nconst full = (value: unknown): value is string => str(value) && value !== '';\nconst count = (value: unknown) => Number.isInteger(value) && (value as number) >= 0;\nconst amount = (value: unknown) =>\n typeof value === 'number' && Number.isFinite(value) && value >= 0;\nconst iso = (value: unknown) =>\n str(value) &&\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/.test(value) &&\n !Number.isNaN(Date.parse(value));\nconst maybe = (value: unknown, check: (value: unknown) => boolean) =>\n value === undefined || value === null || check(value);\n\nfunction need(ok: boolean, error: string): asserts ok {\n if (!ok) throw new ImportError(error);\n}\n\nfunction oneOf(value: unknown, allowed: readonly string[], label: string) {\n need(str(value) && allowed.includes(value), `${label} must be one of ${allowed.join(', ')}`);\n}\n\nfunction list(value: unknown, label: string, check: (item: Json, path: string) => void) {\n need(Array.isArray(value), `${label} must be an array`);\n value.forEach((item, at) => {\n need(obj(item), `${label}[${at}] must be an object`);\n check(item, `${label}[${at}]`);\n });\n}\n\nfunction block(item: Json, path: string) {\n oneOf(item.type, ['text', 'tool-call', 'attachment-ref'], `${path}.type`);\n if (item.type === 'text') need(str(item.text), `${path}.text must be a string`);\n else if (item.type === 'tool-call')\n need(\n full(item.id) && full(item.name) && 'input' in item,\n `${path} needs an id, a name and an input`\n );\n else need(full(item.attachmentId), `${path}.attachmentId must be a non-empty string`);\n}\n\nconst TOKENS = ['input', 'output', 'cacheRead', 'cacheWrite', 'totalTokens'];\nconst COSTS = ['input', 'output', 'cacheRead', 'cacheWrite', 'total'];\n\nfunction message(item: Json, path: string) {\n oneOf(item.role, ['user', 'assistant', 'tool-result'], `${path}.role`);\n if (item.role === 'tool-result') need(full(item.toolCallId), `${path}.toolCallId must be set`);\n need(str(item.id), `${path}.id must be a string`);\n need(\n Number.isInteger(item.sequence) && (item.sequence as number) >= 1,\n `${path}.sequence must be a positive integer`\n );\n need(iso(item.timestamp), `${path}.timestamp must be an ISO 8601 date-time`);\n list(item.content, `${path}.content`, block);\n const usage = item.usage;\n if (usage === undefined) return;\n need(\n obj(usage) &&\n TOKENS.every((key) => count(usage[key])) &&\n obj(usage.cost) &&\n COSTS.every((key) => amount((usage.cost as Json)[key])),\n `${path}.usage is malformed`\n );\n}\n\nfunction attachment(item: Json, path: string) {\n const fields = [\n 'id',\n 'path',\n 'originalName',\n 'mimeType',\n 'sha256',\n 'sourceConversationId',\n 'sourceMessageId',\n ];\n need(\n fields.every((key) => str(item[key])),\n `${path} needs ${fields.join(', ')}`\n );\n need(\n typeof item.byteLength === 'number' && typeof item.present === 'boolean',\n `${path} needs byteLength and present`\n );\n oneOf(item.handling, ['text-redacted', 'binary-unchanged'], `${path}.handling`);\n if (item.present)\n need(\n item.path !== '' &&\n SHA.test(item.sha256 as string) &&\n count(item.byteLength) &&\n item.missingReason === undefined,\n `${path} is present but malformed`\n );\n else {\n need(\n item.path === '' && item.sha256 === '' && item.byteLength === 0,\n `${path} is missing but has a file`\n );\n oneOf(item.missingReason, REASONS.slice(4, 6), `${path}.missingReason`);\n }\n}\n\nfunction redaction(item: Json, path: string) {\n need(str(item.id) && str(item.category) && obj(item.target), `${path} is malformed`);\n oneOf(\n item.detector,\n ['known-secret', 'credential-pattern', 'pre-obfuscated'],\n `${path}.detector`\n );\n const target = item.target as Json;\n oneOf(target.kind, ['json', 'attachment'], `${path}.target.kind`);\n if (target.kind === 'json')\n need(\n str(target.pointer) && (target.pointer === '' || target.pointer.startsWith('/')),\n `${path}.target.pointer is not a JSON pointer`\n );\n else need(full(target.attachmentId), `${path}.target.attachmentId must be set`);\n}\n\nfunction sections(doc: Json) {\n need(doc.schemaVersion === 1, 'schemaVersion must equal 1');\n const exported = doc.export;\n need(\n obj(exported) &&\n str(exported.id) &&\n str(exported.generatedAt) &&\n exported.format === 'slicc-transcript' &&\n obj(exported.producer) &&\n exported.producer.application === 'slicc' &&\n str(exported.producer.version),\n 'export is malformed'\n );\n const session = doc.session;\n need(\n obj(session) && str(session.id) && str(session.title) && obj(session.completeness),\n 'session is malformed'\n );\n oneOf(session.state, ['active', 'frozen'], 'session.state');\n const completeness = session.completeness as Json;\n oneOf(completeness.status, ['complete', 'partial'], 'session.completeness.status');\n need(\n Array.isArray(completeness.missing) &&\n completeness.missing.every((reason) => REASONS.includes(reason)),\n 'session.completeness.missing is malformed'\n );\n const privacy = doc.privacy;\n need(\n obj(privacy) &&\n privacy.reasoningExcluded === true &&\n count(privacy.excludedReasoningBlocks) &&\n privacy.binaryAttachments === 'included-unchanged' &&\n obj(privacy.redactionCounts),\n 'privacy is malformed'\n );\n list(privacy.redactions, 'privacy.redactions', redaction);\n list(doc.conversations, 'conversations', (item, path) => {\n need(str(item.id) && str(item.name), `${path} needs an id and a name`);\n oneOf(item.kind, ['cone', 'scoop'], `${path}.kind`);\n list(item.messages, `${path}.messages`, message);\n });\n list(doc.delegations, 'delegations', (item, path) =>\n need(str(item.sourceConversationId) && str(item.targetConversationId), `${path} is malformed`)\n );\n list(doc.attachments, 'attachments', attachment);\n}\n\nfunction relations(doc: Json) {\n const conversations = new Map<string, { messages: Set<string>; calls: Set<string> }>();\n const messages = new Set<string>();\n const calls = new Set<string>();\n const results: string[] = [];\n const refs: string[] = [];\n for (const conversation of doc.conversations as Json[]) {\n const id = conversation.id as string;\n need(!conversations.has(id), `duplicate conversation id \"${id}\"`);\n const own = { messages: new Set<string>(), calls: new Set<string>() };\n conversations.set(id, own);\n let previous = 0;\n for (const item of conversation.messages as V6Message[]) {\n need(!messages.has(item.id), `duplicate message id \"${item.id}\"`);\n need(\n item.sequence > previous,\n `sequences in conversation \"${id}\" must be strictly increasing`\n );\n previous = item.sequence;\n messages.add(item.id);\n own.messages.add(item.id);\n if (item.role === 'tool-result') results.push(item.toolCallId as string);\n for (const part of item.content)\n if (part.type === 'tool-call') {\n calls.add(part.id);\n own.calls.add(part.id);\n } else if (part.type === 'attachment-ref') refs.push(part.attachmentId);\n }\n }\n for (const id of results)\n need(calls.has(id), `tool-result message references unknown toolCallId \"${id}\"`);\n const attached = new Set((doc.attachments as Json[]).map((item) => item.id as string));\n for (const id of refs)\n need(attached.has(id), `attachment-ref references unknown attachmentId \"${id}\"`);\n for (const item of doc.attachments as Json[])\n need(\n conversations\n .get(item.sourceConversationId as string)\n ?.messages.has(item.sourceMessageId as string) === true,\n `attachment ${item.id as string} comes from an unknown message`\n );\n for (const item of doc.delegations as Json[]) {\n const source = conversations.get(item.sourceConversationId as string);\n need(\n source !== undefined && conversations.has(item.targetConversationId as string),\n 'a delegation names an unknown conversation'\n );\n need(\n !full(item.toolCallId) || source.calls.has(item.toolCallId),\n 'a delegation names an unknown tool call'\n );\n }\n for (const item of (doc.privacy as Json).redactions as Json[]) {\n const target = item.target as Json;\n need(\n target.kind !== 'attachment' || attached.has(target.attachmentId as string),\n 'a redaction names an unknown attachment'\n );\n }\n}\n\nexport function checkTranscript(value: unknown): Transcript {\n need(obj(value), 'document must be a non-null object');\n sections(value);\n relations(value);\n return value as unknown as Transcript;\n}\n\nfunction named(item: Json, path: string) {\n need(\n str(item.key) && str(item.name) && FOLDER.test(String(item.folder)),\n `${path} needs a key, a name and a folder`\n );\n need(maybe(item.conversation, str), `${path}.conversation must be a string`);\n}\n\nfunction manifestLists(value: Json) {\n list(value.cones, 'cones', (cone, path) => {\n named(cone, path);\n need(maybe(cone.transcript, str) && maybe(cone.memory, str), `${path} is malformed`);\n list(cone.scoops, `${path}.scoops`, named);\n });\n list(value.frozen, 'frozen', (item, path) =>\n need(\n str(item.id) && str(item.title) && str(item.transcript) && maybe(item.frozenAt, iso),\n `${path} is malformed`\n )\n );\n for (const key of ['skills', 'sprinkles'])\n list(value[key], key, (item, path) =>\n need(str(item.name) && str(item.path), `${path} is malformed`)\n );\n list(value.files, 'files', (item, path) =>\n need(\n str(item.path) && count(item.size) && SHA.test(String(item.sha256)),\n `${path} is malformed`\n )\n );\n list(value.skipped, 'skipped', (item, path) =>\n need(str(item.path) && str(item.reason), `${path} is malformed`)\n );\n list(value.flagged, 'flagged', (item, path) => {\n need(str(item.path) && count(item.size), `${path} is malformed`);\n oneOf(item.rule, RULES, `${path}.rule`);\n });\n list(value.mcp ?? [], 'mcp', (item, path) =>\n need(str(item.name) && str(item.url), `${path} is malformed`)\n );\n for (const key of ['providers', 'secrets'])\n need(\n Array.isArray(value[key] ?? []) && ((value[key] as unknown[] | undefined) ?? []).every(str),\n `${key} must be strings`\n );\n}\n\nexport function checkManifest(value: unknown): Manifest {\n need(obj(value) && value.format === 'slicc-profile', 'this is not a SLICC 6 profile export');\n need(\n !(typeof value.version === 'number' && value.version > 1),\n 'This export is from a newer SLICC 6; update seven.'\n );\n need(value.version === 1, 'the export version must be 1');\n need(\n str(value.exportId) && /^[A-Za-z0-9-]{1,64}$/.test(value.exportId),\n 'exportId must be a UUID'\n );\n need(\n obj(value.producer) && str(value.producer.slicc) && str(value.producer.origin),\n 'producer is malformed'\n );\n need(\n iso(value.createdAt) && maybe(value.licks, str) && maybe(value.gitconfig, str),\n 'createdAt, licks or gitconfig is malformed'\n );\n const part = value.part as Json | undefined;\n need(\n part === undefined ||\n (obj(part) &&\n count(part.index) &&\n (part.index as number) >= 1 &&\n (part.index as number) <= (part.of as number)),\n 'part is malformed'\n );\n manifestLists(value);\n const folders = (value.cones as Manifest['cones']).flatMap((cone) => [\n `cone:${cone.folder}`,\n ...cone.scoops.map((scoop) => `scoop:${scoop.folder}`),\n ]);\n need(new Set(folders).size === folders.length, 'two cones or two scoops share a folder');\n return value as unknown as Manifest;\n}\n\nconst optional = (value: unknown) => value === undefined || str(value);\nconst target = (value: unknown) => maybe(value, (folder) => FOLDER.test(String(folder)));\n\nexport function checkLicks(value: unknown): Licks {\n need(obj(value), 'licks.json must be an object');\n list(value.crontasks, 'crontasks', (item, path) =>\n need(\n str(item.name) && str(item.cron) && target(item.targetFolder) && optional(item.filter),\n `${path} is malformed`\n )\n );\n list(value.tasks, 'tasks', (item, path) => {\n need(\n str(item.groupFolder) && str(item.prompt) && str(item.scheduleValue),\n `${path} is malformed`\n );\n oneOf(item.scheduleType, ['cron', 'interval', 'once'], `${path}.scheduleType`);\n });\n list(value.webhooks, 'webhooks', (item, path) =>\n need(\n str(item.name) && target(item.targetFolder) && optional(item.filter),\n `${path} is malformed`\n )\n );\n return value as unknown as Licks;\n}\n\nexport function lickName(name: string, fallback: string): string {\n const clean = name\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, '-')\n .replace(/^[^a-z0-9]+/, '')\n .slice(0, 64);\n return clean || fallback;\n}\n\nexport function skillName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9-]+/g, '-')\n .replace(/-{2,}/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 64)\n .replace(/-+$/, '');\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { ImportError } from './zip.ts';\n\ntype Json = Record<string, unknown>;\n\nexport type Block =\n | { type: 'text'; text: string }\n | { type: 'tool-call'; id: string; name: string; input: unknown }\n | { type: 'attachment-ref'; attachmentId: string };\n\nexport type V6Message = {\n id: string;\n sequence: number;\n role: 'user' | 'assistant' | 'tool-result';\n timestamp: string;\n content: Block[];\n toolCallId?: string;\n isError?: boolean;\n model?: { provider: string; id: string; api?: string };\n usage?: Json;\n stopReason?: string;\n};\n\nexport type V6Conversation = {\n id: string;\n kind: 'cone' | 'scoop';\n name: string;\n folder?: string;\n messages: V6Message[];\n};\n\nexport type V6Attachment = {\n id: string;\n path: string;\n originalName: string;\n sha256: string;\n byteLength: number;\n present: boolean;\n};\n\nexport type Transcript = {\n session: { id: string; title: string; updatedAt?: string; frozenAt?: string; createdAt?: string };\n conversations: V6Conversation[];\n attachments: V6Attachment[];\n};\n\nexport type ManifestScoop = {\n key: string;\n folder: string;\n name: string;\n conversation: string | null;\n};\n\nexport type ManifestCone = ManifestScoop & {\n transcript: string | null;\n memory: string | null;\n scoops: ManifestScoop[];\n};\n\nexport type Manifest = {\n exportId: string;\n producer: { slicc: string; origin: string };\n createdAt: string;\n part?: { index: number; of: number };\n cones: ManifestCone[];\n frozen: { id: string; title: string; frozenAt: string | null; transcript: string }[];\n skills: { name: string; path: string }[];\n sprinkles: { name: string; path: string }[];\n licks: string | null;\n gitconfig?: string | null;\n files: { path: string; size: number; sha256: string; source?: string }[];\n skipped: { path: string; reason: string }[];\n flagged: { path: string; size: number; rule: string }[];\n providers: string[];\n mcp?: { name: string; url: string }[];\n secrets?: string[];\n};\n\nexport type Licks = {\n crontasks: { name: string; cron: string; targetFolder?: string | null; filter?: string }[];\n tasks: { groupFolder: string; prompt: string; scheduleType: string; scheduleValue: string }[];\n webhooks: { name: string; targetFolder?: string | null; filter?: string }[];\n};\n\nexport const FOLDER = /^[a-z0-9][a-z0-9._-]{0,63}$/;\nconst SHA = /^[0-9a-fA-F]{64}$/;\nconst REASONS = [\n 'canonical-agent-history-unavailable',\n 'tool-data-may-be-truncated',\n 'model-metadata-unavailable',\n 'scoop-history-unavailable',\n 'attachment-file-missing',\n 'attachment-association-unavailable',\n 'complete-snapshot-unavailable',\n];\nconst RULES = ['env', 'pem', 'git-credentials', 'npmrc', 'slicc-oauth'];\n\nconst obj = (value: unknown): value is Json =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\nconst str = (value: unknown): value is string => typeof value === 'string';\nconst full = (value: unknown): value is string => str(value) && value !== '';\nconst count = (value: unknown) => Number.isInteger(value) && (value as number) >= 0;\nconst amount = (value: unknown) =>\n typeof value === 'number' && Number.isFinite(value) && value >= 0;\nconst iso = (value: unknown) =>\n str(value) &&\n /^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}/.test(value) &&\n !Number.isNaN(Date.parse(value));\nconst maybe = (value: unknown, check: (value: unknown) => boolean) =>\n value === undefined || value === null || check(value);\n\nfunction need(ok: boolean, error: string): asserts ok {\n if (!ok) throw new ImportError(error);\n}\n\nfunction oneOf(value: unknown, allowed: readonly string[], label: string) {\n need(str(value) && allowed.includes(value), `${label} must be one of ${allowed.join(', ')}`);\n}\n\nfunction list(value: unknown, label: string, check: (item: Json, path: string) => void) {\n need(Array.isArray(value), `${label} must be an array`);\n value.forEach((item, at) => {\n need(obj(item), `${label}[${at}] must be an object`);\n check(item, `${label}[${at}]`);\n });\n}\n\nfunction block(item: Json, path: string) {\n oneOf(item.type, ['text', 'tool-call', 'attachment-ref'], `${path}.type`);\n if (item.type === 'text') need(str(item.text), `${path}.text must be a string`);\n else if (item.type === 'tool-call')\n need(\n full(item.id) && full(item.name) && 'input' in item,\n `${path} needs an id, a name and an input`\n );\n else need(full(item.attachmentId), `${path}.attachmentId must be a non-empty string`);\n}\n\nconst TOKENS = ['input', 'output', 'cacheRead', 'cacheWrite', 'totalTokens'];\nconst COSTS = ['input', 'output', 'cacheRead', 'cacheWrite', 'total'];\n\nfunction message(item: Json, path: string) {\n oneOf(item.role, ['user', 'assistant', 'tool-result'], `${path}.role`);\n if (item.role === 'tool-result') need(full(item.toolCallId), `${path}.toolCallId must be set`);\n need(str(item.id), `${path}.id must be a string`);\n need(\n Number.isInteger(item.sequence) && (item.sequence as number) >= 1,\n `${path}.sequence must be a positive integer`\n );\n need(iso(item.timestamp), `${path}.timestamp must be an ISO 8601 date-time`);\n list(item.content, `${path}.content`, block);\n const usage = item.usage;\n if (usage === undefined) return;\n need(\n obj(usage) &&\n TOKENS.every((key) => count(usage[key])) &&\n obj(usage.cost) &&\n COSTS.every((key) => amount((usage.cost as Json)[key])),\n `${path}.usage is malformed`\n );\n}\n\nfunction attachment(item: Json, path: string) {\n const fields = [\n 'id',\n 'path',\n 'originalName',\n 'mimeType',\n 'sha256',\n 'sourceConversationId',\n 'sourceMessageId',\n ];\n need(\n fields.every((key) => str(item[key])),\n `${path} needs ${fields.join(', ')}`\n );\n need(\n typeof item.byteLength === 'number' && typeof item.present === 'boolean',\n `${path} needs byteLength and present`\n );\n oneOf(item.handling, ['text-redacted', 'binary-unchanged'], `${path}.handling`);\n if (item.present)\n need(\n item.path !== '' &&\n SHA.test(item.sha256 as string) &&\n count(item.byteLength) &&\n item.missingReason === undefined,\n `${path} is present but malformed`\n );\n else {\n need(\n item.path === '' && item.sha256 === '' && item.byteLength === 0,\n `${path} is missing but has a file`\n );\n oneOf(item.missingReason, REASONS.slice(4, 6), `${path}.missingReason`);\n }\n}\n\nfunction redaction(item: Json, path: string) {\n need(str(item.id) && str(item.category) && obj(item.target), `${path} is malformed`);\n oneOf(\n item.detector,\n ['known-secret', 'credential-pattern', 'pre-obfuscated'],\n `${path}.detector`\n );\n const target = item.target as Json;\n oneOf(target.kind, ['json', 'attachment'], `${path}.target.kind`);\n if (target.kind === 'json')\n need(\n str(target.pointer) && (target.pointer === '' || target.pointer.startsWith('/')),\n `${path}.target.pointer is not a JSON pointer`\n );\n else need(full(target.attachmentId), `${path}.target.attachmentId must be set`);\n}\n\nfunction sections(doc: Json) {\n need(doc.schemaVersion === 1, 'schemaVersion must equal 1');\n const exported = doc.export;\n need(\n obj(exported) &&\n str(exported.id) &&\n str(exported.generatedAt) &&\n exported.format === 'slicc-transcript' &&\n obj(exported.producer) &&\n exported.producer.application === 'slicc' &&\n str(exported.producer.version),\n 'export is malformed'\n );\n const session = doc.session;\n need(\n obj(session) && str(session.id) && str(session.title) && obj(session.completeness),\n 'session is malformed'\n );\n oneOf(session.state, ['active', 'frozen'], 'session.state');\n const completeness = session.completeness as Json;\n oneOf(completeness.status, ['complete', 'partial'], 'session.completeness.status');\n need(\n Array.isArray(completeness.missing) &&\n completeness.missing.every((reason) => REASONS.includes(reason)),\n 'session.completeness.missing is malformed'\n );\n const privacy = doc.privacy;\n need(\n obj(privacy) &&\n privacy.reasoningExcluded === true &&\n count(privacy.excludedReasoningBlocks) &&\n privacy.binaryAttachments === 'included-unchanged' &&\n obj(privacy.redactionCounts),\n 'privacy is malformed'\n );\n list(privacy.redactions, 'privacy.redactions', redaction);\n list(doc.conversations, 'conversations', (item, path) => {\n need(str(item.id) && str(item.name), `${path} needs an id and a name`);\n oneOf(item.kind, ['cone', 'scoop'], `${path}.kind`);\n list(item.messages, `${path}.messages`, message);\n });\n list(doc.delegations, 'delegations', (item, path) =>\n need(str(item.sourceConversationId) && str(item.targetConversationId), `${path} is malformed`)\n );\n list(doc.attachments, 'attachments', attachment);\n}\n\nfunction relations(doc: Json) {\n const conversations = new Map<string, { messages: Set<string>; calls: Set<string> }>();\n const messages = new Set<string>();\n const calls = new Set<string>();\n const results: string[] = [];\n const refs: string[] = [];\n for (const conversation of doc.conversations as Json[]) {\n const id = conversation.id as string;\n need(!conversations.has(id), `duplicate conversation id \"${id}\"`);\n const own = { messages: new Set<string>(), calls: new Set<string>() };\n conversations.set(id, own);\n let previous = 0;\n for (const item of conversation.messages as V6Message[]) {\n need(!messages.has(item.id), `duplicate message id \"${item.id}\"`);\n need(\n item.sequence > previous,\n `sequences in conversation \"${id}\" must be strictly increasing`\n );\n previous = item.sequence;\n messages.add(item.id);\n own.messages.add(item.id);\n if (item.role === 'tool-result') results.push(item.toolCallId as string);\n for (const part of item.content)\n if (part.type === 'tool-call') {\n calls.add(part.id);\n own.calls.add(part.id);\n } else if (part.type === 'attachment-ref') refs.push(part.attachmentId);\n }\n }\n for (const id of results)\n need(calls.has(id), `tool-result message references unknown toolCallId \"${id}\"`);\n const attached = new Set((doc.attachments as Json[]).map((item) => item.id as string));\n for (const id of refs)\n need(attached.has(id), `attachment-ref references unknown attachmentId \"${id}\"`);\n for (const item of doc.attachments as Json[])\n need(\n conversations\n .get(item.sourceConversationId as string)\n ?.messages.has(item.sourceMessageId as string) === true,\n `attachment ${item.id as string} comes from an unknown message`\n );\n for (const item of doc.delegations as Json[]) {\n const source = conversations.get(item.sourceConversationId as string);\n need(\n source !== undefined && conversations.has(item.targetConversationId as string),\n 'a delegation names an unknown conversation'\n );\n need(\n !full(item.toolCallId) || source.calls.has(item.toolCallId),\n 'a delegation names an unknown tool call'\n );\n }\n for (const item of (doc.privacy as Json).redactions as Json[]) {\n const target = item.target as Json;\n need(\n target.kind !== 'attachment' || attached.has(target.attachmentId as string),\n 'a redaction names an unknown attachment'\n );\n }\n}\n\nexport function checkTranscript(value: unknown): Transcript {\n need(obj(value), 'document must be a non-null object');\n sections(value);\n relations(value);\n return value as unknown as Transcript;\n}\n\nfunction named(item: Json, path: string) {\n need(\n str(item.key) && str(item.name) && FOLDER.test(String(item.folder)),\n `${path} needs a key, a name and a folder`\n );\n need(maybe(item.conversation, str), `${path}.conversation must be a string`);\n}\n\nexport const DIRECTORY_ROOT = '/slicc-v6-upgrade';\nexport const SOURCE_ROOT = '/slicc-fs/';\nconst SIDECAR = '/slicc-fs/.metadata.json';\nconst MOVABLE = ['files/', 'skills/', 'sprinkles/'];\n\nexport function safeSource(path: string): boolean {\n if (!path.startsWith(SOURCE_ROOT) || path === SIDECAR) return false;\n const rest = path.slice(SOURCE_ROOT.length);\n return (\n !/\\\\|\\0/.test(rest) &&\n rest.split('/').every((part) => part !== '' && part !== '.' && part !== '..')\n );\n}\n\nfunction sources(value: Json, version: 1 | 2) {\n const seen = new Set<string>();\n for (const [at, file] of (value.files as Json[]).entries()) {\n if (file.source === undefined) continue;\n need(version === 2, `files[${at}].source needs version 2, the directory form`);\n need(\n str(file.source) && safeSource(file.source),\n `files[${at}].source must be a path under ${SOURCE_ROOT}`\n );\n need(\n MOVABLE.some((top) => String(file.path).startsWith(top)),\n `files[${at}] can't stay in place: only ${MOVABLE.join(', ')} entries can`\n );\n need(!seen.has(file.source), `files moves ${file.source} twice`);\n seen.add(file.source);\n }\n if (version === 2)\n need(\n (value.skipped as Json[]).every((item) => item.reason !== 'archive-limit'),\n 'a directory form has no archive-limit skips'\n );\n}\n\nfunction manifestLists(value: Json) {\n list(value.cones, 'cones', (cone, path) => {\n named(cone, path);\n need(maybe(cone.transcript, str) && maybe(cone.memory, str), `${path} is malformed`);\n list(cone.scoops, `${path}.scoops`, named);\n });\n list(value.frozen, 'frozen', (item, path) =>\n need(\n str(item.id) && str(item.title) && str(item.transcript) && maybe(item.frozenAt, iso),\n `${path} is malformed`\n )\n );\n for (const key of ['skills', 'sprinkles'])\n list(value[key], key, (item, path) =>\n need(str(item.name) && str(item.path), `${path} is malformed`)\n );\n list(value.files, 'files', (item, path) =>\n need(\n str(item.path) && count(item.size) && SHA.test(String(item.sha256)),\n `${path} is malformed`\n )\n );\n list(value.skipped, 'skipped', (item, path) =>\n need(str(item.path) && str(item.reason), `${path} is malformed`)\n );\n list(value.flagged, 'flagged', (item, path) => {\n need(str(item.path) && count(item.size), `${path} is malformed`);\n oneOf(item.rule, RULES, `${path}.rule`);\n });\n list(value.mcp ?? [], 'mcp', (item, path) =>\n need(str(item.name) && str(item.url), `${path} is malformed`)\n );\n for (const key of ['providers', 'secrets'])\n need(\n Array.isArray(value[key] ?? []) && ((value[key] as unknown[] | undefined) ?? []).every(str),\n `${key} must be strings`\n );\n}\n\nexport function checkManifest(value: unknown, version: 1 | 2 = 1): Manifest {\n need(obj(value) && value.format === 'slicc-profile', 'this is not a SLICC 6 profile export');\n need(\n !(typeof value.version === 'number' && value.version > 2),\n 'This export is from a newer SLICC 6; update seven.'\n );\n need(\n value.version !== 2 || version === 2,\n \"this is SLICC 6's directory form; import it with freezer import --in-place\"\n );\n need(value.version === version, `the export version must be ${version}`);\n need(\n str(value.exportId) && /^[A-Za-z0-9-]{1,64}$/.test(value.exportId),\n 'exportId must be a UUID'\n );\n need(\n obj(value.producer) && str(value.producer.slicc) && str(value.producer.origin),\n 'producer is malformed'\n );\n need(\n iso(value.createdAt) && maybe(value.licks, str) && maybe(value.gitconfig, str),\n 'createdAt, licks or gitconfig is malformed'\n );\n const part = value.part as Json | undefined;\n need(version === 1 || part === undefined, 'a directory form is never split into parts');\n need(\n part === undefined ||\n (obj(part) &&\n count(part.index) &&\n (part.index as number) >= 1 &&\n (part.index as number) <= (part.of as number)),\n 'part is malformed'\n );\n manifestLists(value);\n sources(value, version);\n const folders = (value.cones as Manifest['cones']).flatMap((cone) => [\n `cone:${cone.folder}`,\n ...cone.scoops.map((scoop) => `scoop:${scoop.folder}`),\n ]);\n need(new Set(folders).size === folders.length, 'two cones or two scoops share a folder');\n return value as unknown as Manifest;\n}\n\nconst optional = (value: unknown) => value === undefined || str(value);\nconst target = (value: unknown) => maybe(value, (folder) => FOLDER.test(String(folder)));\n\nexport function checkLicks(value: unknown): Licks {\n need(obj(value), 'licks.json must be an object');\n list(value.crontasks, 'crontasks', (item, path) =>\n need(\n str(item.name) && str(item.cron) && target(item.targetFolder) && optional(item.filter),\n `${path} is malformed`\n )\n );\n list(value.tasks, 'tasks', (item, path) => {\n need(\n str(item.groupFolder) && str(item.prompt) && str(item.scheduleValue),\n `${path} is malformed`\n );\n oneOf(item.scheduleType, ['cron', 'interval', 'once'], `${path}.scheduleType`);\n });\n list(value.webhooks, 'webhooks', (item, path) =>\n need(\n str(item.name) && target(item.targetFolder) && optional(item.filter),\n `${path} is malformed`\n )\n );\n return value as unknown as Licks;\n}\n\nexport function lickName(name: string, fallback: string): string {\n const clean = name\n .toLowerCase()\n .replace(/[^a-z0-9._-]+/g, '-')\n .replace(/^[^a-z0-9]+/, '')\n .slice(0, 64);\n return clean || fallback;\n}\n\nexport function skillName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9-]+/g, '-')\n .replace(/-{2,}/g, '-')\n .replace(/^-+|-+$/g, '')\n .slice(0, 64)\n .replace(/-+$/, '');\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["target"]
|
|
7
7
|
}
|
package/dist/freezer/v6-write.js
CHANGED
|
@@ -12,8 +12,16 @@ function done(result, what) {
|
|
|
12
12
|
if (!result.ok) throw new ImportError(`couldn't write ${what}: ${result.error.message}`);
|
|
13
13
|
return result.value;
|
|
14
14
|
}
|
|
15
|
+
const CHUNK = 200;
|
|
16
|
+
function chunks(items) {
|
|
17
|
+
const out = [];
|
|
18
|
+
for (let at = 0; at < items.length; at += CHUNK) out.push(items.slice(at, at + CHUNK));
|
|
19
|
+
return out;
|
|
20
|
+
}
|
|
15
21
|
class Writer {
|
|
16
22
|
#undo = [];
|
|
23
|
+
#modes = /* @__PURE__ */ new Map();
|
|
24
|
+
#moved = [];
|
|
17
25
|
env;
|
|
18
26
|
context;
|
|
19
27
|
signal;
|
|
@@ -66,6 +74,66 @@ class Writer {
|
|
|
66
74
|
done(await env.writeFile(path, bytes, this.context), path);
|
|
67
75
|
return true;
|
|
68
76
|
}
|
|
77
|
+
async remember(paths) {
|
|
78
|
+
for (const part of chunks(paths)) {
|
|
79
|
+
const out = await this.out(`stat -c '%u:%g %a %n' -- ${part.map(quote).join(" ")}`);
|
|
80
|
+
for (const line of out.split("\n").filter(Boolean)) {
|
|
81
|
+
const [owner = "", mode = "", ...name] = line.split(" ");
|
|
82
|
+
this.#modes.set(name.join(" "), `${owner} ${mode}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
async #restore() {
|
|
87
|
+
const groups = /* @__PURE__ */ new Map();
|
|
88
|
+
for (const path of this.#moved) {
|
|
89
|
+
const mode = this.#modes.get(path);
|
|
90
|
+
if (mode) groups.set(mode, [...groups.get(mode) ?? [], path]);
|
|
91
|
+
}
|
|
92
|
+
for (const [both, paths] of groups) {
|
|
93
|
+
const [owner, mode] = both.split(" ");
|
|
94
|
+
for (const part of chunks(paths)) {
|
|
95
|
+
const list = part.map(quote).join(" ");
|
|
96
|
+
await this.env.exec(
|
|
97
|
+
`chown ${quote(owner)} -- ${list} && chmod ${quote(mode)} -- ${list}`,
|
|
98
|
+
void 0,
|
|
99
|
+
BACKGROUND_CONTEXT
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async move(from, to, fresh) {
|
|
105
|
+
this.check();
|
|
106
|
+
if (!this.#moved.length) this.later(() => this.#restore());
|
|
107
|
+
await this.direct(to);
|
|
108
|
+
if (!fresh && !await this.tree(dirname(to))) {
|
|
109
|
+
const old = await this.env.readBinaryFile(to, this.context);
|
|
110
|
+
this.later(
|
|
111
|
+
() => old.ok ? this.env.writeFile(to, old.value, BACKGROUND_CONTEXT) : this.env.remove(to, { force: true }, BACKGROUND_CONTEXT)
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
done(await this.env.createDir(dirname(to), { recursive: true }, this.context), dirname(to));
|
|
115
|
+
done(await this.env.renameFile(from, to, this.context), to);
|
|
116
|
+
this.#moved.push(from);
|
|
117
|
+
this.later(() => this.env.renameFile(to, from, BACKGROUND_CONTEXT));
|
|
118
|
+
}
|
|
119
|
+
async out(command) {
|
|
120
|
+
let out = "";
|
|
121
|
+
let err = "";
|
|
122
|
+
const ran = await this.env.exec(
|
|
123
|
+
command,
|
|
124
|
+
{
|
|
125
|
+
onOutput: (text, _context, info) => {
|
|
126
|
+
if (info.stream === "stderr") err += text;
|
|
127
|
+
else out += text;
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
this.context
|
|
131
|
+
);
|
|
132
|
+
if (!ran.ok) throw new ImportError(`${command.split(" ")[0]}: ${ran.error.message}`);
|
|
133
|
+
if (ran.value.exitCode !== 0)
|
|
134
|
+
throw new ImportError(`${command.split(" ")[0]}: ${err.trim() || "it failed"}`);
|
|
135
|
+
return out;
|
|
136
|
+
}
|
|
69
137
|
async sh(command) {
|
|
70
138
|
let err = "";
|
|
71
139
|
const ran = await this.env.exec(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/freezer/v6-write.ts"],
|
|
4
|
-
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ExecutionEnv, Result } from '@earendil-works/pi-durable/env';\nimport { quote } from '../kernel/env.ts';\nimport { dirname } from '../kernel/paths.ts';\nimport { readTable, sendCommand, writeTable } from '../licks/crontab.ts';\nimport type { LickTarget } from '../licks/lick.ts';\nimport { byteLength, MAX_BYTES, MAX_LINES } from '../memory/format.ts';\nimport { ImportError } from './zip.ts';\n\nconst encoder = new TextEncoder();\n\nexport function same(a: Uint8Array, b: Uint8Array): boolean {\n return a.length === b.length && a.every((byte, at) => byte === b[at]);\n}\n\nfunction done<T>(result: Result<T, { message: string }>, what: string): T {\n if (!result.ok) throw new ImportError(`couldn't write ${what}: ${result.error.message}`);\n return result.value;\n}\n\nexport class Writer {\n readonly #undo: (() => Promise<unknown>)[] = [];\n readonly env: ExecutionEnv;\n readonly context: Context;\n readonly signal: AbortSignal;\n\n constructor(env: ExecutionEnv, context: Context, signal: AbortSignal) {\n this.env = env;\n this.context = context;\n this.signal = signal;\n }\n\n check(): void {\n if (this.signal.aborted) throw new ImportError('the import was cancelled');\n }\n\n later(step: () => Promise<unknown>): void {\n this.#undo.push(step);\n }\n\n async exists(path: string, env = this.env): Promise<boolean> {\n const found = await env.exists(path, this.context);\n return found.ok && found.value;\n }\n\n async tree(root: string, env = this.env): Promise<boolean> {\n let top: string | undefined;\n for (let dir = root; dir !== '/' && !(await this.exists(dir, env)); dir = dirname(dir))\n top = dir;\n if (top === undefined) return false;\n const gone = top;\n this.later(() => env.remove(gone, { recursive: true, force: true }, BACKGROUND_CONTEXT));\n return true;\n }\n\n readonly #real = new Set<string>(['/']);\n\n async direct(path: string): Promise<void> {\n for (let at = dirname(path); !this.#real.has(at); at = dirname(at)) {\n const real = await this.env.canonicalPath(at, this.context);\n if (!real.ok) continue;\n if (real.value !== at)\n throw new ImportError(`${at} leads through a symlink, and the import won't write there`);\n this.#real.add(at);\n break;\n }\n }\n\n async put(path: string, content: Uint8Array | string, fresh: boolean, env = this.env) {\n this.check();\n if (env === this.env) await this.direct(path);\n const bytes = typeof content === 'string' ? encoder.encode(content) : content;\n if (!fresh && !(await this.tree(dirname(path), env))) {\n const old = await env.readBinaryFile(path, this.context);\n if (old.ok && same(old.value, bytes)) return false;\n this.later(() =>\n old.ok\n ? env.writeFile(path, old.value, BACKGROUND_CONTEXT)\n : env.remove(path, { force: true }, BACKGROUND_CONTEXT)\n );\n }\n done(await env.writeFile(path, bytes, this.context), path);\n return true;\n }\n\n async sh(command: string): Promise<void> {\n let err = '';\n const ran = await this.env.exec(\n command,\n {\n onOutput: (text, _context, info) => {\n if (info.stream === 'stderr') err += text;\n },\n },\n this.context\n );\n const failed = ran.ok\n ? ran.value.exitCode === 0\n ? ''\n : err.trim() || 'it failed'\n : ran.error.message;\n if (failed) throw new ImportError(`${command.split(' ')[0]}: ${failed}`);\n }\n\n async rollback(): Promise<void> {\n for (const step of this.#undo.reverse()) await step().catch(() => undefined);\n }\n}\n\nexport async function ownTree(writer: Writer, user: string, home: string, roots: Iterable<string>) {\n for (const root of roots) {\n const parents: string[] = [];\n for (let at = root.lastIndexOf('/'); at > home.length; at = root.lastIndexOf('/', at - 1))\n parents.push(quote(root.slice(0, at)));\n const owner = quote(`${user}:${user}`);\n const lift = parents.length\n ? `chown ${owner} ${parents.join(' ')} && chmod 700 ${parents.join(' ')} && `\n : '';\n await writer.sh(`${lift}chown -R ${owner} ${quote(root)} && chmod -R u=rwX,go= ${quote(root)}`);\n }\n}\n\nconst fits = (text: string) =>\n byteLength(text) <= MAX_BYTES && text.split('\\n').length <= MAX_LINES;\n\nexport async function remember(\n writer: Writer,\n file: string,\n text: string,\n rest: { file: string; date: string }\n): Promise<'merged' | 'aside' | 'none'> {\n const body = text.replace(/^#{1,2}(\\s)/gm, '###$1').trim();\n if (!body) return 'none';\n await writer.direct(file);\n const real = await writer.env.canonicalPath(file, writer.context);\n if (real.ok && real.value !== file)\n throw new ImportError(`${file} is a symlink, and the import won't write memory through it`);\n const read = await writer.env.readTextFile(file, writer.context);\n const before = read.ok ? read.value.trimEnd() : '';\n if (before.includes(body)) return 'none';\n const joined = (section: string) => `${before}${before ? '\\n\\n' : ''}${section}\\n`;\n const heading = `## Imported from SLICC 6 (${rest.date})\\n\\n`;\n const whole = joined(`${heading}${body}`);\n if (fits(whole)) return (await writer.put(file, whole, false)) ? 'merged' : 'none';\n await writer.put(rest.file, `${text.trimEnd()}\\n`, false);\n const lines = body.split('\\n');\n const tail = `The rest is in ${rest.file}.`;\n const cut = () => joined(`${heading}${[...lines, '', tail].join('\\n')}`);\n while (lines.length && !fits(cut())) lines.pop();\n if (!lines.length) return 'aside';\n await writer.put(file, cut(), false);\n return 'merged';\n}\n\nexport type CronLine = {\n name: string;\n schedule: string;\n target: LickTarget;\n message: string;\n filter?: string;\n};\n\nexport async function installCrons(\n writer: Writer,\n user: string,\n crons: readonly CronLine[],\n date: string\n) {\n const before = await readTable(writer.env, user, writer.context);\n if (typeof before !== 'string') throw new ImportError(`crontab -u ${user}: ${before.error}`);\n const blocks = crons.map(\n (cron) => `# # name: ${cron.name}\\n# ${cron.schedule} ${sendCommand(cron.target, cron.message)}`\n );\n const changed = blocks.filter((block) => !before.includes(block)).length;\n if (!changed) return 0;\n const head = `# SLICC 6 crons, imported off on ${date}. Remove \"# \" from a job's two lines to turn it on.`;\n const notes = crons\n .filter((cron) => cron.filter)\n .map(\n (cron) =>\n `# ${cron.name} had a SLICC 6 filter, not imported: ${(cron.filter as string).replace(/\\s+/g, ' ')}`\n );\n const kept = withoutImported(before, new Set(crons.map((cron) => cron.name)));\n const table = `${[...kept, head, ...notes, ...blocks].join('\\n')}\\n`;\n writer.later(async () =>\n before\n ? writeTable(writer.env, user, before, BACKGROUND_CONTEXT)\n : writer.env.exec(`crontab -u ${quote(user)} -r`, undefined, BACKGROUND_CONTEXT)\n );\n const ran = await writeTable(writer.env, user, table, writer.context);\n if (ran.code !== 0) throw new ImportError(`crontab -u ${user}: ${ran.err.trim()}`);\n return changed;\n}\n\nexport function withoutImported(table: string, names: ReadonlySet<string>): string[] {\n const lines = table.split('\\n');\n if (lines.at(-1) === '') lines.pop();\n const out: string[] = [];\n for (let at = 0; at < lines.length; at++) {\n const line = lines[at] as string;\n const named = /^# # name: (\\S+)$/.exec(line);\n if (named && names.has(named[1] as string)) at++;\n else if (\n !line.startsWith('# SLICC 6 crons, imported off on ') &&\n !/^# (\\S+) had a SLICC 6 filter/.test(line)\n )\n out.push(line);\n }\n return out;\n}\n\nexport function userSection(text: string): string {\n const out: string[] = [];\n let inside = false;\n for (const line of text.split('\\n')) {\n if (/^\\s*\\[/.test(line)) inside = /^\\s*\\[user\\]\\s*$/i.test(line);\n if (inside && /^\\s*(\\[user\\]|(name|email)\\s*=)/i.test(line)) out.push(line.trim());\n }\n return out.length > 1\n ? `${out[0]}\\n${out\n .slice(1)\n .map((line) => `\\t${line}`)\n .join('\\n')}\\n`\n : '';\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type { Context } from '@earendil-works/chord';\nimport { BACKGROUND_CONTEXT } from '@earendil-works/chord/context';\nimport type { ExecutionEnv, Result } from '@earendil-works/pi-durable/env';\nimport { quote } from '../kernel/env.ts';\nimport { dirname } from '../kernel/paths.ts';\nimport { readTable, sendCommand, writeTable } from '../licks/crontab.ts';\nimport type { LickTarget } from '../licks/lick.ts';\nimport { byteLength, MAX_BYTES, MAX_LINES } from '../memory/format.ts';\nimport { ImportError } from './zip.ts';\n\nconst encoder = new TextEncoder();\n\nexport function same(a: Uint8Array, b: Uint8Array): boolean {\n return a.length === b.length && a.every((byte, at) => byte === b[at]);\n}\n\nfunction done<T>(result: Result<T, { message: string }>, what: string): T {\n if (!result.ok) throw new ImportError(`couldn't write ${what}: ${result.error.message}`);\n return result.value;\n}\n\nconst CHUNK = 200;\n\nfunction chunks<T>(items: readonly T[]): T[][] {\n const out: T[][] = [];\n for (let at = 0; at < items.length; at += CHUNK) out.push(items.slice(at, at + CHUNK));\n return out;\n}\n\nexport class Writer {\n readonly #undo: (() => Promise<unknown>)[] = [];\n readonly #modes = new Map<string, string>();\n readonly #moved: string[] = [];\n readonly env: ExecutionEnv;\n readonly context: Context;\n readonly signal: AbortSignal;\n\n constructor(env: ExecutionEnv, context: Context, signal: AbortSignal) {\n this.env = env;\n this.context = context;\n this.signal = signal;\n }\n\n check(): void {\n if (this.signal.aborted) throw new ImportError('the import was cancelled');\n }\n\n later(step: () => Promise<unknown>): void {\n this.#undo.push(step);\n }\n\n async exists(path: string, env = this.env): Promise<boolean> {\n const found = await env.exists(path, this.context);\n return found.ok && found.value;\n }\n\n async tree(root: string, env = this.env): Promise<boolean> {\n let top: string | undefined;\n for (let dir = root; dir !== '/' && !(await this.exists(dir, env)); dir = dirname(dir))\n top = dir;\n if (top === undefined) return false;\n const gone = top;\n this.later(() => env.remove(gone, { recursive: true, force: true }, BACKGROUND_CONTEXT));\n return true;\n }\n\n readonly #real = new Set<string>(['/']);\n\n async direct(path: string): Promise<void> {\n for (let at = dirname(path); !this.#real.has(at); at = dirname(at)) {\n const real = await this.env.canonicalPath(at, this.context);\n if (!real.ok) continue;\n if (real.value !== at)\n throw new ImportError(`${at} leads through a symlink, and the import won't write there`);\n this.#real.add(at);\n break;\n }\n }\n\n async put(path: string, content: Uint8Array | string, fresh: boolean, env = this.env) {\n this.check();\n if (env === this.env) await this.direct(path);\n const bytes = typeof content === 'string' ? encoder.encode(content) : content;\n if (!fresh && !(await this.tree(dirname(path), env))) {\n const old = await env.readBinaryFile(path, this.context);\n if (old.ok && same(old.value, bytes)) return false;\n this.later(() =>\n old.ok\n ? env.writeFile(path, old.value, BACKGROUND_CONTEXT)\n : env.remove(path, { force: true }, BACKGROUND_CONTEXT)\n );\n }\n done(await env.writeFile(path, bytes, this.context), path);\n return true;\n }\n\n async remember(paths: readonly string[]): Promise<void> {\n for (const part of chunks(paths)) {\n const out = await this.out(`stat -c '%u:%g %a %n' -- ${part.map(quote).join(' ')}`);\n for (const line of out.split('\\n').filter(Boolean)) {\n const [owner = '', mode = '', ...name] = line.split(' ');\n this.#modes.set(name.join(' '), `${owner} ${mode}`);\n }\n }\n }\n\n async #restore(): Promise<void> {\n const groups = new Map<string, string[]>();\n for (const path of this.#moved) {\n const mode = this.#modes.get(path);\n if (mode) groups.set(mode, [...(groups.get(mode) ?? []), path]);\n }\n for (const [both, paths] of groups) {\n const [owner, mode] = both.split(' ') as [string, string];\n for (const part of chunks(paths)) {\n const list = part.map(quote).join(' ');\n await this.env.exec(\n `chown ${quote(owner)} -- ${list} && chmod ${quote(mode)} -- ${list}`,\n undefined,\n BACKGROUND_CONTEXT\n );\n }\n }\n }\n\n async move(from: string, to: string, fresh: boolean): Promise<void> {\n this.check();\n if (!this.#moved.length) this.later(() => this.#restore());\n await this.direct(to);\n if (!fresh && !(await this.tree(dirname(to)))) {\n const old = await this.env.readBinaryFile(to, this.context);\n this.later(() =>\n old.ok\n ? this.env.writeFile(to, old.value, BACKGROUND_CONTEXT)\n : this.env.remove(to, { force: true }, BACKGROUND_CONTEXT)\n );\n }\n done(await this.env.createDir(dirname(to), { recursive: true }, this.context), dirname(to));\n done(await this.env.renameFile(from, to, this.context), to);\n this.#moved.push(from);\n this.later(() => this.env.renameFile(to, from, BACKGROUND_CONTEXT));\n }\n\n async out(command: string): Promise<string> {\n let out = '';\n let err = '';\n const ran = await this.env.exec(\n command,\n {\n onOutput: (text, _context, info) => {\n if (info.stream === 'stderr') err += text;\n else out += text;\n },\n },\n this.context\n );\n if (!ran.ok) throw new ImportError(`${command.split(' ')[0]}: ${ran.error.message}`);\n if (ran.value.exitCode !== 0)\n throw new ImportError(`${command.split(' ')[0]}: ${err.trim() || 'it failed'}`);\n return out;\n }\n\n async sh(command: string): Promise<void> {\n let err = '';\n const ran = await this.env.exec(\n command,\n {\n onOutput: (text, _context, info) => {\n if (info.stream === 'stderr') err += text;\n },\n },\n this.context\n );\n const failed = ran.ok\n ? ran.value.exitCode === 0\n ? ''\n : err.trim() || 'it failed'\n : ran.error.message;\n if (failed) throw new ImportError(`${command.split(' ')[0]}: ${failed}`);\n }\n\n async rollback(): Promise<void> {\n for (const step of this.#undo.reverse()) await step().catch(() => undefined);\n }\n}\n\nexport async function ownTree(writer: Writer, user: string, home: string, roots: Iterable<string>) {\n for (const root of roots) {\n const parents: string[] = [];\n for (let at = root.lastIndexOf('/'); at > home.length; at = root.lastIndexOf('/', at - 1))\n parents.push(quote(root.slice(0, at)));\n const owner = quote(`${user}:${user}`);\n const lift = parents.length\n ? `chown ${owner} ${parents.join(' ')} && chmod 700 ${parents.join(' ')} && `\n : '';\n await writer.sh(`${lift}chown -R ${owner} ${quote(root)} && chmod -R u=rwX,go= ${quote(root)}`);\n }\n}\n\nconst fits = (text: string) =>\n byteLength(text) <= MAX_BYTES && text.split('\\n').length <= MAX_LINES;\n\nexport async function remember(\n writer: Writer,\n file: string,\n text: string,\n rest: { file: string; date: string }\n): Promise<'merged' | 'aside' | 'none'> {\n const body = text.replace(/^#{1,2}(\\s)/gm, '###$1').trim();\n if (!body) return 'none';\n await writer.direct(file);\n const real = await writer.env.canonicalPath(file, writer.context);\n if (real.ok && real.value !== file)\n throw new ImportError(`${file} is a symlink, and the import won't write memory through it`);\n const read = await writer.env.readTextFile(file, writer.context);\n const before = read.ok ? read.value.trimEnd() : '';\n if (before.includes(body)) return 'none';\n const joined = (section: string) => `${before}${before ? '\\n\\n' : ''}${section}\\n`;\n const heading = `## Imported from SLICC 6 (${rest.date})\\n\\n`;\n const whole = joined(`${heading}${body}`);\n if (fits(whole)) return (await writer.put(file, whole, false)) ? 'merged' : 'none';\n await writer.put(rest.file, `${text.trimEnd()}\\n`, false);\n const lines = body.split('\\n');\n const tail = `The rest is in ${rest.file}.`;\n const cut = () => joined(`${heading}${[...lines, '', tail].join('\\n')}`);\n while (lines.length && !fits(cut())) lines.pop();\n if (!lines.length) return 'aside';\n await writer.put(file, cut(), false);\n return 'merged';\n}\n\nexport type CronLine = {\n name: string;\n schedule: string;\n target: LickTarget;\n message: string;\n filter?: string;\n};\n\nexport async function installCrons(\n writer: Writer,\n user: string,\n crons: readonly CronLine[],\n date: string\n) {\n const before = await readTable(writer.env, user, writer.context);\n if (typeof before !== 'string') throw new ImportError(`crontab -u ${user}: ${before.error}`);\n const blocks = crons.map(\n (cron) => `# # name: ${cron.name}\\n# ${cron.schedule} ${sendCommand(cron.target, cron.message)}`\n );\n const changed = blocks.filter((block) => !before.includes(block)).length;\n if (!changed) return 0;\n const head = `# SLICC 6 crons, imported off on ${date}. Remove \"# \" from a job's two lines to turn it on.`;\n const notes = crons\n .filter((cron) => cron.filter)\n .map(\n (cron) =>\n `# ${cron.name} had a SLICC 6 filter, not imported: ${(cron.filter as string).replace(/\\s+/g, ' ')}`\n );\n const kept = withoutImported(before, new Set(crons.map((cron) => cron.name)));\n const table = `${[...kept, head, ...notes, ...blocks].join('\\n')}\\n`;\n writer.later(async () =>\n before\n ? writeTable(writer.env, user, before, BACKGROUND_CONTEXT)\n : writer.env.exec(`crontab -u ${quote(user)} -r`, undefined, BACKGROUND_CONTEXT)\n );\n const ran = await writeTable(writer.env, user, table, writer.context);\n if (ran.code !== 0) throw new ImportError(`crontab -u ${user}: ${ran.err.trim()}`);\n return changed;\n}\n\nexport function withoutImported(table: string, names: ReadonlySet<string>): string[] {\n const lines = table.split('\\n');\n if (lines.at(-1) === '') lines.pop();\n const out: string[] = [];\n for (let at = 0; at < lines.length; at++) {\n const line = lines[at] as string;\n const named = /^# # name: (\\S+)$/.exec(line);\n if (named && names.has(named[1] as string)) at++;\n else if (\n !line.startsWith('# SLICC 6 crons, imported off on ') &&\n !/^# (\\S+) had a SLICC 6 filter/.test(line)\n )\n out.push(line);\n }\n return out;\n}\n\nexport function userSection(text: string): string {\n const out: string[] = [];\n let inside = false;\n for (const line of text.split('\\n')) {\n if (/^\\s*\\[/.test(line)) inside = /^\\s*\\[user\\]\\s*$/i.test(line);\n if (inside && /^\\s*(\\[user\\]|(name|email)\\s*=)/i.test(line)) out.push(line.trim());\n }\n return out.length > 1\n ? `${out[0]}\\n${out\n .slice(1)\n .map((line) => `\\t${line}`)\n .join('\\n')}\\n`\n : '';\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|