@jskit-ai/assistant-core 0.1.157 → 0.1.159

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jskit-ai/assistant-core",
3
- "version": "0.1.157",
3
+ "version": "0.1.159",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "test": "node --test"
@@ -11,16 +11,16 @@
11
11
  "./shared": "./src/shared/index.js"
12
12
  },
13
13
  "dependencies": {
14
- "@jskit-ai/resource-core": "0.1.123",
15
- "@jskit-ai/resource-crud-core": "0.1.123",
14
+ "@jskit-ai/resource-core": "0.1.125",
15
+ "@jskit-ai/resource-crud-core": "0.1.125",
16
16
  "dompurify": "^3.4.13",
17
17
  "json-rest-schema": "^1.0.17",
18
18
  "marked": "^17.0.4",
19
19
  "openai": "^6.22.0"
20
20
  },
21
21
  "peerDependencies": {
22
- "@jskit-ai/http-runtime": "0.1.179",
23
- "@jskit-ai/kernel": "0.1.181",
22
+ "@jskit-ai/http-runtime": "0.1.181",
23
+ "@jskit-ai/kernel": "0.1.183",
24
24
  "vue": "^3.5.13",
25
25
  "vuetify": "^4.0.0"
26
26
  },
@@ -33,7 +33,7 @@ const ACTION_SEARCH_PARAMETERS = Object.freeze({
33
33
  query: {
34
34
  type: "string",
35
35
  maxLength: 200,
36
- description: "Optional words or action-id fragments to match."
36
+ description: "Optional literal words or action-id fragments; every word must match. Use short resource or operation terms such as list. Omit query to browse all available actions."
37
37
  },
38
38
  cursor: {
39
39
  type: "string",
@@ -125,7 +125,7 @@ const ACTION_EXECUTE_OUTPUT_SCHEMA = Object.freeze({
125
125
  const DISCOVERY_TOOL_DESCRIPTORS = Object.freeze([
126
126
  Object.freeze({
127
127
  name: DISCOVERY_TOOL_NAMES.search,
128
- description: "Search the actions available to the current user and surface. Returns compact paged matches without schemas.",
128
+ description: "Discover application actions available to the current user and surface, including list, search, and query operations for multiple records. Search before claiming a capability is unavailable. If terminology does not match, use broader terms or omit query to browse. Returns compact paged matches without schemas; follow nextCursor when more discovery is needed.",
129
129
  parameters: ACTION_SEARCH_PARAMETERS,
130
130
  outputSchema: ACTION_SEARCH_OUTPUT_SCHEMA
131
131
  }),
@@ -410,6 +410,56 @@ test("large authorized catalogs use compact paged discovery, exact contracts, an
410
410
  assert.equal(executions[0].context.channel, "automation");
411
411
  });
412
412
 
413
+ test("operation search and unfiltered browsing discover collections despite different user terminology", async () => {
414
+ const catalog = createServiceToolCatalog(createActions([
415
+ action({ id: "library.books.list", extensions: { assistant: { description: "List books." } } }),
416
+ action({ id: "warehouse.assets.list", extensions: { assistant: { description: "List assets." } } }),
417
+ action({ id: "warehouse.assets.view" }),
418
+ action({ id: "private.assets.list", permission: { require: "all", permissions: ["private.read"] } })
419
+ ]), { maxDirectTools: 1 });
420
+ const context = { actor: { id: "7" }, surface: "admin" };
421
+ const toolSet = catalog.resolveToolSet(context);
422
+ const searchTool = catalog.toOpenAiToolSchema(toolSet.tools[0]);
423
+ assert.match(searchTool.function.description, /Search before claiming a capability is unavailable/u);
424
+ assert.match(searchTool.function.parameters.properties.query.description, /every word must match/u);
425
+ assert.match(searchTool.function.parameters.properties.query.description, /Omit query to browse/u);
426
+
427
+ const missedSearch = await catalog.executeToolCall({
428
+ toolName: "assistant_action_search",
429
+ argumentsText: JSON.stringify({ query: "vehicles" }),
430
+ context,
431
+ toolSet
432
+ });
433
+ assert.deepEqual(missedSearch, { ok: true, result: { items: [], nextCursor: null, total: 0 } });
434
+
435
+ const collectionSearch = await catalog.executeToolCall({
436
+ toolName: "assistant_action_search",
437
+ argumentsText: JSON.stringify({ query: "list" }),
438
+ context,
439
+ toolSet
440
+ });
441
+ assert.equal(collectionSearch.ok, true);
442
+ assert.deepEqual(collectionSearch.result.items.map((item) => item.actionId), [
443
+ "library.books.list", "warehouse.assets.list"
444
+ ]);
445
+
446
+ const browsedActions = [];
447
+ let cursor;
448
+ do {
449
+ const page = await catalog.executeToolCall({
450
+ toolName: "assistant_action_search",
451
+ argumentsText: JSON.stringify({ limit: 1, ...(cursor ? { cursor } : {}) }),
452
+ context,
453
+ toolSet
454
+ });
455
+ assert.equal(page.ok, true);
456
+ assert.equal(page.result.total, 3);
457
+ browsedActions.push(...page.result.items.map((item) => item.actionId));
458
+ cursor = page.result.nextCursor;
459
+ } while (cursor);
460
+ assert.deepEqual(browsedActions, ["library.books.list", "warehouse.assets.list", "warehouse.assets.view"]);
461
+ });
462
+
413
463
  test("discovery mode bounds authorized always-available tools", () => {
414
464
  const definitions = Array.from({ length: 10 }, (_, index) => action({
415
465
  id: `demo.clock-${String(index + 1).padStart(2, "0")}.read`,