crowe-logic 0.1.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/.dockerignore ADDED
@@ -0,0 +1,14 @@
1
+ venv/
2
+ .venv/
3
+ __pycache__/
4
+ *.pyc
5
+ .env
6
+ .agent_id
7
+ .chat_history
8
+ node_modules/
9
+ data/azure-ft/
10
+ data/crowelm-*/
11
+ .git/
12
+ *.egg-info/
13
+ dist/
14
+ build/
package/.env.example ADDED
@@ -0,0 +1,24 @@
1
+ # Azure AI Foundry — Crowe Logic Agent
2
+ # Copy to .env and fill in your values
3
+
4
+ # Your Azure AI Foundry project endpoint (found in project overview)
5
+ PROJECT_ENDPOINT=https://crowelogicos-7858.services.ai.azure.com
6
+
7
+ # Model deployment name (the gpt-oss-120b deployment you created in Azure)
8
+ MODEL_DEPLOYMENT_NAME=gpt-oss-120b
9
+
10
+ # Bing Search connection ID (for web grounding — create in Azure AI Foundry connections)
11
+ AZURE_BING_CONNECTION_ID=
12
+
13
+ # Azure AI Search connection ID (for vector search — create in Azure AI Foundry connections)
14
+ AI_AZURE_AI_CONNECTION_ID=
15
+
16
+ # Azure AI Search index name
17
+ AI_SEARCH_INDEX_NAME=crowe-logic-kb
18
+
19
+ # Azure subscription details (for Azure Function tools)
20
+ AZURE_SUBSCRIPTION_ID=
21
+ AZURE_RESOURCE_GROUP=rg-crowelogicos-7858
22
+
23
+ # Optional: Application Insights for tracing
24
+ APPLICATIONINSIGHTS_CONNECTION_STRING=
package/Dockerfile ADDED
@@ -0,0 +1,62 @@
1
+ FROM python:3.12-slim AS base
2
+
3
+ LABEL maintainer="michael@crowelogic.com"
4
+ LABEL org.opencontainers.image.title="Crowe Logic Agent"
5
+ LABEL org.opencontainers.image.description="Universal AI Agent powered by gpt-oss-120b on Azure AI Foundry"
6
+ LABEL org.opencontainers.image.vendor="Crowe Logic, Inc."
7
+
8
+ WORKDIR /app
9
+
10
+ # System dependencies for playwright and ripgrep
11
+ RUN apt-get update && apt-get install -y --no-install-recommends \
12
+ git \
13
+ ripgrep \
14
+ curl \
15
+ && rm -rf /var/lib/apt/lists/*
16
+
17
+ # Install Node.js for MCP servers
18
+ RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \
19
+ && apt-get install -y nodejs \
20
+ && rm -rf /var/lib/apt/lists/*
21
+
22
+ # Python dependencies
23
+ COPY requirements.txt .
24
+ RUN pip install --no-cache-dir -r requirements.txt
25
+
26
+ # MCP servers
27
+ COPY package.json package-lock.json* ./
28
+ RUN npm install --production
29
+
30
+ # Application code
31
+ COPY . .
32
+
33
+ # Install crowe-logic CLI
34
+ RUN pip install --no-cache-dir -e .
35
+
36
+ # Default: interactive chat
37
+ ENTRYPOINT ["crowe-logic"]
38
+ CMD ["chat"]
39
+
40
+ # ── GPU variant for fine-tuning ─────────────────
41
+ FROM nvidia/cuda:12.4.1-runtime-ubuntu22.04 AS gpu
42
+
43
+ LABEL maintainer="michael@crowelogic.com"
44
+ LABEL org.opencontainers.image.title="Crowe Logic Agent (GPU)"
45
+
46
+ WORKDIR /app
47
+
48
+ RUN apt-get update && apt-get install -y --no-install-recommends \
49
+ python3.12 python3-pip git ripgrep curl \
50
+ && rm -rf /var/lib/apt/lists/*
51
+
52
+ COPY requirements.txt .
53
+ RUN pip install --no-cache-dir -r requirements.txt
54
+ RUN pip install --no-cache-dir qiskit qiskit-aer cirq pennylane \
55
+ synapse-lang synapse-qubit-flow \
56
+ torch --index-url https://download.pytorch.org/whl/cu124
57
+
58
+ COPY . .
59
+ RUN pip install --no-cache-dir -e ".[quantum]"
60
+
61
+ ENTRYPOINT ["crowe-logic"]
62
+ CMD ["chat"]
File without changes
@@ -0,0 +1,105 @@
1
+ """
2
+ Crowe Logic CLI — Branding & Terminal Art
3
+
4
+ Provides the logo, banner, and styled prompt for the CLI.
5
+ """
6
+
7
+ import os
8
+
9
+ # Gold/amber ANSI escape — closest to the gold ring in the logo
10
+ GOLD = "\033[38;2;191;166;105m"
11
+ WHITE = "\033[97m"
12
+ BLACK_BG = "\033[40m"
13
+ DIM = "\033[2m"
14
+ BOLD = "\033[1m"
15
+ RESET = "\033[0m"
16
+ CYAN = "\033[36m"
17
+
18
+ # ── Compact logo mark for the prompt ────────────────────────────
19
+ # Uses Unicode block/braille characters for a tiny circular icon
20
+ PROMPT_ICON = f"{GOLD}\u25C9{RESET}" # ◉ gold ring dot
21
+
22
+ # ── ASCII art banner ────────────────────────────────────────────
23
+ # Stencil-style portrait in the gold ring — simplified for terminal
24
+ BANNER = f"""{GOLD}
25
+ ╭━━━━━━━━━━━━━━━━━╮
26
+ ╭━━━╯ ╰━━━╮
27
+ ╭━╯ {WHITE}▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄{GOLD} ╰━╮
28
+ ╭━╯ {WHITE}▄████████████████▄{GOLD} ╰━╮
29
+ ╭╯ {WHITE}▄██▀▀▀▀▀▀▀▀▀▀▀▀▀██▄{GOLD} ╰╮
30
+ ╭╯ {WHITE}███ ▄▄▄ ▄▄▄ ███{GOLD} ╰╮
31
+ ┃ {WHITE}████ ▀▄▄▀ ▀▄▄▀ ████{GOLD} ┃
32
+ ┃ {WHITE}████ ████{GOLD} ┃
33
+ ┃ {WHITE}████ ▄ ▄ ████{GOLD} ┃
34
+ ┃ {WHITE}███ ▀▄▄▄▄▄▀ ███{GOLD} ┃
35
+ ╰╮ {WHITE}███▄ ▄███{GOLD} ╭╯
36
+ ╰╮ {WHITE}▀████▄▄▄▄▄▄████▀{GOLD} ╭╯
37
+ ╰━╮ {WHITE}▀▀██████████▀▀{GOLD} ╭━╯
38
+ ╰━╮ ╭━╯
39
+ ╰━━━╮ ╭━━━╯
40
+ ╰━━━━━━━━━━━━━━━╯{RESET}
41
+ """
42
+
43
+ # ── Minimal banner for compact mode ────────────────────────────
44
+ BANNER_COMPACT = f"""{GOLD} ╭━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╮
45
+ ┃ {WHITE}{BOLD}◉ C R O W E L O G I C{RESET}{GOLD} ┃
46
+ ┃ {DIM}Universal AI Agent • gpt-oss-120b{RESET}{GOLD} ┃
47
+ ╰━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╯{RESET}"""
48
+
49
+ # ── Title text ──────────────────────────────────────────────────
50
+ TITLE = f"""{GOLD}{BOLD}
51
+ ██████╗██████╗ ██████╗ ██╗ ██╗███████╗
52
+ ██╔════╝██╔══██╗██╔═══██╗██║ ██║██╔════╝
53
+ ██║ ██████╔╝██║ ██║██║ █╗ ██║█████╗
54
+ ██║ ██╔══██╗██║ ██║██║███╗██║██╔══╝
55
+ ╚██████╗██║ ██║╚██████╔╝╚███╔███╔╝███████╗
56
+ ╚═════╝╚═╝ ╚═╝ ╚═════╝ ╚══╝╚══╝ ╚══════╝
57
+ {DIM}L O G I C{RESET}{GOLD} {DIM}v0.1.0{RESET}
58
+ """
59
+
60
+ # ── Full welcome screen ────────────────────────────────────────
61
+ def welcome_screen(model: str = "gpt-oss-120b", version: str = "0.1.0"):
62
+ """Return the full welcome screen string."""
63
+ return f"""{GOLD}{BOLD}
64
+ ██████╗██████╗ ██████╗ ██╗ ██╗███████╗
65
+ ██╔════╝██╔══██╗██╔═══██╗██║ ██║██╔════╝
66
+ ██║ ██████╔╝██║ ██║██║ █╗ ██║█████╗
67
+ ██║ ██╔══██╗██║ ██║██║███╗██║██╔══╝
68
+ ╚██████╗██║ ██║╚██████╔╝╚███╔███╔╝███████╗
69
+ ╚═════╝╚═╝ ╚═╝ ╚═════╝ ╚══╝╚══╝ ╚══════╝
70
+ {RESET}{GOLD}{DIM}L O G I C{RESET}
71
+
72
+ {DIM}Model: {RESET}{WHITE}{model}{RESET}
73
+ {DIM}Platform: {RESET}{WHITE}Azure AI Foundry{RESET}
74
+ {DIM}Tools: {RESET}{WHITE}29 function tools + code interpreter{RESET}
75
+ {DIM}Version: {RESET}{WHITE}{version}{RESET}
76
+
77
+ {DIM}Type naturally. The agent auto-selects tools.{RESET}
78
+ {DIM}Commands: /exit /tools /status /clear{RESET}
79
+ {GOLD} {'━' * 52}{RESET}
80
+ """
81
+
82
+
83
+ def prompt_string() -> str:
84
+ """Return the styled prompt string for input."""
85
+ return f"{GOLD}{BOLD}you {PROMPT_ICON}{RESET} "
86
+
87
+
88
+ def agent_prefix() -> str:
89
+ """Return the styled prefix for agent responses."""
90
+ return f"{GOLD}{BOLD}crowe-logic {PROMPT_ICON}{RESET} "
91
+
92
+
93
+ # ── iTerm2 inline image protocol ───────────────────────────────
94
+ def show_inline_image(path: str, width: int = 10):
95
+ """Display the icon inline in iTerm2/compatible terminals."""
96
+ import base64
97
+ if not os.path.exists(path):
98
+ return
99
+ term = os.environ.get("TERM_PROGRAM", "")
100
+ if term not in ("iTerm.app", "WezTerm", "ghostty"):
101
+ return # Only works in supported terminals
102
+ with open(path, "rb") as f:
103
+ data = base64.b64encode(f.read()).decode()
104
+ # iTerm2 inline image escape sequence
105
+ print(f"\033]1337;File=inline=1;width={width};preserveAspectRatio=1:{data}\a")
@@ -0,0 +1,268 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Crowe Logic CLI — Universal AI Agent
4
+
5
+ Usage:
6
+ crowe-logic chat # Interactive chat session
7
+ crowe-logic run "your prompt" # Single prompt, get response
8
+ crowe-logic deploy # Create/recreate the agent
9
+ crowe-logic status # Show agent status
10
+ crowe-logic tools # List available tools
11
+ """
12
+
13
+ import os
14
+ import sys
15
+ import json
16
+ import time
17
+
18
+ # Add project root to path
19
+ PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
20
+ sys.path.insert(0, PROJECT_ROOT)
21
+
22
+ import click
23
+ from rich.console import Console
24
+ from rich.markdown import Markdown
25
+ from rich.panel import Panel
26
+ from rich.text import Text
27
+
28
+ from dotenv import load_dotenv
29
+ load_dotenv(os.path.join(PROJECT_ROOT, ".env"))
30
+
31
+ from cli.branding import (
32
+ welcome_screen, prompt_string, agent_prefix,
33
+ show_inline_image, BANNER_COMPACT, PROMPT_ICON, GOLD, RESET, BOLD,
34
+ )
35
+
36
+ console = Console()
37
+
38
+ ICON_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), "icon.png")
39
+
40
+ AGENT_ID_FILE = os.path.join(PROJECT_ROOT, ".agent_id")
41
+
42
+
43
+ def get_agent_id() -> str:
44
+ """Load saved agent ID from .agent_id file."""
45
+ if not os.path.exists(AGENT_ID_FILE):
46
+ console.print("[red]No agent found. Run: crowe-logic deploy[/red]")
47
+ sys.exit(1)
48
+ with open(AGENT_ID_FILE) as f:
49
+ data = json.load(f)
50
+ return data["agent_id"]
51
+
52
+
53
+ def get_client():
54
+ """Create and return an AgentsClient."""
55
+ from azure.ai.agents import AgentsClient
56
+ from azure.identity import DefaultAzureCredential
57
+ from config.agent_config import PROJECT_ENDPOINT
58
+
59
+ return AgentsClient(
60
+ endpoint=PROJECT_ENDPOINT,
61
+ credential=DefaultAzureCredential(),
62
+ )
63
+
64
+
65
+ def setup_toolset(client):
66
+ """Configure the toolset with auto function calling."""
67
+ from azure.ai.agents.models import FunctionTool, ToolSet, CodeInterpreterTool
68
+ from tools import user_functions
69
+
70
+ toolset = ToolSet()
71
+ toolset.add(FunctionTool(user_functions))
72
+ toolset.add(CodeInterpreterTool())
73
+ client.enable_auto_function_calls(toolset)
74
+ return toolset
75
+
76
+
77
+ def stream_response(client, thread_id: str, agent_id: str):
78
+ """Stream agent response with rich formatting."""
79
+ from azure.ai.agents.models import MessageDeltaChunk, ThreadMessage, ThreadRun, RunStep, AgentStreamEvent
80
+
81
+ full_text = ""
82
+
83
+ with client.runs.stream(thread_id=thread_id, agent_id=agent_id) as stream:
84
+ for event_type, event_data, _ in stream:
85
+ if isinstance(event_data, MessageDeltaChunk):
86
+ if event_data.text:
87
+ console.print(event_data.text, end="")
88
+ full_text += event_data.text
89
+
90
+ elif isinstance(event_data, ThreadRun):
91
+ if event_data.status == "failed":
92
+ console.print(f"\n[red]Run failed: {event_data.last_error}[/red]")
93
+
94
+ elif isinstance(event_data, RunStep):
95
+ if event_data.type == "tool_calls" and event_data.status == "in_progress":
96
+ console.print("\n[dim] (calling tools...)[/dim]", end="")
97
+
98
+ elif event_type == AgentStreamEvent.ERROR:
99
+ console.print(f"\n[red]Error: {event_data}[/red]")
100
+
101
+ elif event_type == AgentStreamEvent.DONE:
102
+ break
103
+
104
+ console.print() # Final newline
105
+ return full_text
106
+
107
+
108
+ @click.group()
109
+ @click.version_option(version="0.1.0", prog_name="crowe-logic")
110
+ def main():
111
+ """Crowe Logic — Universal AI Agent powered by gpt-oss-120b"""
112
+ pass
113
+
114
+
115
+ @main.command()
116
+ def chat():
117
+ """Start an interactive chat session with the agent."""
118
+ from prompt_toolkit import PromptSession
119
+ from prompt_toolkit.history import FileHistory
120
+
121
+ agent_id = get_agent_id()
122
+ client = get_client()
123
+ setup_toolset(client)
124
+
125
+ # Create a thread for this session
126
+ thread = client.threads.create()
127
+
128
+ # Show inline image in supported terminals (iTerm2, WezTerm, Ghostty)
129
+ show_inline_image(ICON_PATH, width=8)
130
+
131
+ # Print the branded welcome screen
132
+ print(welcome_screen())
133
+
134
+
135
+ history_file = os.path.join(PROJECT_ROOT, ".chat_history")
136
+ session = PromptSession(history=FileHistory(history_file))
137
+
138
+ while True:
139
+ try:
140
+ user_input = session.prompt(prompt_string(), multiline=False)
141
+ except (EOFError, KeyboardInterrupt):
142
+ print(f"\n{GOLD}{BOLD}Goodbye.{RESET}")
143
+ break
144
+
145
+ user_input = user_input.strip()
146
+ if not user_input:
147
+ continue
148
+ if user_input.lower() in ("exit", "quit", "/exit", "/quit"):
149
+ print(f"{GOLD}{BOLD}Goodbye.{RESET}")
150
+ break
151
+
152
+ # Handle CLI meta-commands
153
+ if user_input.lower() == "/tools":
154
+ _list_tools_inline()
155
+ continue
156
+ if user_input.lower() == "/clear":
157
+ console.clear()
158
+ print(welcome_screen())
159
+ continue
160
+ if user_input.lower() == "/status":
161
+ _show_status_inline()
162
+ continue
163
+
164
+ # Send message
165
+ client.messages.create(thread_id=thread.id, role="user", content=user_input)
166
+
167
+ # Stream response
168
+ console.print()
169
+ print(agent_prefix(), end="", flush=True)
170
+ stream_response(client, thread.id, agent_id)
171
+ console.print()
172
+
173
+
174
+ def _list_tools_inline():
175
+ """Show tools inside the chat session."""
176
+ from tools import user_functions
177
+ print(f"\n{GOLD}{'━' * 52}")
178
+ print(f" Available Tools ({len(user_functions)} custom + code interpreter){RESET}\n")
179
+ for func in sorted(user_functions, key=lambda f: f.__name__):
180
+ doc = (func.__doc__ or "").strip().split("\n")[0]
181
+ print(f" {GOLD}{func.__name__:25s}{RESET} {doc}")
182
+ print(f"\n{GOLD}{'━' * 52}{RESET}\n")
183
+
184
+
185
+ def _show_status_inline():
186
+ """Show status inside the chat session."""
187
+ if not os.path.exists(AGENT_ID_FILE):
188
+ print(f" {GOLD}Status:{RESET} No agent deployed")
189
+ return
190
+ with open(AGENT_ID_FILE) as f:
191
+ data = json.load(f)
192
+ print(f"\n{GOLD}{'━' * 52}{RESET}")
193
+ print(f" {GOLD}Agent ID:{RESET} {data.get('agent_id', 'unknown')}")
194
+ print(f" {GOLD}Name:{RESET} {data.get('name', 'unknown')}")
195
+ print(f" {GOLD}Model:{RESET} {data.get('model', 'unknown')}")
196
+ print(f" {GOLD}Version:{RESET} {data.get('version', 'unknown')}")
197
+ print(f"{GOLD}{'━' * 52}{RESET}\n")
198
+
199
+
200
+ @main.command()
201
+ @click.argument("prompt")
202
+ def run(prompt: str):
203
+ """Run a single prompt and print the response."""
204
+ agent_id = get_agent_id()
205
+ client = get_client()
206
+ setup_toolset(client)
207
+
208
+ thread = client.threads.create()
209
+ client.messages.create(thread_id=thread.id, role="user", content=prompt)
210
+
211
+ stream_response(client, thread.id, agent_id)
212
+
213
+
214
+ @main.command()
215
+ @click.option("--name", default="crowe-logic", help="Agent name")
216
+ def deploy(name: str):
217
+ """Create or recreate the Crowe Logic agent."""
218
+ from scripts.create_agent import create_agent
219
+ create_agent(name=name, verbose=True)
220
+
221
+
222
+ @main.command()
223
+ def status():
224
+ """Show current agent status."""
225
+ if not os.path.exists(AGENT_ID_FILE):
226
+ console.print("[red]No agent deployed. Run: crowe-logic deploy[/red]")
227
+ return
228
+
229
+ with open(AGENT_ID_FILE) as f:
230
+ data = json.load(f)
231
+
232
+ console.print(Panel(
233
+ Text.from_markup(
234
+ f"[bold cyan]CROWE LOGIC STATUS[/bold cyan]\n\n"
235
+ f"[bold]Agent ID:[/bold] {data.get('agent_id', 'unknown')}\n"
236
+ f"[bold]Name:[/bold] {data.get('name', 'unknown')}\n"
237
+ f"[bold]Version:[/bold] {data.get('version', 'unknown')}\n"
238
+ f"[bold]Model:[/bold] {data.get('model', 'unknown')}"
239
+ ),
240
+ border_style="cyan",
241
+ padding=(1, 2),
242
+ ))
243
+
244
+
245
+ @main.command()
246
+ def tools():
247
+ """List all available tools."""
248
+ from tools import user_functions
249
+
250
+ console.print(Panel("[bold cyan]CROWE LOGIC — AVAILABLE TOOLS[/bold cyan]", border_style="cyan"))
251
+ console.print()
252
+
253
+ # Custom function tools
254
+ console.print("[bold]Custom Function Tools:[/bold]")
255
+ for func in sorted(user_functions, key=lambda f: f.__name__):
256
+ doc = (func.__doc__ or "").strip().split("\n")[0]
257
+ console.print(f" [cyan]{func.__name__:25s}[/cyan] {doc}")
258
+
259
+ console.print()
260
+ console.print("[bold]Built-in Azure Tools:[/bold]")
261
+ console.print(f" [cyan]{'code_interpreter':25s}[/cyan] Run Python code in a sandboxed environment")
262
+ console.print(f" [cyan]{'bing_grounding':25s}[/cyan] Search the web via Bing (requires connection)")
263
+ console.print(f" [cyan]{'file_search':25s}[/cyan] RAG over uploaded documents (requires vector store)")
264
+ console.print(f" [cyan]{'azure_ai_search':25s}[/cyan] Vector search over knowledge base (requires index)")
265
+
266
+
267
+ if __name__ == "__main__":
268
+ main()
package/cli/icon.png ADDED
Binary file
File without changes
@@ -0,0 +1,54 @@
1
+ """
2
+ Crowe Logic Agent — Central Configuration
3
+
4
+ All agent settings, system instructions, and tool selection live here.
5
+ """
6
+
7
+ import os
8
+ from dotenv import load_dotenv
9
+
10
+ load_dotenv()
11
+
12
+ # Azure AI Foundry
13
+ PROJECT_ENDPOINT = os.environ.get("PROJECT_ENDPOINT", "https://crowelogicos-7858-resource.services.ai.azure.com/api/projects/crowelogicos-7858")
14
+ MODEL_DEPLOYMENT_NAME = os.environ.get("MODEL_DEPLOYMENT_NAME", "gpt-oss-120b")
15
+
16
+ # Connections (optional — leave empty to skip those tools)
17
+ BING_CONNECTION_ID = os.environ.get("AZURE_BING_CONNECTION_ID", "")
18
+ AI_SEARCH_CONNECTION_ID = os.environ.get("AI_AZURE_AI_CONNECTION_ID", "")
19
+ AI_SEARCH_INDEX_NAME = os.environ.get("AI_SEARCH_INDEX_NAME", "crowe-logic-kb")
20
+
21
+ # Azure
22
+ SUBSCRIPTION_ID = os.environ.get("AZURE_SUBSCRIPTION_ID", "")
23
+ RESOURCE_GROUP = os.environ.get("AZURE_RESOURCE_GROUP", "rg-crowelogicos-7858")
24
+
25
+ # Agent identity
26
+ AGENT_NAME = "crowe-logic"
27
+ AGENT_VERSION = "0.1.0"
28
+
29
+ SYSTEM_INSTRUCTIONS = """You are Crowe Logic, a universal AI agent created by Michael Crowe.
30
+
31
+ You can do anything and everything across all domains. You have access to tools for:
32
+ - Reading, writing, and editing files on the local filesystem
33
+ - Executing shell commands
34
+ - Searching the web for current information
35
+ - Browsing and fetching web pages
36
+ - Searching file contents with pattern matching
37
+ - Listing directory structures
38
+ - Running Python code via Code Interpreter
39
+ - Searching knowledge bases and vector stores
40
+
41
+ When given a task:
42
+ 1. Understand what's being asked — clarify if ambiguous
43
+ 2. Plan your approach — break complex tasks into steps
44
+ 3. Execute using the right tools — don't guess when you can look things up
45
+ 4. Verify your work — check outputs, run tests if applicable
46
+ 5. Report results concisely
47
+
48
+ You are direct, capable, and thorough. You don't hedge or over-explain.
49
+ You write clean, production-quality code. You think before you act.
50
+
51
+ You operate from: /Users/crowelogic
52
+ Current model: gpt-oss-120b (OpenAI open-weight, Apache 2.0)
53
+ Platform: Azure AI Foundry
54
+ """
package/npm/bin.js ADDED
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Crowe Logic CLI — npm wrapper
4
+ *
5
+ * Delegates to the Python CLI. Requires Python 3.10+ and pip.
6
+ * Usage: npx crowe-logic chat
7
+ */
8
+
9
+ const { execFileSync, spawn } = require("child_process");
10
+
11
+ const args = process.argv.slice(2);
12
+
13
+ // Check if crowe-logic is installed as a Python package
14
+ try {
15
+ execFileSync("crowe-logic", ["--version"], { stdio: "pipe" });
16
+ } catch {
17
+ console.log("Installing crowe-logic Python package...");
18
+ try {
19
+ execFileSync("pip", ["install", "crowe-logic"], { stdio: "inherit" });
20
+ } catch {
21
+ console.error(
22
+ "\nCrowe Logic requires Python 3.10+. Install via:\n" +
23
+ " pip install crowe-logic\n"
24
+ );
25
+ process.exit(1);
26
+ }
27
+ }
28
+
29
+ // Delegate to the Python CLI (no shell, no injection risk)
30
+ const child = spawn("crowe-logic", args, {
31
+ stdio: "inherit",
32
+ });
33
+
34
+ child.on("exit", (code) => process.exit(code || 0));
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "crowe-logic",
3
+ "version": "0.1.0",
4
+ "description": "Crowe Logic — Universal AI Agent powered by gpt-oss-120b on Azure AI Foundry",
5
+ "main": "npm/index.js",
6
+ "bin": {
7
+ "crowe-logic": "npm/bin.js"
8
+ },
9
+ "scripts": {
10
+ "start": "node npm/bin.js chat",
11
+ "test": "echo \"Error: no test specified\" && exit 1"
12
+ },
13
+ "keywords": ["ai", "agent", "azure", "llm", "biotech", "quantum", "tool-calling", "crowe-logic"],
14
+ "author": {
15
+ "name": "Michael Crowe",
16
+ "email": "michael@crowelogic.com",
17
+ "url": "https://crowelogic.com"
18
+ },
19
+ "license": "SEE LICENSE IN LICENSE",
20
+ "homepage": "https://crowelogic.com",
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/MichaelCrowe11/crowe-logic-foundry"
24
+ },
25
+ "type": "commonjs",
26
+ "dependencies": {
27
+ "@modelcontextprotocol/sdk": "^1.28.0",
28
+ "@modelcontextprotocol/server-filesystem": "^2026.1.14",
29
+ "@modelcontextprotocol/server-github": "^2025.4.8",
30
+ "@playwright/mcp": "^0.0.68"
31
+ }
32
+ }
package/pyproject.toml ADDED
@@ -0,0 +1,70 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "crowe-logic"
7
+ version = "0.1.0"
8
+ description = "Crowe Logic — Universal AI Agent powered by gpt-oss-120b on Azure AI Foundry"
9
+ readme = "README.md"
10
+ license = {text = "Proprietary"}
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ {name = "Michael Crowe", email = "michael@crowelogic.com"},
14
+ ]
15
+ maintainers = [
16
+ {name = "Michael Crowe", email = "michael@crowelogic.com"},
17
+ ]
18
+ keywords = ["ai", "agent", "azure", "llm", "biotech", "quantum", "tool-calling", "mycology", "mushroom"]
19
+ classifiers = [
20
+ "Development Status :: 3 - Alpha",
21
+ "Intended Audience :: Developers",
22
+ "Intended Audience :: Science/Research",
23
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
24
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
25
+ "Programming Language :: Python :: 3.10",
26
+ "Programming Language :: Python :: 3.11",
27
+ "Programming Language :: Python :: 3.12",
28
+ "Operating System :: MacOS",
29
+ "Operating System :: POSIX :: Linux",
30
+ ]
31
+ dependencies = [
32
+ "azure-ai-agents>=1.1.0",
33
+ "azure-identity>=1.17.0",
34
+ "click>=8.1.0",
35
+ "rich>=13.0.0",
36
+ "prompt-toolkit>=3.0.0",
37
+ "python-dotenv>=1.0.0",
38
+ "httpx>=0.27.0",
39
+ "beautifulsoup4>=4.12.0",
40
+ ]
41
+
42
+ [project.optional-dependencies]
43
+ quantum = [
44
+ "qiskit>=1.0.0",
45
+ "qiskit-aer>=0.15.0",
46
+ "cirq>=1.4.0",
47
+ "pennylane>=0.39.0",
48
+ "synapse-lang>=2.0.0",
49
+ "synapse-qubit-flow>=1.0.0",
50
+ ]
51
+ nvidia = [
52
+ "nvidia-cuda-runtime-cu12",
53
+ "cupy-cuda12x",
54
+ ]
55
+ all = [
56
+ "crowe-logic[quantum,nvidia]",
57
+ ]
58
+
59
+ [project.urls]
60
+ Homepage = "https://crowelogic.com"
61
+ Repository = "https://github.com/MichaelCrowe11/crowe-logic-foundry"
62
+
63
+ [project.scripts]
64
+ crowe-logic = "cli.crowe_logic:main"
65
+
66
+ [tool.setuptools.packages.find]
67
+ include = ["cli*", "tools*", "config*", "scripts*"]
68
+
69
+ [tool.setuptools.package-data]
70
+ cli = ["icon.png", "icons/*.icns"]