create-lykomi-app 0.10.1 → 0.11.1
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 +1 -1
- package/presets/neo4j/manifest.json +1 -1
- package/template/README.md +7 -5
- package/template/package.json +5 -5
- package/template/src/pages/draft-form.tsx +1 -9
- package/template/src/pages/guide-page.tsx +2 -2
- package/template/src/pages/guide-windows.ts +0 -1
- package/template/src/pages/{use-draft-context.ts → use-draft-tools.ts} +3 -45
package/package.json
CHANGED
package/template/README.md
CHANGED
|
@@ -51,16 +51,18 @@ then open chat and ask “Make this idea more specific”. The context indicator
|
|
|
51
51
|
**Your idea**; the AG-UI request includes its field path, current value and selected
|
|
52
52
|
text. The active window also supplies the named form fields and edit mode.
|
|
53
53
|
|
|
54
|
-
`
|
|
55
|
-
|
|
54
|
+
`Field` and `ReadOnlyField` automatically supply the selected field context through
|
|
55
|
+
`@lykomi/web-ui`. No per-field focus handlers or context hook are required.
|
|
56
|
+
`src/pages/use-draft-tools.ts` uses `usePageTools` for the app-owned edits. Its `page_update_draft_field` tool validates the field and
|
|
56
57
|
checks that its current value still matches the value the agent read. Updates
|
|
57
58
|
appear in the same inputs you edit manually. **Save draft** accepts the changes
|
|
58
59
|
in memory; **Cancel** restores the previous values. Closing the draft or switching
|
|
59
60
|
to another window removes its field context and tools. Moving into chat keeps them.
|
|
60
61
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
Wrap native inputs in `Field` to get automatic field context. Use
|
|
63
|
+
`agentContext={false}` on `Field` or `ReadOnlyField` for sensitive values;
|
|
64
|
+
password inputs are always excluded. Your app owns validation and persistence.
|
|
65
|
+
Connect an authenticated storage service before saving remotely.
|
|
64
66
|
|
|
65
67
|
## Coding With AI Agents
|
|
66
68
|
|
package/template/package.json
CHANGED
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
"@assistant-ui/react": "^0.15.1",
|
|
27
27
|
"@azure/msal-browser": "^5.6.3",
|
|
28
28
|
"@azure/msal-react": "^5.2.1",
|
|
29
|
-
"@lykomi/agent": "0.
|
|
30
|
-
"@lykomi/web-primitives": "0.
|
|
31
|
-
"@lykomi/web-shell": "0.
|
|
32
|
-
"@lykomi/web-ui": "0.
|
|
33
|
-
"@lykomi/web-voice": "0.1.
|
|
29
|
+
"@lykomi/agent": "0.52.0",
|
|
30
|
+
"@lykomi/web-primitives": "0.52.0",
|
|
31
|
+
"@lykomi/web-shell": "0.52.0",
|
|
32
|
+
"@lykomi/web-ui": "0.52.0",
|
|
33
|
+
"@lykomi/web-voice": "0.1.36",
|
|
34
34
|
"@radix-ui/react-tabs": "^1.1.22",
|
|
35
35
|
"@tanstack/react-query": "^5.99.0",
|
|
36
36
|
"lucide-react": "^0.553.0",
|
|
@@ -21,15 +21,9 @@ export function DraftForm({ tab }: { tab: GuideWindow }) {
|
|
|
21
21
|
saved: undefined,
|
|
22
22
|
editing: false,
|
|
23
23
|
dirty: false,
|
|
24
|
-
field: undefined,
|
|
25
24
|
});
|
|
26
25
|
requestAnimationFrame(() => editButton.current?.focus());
|
|
27
26
|
};
|
|
28
|
-
const track = (key: "name" | "text", input: HTMLInputElement | HTMLTextAreaElement) => {
|
|
29
|
-
const field = { key, start: input.selectionStart ?? 0, end: input.selectionEnd ?? 0 };
|
|
30
|
-
const current = guideWindows.get().tabs.find((entry) => entry.id === tab.id)?.field;
|
|
31
|
-
if (JSON.stringify(current) !== JSON.stringify(field)) guideWindows.update(tab.id, { field });
|
|
32
|
-
};
|
|
33
27
|
return (
|
|
34
28
|
<FormLayout
|
|
35
29
|
className="mt-4"
|
|
@@ -89,15 +83,13 @@ export function DraftForm({ tab }: { tab: GuideWindow }) {
|
|
|
89
83
|
>
|
|
90
84
|
{tab.editing ? (
|
|
91
85
|
<Control
|
|
86
|
+
name={key}
|
|
92
87
|
id={`starter-draft-${key}`}
|
|
93
88
|
value={tab[key] ?? ""}
|
|
94
89
|
className={valueClass}
|
|
95
90
|
maxLength={2000}
|
|
96
|
-
onFocus={(event) => track(key, event.currentTarget)}
|
|
97
|
-
onSelect={(event) => track(key, event.currentTarget)}
|
|
98
91
|
onChange={(event) => {
|
|
99
92
|
guideWindows.update(tab.id, { [key]: event.target.value, dirty: true });
|
|
100
|
-
track(key, event.currentTarget);
|
|
101
93
|
}}
|
|
102
94
|
/>
|
|
103
95
|
) : (
|
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
DropdownMenuItem,
|
|
10
10
|
} from "@lykomi/web-ui";
|
|
11
11
|
import { DraftForm } from "./draft-form.tsx";
|
|
12
|
-
import {
|
|
12
|
+
import { useDraftTools } from "./use-draft-tools.ts";
|
|
13
13
|
import { guideWindows, openGuideWindow } from "./guide-windows.ts";
|
|
14
14
|
|
|
15
15
|
export function GuidePage() {
|
|
16
|
-
|
|
16
|
+
useDraftTools();
|
|
17
17
|
return (
|
|
18
18
|
<WindowWorkbench
|
|
19
19
|
controller={guideWindows}
|
|
@@ -6,7 +6,6 @@ export interface GuideWindow extends WorkbenchWindow {
|
|
|
6
6
|
name?: string;
|
|
7
7
|
editing?: boolean;
|
|
8
8
|
saved?: { name: string; text: string };
|
|
9
|
-
field?: { key: "name" | "text"; start: number; end: number };
|
|
10
9
|
}
|
|
11
10
|
|
|
12
11
|
// App-owned data; the UI framework owns selection, pinning, ordering and layouts.
|
|
@@ -1,52 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useAppStore, usePageTools } from "@lykomi/web-ui";
|
|
1
|
+
import { usePageTools } from "@lykomi/web-ui";
|
|
3
2
|
import { useWindows } from "@lykomi/web-ui/windows";
|
|
4
3
|
import { guideWindows } from "./guide-windows.ts";
|
|
5
4
|
|
|
6
|
-
/**
|
|
7
|
-
export function
|
|
5
|
+
/** App-owned draft updates. Field focus/value/selection context comes from the framework. */
|
|
6
|
+
export function useDraftTools() {
|
|
8
7
|
const { tabs, active } = useWindows(guideWindows);
|
|
9
8
|
const tab = tabs.find((entry) => entry.id === active);
|
|
10
|
-
useEffect(() => {
|
|
11
|
-
const field = tab?.kind === "draft" && tab.editing ? tab.field : undefined;
|
|
12
|
-
const value = field ? (tab?.[field.key] ?? "") : "";
|
|
13
|
-
const label = field?.key === "name" ? "App name" : "Your idea";
|
|
14
|
-
useAppStore.getState().setContextItem(
|
|
15
|
-
"starter:active-field",
|
|
16
|
-
field
|
|
17
|
-
? {
|
|
18
|
-
type: "ref",
|
|
19
|
-
label,
|
|
20
|
-
sourcePage: "/guide",
|
|
21
|
-
persistence: "ephemeral",
|
|
22
|
-
payload: {
|
|
23
|
-
kind: "ref",
|
|
24
|
-
refType: "form-field",
|
|
25
|
-
refId: `draft:${field.key}`,
|
|
26
|
-
target: {
|
|
27
|
-
kind: "field",
|
|
28
|
-
path: field.key,
|
|
29
|
-
label,
|
|
30
|
-
containerId: "draft",
|
|
31
|
-
containerLabel: "Working draft",
|
|
32
|
-
currentValue: value,
|
|
33
|
-
},
|
|
34
|
-
meta: {
|
|
35
|
-
fieldFocus: "active",
|
|
36
|
-
fieldLabel: label,
|
|
37
|
-
caret: {
|
|
38
|
-
start: field.start,
|
|
39
|
-
end: field.end,
|
|
40
|
-
selectedText: value.slice(field.start, field.end),
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
}
|
|
45
|
-
: null,
|
|
46
|
-
);
|
|
47
|
-
return () => useAppStore.getState().setContextItem("starter:active-field", null);
|
|
48
|
-
}, [tab]);
|
|
49
|
-
|
|
50
9
|
usePageTools(
|
|
51
10
|
tab?.kind === "draft" && tab.editing
|
|
52
11
|
? [
|
|
@@ -85,7 +44,6 @@ export function useDraftContext() {
|
|
|
85
44
|
guideWindows.update(current.id, {
|
|
86
45
|
[args.field]: args.value,
|
|
87
46
|
dirty: true,
|
|
88
|
-
field: { key: args.field, start: 0, end: 0 },
|
|
89
47
|
});
|
|
90
48
|
return JSON.stringify({
|
|
91
49
|
status: "updated",
|