autark-cli 0.4.2 → 0.5.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.
Files changed (2) hide show
  1. package/autark.mjs +4 -113
  2. package/package.json +1 -1
package/autark.mjs CHANGED
@@ -227,10 +227,6 @@ async function main() {
227
227
  if (command === 'delete') return feedbackDelete(rest)
228
228
  if (!command || command === '--help' || command === '-h') return feedbackUsage()
229
229
  }
230
- if (group === 'deliverability') {
231
- if (command === 'check') return deliverabilityCheck(rest)
232
- if (!command || command === '--help' || command === '-h') return deliverabilityUsage()
233
- }
234
230
  if (group === 'context') {
235
231
  if (!command || command === '--help' || command === '-h') return contextUsage()
236
232
  return context([command, ...rest].filter(Boolean))
@@ -782,60 +778,6 @@ function feedbackUsage() {
782
778
  autark feedback delete <feedback-id>`)
783
779
  }
784
780
 
785
- // ====================================================== deliverability
786
-
787
- // Pre-send email validator. Calls AgentMail's recipient-check endpoint so the
788
- // agent can avoid blasting a guessed/permutated address and inflating the
789
- // bounce rate. Falls back to a syntactic check if the endpoint is unreachable.
790
- async function deliverabilityCheck(rest) {
791
- const opts = parseArgs(rest)
792
- const email = required(opts.email || opts._[0], 'email')
793
- const creds = loadCredentials() || {}
794
- const token = creds.agentmail_token
795
- let verdict = { email, deliverable: null, source: 'syntactic', reason: '' }
796
-
797
- if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
798
- verdict = { ...verdict, deliverable: false, reason: 'malformed address' }
799
- console.log(JSON.stringify(verdict, null, 2))
800
- process.exitCode = 1
801
- return
802
- }
803
- if (!token) {
804
- verdict.reason = 'no agentmail token; syntactic check only'
805
- console.log(JSON.stringify(verdict, null, 2))
806
- return
807
- }
808
-
809
- try {
810
- const res = await fetch('https://api.agentmail.to/v0/deliverability/check', {
811
- method: 'POST',
812
- headers: { authorization: `Bearer ${token}`, 'content-type': 'application/json' },
813
- body: JSON.stringify({ email }),
814
- })
815
- if (!res.ok) {
816
- verdict.reason = `agentmail check ${res.status}; fell back to syntactic`
817
- verdict.deliverable = null
818
- } else {
819
- const body = await res.json().catch(() => ({}))
820
- verdict.source = 'agentmail'
821
- verdict.deliverable = body.deliverable !== false
822
- verdict.reason = body.reason || ''
823
- if (body.risk) verdict.risk = body.risk
824
- }
825
- } catch (err) {
826
- verdict.reason = `network error: ${err.message}`
827
- }
828
- console.log(JSON.stringify(verdict, null, 2))
829
- if (verdict.deliverable === false) process.exitCode = 1
830
- }
831
-
832
- function deliverabilityUsage() {
833
- console.log(`autark deliverability check <email>
834
- Returns JSON {email, deliverable, source, reason}. Exits non-zero when the
835
- address is known-undeliverable. Call this before logging an email action so
836
- bounces don't tank your domain rep.`)
837
- }
838
-
839
781
  // rejectUnsendableAddress is defined near the top of the file (before main()
840
782
  // runs) so the const Sets it depends on are out of TDZ when mailSend invokes
841
783
  // it. See block tagged "address reject" up top.
@@ -856,9 +798,6 @@ async function mail(command, rest) {
856
798
  if (command === 'raw') return mailRaw(rest)
857
799
  if (command === 'attachment') return mailAttachment(rest)
858
800
  if (command === 'request') return mailRequest(rest)
859
- if (command === 'suppress') return mailSuppress(rest)
860
- if (command === 'unsuppress') return mailUnsuppress(rest)
861
- if (command === 'suppressed') return mailSuppressed(rest)
862
801
  if (command === 'lint') return mailLint(rest)
863
802
  mailUsage()
864
803
  process.exit(1)
@@ -937,27 +876,6 @@ async function mailLint(rest) {
937
876
  process.exit(1)
938
877
  }
939
878
 
940
- async function mailSuppress(rest) {
941
- const opts = parseArgs(rest)
942
- const entry = required(opts.email || opts._[0], 'email')
943
- const reason = opts.reason || 'manual'
944
- const result = await api('POST', '/v1/suppression', { entry, reason })
945
- printJson(result)
946
- }
947
-
948
- async function mailUnsuppress(rest) {
949
- const opts = parseArgs(rest)
950
- const entry = required(opts.email || opts._[0], 'email')
951
- const result = await api('DELETE', `/v1/suppression/${encodeURIComponent(entry)}`)
952
- printJson(result)
953
- }
954
-
955
- async function mailSuppressed(rest) {
956
- const opts = parseArgs(rest)
957
- const limit = opts.limit ? Number(opts.limit) : 100
958
- const result = await api('GET', `/v1/suppression?limit=${limit}`)
959
- printJson(result)
960
- }
961
879
 
962
880
  async function mailSetup(rest) {
963
881
  const opts = parseArgs(rest)
@@ -990,10 +908,9 @@ async function mailSend(rest) {
990
908
  rejectUnsendableAddress(to)
991
909
  const subject = opts.subject || ''
992
910
  const body = mailBody(opts, { to, subject })
993
- const anchor = readAnchorOpts(opts)
994
911
  const dryRun = opts['dry-run'] === true || opts.dry_run === true
995
912
  if (dryRun) {
996
- printJson({ dry_run: true, would_send: { inbox: creds.inboxId, to, subject, body, anchor } })
913
+ printJson({ dry_run: true, would_send: { inbox: creds.inboxId, to, subject, body } })
997
914
  return
998
915
  }
999
916
  const result = await agentmailRequest('POST', `/inboxes/${encodeURIComponent(creds.inboxId)}/messages/send`, body)
@@ -1003,30 +920,10 @@ async function mailSend(rest) {
1003
920
  recipient: to.join(','),
1004
921
  subject,
1005
922
  response: result,
1006
- metadata: anchor ? { anchor_quote: anchor.quote, anchor_url: anchor.url } : {},
1007
923
  })
1008
924
  printJson({ ...result, autark_action_id: action?.id })
1009
925
  }
1010
926
 
1011
- // Optional anchor-quote primitive. The cold-outreach skill recommends that
1012
- // every send carry a verbatim quote from the recipient's public surface
1013
- // (HN comment, GitHub issue, tweet) plus the URL it was lifted from. The
1014
- // CLI doesn't (yet) enforce — when both are present they're validated and
1015
- // logged into the action's metadata; when absent the send still goes
1016
- // through. Flip to required once the prompt-side discipline catches up.
1017
- function readAnchorOpts(opts) {
1018
- let quote = opts['anchor-quote'] || opts.anchor_quote
1019
- const url = opts['anchor-url'] || opts.anchor_url
1020
- if (quote && String(quote).startsWith('@')) {
1021
- quote = fs.readFileSync(String(quote).slice(1), 'utf8').trim()
1022
- }
1023
- if (!quote && !url) return null
1024
- if (!quote || !url) throw new Error('--anchor-quote and --anchor-url must both be provided (or both omitted)')
1025
- if (String(quote).length < 30) throw new Error(`--anchor-quote too short (${String(quote).length} chars); need >=30 chars of verbatim recipient text`)
1026
- if (!/^https?:\/\//.test(String(url))) throw new Error(`--anchor-url must be a full URL, got: ${url}`)
1027
- return { quote: String(quote).trim(), url: String(url).trim() }
1028
- }
1029
-
1030
927
  async function mailReply(rest, mode) {
1031
928
  const opts = parseArgs(rest)
1032
929
  const creds = requireAgentmailCredentials()
@@ -1425,7 +1322,6 @@ function mailUsage() {
1425
1322
 
1426
1323
  setup --prefix <name> [--force]
1427
1324
  send --to <email[,email]> --subject <s> --text @body.txt [--run-id <id>] [--dry-run]
1428
- [--anchor-quote @./q.txt --anchor-url <url>] record the recipient's verbatim public quote
1429
1325
  reply --message-id <id> --text @reply.txt [--run-id <id>]
1430
1326
  reply-all --message-id <id> --text @reply.txt [--run-id <id>]
1431
1327
  forward --message-id <id> --to <email> [--text @body.txt] [--run-id <id>]
@@ -1436,15 +1332,11 @@ function mailUsage() {
1436
1332
  raw <message_id>
1437
1333
  attachment --message-id <id> --attachment-id <id> [--out file]
1438
1334
  request <METHOD> <path> [--body @json] [--raw]
1439
- suppress <email> [--reason "<text>"] add to org-wide send-block list
1440
- unsuppress <email> remove from send-block list
1441
- suppressed [--limit N] list blocked addresses
1442
1335
  lint --body @draft.txt | <stdin> grade a draft for AI-tells; exit 1 on violations
1443
1336
 
1444
- Mail uses the inbox-scoped token in ~/.autark/credentials.json. Suppression
1445
- verbs proxy through the autark worker (org-scoped). --dry-run prints the
1446
- payload without hitting SES. lint is fully local — runs the outreach skill's
1447
- hard-fail checks against a draft.`)
1337
+ Mail uses the inbox-scoped token in ~/.autark/credentials.json. --dry-run
1338
+ prints the payload without hitting SES. lint is fully local — runs the
1339
+ outreach skill's hard-fail checks against a draft.`)
1448
1340
  }
1449
1341
 
1450
1342
  function usage() {
@@ -1462,7 +1354,6 @@ function usage() {
1462
1354
  log action record one outreach touch
1463
1355
  action escalate flag an action for human attention
1464
1356
  feedback record|delete leave a free-text nudge on a hypothesis
1465
- deliverability check pre-send check for an email address
1466
1357
  context [<slug>|...] pull product or hypothesis context
1467
1358
 
1468
1359
  mail setup|send|reply|... send/read mail via your AgentMail inbox
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "autark-cli",
3
- "version": "0.4.2",
3
+ "version": "0.5.0",
4
4
  "description": "CLI for autark \u2014 hypothesis-driven product runbooks. Track products, hypotheses, runs, and actions from the terminal.",
5
5
  "type": "module",
6
6
  "license": "MIT",