@0x26/amp 0.6.1 → 0.6.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/dist/index.js +6 -4
- 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.2";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
|
|
@@ -149,10 +149,12 @@ Workspace: ${profile2?.name??"default"} \u2192 ${profile2?.store_url??bundle().m
|
|
|
149
149
|
`)}
|
|
150
150
|
`}function snapshot(value,conversation){if(!object(value)||!object(value.conversation)||value.conversation.id!==conversation||typeof value.status!="string"||!statuses.has(value.status)||value.active_request_id!==null&&!validId(value.active_request_id,"req")||!object(value.transcript)||value.transcript.conversation_id!==conversation||value.transcript.version!==1||!Array.isArray(value.transcript.entries))throw invalid();for(let entry of value.transcript.entries){if(!object(entry)||!validId(entry.request_id,"req")||entry.outcome!==void 0&&(typeof entry.outcome!="string"||!terminal.has(entry.outcome)))throw invalid();entry.outcome==="completed"&&answer(entry.answer)}return value}async function readChunk(reader,signal,timeout=6e4){let timer,abort;try{return await Promise.race([reader.read(),new Promise((_,reject)=>{abort=()=>reject(new Error("Ask connection interrupted.")),timer=setTimeout(()=>reject(new Error("Ask connection timed out.")),timeout),signal.addEventListener("abort",abort,{once:!0}),signal.aborted&&abort()})])}finally{clearTimeout(timer),abort&&signal.removeEventListener("abort",abort)}}async function jsonBody(response,signal,limit){if(!response.body)throw invalid();let reader=response.body.getReader(),chunks=[],size=0,deadline=Date.now()+3e4;try{for(;;){let{done,value}=await readChunk(reader,signal,Math.max(1,deadline-Date.now()));if(done)break;if(size+=value.byteLength,size>limit)throw new CliError("ASK_FAILED","Ask response exceeds the byte limit.");chunks.push(value)}try{return JSON.parse(Buffer.concat(chunks).toString("utf8"))}catch{throw invalid()}}finally{reader.cancel().catch(()=>{}),reader.releaseLock()}}async function events(response,conversation,request,io,signal){if(!response.headers.get("content-type")?.toLowerCase().startsWith("text/event-stream")||!response.body)throw invalid();let reader=response.body.getReader(),decoder=new TextDecoder("utf-8",{fatal:!0}),pending="",frameBytes=0,data=[],eventType="",sequence=-1;try{for(;;){let{done,value}=await readChunk(reader,signal).catch(()=>{throw new StreamDisconnected});if(done)throw new StreamDisconnected;for(let offset=0;offset<value.length;offset+=4096){pending+=decoder.decode(value.subarray(offset,offset+4096),{stream:!0});let newline;for(;(newline=pending.indexOf(`
|
|
151
151
|
`))>=0;){let line=pending.slice(0,newline);if(pending=pending.slice(newline+1),frameBytes+=Buffer.byteLength(line)+1,frameBytes>65536)throw new CliError("ASK_FAILED","Ask event exceeds the byte limit.");if(line.endsWith("\r")&&(line=line.slice(0,-1)),line===""){if(data.length){let event;try{event=JSON.parse(data.join(`
|
|
152
|
-
`))}catch{throw invalid()}if(!object(event)||event.conversation_id!==conversation||event.request_id!==request||typeof event.sequence!="number"||!Number.isSafeInteger(event.sequence)||event.sequence<=sequence||event.type!==eventType)throw invalid();switch(sequence=event.sequence,event.type){case"progress":if(typeof event.message!="string")throw invalid();let message=event.message.replace(/[\x00-\x1f\x7f-\x9f]/g," ").slice(0,1e3);io.
|
|
153
|
-
`)
|
|
152
|
+
`))}catch{throw invalid()}if(!object(event)||event.conversation_id!==conversation||event.request_id!==request||typeof event.sequence!="number"||!Number.isSafeInteger(event.sequence)||event.sequence<=sequence||event.type!==eventType)throw invalid();switch(sequence=event.sequence,event.type){case"progress":{if(typeof event.message!="string")throw invalid();let message=event.message.replace(/[\x00-\x1f\x7f-\x9f]/g," ").slice(0,1e3);event.kind==="note"?io.note?io.note(message):io.stderr(` \xB7 ${message}
|
|
153
|
+
`):io.progress?io.progress(message):io.stderr(`${message}
|
|
154
|
+
`);break}case"answer_delta":if(typeof event.text!="string")throw invalid();break;case"status":if(typeof event.status!="string"||!statuses.has(event.status))throw invalid();if(event.status==="cancelling"&&io.progress?.("Stopping work"),event.status==="idle"||event.status==="interrupted")return;break;case"completed":answer(event.answer);return;case"failed":return object(event.error)&&["unsupported_answer","evidence_unavailable"].includes(String(event.error.code))?String(event.error.code):void 0;case"cancelled":return;default:throw invalid()}}frameBytes=0,data=[],eventType=""}else if(line.startsWith("data:"))data.push(line.slice(5).replace(/^ /,""));else if(line.startsWith("event:"))eventType=line.slice(6).replace(/^ /,"");else if(!line.startsWith(":")&&!line.startsWith("id:")&&!line.startsWith("retry:"))throw invalid()}if(frameBytes+Buffer.byteLength(pending)>65536)throw new CliError("ASK_FAILED","Ask event exceeds the byte limit.")}}}finally{reader.cancel().catch(()=>{}),reader.releaseLock()}}async function ask(question,options,injected={}){if(requestCredentialConfigured()||machineConfigFromEnv())throw new CliError("ASK_FAILED","Ask requires a saved human session; machine and request credentials cannot invoke Ask.");if(options.watch&&options.cancel||(options.watch||options.cancel)&&question!==void 0||(options.watch||options.cancel)&&!options.conversation||options.idempotencyKey!==void 0&&(options.watch||options.cancel)||options.conversation!==void 0&&!validId(options.conversation,"conv"))throw new CliError("ASK_FAILED","Use a question, --watch, or --cancel. Watch/cancel require --conversation conv_<id>.");if(!options.watch&&!options.cancel&&(typeof question!="string"||!question.trim()||Buffer.byteLength(question)>32768))throw new CliError("ASK_FAILED","Ask requires a nonempty question of at most 32768 UTF-8 bytes.");if(options.idempotencyKey!==void 0&&(!/^[\x21-\x7e]{1,128}$/.test(options.idempotencyKey)||/[\r\n]/.test(options.idempotencyKey)))throw new CliError("ASK_FAILED","Invalid idempotency key.");let io={...defaults,...injected};experience().quiet&&(io.stderr=()=>{});let structured=(data,meta={})=>`${JSON.stringify(experience().agent?envelope(data,meta):data)}
|
|
154
155
|
`,machineOutput=options.json||experience().json||experience().agent,interactive=!machineOutput&&!experience().quiet&&process.env.TERM!=="dumb"&&(io.interactive??(!!process.stderr.isTTY&&!!process.stdout.isTTY)),status=interactive?askProgress(io.stderr,{color:colorEnabled(process.env,!!process.stderr.isTTY)}):void 0,lastStage="";io.progress=message=>{status?status.update(message):message!==lastStage&&(io.stderr(`${message}
|
|
155
|
-
`),lastStage=message)}
|
|
156
|
+
`),lastStage=message)},io.note=message=>{status?status.note(` \xB7 ${message}`):io.stderr(` \xB7 ${message}
|
|
157
|
+
`)};let submissionKey,aborter=new AbortController,onAbort=()=>aborter.abort();io.signal?.addEventListener("abort",onAbort,{once:!0}),io.signal?.aborted&&aborter.abort();let conversation=options.conversation;try{let firstToken=await io.token(),org=tokenOrg(firstToken),store=origin(io.store(),!0),profile=io.profile?.()??null,request=async(url,method="GET",body,key,stream=!1)=>{let token=await io.token();if(tokenOrg(token)!==org)throw new CliError("ASK_FAILED","Human session changed tenant; refusing Ask request.");let timeout=setTimeout(()=>aborter.abort(),15e3),response;try{response=await io.fetch(url,{method,redirect:"error",signal:aborter.signal,headers:{Authorization:`Bearer ${token}`,Accept:stream?"text/event-stream":"application/json",...body===void 0?{}:{"Content-Type":"application/json"},...key?{"Idempotency-Key":key}:{}},...body===void 0?{}:{body:JSON.stringify(body)}})}catch{throw new CliError("ASK_FAILED","Ask connection unavailable or interrupted.")}finally{clearTimeout(timeout)}if(response.redirected||response.status>=300&&response.status<400)throw response.body?.cancel().catch(()=>{}),new CliError("ASK_FAILED","Ask redirects are forbidden.");if(!response.ok)throw response.body?.cancel().catch(()=>{}),response.status!==409?httpError(response.status):response.status===409?new CliError("ASK_FAILED","Ask conflict (409): conversation_busy or idempotency_conflict; watch the existing conversation or retry the original input/key."):response.status===401?new CliError("ASK_FAILED","Ask authentication expired or revoked. Run amp login, then reattach."):new CliError("ASK_FAILED",`Ask request refused (HTTP ${response.status}).`);return response},config=await jsonBody(await request(`${store.origin}/v1/ask/config`),aborter.signal,65536);if(!object(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,route=()=>`${endpoint}/v1/conversations/${conversation}`,requestId;if(options.cancel){let response=await request(`${route()}/cancel`,"POST",{});if(response.status!==202)throw invalid();let cancelled=await jsonBody(response,aborter.signal,65536);if(!object(cancelled)||cancelled.request_id!==null&&!validId(cancelled.request_id,"req"))throw invalid();status?.stop(),machineOutput?io.stdout(structured({conversation_id:conversation,...cancelled})):io.stderr(`Cancellation requested for ${conversation}; work may still be stopping.
|
|
156
158
|
Check: amp ask --watch --conversation ${conversation}
|
|
157
159
|
`);return}if(!options.watch){let key=options.idempotencyKey??io.uuid();submissionKey=key,interactive||io.stderr(`Idempotency key: ${key}
|
|
158
160
|
`);let requestTimezone;try{let detected=options.timezone??io.timezone?.();if(detected){if(detected.length>100||!/^[A-Za-z_]+(?:\/[A-Za-z0-9_+.-]+)*(?![\s\S])/.test(detected))throw new Error;requestTimezone=new Intl.DateTimeFormat("en-US",{timeZone:detected}).resolvedOptions().timeZone}else if(options.timezone!==void 0)throw new Error}catch{if(options.timezone!==void 0)throw new CliError("ASK_FAILED","Use a valid IANA timezone, such as America/Los_Angeles.")}let response=await request(`${endpoint}/v1/ask`,"POST",{question,...requestTimezone?{timezone:requestTimezone}:{},...conversation?{conversation_id:conversation}:{}},key);if(response.status!==202)throw invalid();let accepted=await jsonBody(response,aborter.signal,65536);if(!object(accepted)||!validId(accepted.conversation_id,"conv")||!validId(accepted.request_id,"req")||conversation&&accepted.conversation_id!==conversation)throw invalid();if(conversation=accepted.conversation_id,requestId=accepted.request_id,io.progress?.("Question accepted"),!machineOutput){let hint=`You can leave this terminal; the request will continue.
|