@granular-software/sdk 0.4.25 → 0.4.27

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/cli/index.js CHANGED
@@ -13114,10 +13114,15 @@ external_exports.union([
13114
13114
  scalarType: external_exports.string().optional()
13115
13115
  }).strict()
13116
13116
  ]);
13117
+ external_exports.union([
13118
+ external_exports.boolean(),
13119
+ external_exports.object({
13120
+ enabled: external_exports.boolean().optional(),
13121
+ phonetic: external_exports.boolean().optional()
13122
+ }).strict()
13123
+ ]);
13117
13124
  external_exports.object({
13118
- operator: external_exports.enum(
13119
- [...VALIDATION_RULE_OPERATORS]
13120
- ),
13125
+ operator: external_exports.enum([...VALIDATION_RULE_OPERATORS]),
13121
13126
  stringValue: external_exports.string().optional(),
13122
13127
  numberValue: external_exports.number().optional(),
13123
13128
  booleanValue: external_exports.boolean().optional(),
@@ -13210,12 +13215,18 @@ function collectMetamodelSummarySelections(packages) {
13210
13215
  const propertyFields = [];
13211
13216
  const methodFields = [];
13212
13217
  for (const metamodelPackage of packages) {
13213
- pushUnique(classFields, metamodelPackage.summary.selections?.classFields || []);
13218
+ pushUnique(
13219
+ classFields,
13220
+ metamodelPackage.summary.selections?.classFields || []
13221
+ );
13214
13222
  pushUnique(
13215
13223
  propertyFields,
13216
13224
  metamodelPackage.summary.selections?.propertyFields || []
13217
13225
  );
13218
- pushUnique(methodFields, metamodelPackage.summary.selections?.methodFields || []);
13226
+ pushUnique(
13227
+ methodFields,
13228
+ metamodelPackage.summary.selections?.methodFields || []
13229
+ );
13219
13230
  }
13220
13231
  return {
13221
13232
  classFields: unique(classFields),
@@ -13303,7 +13314,11 @@ function createMetamodelRegistry(metamodelPackages) {
13303
13314
  return collectMetamodelSummarySelections(packages);
13304
13315
  },
13305
13316
  applyClassSummaryReaders(rawClass, classSummary) {
13306
- return applyMetamodelSummaryReadersToClass(packages, rawClass, classSummary);
13317
+ return applyMetamodelSummaryReadersToClass(
13318
+ packages,
13319
+ rawClass,
13320
+ classSummary
13321
+ );
13307
13322
  },
13308
13323
  applyPropertySummaryReaders(rawProperty, propertySummary) {
13309
13324
  return applyMetamodelSummaryReadersToProperty(
@@ -13313,7 +13328,11 @@ function createMetamodelRegistry(metamodelPackages) {
13313
13328
  );
13314
13329
  },
13315
13330
  applyMethodSummaryReaders(rawMethod, methodSummary) {
13316
- return applyMetamodelSummaryReadersToMethod(packages, rawMethod, methodSummary);
13331
+ return applyMetamodelSummaryReadersToMethod(
13332
+ packages,
13333
+ rawMethod,
13334
+ methodSummary
13335
+ );
13317
13336
  },
13318
13337
  applyClassIR(classIR, classSummary) {
13319
13338
  return applyMetamodelClassIR(packages, classIR, classSummary);
@@ -13361,6 +13380,10 @@ function mergeClassSummaryPatch(target, patch) {
13361
13380
  }
13362
13381
  function mergePropertySummaryPatch(target, patch) {
13363
13382
  pushUnique(target.notes, patch.notes || []);
13383
+ if (patch.searchable !== void 0) target.searchable = patch.searchable;
13384
+ if (patch.searchablePhonetic !== void 0) {
13385
+ target.searchablePhonetic = patch.searchablePhonetic;
13386
+ }
13364
13387
  if (patch.required !== void 0) target.required = patch.required;
13365
13388
  if (patch.enumRule !== void 0) target.enumRule = patch.enumRule;
13366
13389
  if (patch.filterBy !== void 0) target.filterBy = patch.filterBy;
@@ -13372,9 +13395,11 @@ function mergeMethodSummaryPatch(target, patch) {
13372
13395
  if (patch.effectKey !== void 0) target.effectKey = patch.effectKey;
13373
13396
  if (patch.description !== void 0) target.description = patch.description;
13374
13397
  if (patch.inputSchema !== void 0) target.inputSchema = patch.inputSchema;
13375
- if (patch.outputSchema !== void 0) target.outputSchema = patch.outputSchema;
13398
+ if (patch.outputSchema !== void 0)
13399
+ target.outputSchema = patch.outputSchema;
13376
13400
  if (patch.metamodels !== void 0) target.metamodels = patch.metamodels;
13377
- if (patch.effectBehaviors !== void 0) target.effectBehaviors = patch.effectBehaviors;
13401
+ if (patch.effectBehaviors !== void 0)
13402
+ target.effectBehaviors = patch.effectBehaviors;
13378
13403
  if (patch.static !== void 0) target.static = patch.static;
13379
13404
  }
13380
13405
  function toPascalCase2(value) {
@@ -13777,12 +13802,20 @@ function defaultFilterOperators(scalarType) {
13777
13802
  switch ((scalarType || "").toLowerCase()) {
13778
13803
  case "number":
13779
13804
  case "date":
13780
- return ["equal_to", "greater_than", "less_than", "not_null"];
13805
+ return [
13806
+ "equal_to",
13807
+ "greater_than",
13808
+ "greater_than_or_equal_to",
13809
+ "less_than",
13810
+ "less_than_or_equal_to",
13811
+ "not_null"
13812
+ ];
13781
13813
  case "boolean":
13782
- return ["equal_to", "not_null"];
13814
+ return ["equal_to", "true", "false", "not_null"];
13783
13815
  default:
13784
13816
  return [
13785
13817
  "equal_to",
13818
+ "in",
13786
13819
  "contains",
13787
13820
  "not_contains",
13788
13821
  "starts_with",
@@ -13791,16 +13824,26 @@ function defaultFilterOperators(scalarType) {
13791
13824
  ];
13792
13825
  }
13793
13826
  }
13827
+ function supportsDefaultFilterBy(scalarType) {
13828
+ return ["string", "number", "boolean", "date"].includes(
13829
+ String(scalarType || "").toLowerCase()
13830
+ );
13831
+ }
13794
13832
  function normalizeFilterByInput(filterBy, scalarType) {
13795
- if (!filterBy) return null;
13833
+ if (filterBy === false) return null;
13834
+ if (filterBy === void 0) {
13835
+ if (!supportsDefaultFilterBy(scalarType)) return null;
13836
+ return { operators: defaultFilterOperators(scalarType), scalarType };
13837
+ }
13796
13838
  if (filterBy === true) {
13797
- return { operators: defaultFilterOperators(scalarType) };
13839
+ return { operators: defaultFilterOperators(scalarType), scalarType };
13798
13840
  }
13799
13841
  if (Array.isArray(filterBy)) {
13800
- return { operators: filterBy };
13842
+ return { operators: filterBy, scalarType };
13801
13843
  }
13802
13844
  return {
13803
- operators: filterBy.operators
13845
+ operators: filterBy.operators,
13846
+ scalarType: filterBy.scalarType || scalarType
13804
13847
  };
13805
13848
  }
13806
13849
  function buildFilterByFieldMutations(fieldPath, filterBy, scalarType) {
@@ -13811,7 +13854,7 @@ function buildFilterByFieldMutations(fieldPath, filterBy, scalarType) {
13811
13854
  label: `set filterBy on ${fieldPath}`,
13812
13855
  query: `mutation { at(path: ${JSON.stringify(fieldPath)}) { set_filter_by(operators: ${JSON.stringify(
13813
13856
  normalized.operators
13814
- )}) { operators } } }`
13857
+ )}${normalized.scalarType ? `, scalar_type: ${JSON.stringify(normalized.scalarType)}` : ""}) { operators } } }`
13815
13858
  }
13816
13859
  ];
13817
13860
  }
@@ -13821,7 +13864,7 @@ var filterByMetamodelPackage = defineMetamodelPackage({
13821
13864
  fieldRows: [
13822
13865
  {
13823
13866
  key: "filterBy",
13824
- description: "Exposes filter operators for generated query surfaces. Accepts `true`, an operator array, or `{ operators, scalarType }`."
13867
+ description: "Exposes filter operators for generated query surfaces. Scalar fields are filterable by default; set `filterBy: false` to opt out, or override with `true`, an operator array, or `{ operators, scalarType }`."
13825
13868
  }
13826
13869
  ]
13827
13870
  },
@@ -14085,6 +14128,123 @@ var requiredMetamodelPackage = defineMetamodelPackage({
14085
14128
  }
14086
14129
  });
14087
14130
 
14131
+ // ../metamodel-searchable/src/index.ts
14132
+ function supportsDefaultSearchable(scalarType) {
14133
+ return String(scalarType || "").toLowerCase() === "string";
14134
+ }
14135
+ function normalizeSearchableInput(searchable, scalarType) {
14136
+ if (!supportsDefaultSearchable(scalarType)) return null;
14137
+ if (typeof searchable === "boolean" || searchable === void 0) {
14138
+ return {
14139
+ enabled: searchable !== false,
14140
+ phonetic: false
14141
+ };
14142
+ }
14143
+ const enabled = searchable.enabled !== false;
14144
+ return {
14145
+ enabled,
14146
+ phonetic: enabled && searchable.phonetic === true
14147
+ };
14148
+ }
14149
+ function buildSearchableFieldMutations(fieldPath, searchable, scalarType) {
14150
+ const normalized = normalizeSearchableInput(searchable, scalarType);
14151
+ if (normalized === null) return [];
14152
+ return [
14153
+ {
14154
+ label: `set searchable on ${fieldPath}`,
14155
+ query: `mutation { at(path: ${JSON.stringify(fieldPath)}) { set_searchable(enabled: ${normalized.enabled}, phonetic: ${normalized.phonetic}) { enabled phonetic } } }`
14156
+ }
14157
+ ];
14158
+ }
14159
+ var searchableMetamodelPackage = defineMetamodelPackage({
14160
+ id: "searchable",
14161
+ docs: {
14162
+ fieldRows: [
14163
+ {
14164
+ key: "searchable",
14165
+ description: "Controls full-text search exposure for string fields. String fields are searchable by default; set `searchable: false` to opt out, or use `searchable: { phonetic: true }` to keep the field searchable while enabling FalkorDB phonetic matching for class-wide search."
14166
+ }
14167
+ ]
14168
+ },
14169
+ graphql: {
14170
+ typeDefs: [
14171
+ `
14172
+ type SearchableMetamodel {
14173
+ model: Model!
14174
+ enabled: Boolean!
14175
+ phonetic: Boolean!
14176
+ }
14177
+
14178
+ extend type Model {
14179
+ searchable: SearchableMetamodel
14180
+ }
14181
+
14182
+ extend type ModelMutation {
14183
+ set_searchable(enabled: Boolean!, phonetic: Boolean): SearchableMetamodel
14184
+ }
14185
+ `
14186
+ ],
14187
+ createResolvers({ run }) {
14188
+ return {
14189
+ SearchableMetamodel: {
14190
+ model: (value) => value.model,
14191
+ enabled: (value) => value.enabled !== false,
14192
+ phonetic: (value) => value.phonetic === true
14193
+ },
14194
+ Model: {
14195
+ searchable: async (ant) => await run(ant.searchable())
14196
+ },
14197
+ ModelMutation: {
14198
+ set_searchable: async (ant, { enabled, phonetic }) => {
14199
+ return {
14200
+ model: await run(ant.set_searchable(enabled, phonetic === true)),
14201
+ enabled,
14202
+ phonetic: phonetic === true
14203
+ };
14204
+ }
14205
+ }
14206
+ };
14207
+ }
14208
+ },
14209
+ manifest: {
14210
+ buildFieldMutations(fieldPath, spec) {
14211
+ return buildSearchableFieldMutations(
14212
+ fieldPath,
14213
+ spec.searchable,
14214
+ spec.type
14215
+ );
14216
+ }
14217
+ },
14218
+ summary: {
14219
+ selections: {
14220
+ propertyFields: [`searchable { enabled phonetic }`]
14221
+ },
14222
+ readPropertySummary(rawProperty) {
14223
+ if (typeof rawProperty.searchable?.enabled !== "boolean") {
14224
+ return {};
14225
+ }
14226
+ return {
14227
+ searchable: rawProperty.searchable.enabled,
14228
+ searchablePhonetic: rawProperty.searchable.phonetic === true
14229
+ };
14230
+ }
14231
+ },
14232
+ domain: {
14233
+ applyToPropertyIR(propertyIR, propertySummary) {
14234
+ if (String(propertySummary.type || "").toLowerCase() !== "string" || propertySummary.searchable === false) {
14235
+ return propertyIR;
14236
+ }
14237
+ return {
14238
+ ...propertyIR,
14239
+ docs: [
14240
+ ...propertyIR.docs,
14241
+ propertySummary.searchablePhonetic ? "Searchable via `search` using FalkorDB full-text query syntax with phonetic matching enabled." : "Searchable via `search` using FalkorDB full-text query syntax."
14242
+ ]
14243
+ };
14244
+ }
14245
+ }
14246
+ });
14247
+
14088
14248
  // ../metamodel-state-machine/src/index.ts
14089
14249
  function normalizeStateMachines(values) {
14090
14250
  return (values || []).map((machine) => {
@@ -14665,6 +14825,7 @@ var DEFAULT_METAMODEL_PACKAGES = [
14665
14825
  requiredMetamodelPackage,
14666
14826
  enumMetamodelPackage,
14667
14827
  filterByMetamodelPackage,
14828
+ searchableMetamodelPackage,
14668
14829
  validationRuleMetamodelPackage,
14669
14830
  stateMachineMetamodelPackage,
14670
14831
  effectBehaviorsMetamodelPackage
@@ -14838,6 +14999,7 @@ Scalar fields can carry lightweight metamodels directly in their field spec:
14838
14999
  "type": "string",
14839
15000
  "required": true,
14840
15001
  "note": "Must use the canonical prefix",
15002
+ "searchable": { "phonetic": true },
14841
15003
  "filterBy": true,
14842
15004
  "validate": [
14843
15005
  { "operator": "regex", "stringValue": "^TKT-[A-Z0-9-]+$" }
@@ -14858,11 +15020,24 @@ Scalar fields can carry lightweight metamodels directly in their field spec:
14858
15020
  { "operator": "gt", "numberValue": 0 },
14859
15021
  { "operator": "lt", "numberValue": 100 }
14860
15022
  ]
15023
+ },
15024
+ "internal_code": {
15025
+ "type": "string",
15026
+ "description": "Opaque implementation detail",
15027
+ "searchable": false,
15028
+ "filterBy": false
14861
15029
  }
14862
15030
  }
14863
15031
  }
14864
15032
  \`\`\`
14865
15033
 
15034
+ Scalar fields are filterable by default. Set \`"filterBy": false\` only when a field should not appear in generated filter surfaces.
15035
+ String fields are searchable by default. Set \`"searchable": false\` only when a field should be excluded from generated full-text search surfaces and heavy full-text indexes.
15036
+ \`search\` is broad class-wide retrieval across all searchable string fields of a class. It is not a field-scoped operator. Use \`filter\` for exact field-specific constraints, and combine \`search\` + \`filter\` when you need both flexible text matching and exact structure.
15037
+ Runtime note: class-wide \`search\` is implemented as one denormalized full-text search document per class instance, built from that instance's searchable string fields. Exact field constraints still belong in \`filter\`.
15038
+ Optional indexing note: \`"searchable": { "phonetic": true }\` keeps the field searchable and enables FalkorDB phonetic matching for the class-wide search index. Query syntax does not change; agents should keep using normal \`search\` strings.
15039
+ Without an explicit sort, indexed \`search\` results are returned in FalkorDB relevance order. If you pass a sort, that explicit sort takes precedence.
15040
+
14866
15041
  Supported field metamodel keys:
14867
15042
 
14868
15043
  ${fieldMetamodelTable}
@@ -18203,6 +18378,22 @@ var Session = class {
18203
18378
  }
18204
18379
  };
18205
18380
  }
18381
+ stringifyConversationValue(value) {
18382
+ if (typeof value === "string") {
18383
+ return value;
18384
+ }
18385
+ if (typeof value === "boolean") {
18386
+ return value ? "Confirmed" : "Canceled";
18387
+ }
18388
+ if (value === void 0) {
18389
+ return "";
18390
+ }
18391
+ try {
18392
+ return JSON.stringify(value, null, 2);
18393
+ } catch {
18394
+ return String(value);
18395
+ }
18396
+ }
18206
18397
  // --- Public API ---
18207
18398
  get document() {
18208
18399
  return this.client.doc;
@@ -18353,6 +18544,20 @@ var Session = class {
18353
18544
  answer: resolvedAnswer,
18354
18545
  value: resolvedAnswer
18355
18546
  });
18547
+ try {
18548
+ const content = this.stringifyConversationValue(resolvedAnswer);
18549
+ if (content.trim()) {
18550
+ await this.appendConversationMessage({
18551
+ role: "user",
18552
+ content,
18553
+ promptId
18554
+ });
18555
+ }
18556
+ } catch {
18557
+ }
18558
+ }
18559
+ async appendConversationMessage(input) {
18560
+ return this.client.call("conversation.append", input);
18356
18561
  }
18357
18562
  /**
18358
18563
  * Get the current list of available effects.
@@ -18492,9 +18697,24 @@ var Session = class {
18492
18697
  * Get domain documentation for LLMs. Returns types (preferred) or fallback.
18493
18698
  */
18494
18699
  async getDomainDocumentation() {
18495
- const types = await this.getDomainTypes();
18496
- if (types && (types.includes("export declare class") || types.includes("export async function"))) {
18497
- return types;
18700
+ const [types, docs] = await Promise.all([
18701
+ this.getDomainTypes(),
18702
+ this.getDomainDocs()
18703
+ ]);
18704
+ const normalizedTypes = types.trim();
18705
+ const normalizedDocs = docs.trim();
18706
+ if (normalizedTypes && (normalizedTypes.includes("export declare class") || normalizedTypes.includes("export async function"))) {
18707
+ if (!normalizedDocs) {
18708
+ return normalizedTypes;
18709
+ }
18710
+ return [
18711
+ normalizedTypes,
18712
+ "Generated usage notes from ./sandbox-tools docs:",
18713
+ normalizedDocs
18714
+ ].join("\n\n");
18715
+ }
18716
+ if (normalizedDocs) {
18717
+ return normalizedDocs;
18498
18718
  }
18499
18719
  const summary = await this.getDomain();
18500
18720
  return this.generateFallbackDocs(summary);