@hasna/instructions 0.7.0 → 0.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/README.md +52 -11
  2. package/dist/chunks/{apply-7svah2qm.js → apply-ps6jjt6k.js} +3 -3
  3. package/dist/chunks/{apply-jp13sa1e.js → apply-wj7wh5km.js} +3 -3
  4. package/dist/chunks/{index-1cnyjnd7.js → index-18j7x3xw.js} +2 -2
  5. package/dist/chunks/{index-3djthcm6.js → index-27az1qb1.js} +28 -1
  6. package/dist/chunks/{index-fwbs6tma.js → index-ape24zc0.js} +2 -2
  7. package/dist/chunks/{index-bzyxvwcd.js → index-ek15201v.js} +2 -2
  8. package/dist/chunks/{index-arrrx0ed.js → index-mvckkf15.js} +39 -20
  9. package/dist/chunks/{index-7m4j8a33.js → index-n6nh6f5r.js} +235 -20
  10. package/dist/chunks/{index-4pfq42t5.js → index-pq18fdbj.js} +146 -32
  11. package/dist/chunks/{index-n3fjspr0.js → index-preyvj8n.js} +28 -1
  12. package/dist/chunks/{index-z3ma4aqk.js → index-y8410ve0.js} +3 -3
  13. package/dist/chunks/{local-5wvv5xv3.js → local-1c1qxzvx.js} +155 -4
  14. package/dist/chunks/{local-zxa5dpf4.js → local-hc67bynj.js} +155 -4
  15. package/dist/chunks/{s3-backup-n2z4fwyh.js → s3-backup-hxe3zpfz.js} +1 -1
  16. package/dist/chunks/{s3-object-store-90tgbh6k.js → s3-object-store-n0s82swt.js} +1 -1
  17. package/dist/chunks/{sync-r8t7zsp3.js → sync-12m3vs6g.js} +4 -4
  18. package/dist/chunks/{sync-2075deve.js → sync-azd9t4p8.js} +4 -4
  19. package/dist/chunks/{template-wgnzdn7h.js → template-e4qrxs8p.js} +1 -1
  20. package/dist/chunks/{template-fsfxpe4p.js → template-nhn124zd.js} +1 -1
  21. package/dist/cli/index.js +860 -181
  22. package/dist/data/config-store.d.ts +22 -6
  23. package/dist/data/config-store.d.ts.map +1 -1
  24. package/dist/db/configs.d.ts +4 -1
  25. package/dist/db/configs.d.ts.map +1 -1
  26. package/dist/db/local.d.ts +1 -1
  27. package/dist/db/local.d.ts.map +1 -1
  28. package/dist/index.d.ts +5 -3
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +940 -134
  31. package/dist/lib/asset-plan.d.ts.map +1 -1
  32. package/dist/lib/codewith-shared-todos-storage-standard.d.ts.map +1 -1
  33. package/dist/lib/compact-output.d.ts +2 -18
  34. package/dist/lib/compact-output.d.ts.map +1 -1
  35. package/dist/lib/dangerous-operation-guard-standard.d.ts.map +1 -1
  36. package/dist/lib/export.d.ts.map +1 -1
  37. package/dist/lib/global-agent-rules-standard.d.ts.map +1 -1
  38. package/dist/lib/global-source-coverage.d.ts +12 -7
  39. package/dist/lib/global-source-coverage.d.ts.map +1 -1
  40. package/dist/lib/import.d.ts.map +1 -1
  41. package/dist/lib/instruction-graph.d.ts +1 -1
  42. package/dist/lib/instruction-graph.d.ts.map +1 -1
  43. package/dist/lib/instruction-source-policy.d.ts +6 -0
  44. package/dist/lib/instruction-source-policy.d.ts.map +1 -0
  45. package/dist/lib/platform-profiles.d.ts.map +1 -1
  46. package/dist/lib/project-dashboard-standard.d.ts.map +1 -1
  47. package/dist/lib/session-apply.d.ts +24 -0
  48. package/dist/lib/session-apply.d.ts.map +1 -1
  49. package/dist/lib/session-refresh.d.ts +30 -0
  50. package/dist/lib/session-refresh.d.ts.map +1 -0
  51. package/dist/lib/session-render.d.ts +34 -1
  52. package/dist/lib/session-render.d.ts.map +1 -1
  53. package/dist/lib/transforms.d.ts +1 -0
  54. package/dist/lib/transforms.d.ts.map +1 -1
  55. package/dist/mcp/index.js +23 -22
  56. package/dist/mcp/server.d.ts.map +1 -1
  57. package/dist/sdk/index.js +46 -3
  58. package/dist/sdk/v1-client.d.ts +10 -3
  59. package/dist/sdk/v1-client.d.ts.map +1 -1
  60. package/dist/sdk/v1.generated.d.ts +52 -2
  61. package/dist/sdk/v1.generated.d.ts.map +1 -1
  62. package/dist/server/index.d.ts +1 -1
  63. package/dist/server/index.d.ts.map +1 -1
  64. package/dist/server/index.js +215 -15
  65. package/dist/server/openapi.d.ts +240 -3
  66. package/dist/server/openapi.d.ts.map +1 -1
  67. package/dist/server/v1.d.ts.map +1 -1
  68. package/dist/storage/cloud-store.d.ts +2 -15
  69. package/dist/storage/cloud-store.d.ts.map +1 -1
  70. package/dist/storage/index.js +39 -20
  71. package/dist/storage/s3-object-store.d.ts.map +1 -1
  72. package/dist/types/index.d.ts +49 -2
  73. package/dist/types/index.d.ts.map +1 -1
  74. package/package.json +3 -3
@@ -14,8 +14,9 @@ import {
14
14
  ProfileNotFoundError,
15
15
  isTemplate,
16
16
  renderTemplate,
17
- renderTemplatePreview
18
- } from "./index-n3fjspr0.js";
17
+ renderTemplatePreview,
18
+ validateExpectedConfigVersion
19
+ } from "./index-preyvj8n.js";
19
20
  import {
20
21
  INSTRUCTIONS_LOCAL_OPT_IN_ENV_KEYS,
21
22
  clientTransportEnvKeys,
@@ -77,6 +78,36 @@ function truncateMiddle(value, max = 80) {
77
78
  return `${text.slice(0, head)}...${text.slice(text.length - tail)}`;
78
79
  }
79
80
 
81
+ // src/lib/instruction-source-policy.ts
82
+ function isRetiredInstructionSource(config) {
83
+ return config.tags.some((tag) => tag === "retired-global-source" || tag === "retired-instruction-source");
84
+ }
85
+ function instructionSourceRejection(config) {
86
+ if (isRetiredInstructionSource(config) || config.tags.includes("config-only")) {
87
+ return "source is retired or explicitly configuration-only";
88
+ }
89
+ if (config.category !== "rules")
90
+ return `category ${config.category} is not an instruction source; classify reviewed prose as rules`;
91
+ if (config.format !== "markdown" && config.format !== "text")
92
+ return `format ${config.format} is not instruction prose`;
93
+ if (config.is_template)
94
+ return "unresolved templates must be rendered and reviewed before prompt injection";
95
+ if (!config.content.trim())
96
+ return "instruction source is empty";
97
+ if (config.content.includes("\x00"))
98
+ return "instruction source contains binary content";
99
+ const target = config.target_path?.split(/[\\/]/).pop() ?? "";
100
+ if (/\.(?:json|toml|yaml|yml|ini|sh|bash|zsh|fish|js|ts|py|rules)$/i.test(target)) {
101
+ return "target is an executable, provider policy, or settings file rather than a prompt";
102
+ }
103
+ return null;
104
+ }
105
+ function assertInstructionSource(config) {
106
+ const rejection = instructionSourceRejection(config);
107
+ if (rejection)
108
+ throw new Error(`Cannot inject ${config.slug}: ${rejection}.`);
109
+ }
110
+
80
111
  // src/lib/global-agent-rules-standard.ts
81
112
  import { createHash as createHash7 } from "crypto";
82
113
 
@@ -186,17 +217,18 @@ async function ensureCodewithSharedTodosStorageStandardConfig(store = resolveCon
186
217
  let config;
187
218
  try {
188
219
  const existing = await store.getConfig(CODEWITH_SHARED_TODOS_STORAGE_STANDARD_SLUG);
220
+ if (isRetiredInstructionSource(existing))
221
+ return existing;
189
222
  if (existing.content !== input.content || existing.description !== input.description || existing.category !== input.category || existing.agent !== input.agent || existing.format !== input.format || existing.kind !== input.kind || JSON.stringify(existing.tags) !== JSON.stringify(input.tags)) {
190
223
  config = await store.updateConfig(existing.id, input);
191
224
  } else {
192
225
  config = existing;
193
226
  }
194
- } catch {
227
+ } catch (error) {
228
+ if (!(error instanceof ConfigNotFoundError))
229
+ throw error;
195
230
  config = await store.createConfig(input);
196
231
  }
197
- for (const profile of await store.listProfiles()) {
198
- await store.addConfigToProfile(profile.id, config.id);
199
- }
200
232
  return config;
201
233
  }
202
234
 
@@ -7373,6 +7405,9 @@ function buildCodexAgentsMd(source, context = {}) {
7373
7405
  function buildOpenCodeAgentsMd(source, context = {}) {
7374
7406
  return flattenWithRules(source, context);
7375
7407
  }
7408
+ function buildSumiAgentsMd(source, context = {}) {
7409
+ return flattenWithRules(source, context);
7410
+ }
7376
7411
  function buildCursorMdc(source) {
7377
7412
  const stem = source.target_path ? basename2(source.target_path, extname(source.target_path)) : source.slug;
7378
7413
  const description = source.name || stem;
@@ -7401,6 +7436,8 @@ function applyTransform(source, output, context = {}) {
7401
7436
  return buildCodexAgentsMd(source, context);
7402
7437
  case "opencode-flat":
7403
7438
  return buildOpenCodeAgentsMd(source, context);
7439
+ case "sumi-flat":
7440
+ return buildSumiAgentsMd(source, context);
7404
7441
  case "cursor-mdc":
7405
7442
  return buildCursorMdc(source);
7406
7443
  case "skill-neutral":
@@ -7515,6 +7552,7 @@ var DEFAULT_ASSET_SURFACES = Object.freeze({
7515
7552
  codex: "cli",
7516
7553
  cursor: "ide",
7517
7554
  opencode: "cli",
7555
+ sumi: "cli",
7518
7556
  codewith: "cli",
7519
7557
  qwen: "cli",
7520
7558
  aicopilot: "cli",
@@ -8178,6 +8216,7 @@ var SESSION_RENDER_TOOLS = [
8178
8216
  "codex",
8179
8217
  "cursor",
8180
8218
  "opencode",
8219
+ "sumi",
8181
8220
  "codewith",
8182
8221
  "qwen",
8183
8222
  "aicopilot",
@@ -8266,6 +8305,15 @@ var SESSION_TOOL_ADAPTERS = {
8266
8305
  description: "OpenCode AGENTS.md plus opencode.json instructions pointing at managed fragments.",
8267
8306
  providerSurface: "legacy-dual"
8268
8307
  },
8308
+ sumi: {
8309
+ tool: "sumi",
8310
+ mode: "flattened-markdown",
8311
+ indexFile: "AGENTS.md",
8312
+ managedDir: SESSION_RENDER_INSTRUCTIONS_MANAGED_DIR,
8313
+ envVar: "SUMI_CONFIG_DIR",
8314
+ nativeImports: false,
8315
+ description: "Sumi native AGENTS.md in the explicit resolved config directory or project root."
8316
+ },
8269
8317
  aicopilot: {
8270
8318
  tool: "aicopilot",
8271
8319
  mode: "flattened-markdown",
@@ -8550,9 +8598,19 @@ function skippedSource(source, reason) {
8550
8598
  };
8551
8599
  }
8552
8600
  function normalizeSources(sources, tool, allowEmptySources) {
8553
- const normalized = sources.map((source, index) => {
8601
+ const providerSkipped = [];
8602
+ const normalized = sources.flatMap((source, index) => {
8554
8603
  if (!source.id.trim())
8555
8604
  throw new Error("Session instruction source id is required.");
8605
+ if (source.targetProviders?.length && !providerTargetsTool(source.targetProviders, tool)) {
8606
+ providerSkipped.push({
8607
+ id: source.id,
8608
+ label: source.label ?? source.id,
8609
+ targetProviders: source.targetProviders,
8610
+ reason: "instruction source targets a different provider"
8611
+ });
8612
+ return [];
8613
+ }
8556
8614
  const floored = applyAgentOperatingRulesFloor(source, source.content ?? "");
8557
8615
  const content = filterProviderOnlyBlocks(floored.content, tool);
8558
8616
  const normalized2 = {
@@ -8571,7 +8629,7 @@ function normalizeSources(sources, tool, allowEmptySources) {
8571
8629
  if (!allowEmptySources && !normalized2.content.trim() && normalized2.resolvedRules.length === 0 && !hasPathReferences) {
8572
8630
  throw new Error(`Session instruction source "${source.id}" is empty. Pass --allow-empty-sources only for explicit empty renders.`);
8573
8631
  }
8574
- return normalized2;
8632
+ return [normalized2];
8575
8633
  });
8576
8634
  const originalOrder = [...normalized].sort(compareSessionInstructionSources);
8577
8635
  const deduplicated = deduplicateSemanticPolicySources(normalized);
@@ -8579,7 +8637,7 @@ function normalizeSources(sources, tool, allowEmptySources) {
8579
8637
  validateTargetedReplacementSources(originalOrder, ordered, deduplicated.skipped, tool);
8580
8638
  rejectDuplicateSourceSlugs(ordered);
8581
8639
  rejectDuplicateRulePaths(ordered);
8582
- return { sources: ordered, skipped: deduplicated.skipped };
8640
+ return { sources: ordered, skipped: [...providerSkipped, ...deduplicated.skipped] };
8583
8641
  }
8584
8642
  function compareSessionInstructionSources(a, b) {
8585
8643
  return SESSION_LAYER_RANK[a.resolvedLayer] - SESSION_LAYER_RANK[b.resolvedLayer] || a.resolvedOrder - b.resolvedOrder || a.id.localeCompare(b.id);
@@ -9185,6 +9243,11 @@ function isNativeProfileSessionTarget(input) {
9185
9243
  return (input.tool === "grok" || input.tool === "devin") && Boolean(input.targetHome?.trim()) && !input.projectRoot;
9186
9244
  }
9187
9245
  function adapterFor(input) {
9246
+ if (input.tool === "sumi" && input.projectRoot) {
9247
+ if (input.providerSurface)
9248
+ throw new Error(`Provider surface ${input.providerSurface} is not valid for Sumi.`);
9249
+ return Object.freeze({ ...SESSION_TOOL_ADAPTERS.sumi, projectScoped: true, envVar: undefined });
9250
+ }
9188
9251
  if (input.tool === "opencode" && input.providerSurface) {
9189
9252
  if (input.providerSurface !== "opencode-config-instructions" && input.providerSurface !== "opencode-agents-md") {
9190
9253
  throw new Error(`Provider surface ${input.providerSurface} is not valid for OpenCode.`);
@@ -9226,7 +9289,7 @@ function adapterFor(input) {
9226
9289
  }
9227
9290
  if (input.tool !== "codewith")
9228
9291
  return SESSION_TOOL_ADAPTERS[input.tool];
9229
- const gatedNativeImports = input.codewithNativeImports === true || process.env[CODEWITH_NATIVE_IMPORTS_ENV] === "1" || process.env[CODEWITH_NATIVE_IMPORTS_ENV] === "true";
9292
+ const gatedNativeImports = input.codewithNativeImports ?? (process.env[CODEWITH_NATIVE_IMPORTS_ENV] === "1" || process.env[CODEWITH_NATIVE_IMPORTS_ENV] === "true");
9230
9293
  return gatedNativeImports ? CODEWITH_NATIVE_ADAPTER : CODEWITH_FLATTENED_ADAPTER;
9231
9294
  }
9232
9295
  function getHomeDir() {
@@ -9277,6 +9340,13 @@ function assertSafeTargetRoot(targetHome) {
9277
9340
  return normalized;
9278
9341
  }
9279
9342
  function resolveRenderTarget(input, adapter) {
9343
+ if (input.tool === "sumi" && !input.projectRoot && !input.targetHome?.trim()) {
9344
+ return {
9345
+ targetHome: defaultTargetHome(input.tool, input.profile, input.sessionId),
9346
+ targetKind: "blocked",
9347
+ blockers: ["Sumi requires --target-home from `sumi debug paths config`, or --project-root for repository AGENTS.md."]
9348
+ };
9349
+ }
9280
9350
  if (adapter.projectScoped) {
9281
9351
  if (!input.projectRoot) {
9282
9352
  const label = input.tool === "cursor" ? "Cursor rules" : input.tool === "antigravity" ? "Antigravity rules" : `${adapter.description.split(".")[0]} files`;
@@ -9378,6 +9448,14 @@ function planSessionRender(input) {
9378
9448
  const normalized = normalizeSources(input.sources, input.tool, allowEmptySources);
9379
9449
  const composed = composeSources(normalized.sources, input.tool);
9380
9450
  const orderedSources = composed.sources;
9451
+ if (input.tool === "sumi") {
9452
+ for (const source of orderedSources) {
9453
+ const activation = source.metadata?.["activation"];
9454
+ if (source.globs?.length || source.resolvedRules.some((rule) => rule.globs?.length) || activation?.mode && activation.mode !== "always") {
9455
+ throw new Error(`Sumi AGENTS.md cannot preserve conditional activation for source ${source.id}; compile a profile with an explicit supported fallback.`);
9456
+ }
9457
+ }
9458
+ }
9381
9459
  const skippedSources = [
9382
9460
  ...input.skippedSources ?? [],
9383
9461
  ...normalized.skipped,
@@ -9421,6 +9499,7 @@ function planSessionRender(input) {
9421
9499
  adapterMode: adapter.mode,
9422
9500
  profile: input.profile,
9423
9501
  sessionId: input.sessionId ?? null,
9502
+ ...input.refreshSelector ? { refreshSelector: input.refreshSelector } : {},
9424
9503
  targetHome,
9425
9504
  targetKind,
9426
9505
  targetOwner,
@@ -9933,6 +10012,7 @@ var DEFAULT_PROVIDER_CAPABILITIES = Object.freeze({
9933
10012
  codex: capability("codex", ">=0.1.0", "flattened", "AGENTS.md", { asset_surface: "cli" }),
9934
10013
  cursor: capability("cursor", ">=1.0.0", "cursor-rule", ".cursor/rules/*.mdc", { activation_modes: ["always", "glob"], conditional_artifacts: true, asset_surface: "ide" }),
9935
10014
  opencode: capability("opencode", ">=1.0.0", "managed-fragment", "opencode.json instructions", { provider_variant: "v1-instructions", session_surface: "opencode-config-instructions" }),
10015
+ sumi: capability("sumi", ">=0.2.22 <0.3.0", "flattened", "AGENTS.md"),
9936
10016
  codewith: capability("codewith", ">=0.1.0", "flattened", "CODEWITH.md"),
9937
10017
  qwen: capability("qwen", ">=0.1.0", "flattened", "QWEN.md"),
9938
10018
  aicopilot: capability("aicopilot", ">=0.1.0", "flattened", "AICOPILOT.md"),
@@ -10155,12 +10235,22 @@ function compileInstructionGraph(input) {
10155
10235
  const selector = binding.providers?.find((entry) => entry.provider === input.context.provider || entry.provider === "global");
10156
10236
  if (binding.providers?.length && !selector)
10157
10237
  continue;
10238
+ const output = config.outputs.find((entry) => entry.agent === input.context.provider);
10239
+ if (!binding.providers?.length && config.agent !== "global" && config.agent !== input.context.provider && !output) {
10240
+ diagnostics.push({ severity: "info", code: "SOURCE_PROVIDER_NOT_SELECTED", config_id: configId, message: `${config.slug} targets ${config.agent}, not ${input.context.provider}.` });
10241
+ continue;
10242
+ }
10158
10243
  if (selector?.version_range && !providerVersionSatisfies(input.context.provider_version, selector.version_range)) {
10159
10244
  diagnostics.push({ severity: binding.required ? "error" : "warning", code: "PROVIDER_SELECTOR_VERSION_MISMATCH", config_id: configId, message: `${config.slug} requires ${input.context.provider} ${selector.version_range}; current version is ${input.context.provider_version}.` });
10160
10245
  continue;
10161
10246
  }
10162
10247
  if (!activationMatches(binding.activation, config, input.context))
10163
10248
  continue;
10249
+ const rejection = instructionSourceRejection(config);
10250
+ if (rejection) {
10251
+ diagnostics.push({ severity: !binding.required && binding.fallback === "omit" ? "warning" : "error", code: "SOURCE_NOT_INSTRUCTION", config_id: configId, message: `${config.slug}: ${rejection}.` });
10252
+ continue;
10253
+ }
10164
10254
  if (capability2.activation_modes.includes(binding.activation.mode)) {
10165
10255
  selected.add(configId);
10166
10256
  effective.set(configId, binding.activation);
@@ -10235,7 +10325,9 @@ function compileInstructionGraph(input) {
10235
10325
  assertExactOnce(units, artifacts);
10236
10326
  const sources = units.map((unit, index) => {
10237
10327
  const config = configs.get(unit.config_id);
10238
- return sourceForUnit(config, unit, index);
10328
+ const output = config.outputs.find((entry) => entry.agent === input.context.provider);
10329
+ const content = output ? applyTransform(config, output, { configs: [config] }) : config.content;
10330
+ return sourceForUnit({ ...config, content }, unit, index);
10239
10331
  });
10240
10332
  const planWithoutHash = {
10241
10333
  schema: INSTRUCTION_GRAPH_PLAN_SCHEMA,
@@ -11722,6 +11814,19 @@ function parseBoundedOrLegacyPage(value, legacyItems, options, label) {
11722
11814
  const page = boundedReadPage(legacyItems.slice(normalized.cursor, normalized.cursor + normalized.limit), legacyItems.length, normalized);
11723
11815
  return { ...page, source_bounded: false };
11724
11816
  }
11817
+ function projectBoundedPage(page, project) {
11818
+ return {
11819
+ items: page.items.map(project),
11820
+ total: page.total,
11821
+ limit: page.limit,
11822
+ cursor: page.cursor,
11823
+ next_cursor: page.next_cursor,
11824
+ has_more: page.has_more,
11825
+ complete: page.complete,
11826
+ truncated: page.truncated,
11827
+ source_bounded: page.source_bounded
11828
+ };
11829
+ }
11725
11830
 
11726
11831
  class CollectionChangedWhilePagingError extends Error {
11727
11832
  constructor(label, detail) {
@@ -11806,7 +11911,7 @@ function formatCliError(err, env = process.env) {
11806
11911
  var localStoreModulePromise = null;
11807
11912
  function localStoreModule() {
11808
11913
  if (!localStoreModulePromise)
11809
- localStoreModulePromise = import("./local-zxa5dpf4.js");
11914
+ localStoreModulePromise = import("./local-hc67bynj.js");
11810
11915
  return localStoreModulePromise;
11811
11916
  }
11812
11917
 
@@ -11820,6 +11925,15 @@ class LocalConfigStore {
11820
11925
  async listConfigs(filter) {
11821
11926
  return (await localStoreModule()).listConfigs(filter, this.db);
11822
11927
  }
11928
+ async listConfigsPage(filter = {}, options = {}) {
11929
+ return (await localStoreModule()).listConfigsPage(filter, options, this.db);
11930
+ }
11931
+ async listConfigIdentitiesPage(filter = {}, options = {}) {
11932
+ return (await localStoreModule()).listConfigIdentitiesPage(filter, options, this.db);
11933
+ }
11934
+ async listConfigSummariesPage(filter = {}, options = {}) {
11935
+ return (await localStoreModule()).listConfigSummariesPage(filter, options, this.db);
11936
+ }
11823
11937
  async getConfig(idOrSlug) {
11824
11938
  return (await localStoreModule()).getConfig(idOrSlug, this.db);
11825
11939
  }
@@ -11923,6 +12037,43 @@ class LocalConfigStore {
11923
12037
  (await localStoreModule()).resetLocalDatabase();
11924
12038
  }
11925
12039
  }
12040
+ function toConfigIdentity(value) {
12041
+ const record = value && typeof value === "object" ? value : {};
12042
+ return {
12043
+ id: String(record.id ?? ""),
12044
+ name: String(record.name ?? ""),
12045
+ slug: String(record.slug ?? ""),
12046
+ kind: String(record.kind ?? ""),
12047
+ category: String(record.category ?? ""),
12048
+ agent: String(record.agent ?? ""),
12049
+ format: String(record.format ?? ""),
12050
+ is_template: Boolean(record.is_template),
12051
+ version: Number(record.version ?? 0),
12052
+ created_at: String(record.created_at ?? ""),
12053
+ updated_at: String(record.updated_at ?? ""),
12054
+ synced_at: record.synced_at == null ? null : String(record.synced_at)
12055
+ };
12056
+ }
12057
+ function toConfigSummary(value) {
12058
+ const record = value && typeof value === "object" ? value : {};
12059
+ const outputs = Array.isArray(record.outputs) ? record.outputs : [];
12060
+ return {
12061
+ id: String(record.id ?? ""),
12062
+ slug: String(record.slug ?? ""),
12063
+ name: String(record.name ?? ""),
12064
+ category: String(record.category ?? ""),
12065
+ agent: String(record.agent ?? ""),
12066
+ kind: String(record.kind ?? ""),
12067
+ format: String(record.format ?? ""),
12068
+ target_path: record.target_path == null ? null : String(record.target_path),
12069
+ output_count: Number(record.output_count ?? outputs.length),
12070
+ version: Number(record.version ?? 0),
12071
+ is_template: Boolean(record.is_template),
12072
+ ...record.updated_at !== undefined ? { updated_at: String(record.updated_at) } : {},
12073
+ ...record.description !== undefined ? { description: record.description == null ? null : String(record.description) } : {},
12074
+ ...Array.isArray(record.tags) ? { tags: record.tags.map(String) } : {}
12075
+ };
12076
+ }
11926
12077
 
11927
12078
  class CloudConfigStore {
11928
12079
  mode = "api";
@@ -11944,7 +12095,7 @@ class CloudConfigStore {
11944
12095
  throw err;
11945
12096
  }
11946
12097
  }
11947
- async listConfigsPageRemote(filter, options) {
12098
+ async listConfigsPage(filter = {}, options = {}) {
11948
12099
  const normalized = normalizeBoundedReadOptions(options);
11949
12100
  const params = new URLSearchParams;
11950
12101
  if (filter.category)
@@ -11955,13 +12106,67 @@ class CloudConfigStore {
11955
12106
  params.set("kind", filter.kind);
11956
12107
  if (filter.search)
11957
12108
  params.set("search", filter.search);
12109
+ for (const tag of filter.tags ?? [])
12110
+ params.append("tag", tag);
11958
12111
  params.set("limit", String(normalized.limit));
11959
12112
  params.set("cursor", String(normalized.cursor));
11960
12113
  const { data } = await this.request("GET", `/configs?${params.toString()}`);
11961
12114
  return parseBoundedOrLegacyPage(data, data?.configs, normalized, "config list");
11962
12115
  }
12116
+ async listConfigIdentitiesPage(filter = {}, options = {}) {
12117
+ const normalized = normalizeBoundedReadOptions(options);
12118
+ const params = new URLSearchParams;
12119
+ if (filter.category)
12120
+ params.set("category", filter.category);
12121
+ if (filter.agent)
12122
+ params.set("agent", filter.agent);
12123
+ if (filter.kind)
12124
+ params.set("kind", filter.kind);
12125
+ if (filter.search)
12126
+ params.set("search", filter.search);
12127
+ for (const tag of filter.tags ?? [])
12128
+ params.append("tag", tag);
12129
+ params.set("view", "identity");
12130
+ params.set("limit", String(normalized.limit));
12131
+ params.set("cursor", String(normalized.cursor));
12132
+ const { data } = await this.request("GET", `/configs?${params.toString()}`);
12133
+ const page = parseBoundedOrLegacyPage(data, data?.configs, normalized, "config identity list");
12134
+ if (page.items.some((item) => {
12135
+ const record = item && typeof item === "object" ? item : {};
12136
+ return ["content", "target_path", "outputs", "description", "tags"].some((field) => Object.prototype.hasOwnProperty.call(record, field));
12137
+ })) {
12138
+ throw new Error("Instructions /v1 config identity projection is unavailable; deploy the identity endpoint before using compact lists");
12139
+ }
12140
+ return projectBoundedPage(page, toConfigIdentity);
12141
+ }
12142
+ async listConfigSummariesPage(filter = {}, options = {}) {
12143
+ const normalized = normalizeBoundedReadOptions(options);
12144
+ const params = new URLSearchParams;
12145
+ if (filter.category)
12146
+ params.set("category", filter.category);
12147
+ if (filter.agent)
12148
+ params.set("agent", filter.agent);
12149
+ if (filter.kind)
12150
+ params.set("kind", filter.kind);
12151
+ if (filter.search)
12152
+ params.set("search", filter.search);
12153
+ for (const tag of filter.tags ?? [])
12154
+ params.append("tag", tag);
12155
+ params.set("view", "summary");
12156
+ params.set("limit", String(normalized.limit));
12157
+ params.set("cursor", String(normalized.cursor));
12158
+ const { data } = await this.request("GET", `/configs?${params.toString()}`);
12159
+ const page = parseBoundedOrLegacyPage(data, data?.configs, normalized, "config summary list");
12160
+ if (page.items.some((item) => {
12161
+ const record = item && typeof item === "object" ? item : {};
12162
+ return Object.prototype.hasOwnProperty.call(record, "content") || Object.prototype.hasOwnProperty.call(record, "outputs");
12163
+ })) {
12164
+ throw new Error("Instructions /v1 config summary projection is unavailable; deploy the summary endpoint before using summary lists");
12165
+ }
12166
+ return projectBoundedPage(page, toConfigSummary);
12167
+ }
11963
12168
  async listConfigs(filter = {}) {
11964
- const configs = await aggregateBoundedCollection("config list", (cursor) => this.listConfigsPageRemote(filter, { limit: 100, cursor }), (config) => config.id, { requireAscendingIdentity: true });
12169
+ const configs = await aggregateBoundedCollection("config list", (cursor) => this.listConfigsPage(filter, { limit: 100, cursor }), (config) => config.id, { requireAscendingIdentity: true });
11965
12170
  let filtered = configs;
11966
12171
  if (filter.tags && filter.tags.length > 0) {
11967
12172
  filtered = filtered.filter((config) => filter.tags.every((tag) => config.tags.includes(tag)));
@@ -11987,7 +12192,9 @@ class CloudConfigStore {
11987
12192
  return data.config;
11988
12193
  }
11989
12194
  async updateConfig(idOrSlug, input) {
11990
- const { data } = await this.request("PATCH", `/configs/${encodeURIComponent(idOrSlug)}`, input);
12195
+ validateExpectedConfigVersion(input.expected_version);
12196
+ const conditional = input.expected_version !== undefined;
12197
+ const { data } = await this.request(conditional ? "POST" : "PATCH", `/configs/${encodeURIComponent(idOrSlug)}${conditional ? "/conditional-update" : ""}`, input);
11991
12198
  return data.config;
11992
12199
  }
11993
12200
  async deleteConfig(idOrSlug) {
@@ -12027,7 +12234,7 @@ class CloudConfigStore {
12027
12234
  return data?.pruned ?? 0;
12028
12235
  }
12029
12236
  async listProfiles() {
12030
- return aggregateBoundedCollection("profile list", (cursor) => this.listProfilesPage({ limit: 100, cursor }), (profile) => profile.id, { requireAscendingIdentity: true });
12237
+ return aggregateBoundedCollection("profile list", (cursor) => this.listProfilesPage({ limit: 100, cursor }), (profile) => profile.id);
12031
12238
  }
12032
12239
  async listProfilesPage(options = {}) {
12033
12240
  const normalized = normalizeBoundedReadOptions(options);
@@ -12064,7 +12271,7 @@ class CloudConfigStore {
12064
12271
  throw new ProfileNotFoundError(idOrSlug);
12065
12272
  return parseBoundedOrLegacyPage(data.configs, data.profile.configs, normalized, "profile membership");
12066
12273
  }
12067
- async getProfileConfigBindings(idOrSlug) {
12274
+ async getProfileConfigBindings(idOrSlug, options = {}) {
12068
12275
  let routeMissing = false;
12069
12276
  const bindings = await aggregateBoundedCollection("profile config bindings", async (cursor) => {
12070
12277
  const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
@@ -12077,6 +12284,8 @@ class CloudConfigStore {
12077
12284
  }, (binding) => `${binding.profile_id}\x00${binding.config_id}`);
12078
12285
  if (!routeMissing)
12079
12286
  return bindings;
12287
+ if (options.requireExplicit)
12288
+ throw new Error("HOSTED_BINDINGS_REQUIRED: profile config binding route is unavailable; refusing legacy activation fallback.");
12080
12289
  const profile = await this.getProfile(idOrSlug);
12081
12290
  const configs = await this.getProfileConfigs(idOrSlug);
12082
12291
  return configs.map((config, sort_order) => ({
@@ -12141,7 +12350,7 @@ class CloudConfigStore {
12141
12350
  async removeConfigFromProfile(profileIdOrSlug, configId) {
12142
12351
  await this.request("DELETE", `/profiles/${encodeURIComponent(profileIdOrSlug)}/configs/${encodeURIComponent(configId)}`, undefined, { allow404: true });
12143
12352
  }
12144
- async getProfileAssetBindings(profileIdOrSlug) {
12353
+ async getProfileAssetBindings(profileIdOrSlug, options = {}) {
12145
12354
  let routeMissing = false;
12146
12355
  const assets = await aggregateBoundedCollection("profile asset bindings", async (cursor) => {
12147
12356
  const normalized = normalizeBoundedReadOptions({ limit: 100, cursor });
@@ -12154,6 +12363,8 @@ class CloudConfigStore {
12154
12363
  }, (asset) => `${asset.profile_id}\x00${asset.binding.assetKey}`);
12155
12364
  if (!routeMissing)
12156
12365
  return assets;
12366
+ if (options.requireExplicit)
12367
+ throw new Error("HOSTED_ASSETS_REQUIRED: profile asset binding route is unavailable; refusing an empty asset fallback.");
12157
12368
  await this.getProfile(profileIdOrSlug);
12158
12369
  return [];
12159
12370
  }
@@ -12467,9 +12678,13 @@ async function ensureGlobalAgentRulesStandardConfig(store = resolveConfigStore()
12467
12678
  let existing;
12468
12679
  try {
12469
12680
  existing = await store.getConfig(GLOBAL_AGENT_RULES_STANDARD_SLUG);
12470
- } catch {
12681
+ } catch (error) {
12682
+ if (!(error instanceof ConfigNotFoundError))
12683
+ throw error;
12471
12684
  return await store.createConfig(standardConfigInput(resolveAgentOperatingRulesPayload(null)));
12472
12685
  }
12686
+ if (isRetiredInstructionSource(existing))
12687
+ return existing;
12473
12688
  const payload = resolveAgentOperatingRulesPayload(existing.content);
12474
12689
  const input = standardConfigInput(payload);
12475
12690
  if (existing.content !== input.content || existing.description !== input.description || existing.category !== input.category || existing.agent !== input.agent || existing.format !== input.format || existing.kind !== input.kind || JSON.stringify(existing.tags) !== JSON.stringify(input.tags)) {
@@ -12575,4 +12790,4 @@ function renderMachineAwareContentPreview(content, variables) {
12575
12790
  return isTemplate(content) ? renderTemplatePreview(content, variables) : { content, unresolved: [] };
12576
12791
  }
12577
12792
 
12578
- export { DEFAULT_LIST_LIMIT, parseLimit, paginate, truncateText, truncateMiddle, normalizeBoundedReadOptions, boundedReadPage, ensureGlobalAgentRulesStandardConfig, ensureCodewithSharedTodosStorageStandardConfig, redactFormatForTarget, redactContent, scanSecrets, isSecretVarName, SESSION_RENDER_MANAGED_MARKER, SESSION_RENDER_SCHEMA, SESSION_RENDER_MANIFEST_RELATIVE_PATH, SESSION_INSTRUCTION_LAYERS, getSessionRenderSnapshotDir, sessionRenderSnapshotWorkspaceRoot, PROJECT_CONTEXT_MAX_INPUT_BYTES, SESSION_MANAGED_INPUT_MAX_BYTES, ProjectContextError, parseProjectContextBundle, planProjectContext, observeProjectContextSessionGuard, withProjectContextSessionGuard, applyProjectContext, writeProjectContextCoordinatedFile, removeProjectContextCoordinatedFile, isRetiredOrUnsupportedConfigAgent, retiredOrUnsupportedAgentReason, applyTransform, normalizeProfileAssetBinding, observeCursorGlobalAuthorityAtPath, isCursorGlobalAuthorityPath, stampCursorGlobalAuthorityMarker, detectCursorAuthorityConflicts, detectClaudeAuthorityConflicts, ANTIGRAVITY_RULE_FILE_CHAR_LIMIT, SESSION_RENDERER_OWNER_ID, SESSION_RENDER_TOOLS, SESSION_RENDER_OWNED_CONFIG_TARGETS, SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS, normalizeSessionInstructionSourceId, resolveSessionPath, planSessionRender, sourceFromFilePath, sourceFromConfig, sourcesFromIdentityExport, legacyProfileConfigBinding, normalizeProfileConfigBinding, planProfileSessionRender, normalizeOsFamily, detectMachineContext, machineContextToVariables, resolveProfileVariables, templateizeMachineContent, renderMachineAwareContentPreview, formatCliError, CloudConfigStore, resolveConfigStore };
12793
+ export { DEFAULT_LIST_LIMIT, parseLimit, paginate, truncateText, truncateMiddle, normalizeBoundedReadOptions, boundedReadPage, isRetiredInstructionSource, instructionSourceRejection, assertInstructionSource, ensureGlobalAgentRulesStandardConfig, ensureCodewithSharedTodosStorageStandardConfig, exports_external, redactFormatForTarget, redactContent, scanSecrets, isSecretVarName, CODEWITH_NATIVE_IMPORTS_ENV, SESSION_RENDER_MANAGED_MARKER, SESSION_RENDER_SCHEMA, SESSION_RENDER_MANIFEST_RELATIVE_PATH, SESSION_INSTRUCTION_LAYERS, getSessionRenderSnapshotDir, sessionRenderSnapshotWorkspaceRoot, PROJECT_CONTEXT_MAX_INPUT_BYTES, SESSION_MANAGED_INPUT_MAX_BYTES, ProjectContextError, parseProjectContextBundle, planProjectContext, observeProjectContextSessionGuard, withProjectContextSessionGuard, applyProjectContext, writeProjectContextCoordinatedFile, removeProjectContextCoordinatedFile, isRetiredOrUnsupportedConfigAgent, retiredOrUnsupportedAgentReason, applyTransform, normalizeProfileAssetBinding, observeCursorGlobalAuthorityAtPath, isCursorGlobalAuthorityPath, stampCursorGlobalAuthorityMarker, detectCursorAuthorityConflicts, detectClaudeAuthorityConflicts, ANTIGRAVITY_RULE_FILE_CHAR_LIMIT, SESSION_RENDERER_OWNER_ID, SESSION_RENDER_TOOLS, SESSION_RENDER_OWNED_CONFIG_TARGETS, SESSION_RENDER_EXCLUSIVE_MANAGED_PATHS, normalizeSessionInstructionSourceId, resolveSessionPath, planSessionRender, sourceFromFilePath, sourceFromConfig, sourcesFromIdentityExport, legacyProfileConfigBinding, normalizeProfileConfigBinding, planProfileSessionRender, normalizeOsFamily, detectMachineContext, machineContextToVariables, resolveProfileVariables, templateizeMachineContent, renderMachineAwareContentPreview, formatCliError, CloudConfigStore, resolveConfigStore };