@topolo/cli 0.6.5 → 0.6.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/dist/index.js CHANGED
@@ -98,13 +98,13 @@ var TopoloHttpError = class extends TopoloSdkError {
98
98
  path;
99
99
  requestId;
100
100
  retryAfter;
101
- constructor(service, path8, status, body, message, options = {}) {
102
- super(extractHttpErrorCode(body), message ?? `HTTP ${status} from ${service}${path8}`);
101
+ constructor(service, path9, status, body, message, options = {}) {
102
+ super(extractHttpErrorCode(body), message ?? `HTTP ${status} from ${service}${path9}`);
103
103
  this.name = "TopoloHttpError";
104
104
  this.status = status;
105
105
  this.body = body;
106
106
  this.service = service;
107
- this.path = path8;
107
+ this.path = path9;
108
108
  this.requestId = options.requestId;
109
109
  this.retryAfter = options.retryAfter;
110
110
  }
@@ -113,6 +113,7 @@ var APP_API_URLS = {
113
113
  agent: "https://agent.topolo.app",
114
114
  auth: "https://auth.topolo.app",
115
115
  backup: "https://backup.topolo.app",
116
+ blog: "https://blog.topolo.app",
116
117
  books: "https://books.topolo.app",
117
118
  brand: "https://brand.topolo.app",
118
119
  bugfix: "https://bugfix.topolo.app",
@@ -125,6 +126,7 @@ var APP_API_URLS = {
125
126
  compose: "https://compose.topolo.app",
126
127
  consent: "https://consent.topolo.app",
127
128
  crm: "https://crm.topolo.app",
129
+ design: "https://design.topolo.app",
128
130
  developers: "https://developers.topolo.app",
129
131
  director: "https://director.topolo.app",
130
132
  feed: "https://feed.topolo.app",
@@ -208,7 +210,9 @@ var APPLICATIONS = {
208
210
  "domains": [
209
211
  "agent.topolo.app"
210
212
  ],
211
- "routes": [],
213
+ "routes": [
214
+ "agent.topolo.app"
215
+ ],
212
216
  "appId": "agent"
213
217
  },
214
218
  {
@@ -269,6 +273,38 @@ var APPLICATIONS = {
269
273
  }
270
274
  ]
271
275
  },
276
+ "blog": {
277
+ "id": "blog",
278
+ "appDir": "TopoloBlog",
279
+ "name": "topolo-blog",
280
+ "packageName": "topolo-blog",
281
+ "productionUrl": "https://blog.topolo.app",
282
+ "services": [
283
+ "blog"
284
+ ],
285
+ "deployTargets": [
286
+ {
287
+ "name": "topolo-blog",
288
+ "kind": "worker",
289
+ "apiUrl": "https://blog.topolo.app",
290
+ "domains": [
291
+ "blog.topolo.app"
292
+ ],
293
+ "routes": [
294
+ "blog.topolo.app"
295
+ ],
296
+ "appId": "blog"
297
+ },
298
+ {
299
+ "name": "topolo-blog-api",
300
+ "kind": "worker",
301
+ "apiUrl": null,
302
+ "domains": [],
303
+ "routes": [],
304
+ "appId": null
305
+ }
306
+ ]
307
+ },
272
308
  "books": {
273
309
  "id": "books",
274
310
  "appDir": "TopoloBooks",
@@ -286,7 +322,9 @@ var APPLICATIONS = {
286
322
  "domains": [
287
323
  "books.topolo.app"
288
324
  ],
289
- "routes": [],
325
+ "routes": [
326
+ "books.topolo.app"
327
+ ],
290
328
  "appId": "books"
291
329
  },
292
330
  {
@@ -436,7 +474,9 @@ var APPLICATIONS = {
436
474
  "domains": [
437
475
  "campaigns.topolo.app"
438
476
  ],
439
- "routes": [],
477
+ "routes": [
478
+ "campaigns.topolo.app"
479
+ ],
440
480
  "appId": "campaigns"
441
481
  },
442
482
  {
@@ -578,7 +618,9 @@ var APPLICATIONS = {
578
618
  "domains": [
579
619
  "compose.topolo.app"
580
620
  ],
581
- "routes": [],
621
+ "routes": [
622
+ "compose.topolo.app"
623
+ ],
582
624
  "appId": "compose"
583
625
  },
584
626
  {
@@ -608,7 +650,9 @@ var APPLICATIONS = {
608
650
  "domains": [
609
651
  "consent.topolo.app"
610
652
  ],
611
- "routes": [],
653
+ "routes": [
654
+ "consent.topolo.app"
655
+ ],
612
656
  "appId": "consent"
613
657
  },
614
658
  {
@@ -646,11 +690,45 @@ var APPLICATIONS = {
646
690
  "domains": [
647
691
  "crm.topolo.app"
648
692
  ],
649
- "routes": [],
693
+ "routes": [
694
+ "crm.topolo.app"
695
+ ],
650
696
  "appId": "crm"
651
697
  }
652
698
  ]
653
699
  },
700
+ "design": {
701
+ "id": "design",
702
+ "appDir": "TopoloDesign",
703
+ "name": "topolo-design",
704
+ "packageName": "@topolo-io/design",
705
+ "productionUrl": "https://design.topolo.app",
706
+ "services": [
707
+ "design"
708
+ ],
709
+ "deployTargets": [
710
+ {
711
+ "name": "topolo-design",
712
+ "kind": "worker",
713
+ "apiUrl": "https://design.topolo.app",
714
+ "domains": [
715
+ "design.topolo.app"
716
+ ],
717
+ "routes": [
718
+ "design.topolo.app"
719
+ ],
720
+ "appId": "design"
721
+ },
722
+ {
723
+ "name": "topolo-design-api",
724
+ "kind": "worker",
725
+ "apiUrl": null,
726
+ "domains": [],
727
+ "routes": [],
728
+ "appId": null
729
+ }
730
+ ]
731
+ },
654
732
  "developers": {
655
733
  "id": "developers",
656
734
  "appDir": "TopoloDevelopers",
@@ -706,7 +784,9 @@ var APPLICATIONS = {
706
784
  "domains": [
707
785
  "director.topolo.app"
708
786
  ],
709
- "routes": [],
787
+ "routes": [
788
+ "director.topolo.app"
789
+ ],
710
790
  "appId": "director"
711
791
  },
712
792
  {
@@ -814,7 +894,9 @@ var APPLICATIONS = {
814
894
  "domains": [
815
895
  "flow.topolo.app"
816
896
  ],
817
- "routes": [],
897
+ "routes": [
898
+ "flow.topolo.app"
899
+ ],
818
900
  "appId": "flow"
819
901
  },
820
902
  {
@@ -844,7 +926,9 @@ var APPLICATIONS = {
844
926
  "domains": [
845
927
  "forecast.topolo.app"
846
928
  ],
847
- "routes": [],
929
+ "routes": [
930
+ "forecast.topolo.app"
931
+ ],
848
932
  "appId": "forecast"
849
933
  },
850
934
  {
@@ -938,7 +1022,9 @@ var APPLICATIONS = {
938
1022
  "domains": [
939
1023
  "insights.topolo.app"
940
1024
  ],
941
- "routes": [],
1025
+ "routes": [
1026
+ "insights.topolo.app"
1027
+ ],
942
1028
  "appId": "insights"
943
1029
  },
944
1030
  {
@@ -968,7 +1054,9 @@ var APPLICATIONS = {
968
1054
  "domains": [
969
1055
  "inventory.topolo.app"
970
1056
  ],
971
- "routes": [],
1057
+ "routes": [
1058
+ "inventory.topolo.app"
1059
+ ],
972
1060
  "appId": "inventory"
973
1061
  },
974
1062
  {
@@ -1322,7 +1410,9 @@ var APPLICATIONS = {
1322
1410
  "domains": [
1323
1411
  "pay.topolo.app"
1324
1412
  ],
1325
- "routes": [],
1413
+ "routes": [
1414
+ "pay.topolo.app"
1415
+ ],
1326
1416
  "appId": "pay"
1327
1417
  },
1328
1418
  {
@@ -2277,17 +2367,17 @@ function validateTopoloActionInput(schema, input3) {
2277
2367
  validateNode(schema, input3, "$", schema, errors, 0);
2278
2368
  return { valid: errors.length === 0, errors };
2279
2369
  }
2280
- function inspectSchema(schema, path8, root, depth) {
2281
- if (depth > 128) return { path: path8, code: "schema_depth", message: "Schema recursion exceeded 128 levels." };
2370
+ function inspectSchema(schema, path9, root, depth) {
2371
+ if (depth > 128) return { path: path9, code: "schema_depth", message: "Schema recursion exceeded 128 levels." };
2282
2372
  const unsupportedKeyword = Object.keys(schema).find((keyword) => !SUPPORTED_SCHEMA_KEYWORDS.has(keyword));
2283
2373
  if (unsupportedKeyword) {
2284
- return { path: path8, code: "unsupported_schema_keyword", message: `Action schema uses unsupported keyword ${unsupportedKeyword}.` };
2374
+ return { path: path9, code: "unsupported_schema_keyword", message: `Action schema uses unsupported keyword ${unsupportedKeyword}.` };
2285
2375
  }
2286
2376
  if (typeof schema.format === "string" && !["uri", "email", "date-time"].includes(schema.format)) {
2287
- return { path: path8, code: "unsupported_schema_format", message: `Action schema uses unsupported format ${schema.format}.` };
2377
+ return { path: path9, code: "unsupported_schema_format", message: `Action schema uses unsupported format ${schema.format}.` };
2288
2378
  }
2289
2379
  if (typeof schema.$ref === "string" && !resolveLocalReference(root, schema.$ref)) {
2290
- return { path: path8, code: "unsupported_schema_ref", message: `Cannot resolve schema reference ${schema.$ref}.` };
2380
+ return { path: path9, code: "unsupported_schema_ref", message: `Cannot resolve schema reference ${schema.$ref}.` };
2291
2381
  }
2292
2382
  const children = [];
2293
2383
  if (isRecord(schema.properties)) children.push(...Object.entries(schema.properties));
@@ -2303,7 +2393,7 @@ function inspectSchema(schema, path8, root, depth) {
2303
2393
  );
2304
2394
  for (const [key, child] of children) {
2305
2395
  if (!isRecord(child)) continue;
2306
- const issue = inspectSchema(child, `${path8}.${key}`, root, depth + 1);
2396
+ const issue = inspectSchema(child, `${path9}.${key}`, root, depth + 1);
2307
2397
  if (issue) return issue;
2308
2398
  }
2309
2399
  return null;
@@ -2311,129 +2401,129 @@ function inspectSchema(schema, path8, root, depth) {
2311
2401
  function arraySchemaEntries(keyword, value) {
2312
2402
  return Array.isArray(value) ? value.map((candidate, index) => [`${keyword}[${index}]`, candidate]) : [];
2313
2403
  }
2314
- function validateNode(schema, value, path8, root, errors, depth) {
2404
+ function validateNode(schema, value, path9, root, errors, depth) {
2315
2405
  if (depth > 128) {
2316
- errors.push({ path: path8, code: "schema_depth", message: "Schema recursion exceeded 128 levels." });
2406
+ errors.push({ path: path9, code: "schema_depth", message: "Schema recursion exceeded 128 levels." });
2317
2407
  return;
2318
2408
  }
2319
2409
  if (typeof schema.$ref === "string") {
2320
2410
  const resolved = resolveLocalReference(root, schema.$ref);
2321
2411
  if (!resolved) {
2322
- errors.push({ path: path8, code: "unsupported_schema_ref", message: `Cannot resolve schema reference ${schema.$ref}.` });
2412
+ errors.push({ path: path9, code: "unsupported_schema_ref", message: `Cannot resolve schema reference ${schema.$ref}.` });
2323
2413
  return;
2324
2414
  }
2325
- validateNode(resolved, value, path8, root, errors, depth + 1);
2415
+ validateNode(resolved, value, path9, root, errors, depth + 1);
2326
2416
  }
2327
2417
  if (Array.isArray(schema.allOf)) {
2328
2418
  for (const candidate of schema.allOf) {
2329
- if (isRecord(candidate)) validateNode(candidate, value, path8, root, errors, depth + 1);
2419
+ if (isRecord(candidate)) validateNode(candidate, value, path9, root, errors, depth + 1);
2330
2420
  }
2331
2421
  }
2332
2422
  if (Array.isArray(schema.anyOf) && !schema.anyOf.some((candidate) => candidateMatches(candidate, value, root, depth))) {
2333
- errors.push({ path: path8, code: "any_of", message: "Value does not match any allowed schema." });
2423
+ errors.push({ path: path9, code: "any_of", message: "Value does not match any allowed schema." });
2334
2424
  return;
2335
2425
  }
2336
2426
  if (Array.isArray(schema.oneOf)) {
2337
2427
  const matches = schema.oneOf.filter((candidate) => candidateMatches(candidate, value, root, depth)).length;
2338
2428
  if (matches !== 1) {
2339
- errors.push({ path: path8, code: "one_of", message: "Value must match exactly one allowed schema." });
2429
+ errors.push({ path: path9, code: "one_of", message: "Value must match exactly one allowed schema." });
2340
2430
  return;
2341
2431
  }
2342
2432
  }
2343
2433
  if (value === null && schema.nullable === true) return;
2344
2434
  if (Object.prototype.hasOwnProperty.call(schema, "const") && !sameJsonValue(value, schema.const)) {
2345
- errors.push({ path: path8, code: "const", message: `Value must equal ${JSON.stringify(schema.const)}.` });
2435
+ errors.push({ path: path9, code: "const", message: `Value must equal ${JSON.stringify(schema.const)}.` });
2346
2436
  return;
2347
2437
  }
2348
2438
  if (Array.isArray(schema.enum) && !schema.enum.some((candidate) => sameJsonValue(value, candidate))) {
2349
- errors.push({ path: path8, code: "enum", message: `Value must be one of ${schema.enum.map((item) => JSON.stringify(item)).join(", ")}.` });
2439
+ errors.push({ path: path9, code: "enum", message: `Value must be one of ${schema.enum.map((item) => JSON.stringify(item)).join(", ")}.` });
2350
2440
  return;
2351
2441
  }
2352
2442
  if (!matchesType(schema.type, value)) {
2353
- errors.push({ path: path8, code: "type", message: `Expected ${String(schema.type)}.` });
2443
+ errors.push({ path: path9, code: "type", message: `Expected ${String(schema.type)}.` });
2354
2444
  return;
2355
2445
  }
2356
- if (typeof value === "string") validateString(schema, value, path8, errors);
2357
- if (typeof value === "number") validateNumber(schema, value, path8, errors);
2358
- if (Array.isArray(value)) validateArray(schema, value, path8, root, errors, depth);
2359
- if (isRecord(value)) validateObject(schema, value, path8, root, errors, depth);
2446
+ if (typeof value === "string") validateString(schema, value, path9, errors);
2447
+ if (typeof value === "number") validateNumber(schema, value, path9, errors);
2448
+ if (Array.isArray(value)) validateArray(schema, value, path9, root, errors, depth);
2449
+ if (isRecord(value)) validateObject(schema, value, path9, root, errors, depth);
2360
2450
  }
2361
- function validateObject(schema, value, path8, root, errors, depth) {
2451
+ function validateObject(schema, value, path9, root, errors, depth) {
2362
2452
  if (typeof schema.minProperties === "number" && Object.keys(value).length < schema.minProperties) {
2363
- errors.push({ path: path8, code: "min_properties", message: `Expected at least ${schema.minProperties} properties.` });
2453
+ errors.push({ path: path9, code: "min_properties", message: `Expected at least ${schema.minProperties} properties.` });
2364
2454
  }
2365
2455
  if (typeof schema.maxProperties === "number" && Object.keys(value).length > schema.maxProperties) {
2366
- errors.push({ path: path8, code: "max_properties", message: `Expected at most ${schema.maxProperties} properties.` });
2456
+ errors.push({ path: path9, code: "max_properties", message: `Expected at most ${schema.maxProperties} properties.` });
2367
2457
  }
2368
2458
  const properties = isRecord(schema.properties) ? schema.properties : {};
2369
2459
  const required = Array.isArray(schema.required) ? schema.required.map(String) : [];
2370
2460
  for (const key of required) {
2371
2461
  if (!Object.prototype.hasOwnProperty.call(value, key)) {
2372
- errors.push({ path: `${path8}.${key}`, code: "required", message: "Required property is missing." });
2462
+ errors.push({ path: `${path9}.${key}`, code: "required", message: "Required property is missing." });
2373
2463
  }
2374
2464
  }
2375
2465
  if (isRecord(schema.propertyNames)) {
2376
2466
  for (const key of Object.keys(value)) {
2377
- validateNode(schema.propertyNames, key, `${path8}.${key}`, root, errors, depth + 1);
2467
+ validateNode(schema.propertyNames, key, `${path9}.${key}`, root, errors, depth + 1);
2378
2468
  }
2379
2469
  }
2380
2470
  for (const [key, child] of Object.entries(value)) {
2381
2471
  const childSchema = properties[key];
2382
2472
  if (isRecord(childSchema)) {
2383
- validateNode(childSchema, child, `${path8}.${key}`, root, errors, depth + 1);
2473
+ validateNode(childSchema, child, `${path9}.${key}`, root, errors, depth + 1);
2384
2474
  } else if (schema.additionalProperties === false) {
2385
- errors.push({ path: `${path8}.${key}`, code: "additional_property", message: "Property is not declared by the action schema." });
2475
+ errors.push({ path: `${path9}.${key}`, code: "additional_property", message: "Property is not declared by the action schema." });
2386
2476
  } else if (isRecord(schema.additionalProperties)) {
2387
- validateNode(schema.additionalProperties, child, `${path8}.${key}`, root, errors, depth + 1);
2477
+ validateNode(schema.additionalProperties, child, `${path9}.${key}`, root, errors, depth + 1);
2388
2478
  }
2389
2479
  }
2390
2480
  }
2391
- function validateArray(schema, value, path8, root, errors, depth) {
2481
+ function validateArray(schema, value, path9, root, errors, depth) {
2392
2482
  if (typeof schema.minItems === "number" && value.length < schema.minItems) {
2393
- errors.push({ path: path8, code: "min_items", message: `Expected at least ${schema.minItems} items.` });
2483
+ errors.push({ path: path9, code: "min_items", message: `Expected at least ${schema.minItems} items.` });
2394
2484
  }
2395
2485
  if (typeof schema.maxItems === "number" && value.length > schema.maxItems) {
2396
- errors.push({ path: path8, code: "max_items", message: `Expected at most ${schema.maxItems} items.` });
2486
+ errors.push({ path: path9, code: "max_items", message: `Expected at most ${schema.maxItems} items.` });
2397
2487
  }
2398
2488
  if (schema.uniqueItems === true) {
2399
2489
  const unique4 = new Set(value.map((item) => JSON.stringify(item)));
2400
- if (unique4.size !== value.length) errors.push({ path: path8, code: "unique_items", message: "Expected every item to be unique." });
2490
+ if (unique4.size !== value.length) errors.push({ path: path9, code: "unique_items", message: "Expected every item to be unique." });
2401
2491
  }
2402
2492
  if (isRecord(schema.items)) {
2403
- value.forEach((item, index) => validateNode(schema.items, item, `${path8}[${index}]`, root, errors, depth + 1));
2493
+ value.forEach((item, index) => validateNode(schema.items, item, `${path9}[${index}]`, root, errors, depth + 1));
2404
2494
  }
2405
2495
  }
2406
- function validateString(schema, value, path8, errors) {
2496
+ function validateString(schema, value, path9, errors) {
2407
2497
  if (typeof schema.minLength === "number" && value.length < schema.minLength) {
2408
- errors.push({ path: path8, code: "min_length", message: `Expected at least ${schema.minLength} characters.` });
2498
+ errors.push({ path: path9, code: "min_length", message: `Expected at least ${schema.minLength} characters.` });
2409
2499
  }
2410
2500
  if (typeof schema.maxLength === "number" && value.length > schema.maxLength) {
2411
- errors.push({ path: path8, code: "max_length", message: `Expected at most ${schema.maxLength} characters.` });
2501
+ errors.push({ path: path9, code: "max_length", message: `Expected at most ${schema.maxLength} characters.` });
2412
2502
  }
2413
2503
  if (typeof schema.pattern === "string") {
2414
2504
  try {
2415
- if (!new RegExp(schema.pattern).test(value)) errors.push({ path: path8, code: "pattern", message: "Value does not match the required pattern." });
2505
+ if (!new RegExp(schema.pattern).test(value)) errors.push({ path: path9, code: "pattern", message: "Value does not match the required pattern." });
2416
2506
  } catch {
2417
- errors.push({ path: path8, code: "invalid_schema_pattern", message: "Action schema contains an invalid pattern." });
2507
+ errors.push({ path: path9, code: "invalid_schema_pattern", message: "Action schema contains an invalid pattern." });
2418
2508
  }
2419
2509
  }
2420
- if (schema.format === "uri" && !isUrl(value)) errors.push({ path: path8, code: "format_uri", message: "Expected an absolute URL." });
2421
- if (schema.format === "email" && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(value)) errors.push({ path: path8, code: "format_email", message: "Expected an email address." });
2422
- if (schema.format === "date-time" && !isDateTime(value)) errors.push({ path: path8, code: "format_date_time", message: "Expected an ISO-8601 date-time." });
2510
+ if (schema.format === "uri" && !isUrl(value)) errors.push({ path: path9, code: "format_uri", message: "Expected an absolute URL." });
2511
+ if (schema.format === "email" && !/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(value)) errors.push({ path: path9, code: "format_email", message: "Expected an email address." });
2512
+ if (schema.format === "date-time" && !isDateTime(value)) errors.push({ path: path9, code: "format_date_time", message: "Expected an ISO-8601 date-time." });
2423
2513
  }
2424
- function validateNumber(schema, value, path8, errors) {
2425
- if (typeof schema.minimum === "number" && value < schema.minimum) errors.push({ path: path8, code: "minimum", message: `Expected a value of at least ${schema.minimum}.` });
2426
- if (typeof schema.maximum === "number" && value > schema.maximum) errors.push({ path: path8, code: "maximum", message: `Expected a value of at most ${schema.maximum}.` });
2514
+ function validateNumber(schema, value, path9, errors) {
2515
+ if (typeof schema.minimum === "number" && value < schema.minimum) errors.push({ path: path9, code: "minimum", message: `Expected a value of at least ${schema.minimum}.` });
2516
+ if (typeof schema.maximum === "number" && value > schema.maximum) errors.push({ path: path9, code: "maximum", message: `Expected a value of at most ${schema.maximum}.` });
2427
2517
  const exclusiveMinimum = typeof schema.exclusiveMinimum === "number" ? schema.exclusiveMinimum : schema.exclusiveMinimum === true && typeof schema.minimum === "number" ? schema.minimum : null;
2428
2518
  const exclusiveMaximum = typeof schema.exclusiveMaximum === "number" ? schema.exclusiveMaximum : schema.exclusiveMaximum === true && typeof schema.maximum === "number" ? schema.maximum : null;
2429
2519
  if (exclusiveMinimum !== null && value <= exclusiveMinimum) {
2430
- errors.push({ path: path8, code: "exclusive_minimum", message: `Expected a value greater than ${exclusiveMinimum}.` });
2520
+ errors.push({ path: path9, code: "exclusive_minimum", message: `Expected a value greater than ${exclusiveMinimum}.` });
2431
2521
  }
2432
2522
  if (exclusiveMaximum !== null && value >= exclusiveMaximum) {
2433
- errors.push({ path: path8, code: "exclusive_maximum", message: `Expected a value less than ${exclusiveMaximum}.` });
2523
+ errors.push({ path: path9, code: "exclusive_maximum", message: `Expected a value less than ${exclusiveMaximum}.` });
2434
2524
  }
2435
2525
  if (typeof schema.multipleOf === "number" && !isMultipleOf(value, schema.multipleOf)) {
2436
- errors.push({ path: path8, code: "multiple_of", message: `Expected a multiple of ${schema.multipleOf}.` });
2526
+ errors.push({ path: path9, code: "multiple_of", message: `Expected a multiple of ${schema.multipleOf}.` });
2437
2527
  }
2438
2528
  }
2439
2529
  function candidateMatches(candidate, value, root, depth) {
@@ -2565,8 +2655,8 @@ function prepareTopoloUrlSessionUploadInput(contractValue, byteLength, input3, o
2565
2655
  }
2566
2656
  };
2567
2657
  }
2568
- function topoloUploadResponseValue(response, path8) {
2569
- return path8.split(".").reduce((value, segment) => isRecord2(value) ? value[segment] : void 0, response);
2658
+ function topoloUploadResponseValue(response, path9) {
2659
+ return path9.split(".").reduce((value, segment) => isRecord2(value) ? value[segment] : void 0, response);
2570
2660
  }
2571
2661
  function decodeTopoloActionBase64(contentBase64) {
2572
2662
  if (!isCanonicalBase64(contentBase64)) {
@@ -2613,11 +2703,11 @@ function parseCompleteContract(value) {
2613
2703
  };
2614
2704
  }
2615
2705
  function requiredPath(value, name) {
2616
- const path8 = typeof value === "string" ? value.trim() : "";
2617
- if (!/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(path8)) {
2706
+ const path9 = typeof value === "string" ? value.trim() : "";
2707
+ if (!/^[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*$/.test(path9)) {
2618
2708
  throw new TopoloSdkError("invalid_upload_contract", `The action upload contract has an invalid ${name}.`);
2619
2709
  }
2620
- return path8;
2710
+ return path9;
2621
2711
  }
2622
2712
  function unsupportedInlineProfile() {
2623
2713
  return new TopoloSdkError("invalid_upload_contract", "This action does not publish an inline-base64 upload contract.");
@@ -3572,8 +3662,8 @@ function normalizeActionCatalogEntry(item) {
3572
3662
  const name = pickActionString(a.name);
3573
3663
  const appId = pickActionString(a.app_id) ?? pickActionString(a.appId);
3574
3664
  const method = pickActionString(a.method)?.toUpperCase();
3575
- const path8 = pickActionString(a.path);
3576
- if (!actionId || !name || !appId || !method || !path8 || !isHttpMethod(method)) {
3665
+ const path9 = pickActionString(a.path);
3666
+ if (!actionId || !name || !appId || !method || !path9 || !isHttpMethod(method)) {
3577
3667
  return null;
3578
3668
  }
3579
3669
  return {
@@ -3588,7 +3678,7 @@ function normalizeActionCatalogEntry(item) {
3588
3678
  appSlug: pickActionString(a.app_slug) ?? pickActionString(a.appSlug) ?? null,
3589
3679
  appName: pickActionString(a.app_name) ?? pickActionString(a.appName) ?? null,
3590
3680
  method,
3591
- path: path8,
3681
+ path: path9,
3592
3682
  permissionName: pickActionString(a.permission_name) ?? pickActionString(a.permissionName) ?? "",
3593
3683
  requiredPermission: pickActionString(a.required_permission) ?? pickActionString(a.requiredPermission) ?? "",
3594
3684
  authorizationMode: pickAuthorizationMode(a.authorization_mode ?? a.authorizationMode),
@@ -3624,7 +3714,7 @@ function stringArray(value) {
3624
3714
  }
3625
3715
  function mapActionInput(action, input3) {
3626
3716
  const remaining = { ...input3 || {} };
3627
- const path8 = action.path.replace(/\{([a-zA-Z0-9_]+)\}/g, (_match, key) => {
3717
+ const path9 = action.path.replace(/\{([a-zA-Z0-9_]+)\}/g, (_match, key) => {
3628
3718
  const value = remaining[key];
3629
3719
  if (value === void 0 || value === null || value === "") {
3630
3720
  throw new TopoloSdkError(
@@ -3641,14 +3731,14 @@ function mapActionInput(action, input3) {
3641
3731
  delete remaining.body;
3642
3732
  if (action.method === "GET") {
3643
3733
  return {
3644
- path: path8,
3734
+ path: path9,
3645
3735
  query: objectToQuery({ ...remaining, ...explicitQuery })
3646
3736
  };
3647
3737
  }
3648
3738
  const query = objectToQuery(explicitQuery);
3649
3739
  const body = explicitBody !== void 0 ? explicitBody : remaining;
3650
3740
  return {
3651
- path: path8,
3741
+ path: path9,
3652
3742
  ...query ? { query } : {},
3653
3743
  body
3654
3744
  };
@@ -3818,8 +3908,8 @@ var TopoloOAuth = class {
3818
3908
  if (params.clientSecret) body.set("client_secret", params.clientSecret);
3819
3909
  return this.#postForm("/api/developer-oauth/token", body);
3820
3910
  }
3821
- async #postForm(path8, body) {
3822
- const url = new URL(path8, this.baseUrl.endsWith("/") ? this.baseUrl : `${this.baseUrl}/`);
3911
+ async #postForm(path9, body) {
3912
+ const url = new URL(path9, this.baseUrl.endsWith("/") ? this.baseUrl : `${this.baseUrl}/`);
3823
3913
  const res = await this.fetchImpl(url.toString(), {
3824
3914
  method: "POST",
3825
3915
  headers: {
@@ -3835,7 +3925,7 @@ var TopoloOAuth = class {
3835
3925
  const err = parsed;
3836
3926
  throw new TopoloAuthError(err.error_description || err.error, err.error);
3837
3927
  }
3838
- throw new TopoloHttpError("auth", path8, res.status, parsed);
3928
+ throw new TopoloHttpError("auth", path9, res.status, parsed);
3839
3929
  }
3840
3930
  return parsed;
3841
3931
  }
@@ -3898,13 +3988,13 @@ var TopoloHttpError2 = class extends TopoloSdkError2 {
3898
3988
  path;
3899
3989
  requestId;
3900
3990
  retryAfter;
3901
- constructor(service, path8, status, body, message, options = {}) {
3902
- super(extractHttpErrorCode2(body), message ?? `HTTP ${status} from ${service}${path8}`);
3991
+ constructor(service, path9, status, body, message, options = {}) {
3992
+ super(extractHttpErrorCode2(body), message ?? `HTTP ${status} from ${service}${path9}`);
3903
3993
  this.name = "TopoloHttpError";
3904
3994
  this.status = status;
3905
3995
  this.body = body;
3906
3996
  this.service = service;
3907
- this.path = path8;
3997
+ this.path = path9;
3908
3998
  this.requestId = options.requestId;
3909
3999
  this.retryAfter = options.retryAfter;
3910
4000
  }
@@ -3913,6 +4003,7 @@ var APP_API_URLS2 = {
3913
4003
  agent: "https://agent.topolo.app",
3914
4004
  auth: "https://auth.topolo.app",
3915
4005
  backup: "https://backup.topolo.app",
4006
+ blog: "https://blog.topolo.app",
3916
4007
  books: "https://books.topolo.app",
3917
4008
  brand: "https://brand.topolo.app",
3918
4009
  bugfix: "https://bugfix.topolo.app",
@@ -3925,6 +4016,7 @@ var APP_API_URLS2 = {
3925
4016
  compose: "https://compose.topolo.app",
3926
4017
  consent: "https://consent.topolo.app",
3927
4018
  crm: "https://crm.topolo.app",
4019
+ design: "https://design.topolo.app",
3928
4020
  developers: "https://developers.topolo.app",
3929
4021
  director: "https://director.topolo.app",
3930
4022
  feed: "https://feed.topolo.app",
@@ -4037,8 +4129,8 @@ var TopoloOAuth2 = class {
4037
4129
  if (params.clientSecret) body.set("client_secret", params.clientSecret);
4038
4130
  return this.#postForm("/api/developer-oauth/token", body);
4039
4131
  }
4040
- async #postForm(path8, body) {
4041
- const url = new URL(path8, this.baseUrl.endsWith("/") ? this.baseUrl : `${this.baseUrl}/`);
4132
+ async #postForm(path9, body) {
4133
+ const url = new URL(path9, this.baseUrl.endsWith("/") ? this.baseUrl : `${this.baseUrl}/`);
4042
4134
  const res = await this.fetchImpl(url.toString(), {
4043
4135
  method: "POST",
4044
4136
  headers: {
@@ -4054,7 +4146,7 @@ var TopoloOAuth2 = class {
4054
4146
  const err = parsed;
4055
4147
  throw new TopoloAuthError2(err.error_description || err.error, err.error);
4056
4148
  }
4057
- throw new TopoloHttpError2("auth", path8, res.status, parsed);
4149
+ throw new TopoloHttpError2("auth", path9, res.status, parsed);
4058
4150
  }
4059
4151
  return parsed;
4060
4152
  }
@@ -4084,22 +4176,22 @@ function configPath() {
4084
4176
  return join(base, "topolo", "config.json");
4085
4177
  }
4086
4178
  async function readConfig() {
4087
- const path8 = configPath();
4088
- if (!existsSync(path8)) return {};
4179
+ const path9 = configPath();
4180
+ if (!existsSync(path9)) return {};
4089
4181
  try {
4090
- const raw = await readFile(path8, "utf8");
4182
+ const raw = await readFile(path9, "utf8");
4091
4183
  return JSON.parse(raw);
4092
4184
  } catch {
4093
4185
  return {};
4094
4186
  }
4095
4187
  }
4096
4188
  async function writeConfig(config) {
4097
- const path8 = configPath();
4098
- await mkdir(dirname(path8), { recursive: true });
4099
- await writeFile(path8, JSON.stringify(config, null, 2) + "\n", "utf8");
4189
+ const path9 = configPath();
4190
+ await mkdir(dirname(path9), { recursive: true });
4191
+ await writeFile(path9, JSON.stringify(config, null, 2) + "\n", "utf8");
4100
4192
  if (platform() !== "win32") {
4101
4193
  try {
4102
- await chmod(path8, 384);
4194
+ await chmod(path9, 384);
4103
4195
  } catch {
4104
4196
  }
4105
4197
  }
@@ -4429,9 +4521,9 @@ function readCliVersion() {
4429
4521
  join2(here, "package.json"),
4430
4522
  join2(here, "..", "package.json")
4431
4523
  ];
4432
- for (const path8 of candidates) {
4524
+ for (const path9 of candidates) {
4433
4525
  try {
4434
- const pkg = JSON.parse(readFileSync(path8, "utf8"));
4526
+ const pkg = JSON.parse(readFileSync(path9, "utf8"));
4435
4527
  if (typeof pkg.version === "string" && pkg.version) return pkg.version;
4436
4528
  } catch {
4437
4529
  }
@@ -4791,7 +4883,7 @@ function registerApiCommand(program2) {
4791
4883
  "-q, --query <kv...>",
4792
4884
  "Query params as key=value (repeatable), e.g. --query source=cli page=2"
4793
4885
  ).option("--resource-type <type>", "Cataloged app-local workspace resource alias for resource-scoped API keys").option("--resource-id <id>", "Workspace resource id for resource-scoped API keys").option("--confirm", "Acknowledge a mutating request").option("--json", "Output JSON", true).option("--no-json", "Output human-readable text").action(
4794
- async (service, method, path8, opts) => {
4886
+ async (service, method, path9, opts) => {
4795
4887
  const mode = resolveOutputMode(opts.json);
4796
4888
  try {
4797
4889
  const upperMethod = method.toUpperCase();
@@ -4830,7 +4922,7 @@ function registerApiCommand(program2) {
4830
4922
  const result = await topolo.client.request({
4831
4923
  service,
4832
4924
  method: httpMethod,
4833
- path: path8,
4925
+ path: path9,
4834
4926
  body,
4835
4927
  ...query ? { query } : {},
4836
4928
  ...resource ? { resource } : {},
@@ -5018,13 +5110,13 @@ async function requiredClient() {
5018
5110
  function parseJsonObject(value) {
5019
5111
  let source = value;
5020
5112
  if (value.startsWith("@")) {
5021
- const path8 = value.slice(1);
5022
- if (!path8) throw new Error("--data @file path must not be empty");
5113
+ const path9 = value.slice(1);
5114
+ if (!path9) throw new Error("--data @file path must not be empty");
5023
5115
  try {
5024
- source = readFileSync2(path8, "utf8");
5116
+ source = readFileSync2(path9, "utf8");
5025
5117
  } catch (err) {
5026
5118
  const detail = err instanceof Error ? err.message : String(err);
5027
- throw new Error(`Could not read --data file ${path8}: ${detail}`);
5119
+ throw new Error(`Could not read --data file ${path9}: ${detail}`);
5028
5120
  }
5029
5121
  }
5030
5122
  let parsed;
@@ -5038,7 +5130,7 @@ function parseJsonObject(value) {
5038
5130
  }
5039
5131
  return parsed;
5040
5132
  }
5041
- function inferContentType(path8) {
5133
+ function inferContentType(path9) {
5042
5134
  return {
5043
5135
  ".avif": "image/avif",
5044
5136
  ".gif": "image/gif",
@@ -5051,7 +5143,7 @@ function inferContentType(path8) {
5051
5143
  ".png": "image/png",
5052
5144
  ".svg": "image/svg+xml",
5053
5145
  ".webp": "image/webp"
5054
- }[extname(path8).toLowerCase()] ?? null;
5146
+ }[extname(path9).toLowerCase()] ?? null;
5055
5147
  }
5056
5148
  function formatActionRows(rows, nextCursor = null) {
5057
5149
  if (rows.length === 0) return "No actions available for this credential.";
@@ -5113,8 +5205,8 @@ function formatActionPlan(plan) {
5113
5205
 
5114
5206
  // src/commands/apps.ts
5115
5207
  import { execSync } from "child_process";
5116
- import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
5117
- import path5 from "path";
5208
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync as writeFileSync2 } from "fs";
5209
+ import path6 from "path";
5118
5210
 
5119
5211
  // src/commands/app-audit-local.ts
5120
5212
  import {
@@ -6251,14 +6343,14 @@ import { constants } from "fs";
6251
6343
  import { access } from "fs/promises";
6252
6344
  import { relative, resolve } from "path";
6253
6345
  function normalizeHomePath(value) {
6254
- const path8 = String(value || "/dashboard").trim();
6255
- if (!path8.startsWith("/") || path8.startsWith("//") || /[?#]/.test(path8)) {
6346
+ const path9 = String(value || "/dashboard").trim();
6347
+ if (!path9.startsWith("/") || path9.startsWith("//") || /[?#]/.test(path9)) {
6256
6348
  throw new Error("Invalid home path. Use an absolute application path such as /dashboard.");
6257
6349
  }
6258
- if (["/", "/login", "/auth/callback", "/getting-started"].includes(path8)) {
6350
+ if (["/", "/login", "/auth/callback", "/getting-started"].includes(path9)) {
6259
6351
  throw new Error("Home path must be a protected product route, not a reserved entry route.");
6260
6352
  }
6261
- return path8.replace(/\/$/, "") || "/dashboard";
6353
+ return path9.replace(/\/$/, "") || "/dashboard";
6262
6354
  }
6263
6355
  function normalizeHomeLabel(value) {
6264
6356
  const label = String(value || "Dashboard").trim();
@@ -6389,9 +6481,9 @@ function toTitle(value) {
6389
6481
  function json(value) {
6390
6482
  return JSON.stringify(value, null, 2);
6391
6483
  }
6392
- async function pathExists(path8) {
6484
+ async function pathExists(path9) {
6393
6485
  try {
6394
- await access(path8, constants.F_OK);
6486
+ await access(path9, constants.F_OK);
6395
6487
  return true;
6396
6488
  } catch {
6397
6489
  return false;
@@ -6421,6 +6513,54 @@ function firstPartyAppPath(appDir, _audience) {
6421
6513
  return `apps/${appDir}`;
6422
6514
  }
6423
6515
 
6516
+ // src/commands/app-scaffold-platform-versions.ts
6517
+ import { readdirSync as readdirSync2, readFileSync as readFileSync4 } from "fs";
6518
+ import path2 from "path";
6519
+ var versionCache = /* @__PURE__ */ new Map();
6520
+ function platformPackagePin(packageName, options = {}) {
6521
+ const workspaceRoot = resolveTopoloRepoRoot(
6522
+ options.repoRoot ?? process.env.TOPOLO_WORKSPACE_ROOT ?? void 0,
6523
+ options.cwd ?? process.cwd()
6524
+ );
6525
+ if (!workspaceRoot) {
6526
+ throw new Error(
6527
+ `Cannot resolve a concrete version for ${packageName}: platform-target scaffolds must run inside the Topolo workspace checkout (a directory containing apps/ and system-apps/), or receive --repo-root. The fleet pinning policy requires exact ^<latest> pins, never "latest".`
6528
+ );
6529
+ }
6530
+ const version = platformPackageVersions(workspaceRoot).get(packageName);
6531
+ if (!version) {
6532
+ throw new Error(
6533
+ `Unknown Topolo platform package: ${packageName} \u2014 no published package with that name under ${path2.join(workspaceRoot, "topolo-platform", "packages")}.`
6534
+ );
6535
+ }
6536
+ return `^${version}`;
6537
+ }
6538
+ function platformPackageVersions(workspaceRoot) {
6539
+ const packagesRoot = path2.join(workspaceRoot, "topolo-platform", "packages");
6540
+ const cached = versionCache.get(packagesRoot);
6541
+ if (cached) return cached;
6542
+ const versions = /* @__PURE__ */ new Map();
6543
+ let entries = [];
6544
+ try {
6545
+ entries = readdirSync2(packagesRoot);
6546
+ } catch {
6547
+ }
6548
+ for (const entry of entries) {
6549
+ let packageJson2;
6550
+ try {
6551
+ packageJson2 = JSON.parse(readFileSync4(path2.join(packagesRoot, entry, "package.json"), "utf8"));
6552
+ } catch {
6553
+ continue;
6554
+ }
6555
+ const version = packageJson2.topoloPublishedVersion || packageJson2.version;
6556
+ if (packageJson2.name && /^@topolo(-io)?\//.test(packageJson2.name) && !packageJson2.private && version) {
6557
+ versions.set(packageJson2.name, version);
6558
+ }
6559
+ }
6560
+ versionCache.set(packagesRoot, versions);
6561
+ return versions;
6562
+ }
6563
+
6424
6564
  // src/commands/app-scaffold-cloudflare-constants.ts
6425
6565
  var CLOUDFLARE_ACCOUNT_ID = "49ef1ba682ad8cfd720c86699ae17521";
6426
6566
  var STAGING_CLOUDFLARE_ACCOUNT_ID = "4f4e1c69a3830946f9fea7b1eb7531ac";
@@ -6453,7 +6593,7 @@ function packageJson(application, target, options) {
6453
6593
  devDependencies.tailwindcss = "3.4.19";
6454
6594
  dependencies["react-router-dom"] = "^7.6.2";
6455
6595
  } else {
6456
- dependencies["@topolo/login"] = topoloPackageVersion("@topolo/login", target);
6596
+ dependencies["@topolo/login"] = topoloPackageVersion("@topolo/login", target, options.repoRoot);
6457
6597
  }
6458
6598
  }
6459
6599
  if (options.api) {
@@ -6465,13 +6605,13 @@ function packageJson(application, target, options) {
6465
6605
  scripts["deploy:staging"] = `DEPLOY_ENVIRONMENT=staging CLOUDFLARE_ACCOUNT_ID=${STAGING_CLOUDFLARE_ACCOUNT_ID} python3 .github/scripts/standard_deploy.py local-deploy`;
6466
6606
  scripts["deploy:production"] = `DEPLOY_ENVIRONMENT=production CLOUDFLARE_ACCOUNT_ID=${CLOUDFLARE_ACCOUNT_ID} python3 .github/scripts/standard_deploy.py local-deploy`;
6467
6607
  } else {
6468
- dependencies["@topolo/sdk"] = topoloPackageVersion("@topolo/sdk", target);
6608
+ dependencies["@topolo/sdk"] = topoloPackageVersion("@topolo/sdk", target, options.repoRoot);
6469
6609
  scripts.deploy = "npm run build && wrangler deploy";
6470
6610
  }
6471
6611
  devDependencies.wrangler = "^4.91.0";
6472
6612
  }
6473
6613
  for (const packageName of options.packages) {
6474
- dependencies[packageName] = topoloPackageVersion(packageName, target);
6614
+ dependencies[packageName] = topoloPackageVersion(packageName, target, options.repoRoot);
6475
6615
  }
6476
6616
  if (target === "platform") {
6477
6617
  const testDirs = [];
@@ -6513,14 +6653,16 @@ function packageJson(application, target, options) {
6513
6653
  })}
6514
6654
  `;
6515
6655
  }
6516
- function topoloPackageVersion(packageName, target) {
6656
+ function topoloPackageVersion(packageName, target, repoRoot) {
6517
6657
  if (target === "developer") {
6518
6658
  if (packageName === "@topolo/login") return "^0.1.0";
6519
6659
  if (packageName === "@topolo-io/auth-client") return "^1.0.0";
6520
6660
  if (packageName === "@topolo/sdk") return "^0.8.1";
6521
6661
  return "^0.1.0";
6522
6662
  }
6523
- if (packageName.startsWith("@topolo/") || packageName.startsWith("@topolo-io/")) return "latest";
6663
+ if (packageName.startsWith("@topolo/") || packageName.startsWith("@topolo-io/")) {
6664
+ return platformPackagePin(packageName, { repoRoot });
6665
+ }
6524
6666
  throw new Error(`Unknown Topolo platform package: ${packageName}`);
6525
6667
  }
6526
6668
  function hasScaffoldResources(resources) {
@@ -7159,6 +7301,10 @@ function envDts(api) {
7159
7301
  "interface ImportMetaEnv {",
7160
7302
  " readonly VITE_TOPOLO_AUTH_URL?: string;",
7161
7303
  " readonly VITE_TOPOLO_APP_ID?: string;",
7304
+ " readonly VITE_TOPOLO_INSIGHTS_SITE_KEY?: string;",
7305
+ " readonly VITE_TOPOLO_INSIGHTS_ENDPOINT?: string;",
7306
+ " readonly VITE_TOPOLO_CONSENT_BASE_URL?: string;",
7307
+ " readonly VITE_TOPOLO_CONSENT_SDK_KEY?: string;",
7162
7308
  " readonly VITE_TOPOLO_CLIENT_ID?: string;",
7163
7309
  " readonly VITE_TOPOLO_REDIRECT_URI?: string;",
7164
7310
  " readonly VITE_TOPOLO_SCOPES?: string;"
@@ -8489,10 +8635,10 @@ function developerWorkerTs(application) {
8489
8635
  }
8490
8636
 
8491
8637
  // src/commands/app-scaffold-generate.ts
8492
- import { existsSync as existsSync3, mkdirSync, mkdtempSync, readFileSync as readFileSync4, rmSync, writeFileSync } from "fs";
8638
+ import { existsSync as existsSync3, mkdirSync, mkdtempSync, readFileSync as readFileSync5, rmSync, writeFileSync } from "fs";
8493
8639
  import { spawnSync } from "child_process";
8494
8640
  import { tmpdir } from "os";
8495
- import path2 from "path";
8641
+ import path3 from "path";
8496
8642
  function resolveGeneratorPath() {
8497
8643
  const candidates = [
8498
8644
  // Published CLI: vendored alongside dist/index.js at build time.
@@ -8519,18 +8665,18 @@ var GENERATED = {
8519
8665
  };
8520
8666
  function deriveGeneratedConfigs(files, base) {
8521
8667
  const generator = resolveGeneratorPath();
8522
- const root = mkdtempSync(path2.join(tmpdir(), "topolo-scaffold-generate-"));
8668
+ const root = mkdtempSync(path3.join(tmpdir(), "topolo-scaffold-generate-"));
8523
8669
  try {
8524
8670
  const prefix = `${base}/`;
8525
8671
  for (const file of files) {
8526
8672
  if (!file.path.startsWith(prefix)) continue;
8527
- const abs = path2.join(root, file.path.slice(prefix.length));
8528
- mkdirSync(path2.dirname(abs), { recursive: true });
8673
+ const abs = path3.join(root, file.path.slice(prefix.length));
8674
+ mkdirSync(path3.dirname(abs), { recursive: true });
8529
8675
  writeFileSync(abs, file.content, "utf8");
8530
8676
  }
8531
8677
  const result = spawnSync(
8532
8678
  process.execPath,
8533
- [generator, `--manifest=${path2.join(root, "topolo.app.json")}`],
8679
+ [generator, `--manifest=${path3.join(root, "topolo.app.json")}`],
8534
8680
  { cwd: root, encoding: "utf8" }
8535
8681
  );
8536
8682
  if (result.status !== 0) {
@@ -8547,7 +8693,7 @@ ${result.stdout ?? ""}`);
8547
8693
  return written.map((rel) => ({
8548
8694
  path: `${base}/${rel}`,
8549
8695
  ...GENERATED,
8550
- content: readFileSync4(path2.join(root, rel), "utf8")
8696
+ content: readFileSync5(path3.join(root, rel), "utf8")
8551
8697
  }));
8552
8698
  } finally {
8553
8699
  rmSync(root, { recursive: true, force: true });
@@ -8829,6 +8975,13 @@ function topoloAppManifestJson(application, options) {
8829
8975
  production: "cd ../.. && DEPLOY_ENVIRONMENT=production VITE_TOPOLO_AUTH_URL=https://auth.topolo.app pnpm run build"
8830
8976
  },
8831
8977
  healthcheckPath: options.api ? "/api/health" : "/",
8978
+ vars: {
8979
+ INSIGHTS_SITE_KEY: {
8980
+ development: "",
8981
+ staging: "",
8982
+ production: ""
8983
+ }
8984
+ },
8832
8985
  ...options.api ? {
8833
8986
  bindings: {
8834
8987
  services: [
@@ -8887,6 +9040,7 @@ function topoloAppManifestJson(application, options) {
8887
9040
  version: "1.0.0",
8888
9041
  pricing: { type: "free", monthlyPrice: null },
8889
9042
  supportEmail: "support@topolo.io",
9043
+ repoUrl: `https://github.com/Topolo-io/${application.appDir}`,
8890
9044
  auth: {
8891
9045
  callbackPath: "/auth/callback",
8892
9046
  requestedScopes: unique3([
@@ -8900,7 +9054,7 @@ function topoloAppManifestJson(application, options) {
8900
9054
  },
8901
9055
  capabilities: options.payload.capabilities,
8902
9056
  marketplace: {
8903
- intent: options.payload.distributionModel === "marketplace" ? "submit_when_ready" : "not_requested",
9057
+ intent: options.payload.distributionModel === "marketplace" ? "publish" : "not_requested",
8904
9058
  status: "preview",
8905
9059
  shortBlurb: options.payload.experience.tagline,
8906
9060
  tagline: options.payload.experience.tagline,
@@ -9693,7 +9847,7 @@ function applicationScaffoldPayload(application, options = {}) {
9693
9847
  const containerAppId = normalizeContainerAppId(options.containerAppId, surfaceModel);
9694
9848
  const profile = normalizeScaffoldProfile(options.profile);
9695
9849
  const ownerType = target === "platform" ? "topolo_first_party" : "third_party";
9696
- const distributionModel = target === "platform" ? "marketplace" : "organization_internal";
9850
+ const distributionModel = target === "platform" ? "marketplace" : options.distributionModel ?? "organization_internal";
9697
9851
  const capabilityComposition = resolveApplicationCapabilities({
9698
9852
  target,
9699
9853
  browser,
@@ -9781,7 +9935,8 @@ function applicationScaffoldPayload(application, options = {}) {
9781
9935
  target,
9782
9936
  browser,
9783
9937
  api,
9784
- ciWorkflow
9938
+ ciWorkflow,
9939
+ repoRoot: options.repoRoot
9785
9940
  }),
9786
9941
  commands: scaffoldCommands({
9787
9942
  id,
@@ -9869,7 +10024,8 @@ function scaffoldFiles(options) {
9869
10024
  browser: options.browser,
9870
10025
  api: options.api,
9871
10026
  resources: options.payload.resources,
9872
- packages: options.payload.capabilityComposition.packages
10027
+ packages: options.payload.capabilityComposition.packages,
10028
+ repoRoot: options.repoRoot
9873
10029
  })
9874
10030
  },
9875
10031
  {
@@ -10584,7 +10740,7 @@ function buildProvisioningRequest(payload, supportEmail) {
10584
10740
  ...payload.application.appId ? [`${payload.application.id}:read`] : []
10585
10741
  ])),
10586
10742
  marketplace: {
10587
- intent: payload.distributionModel === "marketplace" ? "submit_when_ready" : "not_requested",
10743
+ intent: payload.target === "platform" && payload.distributionModel === "marketplace" ? "publish" : payload.distributionModel === "marketplace" ? "submit_when_ready" : "not_requested",
10588
10744
  status: "preview",
10589
10745
  shortBlurb: payload.experience.tagline,
10590
10746
  tagline: payload.experience.tagline,
@@ -10600,7 +10756,7 @@ function buildProvisioningRequest(payload, supportEmail) {
10600
10756
  pricingType: "free",
10601
10757
  monthlyPrice: null,
10602
10758
  demoUrl: payload.application.productionUrl,
10603
- repoUrl: null,
10759
+ repoUrl: payload.target === "platform" ? `https://github.com/Topolo-io/${payload.application.appDir}` : null,
10604
10760
  supportEmail,
10605
10761
  tags: [],
10606
10762
  screenshots: [],
@@ -10680,18 +10836,18 @@ import { join as join3 } from "path";
10680
10836
 
10681
10837
  // src/commands/app-reconcile.ts
10682
10838
  import { readFile as readFile4, writeFile as writeFile5 } from "fs/promises";
10683
- import path4 from "path";
10839
+ import path5 from "path";
10684
10840
  import { createInterface as createInterface2 } from "readline/promises";
10685
10841
  import { stdin as input2, stdout as output } from "process";
10686
10842
 
10687
10843
  // src/commands/app-capability-composition.ts
10688
10844
  import { mkdir as mkdir3, readFile as readFile3, writeFile as writeFile4 } from "fs/promises";
10689
- import path3 from "path";
10845
+ import path4 from "path";
10690
10846
  async function reconcileApplicationCapabilitySource(options) {
10691
- const manifestPath = path3.resolve(options.manifestPath || "topolo.app.json");
10692
- const root = path3.dirname(manifestPath);
10693
- const packagePath = path3.join(root, "package.json");
10694
- const contractPath = path3.join(root, "topolo.capability-contract.json");
10847
+ const manifestPath = path4.resolve(options.manifestPath || "topolo.app.json");
10848
+ const root = path4.dirname(manifestPath);
10849
+ const packagePath = path4.join(root, "package.json");
10850
+ const contractPath = path4.join(root, "topolo.capability-contract.json");
10695
10851
  const manifest = parseRecord(await readFile3(manifestPath, "utf8"), manifestPath);
10696
10852
  const registration = record(manifest.registration);
10697
10853
  if (!registration) throw new Error("topolo.app.json must declare registration before capability composition.");
@@ -10701,13 +10857,15 @@ async function reconcileApplicationCapabilitySource(options) {
10701
10857
  const target = options.ownerType === "topolo_first_party" ? "platform" : "developer";
10702
10858
  const surfaces = resolveManifestSurfaces(manifest, registration);
10703
10859
  const existing = Array.isArray(registration.capabilities) ? registration.capabilities.filter((value) => typeof value === "string") : [];
10860
+ const declaredNotificationRole = record(manifest.notifications)?.role;
10861
+ const inferredCapabilities = declaredNotificationRole === "producer" ? ["notification_producer"] : [];
10704
10862
  const capabilities = resolveApplicationCapabilities({
10705
10863
  target,
10706
10864
  browser: surfaces.browser,
10707
10865
  api: surfaces.api,
10708
10866
  mobile: surfaces.mobile,
10709
10867
  distributionModel: registration.distributionModel === "marketplace" ? "marketplace" : "organization_internal",
10710
- requested: [...existing, ...options.additions ?? []]
10868
+ requested: [...existing, ...inferredCapabilities, ...options.additions ?? []]
10711
10869
  });
10712
10870
  const marketplace = record(registration.marketplace);
10713
10871
  const unlistedNativeArtifact = options.ownerType === "topolo_first_party" && registration.surfaceModel === "mobile_container" && registration.distributionModel === "organization_internal" && marketplace?.intent === "unlisted";
@@ -10736,7 +10894,7 @@ async function reconcileApplicationCapabilitySource(options) {
10736
10894
  const nextDependencies = { ...dependencies };
10737
10895
  for (const packageName of capabilities.packages) {
10738
10896
  if (typeof nextDependencies[packageName] !== "string") {
10739
- nextDependencies[packageName] = packageVersion(packageName, target);
10897
+ nextDependencies[packageName] = packageVersion(packageName, target, { repoRoot: options.repoRoot, cwd: root });
10740
10898
  }
10741
10899
  }
10742
10900
  const sortedDependencies = sortRecord(nextDependencies);
@@ -10746,9 +10904,9 @@ async function reconcileApplicationCapabilitySource(options) {
10746
10904
  compareChange(changes, "topolo.capability-contract.json", existingContract, expectedContract);
10747
10905
  const adapter = target === "platform" ? managedCapabilityAdapter(capabilities.selected) : null;
10748
10906
  const apiDirectory = resolveApiDirectory(root, manifest, target);
10749
- const adapterPath = path3.join(apiDirectory, "src", "topolo-capabilities.ts");
10907
+ const adapterPath = path4.join(apiDirectory, "src", "topolo-capabilities.ts");
10750
10908
  if (adapter) compareChange(changes, relativePath(root, adapterPath), await readOptionalText(adapterPath), adapter);
10751
- const pricingPath = path3.join(root, "pricing-manifest.json");
10909
+ const pricingPath = path4.join(root, "pricing-manifest.json");
10752
10910
  const pricingManifest = capabilities.selected.includes("billing") ? defaultPricingManifest({
10753
10911
  appId: String(manifest.appId || manifest.app_id || "").trim(),
10754
10912
  displayName: String(registration.displayName || manifest.name || "Application"),
@@ -10760,7 +10918,7 @@ async function reconcileApplicationCapabilitySource(options) {
10760
10918
  const missingResources = capabilities.resources.filter((resource) => !manifestProvidesResource(manifest, resource));
10761
10919
  const verticalConfiguration = [];
10762
10920
  for (const [capability2, fileName, description] of VERTICAL_CAPABILITY_FILES) {
10763
- if (capabilities.selected.includes(capability2) && !await fileExists(path3.join(root, fileName))) {
10921
+ if (capabilities.selected.includes(capability2) && !await fileExists(path4.join(root, fileName))) {
10764
10922
  verticalConfiguration.push(`${fileName}: ${description}`);
10765
10923
  }
10766
10924
  }
@@ -10775,7 +10933,7 @@ async function reconcileApplicationCapabilitySource(options) {
10775
10933
  await writeJson(contractPath, expectedContract);
10776
10934
  if (pricingManifest) await writeJson(pricingPath, pricingManifest);
10777
10935
  if (adapter) {
10778
- await mkdir3(path3.dirname(adapterPath), { recursive: true });
10936
+ await mkdir3(path4.dirname(adapterPath), { recursive: true });
10779
10937
  await writeFile4(adapterPath, adapter, "utf8");
10780
10938
  }
10781
10939
  }
@@ -10878,11 +11036,8 @@ function manifestProvidesResource(manifest, resource) {
10878
11036
  }
10879
11037
  return false;
10880
11038
  }
10881
- function packageVersion(packageName, target) {
10882
- if (target === "platform") {
10883
- if (packageName === "@topolo-io/notifications") return "^0.6.8";
10884
- return "latest";
10885
- }
11039
+ function packageVersion(packageName, target, resolution) {
11040
+ if (target === "platform") return platformPackagePin(packageName, resolution);
10886
11041
  if (packageName === "@topolo/login") return "^0.1.0";
10887
11042
  if (packageName === "@topolo/sdk") return "^0.8.1";
10888
11043
  throw new Error(`Capability registry exposed private package ${packageName} to a third-party application.`);
@@ -10959,13 +11114,13 @@ function resolveApiDirectory(root, manifest, target) {
10959
11114
  for (const value of Object.values(record(manifest.targets) ?? {})) {
10960
11115
  const targetRecord = record(value);
10961
11116
  if (targetRecord?.kind === "worker" && !targetRecord.assets && typeof targetRecord.dir === "string") {
10962
- return path3.resolve(root, targetRecord.dir);
11117
+ return path4.resolve(root, targetRecord.dir);
10963
11118
  }
10964
11119
  }
10965
- return path3.join(root, "apps", "api");
11120
+ return path4.join(root, "apps", "api");
10966
11121
  }
10967
11122
  function relativePath(root, filePath) {
10968
- return path3.relative(root, filePath).split(path3.sep).join("/");
11123
+ return path4.relative(root, filePath).split(path4.sep).join("/");
10969
11124
  }
10970
11125
 
10971
11126
  // src/commands/app-reconcile.ts
@@ -11035,7 +11190,7 @@ function titleFromSlug(value) {
11035
11190
  return value.replace(/^topolo[-_]/, "").split(/[-_]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
11036
11191
  }
11037
11192
  async function completeApplicationRegistrationInteractively(options) {
11038
- const manifestPath = path4.resolve(options.manifestPath || "topolo.app.json");
11193
+ const manifestPath = path5.resolve(options.manifestPath || "topolo.app.json");
11039
11194
  const manifest = JSON.parse(await readFile4(manifestPath, "utf8"));
11040
11195
  const existing = record2(manifest.registration) || {};
11041
11196
  const appId = String(manifest.appId || manifest.app_id || "").trim();
@@ -11084,7 +11239,7 @@ async function completeApplicationRegistrationInteractively(options) {
11084
11239
  },
11085
11240
  capabilities: Array.isArray(existing.capabilities) ? existing.capabilities : ["login", "launcher"],
11086
11241
  marketplace: record2(existing.marketplace) || {
11087
- intent: options.expectedOwnerType === "topolo_first_party" ? "submit_when_ready" : "not_requested",
11242
+ intent: options.expectedOwnerType === "topolo_first_party" ? "publish" : "not_requested",
11088
11243
  status: "preview",
11089
11244
  shortBlurb: description,
11090
11245
  tagline: description,
@@ -11115,7 +11270,7 @@ async function completeApplicationRegistrationInteractively(options) {
11115
11270
  }
11116
11271
  }
11117
11272
  async function loadApplicationReconcileRequest(options) {
11118
- const manifestPath = path4.resolve(options.manifestPath || "topolo.app.json");
11273
+ const manifestPath = path5.resolve(options.manifestPath || "topolo.app.json");
11119
11274
  const raw = await readFile4(manifestPath, "utf8");
11120
11275
  const manifest = JSON.parse(raw);
11121
11276
  assertRegistration(manifest.registration);
@@ -11161,7 +11316,8 @@ async function loadApplicationReconcileRequest(options) {
11161
11316
  requestedScopes: registration.auth?.requestedScopes ?? [],
11162
11317
  capabilities: registration.capabilities,
11163
11318
  marketplace: { ...registration.marketplace, appUrl: productionUrl },
11164
- notifications: manifest.notifications ?? null
11319
+ notifications: manifest.notifications ?? null,
11320
+ actions: manifest.actions ?? []
11165
11321
  }
11166
11322
  };
11167
11323
  }
@@ -11413,6 +11569,9 @@ function registerAppsCommand(program2) {
11413
11569
  apps.command("scaffold <application>").description(
11414
11570
  "Generate a third-party Topolo application scaffold for business or personal/household use."
11415
11571
  ).option("--json", "Output JSON").option("--no-json", "Output human-readable checklist").option("--app-dir <path>", "Application directory under the scaffold root").option("--name <name>", "Application display/package source name").option("--package-name <name>", "package.json name").option("--production-url <url>", "Production browser URL").option("--app-id <id>", "Stable SDK/Auth app id for API-backed apps").option("--audience <audience>", "Developer app audience: business or personal").option("--tenancy <tenancy>", "Developer app tenancy: organization or household").option(
11572
+ "--distribution-model <model>",
11573
+ "Developer app distribution: organization_internal or marketplace (marketplace requires approval)"
11574
+ ).option(
11416
11575
  "--surface-model <surfaceModel>",
11417
11576
  "Developer app surface model: web_app, mobile_container, mobile_module, or messaging_surface"
11418
11577
  ).option("--container-app-id <appId>", "Container app id when --surface-model mobile_module is used").option("--capability <id...>", "Compose one or more approved Topolo capabilities").option("--write", "Write the generated scaffold files to disk").option("--repo-root <path>", "Directory where scaffold files should be written").option("--force", "Overwrite existing scaffold files when --write is set").option("--with-api", "Include API/service files for developer scaffolds").option("--no-api", "Do not include API/service requirements").option("--no-browser", "Do not include browser-shell requirements").option(
@@ -11433,6 +11592,7 @@ function registerAppsCommand(program2) {
11433
11592
  target: "developer",
11434
11593
  audience: resolveScaffoldAudience(opts.audience),
11435
11594
  tenancy: resolveScaffoldTenancy(opts.tenancy),
11595
+ distributionModel: resolveScaffoldDistributionModel(opts.distributionModel),
11436
11596
  surfaceModel: resolveScaffoldSurfaceModel(opts.surfaceModel),
11437
11597
  containerAppId: opts.containerAppId,
11438
11598
  capabilities: opts.capability
@@ -11519,7 +11679,7 @@ function applicationAuditPayload(application, options = {}) {
11519
11679
  }
11520
11680
  function recordApplicationEvidence(application, options = {}) {
11521
11681
  const appId = resolveApplication(application).id;
11522
- const root = path5.resolve(options.appRoot ?? process.cwd());
11682
+ const root = path6.resolve(options.appRoot ?? process.cwd());
11523
11683
  if (!existsSync4(root)) {
11524
11684
  throw new Error(`Application root does not exist: ${root}`);
11525
11685
  }
@@ -11531,12 +11691,12 @@ function recordApplicationEvidence(application, options = {}) {
11531
11691
  commit = void 0;
11532
11692
  }
11533
11693
  }
11534
- const evidenceDir = path5.join(root, ".topolo");
11535
- const evidencePath = path5.join(evidenceDir, "evidence.json");
11694
+ const evidenceDir = path6.join(root, ".topolo");
11695
+ const evidencePath = path6.join(evidenceDir, "evidence.json");
11536
11696
  let before = null;
11537
11697
  if (existsSync4(evidencePath)) {
11538
11698
  try {
11539
- const raw = JSON.parse(readFileSync5(evidencePath, "utf8"));
11699
+ const raw = JSON.parse(readFileSync6(evidencePath, "utf8"));
11540
11700
  if (raw && typeof raw === "object" && raw.version === 1) {
11541
11701
  before = raw;
11542
11702
  }
@@ -11792,6 +11952,16 @@ function resolveScaffoldTenancy(value) {
11792
11952
  }
11793
11953
  throw new Error("Invalid --tenancy value. Use organization or household.");
11794
11954
  }
11955
+ function resolveScaffoldDistributionModel(value) {
11956
+ if (!value) return void 0;
11957
+ const normalized = value.trim().toLowerCase().replace(/-/g, "_");
11958
+ if (normalized === "marketplace" || normalized === "organization_internal") {
11959
+ return normalized;
11960
+ }
11961
+ throw new Error(
11962
+ "Invalid --distribution-model value. Use organization_internal or marketplace."
11963
+ );
11964
+ }
11795
11965
  function resolveScaffoldSurfaceModel(value) {
11796
11966
  if (!value) return void 0;
11797
11967
  const normalized = value.trim().toLowerCase();
@@ -11831,14 +12001,14 @@ function statusesAtOrWorse(threshold) {
11831
12001
  }
11832
12002
 
11833
12003
  // src/commands/platform.ts
11834
- import { readdirSync as readdirSync2, readFileSync as readFileSync6, statSync as statSync2 } from "fs";
11835
- import path7 from "path";
12004
+ import { readdirSync as readdirSync3, readFileSync as readFileSync7, statSync as statSync2 } from "fs";
12005
+ import path8 from "path";
11836
12006
 
11837
12007
  // src/commands/app-capability-provision.ts
11838
12008
  import { readFile as readFile5, writeFile as writeFile6 } from "fs/promises";
11839
- import path6 from "path";
12009
+ import path7 from "path";
11840
12010
  async function provisionApplicationResources(options) {
11841
- const manifestPath = path6.resolve(options.manifestPath || "topolo.app.json");
12011
+ const manifestPath = path7.resolve(options.manifestPath || "topolo.app.json");
11842
12012
  const manifest = parseRecord2(await readFile5(manifestPath, "utf8"), manifestPath);
11843
12013
  const environments = requiredRecord(manifest.environments, "topolo.app.json#environments");
11844
12014
  const environment = requiredRecord(environments[options.environment], `topolo.app.json#environments.${options.environment}`);
@@ -12043,7 +12213,8 @@ function registerPlatformCommand(program2) {
12043
12213
  navigationMode: opts.navigationMode,
12044
12214
  workspaceSwitcher: opts.workspaceSwitcher,
12045
12215
  uiTemplate: opts.uiTemplate,
12046
- tagline: opts.tagline
12216
+ tagline: opts.tagline,
12217
+ repoRoot: opts.repoRoot
12047
12218
  });
12048
12219
  if (opts.workflowOnly && !payload.ciWorkflow) {
12049
12220
  throw new Error("--workflow-only is only available for first-party scaffolds.");
@@ -12110,12 +12281,12 @@ var SKIPPED_SCAN_DIRS = /* @__PURE__ */ new Set([
12110
12281
  "output"
12111
12282
  ]);
12112
12283
  function scanStagingProductionUrls(rootInput, allowPatterns) {
12113
- const root = path7.resolve(rootInput);
12284
+ const root = path8.resolve(rootInput);
12114
12285
  const allowlist = allowPatterns.map((pattern) => new RegExp(pattern));
12115
12286
  const violations = [];
12116
12287
  function shouldSkipFile(filePath) {
12117
- const basename2 = path7.basename(filePath);
12118
- const relativePath2 = path7.relative(root, filePath);
12288
+ const basename2 = path8.basename(filePath);
12289
+ const relativePath2 = path8.relative(root, filePath);
12119
12290
  if (basename2 === "package-lock.json" || basename2 === "pnpm-lock.yaml" || basename2 === "yarn.lock") return true;
12120
12291
  if (basename2 === "topolo.cloudcontrol.json") return true;
12121
12292
  if (basename2 === "wrangler.toml" || basename2 === "wrangler.jsonc") return true;
@@ -12124,15 +12295,15 @@ function scanStagingProductionUrls(rootInput, allowPatterns) {
12124
12295
  if (basename2.endsWith(".generated.ts")) return true;
12125
12296
  if (basename2.endsWith(".test.ts") || basename2.endsWith(".test.tsx") || basename2.endsWith(".spec.ts")) return true;
12126
12297
  if (basename2 === ".env.production") return true;
12127
- if (relativePath2 === path7.join("src", "environment.ts") || relativePath2 === path7.join("src", "environmentUrls.ts") || relativePath2.endsWith(path7.join("src", "environment.ts")) || relativePath2.endsWith(path7.join("src", "lib", "environment.ts")) || relativePath2 === path7.join("packages", "topolo-ui-kit", "src", "environmentUrls.ts")) return true;
12128
- if (relativePath2.includes(`${path7.sep}test${path7.sep}`) || relativePath2.includes(`${path7.sep}tests${path7.sep}`) || relativePath2.includes(`${path7.sep}e2e${path7.sep}`)) return true;
12129
- if (relativePath2.startsWith(`scripts${path7.sep}`) || relativePath2.includes(`${path7.sep}scripts${path7.sep}`)) return true;
12130
- return !RUNTIME_EXTENSIONS.has(path7.extname(filePath));
12298
+ if (relativePath2 === path8.join("src", "environment.ts") || relativePath2 === path8.join("src", "environmentUrls.ts") || relativePath2.endsWith(path8.join("src", "environment.ts")) || relativePath2.endsWith(path8.join("src", "lib", "environment.ts")) || relativePath2 === path8.join("packages", "topolo-ui-kit", "src", "environmentUrls.ts")) return true;
12299
+ if (relativePath2.includes(`${path8.sep}test${path8.sep}`) || relativePath2.includes(`${path8.sep}tests${path8.sep}`) || relativePath2.includes(`${path8.sep}e2e${path8.sep}`)) return true;
12300
+ if (relativePath2.startsWith(`scripts${path8.sep}`) || relativePath2.includes(`${path8.sep}scripts${path8.sep}`)) return true;
12301
+ return !RUNTIME_EXTENSIONS.has(path8.extname(filePath));
12131
12302
  }
12132
12303
  function scanFile(filePath) {
12133
12304
  if (shouldSkipFile(filePath)) return;
12134
- const relativePath2 = path7.relative(root, filePath);
12135
- const content = readFileSync6(filePath, "utf8");
12305
+ const relativePath2 = path8.relative(root, filePath);
12306
+ const content = readFileSync7(filePath, "utf8");
12136
12307
  const lines = content.split(/\r?\n/);
12137
12308
  lines.forEach((line, index) => {
12138
12309
  const matches = [...line.matchAll(PRODUCTION_TOPOLO_URL_PATTERN)].map((match) => match[0]);
@@ -12145,8 +12316,8 @@ function scanStagingProductionUrls(rootInput, allowPatterns) {
12145
12316
  });
12146
12317
  }
12147
12318
  function walk(dir) {
12148
- for (const entry of readdirSync2(dir, { withFileTypes: true })) {
12149
- const fullPath = path7.join(dir, entry.name);
12319
+ for (const entry of readdirSync3(dir, { withFileTypes: true })) {
12320
+ const fullPath = path8.join(dir, entry.name);
12150
12321
  if (entry.isDirectory()) {
12151
12322
  if (!SKIPPED_SCAN_DIRS.has(entry.name)) walk(fullPath);
12152
12323
  continue;
@@ -12314,7 +12485,7 @@ var DEFAULT_SEED_BASE_URL = "https://seed.stg.topolo.us";
12314
12485
  function seedBaseUrl() {
12315
12486
  return process.env.TOPOLO_SEED_URL || DEFAULT_SEED_BASE_URL;
12316
12487
  }
12317
- async function authedFetch(path8, init = {}) {
12488
+ async function authedFetch(path9, init = {}) {
12318
12489
  const credential = await refreshCredentialIfNeeded("staging");
12319
12490
  if (!credential) {
12320
12491
  throw new Error("No staging credential configured. Run `topolo auth login --env staging` or set TOPOLO_STAGING_API_KEY.");
@@ -12324,7 +12495,7 @@ async function authedFetch(path8, init = {}) {
12324
12495
  else headers.set("Authorization", `Bearer ${credential.accessToken}`);
12325
12496
  headers.set("X-Topolo-Client", `topolo-cli/${CLI_VERSION}`);
12326
12497
  if (init.body && !headers.has("Content-Type")) headers.set("Content-Type", "application/json");
12327
- const response = await fetch(`${seedBaseUrl()}${path8}`, { ...init, headers });
12498
+ const response = await fetch(`${seedBaseUrl()}${path9}`, { ...init, headers });
12328
12499
  const text = await response.text();
12329
12500
  let body;
12330
12501
  try {
@@ -12601,7 +12772,7 @@ function createOAuthClientPayload(options) {
12601
12772
  logo_url: options.logoUrl
12602
12773
  };
12603
12774
  }
12604
- async function authFetchJson(path8, init = {}) {
12775
+ async function authFetchJson(path9, init = {}) {
12605
12776
  const environment = selectedEnvironment();
12606
12777
  const credential = await refreshCredentialIfNeeded(environment);
12607
12778
  if (!credential) {
@@ -12623,7 +12794,7 @@ async function authFetchJson(path8, init = {}) {
12623
12794
  throw err;
12624
12795
  }
12625
12796
  headers.set("Authorization", `Bearer ${credential.accessToken}`);
12626
- const response = await fetch(`${authBaseUrl}${path8}`, { ...init, headers });
12797
+ const response = await fetch(`${authBaseUrl}${path9}`, { ...init, headers });
12627
12798
  const text = await response.text();
12628
12799
  const payload = text ? JSON.parse(text) : {};
12629
12800
  if (!response.ok || payload.success === false) {
@@ -12878,11 +13049,11 @@ function registerViaOfficialCli(cli, mcp, agentName) {
12878
13049
  return result.status === 0;
12879
13050
  }
12880
13051
  async function registerClaudeViaConfig(mcp) {
12881
- const path8 = join5(homedir2(), ".claude.json");
13052
+ const path9 = join5(homedir2(), ".claude.json");
12882
13053
  let config = {};
12883
- if (existsSync5(path8)) {
13054
+ if (existsSync5(path9)) {
12884
13055
  try {
12885
- config = JSON.parse(await readFile7(path8, "utf8"));
13056
+ config = JSON.parse(await readFile7(path9, "utf8"));
12886
13057
  } catch {
12887
13058
  config = {};
12888
13059
  }
@@ -12895,13 +13066,13 @@ async function registerClaudeViaConfig(mcp) {
12895
13066
  env: { TOPOLO_AGENT_NAME: AGENT_NAME_FOR.claude }
12896
13067
  };
12897
13068
  config.mcpServers = servers;
12898
- await writeFile7(path8, `${JSON.stringify(config, null, 2)}
13069
+ await writeFile7(path9, `${JSON.stringify(config, null, 2)}
12899
13070
  `, "utf8");
12900
13071
  }
12901
13072
  async function registerCodexViaConfig(mcp) {
12902
- const path8 = join5(homedir2(), ".codex", "config.toml");
13073
+ const path9 = join5(homedir2(), ".codex", "config.toml");
12903
13074
  let text = "";
12904
- if (existsSync5(path8)) text = await readFile7(path8, "utf8");
13075
+ if (existsSync5(path9)) text = await readFile7(path9, "utf8");
12905
13076
  text = text.replace(
12906
13077
  /(^|\n)\[mcp_servers\.topolo(?:\.[a-z]+)?\][^\[]*/g,
12907
13078
  (match) => match.startsWith("\n") ? "\n" : ""
@@ -12917,8 +13088,8 @@ command = "${mcp.command}"${argsToml}
12917
13088
  [mcp_servers.topolo.env]
12918
13089
  TOPOLO_AGENT_NAME = "${AGENT_NAME_FOR.codex}"
12919
13090
  `;
12920
- await mkdir4(dirname4(path8), { recursive: true });
12921
- await writeFile7(path8, `${text}${block}`, "utf8");
13091
+ await mkdir4(dirname4(path9), { recursive: true });
13092
+ await writeFile7(path9, `${text}${block}`, "utf8");
12922
13093
  }
12923
13094
  async function installForAgent(agent, sourceDir, mcp, opts) {
12924
13095
  const skillDir = agent === "claude" ? claudeSkillDir(opts.projectDir) : codexSkillDir();