agents-inc 0.170.1 → 0.170.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/{chunk-BMRUNMPV.js → chunk-2YA4DDRM.js} +35 -35
- package/dist/chunk-2YA4DDRM.js.map +1 -0
- package/dist/{chunk-44TE3RKH.js → chunk-3ED3KHHD.js} +5 -4
- package/dist/chunk-3ED3KHHD.js.map +1 -0
- package/dist/{chunk-3G7X2WKI.js → chunk-5BNX73OU.js} +18 -38
- package/dist/chunk-5BNX73OU.js.map +1 -0
- package/dist/{chunk-7RDMTR64.js → chunk-66AEVERM.js} +785 -256
- package/dist/chunk-66AEVERM.js.map +1 -0
- package/dist/{chunk-PJWGTNOX.js → chunk-7C3PFRBU.js} +144 -186
- package/dist/chunk-7C3PFRBU.js.map +1 -0
- package/dist/{chunk-52HDHJ7I.js → chunk-AUNRHWH4.js} +32 -21
- package/dist/chunk-AUNRHWH4.js.map +1 -0
- package/dist/{chunk-KOLDW6SF.js → chunk-BBDGYJHX.js} +2 -2
- package/dist/chunk-BBDGYJHX.js.map +1 -0
- package/dist/{chunk-SZYQISA2.js → chunk-ELV5WDS3.js} +43 -29
- package/dist/chunk-ELV5WDS3.js.map +1 -0
- package/dist/{chunk-MQ6CGZNJ.js → chunk-GAKVZNTX.js} +1879 -2019
- package/dist/chunk-GAKVZNTX.js.map +1 -0
- package/dist/chunk-GEMW5RQ2.js +1169 -0
- package/dist/chunk-GEMW5RQ2.js.map +1 -0
- package/dist/{chunk-NQW25DCF.js → chunk-GHHJYNAN.js} +1 -7
- package/dist/chunk-GHHJYNAN.js.map +1 -0
- package/dist/{chunk-WTWMGH2C.js → chunk-HACRR422.js} +2 -2
- package/dist/chunk-HACRR422.js.map +1 -0
- package/dist/{chunk-F2BHT5C4.js → chunk-IWY5IR4F.js} +129 -151
- package/dist/chunk-IWY5IR4F.js.map +1 -0
- package/dist/{chunk-JFLVEFFP.js → chunk-KIK5EZYD.js} +1 -1
- package/dist/chunk-KIK5EZYD.js.map +1 -0
- package/dist/{chunk-USVBYQSQ.js → chunk-O4LN3HFI.js} +16 -6
- package/dist/chunk-O4LN3HFI.js.map +1 -0
- package/dist/{chunk-RIPSGNLU.js → chunk-OCAVW6N5.js} +3 -3
- package/dist/chunk-OCAVW6N5.js.map +1 -0
- package/dist/{chunk-4AAOOAIN.js → chunk-P6CYS4JK.js} +2 -2
- package/dist/chunk-P6CYS4JK.js.map +1 -0
- package/dist/chunk-PLFANHRZ.js +35 -0
- package/dist/chunk-PLFANHRZ.js.map +1 -0
- package/dist/{chunk-6ZRH5RHC.js → chunk-PMUZR4XO.js} +4 -4
- package/dist/chunk-PMUZR4XO.js.map +1 -0
- package/dist/{chunk-F5EBEATU.js → chunk-PSUTNOQ2.js} +34 -46
- package/dist/chunk-PSUTNOQ2.js.map +1 -0
- package/dist/chunk-RIK45Q4I.js +103 -0
- package/dist/chunk-RIK45Q4I.js.map +1 -0
- package/dist/{chunk-HED2DAXZ.js → chunk-THO7LO5B.js} +5 -5
- package/dist/chunk-THO7LO5B.js.map +1 -0
- package/dist/{chunk-OYJQUA3D.js → chunk-YGDWHDOY.js} +31 -13
- package/dist/chunk-YGDWHDOY.js.map +1 -0
- package/dist/{chunk-NCWDK6L7.js → chunk-YXKTY5WM.js} +254 -379
- package/dist/chunk-YXKTY5WM.js.map +1 -0
- package/dist/{chunk-NEZ4OAOL.js → chunk-ZEGM3MVR.js} +3 -5
- package/dist/chunk-ZEGM3MVR.js.map +1 -0
- package/dist/commands/build/marketplace.js +46 -46
- package/dist/commands/build/marketplace.js.map +1 -1
- package/dist/commands/build/plugins.js +25 -28
- package/dist/commands/build/plugins.js.map +1 -1
- package/dist/commands/compile.js +87 -178
- package/dist/commands/compile.js.map +1 -1
- package/dist/commands/doctor.js +510 -360
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/edit.js +451 -357
- package/dist/commands/edit.js.map +1 -1
- package/dist/commands/eject.js +144 -125
- package/dist/commands/eject.js.map +1 -1
- package/dist/commands/init.js +20 -27
- package/dist/commands/list.js +39 -55
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/new/marketplace.js +6 -11
- package/dist/commands/new/marketplace.js.map +1 -1
- package/dist/commands/search.js +35 -32
- package/dist/commands/search.js.map +1 -1
- package/dist/commands/share.js +17 -77
- package/dist/commands/share.js.map +1 -1
- package/dist/commands/uninstall.js +159 -222
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/commands/update.js +9 -32
- package/dist/commands/update.js.map +1 -1
- package/dist/components/common/prompt-confirm.js +2 -2
- package/dist/components/common/removal-plan-confirm.js +2 -2
- package/dist/components/common/scroll-affordance.js +2 -2
- package/dist/components/common/select-list.js +2 -2
- package/dist/components/common/skill-agent-summary.js +4 -4
- package/dist/components/common/spinner.js +2 -4
- package/dist/components/common/summary-panel.js +5 -5
- package/dist/components/common/summary-panel.js.map +1 -1
- package/dist/config-exports.js +7 -3
- package/dist/config-exports.js.map +1 -1
- package/dist/hooks/init.js +18 -19
- package/dist/hooks/init.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/load-agent-defs-6QUUMGHK.js +14 -0
- package/dist/recompile-project-agents-I33KQJFB.js +65 -0
- package/dist/recompile-project-agents-I33KQJFB.js.map +1 -0
- package/dist/{source-loader-C5SQXZXI.js → source-loader-TTJVW2ER.js} +5 -5
- package/dist/src/agents/developer/ai-developer/playbook.md +2 -5
- package/dist/src/agents/developer/api-developer/playbook.md +2 -5
- package/dist/src/agents/developer/cli-developer/playbook.md +2 -5
- package/dist/src/agents/developer/web-developer/playbook.md +2 -5
- package/dist/src/agents/meta/agent-summoner/output.md +2 -2
- package/dist/src/agents/meta/agent-summoner/playbook.md +1 -13
- package/dist/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
- package/dist/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
- package/dist/src/agents/tester/ai-tester/critical-requirements.md +1 -2
- package/dist/src/agents/tester/ai-tester/playbook.md +2 -0
- package/dist/src/agents/tester/api-tester/critical-requirements.md +1 -2
- package/dist/src/agents/tester/api-tester/playbook.md +2 -0
- package/dist/src/agents/tester/cli-tester/critical-requirements.md +1 -2
- package/dist/src/agents/tester/cli-tester/playbook.md +2 -0
- package/dist/src/agents/tester/web-tester/critical-requirements.md +1 -2
- package/dist/src/agents/tester/web-tester/playbook.md +2 -0
- package/package.json +9 -8
- package/src/agents/developer/ai-developer/playbook.md +2 -5
- package/src/agents/developer/api-developer/playbook.md +2 -5
- package/src/agents/developer/cli-developer/playbook.md +2 -5
- package/src/agents/developer/web-developer/playbook.md +2 -5
- package/src/agents/meta/agent-summoner/output.md +2 -2
- package/src/agents/meta/agent-summoner/playbook.md +1 -13
- package/src/agents/meta/codex-keeper/critical-requirements.md +2 -5
- package/src/agents/meta/convention-keeper/critical-requirements.md +2 -4
- package/src/agents/tester/ai-tester/critical-requirements.md +1 -2
- package/src/agents/tester/ai-tester/playbook.md +2 -0
- package/src/agents/tester/api-tester/critical-requirements.md +1 -2
- package/src/agents/tester/api-tester/playbook.md +2 -0
- package/src/agents/tester/cli-tester/critical-requirements.md +1 -2
- package/src/agents/tester/cli-tester/playbook.md +2 -0
- package/src/agents/tester/web-tester/critical-requirements.md +1 -2
- package/src/agents/tester/web-tester/playbook.md +2 -0
- package/src/schemas/project-config.schema.json +0 -3
- package/src/schemas/project-source-config.schema.json +0 -6
- package/dist/chunk-3G7X2WKI.js.map +0 -1
- package/dist/chunk-44TE3RKH.js.map +0 -1
- package/dist/chunk-4AAOOAIN.js.map +0 -1
- package/dist/chunk-52HDHJ7I.js.map +0 -1
- package/dist/chunk-6HNXYYVF.js +0 -373
- package/dist/chunk-6HNXYYVF.js.map +0 -1
- package/dist/chunk-6ZRH5RHC.js.map +0 -1
- package/dist/chunk-7RDMTR64.js.map +0 -1
- package/dist/chunk-BMRUNMPV.js.map +0 -1
- package/dist/chunk-CLPUWOSA.js +0 -46
- package/dist/chunk-CLPUWOSA.js.map +0 -1
- package/dist/chunk-F2BHT5C4.js.map +0 -1
- package/dist/chunk-F5EBEATU.js.map +0 -1
- package/dist/chunk-HED2DAXZ.js.map +0 -1
- package/dist/chunk-JFLVEFFP.js.map +0 -1
- package/dist/chunk-KOLDW6SF.js.map +0 -1
- package/dist/chunk-MQ6CGZNJ.js.map +0 -1
- package/dist/chunk-NCWDK6L7.js.map +0 -1
- package/dist/chunk-NEZ4OAOL.js.map +0 -1
- package/dist/chunk-NIHUOWE4.js +0 -106
- package/dist/chunk-NIHUOWE4.js.map +0 -1
- package/dist/chunk-NQW25DCF.js.map +0 -1
- package/dist/chunk-OYJQUA3D.js.map +0 -1
- package/dist/chunk-PJWGTNOX.js.map +0 -1
- package/dist/chunk-RIPSGNLU.js.map +0 -1
- package/dist/chunk-SZYQISA2.js.map +0 -1
- package/dist/chunk-USVBYQSQ.js.map +0 -1
- package/dist/chunk-V3KTSP3Q.js +0 -940
- package/dist/chunk-V3KTSP3Q.js.map +0 -1
- package/dist/chunk-WTWMGH2C.js.map +0 -1
- package/dist/load-agent-defs-YMDWBFDP.js +0 -14
- package/dist/recompile-project-agents-SZ76WNTW.js +0 -18
- package/dist/source-loader-C5SQXZXI.js.map +0 -1
- /package/dist/{load-agent-defs-YMDWBFDP.js.map → load-agent-defs-6QUUMGHK.js.map} +0 -0
- /package/dist/{recompile-project-agents-SZ76WNTW.js.map → source-loader-TTJVW2ER.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/commands/share.ts","../../src/cli/lib/seed/read-piped-payload.ts","../../src/cli/utils/read-stream.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { isLocalSource } from \"../lib/configuration/config.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { unofferablePlacementsFound } from \"../lib/hosts/configured-placements.js\";\nimport { seedPayloadForInstallation } from \"../lib/seed/installation-payload.js\";\nimport { publishSeedConfig } from \"../lib/seed/publish-seed.js\";\nimport {\n readPipedPayload,\n STDIN_IS_A_TERMINAL,\n type PipedPayload,\n} from \"../lib/seed/read-piped-payload.js\";\nimport {\n providerFlag,\n providerNamedBy,\n refuseAnAmbiguousInstallation,\n} from \"../lib/installation/provider-flag.js\";\nimport { warn } from \"../utils/logger.js\";\nimport { readAllOf } from \"../utils/read-stream.js\";\nimport {\n sharedConfigDestinations,\n sharedIdNamesAFolder,\n sharedSkillsLeftBehind,\n shareRefusesEjectedSkills,\n} from \"../utils/messages.js\";\nimport { typedEntries } from \"../utils/typed-object.js\";\nimport type { SkillId } from \"../types/index.js\";\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\n/** A payload to publish, and what is owed about it once it has an id. */\ntype ShareablePayload = { payload: SeedPayload; caveats: string[] };\n\n/**\n * What an id minted from this installation will not do everywhere, said after the id rather than\n * refused: it still installs everything else.\n *\n * A payload names one marketplace, by the ref `--marketplace` took. A folder is a ref only this\n * machine can follow, and a plugin from any other marketplace is skipped wherever the id is\n * installed.\n */\nfunction caveatsAbout(payload: SeedPayload, leftBehind: readonly SkillId[]): string[] {\n const { marketplace } = payload;\n return [\n ...(isAFolder(marketplace) ? [sharedIdNamesAFolder(marketplace)] : []),\n ...(leftBehind.length > 0 ? [sharedSkillsLeftBehind(leftBehind)] : []),\n ];\n}\n\n/** Whether a payload's marketplace ref is a folder on this machine rather than a repository. */\nfunction isAFolder(marketplace: string | undefined): marketplace is string {\n return marketplace !== undefined && isLocalSource(marketplace);\n}\n\n/** The skills a payload asks the receiver to eject — local copies, editor-added ones included. */\nfunction ejectedSkillsIn(payload: SeedPayload): string[] {\n return typedEntries(payload.skills)\n .filter(([, skill]) => skill.install === \"eject\")\n .map(([id]) => id);\n}\n\nexport default class Share extends BaseCommand {\n static summary = \"Share this installation as an id anyone can install\";\n\n static description =\n \"Turns the skills, sub-agents and per-agent curation installed here into a configuration the agentsinc.sh store holds, and prints the id it was given. Install it elsewhere with 'init --from <id>', or open it in the editor. The id is the configuration's own hash, so sharing an unchanged installation returns the id it already had.\";\n\n static flags = {\n stdin: Flags.boolean({\n description:\n \"Share a configuration piped in on standard input instead of the one installed here\",\n default: false,\n }),\n provider: providerFlag(),\n };\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"cat proposal.json | <%= config.bin %> <%= command.id %> --stdin\",\n ];\n\n /**\n * Read, map, refuse, publish, then say what the id will not do everywhere.\n *\n * Everything that can fail locally fails before the POST. The store's free tier allows a\n * thousand writes a day and reads a hundred times that, so a write is the scarce half — and one\n * spent on a configuration that cannot be installed buys a dead link.\n *\n * The first three steps are `seedPayloadForInstallation`, shared with `edit --ui`: the two\n * commands mint the same id from the same directory and differ only in what they do with it.\n * The one refusal `edit --ui` does not share is of ejected skills — a share carries plugins\n * only, and the editor is where a user goes to turn ejected skills into plugins.\n */\n async run(): Promise<void> {\n const { flags } = await this.parse(Share);\n\n // Only the installation path reads a directory. A piped payload is the CALLER's configuration\n // and no folder on this machine decides anything about it, so neither a scope holding two\n // installations nor a placement this host cannot fill is this run's problem — asking anyway\n // would refuse a `--stdin` share for the state of a directory it never opens.\n if (!flags.stdin) {\n await refuseAnAmbiguousInstallation(\n process.cwd(),\n \"share\",\n providerNamedBy(flags.provider),\n (message) => this.error(message, { exit: EXIT_CODES.INVALID_ARGS }),\n );\n await this.ensureConfigReadable(process.cwd());\n await this.refuseUnofferablePlacements(process.cwd());\n }\n\n const { payload, caveats } = flags.stdin\n ? await this.payloadFromPipe()\n : await this.payloadFromInstallation();\n\n const published = await publishSeedConfig(payload);\n if (!published.ok) {\n this.error(published.error, { exit: EXIT_CODES.ERROR });\n }\n\n this.reportShared(published.id);\n // Through `warn()` from `utils/logger.ts` rather than `this.warn`: oclif hard-wraps at the\n // terminal width, and a caveat names a folder path that does not survive being broken.\n for (const caveat of caveats) warn(caveat);\n }\n\n /**\n * Refuses a configuration asking for a mode/scope cell its own host does not offer, before the\n * payload is built and long before the POST.\n *\n * **`share` is a read path, and the roster that names them missed it.** The list this refusal\n * was built against reads \"`compile`, `edit`, `update` and `doctor`\" and claims to be every\n * command that acts on a configuration it did not just write — while `share` sits beside them\n * reading the same file through `seedPayloadForInstallation`. What it publishes is described as\n * \"the skills, sub-agents and per-agent curation installed HERE\", and a row the host could not\n * place was never installed here at all, so the id would describe an installation that does not\n * exist. `refuseAnAmbiguousInstallation` above is this finding's sibling and was already asked;\n * the two are the pair `doctor`'s Placements row reports together.\n *\n * A refusal rather than a row, like the other three writers, and for a reason of its own: the\n * store's write is the scarce half, and one spent on an installation nothing on this machine\n * will act on buys a link to a misdescription.\n *\n * `uninstall` reads the same file and is deliberately NOT on this roster: a refusal there would\n * make an unofferable installation unremovable, which is a guard that has swallowed its domain.\n */\n private async refuseUnofferablePlacements(cwd: string): Promise<void> {\n const [finding] = await unofferablePlacementsFound(cwd);\n if (finding !== undefined) this.error(finding, { exit: EXIT_CODES.ERROR });\n }\n\n /** The installation in this directory: mapped, refused if it holds ejected skills, announced. */\n private async payloadFromInstallation(): Promise<ShareablePayload> {\n const prepared = await seedPayloadForInstallation(process.cwd());\n if (!prepared.ok) {\n this.error(prepared.error, { exit: EXIT_CODES.ERROR });\n }\n\n this.refuseEjectedSkills(prepared.payload);\n this.log(`Sharing ${prepared.skills} skill(s) across ${prepared.agents} sub-agent(s)...`);\n\n return {\n payload: prepared.payload,\n caveats: caveatsAbout(prepared.payload, prepared.leftBehind),\n };\n }\n\n /**\n * Refuses a share while anything it would send is an ejected (Local) skill.\n *\n * An ejected skill is a copy on this machine, which the user may have edited and an\n * editor-added skill always is, so a share carries plugins only — from a project, that covers\n * the ejected skills it inherits from the global installation as well as its own. A skill the\n * user wrote by hand is never in the payload, so it neither travels nor refuses.\n */\n private refuseEjectedSkills(payload: SeedPayload): void {\n const ejected = ejectedSkillsIn(payload);\n if (ejected.length > 0) {\n this.error(shareRefusesEjectedSkills(ejected), { exit: EXIT_CODES.ERROR });\n }\n }\n\n /**\n * A configuration the CALLER holds, which is why nothing here reads an installation.\n *\n * That is the whole distinction the flag draws, and it is not cosmetic: a bare `share` resolves\n * an installation the way every other command does — this project, then the global one — so\n * without this branch, sharing a piped payload from a directory with nothing in it would\n * publish whatever the machine happens to have installed globally.\n *\n * The producer this exists for is not this CLI. `meta-config-stack-detect` walks a repository\n * and emits a `SeedPayload` it is forbidden to write or apply, and an id is the only door into\n * the editor, which reads `?fromId=` and nothing else. Publishing from here rather than from\n * the producer keeps `SEED_VERSION`, the `AGENTS_INC_API_URL` override and the caller's\n * user-agent in the one place that owns them.\n *\n * It owes no caveats: those describe an installation, and none was read.\n */\n private async payloadFromPipe(): Promise<ShareablePayload> {\n if (process.stdin.isTTY) {\n this.error(STDIN_IS_A_TERMINAL, { exit: EXIT_CODES.ERROR });\n }\n\n const read: PipedPayload = readPipedPayload(await readAllOf(process.stdin));\n if (!read.ok) {\n this.error(read.error, { exit: EXIT_CODES.ERROR });\n }\n\n return { payload: read.payload, caveats: [] };\n }\n\n /**\n * Both destinations, because an id nobody can act on is not a share and there are exactly two\n * things that read one: this CLI, and the editor the configuration can be reopened in. The\n * lines themselves are `sharedConfigDestinations`, shared with `edit --ui` for the same reason\n * the mint above is.\n */\n private reportShared(id: string): void {\n this.logSuccess(`Shared as ${id}`);\n for (const destination of sharedConfigDestinations(id)) {\n this.log(destination);\n }\n }\n}\n","import { installableSeedPayloadSchema, type SeedPayload } from \"@workspace/matrix/seed\";\n\nimport { formatZodErrors } from \"../schema-validator.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport { stripTerminalControls, truncateText } from \"../../utils/string.js\";\n\n/** A payload read from a pipe, or the reason it could not be. */\nexport type PipedPayload =\n | { readonly ok: true; readonly payload: SeedPayload }\n | { readonly ok: false; readonly error: string };\n\nexport const NOTHING_PIPED =\n \"--stdin expects a configuration on standard input and none arrived. Pipe one in, as 'cat proposal.json | agents-inc share --stdin'.\";\n\nexport const STDIN_IS_A_TERMINAL =\n \"--stdin expects a configuration on standard input, but standard input is a terminal. Pipe one in rather than typing it.\";\n\n/**\n * How much of a body to quote back when it is not JSON, so a refusal names what it read.\n *\n * A CHARACTER bound, because what it clips is arbitrary bytes a producer piped by mistake: any\n * cut is as good as any other, and the point is only that the caller recognises what they sent.\n */\nconst EXCERPT = 80;\n\n/**\n * How many problems to name before the rest are counted instead.\n *\n * The scope rule raises one issue per (skill, sub-agent) PAIR rather than one per payload, and\n * each renders at roughly 150 characters — the same sentence every time, with two names changed.\n * A repository scan is 20-40 skills across 3-6 sub-agents, so an unbounded list is 60-240 of them\n * and hundreds of lines: the refusal becomes the wall of text it is complaining about.\n *\n * Four, so the whole message lands near twice the 300-character `EXPLANATION_BUDGET` in\n * `publish-seed.ts`, which bounds the store's account of this same refusal arriving over the\n * wire. Twice, because that one quotes back a remote explanation of a payload already sent, where\n * these are the caller's own pairs and each name is somewhere they have to go and edit — and four\n * of them is enough to show the mistake is a pattern rather than a one-off.\n *\n * A COUNT rather than a `truncateText` over the joined list, which is the one place this file's\n * two bounds differ. A character cut lands mid-sentence, and mid-sentence here means a half-named\n * skill or sub-agent — worse than one left out and counted, because it reads as a name.\n */\nconst PROBLEMS_NAMED = 4;\n\n/**\n * Everything that can fail locally, failing before the caller spends a write.\n *\n * The store's free tier allows a thousand writes a day against a hundred times that in reads, so\n * a write is the scarce half — and one spent on a payload the decoder cannot read buys a dead\n * link. Each of the three refusals below is a different mistake and says which: nothing arrived,\n * what arrived is not JSON, or it is JSON the contract does not accept.\n *\n * `installableSeedPayloadSchema` rather than a shape written here, and that is the point of\n * publishing from the CLI at all. `SEED_VERSION` is a `z.literal`, so a producer that hardcodes\n * the wire format emits payloads the store refuses the day it moves; the schema travels with the\n * code that posts.\n *\n * THE *INSTALLABLE* SCHEMA, AND THE DIFFERENCE IS THE WHOLE BUG THIS CLOSED. The worker validates\n * a POST with `installableSeedPayloadSchema` and a GET with the base `seedPayloadSchema` — write\n * strict, read lenient, deliberately, so links already in the wild stay repairable in the editor.\n * This gate read the BASE schema, so the one rule the two differ by — a project-scoped skill\n * assigned to a sub-agent resting at global, which has nowhere to be written — was the single\n * payload that passed locally and failed at the edge. It arrived as a bare `HTTP 400`.\n *\n * That was not an exotic shape. `agents` is sparse and an absent entry rests on the shared default\n * of `global`, so \"assign a skill and say nothing else\" is already the unwritable pair;\n * `meta-config-stack-detect` emitted it on every run. Reading the same schema the store writes\n * with is what makes this file's promise — everything that can fail locally, failing before the\n * caller spends a write — true rather than nearly true.\n */\nexport function readPipedPayload(body: string): PipedPayload {\n if (body.trim() === \"\") return { ok: false, error: NOTHING_PIPED };\n\n const read = readJson(body);\n if (!read.parsed) return { ok: false, error: notJsonMessage(body, read.reason) };\n\n const result = installableSeedPayloadSchema.safeParse(read.value);\n if (!result.success) {\n return { ok: false, error: refusedByContract(formatZodErrors(result.error)) };\n }\n\n return { ok: true, payload: result.data };\n}\n\n/** Whether a body is JSON at all, separated from whether it is a payload. */\ntype JsonRead =\n | { readonly parsed: true; readonly value: unknown }\n | { readonly parsed: false; readonly reason: string };\n\n/**\n * `JSON.parse` behind a verdict, so the caller reads as three guards rather than as a `let`\n * assigned inside a `try`. The same shape `readYaml` takes in `lib/skills/skill-metadata.ts`,\n * for the same reason: the failure is one of several a reader has to tell apart, and a thrown\n * exception is the one form that cannot sit beside the others.\n */\nfunction readJson(body: string): JsonRead {\n try {\n return { parsed: true, value: JSON.parse(body) };\n } catch (error) {\n return { parsed: false, reason: getErrorMessage(error) };\n }\n}\n\n/**\n * Two quotes of the same untrusted body, and both have to be made inert.\n *\n * The excerpt is the obvious one. The REASON is not, and it is the one that got through: V8 writes\n * `Unexpected token 'h', \"here is...\" is not valid JSON`, quoting the offending input verbatim, so\n * a parser's own account of a failure carries whatever caused it. `truncateText` covers the\n * excerpt; nothing covered the reason, because nothing looked like it came from outside.\n */\nfunction notJsonMessage(body: string, reason: string): string {\n const opening = truncateText(body.trim(), EXCERPT);\n const said = stripTerminalControls(reason);\n return `What arrived on standard input is not JSON: ${said}. It began: ${opening}`;\n}\n\nfunction refusedByContract(problems: string[]): string {\n return `The configuration on standard input is not one this store accepts: ${namedProblems(problems)}`;\n}\n\n/**\n * The first few problems in full, and a count of however many were left out.\n *\n * The count is what keeps a clipped list honest. Without it a caller who fixed the pairs named\n * here and ran again would have no way to tell this from a complete list — so the second refusal\n * would read as a new fault rather than as the rest of the one they were already fixing.\n */\nfunction namedProblems(problems: string[]): string {\n const named = problems.slice(0, PROBLEMS_NAMED).join(\"; \");\n const elided = problems.length - PROBLEMS_NAMED;\n return elided > 0 ? `${named} (and ${elided} more)` : named;\n}\n","import type { Readable } from \"node:stream\";\n\n/**\n * Every chunk of a readable, as text.\n *\n * A stream rather than `readFileSync(\"/dev/stdin\")`: that path does not exist on every platform\n * this CLI runs on, and it reads a pipe the operating system may still be filling. Async\n * iteration is the one form that is correct on all of them.\n */\nexport async function readAllOf(stream: Readable): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n }\n\n return Buffer.concat(chunks).toString(\"utf-8\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,aAAa;;;ACWf,IAAM,gBACX;AAEK,IAAM,sBACX;AAQF,IAAM,UAAU;AAoBhB,IAAM,iBAAiB;AA4BhB,SAAS,iBAAiB,MAA4B;AAC3D,MAAI,KAAK,KAAK,MAAM,GAAI,QAAO,EAAE,IAAI,OAAO,OAAO,cAAc;AAEjE,QAAM,OAAO,SAAS,IAAI;AAC1B,MAAI,CAAC,KAAK,OAAQ,QAAO,EAAE,IAAI,OAAO,OAAO,eAAe,MAAM,KAAK,MAAM,EAAE;AAE/E,QAAM,SAAS,6BAA6B,UAAU,KAAK,KAAK;AAChE,MAAI,CAAC,OAAO,SAAS;AACnB,WAAO,EAAE,IAAI,OAAO,OAAO,kBAAkB,gBAAgB,OAAO,KAAK,CAAC,EAAE;AAAA,EAC9E;AAEA,SAAO,EAAE,IAAI,MAAM,SAAS,OAAO,KAAK;AAC1C;AAaA,SAAS,SAAS,MAAwB;AACxC,MAAI;AACF,WAAO,EAAE,QAAQ,MAAM,OAAO,KAAK,MAAM,IAAI,EAAE;AAAA,EACjD,SAAS,OAAO;AACd,WAAO,EAAE,QAAQ,OAAO,QAAQ,gBAAgB,KAAK,EAAE;AAAA,EACzD;AACF;AAUA,SAAS,eAAe,MAAc,QAAwB;AAC5D,QAAM,UAAU,aAAa,KAAK,KAAK,GAAG,OAAO;AACjD,QAAM,OAAO,sBAAsB,MAAM;AACzC,SAAO,+CAA+C,IAAI,eAAe,OAAO;AAClF;AAEA,SAAS,kBAAkB,UAA4B;AACrD,SAAO,sEAAsE,cAAc,QAAQ,CAAC;AACtG;AASA,SAAS,cAAc,UAA4B;AACjD,QAAM,QAAQ,SAAS,MAAM,GAAG,cAAc,EAAE,KAAK,IAAI;AACzD,QAAM,SAAS,SAAS,SAAS;AACjC,SAAO,SAAS,IAAI,GAAG,KAAK,SAAS,MAAM,WAAW;AACxD;;;AC5HA,eAAsB,UAAU,QAAmC;AACjE,QAAM,SAAmB,CAAC;AAC1B,mBAAiB,SAAS,QAAQ;AAChC,WAAO,KAAK,OAAO,SAAS,KAAK,IAAI,QAAQ,OAAO,KAAK,OAAO,KAAK,CAAC,CAAC;AAAA,EACzE;AAEA,SAAO,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO;AAC/C;;;AFyBA,SAAS,aAAa,SAAsB,YAA0C;AACpF,QAAM,EAAE,YAAY,IAAI;AACxB,SAAO;AAAA,IACL,GAAI,UAAU,WAAW,IAAI,CAAC,qBAAqB,WAAW,CAAC,IAAI,CAAC;AAAA,IACpE,GAAI,WAAW,SAAS,IAAI,CAAC,uBAAuB,UAAU,CAAC,IAAI,CAAC;AAAA,EACtE;AACF;AAGA,SAAS,UAAU,aAAwD;AACzE,SAAO,gBAAgB,UAAa,cAAc,WAAW;AAC/D;AAGA,SAAS,gBAAgB,SAAgC;AACvD,SAAO,aAAa,QAAQ,MAAM,EAC/B,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,MAAM,YAAY,OAAO,EAC/C,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE;AACrB;AAEA,IAAqB,QAArB,MAAqB,eAAc,YAAY;AAAA,EAC7C,OAAO,UAAU;AAAA,EAEjB,OAAO,cACL;AAAA,EAEF,OAAO,QAAQ;AAAA,IACb,OAAO,MAAM,QAAQ;AAAA,MACnB,aACE;AAAA,MACF,SAAS;AAAA,IACX,CAAC;AAAA,IACD,UAAU,aAAa;AAAA,EACzB;AAAA,EAEA,OAAO,WAAW;AAAA,IAChB;AAAA,IACA;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,MAAK;AAMxC,QAAI,CAAC,MAAM,OAAO;AAChB,YAAM;AAAA,QACJ,QAAQ,IAAI;AAAA,QACZ;AAAA,QACA,gBAAgB,MAAM,QAAQ;AAAA,QAC9B,CAAC,YAAY,KAAK,MAAM,SAAS,EAAE,MAAM,WAAW,aAAa,CAAC;AAAA,MACpE;AACA,YAAM,KAAK,qBAAqB,QAAQ,IAAI,CAAC;AAC7C,YAAM,KAAK,4BAA4B,QAAQ,IAAI,CAAC;AAAA,IACtD;AAEA,UAAM,EAAE,SAAS,QAAQ,IAAI,MAAM,QAC/B,MAAM,KAAK,gBAAgB,IAC3B,MAAM,KAAK,wBAAwB;AAEvC,UAAM,YAAY,MAAM,kBAAkB,OAAO;AACjD,QAAI,CAAC,UAAU,IAAI;AACjB,WAAK,MAAM,UAAU,OAAO,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IACxD;AAEA,SAAK,aAAa,UAAU,EAAE;AAG9B,eAAW,UAAU,QAAS,MAAK,MAAM;AAAA,EAC3C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MAAc,4BAA4B,KAA4B;AACpE,UAAM,CAAC,OAAO,IAAI,MAAM,2BAA2B,GAAG;AACtD,QAAI,YAAY,OAAW,MAAK,MAAM,SAAS,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,EAC3E;AAAA;AAAA,EAGA,MAAc,0BAAqD;AACjE,UAAM,WAAW,MAAM,2BAA2B,QAAQ,IAAI,CAAC;AAC/D,QAAI,CAAC,SAAS,IAAI;AAChB,WAAK,MAAM,SAAS,OAAO,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IACvD;AAEA,SAAK,oBAAoB,SAAS,OAAO;AACzC,SAAK,IAAI,WAAW,SAAS,MAAM,oBAAoB,SAAS,MAAM,kBAAkB;AAExF,WAAO;AAAA,MACL,SAAS,SAAS;AAAA,MAClB,SAAS,aAAa,SAAS,SAAS,SAAS,UAAU;AAAA,IAC7D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,oBAAoB,SAA4B;AACtD,UAAM,UAAU,gBAAgB,OAAO;AACvC,QAAI,QAAQ,SAAS,GAAG;AACtB,WAAK,MAAM,0BAA0B,OAAO,GAAG,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IAC3E;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAkBA,MAAc,kBAA6C;AACzD,QAAI,QAAQ,MAAM,OAAO;AACvB,WAAK,MAAM,qBAAqB,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IAC5D;AAEA,UAAM,OAAqB,iBAAiB,MAAM,UAAU,QAAQ,KAAK,CAAC;AAC1E,QAAI,CAAC,KAAK,IAAI;AACZ,WAAK,MAAM,KAAK,OAAO,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,IACnD;AAEA,WAAO,EAAE,SAAS,KAAK,SAAS,SAAS,CAAC,EAAE;AAAA,EAC9C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQQ,aAAa,IAAkB;AACrC,SAAK,WAAW,aAAa,EAAE,EAAE;AACjC,eAAW,eAAe,yBAAyB,EAAE,GAAG;AACtD,WAAK,IAAI,WAAW;AAAA,IACtB;AAAA,EACF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/commands/share.ts","../../src/cli/lib/seed/read-piped-payload.ts","../../src/cli/utils/read-stream.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\n\nimport { BaseCommand } from \"../base-command.js\";\nimport { isLocalSource } from \"../lib/configuration/config.js\";\nimport { EXIT_CODES } from \"../lib/exit-codes.js\";\nimport { unofferablePlacementsFound } from \"../lib/hosts/configured-placements.js\";\nimport { seedPayloadForInstallation } from \"../lib/seed/installation-payload.js\";\nimport { publishSeedConfig } from \"../lib/seed/publish-seed.js\";\nimport {\n readPipedPayload,\n STDIN_IS_A_TERMINAL,\n type PipedPayload,\n} from \"../lib/seed/read-piped-payload.js\";\nimport {\n providerFlag,\n providerNamedBy,\n refuseAnAmbiguousInstallation,\n} from \"../lib/installation/provider-flag.js\";\nimport { warn } from \"../utils/logger.js\";\nimport { readAllOf } from \"../utils/read-stream.js\";\nimport {\n sharedConfigDestinations,\n sharedIdNamesAFolder,\n sharedSkillsLeftBehind,\n shareRefusesEjectedSkills,\n} from \"../utils/messages.js\";\nimport { typedEntries } from \"../utils/typed-object.js\";\nimport type { SkillId } from \"../types/index.js\";\nimport type { SeedPayload } from \"@workspace/matrix/seed\";\n\ntype ShareablePayload = { payload: SeedPayload; caveats: string[] };\n\n/** What the id will not do everywhere — warned after the id rather than refused. */\nfunction caveatsAbout(payload: SeedPayload, leftBehind: readonly SkillId[]): string[] {\n const { marketplace } = payload;\n return [\n ...(isAFolder(marketplace) ? [sharedIdNamesAFolder(marketplace)] : []),\n ...(leftBehind.length > 0 ? [sharedSkillsLeftBehind(leftBehind)] : []),\n ];\n}\n\nfunction isAFolder(marketplace: string | undefined): marketplace is string {\n return marketplace !== undefined && isLocalSource(marketplace);\n}\n\nfunction ejectedSkillsIn(payload: SeedPayload): string[] {\n return typedEntries(payload.skills)\n .filter(([, skill]) => skill.install === \"eject\")\n .map(([id]) => id);\n}\n\nexport default class Share extends BaseCommand {\n static summary = \"Share this installation as an id anyone can install\";\n\n static description =\n \"Turns the skills, sub-agents and per-agent curation installed here into a configuration the agentsinc.sh store holds, and prints the id it was given. Install it elsewhere with 'init --from <id>', or open it in the editor. The id is the configuration's own hash, so sharing an unchanged installation returns the id it already had.\";\n\n static flags = {\n stdin: Flags.boolean({\n description:\n \"Share a configuration piped in on standard input instead of the one installed here\",\n default: false,\n }),\n provider: providerFlag(),\n };\n\n static examples = [\n \"<%= config.bin %> <%= command.id %>\",\n \"cat proposal.json | <%= config.bin %> <%= command.id %> --stdin\",\n ];\n\n /** Everything that can fail locally fails before the POST: store writes are the scarce quota. */\n async run(): Promise<void> {\n const { flags } = await this.parse(Share);\n\n // A piped payload never reads this directory, so its state must not refuse it.\n if (!flags.stdin) {\n await refuseAnAmbiguousInstallation(\n process.cwd(),\n \"share\",\n providerNamedBy(flags.provider),\n (message) => this.error(message, { exit: EXIT_CODES.INVALID_ARGS }),\n );\n await this.ensureConfigReadable(process.cwd());\n await this.refuseUnofferablePlacements(process.cwd());\n }\n\n const { payload, caveats } = flags.stdin\n ? await this.payloadFromPipe()\n : await this.payloadFromInstallation();\n\n const published = await publishSeedConfig(payload);\n if (!published.ok) {\n this.error(published.error, { exit: EXIT_CODES.ERROR });\n }\n\n this.reportShared(published.id);\n // Not `this.warn`: oclif hard-wraps, which breaks the folder paths caveats name.\n for (const caveat of caveats) warn(caveat);\n }\n\n /** A placement the host cannot fill was never installed here, so the id would misdescribe it. */\n private async refuseUnofferablePlacements(cwd: string): Promise<void> {\n const [finding] = await unofferablePlacementsFound(cwd);\n if (finding !== undefined) this.error(finding, { exit: EXIT_CODES.ERROR });\n }\n\n private async payloadFromInstallation(): Promise<ShareablePayload> {\n const prepared = await seedPayloadForInstallation(process.cwd());\n if (!prepared.ok) {\n this.error(prepared.error, { exit: EXIT_CODES.ERROR });\n }\n\n this.refuseEjectedSkills(prepared.payload);\n this.log(`Sharing ${prepared.skills} skill(s) across ${prepared.agents} sub-agent(s)...`);\n\n return {\n payload: prepared.payload,\n caveats: caveatsAbout(prepared.payload, prepared.leftBehind),\n };\n }\n\n /** A share carries plugins only: an ejected skill is a local copy the user may have edited. */\n private refuseEjectedSkills(payload: SeedPayload): void {\n const ejected = ejectedSkillsIn(payload);\n if (ejected.length > 0) {\n this.error(shareRefusesEjectedSkills(ejected), { exit: EXIT_CODES.ERROR });\n }\n }\n\n /** The caller's configuration; no installation is read, so it owes no caveats. */\n private async payloadFromPipe(): Promise<ShareablePayload> {\n if (process.stdin.isTTY) {\n this.error(STDIN_IS_A_TERMINAL, { exit: EXIT_CODES.ERROR });\n }\n\n const read: PipedPayload = readPipedPayload(await readAllOf(process.stdin));\n if (!read.ok) {\n this.error(read.error, { exit: EXIT_CODES.ERROR });\n }\n\n return { payload: read.payload, caveats: [] };\n }\n\n private reportShared(id: string): void {\n this.logSuccess(`Shared as ${id}`);\n for (const destination of sharedConfigDestinations(id)) {\n this.log(destination);\n }\n }\n}\n","import { installableSeedPayloadSchema, type SeedPayload } from \"@workspace/matrix/seed\";\n\nimport { formatZodErrors } from \"../schema-validator.js\";\nimport { getErrorMessage } from \"../../utils/errors.js\";\nimport { stripTerminalControls, truncateText } from \"../../utils/string.js\";\n\nexport type PipedPayload =\n | { readonly ok: true; readonly payload: SeedPayload }\n | { readonly ok: false; readonly error: string };\n\nexport const NOTHING_PIPED =\n \"--stdin expects a configuration on standard input and none arrived. Pipe one in, as 'cat proposal.json | agents-inc share --stdin'.\";\n\nexport const STDIN_IS_A_TERMINAL =\n \"--stdin expects a configuration on standard input, but standard input is a terminal. Pipe one in rather than typing it.\";\n\n/** Characters of a non-JSON body to quote back, enough for the caller to recognise it. */\nconst EXCERPT = 80;\n\n/**\n * The scope rule raises one issue per (skill, sub-agent) pair, so the list can run to hundreds.\n * A count, not a character cut, so no name is left half-printed.\n */\nconst PROBLEMS_NAMED = 4;\n\n/**\n * Fails locally before a write is spent. Uses the installable schema the store's POST validates\n * with, not the lenient read schema, so nothing passes here and fails at the edge.\n */\nexport function readPipedPayload(body: string): PipedPayload {\n if (body.trim() === \"\") return { ok: false, error: NOTHING_PIPED };\n\n const read = readJson(body);\n if (!read.parsed) return { ok: false, error: notJsonMessage(body, read.reason) };\n\n const result = installableSeedPayloadSchema.safeParse(read.value);\n if (!result.success) {\n return { ok: false, error: refusedByContract(formatZodErrors(result.error)) };\n }\n\n return { ok: true, payload: result.data };\n}\n\ntype JsonRead =\n | { readonly parsed: true; readonly value: unknown }\n | { readonly parsed: false; readonly reason: string };\n\nfunction readJson(body: string): JsonRead {\n try {\n return { parsed: true, value: JSON.parse(body) };\n } catch (error) {\n return { parsed: false, reason: getErrorMessage(error) };\n }\n}\n\n/** The parse reason is stripped too: V8 quotes the offending input verbatim in it. */\nfunction notJsonMessage(body: string, reason: string): string {\n const opening = truncateText(body.trim(), EXCERPT);\n const said = stripTerminalControls(reason);\n return `What arrived on standard input is not JSON: ${said}. It began: ${opening}`;\n}\n\nfunction refusedByContract(problems: string[]): string {\n return `The configuration on standard input is not one this store accepts: ${namedProblems(problems)}`;\n}\n\n/** The count tells a clipped list from a complete one. */\nfunction namedProblems(problems: string[]): string {\n const named = problems.slice(0, PROBLEMS_NAMED).join(\"; \");\n const elided = problems.length - PROBLEMS_NAMED;\n return elided > 0 ? `${named} (and ${elided} more)` : named;\n}\n","import type { Readable } from \"node:stream\";\n\n/** Async iteration rather than `readFileSync(\"/dev/stdin\")`, which is not portable. */\nexport async function readAllOf(stream: Readable): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));\n }\n\n return Buffer.concat(chunks).toString(\"utf-8\");\n}\n"],"mappings":"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","names":[]}
|