adsinagents 0.1.5 → 0.1.7

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/cli/dist/index.js CHANGED
@@ -19,6 +19,7 @@ import { hostname } from "node:os";
19
19
  import { homedir } from "node:os";
20
20
  import { join } from "node:path";
21
21
  var ADLINE_DIR = join(homedir(), ".adsinagents");
22
+ var HOOK_PORT = 8473;
22
23
  var PATHS = {
23
24
  root: ADLINE_DIR,
24
25
  config: join(ADLINE_DIR, "config.json"),
@@ -4097,6 +4098,7 @@ function isCategory(value) {
4097
4098
  }
4098
4099
 
4099
4100
  // ../../shared/dist/schemas.js
4101
+ var AdSourceSchema = external_exports.enum(["gravity", "direct"]);
4100
4102
  var AdSchema = external_exports.object({
4101
4103
  /** Stable impression id for this rotation; idempotency key for firing. */
4102
4104
  id: external_exports.string().min(1),
@@ -4113,7 +4115,7 @@ var AdSchema = external_exports.object({
4113
4115
  /** Gravity click pixel (GET). Empty for direct campaigns. */
4114
4116
  clickUrl: external_exports.string().default(""),
4115
4117
  /** Source of demand. */
4116
- source: external_exports.enum(["gravity", "direct"]),
4118
+ source: AdSourceSchema,
4117
4119
  /** Unix ms when this ad was fetched into cache. */
4118
4120
  fetchedAt: external_exports.number().int(),
4119
4121
  /**
@@ -4216,7 +4218,11 @@ var ImpressionSchema = external_exports.object({
4216
4218
  verifiedAt: external_exports.number().int().nullable(),
4217
4219
  impFired: external_exports.boolean(),
4218
4220
  clicked: external_exports.boolean(),
4219
- source: external_exports.enum(["gravity", "direct"]),
4221
+ source: AdSourceSchema,
4222
+ /** Render surface the ad painted on. Only "statusline" is billable today
4223
+ * (spinner reach is un-billable and never writes a row). Recorded so the
4224
+ * publisher log can show *where* the ad showed. Older daemons omit it. */
4225
+ slot: external_exports.enum(["statusline", "spinner"]).default("statusline"),
4220
4226
  /** Server serve-proof echoed back on sync. Empty for standalone/unverified. */
4221
4227
  nonce: external_exports.string().default("")
4222
4228
  });
@@ -4899,7 +4905,7 @@ function buildPlan(placement, spinnerVerbs) {
4899
4905
  const statuslineCommand = existsSync5(nativeStatusline) ? nativeStatusline : `node ${join5(HERE2, "..", "..", "statusline", "dist", "index.js")}`;
4900
4906
  return {
4901
4907
  statuslineCommand,
4902
- hookBaseUrl: "http://127.0.0.1:8473",
4908
+ hookBaseUrl: `http://127.0.0.1:${HOOK_PORT}`,
4903
4909
  placement,
4904
4910
  spinnerVerbs,
4905
4911
  version: VERSION
@@ -4946,6 +4952,7 @@ async function cmdInit(flags) {
4946
4952
  }
4947
4953
  } else {
4948
4954
  process.stdout.write("\u2022 device already registered\n");
4955
+ if (cfg.claimToken) claimUrl = `${cfg.serverUrl}/claim?t=${cfg.claimToken}`;
4949
4956
  }
4950
4957
  const platform = getPlatform();
4951
4958
  const nodeBin = process.execPath;
@@ -4958,6 +4965,7 @@ async function cmdInit(flags) {
4958
4965
  process.stdout.write(`
4959
4966
  AdsInAgents is live (placement=${placement}). Run \`adsinagents doctor\` to verify.
4960
4967
  `);
4968
+ process.stdout.write("Restart Claude Code (quit + reopen) so the status line picks up the ad.\n");
4961
4969
  if (claimUrl) {
4962
4970
  process.stdout.write(
4963
4971
  `
@@ -14,6 +14,7 @@ import { writeFileSync as writeFileSync4 } from "node:fs";
14
14
  import { homedir } from "node:os";
15
15
  import { join } from "node:path";
16
16
  var ADLINE_DIR = join(homedir(), ".adsinagents");
17
+ var HOOK_PORT = 8473;
17
18
  var PATHS = {
18
19
  root: ADLINE_DIR,
19
20
  config: join(ADLINE_DIR, "config.json"),
@@ -4102,6 +4103,9 @@ function matchesBlocked(ad, blocked) {
4102
4103
  }
4103
4104
 
4104
4105
  // ../../shared/dist/schemas.js
4106
+ var AdSourceSchema = external_exports.enum(["gravity", "direct"]);
4107
+ var GRAVITY_CAMPAIGN_ID = "gravity";
4108
+ var FALLBACK_AD_URL = "https://trygravity.ai";
4105
4109
  var AdSchema = external_exports.object({
4106
4110
  /** Stable impression id for this rotation; idempotency key for firing. */
4107
4111
  id: external_exports.string().min(1),
@@ -4118,7 +4122,7 @@ var AdSchema = external_exports.object({
4118
4122
  /** Gravity click pixel (GET). Empty for direct campaigns. */
4119
4123
  clickUrl: external_exports.string().default(""),
4120
4124
  /** Source of demand. */
4121
- source: external_exports.enum(["gravity", "direct"]),
4125
+ source: AdSourceSchema,
4122
4126
  /** Unix ms when this ad was fetched into cache. */
4123
4127
  fetchedAt: external_exports.number().int(),
4124
4128
  /**
@@ -4222,7 +4226,11 @@ var ImpressionSchema = external_exports.object({
4222
4226
  verifiedAt: external_exports.number().int().nullable(),
4223
4227
  impFired: external_exports.boolean(),
4224
4228
  clicked: external_exports.boolean(),
4225
- source: external_exports.enum(["gravity", "direct"]),
4229
+ source: AdSourceSchema,
4230
+ /** Render surface the ad painted on. Only "statusline" is billable today
4231
+ * (spinner reach is un-billable and never writes a row). Recorded so the
4232
+ * publisher log can show *where* the ad showed. Older daemons omit it. */
4233
+ slot: external_exports.enum(["statusline", "spinner"]).default("statusline"),
4226
4234
  /** Server serve-proof echoed back on sync. Empty for standalone/unverified. */
4227
4235
  nonce: external_exports.string().default("")
4228
4236
  });
@@ -4818,6 +4826,7 @@ var Ledger = class {
4818
4826
  imp_fired INTEGER NOT NULL DEFAULT 0,
4819
4827
  clicked INTEGER NOT NULL DEFAULT 0,
4820
4828
  nonce TEXT NOT NULL DEFAULT '',
4829
+ slot TEXT NOT NULL DEFAULT 'statusline',
4821
4830
  synced INTEGER NOT NULL DEFAULT 0
4822
4831
  );
4823
4832
  CREATE INDEX IF NOT EXISTS idx_imp_unsynced ON impressions(synced);
@@ -4827,14 +4836,17 @@ var Ledger = class {
4827
4836
  if (!cols.some((c) => c.name === "nonce")) {
4828
4837
  this.db.exec(`ALTER TABLE impressions ADD COLUMN nonce TEXT NOT NULL DEFAULT ''`);
4829
4838
  }
4839
+ if (!cols.some((c) => c.name === "slot")) {
4840
+ this.db.exec(`ALTER TABLE impressions ADD COLUMN slot TEXT NOT NULL DEFAULT 'statusline'`);
4841
+ }
4830
4842
  }
4831
4843
  /** Record an impression starting (idempotent — ignore if id already present). */
4832
4844
  startImpression(row) {
4833
4845
  this.db.prepare(
4834
4846
  `INSERT OR IGNORE INTO impressions
4835
- (id, ad_id, campaign_id, session_id, source, started_at, nonce)
4836
- VALUES (@id, @adId, @campaignId, @sessionId, @source, @startedAt, @nonce)`
4837
- ).run({ ...row, nonce: row.nonce ?? "" });
4847
+ (id, ad_id, campaign_id, session_id, source, started_at, nonce, slot)
4848
+ VALUES (@id, @adId, @campaignId, @sessionId, @source, @startedAt, @nonce, @slot)`
4849
+ ).run({ ...row, nonce: row.nonce ?? "", slot: row.slot ?? "statusline" });
4838
4850
  }
4839
4851
  /**
4840
4852
  * Mark verified + fired. Persist-before-fire: call this, then fire impUrl.
@@ -4874,7 +4886,7 @@ var Ledger = class {
4874
4886
  const rows = this.db.prepare(
4875
4887
  `SELECT id, ad_id as adId, campaign_id as campaignId, session_id as sessionId,
4876
4888
  source, started_at as startedAt, verified_at as verifiedAt,
4877
- imp_fired as impFired, clicked, nonce
4889
+ imp_fired as impFired, clicked, nonce, slot
4878
4890
  FROM impressions WHERE synced = 0 ORDER BY started_at LIMIT @limit`
4879
4891
  ).all({ limit });
4880
4892
  return rows.map((r) => ({
@@ -4887,6 +4899,7 @@ var Ledger = class {
4887
4899
  verifiedAt: r.verifiedAt ?? null,
4888
4900
  impFired: !!r.impFired,
4889
4901
  clicked: !!r.clicked,
4902
+ slot: r.slot ?? "statusline",
4890
4903
  nonce: r.nonce ?? ""
4891
4904
  }));
4892
4905
  }
@@ -5027,7 +5040,7 @@ function newImpId(nowMs) {
5027
5040
  }
5028
5041
  var BUILTIN_TEST_ADS = [
5029
5042
  {
5030
- campaignId: "gravity",
5043
+ campaignId: GRAVITY_CAMPAIGN_ID,
5031
5044
  text: "Ship faster \u2014 catch errors before users do",
5032
5045
  brandName: "Sentry",
5033
5046
  url: "https://sentry.io",
@@ -5036,7 +5049,7 @@ var BUILTIN_TEST_ADS = [
5036
5049
  source: "gravity"
5037
5050
  },
5038
5051
  {
5039
- campaignId: "gravity",
5052
+ campaignId: GRAVITY_CAMPAIGN_ID,
5040
5053
  text: "Postgres without the ops \u2014 serverless branches",
5041
5054
  brandName: "Neon",
5042
5055
  url: "https://neon.tech",
@@ -5045,7 +5058,7 @@ var BUILTIN_TEST_ADS = [
5045
5058
  source: "gravity"
5046
5059
  },
5047
5060
  {
5048
- campaignId: "gravity",
5061
+ campaignId: GRAVITY_CAMPAIGN_ID,
5049
5062
  text: "Deploy in seconds, scale to zero",
5050
5063
  brandName: "Vercel",
5051
5064
  url: "https://vercel.com",
@@ -5133,7 +5146,7 @@ function startServer(deps) {
5133
5146
  const ad = readCurrentAd();
5134
5147
  deps.ledger.markClicked(impId);
5135
5148
  if (ad && ad.id === impId && ad.clickUrl) deps.firePixel(ad.clickUrl);
5136
- const dest = ad?.url || "https://trygravity.ai";
5149
+ const dest = ad?.url || FALLBACK_AD_URL;
5137
5150
  res.writeHead(302, { location: dest });
5138
5151
  res.end();
5139
5152
  return;
@@ -5172,12 +5185,22 @@ function startServer(deps) {
5172
5185
  res.end("error");
5173
5186
  }
5174
5187
  });
5175
- return new Promise((resolve) => {
5176
- server.listen(0, "127.0.0.1", () => {
5188
+ return new Promise((resolve, reject) => {
5189
+ const onListening = () => {
5177
5190
  const addr = server.address();
5178
5191
  const port = typeof addr === "object" && addr ? addr.port : 0;
5179
5192
  resolve({ server, port });
5180
- });
5193
+ };
5194
+ const onError = (err) => {
5195
+ if (err.code === "EADDRINUSE") {
5196
+ server.once("error", reject);
5197
+ server.listen(0, "127.0.0.1", onListening);
5198
+ return;
5199
+ }
5200
+ reject(err);
5201
+ };
5202
+ server.once("error", onError);
5203
+ server.listen(HOOK_PORT, "127.0.0.1", onListening);
5181
5204
  });
5182
5205
  }
5183
5206
 
@@ -5361,7 +5384,10 @@ async function main() {
5361
5384
  sessionId: sid,
5362
5385
  source: ad.source,
5363
5386
  startedAt: nowMs,
5364
- nonce: ad.nonce
5387
+ nonce: ad.nonce,
5388
+ // Only the status line writes a billable impression — spinner reach
5389
+ // is un-billable and never reaches this path. Recorded for the log.
5390
+ slot: "statusline"
5365
5391
  });
5366
5392
  }
5367
5393
  } catch (e) {
package/native/build.sh CHANGED
@@ -7,6 +7,13 @@ set -euo pipefail
7
7
  HERE="$(cd "$(dirname "$0")" && pwd)"
8
8
  OUT="${1:-$HERE/build}"
9
9
 
10
+ # macOS-only: these helpers import AppKit. On any non-Darwin host (Linux CI),
11
+ # skip cleanly — the binary is compiled on the user's Mac at runtime, never in CI.
12
+ if [ "$(uname -s)" != "Darwin" ]; then
13
+ echo "native: skipping Swift build on non-macOS ($(uname -s))" >&2
14
+ exit 0
15
+ fi
16
+
10
17
  if ! xcrun --find swiftc >/dev/null 2>&1 && ! command -v swiftc >/dev/null 2>&1; then
11
18
  echo "swiftc not found (install Xcode Command Line Tools: xcode-select --install)" >&2
12
19
  exit 3
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adsinagents",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Get paid while you build. AdsInAgents is the terminal-native ad layer for AI coding agents. Verified impressions pay you.",
5
5
  "homepage": "https://adsinagents.com",
6
6
  "license": "UNLICENSED",
@@ -4082,6 +4082,7 @@ var CATEGORY_KEYS = Object.keys(CATEGORIES);
4082
4082
  var CategorySchema = external_exports.enum(CATEGORY_KEYS);
4083
4083
 
4084
4084
  // ../../shared/dist/schemas.js
4085
+ var AdSourceSchema = external_exports.enum(["gravity", "direct"]);
4085
4086
  var AdSchema = external_exports.object({
4086
4087
  /** Stable impression id for this rotation; idempotency key for firing. */
4087
4088
  id: external_exports.string().min(1),
@@ -4098,7 +4099,7 @@ var AdSchema = external_exports.object({
4098
4099
  /** Gravity click pixel (GET). Empty for direct campaigns. */
4099
4100
  clickUrl: external_exports.string().default(""),
4100
4101
  /** Source of demand. */
4101
- source: external_exports.enum(["gravity", "direct"]),
4102
+ source: AdSourceSchema,
4102
4103
  /** Unix ms when this ad was fetched into cache. */
4103
4104
  fetchedAt: external_exports.number().int(),
4104
4105
  /**
@@ -4201,7 +4202,11 @@ var ImpressionSchema = external_exports.object({
4201
4202
  verifiedAt: external_exports.number().int().nullable(),
4202
4203
  impFired: external_exports.boolean(),
4203
4204
  clicked: external_exports.boolean(),
4204
- source: external_exports.enum(["gravity", "direct"]),
4205
+ source: AdSourceSchema,
4206
+ /** Render surface the ad painted on. Only "statusline" is billable today
4207
+ * (spinner reach is un-billable and never writes a row). Recorded so the
4208
+ * publisher log can show *where* the ad showed. Older daemons omit it. */
4209
+ slot: external_exports.enum(["statusline", "spinner"]).default("statusline"),
4205
4210
  /** Server serve-proof echoed back on sync. Empty for standalone/unverified. */
4206
4211
  nonce: external_exports.string().default("")
4207
4212
  });