@heyquilt/seam 0.143.0 → 0.144.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/bin/seam.js +12 -1
- package/lib/quilts/cli.js +13 -2
- package/lib/quilts/client.js +2 -0
- package/lib/quilts/export-git.js +5 -3
- package/lib/quilts/tools.js +7 -4
- package/package.json +1 -1
package/bin/seam.js
CHANGED
|
@@ -24,6 +24,7 @@ Docs: https://seam.heyquilt.com/docs
|
|
|
24
24
|
seam account delete --confirm <your email> delete your Seam account (your patches stay)
|
|
25
25
|
seam agent new <name> | list | key <name> | revoke <name> | relink [agent:<id>] your agents and their keys
|
|
26
26
|
seam oauth client new <name> --redirect <uri> | list | revoke <client_id> apps that ask people for access (OAuth 2, PKCE)
|
|
27
|
+
seam oauth allowed [list | revoke <grant id>] the apps you allowed into your account, and ending one
|
|
27
28
|
seam quilts [new <slug> | show <q>] Your quilts (repositories)
|
|
28
29
|
seam import git <path> [--into <slug>] [--authors <file>]
|
|
29
30
|
seam github [import <owner/name> --installation <id> [--into <slug>]] from GitHub, followed
|
|
@@ -98,6 +99,7 @@ Docs: https://seam.heyquilt.com/docs
|
|
|
98
99
|
seam org log <org> [-n <count>] [--before <id>] what happened in an org: members, roles, teams, quilts (owners and admins)
|
|
99
100
|
seam org team <org> <name> [<member>...] an org's team, named org_team:<name> in its quilts' protections
|
|
100
101
|
seam quilts new <slug> --org <org> | quilts move --quilt <q> --org <org> a quilt that belongs to an org
|
|
102
|
+
seam quilts rename <new-slug> --quilt <q> [--title <name>] a new address (<owner>/<new-slug>); the old one stays an alias
|
|
101
103
|
seam quilts agents-make-lines on|off whether agents may make lines, tags and releases
|
|
102
104
|
seam quilts public on|off anyone may read the quilt, signed in or not
|
|
103
105
|
seam quilts add <email|member> [--level read|write|admin] add a member; an email with no account yet is invited
|
|
@@ -185,7 +187,16 @@ async function oauthCommand (argv) {
|
|
|
185
187
|
}
|
|
186
188
|
}
|
|
187
189
|
const [what, sub, ...rest] = argv
|
|
188
|
-
|
|
190
|
+
// The apps you allowed (GET /v1/me/grants): what each may do; revoking one ends its tokens.
|
|
191
|
+
if (what === 'allowed') {
|
|
192
|
+
if (sub === 'revoke') { if (!rest[0]) fail('seam oauth allowed revoke <grant id>'); await go('DELETE', `/v1/me/grants/${encodeURIComponent(rest[0])}`); return console.log(`Revoked: the app's tokens from that approval have ended. It asks you again to come back.`) }
|
|
193
|
+
if (sub && sub !== 'list') fail(`seam oauth allowed: '${sub}' is not a command (list, revoke).`)
|
|
194
|
+
const { grants } = await go('GET', '/v1/me/grants')
|
|
195
|
+
if (!grants.length) return console.log('You have allowed no apps.')
|
|
196
|
+
for (const g of grants) console.log(`${g.id} ${g.client.name} ${g.scopes.map((x) => { const q = g.quilts.find((y) => x === `quilt:${y.id}:${y.level}`); return q ? `${q.slug || q.id}:${q.level}` : x }).join(' ')}`)
|
|
197
|
+
return
|
|
198
|
+
}
|
|
199
|
+
if (what !== 'client') fail('seam oauth client new <name> --redirect <uri> | list | revoke <client_id> | seam oauth allowed [list | revoke <grant id>]')
|
|
189
200
|
if (sub === 'new') {
|
|
190
201
|
const redirects = []; const words = []
|
|
191
202
|
for (let i = 0; i < rest.length; i++) { if (rest[i] === '--redirect') redirects.push(rest[++i]); else words.push(rest[i]) }
|
package/lib/quilts/cli.js
CHANGED
|
@@ -147,6 +147,12 @@ export async function runSeamCommand (cmd, argv, { cwd = process.cwd(), token, o
|
|
|
147
147
|
const r = await client.setQuiltOwner(needQuilt(), flags['--org'])
|
|
148
148
|
return print(r, `${r.quilt} now belongs to ${r.org}.`)
|
|
149
149
|
}
|
|
150
|
+
if (pos[0] === 'rename') {
|
|
151
|
+
// seam quilts rename <new-slug> --quilt <q> [--title <name>]: its address is <owner>/<new-slug> after.
|
|
152
|
+
if (!pos[1] && !flags['--title']) throw new Error('seam quilts rename <new-slug> --quilt <q> [--title <name>]')
|
|
153
|
+
const r = await client.renameQuilt(needQuilt(), { ...(pos[1] ? { slug: pos[1] } : {}), ...(flags['--title'] ? { name: flags['--title'] } : {}) })
|
|
154
|
+
return print(r, r.slug === r.was ? `${r.slug} is now called ${r.name}.` : `${r.was} is now ${r.path || r.slug}${r.name !== r.slug ? ` (${r.name})` : ''}. Links by its id keep working; its old address doesn't. In a block folder of it, nothing changes: the block names it by id.`)
|
|
155
|
+
}
|
|
150
156
|
if (pos[0] === 'sealed') {
|
|
151
157
|
if (!['on', 'off'].includes(pos[1])) throw new Error('seam quilts sealed on|off --quilt <q>')
|
|
152
158
|
const r = await client.setSealed(needQuilt(), pos[1] === 'on')
|
|
@@ -1097,8 +1103,13 @@ export async function runSeamCommand (cmd, argv, { cwd = process.cwd(), token, o
|
|
|
1097
1103
|
case 'export': {
|
|
1098
1104
|
// To a git remote, on the server, after each merge (14): seam export remote <url> | status.
|
|
1099
1105
|
if (pos[0] === 'remote' && pos[1]) {
|
|
1100
|
-
const r = await client.setExport(needQuilt(), { target: pos[1], lines: flags['--line'] ? String(flags['--line']).split(',') : undefined, releases: !!flags['--releases'], credential: flags['--credential'] || undefined, scratch: !!flags['--scratch'], enabled: !flags['--off'], lfs: flags['--lfs-url'] ? { url: String(flags['--lfs-url']), ...(flags['--lfs-threshold'] != null ? { threshold_bytes: Number(flags['--lfs-threshold']) } : {}) } : undefined })
|
|
1101
|
-
return print(r, r.enabled ? `Exporting ${r.lines.join(', ')} to ${r.target} after each merge${r.releases ? ', with release tags' : ''}${r.lfs ? `, files over ${r.lfs.threshold_bytes} bytes to LFS at ${r.lfs.url}` : ''}. seam export status` : `The export to ${r.target} is off.`)
|
|
1106
|
+
const r = await client.setExport(needQuilt(), { target: pos[1], lines: flags['--line'] ? String(flags['--line']).split(',') : undefined, releases: !!flags['--releases'], credential: flags['--credential'] || undefined, scratch: !!flags['--scratch'], enabled: !flags['--off'], lfs: flags['--lfs-url'] ? { url: String(flags['--lfs-url']), ...(flags['--lfs-threshold'] != null ? { threshold_bytes: Number(flags['--lfs-threshold']) } : {}) } : undefined, main_as: flags['--main-as'] || undefined, push: flags['--push'] || undefined, exclude: flags['--exclude'] ? String(flags['--exclude']).split(',').map((x) => x.trim()).filter(Boolean) : undefined })
|
|
1107
|
+
return print(r, r.enabled ? `Exporting ${r.lines.join(', ')} to ${r.target} ${r.push === 'tag' ? 'up to the newest tagged patch' : 'after each merge'}${r.main_as && r.main_as !== 'main' ? `, main as ${r.main_as}` : ''}${r.releases ? ', with release tags' : ''}${r.exclude?.length ? `, without ${r.exclude.join(', ')}` : ''}${r.lfs ? `, files over ${r.lfs.threshold_bytes} bytes to LFS at ${r.lfs.url}` : ''}. seam export status` : `The export to ${r.target} is off.`)
|
|
1108
|
+
}
|
|
1109
|
+
// Runs the export now (admins): after fixing a remote, or without waiting for the next retry.
|
|
1110
|
+
if (pos[0] === 'push') {
|
|
1111
|
+
const r = await client.exportPush(needQuilt())
|
|
1112
|
+
return print(r, `Pushing to ${r.target} now. seam export status`)
|
|
1102
1113
|
}
|
|
1103
1114
|
if (pos[0] === 'status') {
|
|
1104
1115
|
const r = await client.exportStatus(needQuilt())
|
package/lib/quilts/client.js
CHANGED
|
@@ -345,6 +345,7 @@ export function quiltClient ({ api, token, fetch: fetchImpl = globalThis.fetch,
|
|
|
345
345
|
setOrgTeam: (o, name, members) => call('PUT', `/v1/orgs/${enc(o)}/teams/${enc(name)}`, { members }),
|
|
346
346
|
setOrgMember: (o, member, role) => String(member).includes('@') ? call('POST', `/v1/orgs/${enc(o)}/members`, { email: member, role }) : call('PUT', `/v1/orgs/${enc(o)}/members/${enc(member)}`, { role }),
|
|
347
347
|
setQuiltOwner: (q, org) => call('PUT', `${Q(q)}/owner`, { org }),
|
|
348
|
+
renameQuilt: (q, body) => call('PATCH', Q(q), body),
|
|
348
349
|
setAgentsMakeLines: (q, allow) => call('PUT', `${Q(q)}/agents-make-lines`, { allow }),
|
|
349
350
|
setPublic: (q, value) => call('PUT', `${Q(q)}/public`, { public: value }),
|
|
350
351
|
setSealed: (q, value) => call('PUT', `${Q(q)}/sealed`, { sealed: value }),
|
|
@@ -372,6 +373,7 @@ export function quiltClient ({ api, token, fetch: fetchImpl = globalThis.fetch,
|
|
|
372
373
|
importKnown: (q, shas) => call('POST', `${Q(q)}/import/known`, { shas }),
|
|
373
374
|
setExport: (q, b) => call('PUT', `${Q(q)}/export`, b),
|
|
374
375
|
exportStatus: (q) => call('GET', `${Q(q)}/export`),
|
|
376
|
+
exportPush: (q) => call('POST', `${Q(q)}/export/push`, {}),
|
|
375
377
|
startImport: (b) => call('POST', '/v1/imports', b),
|
|
376
378
|
github: () => call('GET', '/v1/github'),
|
|
377
379
|
importGithub: (b) => call('POST', '/v1/github/import', b),
|
package/lib/quilts/export-git.js
CHANGED
|
@@ -61,9 +61,10 @@ async function fetchBlobs (client, q, ids) {
|
|
|
61
61
|
* missing). Returns { exported, patch_no, sha, branch }. With `sign` (export-sign.js exportKey), every
|
|
62
62
|
* commit carries an SSH signature with that key. With `lfs` ({ threshold, upload(bytes) → pointer
|
|
63
63
|
* text }, export-lfs.js), a file over the threshold or named by a `filter=lfs` line of the root
|
|
64
|
-
* `.gitattributes` is written as an LFS pointer and its bytes uploaded.
|
|
64
|
+
* `.gitattributes` is written as an LFS pointer and its bytes uploaded. With `exclude` (a function
|
|
65
|
+
* of a path), the paths it names are left out of every exported tree (14, `exclude`).
|
|
65
66
|
*/
|
|
66
|
-
export async function exportGit (client, { q, dir, line = 'main', branch, page = 200, sign = null, lfs = null, log = () => {} }) {
|
|
67
|
+
export async function exportGit (client, { q, dir, line = 'main', branch, page = 200, sign = null, lfs = null, exclude = null, log = () => {} }) {
|
|
67
68
|
branch = branch || line
|
|
68
69
|
const gitDir = openRepo(dir)
|
|
69
70
|
const stateFile = path.join(gitDir, 'quilt-export.json')
|
|
@@ -89,7 +90,7 @@ export async function exportGit (client, { q, dir, line = 'main', branch, page =
|
|
|
89
90
|
if (version !== null && version !== r.version) throw new Error(`export format ${r.version} differs from the ${version} this branch was exported with: export to a new branch`)
|
|
90
91
|
version = r.version; quiltId = r.quilt
|
|
91
92
|
if (!r.patches.length) break
|
|
92
|
-
const blobs = await fetchBlobs(client, q, r.patches.flatMap((p) => p.changes.filter((c) => c.op === 'put').map((c) => c.blob)))
|
|
93
|
+
const blobs = await fetchBlobs(client, q, r.patches.flatMap((p) => p.changes.filter((c) => c.op === 'put' && !(exclude && exclude(c.path))).map((c) => c.blob)))
|
|
93
94
|
const marksFile = path.join(gitDir, 'quilt-export.marks')
|
|
94
95
|
const fi = fastImport(dir, marksFile)
|
|
95
96
|
const send = async (s) => { const w = fi.write(s); if (w) await w }
|
|
@@ -116,6 +117,7 @@ export async function exportGit (client, { q, dir, line = 'main', branch, page =
|
|
|
116
117
|
if (attrs) lfsMatch = attrs.op === 'delete' ? null : lfsPatterns(blobs.get(attrs.blob)?.toString('utf8'))
|
|
117
118
|
}
|
|
118
119
|
for (const c of p.changes) {
|
|
120
|
+
if (exclude && exclude(c.path)) continue
|
|
119
121
|
const bytes = lfs && c.op === 'put' && (!c.mode || c.mode === 'file' || c.mode === 'exec') && c.path !== '.gitattributes' ? blobs.get(c.blob) : null
|
|
120
122
|
if (bytes && (bytes.length > lfs.threshold || lfsMatch?.ignores(c.path))) {
|
|
121
123
|
const pointer = await lfs.upload(bytes)
|
package/lib/quilts/tools.js
CHANGED
|
@@ -19,7 +19,7 @@ import { rebuild as rebuildBlock, conflictStyle } from './block.js'
|
|
|
19
19
|
import { describeRebuild, describeOpened, describeBoth } from './describe.js'
|
|
20
20
|
import { status as blockStatus, commitFolder, amendFolder, syncTo, pull, toLineTip, checkout, restore, reset, clean, localChanges, bytesOf, livePatch, resolvePulled } from './block.js'
|
|
21
21
|
|
|
22
|
-
export const SEAM_TOOLS = ['seam_quilts', 'seam_open_square', 'seam_squares', 'seam_log', 'seam_show', 'seam_diff', 'seam_blame', 'seam_cat', 'seam_ls', 'seam_commit', 'seam_merge', 'seam_rebase', 'seam_revert', 'seam_cherry_pick', 'seam_resolve', 'seam_square_status', 'seam_square_handoff', 'seam_abandon', 'seam_square_merged', 'seam_reopen', 'seam_fold', 'seam_split', 'seam_events', 'seam_events_webhook', 'seam_line_list', 'seam_line_new', 'seam_line_freeze', 'seam_line_unfreeze', 'seam_line_require', 'seam_reviews', 'seam_review', 'seam_tag_list', 'seam_tag', 'seam_release_list', 'seam_release', 'seam_import_git', 'seam_import_remote', 'seam_github', 'seam_github_import', 'seam_import_status', 'seam_import_authors', 'seam_import_poke', 'seam_import_cutover', 'seam_export_remote', 'seam_export_status', 'seam_restore', 'seam_reset', 'seam_clean', 'seam_live', 'seam_live_join', 'seam_live_set', 'seam_bisect', 'seam_grep', 'seam_search', 'seam_describe', 'seam_merge_base', 'seam_stack', 'seam_migrations_dir', 'seam_claims', 'seam_claim', 'seam_unclaim', 'seam_check', 'seam_resolutions', 'seam_forget_resolution', 'seam_sign', 'seam_keys', 'seam_key_add', 'seam_key_remove', 'seam_token_list', 'seam_token_new', 'seam_token_revoke', 'seam_protections', 'seam_protections_set', 'seam_team_set', 'seam_verify', 'seam_redact', 'seam_redactions', 'seam_seal', 'seam_secret_scanning', 'seam_public', 'seam_sealed', 'seam_policy', 'seam_line_policy_versions', 'seam_orgs', 'seam_org_log', 'seam_org_domain', 'seam_apps', 'seam_app', 'seam_app_key', 'seam_app_manager', 'seam_app_install', 'seam_app_request', 'seam_org_member', 'seam_org_team', 'seam_agent_token_new', 'seam_agent_token_list', 'seam_agent_token_revoke', 'seam_agents_make_lines', 'seam_checks', 'seam_check_rerun', 'seam_reparent', 'seam_archive', 'seam_unarchive', 'seam_hide', 'seam_unhide', 'seam_square_edit', 'seam_share', 'seam_unshare', 'seam_export_tarball', 'seam_claim_request', 'seam_claim_withdraw', 'seam_claim_handoff', 'seam_claim_finish', 'seam_blocks', 'seam_block_open', 'seam_block_touch', 'seam_block_close', 'seam_ancestor', 'seam_contains', 'seam_pipeline', 'seam_watch', 'seam_unwatch', 'seam_absorb', 'seam_interdiff', 'seam_apply_suggestion', 'seam_infra_paths', 'seam_owner_idle_hours', 'seam_public_reads', 'seam_export_archive', 'seam_metrics', 'seam_daemon', 'seam_block_rebuild', 'seam_clone', 'seam_pull', 'seam_member_add']
|
|
22
|
+
export const SEAM_TOOLS = ['seam_quilts', 'seam_open_square', 'seam_squares', 'seam_log', 'seam_show', 'seam_diff', 'seam_blame', 'seam_cat', 'seam_ls', 'seam_commit', 'seam_merge', 'seam_rebase', 'seam_revert', 'seam_cherry_pick', 'seam_resolve', 'seam_square_status', 'seam_square_handoff', 'seam_abandon', 'seam_square_merged', 'seam_reopen', 'seam_fold', 'seam_split', 'seam_events', 'seam_events_webhook', 'seam_line_list', 'seam_line_new', 'seam_line_freeze', 'seam_line_unfreeze', 'seam_line_require', 'seam_reviews', 'seam_review', 'seam_tag_list', 'seam_tag', 'seam_release_list', 'seam_release', 'seam_import_git', 'seam_import_remote', 'seam_github', 'seam_github_import', 'seam_import_status', 'seam_import_authors', 'seam_import_poke', 'seam_import_cutover', 'seam_export_remote', 'seam_export_status', 'seam_export_push', 'seam_restore', 'seam_reset', 'seam_clean', 'seam_live', 'seam_live_join', 'seam_live_set', 'seam_bisect', 'seam_grep', 'seam_search', 'seam_describe', 'seam_merge_base', 'seam_stack', 'seam_migrations_dir', 'seam_claims', 'seam_claim', 'seam_unclaim', 'seam_check', 'seam_resolutions', 'seam_forget_resolution', 'seam_sign', 'seam_keys', 'seam_key_add', 'seam_key_remove', 'seam_token_list', 'seam_token_new', 'seam_token_revoke', 'seam_protections', 'seam_protections_set', 'seam_team_set', 'seam_verify', 'seam_redact', 'seam_redactions', 'seam_seal', 'seam_secret_scanning', 'seam_public', 'seam_sealed', 'seam_policy', 'seam_line_policy_versions', 'seam_orgs', 'seam_org_log', 'seam_org_domain', 'seam_apps', 'seam_app', 'seam_app_key', 'seam_app_manager', 'seam_app_install', 'seam_app_request', 'seam_org_member', 'seam_org_team', 'seam_agent_token_new', 'seam_agent_token_list', 'seam_agent_token_revoke', 'seam_agents_make_lines', 'seam_checks', 'seam_check_rerun', 'seam_reparent', 'seam_archive', 'seam_unarchive', 'seam_hide', 'seam_unhide', 'seam_square_edit', 'seam_share', 'seam_unshare', 'seam_export_tarball', 'seam_claim_request', 'seam_claim_withdraw', 'seam_claim_handoff', 'seam_claim_finish', 'seam_blocks', 'seam_block_open', 'seam_block_touch', 'seam_block_close', 'seam_ancestor', 'seam_contains', 'seam_pipeline', 'seam_watch', 'seam_unwatch', 'seam_absorb', 'seam_interdiff', 'seam_apply_suggestion', 'seam_infra_paths', 'seam_owner_idle_hours', 'seam_public_reads', 'seam_export_archive', 'seam_metrics', 'seam_daemon', 'seam_block_rebuild', 'seam_clone', 'seam_pull', 'seam_member_add']
|
|
23
23
|
|
|
24
24
|
/** What every agent is told about source control, in each MCP's instructions. */
|
|
25
25
|
export const SEAM_GUIDE = 'Quilt source control (quilts): a quilt is a repository on the Quilt server; you work in a square (your own branch and working copy), commit save points in it, and merge it into main, where it becomes a patch. ' +
|
|
@@ -71,6 +71,7 @@ export const SEAM_DESCRIPTIONS = {
|
|
|
71
71
|
seam_export_archive: 'Writes the whole quilt as one .tar (admin) to a file on this computer: every log segment, every pack and the members, with a manifest of sizes and BLAKE3s; out (default <quilt>-<row>.seam.tar). seam export check <file> checks it offline. Over HTTP: POST /v1/quilts/:q/exit/archive.',
|
|
72
72
|
seam_export_tarball: 'Writes one commit as a .tar.gz (what git archive makes) to a file on this computer: rev (default main), paths to take only part, out (default <quilt>-<commit>.tar.gz in this folder). The same commit always gives the same bytes. Over HTTP: GET /v1/quilts/:q/tarball/:rev?paths=.',
|
|
73
73
|
seam_export_status: 'The export to a git remote: its target, lines, state (idle, ok, retrying, refused), each line\'s last exported patch and sha, and the last error.',
|
|
74
|
+
seam_export_push: 'Runs the export to a git remote now (admins), without waiting for the next merge or retry.',
|
|
74
75
|
seam_import_cutover: 'Ends a following import for good (admins): a last pass, a check that the remote\'s tips equal the imported ones, then main and release/* take merges in Seam and main exports to the source after each merge. Refuses with remote_moved if git moved.',
|
|
75
76
|
seam_import_status: 'An import from a git remote: its state (reading, awaiting_authors, following, done, failed), its lines with their git tips, its last error, and while it waits the authors with the proposed member of each.',
|
|
76
77
|
seam_import_authors: 'Answers an import waiting in awaiting_authors (admins): a map of git author email → member id of the quilt; the import then runs. An email left out becomes a stub member. Refuses an id that is not a member (unknown_author).',
|
|
@@ -200,10 +201,11 @@ export const SEAM_INPUTS = {
|
|
|
200
201
|
seam_github: {},
|
|
201
202
|
seam_github_import: { repo: z.string().max(201).describe('owner/name, as seam_github lists it'), installation: z.string().max(20).describe('The installation id seam_github shows for it'), into: z.string().max(63).optional().describe('The new quilt\'s slug (default the repo\'s name)'), follow: z.boolean().optional().describe('Keep following it (default true)') },
|
|
202
203
|
seam_import_remote: { url: z.string().max(2000).describe('The git remote: https://, ssh:// or user@host:path'), into: z.string().max(63).describe('The new quilt\'s slug'), follow: z.boolean().optional().describe('Keep following main and release/* until cut-over'), interval: z.number().int().min(60).optional().describe('Seconds between follow passes (default 600)'), credential: z.string().max(100).optional().describe('The name of the server secret that reads the remote (user:token or a token)'), authors: z.record(z.string(), z.string()).optional().describe('Git author email → member id of the quilt'), ask_authors: z.boolean().optional().describe('Wait in awaiting_authors with the authors and a proposed map until seam_import_authors answers') },
|
|
203
|
-
seam_export_remote: { quilt: z.string().max(100).optional().describe('The quilt'), target: z.string().max(2000).describe('The git remote'), lines: z.array(z.string().max(100)).max(20).optional().describe('Lines to export (default ["main"]); release/* for every release line'), releases: z.boolean().optional().describe('Push release tags too'), credential: z.string().max(100).optional().describe('The name of the server secret that may push'), scratch: z.boolean().optional().describe('A scratch remote nothing pins a sha from'), enabled: z.boolean().optional().describe('false turns the export off'), lfs: z.object({ url: z.string().max(2000).describe('The LFS endpoint (…/info/lfs)'), threshold_bytes: z.number().int().min(0).optional().describe('Files over this many bytes go to LFS (default 50 MiB)') }).optional().describe('Git LFS on the remote: big files and filter=lfs paths go as LFS pointers. Set before the first export') },
|
|
204
|
+
seam_export_remote: { quilt: z.string().max(100).optional().describe('The quilt'), target: z.string().max(2000).describe('The git remote'), lines: z.array(z.string().max(100)).max(20).optional().describe('Lines to export (default ["main"]); release/* for every release line'), releases: z.boolean().optional().describe('Push release tags too'), credential: z.string().max(100).optional().describe('The name of the server secret that may push'), scratch: z.boolean().optional().describe('A scratch remote nothing pins a sha from'), enabled: z.boolean().optional().describe('false turns the export off'), lfs: z.object({ url: z.string().max(2000).describe('The LFS endpoint (…/info/lfs)'), threshold_bytes: z.number().int().min(0).optional().describe('Files over this many bytes go to LFS (default 50 MiB)') }).optional().describe('Git LFS on the remote: big files and filter=lfs paths go as LFS pointers. Set before the first export'), main_as: z.string().max(100).optional().describe('The branch name main has on the remote (default main), such as master or trunk'), push: z.enum(['patch', 'tag']).optional().describe('patch (default): after every merged patch; tag: only up to the newest patch a tag or release points at'), exclude: z.array(z.string().max(500)).max(100).optional().describe('Paths left out of the exported tree: a folder ending in /, a file or a glob. Set before the first export') },
|
|
204
205
|
seam_export_archive: { quilt: z.string().max(100).optional().describe('The quilt'), out: z.string().max(1000).optional() },
|
|
205
206
|
seam_export_tarball: { quilt: z.string().max(100).optional().describe('The quilt'), rev: z.string().max(200).optional(), paths: z.array(z.string().max(1000)).max(100).optional(), out: z.string().max(1000).optional() },
|
|
206
207
|
seam_export_status: { quilt: z.string().max(100).optional().describe('The quilt') },
|
|
208
|
+
seam_export_push: { quilt: z.string().max(100).optional().describe('The quilt') },
|
|
207
209
|
seam_import_cutover: { id: z.string().max(100).describe('The import id'), credential: z.string().max(100).optional().describe('The server secret that may push to the source (default the import\'s)') },
|
|
208
210
|
seam_import_status: { id: z.string().max(100).describe('The import id') },
|
|
209
211
|
seam_import_authors: { id: z.string().max(100).describe('The import id'), authors: z.record(z.string(), z.string()).describe('Git author email → member id of the quilt') },
|
|
@@ -530,7 +532,8 @@ export async function runSeamTool (name, args, { client, found = null, hosted =
|
|
|
530
532
|
}
|
|
531
533
|
case 'seam_github_import': { const r = await client.importGithub({ installation_id: args.installation, repo: args.repo, slug: args.into, follow: args.follow !== false }); return `Importing ${args.repo} into ${r.id ? (args.into || args.repo.split('/')[1]) : '?'} (import ${r.id})${r.follow ? ', following it' : ''}.` }
|
|
532
534
|
case 'seam_import_remote': { const r = await client.startImport({ url: args.url, slug: args.into, follow: !!args.follow, interval: args.interval, credential: args.credential, authors: args.authors, ask_authors: !!args.ask_authors }); return `Importing ${args.url} into ${args.into} (import ${r.id})${r.ask_authors ? ', waiting for its authors first (seam_import_status, then seam_import_authors)' : ''}${r.follow ? `, following every ${r.interval_s} s; poke secret ${r.poke_secret} (shown once)` : ''}.` }
|
|
533
|
-
case 'seam_export_remote': { const r = await client.setExport(needQuilt(), { target: args.target, lines: args.lines, releases: args.releases, credential: args.credential, scratch: args.scratch, enabled: args.enabled !== false, lfs: args.lfs }); return r.enabled ? `Exporting ${r.lines.join(', ')} to ${r.target} after each merge.` : `The export to ${r.target} is off.` }
|
|
535
|
+
case 'seam_export_remote': { const r = await client.setExport(needQuilt(), { target: args.target, lines: args.lines, releases: args.releases, credential: args.credential, scratch: args.scratch, enabled: args.enabled !== false, lfs: args.lfs, main_as: args.main_as, push: args.push, exclude: args.exclude }); return r.enabled ? `Exporting ${r.lines.join(', ')} to ${r.target} ${r.push === 'tag' ? 'up to the newest tagged patch' : 'after each merge'}.` : `The export to ${r.target} is off.` }
|
|
536
|
+
case 'seam_export_push': { const r = await client.exportPush(needQuilt()); return `Pushing to ${r.target} now; seam_export_status shows how it went.` }
|
|
534
537
|
case 'seam_export_archive': {
|
|
535
538
|
if (hosted) return `This server cannot write files to your computer. Fetch the archive over HTTP with your token: POST /v1/quilts/${encodeURIComponent(needQuilt())}/exit/archive`
|
|
536
539
|
const r = await client.exitArchive(needQuilt())
|
|
@@ -548,7 +551,7 @@ export async function runSeamTool (name, args, { client, found = null, hosted =
|
|
|
548
551
|
writeFileSync(file, r.bytes)
|
|
549
552
|
return `Wrote ${args.rev || 'main'} (${String(r.commit || 'empty').slice(0, 12)}) to ${file}: ${r.bytes.length} bytes.`
|
|
550
553
|
}
|
|
551
|
-
case 'seam_export_status': { const r = await client.exportStatus(needQuilt()); return JSON.stringify({ target: r.target, lines: r.lines, releases: r.releases, enabled: r.enabled, status: r.status }, null, 2) }
|
|
554
|
+
case 'seam_export_status': { const r = await client.exportStatus(needQuilt()); return JSON.stringify({ target: r.target, lines: r.lines, main_as: r.main_as, push: r.push, exclude: r.exclude, releases: r.releases, enabled: r.enabled, status: r.status }, null, 2) }
|
|
552
555
|
case 'seam_import_cutover': { const r = await client.cutover(args.id, { credential: args.credential }); return `Cut over: import ${r.import.id} is done; main exports to ${r.export.target} after each merge.` }
|
|
553
556
|
case 'seam_import_status': return describeImportRecord(await client.importStatus(args.id))
|
|
554
557
|
case 'seam_import_authors': { const r = await client.answerImportAuthors(args.id, { authors: args.authors }); return `Import ${r.id} has its authors and runs now.` }
|
package/package.json
CHANGED