jp.keijiro.ai.assistant.extensions 1.0.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.
Binary file
package/CHANGELOG.md ADDED
@@ -0,0 +1,10 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
6
+ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [1.0.0] - 2025-04-23
9
+
10
+ - Initial version.
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 6935281b116204b859c9ec601a5887cf
3
+ TextScriptImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
@@ -0,0 +1,70 @@
1
+ using UnityEditor;
2
+ using UnityEngine;
3
+ using UnityEngine.UIElements;
4
+
5
+ namespace AIAssistantExtensions {
6
+
7
+ [InitializeOnLoad]
8
+ static class AssistantFontModifier
9
+ {
10
+ const string OverrideStylePath =
11
+ "Packages/jp.keijiro.ai.assistant.extensions/Editor/AssistantFontOverride.uss";
12
+
13
+ const string TargetWindowTypeName =
14
+ "Unity.AI.Assistant.UI.Editor.Scripts.AssistantWindow";
15
+
16
+ const string TargetRootElementName = "root-panel";
17
+
18
+ //
19
+ // Constructor and event handlers
20
+ //
21
+
22
+ static AssistantFontModifier()
23
+ {
24
+ // Subscribe to window focus change events
25
+ EditorWindow.windowFocusChanged += OnWindowFocusChanged;
26
+
27
+ // Double delayCall to wait for Assistant UI to be fully constructed after domain reload
28
+ EditorApplication.delayCall += () =>
29
+ { EditorApplication.delayCall += () => ApplyToAllOpenWindows(); };
30
+ }
31
+
32
+ static void OnWindowFocusChanged()
33
+ => EditorApplication.delayCall += () =>
34
+ CheckAndApplyCustomFont(EditorWindow.focusedWindow);
35
+
36
+ static void ApplyToAllOpenWindows()
37
+ {
38
+ foreach (var window in Resources.FindObjectsOfTypeAll<EditorWindow>())
39
+ CheckAndApplyCustomFont(window);
40
+ }
41
+
42
+ //
43
+ // Font application logic
44
+ //
45
+
46
+ static StyleSheet _styleSheet;
47
+
48
+ static bool CheckWindowType(EditorWindow window)
49
+ => window?.GetType()?.FullName == TargetWindowTypeName;
50
+
51
+ static void ApplyCustomFont(EditorWindow window)
52
+ {
53
+ var root = window.rootVisualElement;
54
+ var target = root?.Q<VisualElement>(TargetRootElementName);
55
+ if (target == null) return;
56
+
57
+ if (_styleSheet == null)
58
+ _styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>(OverrideStylePath);
59
+
60
+ if (!target.styleSheets.Contains(_styleSheet))
61
+ target.styleSheets.Add(_styleSheet);
62
+ }
63
+
64
+ static void CheckAndApplyCustomFont(EditorWindow window)
65
+ {
66
+ if (CheckWindowType(window)) ApplyCustomFont(window);
67
+ }
68
+ }
69
+
70
+ } // namespace AIAssistantExtensions
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: 6d8c196a7df840d9a0081610516a8c1a
@@ -0,0 +1,3 @@
1
+ .unity-text-element {
2
+ -unity-font-definition: url("project://database/Packages/jp.keijiro.ai.assistant.extensions/Editor/NotoSansJP-Regular.ttf?fileID=12800000&guid=f7d2dd1a328194df9b71491ff2d07e2b&type=3#NotoSansJP-Regular");
3
+ }
@@ -0,0 +1,12 @@
1
+ fileFormatVersion: 2
2
+ guid: 728a4d733b053455383a3ad0494cb2f5
3
+ ScriptedImporter:
4
+ internalIDToNameTable: []
5
+ externalObjects: {}
6
+ serializedVersion: 2
7
+ userData:
8
+ assetBundleName:
9
+ assetBundleVariant:
10
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
11
+ disableValidation: 0
12
+ unsupportedSelectorAction: 0
@@ -0,0 +1,171 @@
1
+ using UnityEditor;
2
+ using UnityEngine;
3
+ using UnityEngine.UIElements;
4
+
5
+ namespace AIAssistantExtensions {
6
+
7
+ class AssistantImeProxyWindow : EditorWindow
8
+ {
9
+ const string UxmlPath =
10
+ "Packages/jp.keijiro.ai.assistant.extensions/Editor/AssistantImeProxy.uxml";
11
+
12
+ const string StyleSheetPath =
13
+ "Packages/jp.keijiro.ai.assistant.extensions/Editor/AssistantImeProxy.uss";
14
+
15
+ VisualElement _placeholder;
16
+ VisualElement _inputRoot;
17
+ VisualElement _textFieldContainer;
18
+ TextField _textField;
19
+
20
+ [MenuItem("Window/AI/IME Proxy")]
21
+ static void Open()
22
+ {
23
+ var window = GetWindow<AssistantImeProxyWindow>();
24
+ window.titleContent = new GUIContent("IME Proxy");
25
+ }
26
+
27
+ static VisualTreeAsset _uxml;
28
+ static StyleSheet _styleSheet;
29
+
30
+ void CreateGUI()
31
+ {
32
+ _uxml ??= AssetDatabase.LoadAssetAtPath<VisualTreeAsset>(UxmlPath);
33
+ _styleSheet ??= AssetDatabase.LoadAssetAtPath<StyleSheet>(StyleSheetPath);
34
+
35
+ rootVisualElement.Clear();
36
+ if (_styleSheet != null && !rootVisualElement.styleSheets.Contains(_styleSheet))
37
+ rootVisualElement.styleSheets.Add(_styleSheet);
38
+
39
+ if (_uxml == null)
40
+ {
41
+ rootVisualElement.Add(new Label("Failed to load AssistantImeProxy.uxml"));
42
+ return;
43
+ }
44
+
45
+ _uxml?.CloneTree(rootVisualElement);
46
+
47
+ _placeholder = rootVisualElement.Q<VisualElement>("placeholder");
48
+ _inputRoot = rootVisualElement.Q<VisualElement>("input-root");
49
+ if (_placeholder == null || _inputRoot == null)
50
+ {
51
+ rootVisualElement.Clear();
52
+ rootVisualElement.Add(new Label("Assistant IME Proxy UI is invalid."));
53
+ return;
54
+ }
55
+
56
+ _placeholder.RegisterCallback<ClickEvent>(_ => ActivateTextField());
57
+ }
58
+
59
+ void ActivateTextField()
60
+ {
61
+ // Hide placeholder
62
+ _placeholder.style.display = DisplayStyle.None;
63
+
64
+ // Container with rounded corners and relative positioning for the hint label
65
+ _textFieldContainer = new VisualElement();
66
+ _textFieldContainer.AddToClassList("ime-input-container");
67
+
68
+ // Create a fresh TextField each time — no stale cursor or IME state.
69
+ _textField = new TextField { multiline = true };
70
+ _textField.AddToClassList("ime-input-field");
71
+
72
+ // Also round the inner TextInput element
73
+ var textInput = _textField.Q("unity-text-input");
74
+ if (textInput != null) textInput.AddToClassList("ime-input-field__input");
75
+
76
+ _textField.RegisterCallback<KeyDownEvent>(OnKeyDown, TrickleDown.TrickleDown);
77
+ _textFieldContainer.Add(_textField);
78
+
79
+ // Hint label overlaid at the bottom-right corner
80
+ var hint = new Label("\u2318+Enter to send");
81
+ hint.AddToClassList("ime-input-hint");
82
+ hint.pickingMode = PickingMode.Ignore;
83
+ _textFieldContainer.Add(hint);
84
+
85
+ _inputRoot.style.display = DisplayStyle.Flex;
86
+ _inputRoot.Add(_textFieldContainer);
87
+
88
+ // Focus after the element is attached to the panel
89
+ _textField.schedule.Execute(() => _textField.Focus());
90
+ }
91
+
92
+ void DeactivateTextField()
93
+ {
94
+ // Destroy the TextField entirely — all internal state is discarded.
95
+ if (_textFieldContainer != null)
96
+ {
97
+ _textFieldContainer.RemoveFromHierarchy();
98
+ _textFieldContainer = null;
99
+ _textField = null;
100
+ }
101
+
102
+ // Show placeholder again
103
+ _inputRoot.style.display = DisplayStyle.None;
104
+ _placeholder.style.display = DisplayStyle.Flex;
105
+ }
106
+
107
+ void OnKeyDown(KeyDownEvent evt)
108
+ {
109
+ if (evt.keyCode is not (KeyCode.Return or KeyCode.KeypadEnter)) return;
110
+ if (!evt.commandKey) return; // Cmd+Enter to send
111
+
112
+ var text = _textField.value?.Trim();
113
+ if (string.IsNullOrEmpty(text)) return;
114
+
115
+ evt.StopImmediatePropagation();
116
+ #pragma warning disable CS0618
117
+ evt.PreventDefault();
118
+ #pragma warning restore CS0618
119
+
120
+ SendToAssistant(text);
121
+
122
+ // Destroy the TextField after the current event processing completes.
123
+ _textField.schedule.Execute(DeactivateTextField);
124
+ }
125
+
126
+ void SendToAssistant(string text)
127
+ {
128
+ // Find the AI Assistant window's chat input and action button.
129
+ TextField chatInput = null;
130
+ Button actionButton = null;
131
+
132
+ foreach (var w in Resources.FindObjectsOfTypeAll<EditorWindow>())
133
+ {
134
+ if (w == this) continue;
135
+ var typeName = w.GetType().FullName;
136
+ if (typeName == null || !typeName.Contains("Assistant")) continue;
137
+
138
+ var root = w.rootVisualElement;
139
+ chatInput = root?.Q<TextField>("input");
140
+ actionButton = root?.Q<Button>("actionButton");
141
+
142
+ if (chatInput != null && actionButton != null) break;
143
+ chatInput = null;
144
+ actionButton = null;
145
+ }
146
+
147
+ if (chatInput == null || actionButton == null) return;
148
+
149
+ // Set the text on the chat input field.
150
+ // This triggers OnTextFieldValueChanged -> OnChatValueChanged,
151
+ // which saves the prompt and enables the submit button.
152
+ chatInput.value = text;
153
+
154
+ // Click the action button after the value change has propagated.
155
+ // Using PointerUpEvent avoids the KeyDownEvent -> BubbleUp crash
156
+ // path entirely.
157
+ chatInput.schedule.Execute(() =>
158
+ {
159
+ var guiEvent = new Event
160
+ {
161
+ type = EventType.MouseUp,
162
+ button = 0,
163
+ mousePosition = actionButton.worldBound.center
164
+ };
165
+ using var ptrUp = PointerUpEvent.GetPooled(guiEvent);
166
+ actionButton.SendEvent(ptrUp);
167
+ });
168
+ }
169
+ }
170
+
171
+ } // namespace AIAssistantExtensions
@@ -0,0 +1,2 @@
1
+ fileFormatVersion: 2
2
+ guid: c5fe7b2f51bd94dd8b080c4627d0bf7e
@@ -0,0 +1,58 @@
1
+ .ime-proxy-root {
2
+ flex-grow: 1;
3
+ padding: 4px;
4
+ }
5
+
6
+ .ime-proxy-panel {
7
+ flex-grow: 1;
8
+ border-top-left-radius: 8px;
9
+ border-top-right-radius: 8px;
10
+ border-bottom-left-radius: 8px;
11
+ border-bottom-right-radius: 8px;
12
+ }
13
+
14
+ .ime-proxy-placeholder {
15
+ justify-content: center;
16
+ align-items: center;
17
+ background-color: rgb(51, 51, 51);
18
+ }
19
+
20
+ .ime-proxy-placeholder__label {
21
+ color: rgb(153, 153, 153);
22
+ }
23
+
24
+ .ime-proxy-input-root {
25
+ flex-grow: 1;
26
+ }
27
+
28
+ .ime-input-container {
29
+ flex-grow: 1;
30
+ position: relative;
31
+ }
32
+
33
+ .ime-input-field {
34
+ flex-grow: 1;
35
+ overflow: hidden;
36
+ -unity-font-definition: url("project://database/Packages/jp.keijiro.ai.assistant.extensions/Editor/NotoSansJP-Regular.ttf?fileID=12800000&guid=f7d2dd1a328194df9b71491ff2d07e2b&type=3#NotoSansJP-Regular");
37
+ border-top-left-radius: 8px;
38
+ border-top-right-radius: 8px;
39
+ border-bottom-left-radius: 8px;
40
+ border-bottom-right-radius: 8px;
41
+ }
42
+
43
+ .ime-input-field__input {
44
+ -unity-font-definition: url("project://database/Packages/jp.keijiro.ai.assistant.extensions/Editor/NotoSansJP-Regular.ttf?fileID=12800000&guid=f7d2dd1a328194df9b71491ff2d07e2b&type=3#NotoSansJP-Regular");
45
+ white-space: normal;
46
+ border-top-left-radius: 8px;
47
+ border-top-right-radius: 8px;
48
+ border-bottom-left-radius: 8px;
49
+ border-bottom-right-radius: 8px;
50
+ }
51
+
52
+ .ime-input-hint {
53
+ position: absolute;
54
+ right: 10px;
55
+ bottom: 6px;
56
+ font-size: 11px;
57
+ color: rgba(128, 128, 128, 0.6);
58
+ }
@@ -0,0 +1,12 @@
1
+ fileFormatVersion: 2
2
+ guid: 73fe18140135455489bef80074f4cbca
3
+ ScriptedImporter:
4
+ internalIDToNameTable: []
5
+ externalObjects: {}
6
+ serializedVersion: 2
7
+ userData:
8
+ assetBundleName:
9
+ assetBundleVariant:
10
+ script: {fileID: 12385, guid: 0000000000000000e000000000000000, type: 0}
11
+ disableValidation: 0
12
+ unsupportedSelectorAction: 0
@@ -0,0 +1,8 @@
1
+ <ui:UXML xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ui="UnityEngine.UIElements" xmlns:uie="UnityEditor.UIElements" noNamespaceSchemaLocation="../../UIElementsSchema/UIElements.xsd" editor-extension-mode="True">
2
+ <ui:VisualElement name="ime-proxy-root" class="ime-proxy-root">
3
+ <ui:VisualElement name="placeholder" class="ime-proxy-panel ime-proxy-placeholder">
4
+ <ui:Label text="Click here to type a prompt" class="ime-proxy-placeholder__label" />
5
+ </ui:VisualElement>
6
+ <ui:VisualElement name="input-root" class="ime-proxy-input-root" style="display: none;" />
7
+ </ui:VisualElement>
8
+ </ui:UXML>
@@ -0,0 +1,10 @@
1
+ fileFormatVersion: 2
2
+ guid: c54216f5e4e64d86b94a600411cef6eb
3
+ ScriptedImporter:
4
+ internalIDToNameTable: []
5
+ externalObjects: {}
6
+ serializedVersion: 2
7
+ userData:
8
+ assetBundleName:
9
+ assetBundleVariant:
10
+ script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0}
Binary file
@@ -0,0 +1,21 @@
1
+ fileFormatVersion: 2
2
+ guid: f7d2dd1a328194df9b71491ff2d07e2b
3
+ TrueTypeFontImporter:
4
+ externalObjects: {}
5
+ serializedVersion: 4
6
+ fontSize: 16
7
+ forceTextureCase: -2
8
+ characterSpacing: 0
9
+ characterPadding: 1
10
+ includeFontData: 1
11
+ fontNames:
12
+ - Noto Sans JP
13
+ fallbackFontReferences: []
14
+ customCharacters:
15
+ fontRenderingMode: 0
16
+ ascentCalculationMode: 1
17
+ useLegacyBoundsCalculation: 0
18
+ shouldRoundAdvanceValue: 1
19
+ userData:
20
+ assetBundleName:
21
+ assetBundleVariant:
package/Editor.meta ADDED
@@ -0,0 +1,8 @@
1
+ fileFormatVersion: 2
2
+ guid: cce2c3b4ef3f24e74858d2b4539b2301
3
+ folderAsset: yes
4
+ DefaultImporter:
5
+ externalObjects: {}
6
+ userData:
7
+ assetBundleName:
8
+ assetBundleVariant:
@@ -0,0 +1,127 @@
1
+ #!/usr/bin/env python3
2
+ from __future__ import annotations
3
+
4
+ import argparse
5
+ import json
6
+ import re
7
+ from dataclasses import dataclass, field
8
+ from pathlib import Path
9
+ from typing import Optional
10
+
11
+
12
+ MESSAGE_RE = re.compile(
13
+ r'"\$type":"(?P<type>[^"]+)".*?'
14
+ r'"message_id":"(?P<message_id>[^"]+)".*?'
15
+ r'(?:"last_message":(?P<last_message>true|false).*?)?'
16
+ r'"markdown":"(?P<markdown>(?:\\.|[^"\\])*)"',
17
+ )
18
+
19
+
20
+ @dataclass
21
+ class ConversationPair:
22
+ prompt: str
23
+ prompt_line: int
24
+ prompt_message_id: str
25
+ response_parts: list[str] = field(default_factory=list)
26
+ response_lines: list[int] = field(default_factory=list)
27
+ response_message_id: Optional[str] = None
28
+
29
+ @property
30
+ def response(self) -> str:
31
+ return "".join(self.response_parts).strip()
32
+
33
+
34
+ def decode_markdown(value: str) -> str:
35
+ return json.loads(f'"{value}"')
36
+
37
+
38
+ def parse_line(line: str):
39
+ match = MESSAGE_RE.search(line)
40
+ if not match:
41
+ return None
42
+
43
+ groups = match.groupdict()
44
+ return {
45
+ "type": groups["type"],
46
+ "message_id": groups["message_id"],
47
+ "last_message": groups["last_message"] == "true",
48
+ "markdown": decode_markdown(groups["markdown"]),
49
+ }
50
+
51
+
52
+ def extract_pairs(path: Path) -> list[ConversationPair]:
53
+ pairs: list[ConversationPair] = []
54
+ current_pair: Optional[ConversationPair] = None
55
+ active_response_id: Optional[str] = None
56
+
57
+ for line_number, raw_line in enumerate(path.read_text(encoding="utf-8").splitlines(), start=1):
58
+ parsed = parse_line(raw_line)
59
+ if not parsed:
60
+ continue
61
+
62
+ message_type = parsed["type"]
63
+ markdown = parsed["markdown"]
64
+
65
+ if message_type == "CHAT_ACKNOWLEDGMENT_V1" and markdown:
66
+ if current_pair and current_pair.response_parts:
67
+ pairs.append(current_pair)
68
+
69
+ current_pair = ConversationPair(
70
+ prompt=markdown.strip(),
71
+ prompt_line=line_number,
72
+ prompt_message_id=parsed["message_id"],
73
+ )
74
+ active_response_id = None
75
+ continue
76
+
77
+ if message_type != "CHAT_RESPONSE_V1" or current_pair is None:
78
+ continue
79
+
80
+ if markdown and not markdown.startswith("<"):
81
+ if active_response_id is None:
82
+ active_response_id = parsed["message_id"]
83
+ current_pair.response_message_id = active_response_id
84
+
85
+ if parsed["message_id"] == active_response_id:
86
+ current_pair.response_parts.append(markdown)
87
+ current_pair.response_lines.append(line_number)
88
+
89
+ if parsed["last_message"] and active_response_id == parsed["message_id"]:
90
+ pairs.append(current_pair)
91
+ current_pair = None
92
+ active_response_id = None
93
+
94
+ if current_pair:
95
+ pairs.append(current_pair)
96
+
97
+ return pairs
98
+
99
+
100
+ def build_markdown(pairs: list[ConversationPair], include_empty: bool) -> str:
101
+ sections = []
102
+
103
+ for pair in pairs:
104
+ if not include_empty and not pair.response:
105
+ continue
106
+
107
+ response = pair.response or "(No extracted response)"
108
+ sections.append(f"## User\n\n{pair.prompt}\n\n## Assistant\n\n{response}")
109
+
110
+ return "\n\n".join(sections)
111
+
112
+
113
+ def main():
114
+ parser = argparse.ArgumentParser(
115
+ description="Extract user prompts and natural-language assistant replies from Unity AI relay logs."
116
+ )
117
+ parser.add_argument("logfile", nargs="?", default="relay.txt", help="Path to relay log file")
118
+ parser.add_argument("--include-empty", action="store_true", help="Include prompts without extracted replies")
119
+ args = parser.parse_args()
120
+
121
+ path = Path(args.logfile)
122
+ pairs = extract_pairs(path)
123
+ print(build_markdown(pairs, args.include_empty))
124
+
125
+
126
+ if __name__ == "__main__":
127
+ main()
package/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ This is free and unencumbered software released into the public domain.
2
+
3
+ Anyone is free to copy, modify, publish, use, compile, sell, or
4
+ distribute this software, either in source code form or as a compiled
5
+ binary, for any purpose, commercial or non-commercial, and by any
6
+ means.
7
+
8
+ In jurisdictions that recognize copyright laws, the author or authors
9
+ of this software dedicate any and all copyright interest in the
10
+ software to the public domain. We make this dedication for the benefit
11
+ of the public at large and to the detriment of our heirs and
12
+ successors. We intend this dedication to be an overt act of
13
+ relinquishment in perpetuity of all present and future rights to this
14
+ software under copyright law.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20
+ OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ For more information, please refer to <https://unlicense.org/>
package/LICENSE.meta ADDED
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 785b585583b1c48f6ab38e4d4b8764ae
3
+ DefaultImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
package/README.md ADDED
@@ -0,0 +1,20 @@
1
+ # AIA Extensions
2
+
3
+ **AIA Extensions** is a custom Unity package that provides extensions for Unity
4
+ AI Assistant.
5
+
6
+ ## IME Proxy
7
+
8
+ <img width="400" height="284" alt="IME Proxy" src="https://github.com/user-attachments/assets/a6b5146d-1b63-47dd-ab4d-633357996974" />
9
+
10
+ **IME Proxy** is a custom window that works around several IME-related issues,
11
+ especially when entering Japanese text. You can open it from
12
+ `Window > AI > IME Proxy`. It automatically copies the contents of its text
13
+ field to the AI Assistant chat field and sends the message when you press
14
+ `⌘ + Enter`.
15
+
16
+ ## Font Modifier
17
+
18
+ This package includes `AssistantFontModifier` that replaces fonts used in the
19
+ AI Assistant chat window with the Noto Sans JP font. It suppresses a font atlas
20
+ overflow issue that occurs in the Unity Editor on macOS.
package/README.md.meta ADDED
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 4fb0d1f82fdf74cd592a680913ce158d
3
+ TextScriptImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant:
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "jp.keijiro.ai.assistant.extensions",
3
+ "version": "1.0.0",
4
+ "displayName": "AI Assistant Extensions",
5
+ "description": "Custom Unity package that provides extensions for Unity AI Assistant.",
6
+ "unity": "6000.0",
7
+ "author": "Keijiro Takahashi",
8
+ "dependencies": {
9
+ "com.unity.ai.assistant": "2.6.0-pre.1"
10
+ },
11
+ "changelogUrl": "https://github.com/keijiro/AIA-Extensions/blob/master/CHANGELOG.md",
12
+ "documentationUrl": "https://github.com/keijiro/AIA-Extensions",
13
+ "licensesUrl": "https://github.com/keijiro/AIA-Extensions/blob/master/LICENSE",
14
+ "license": "Unlicense",
15
+ "_upm": {
16
+ "changelog": "- Initial release."
17
+ },
18
+ "repository": {
19
+ "url": "git@github.com:keijiro/AIA-Extensions.git",
20
+ "type": "git",
21
+ "revision": "5972c2dd0d5b6a7ad01c2de12f17396f77b1cfc7"
22
+ }
23
+ }
@@ -0,0 +1,7 @@
1
+ fileFormatVersion: 2
2
+ guid: 137f1a9a80af747bdb859d72320ec089
3
+ PackageManifestImporter:
4
+ externalObjects: {}
5
+ userData:
6
+ assetBundleName:
7
+ assetBundleVariant: