@0x26/amp 0.6.0 → 0.6.1
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/dist/index.js +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ Preview only; use --json or --out <file> for all returned data.`:"")}var current
|
|
|
14
14
|
`)?err.body:`${err.body}
|
|
15
15
|
`)):err instanceof NotLoggedInError?process.stderr.write(`${err.message}
|
|
16
16
|
`):process.stderr.write(`${err instanceof Error?err.message:String(err)}
|
|
17
|
-
`),process.exitCode=1}var DoorRefusalError,init_http=__esm({"src/http.ts"(){"use strict";init_experience(),init_brand(),init_credentials(),init_machine(),init_env_customer(),init_session(),init_request_credential(),DoorRefusalError=class extends Error{constructor(status,body){super(`door refused (HTTP ${status})`),this.status=status,this.body=body}}}});init_terminal();var CLI_VERSION="0.6.
|
|
17
|
+
`),process.exitCode=1}var DoorRefusalError,init_http=__esm({"src/http.ts"(){"use strict";init_experience(),init_brand(),init_credentials(),init_machine(),init_env_customer(),init_session(),init_request_credential(),DoorRefusalError=class extends Error{constructor(status,body){super(`door refused (HTTP ${status})`),this.status=status,this.body=body}}}});init_terminal();var CLI_VERSION="0.6.1";init_brand();init_config();init_credentials();init_lock();init_experience();init_brand();init_brand();init_workos();init_credentials();init_env_customer();init_config();init_brand();var MAX_BYTES=65536;function skillUrl(service){let url=new URL(service);if(url.protocol!=="https:"||url.username||url.password||url.search||url.hash||url.pathname!=="/"||!/^(?:[a-z0-9.-]+|\[[a-f0-9:]+\])$/i.test(url.hostname)||/[\s\\]/.test(service))throw new Error("Use an HTTPS Ask service origin without a path or credentials.");return`${url.origin}/skill.md`}var skillVersion=text=>createHash2("sha256").update(text).digest("hex");function validSkill(text){return typeof text=="string"&&Buffer.byteLength(text)<=MAX_BYTES&&/^---\r?\nname: amp-cli\r?\n/.test(text)&&/^description: .+/m.test(text)&&!text.includes("\0")}async function fetchSkill(service,bundled,options={}){let url=skillUrl(service),file=join3(options.cacheDir??join3(homedir3(),".cache","amp","skills"),`${skillVersion(url)}.json`),cached3;try{let raw=readFileSync3(file);if(raw.length<=MAX_BYTES*2){let value=JSON.parse(raw.toString());value.url===url&&validSkill(value.text)&&(value.etag===void 0||typeof value.etag=="string"&&value.etag.length<=200&&!/[\r\n]/.test(value.etag))&&(cached3=value)}}catch{}let result=(text,source,stale,warning)=>({text,source,stale,url,version:skillVersion(text),...warning?{warning}:{}});try{let response=await(options.fetch??fetch)(url,{redirect:"error",credentials:"omit",signal:AbortSignal.timeout(options.timeoutMs??5e3),headers:{Accept:"text/markdown",...cached3?.etag?{"If-None-Match":cached3.etag}:{}}});if(response.status===304&&cached3)return result(cached3.text,"cache",!1);if(response.status!==200||response.redirected||!response.headers.get("content-type")?.startsWith("text/markdown"))throw await response.body?.cancel(),new Error("Invalid skill response");if(Number(response.headers.get("content-length"))>MAX_BYTES)throw await response.body?.cancel(),new Error("Skill too large");let reader=response.body?.getReader();if(!reader)throw new Error("Missing skill body");let chunks=[],bytes=0;try{for(;;){let{done,value}=await reader.read();if(done)break;if(bytes+=value.byteLength,bytes>MAX_BYTES)throw new Error("Skill too large");chunks.push(value)}}finally{await reader.cancel().catch(()=>{})}let text=new TextDecoder("utf-8",{fatal:!0}).decode(Buffer.concat(chunks));if(!validSkill(text))throw new Error("Invalid skill");let etag=response.headers.get("etag"),next={url,text,...etag&&etag.length<=200&&!/[\r\n]/.test(etag)?{etag}:{}},temporary=`${file}.${randomUUID()}.tmp`;try{mkdirSync3(dirname3(file),{recursive:!0,mode:448}),writeFileSync3(temporary,JSON.stringify(next),{mode:384}),renameSync(temporary,file)}catch{return result(text,"remote",!1,"Skill fetched; local cache could not be saved.")}finally{try{rmSync2(temporary,{force:!0})}catch{}}return result(text,"remote",!1)}catch{return result(cached3?.text??bundled(),cached3?"cache":"bundled",!0,"Published skill unavailable; using fallback instructions. Retry in a new chat or on explicit refresh.")}}init_experience();init_brand();init_brand();init_config();init_lock();init_brand();init_brand();init_credentials();var PACKAGE_NAME=NPM_PACKAGE,TTL_MS=1440*60*1e3;function isNewer(current2,candidate){let parse=v=>v.replace(/^v/,"").split("-")[0].split(".").map(n=>Number.parseInt(n,10)||0),a=parse(current2),b=parse(candidate);for(let i=0;i<Math.max(a.length,b.length);i+=1){let x=a[i]??0,y=b[i]??0;if(y>x)return!0;if(y<x)return!1}return!1}function fetchLatest(runner=(cmd,args)=>execFileSync(cmd,args,{encoding:"utf8",timeout:4e3,stdio:["ignore","pipe","ignore"]})){try{let out=runner("npm",["view",PACKAGE_NAME,"version","--json"]).trim(),parsed=JSON.parse(out);return typeof parsed=="string"?parsed:Array.isArray(parsed)&&typeof parsed[parsed.length-1]=="string"?parsed[parsed.length-1]:null}catch{return null}}var HOOK_MARKER="amp --agent skill sync",HOOK_COMMAND=`command -v amp >/dev/null 2>&1 && ${HOOK_MARKER} || true`;function npmInstall(spec){return spawnSync("npm",["install","-g",spec],{stdio:"ignore",timeout:9e4,shell:process.platform==="win32"}).status===0}function ensureLatestCli(opts={}){let env=opts.env??process.env,current2=CLI_VERSION;if(env.AMP_NO_UPDATE_CHECK==="1")return{status:"skipped",current:current2};let latest=(opts.latest??fetchLatest)();return latest?isNewer(current2,latest)?{status:(opts.install??npmInstall)(`${NPM_PACKAGE}@${latest}`)?"updated":"failed",current:current2,latest}:{status:"current",current:current2,latest}:{status:"unknown",current:current2}}function claudeSettingsPath(){return join5(homedir4(),".claude","settings.json")}function installSessionHook(settingsPath=claudeSettingsPath()){if(!existsSync4(dirname5(settingsPath)))return"skipped";let settings={};if(existsSync4(settingsPath))try{let parsed=JSON.parse(readFileSync5(settingsPath,"utf8"));if(!parsed||typeof parsed!="object"||Array.isArray(parsed))return"skipped";settings=parsed}catch{return"skipped"}let hooks=settings.hooks??{};if(!hooks||typeof hooks!="object"||Array.isArray(hooks))return"skipped";let sessionStart=hooks.SessionStart??[];if(!Array.isArray(sessionStart))return"skipped";if(sessionStart.some(group=>Array.isArray(group?.hooks)&&group.hooks.some(h=>typeof h?.command=="string"&&h.command.includes(HOOK_MARKER))))return"present";sessionStart.push({matcher:"startup|clear",hooks:[{type:"command",command:HOOK_COMMAND,timeout:120}]}),settings.hooks={...hooks,SessionStart:sessionStart};let tmp=`${settingsPath}.${process.pid}.tmp`;return writeFileSync5(tmp,`${JSON.stringify(settings,null,2)}
|
|
18
18
|
`),renameSync2(tmp,settingsPath),"installed"}function reexecSync(target){let r=spawnSync("amp",["--agent","skill","sync","--skip-update",...target===defaultInstallPath()?[]:["--dir",dirname5(target)]],{encoding:"utf8",timeout:3e4,shell:process.platform==="win32"});if(r.status!==0)return null;try{return JSON.parse(r.stdout).data}catch{return null}}async function syncSkill(opts={}){let target=opts.target??defaultInstallPath(),lock=join5(dirname5(configPath()),"skill-sync.lock");mkdirSync5(dirname5(lock),{recursive:!0,mode:448});let cli=opts.skipUpdate?{status:"skipped",current:CLI_VERSION}:await withFileLock(lock,async()=>(opts.update??ensureLatestCli)());if(cli.status==="updated"){let child=(opts.reexec??reexecSync)(target);if(child)return{...child,cli}}return withFileLock(lock,async()=>{let result={cli,skill:{path:target,outcome:installSkill(target)}},service=existsSync4(target)?skillService(readFileSync5(target,"utf8")):void 0;if(service){let published=await fetchSkill(service,bundledSkill,{fetch:opts.fetch,cacheDir:opts.cacheDir});result.published={url:published.url,source:published.source,stale:published.stale,version:published.version,...published.warning?{warning:published.warning}:{}}}return result})}var STAMP_PREFIX="<!-- amp-managed skill \xB7 amp ";function bundledSkillPath(){return resolve(dirname6(fileURLToPath(import.meta.url)),"..","skill","SKILL.md")}function bundledSkill(){let p=bundledSkillPath();if(!existsSync5(p))throw new Error("Bundled skill missing. Reinstall the CLI package.");return readFileSync6(p,"utf8")}function defaultInstallPath(){return join6(homedir5(),".claude","skills","amp-cli","SKILL.md")}function stamped(text){return`${STAMP_PREFIX}${CLI_VERSION} \u2014 bundled customer skill; remove this stamp to preserve manual edits -->
|
|
19
19
|
${text}`}function isAmpManaged(text){return text.startsWith(STAMP_PREFIX)}function installSkill(target=defaultInstallPath(),service){let current2=existsSync5(target)?readFileSync6(target,"utf8"):void 0;if(current2!==void 0&&!isAmpManaged(current2))return"kept-hand-edited";let publisher=service??(current2===void 0?void 0:skillService(current2)),next=stamped(publisher?bootstrapSkill(publisher):bundledSkill());return current2!==void 0?(current2===next||writeFileSync6(target,next),"refreshed"):(mkdirSync6(dirname6(target),{recursive:!0}),writeFileSync6(target,next),"installed")}function skillService(text){return text.match(/^<!-- amp-skill-service: (https:\/\/[^\s]+) -->$/m)?.[1]}function bootstrapSkill(service){let url=skillUrl(service),origin2=new URL(url).origin;return`---
|
|
20
20
|
name: amp-cli
|
|
@@ -189,7 +189,7 @@ ${data.note}`:""].join(`
|
|
|
189
189
|
${answer2}`})].join(`
|
|
190
190
|
`)}}}async function usage(view,id,options,injected={}){if(requestCredentialConfigured()||machineConfigFromEnv())throw new CliError("INVALID_ARGUMENT","Usage requires a saved human session; machine and request credentials cannot read Ask usage.");if(!USAGE_VIEWS.includes(view))throw new CliError("INVALID_ARGUMENT",`Unknown view "${view}". Use one of: ${USAGE_VIEWS.join(", ")}.`,!1,"amp usage --help");if(view==="conversation"?!id||!/^conv_[A-Za-z0-9_-]{1,128}$/.test(id):id!==void 0)throw new CliError("INVALID_ARGUMENT",view==="conversation"?"Give a conversation id: usage conversation conv_<id>.":"Only the conversation view takes an id.");let io={...defaults,...injected},first=await io.token(),org=tokenOrg(first),store=origin(io.store(),!0),request=async(url,method,body)=>{let token=await io.token();if(tokenOrg(token)!==org)throw new CliError("ASK_FAILED","Human session changed tenant; refusing usage request.");let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),12e4),response;try{response=await io.fetch(url,{method,redirect:"error",signal:controller.signal,headers:{Authorization:`Bearer ${token}`,Accept:"application/json",...body===void 0?{}:{"Content-Type":"application/json"}},...body===void 0?{}:{body:JSON.stringify(body)}})}catch{throw new CliError("ASK_FAILED","Ask connection unavailable or interrupted.",!0)}finally{clearTimeout(timeout)}if(!response.ok)throw response.body?.cancel().catch(()=>{}),response.status===403?new CliError("ACCESS_DENIED","Ask usage is admin-only. Ask your workspace administrator for access.",!1,"amp login --status"):response.status===400?new CliError("INVALID_ARGUMENT","The usage request was rejected. Check --since/--until (a date, an ISO time with a zone, or 7d/4w/3m), --by and --user.",!1,"amp usage --help"):httpError(response.status);let text=await response.text();if(Buffer.byteLength(text)>MAX_BYTES2)throw new CliError("ASK_FAILED","Ask usage response exceeds the supported size; narrow --since/--until or --limit.");try{return JSON.parse(text)}catch{throw new CliError("ASK_FAILED","Invalid Ask response.")}},config=await request(`${store.origin}/v1/ask/config`,"GET");if(!object2(config)||config.org_id!==org||config.protocol_version!==1)throw new CliError("ASK_FAILED","Ask discovery does not match this session's tenant/protocol.");let endpoint=origin(config.endpoint,loopback(store)).origin,data=view==="conversation"?await request(`${endpoint}/v1/conversations/${id}`,"GET"):await request(`${endpoint}/v1/usage`,"POST",usageBody(view,options,options.timezone??io.timezone?.()));if(!object2(data))throw new CliError("ASK_FAILED","Invalid Ask response.");let machine=options.json||experience().json||experience().agent;return io.stdout(machine?`${JSON.stringify(experience().agent?envelope(data,{view}):data)}
|
|
191
191
|
`:`${formatUsage(view,data)}
|
|
192
|
-
`),data}function registerUsage(program2){program2.command("usage [view] [id]").description("Ask usage (admin only): summary, users, trend, questions, failures, or one conversation's full history").option("--since <when>","start: a date, an ISO time with a zone, or 7d / 4w / 3m ago (default 30 days)").option("--until <when>","end (exclusive), same forms (default now)").option("--user <email-or-id>","only this person; repeatable",(value,previous=[])=>[...previous,value]).option("--by <period>","trend buckets: day, week or month (default day)").option("--timezone <zone>","timezone for days and weeks (defaults to your computer timezone)").option("--limit <n>","questions to list, 1-1000 (default 100)").option("--with-answers","include answer text in the questions view").option("--json","write the structured response to stdout").addHelpText("after",`
|
|
192
|
+
`),data}function registerUsage(program2,{hidden=!1}={}){program2.command("usage [view] [id]",{hidden}).description("Ask usage (admin only): summary, users, trend, questions, failures, or one conversation's full history").option("--since <when>","start: a date, an ISO time with a zone, or 7d / 4w / 3m ago (default 30 days)").option("--until <when>","end (exclusive), same forms (default now)").option("--user <email-or-id>","only this person; repeatable",(value,previous=[])=>[...previous,value]).option("--by <period>","trend buckets: day, week or month (default day)").option("--timezone <zone>","timezone for days and weeks (defaults to your computer timezone)").option("--limit <n>","questions to list, 1-1000 (default 100)").option("--with-answers","include answer text in the questions view").option("--json","write the structured response to stdout").addHelpText("after",`
|
|
193
193
|
Examples:
|
|
194
194
|
amp usage 30-day summary
|
|
195
195
|
amp usage users --since 2026-09-01 who uses Ask, and how much
|
|
@@ -200,4 +200,4 @@ Examples:
|
|
|
200
200
|
|
|
201
201
|
Turns are attributed to the person who started the conversation.`).action(async(view,id,opts)=>{await usage(view??"summary",id,opts)})}init_experience();init_brand();init_brand();init_http();async function catalog(includeHidden=!1){let result=JSON.parse(await doorRequest("GET","/v1/ontology/object-types"));if(!Array.isArray(result.objectTypes))throw new Error("Invalid schema response.");return result.objectTypes}function publicSchema(row){if(typeof row.apiName!="string"||!/^[A-Za-z_][A-Za-z0-9_]*$/.test(row.apiName))throw new Error("Invalid schema response.");return{name:row.apiName,table:`main_${row.apiName}`,description:row.description??"",columns:Object.entries(row.properties??{}).map(([name,property])=>({name,type:property.baseType??"unknown"}))}}async function schema(table,opts){readContext();let rows=(await catalog()).map(publicSchema);if(table!==void 0){let row=rows.find(row2=>row2.name===table||row2.table===table);if(!row)throw new CliError("NOT_FOUND","That table is unavailable in this workspace.",!1,"amp schema");emit(row,opts,()=>`${row.table} \u2014 ${row.description}
|
|
202
202
|
${humanTable(row.columns)}`)}else emit({tables:rows},opts,()=>humanTable(rows.map(row=>({table:row.table,description:row.description,columns:row.columns.length}))))}function registerSchema(program2){program2.command("schema").argument("[table]","type name from the authorized catalog").description("List authorized types and columns").option("--json","compact JSON output").option("--out <file>","write results to a file").action(schema)}init_request_credential();init_machine();init_experience();init_http();var program=new Command().name("amp").description("Query your data with Ampersand").version(CLI_VERSION).option("--profile <name>","select a saved tenant profile").option("--agent","structured JSON for agents; never prompt").option("--human","readable output for people").option("--quiet","hide routine progress").option("--no-input","never open a browser or wait for input").exitOverride().configureOutput({writeErr:()=>{}}).hook("preAction",(_,action)=>{if(configureExperience({...program.opts(),json:action.opts().json}),requestCredentialConfigured()||machineConfigFromEnv())throw new CliError("UNSUPPORTED_IDENTITY","Use a saved human session. Remove machine/request credentials first. Agent output does not change identity.");setProfileOverride(program.opts().profile)});installTerminalHelp(program,{edition:"workspace CLI",examples:["amp login --store <workspace-url>","amp schema",'amp ask "What data is available to me?"']});program.command("login").description("Sign in or manage your local session").option("--store <url>","tenant store HTTPS origin").option("--name <profile>","saved profile name").option("--org <id>","select your organization during sign-in").option("--status","show the signed-in identity").option("--logout","remove credentials for the selected profile on this machine").option("--json","raw JSON output (compatible with existing scripts)").option("--install-skill","install the bundled skill; can run without signing in").option("--skill-dir <path>","install SKILL.md in this directory; requires --install-skill").option("--skill-service <origin>","install a skill that refreshes from this HTTPS Ask service; requires --install-skill").action(async opts=>{if(opts.status&&opts.logout||(opts.status||opts.logout)&&(opts.store||opts.name||opts.org||opts.installSkill||opts.skillDir||opts.skillService))throw new CliError("INVALID_ARGUMENT","Use --status or --logout alone, or sign in with --store.");if(opts.skillDir&&!opts.installSkill)throw new CliError("INVALID_ARGUMENT","--skill-dir requires --install-skill.");if(opts.skillService&&!opts.installSkill)throw new CliError("INVALID_ARGUMENT","--skill-service requires --install-skill.");if(opts.skillService)try{skillUrl(opts.skillService)}catch{throw new CliError("INVALID_ARGUMENT","Use --skill-service with an HTTPS Ask service origin, without a path or credentials.")}let install=()=>{let skill=installSkill(opts.skillDir?join8(resolve2(opts.skillDir),"SKILL.md"):void 0,opts.skillService),hook=opts.skillDir||skill==="kept-hand-edited"?"skipped":installSessionHook();return{skill,hook}},describe=({skill,hook})=>`Skill ${skill}.${hook==="installed"?" Claude Code will update amp and refresh the skill when each new session starts.":""}`;if(opts.status)return whoami();if(opts.installSkill&&!opts.store&&!opts.name&&!opts.org){let result=install();emit(result,opts,()=>`${describe(result)} Start a new agent session to load it.`);return}if(opts.logout){let path=credentialsPath();existsSync7(path)&&await withFileLock(`${path}.lock`,async()=>{rmSync3(path,{force:!0})}),emit({logged_out:!0},opts,()=>"Local session removed.");return}let store=opts.store??activeProfile()?.store_url;if(!store)throw new CliError("WORKSPACE_REQUIRED","Choose your workspace to sign in.",!1,"amp login --store <your tenant store URL>");await login({store,name:opts.name,orgId:opts.org}),opts.installSkill&&process.stdout.write(`${describe(install())}
|
|
203
|
-
`)});registerSkill(program);registerSchema(program);registerSql(program);registerAsk(program);registerUsage(program);program.parseAsync(process.argv).catch(error=>{if(!(error instanceof CommanderError&&error.exitCode===0)){if(!experience().enabled)try{configureExperience(program.opts())}catch{configureExperience({agent:!0})}reportError(error instanceof CommanderError?new CliError("INVALID_ARGUMENT","Unknown command or invalid arguments. Run amp --help.",!1,"amp --help"):error)}});
|
|
203
|
+
`)});registerSkill(program);registerSchema(program);registerSql(program);registerAsk(program);registerUsage(program,{hidden:!0});program.parseAsync(process.argv).catch(error=>{if(!(error instanceof CommanderError&&error.exitCode===0)){if(!experience().enabled)try{configureExperience(program.opts())}catch{configureExperience({agent:!0})}reportError(error instanceof CommanderError?new CliError("INVALID_ARGUMENT","Unknown command or invalid arguments. Run amp --help.",!1,"amp --help"):error)}});
|