inconvo 1.2.1 → 1.4.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.
- package/README.md +2 -0
- package/dist/commands/add.js +2 -0
- package/dist/lib/thread-injector.js +86 -0
- package/dist/templates/packs.js +1 -1
- package/package.json +1 -1
- package/templates/assistant-ui/src/components/assistant-ui/tools/inconvo-hidden-tools.tsx +30 -0
- package/templates/assistant-ui/src/components/assistant-ui/tools/inconvo-tools.tsx +11 -1
package/README.md
CHANGED
|
@@ -20,6 +20,8 @@ Options:
|
|
|
20
20
|
|
|
21
21
|
By default the installer writes everything under `src/`, including the tool components and their supporting `src/lib/inconvo/types.ts`. It also installs external dependencies such as `recharts` and `@tanstack/react-table` unless you opt out with `--skip-install`.
|
|
22
22
|
|
|
23
|
+
After the files are copied, the CLI attempts to update `src/components/assistant-ui/thread.tsx` by importing `InconvoTools` and rendering it inside `ThreadPrimitive.Root`. If the file is missing or has been customized heavily, you'll see a warning and can complete the insertion manually.
|
|
24
|
+
|
|
23
25
|
## Development
|
|
24
26
|
|
|
25
27
|
```bash
|
package/dist/commands/add.js
CHANGED
|
@@ -4,6 +4,7 @@ import fs from "node:fs/promises";
|
|
|
4
4
|
import { logger } from "../lib/logger.js";
|
|
5
5
|
import { confirmPrompt } from "../lib/prompt.js";
|
|
6
6
|
import { installDependencies } from "../lib/install-dependencies.js";
|
|
7
|
+
import { ensureThreadHasTools } from "../lib/thread-injector.js";
|
|
7
8
|
import { componentPacks, getPack } from "../templates/packs.js";
|
|
8
9
|
export const addCommand = new Command()
|
|
9
10
|
.name("add")
|
|
@@ -70,6 +71,7 @@ export const addCommand = new Command()
|
|
|
70
71
|
if (replaced.size) {
|
|
71
72
|
logger.info(`Overwrote ${replaced.size} file(s).`);
|
|
72
73
|
}
|
|
74
|
+
await ensureThreadHasTools(cwd);
|
|
73
75
|
if (pack.dependencies) {
|
|
74
76
|
const depList = Object.entries(pack.dependencies).map(([name, version]) => `${name}@${version}`);
|
|
75
77
|
if (!depList.length)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { logger } from "./logger.js";
|
|
4
|
+
const TOOLS_IMPORT = `import { InconvoTools } from "./tools/inconvo-tools";`;
|
|
5
|
+
const THREAD_PATH = ["src", "components", "assistant-ui", "thread.tsx"];
|
|
6
|
+
export async function ensureThreadHasTools(projectRoot) {
|
|
7
|
+
const threadPath = path.join(projectRoot, ...THREAD_PATH);
|
|
8
|
+
if (!(await fileExists(threadPath))) {
|
|
9
|
+
logger.warn(`Could not find ${path.relative(projectRoot, threadPath)}. Skipping thread update.`);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
let content = await fs.readFile(threadPath, "utf8");
|
|
13
|
+
let updated = false;
|
|
14
|
+
if (!hasToolsImport(content)) {
|
|
15
|
+
content = injectImport(content);
|
|
16
|
+
updated = true;
|
|
17
|
+
}
|
|
18
|
+
if (!content.includes("<InconvoTools")) {
|
|
19
|
+
const nextContent = injectComponentUsage(content);
|
|
20
|
+
if (nextContent) {
|
|
21
|
+
content = nextContent;
|
|
22
|
+
updated = true;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
logger.warn("Could not locate </ThreadPrimitive.Root> in thread.tsx. Please insert <InconvoTools /> manually.");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (updated) {
|
|
29
|
+
await fs.writeFile(threadPath, content, "utf8");
|
|
30
|
+
logger.success("Updated thread component to render <InconvoTools />.");
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
logger.info("Thread component already renders <InconvoTools />.");
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function hasToolsImport(content) {
|
|
37
|
+
const namedImportRegex = /import\s+{[^}]*InconvoTools[^}]*}\s+from\s+["'][^"']+["']/;
|
|
38
|
+
const defaultImportRegex = /import\s+InconvoTools\s+from\s+["'][^"']+["']/;
|
|
39
|
+
return (namedImportRegex.test(content) || defaultImportRegex.test(content));
|
|
40
|
+
}
|
|
41
|
+
function injectImport(content) {
|
|
42
|
+
const lines = content.split("\n");
|
|
43
|
+
let lastImportIndex = -1;
|
|
44
|
+
for (let i = 0; i < lines.length; i++) {
|
|
45
|
+
if (lines[i].startsWith("import ")) {
|
|
46
|
+
lastImportIndex = i;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (lastImportIndex >= 0) {
|
|
50
|
+
lines.splice(lastImportIndex + 1, 0, TOOLS_IMPORT);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
lines.unshift(TOOLS_IMPORT);
|
|
54
|
+
}
|
|
55
|
+
return lines.join("\n");
|
|
56
|
+
}
|
|
57
|
+
function injectComponentUsage(content) {
|
|
58
|
+
const lines = content.split("\n");
|
|
59
|
+
const rootIndex = lines.findIndex((line) => line.includes("<ThreadPrimitive.Root"));
|
|
60
|
+
if (rootIndex === -1) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
let insertIndex = rootIndex + 1;
|
|
64
|
+
for (let i = rootIndex; i < lines.length; i++) {
|
|
65
|
+
if (lines[i].includes(">")) {
|
|
66
|
+
insertIndex = i + 1;
|
|
67
|
+
break;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const baseIndent = lines[rootIndex].match(/^\s*/)?.[0] ?? "";
|
|
71
|
+
const componentLine = `${baseIndent} <InconvoTools />`;
|
|
72
|
+
lines.splice(insertIndex, 0, componentLine);
|
|
73
|
+
return lines.join("\n");
|
|
74
|
+
}
|
|
75
|
+
async function fileExists(target) {
|
|
76
|
+
try {
|
|
77
|
+
await fs.stat(target);
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (error && error.code === "ENOENT") {
|
|
82
|
+
return false;
|
|
83
|
+
}
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
}
|
package/dist/templates/packs.js
CHANGED
|
@@ -2,7 +2,7 @@ import { resolveFromRoot } from "../lib/paths.js";
|
|
|
2
2
|
export const componentPacks = {
|
|
3
3
|
"assistant-ui-tool-components": {
|
|
4
4
|
name: "assistant-ui-tool-components",
|
|
5
|
-
description: "Inconvo-flavored
|
|
5
|
+
description: "Inconvo-flavored tool output components for assistant-ui.",
|
|
6
6
|
templateDir: resolveFromRoot("templates", "assistant-ui", "src"),
|
|
7
7
|
targetDir: "src",
|
|
8
8
|
dependencies: {
|
package/package.json
CHANGED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
makeAssistantToolUI,
|
|
5
|
+
type ToolCallMessagePartComponent,
|
|
6
|
+
} from "@assistant-ui/react";
|
|
7
|
+
|
|
8
|
+
type GenericArgs = Record<string, unknown>;
|
|
9
|
+
type GenericResult = unknown;
|
|
10
|
+
|
|
11
|
+
const HiddenToolRender: ToolCallMessagePartComponent<
|
|
12
|
+
GenericArgs,
|
|
13
|
+
GenericResult
|
|
14
|
+
> = () => null;
|
|
15
|
+
|
|
16
|
+
export const GetDataSummaryTool = makeAssistantToolUI<
|
|
17
|
+
GenericArgs,
|
|
18
|
+
GenericResult
|
|
19
|
+
>({
|
|
20
|
+
toolName: "get_data_summary",
|
|
21
|
+
render: HiddenToolRender,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export const StartDataAnalystConversationTool = makeAssistantToolUI<
|
|
25
|
+
GenericArgs,
|
|
26
|
+
GenericResult
|
|
27
|
+
>({
|
|
28
|
+
toolName: "start_data_analyst_conversation",
|
|
29
|
+
render: HiddenToolRender,
|
|
30
|
+
});
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { MessageDataAnalystTool } from "~/components/assistant-ui/tools/message-data-analyst-tool";
|
|
4
|
+
import {
|
|
5
|
+
GetDataSummaryTool,
|
|
6
|
+
StartDataAnalystConversationTool,
|
|
7
|
+
} from "~/components/assistant-ui/tools/inconvo-hidden-tools";
|
|
4
8
|
|
|
5
9
|
export const InconvoTools = () => {
|
|
6
|
-
return
|
|
10
|
+
return (
|
|
11
|
+
<>
|
|
12
|
+
<MessageDataAnalystTool />
|
|
13
|
+
<GetDataSummaryTool />
|
|
14
|
+
<StartDataAnalystConversationTool />
|
|
15
|
+
</>
|
|
16
|
+
);
|
|
7
17
|
};
|