@stigmer/ink 3.20.0 → 3.22.0

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.
@@ -9,6 +9,13 @@ export interface AgentPickerProps {
9
9
  readonly scope?: "org" | "all";
10
10
  /** Called with the chosen agent's search result on selection. */
11
11
  readonly onSelect: (agent: SearchResult) => void;
12
+ /**
13
+ * When given, the list opens with the built-in assistant — the answer a
14
+ * session gets with no agent at all — as its first row, and choosing it
15
+ * calls this instead of `onSelect`. Absent, the picker offers agents only
16
+ * (a caller that needs an agent, such as a schedule, leaves it out).
17
+ */
18
+ readonly onSelectBuiltInAssistant?: () => void;
12
19
  /** Called when the user cancels (Esc / Ctrl+C). */
13
20
  readonly onCancel: () => void;
14
21
  }
@@ -29,5 +36,5 @@ export interface AgentPickerProps {
29
36
  * );
30
37
  * ```
31
38
  */
32
- export declare function AgentPicker({ org, initialQuery, scope, onSelect, onCancel }: AgentPickerProps): import("react/jsx-runtime").JSX.Element;
39
+ export declare function AgentPicker({ org, initialQuery, scope, onSelect, onSelectBuiltInAssistant, onCancel, }: AgentPickerProps): import("react/jsx-runtime").JSX.Element;
33
40
  //# sourceMappingURL=AgentPicker.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AgentPicker.d.ts","sourceRoot":"","sources":["../../src/components/AgentPicker.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAC;AAI/E,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,qCAAqC;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAC/B,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACjD,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;CAC/B;AAKD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,gBAAgB,2CAkC7F"}
1
+ {"version":3,"file":"AgentPicker.d.ts","sourceRoot":"","sources":["../../src/components/AgentPicker.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4CAA4C,CAAC;AAI/E,qCAAqC;AACrC,MAAM,WAAW,gBAAgB;IAC/B,qCAAqC;IACrC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,0EAA0E;IAC1E,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;IAC/B,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;IACjD;;;;;OAKG;IACH,QAAQ,CAAC,wBAAwB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC/C,mDAAmD;IACnD,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;CAC/B;AAkBD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,WAAW,CAAC,EAC1B,GAAG,EACH,YAAY,EACZ,KAAK,EACL,QAAQ,EACR,wBAAwB,EACxB,QAAQ,GACT,EAAE,gBAAgB,2CA2ClB"}
@@ -1,9 +1,20 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useMemo } from "react";
3
- import { useAgentSearch } from "@stigmer/react";
3
+ import { BUILT_IN_ASSISTANT_NAME, useAgentSearch } from "@stigmer/react";
4
4
  import { ResourcePicker } from "./ResourcePicker.js";
5
5
  /** Max description length shown as the row subtitle before truncation. */
6
6
  const SUBTITLE_MAX = 60;
7
+ /**
8
+ * The built-in assistant's row id: no agent carries an empty id, so it cannot
9
+ * collide with a search result, and it reads as what it is on the wire (an
10
+ * empty `agentInstanceId` is the built-in assistant).
11
+ */
12
+ const BUILT_IN_ASSISTANT_ITEM_ID = "";
13
+ const BUILT_IN_ASSISTANT_ITEM = {
14
+ id: BUILT_IN_ASSISTANT_ITEM_ID,
15
+ title: `${BUILT_IN_ASSISTANT_NAME} (built-in)`,
16
+ subtitle: "No agent: answers with the tools the conversation carries",
17
+ };
7
18
  /**
8
19
  * Interactive picker for choosing an agent by name.
9
20
  *
@@ -21,7 +32,7 @@ const SUBTITLE_MAX = 60;
21
32
  * );
22
33
  * ```
23
34
  */
24
- export function AgentPicker({ org, initialQuery, scope, onSelect, onCancel }) {
35
+ export function AgentPicker({ org, initialQuery, scope, onSelect, onSelectBuiltInAssistant, onCancel, }) {
25
36
  const { results, isLoading, error, query, setQuery } = useAgentSearch(org, { scope });
26
37
  // Seed the typed-but-unresolved query once on mount so the user picks up
27
38
  // where the smart-resolution attempt left off.
@@ -31,12 +42,21 @@ export function AgentPicker({ org, initialQuery, scope, onSelect, onCancel }) {
31
42
  // Mount-only: re-seeding on every render would fight the user's typing.
32
43
  // eslint-disable-next-line react-hooks/exhaustive-deps
33
44
  }, []);
34
- const items = useMemo(() => results.map(toAgentItem), [results]);
45
+ // The assistant row stays first whatever the query, because it is not a
46
+ // search result: it is the choice of not searching for an agent at all.
47
+ const items = useMemo(() => {
48
+ const agents = results.map(toAgentItem);
49
+ return onSelectBuiltInAssistant ? [BUILT_IN_ASSISTANT_ITEM, ...agents] : agents;
50
+ }, [results, onSelectBuiltInAssistant]);
35
51
  const handleSelect = useCallback((item) => {
52
+ if (item.id === BUILT_IN_ASSISTANT_ITEM_ID) {
53
+ onSelectBuiltInAssistant?.();
54
+ return;
55
+ }
36
56
  const found = results.find((r) => r.id === item.id);
37
57
  if (found !== undefined)
38
58
  onSelect(found);
39
- }, [results, onSelect]);
59
+ }, [results, onSelect, onSelectBuiltInAssistant]);
40
60
  return (_jsx(ResourcePicker, { prompt: "Select an agent", items: items, query: query, onQueryChange: setQuery, isLoading: isLoading, error: error, onSelect: handleSelect, onCancel: onCancel, emptyLabel: "no agents found" }));
41
61
  }
42
62
  /** Map a search result to a picker row: org/slug title, description subtitle. */
@@ -1 +1 @@
1
- {"version":3,"file":"AgentPicker.js","sourceRoot":"","sources":["../../src/components/AgentPicker.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAE/D,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAmB,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAgBtE,0EAA0E;AAC1E,MAAM,YAAY,GAAG,EAAE,CAAC;AAExB;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,WAAW,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAoB;IAC5F,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,cAAc,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IAEtF,yEAAyE;IACzE,+CAA+C;IAC/C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,YAAY,KAAK,SAAS,IAAI,YAAY,KAAK,EAAE;YAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;QAC9E,wEAAwE;QACxE,uDAAuD;IACzD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,KAAK,GAAG,OAAO,CAAe,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAE/E,MAAM,YAAY,GAAG,WAAW,CAC9B,CAAC,IAAgB,EAAE,EAAE;QACnB,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC;QACpD,IAAI,KAAK,KAAK,SAAS;YAAE,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC,EACD,CAAC,OAAO,EAAE,QAAQ,CAAC,CACpB,CAAC;IAEF,OAAO,CACL,KAAC,cAAc,IACb,MAAM,EAAC,iBAAiB,EACxB,KAAK,EAAE,KAAK,EACZ,KAAK,EAAE,KAAK,EACZ,aAAa,EAAE,QAAQ,EACvB,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,QAAQ,EAClB,UAAU,EAAC,iBAAiB,GAC5B,CACH,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,SAAS,WAAW,CAAC,MAAoB;IACvC,MAAM,KAAK,GAAG,MAAM,CAAC,aAAa,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;IAClG,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,YAAY,CAAC,EAAE,CAAC;AACxF,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,GAAW;IACzC,OAAO,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC;AAClE,CAAC"}
1
+ {"version":3,"file":"AgentPicker.js","sourceRoot":"","sources":["../../src/components/AgentPicker.tsx"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stigmer/ink",
3
- "version": "3.20.0",
3
+ "version": "3.22.0",
4
4
  "description": "Ink (React for terminals) components for rendering Stigmer agent sessions in the terminal",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "dependencies": {
37
37
  "@connectrpc/connect-node": "^2.1.1",
38
- "@stigmer/react": "3.20.0",
38
+ "@stigmer/react": "3.22.0",
39
39
  "ink-spinner": "^5.0.0",
40
40
  "ink-text-input": "^6.0.0",
41
41
  "marked": "^15.0.7",
@@ -43,8 +43,8 @@
43
43
  },
44
44
  "peerDependencies": {
45
45
  "@bufbuild/protobuf": "^2.0.0",
46
- "@stigmer/protos": "3.20.0",
47
- "@stigmer/sdk": "3.20.0",
46
+ "@stigmer/protos": "3.22.0",
47
+ "@stigmer/sdk": "3.22.0",
48
48
  "ink": "^7.0.0",
49
49
  "react": ">=19.0.0"
50
50
  }
@@ -54,6 +54,50 @@ describe("AgentPicker", () => {
54
54
  expect(onSelect.mock.calls[0][0].id).toBe("agt_1");
55
55
  });
56
56
 
57
+ it("offers the built-in assistant first when asked, and picks it without an agent", async () => {
58
+ const results = [agentResult("agt_1", "acme/alpha", "first")];
59
+ const client = fakeClient({
60
+ agent: { list: vi.fn(async () => ({ entries: results, totalPages: 1, totalCount: 1 })) },
61
+ });
62
+ const onSelect = vi.fn();
63
+ const onSelectBuiltInAssistant = vi.fn();
64
+
65
+ const { lastFrame, stdin } = render(
66
+ <InkStigmerProvider client={client}>
67
+ <AgentPicker
68
+ org="acme"
69
+ onSelect={onSelect}
70
+ onSelectBuiltInAssistant={onSelectBuiltInAssistant}
71
+ onCancel={vi.fn()}
72
+ />
73
+ </InkStigmerProvider>,
74
+ );
75
+
76
+ await settle();
77
+ const frame = lastFrame() ?? "";
78
+ expect(frame).toContain("Assistant (built-in)");
79
+ // First row: above every agent the search found.
80
+ expect(frame.indexOf("Assistant (built-in)")).toBeLessThan(frame.indexOf("acme/alpha"));
81
+
82
+ stdin.write(KEY.enter);
83
+ await settle();
84
+ expect(onSelectBuiltInAssistant).toHaveBeenCalledTimes(1);
85
+ expect(onSelect).not.toHaveBeenCalled();
86
+ });
87
+
88
+ it("offers agents only when no built-in handler is given", async () => {
89
+ const client = fakeClient({
90
+ agent: { list: vi.fn(async () => ({ entries: [], totalPages: 0, totalCount: 0 })) },
91
+ });
92
+ const { lastFrame } = render(
93
+ <InkStigmerProvider client={client}>
94
+ <AgentPicker org="acme" onSelect={vi.fn()} onCancel={vi.fn()} />
95
+ </InkStigmerProvider>,
96
+ );
97
+ await settle();
98
+ expect(lastFrame() ?? "").not.toContain("Assistant (built-in)");
99
+ });
100
+
57
101
  it("seeds the search box from initialQuery", async () => {
58
102
  const list = vi.fn(async () => ({ entries: [], totalPages: 0, totalCount: 0 }));
59
103
  const client = fakeClient({ agent: { list } });
@@ -1,6 +1,6 @@
1
1
  import React, { useCallback, useEffect, useMemo } from "react";
2
2
  import type { SearchResult } from "@stigmer/protos/ai/stigmer/search/v1/io_pb";
3
- import { useAgentSearch } from "@stigmer/react";
3
+ import { BUILT_IN_ASSISTANT_NAME, useAgentSearch } from "@stigmer/react";
4
4
  import { type PickerItem, ResourcePicker } from "./ResourcePicker.js";
5
5
 
6
6
  /** Props for {@link AgentPicker}. */
@@ -13,6 +13,13 @@ export interface AgentPickerProps {
13
13
  readonly scope?: "org" | "all";
14
14
  /** Called with the chosen agent's search result on selection. */
15
15
  readonly onSelect: (agent: SearchResult) => void;
16
+ /**
17
+ * When given, the list opens with the built-in assistant — the answer a
18
+ * session gets with no agent at all — as its first row, and choosing it
19
+ * calls this instead of `onSelect`. Absent, the picker offers agents only
20
+ * (a caller that needs an agent, such as a schedule, leaves it out).
21
+ */
22
+ readonly onSelectBuiltInAssistant?: () => void;
16
23
  /** Called when the user cancels (Esc / Ctrl+C). */
17
24
  readonly onCancel: () => void;
18
25
  }
@@ -20,6 +27,19 @@ export interface AgentPickerProps {
20
27
  /** Max description length shown as the row subtitle before truncation. */
21
28
  const SUBTITLE_MAX = 60;
22
29
 
30
+ /**
31
+ * The built-in assistant's row id: no agent carries an empty id, so it cannot
32
+ * collide with a search result, and it reads as what it is on the wire (an
33
+ * empty `agentInstanceId` is the built-in assistant).
34
+ */
35
+ const BUILT_IN_ASSISTANT_ITEM_ID = "";
36
+
37
+ const BUILT_IN_ASSISTANT_ITEM: PickerItem = {
38
+ id: BUILT_IN_ASSISTANT_ITEM_ID,
39
+ title: `${BUILT_IN_ASSISTANT_NAME} (built-in)`,
40
+ subtitle: "No agent: answers with the tools the conversation carries",
41
+ };
42
+
23
43
  /**
24
44
  * Interactive picker for choosing an agent by name.
25
45
  *
@@ -37,7 +57,14 @@ const SUBTITLE_MAX = 60;
37
57
  * );
38
58
  * ```
39
59
  */
40
- export function AgentPicker({ org, initialQuery, scope, onSelect, onCancel }: AgentPickerProps) {
60
+ export function AgentPicker({
61
+ org,
62
+ initialQuery,
63
+ scope,
64
+ onSelect,
65
+ onSelectBuiltInAssistant,
66
+ onCancel,
67
+ }: AgentPickerProps) {
41
68
  const { results, isLoading, error, query, setQuery } = useAgentSearch(org, { scope });
42
69
 
43
70
  // Seed the typed-but-unresolved query once on mount so the user picks up
@@ -48,14 +75,23 @@ export function AgentPicker({ org, initialQuery, scope, onSelect, onCancel }: Ag
48
75
  // eslint-disable-next-line react-hooks/exhaustive-deps
49
76
  }, []);
50
77
 
51
- const items = useMemo<PickerItem[]>(() => results.map(toAgentItem), [results]);
78
+ // The assistant row stays first whatever the query, because it is not a
79
+ // search result: it is the choice of not searching for an agent at all.
80
+ const items = useMemo<PickerItem[]>(() => {
81
+ const agents = results.map(toAgentItem);
82
+ return onSelectBuiltInAssistant ? [BUILT_IN_ASSISTANT_ITEM, ...agents] : agents;
83
+ }, [results, onSelectBuiltInAssistant]);
52
84
 
53
85
  const handleSelect = useCallback(
54
86
  (item: PickerItem) => {
87
+ if (item.id === BUILT_IN_ASSISTANT_ITEM_ID) {
88
+ onSelectBuiltInAssistant?.();
89
+ return;
90
+ }
55
91
  const found = results.find((r) => r.id === item.id);
56
92
  if (found !== undefined) onSelect(found);
57
93
  },
58
- [results, onSelect],
94
+ [results, onSelect, onSelectBuiltInAssistant],
59
95
  );
60
96
 
61
97
  return (