janet-cli 0.2.2__py3-none-any.whl
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.
- janet/__init__.py +3 -0
- janet/__main__.py +6 -0
- janet/api/__init__.py +0 -0
- janet/api/client.py +128 -0
- janet/api/models.py +92 -0
- janet/api/organizations.py +57 -0
- janet/api/projects.py +57 -0
- janet/api/tickets.py +125 -0
- janet/auth/__init__.py +0 -0
- janet/auth/callback_server.py +360 -0
- janet/auth/oauth_flow.py +276 -0
- janet/auth/token_manager.py +92 -0
- janet/cli.py +602 -0
- janet/config/__init__.py +0 -0
- janet/config/manager.py +116 -0
- janet/config/models.py +66 -0
- janet/markdown/__init__.py +0 -0
- janet/markdown/generator.py +272 -0
- janet/markdown/yjs_converter.py +225 -0
- janet/sync/__init__.py +0 -0
- janet/sync/file_manager.py +199 -0
- janet/sync/readme_generator.py +174 -0
- janet/sync/sync_engine.py +271 -0
- janet/utils/__init__.py +0 -0
- janet/utils/console.py +39 -0
- janet/utils/errors.py +49 -0
- janet/utils/paths.py +66 -0
- janet_cli-0.2.2.dist-info/METADATA +220 -0
- janet_cli-0.2.2.dist-info/RECORD +33 -0
- janet_cli-0.2.2.dist-info/WHEEL +5 -0
- janet_cli-0.2.2.dist-info/entry_points.txt +2 -0
- janet_cli-0.2.2.dist-info/licenses/LICENSE +21 -0
- janet_cli-0.2.2.dist-info/top_level.txt +1 -0
janet/utils/errors.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Custom exception classes for Janet CLI."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class JanetCLIError(Exception):
|
|
5
|
+
"""Base exception for all CLI errors."""
|
|
6
|
+
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AuthenticationError(JanetCLIError):
|
|
11
|
+
"""Authentication failed or token expired."""
|
|
12
|
+
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class OrganizationAccessError(JanetCLIError):
|
|
17
|
+
"""User doesn't have access to organization."""
|
|
18
|
+
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class NetworkError(JanetCLIError):
|
|
23
|
+
"""Network request failed."""
|
|
24
|
+
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ConfigurationError(JanetCLIError):
|
|
29
|
+
"""Invalid configuration."""
|
|
30
|
+
|
|
31
|
+
pass
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class SyncError(JanetCLIError):
|
|
35
|
+
"""Sync operation failed."""
|
|
36
|
+
|
|
37
|
+
pass
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class TokenExpiredError(AuthenticationError):
|
|
41
|
+
"""Access token has expired."""
|
|
42
|
+
|
|
43
|
+
pass
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class InvalidTokenError(AuthenticationError):
|
|
47
|
+
"""Invalid or malformed token."""
|
|
48
|
+
|
|
49
|
+
pass
|
janet/utils/paths.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Path utilities for Janet CLI."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from platformdirs import user_config_dir, user_data_dir
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def get_config_dir() -> Path:
|
|
9
|
+
"""Get configuration directory path."""
|
|
10
|
+
config_dir = Path(user_config_dir("janet-cli", appauthor=False))
|
|
11
|
+
config_dir.mkdir(parents=True, exist_ok=True)
|
|
12
|
+
return config_dir
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def get_data_dir() -> Path:
|
|
16
|
+
"""Get data directory path."""
|
|
17
|
+
data_dir = Path(user_data_dir("janet-cli", appauthor=False))
|
|
18
|
+
data_dir.mkdir(parents=True, exist_ok=True)
|
|
19
|
+
return data_dir
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_config_file() -> Path:
|
|
23
|
+
"""Get configuration file path."""
|
|
24
|
+
return get_config_dir() / "config.json"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def sanitize_filename(name: str) -> str:
|
|
28
|
+
"""
|
|
29
|
+
Sanitize a string to be safe for use as a filename.
|
|
30
|
+
|
|
31
|
+
Replaces invalid characters with hyphens and limits length.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
name: String to sanitize
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
Sanitized filename-safe string
|
|
38
|
+
"""
|
|
39
|
+
# Replace invalid filesystem characters with hyphens
|
|
40
|
+
invalid_chars = r'[<>:"/\\|?*]'
|
|
41
|
+
sanitized = re.sub(invalid_chars, "-", name)
|
|
42
|
+
|
|
43
|
+
# Remove leading/trailing whitespace and dots
|
|
44
|
+
sanitized = sanitized.strip(". ")
|
|
45
|
+
|
|
46
|
+
# Replace multiple consecutive hyphens with single hyphen
|
|
47
|
+
sanitized = re.sub(r"-+", "-", sanitized)
|
|
48
|
+
|
|
49
|
+
# Limit length to 255 characters (filesystem limit)
|
|
50
|
+
if len(sanitized) > 255:
|
|
51
|
+
sanitized = sanitized[:255].rstrip("-")
|
|
52
|
+
|
|
53
|
+
return sanitized if sanitized else "unnamed"
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def expand_path(path: str) -> Path:
|
|
57
|
+
"""
|
|
58
|
+
Expand user home directory and resolve path.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
path: Path string (may contain ~)
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
Resolved absolute Path
|
|
65
|
+
"""
|
|
66
|
+
return Path(path).expanduser().resolve()
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: janet-cli
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: CLI tool to sync Janet AI tickets to local markdown files
|
|
5
|
+
Author-email: Janet AI <support@janet-ai.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/janet-ai/janet-cli
|
|
8
|
+
Project-URL: Repository, https://github.com/janet-ai/janet-cli
|
|
9
|
+
Project-URL: Issues, https://github.com/janet-ai/janet-cli/issues
|
|
10
|
+
Keywords: cli,janet,tickets,markdown,sync
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Requires-Python: >=3.8
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: typer>=0.12.0
|
|
24
|
+
Requires-Dist: httpx>=0.27.0
|
|
25
|
+
Requires-Dist: pydantic>=2.0.0
|
|
26
|
+
Requires-Dist: pydantic-settings>=2.0.0
|
|
27
|
+
Requires-Dist: rich>=13.0.0
|
|
28
|
+
Requires-Dist: platformdirs>=4.0.0
|
|
29
|
+
Requires-Dist: keyring>=25.0.0
|
|
30
|
+
Requires-Dist: python-dateutil>=2.8.0
|
|
31
|
+
Requires-Dist: pycrdt>=0.9.0
|
|
32
|
+
Requires-Dist: InquirerPy>=0.3.4
|
|
33
|
+
Provides-Extra: dev
|
|
34
|
+
Requires-Dist: pytest>=8.0.0; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
|
|
37
|
+
Requires-Dist: httpx-mock>=0.15.0; extra == "dev"
|
|
38
|
+
Requires-Dist: black>=24.0.0; extra == "dev"
|
|
39
|
+
Requires-Dist: mypy>=1.8.0; extra == "dev"
|
|
40
|
+
Requires-Dist: ruff>=0.2.0; extra == "dev"
|
|
41
|
+
Dynamic: license-file
|
|
42
|
+
|
|
43
|
+
# Janet AI CLI
|
|
44
|
+
|
|
45
|
+
> Sync your Janet AI tickets to local markdown files for seamless integration with AI coding agents.
|
|
46
|
+
|
|
47
|
+
[](https://opensource.org/licenses/MIT)
|
|
48
|
+
[](https://www.python.org/downloads/)
|
|
49
|
+
|
|
50
|
+
## What is Janet AI?
|
|
51
|
+
|
|
52
|
+
[Janet AI](https://tryjanet.ai) is an AI-native project management platform for modern software teams. The Janet CLI allows developers to sync their tickets locally as markdown files, enabling AI coding assistants like Claude Code, Cursor, and GitHub Copilot to have full project context.
|
|
53
|
+
|
|
54
|
+
## Why Use the CLI?
|
|
55
|
+
|
|
56
|
+
AI coding assistants work better when they understand your project's tickets, requirements, and priorities. By syncing Janet AI tickets to your workspace, AI agents can:
|
|
57
|
+
|
|
58
|
+
- Reference specific tickets while writing code
|
|
59
|
+
- Understand requirements and acceptance criteria
|
|
60
|
+
- Answer questions about project priorities
|
|
61
|
+
- Suggest implementations based on ticket descriptions
|
|
62
|
+
|
|
63
|
+
## Installation
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install janet-cli
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Quick Start
|
|
70
|
+
|
|
71
|
+
### 1. Authenticate
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
janet login
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 2. Sync Tickets
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
janet sync
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 3. Use with AI Agents
|
|
84
|
+
|
|
85
|
+
Your tickets are now available as markdown files! Point your AI coding agent to the sync directory.
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# Example prompts for Claude Code, Cursor, etc:
|
|
89
|
+
"Look at ticket CS-42 and implement the authentication flow"
|
|
90
|
+
"What are the high priority tickets in the Backend project?"
|
|
91
|
+
"Implement the feature described in PROJ-15"
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Usage
|
|
95
|
+
|
|
96
|
+
### Basic Commands
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Authentication
|
|
100
|
+
janet login # Authenticate with Janet AI
|
|
101
|
+
janet logout # Clear credentials
|
|
102
|
+
janet auth status # Show authentication status
|
|
103
|
+
|
|
104
|
+
# Organization Management
|
|
105
|
+
janet org list # List your organizations
|
|
106
|
+
janet org select <org-id> # Switch organization
|
|
107
|
+
|
|
108
|
+
# Project Management
|
|
109
|
+
janet project list # List projects in current org
|
|
110
|
+
|
|
111
|
+
# Syncing
|
|
112
|
+
janet sync # Interactive mode
|
|
113
|
+
janet sync --all # Sync all projects (skip selection)
|
|
114
|
+
janet sync --dir ./tickets # Specify custom directory
|
|
115
|
+
|
|
116
|
+
# Status & Configuration
|
|
117
|
+
janet status # Show overall status
|
|
118
|
+
janet config show # Display configuration
|
|
119
|
+
janet --help # Show help
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Example Workflow
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# First time setup
|
|
126
|
+
janet login
|
|
127
|
+
janet sync
|
|
128
|
+
|
|
129
|
+
# Re-sync to get updates
|
|
130
|
+
janet sync
|
|
131
|
+
|
|
132
|
+
# Sync to specific directory
|
|
133
|
+
cd /path/to/my/project
|
|
134
|
+
janet sync --dir ./janet-tickets
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## File Organization
|
|
138
|
+
|
|
139
|
+
Tickets are organized in a clear hierarchy:
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
janet-tickets/
|
|
143
|
+
├── README.md # Context for AI agents
|
|
144
|
+
└── My Organization/
|
|
145
|
+
├── Backend/
|
|
146
|
+
│ ├── BACK-1.md
|
|
147
|
+
│ ├── BACK-2.md
|
|
148
|
+
│ └── BACK-42.md
|
|
149
|
+
└── Frontend/
|
|
150
|
+
├── FRONT-1.md
|
|
151
|
+
└── FRONT-15.md
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Markdown Format
|
|
155
|
+
|
|
156
|
+
Each ticket is exported with complete information:
|
|
157
|
+
|
|
158
|
+
```markdown
|
|
159
|
+
# PROJ-42: Add user authentication
|
|
160
|
+
|
|
161
|
+
## Metadata
|
|
162
|
+
- **Status:** In Progress
|
|
163
|
+
- **Priority:** High
|
|
164
|
+
- **Type:** Feature
|
|
165
|
+
- **Assignees:** John Doe, Jane Smith
|
|
166
|
+
- **Created:** Jan 07, 2026 10:30 AM
|
|
167
|
+
- **Updated:** Jan 07, 2026 02:45 PM
|
|
168
|
+
- **Labels:** backend, security
|
|
169
|
+
|
|
170
|
+
## Description
|
|
171
|
+
|
|
172
|
+
We need to implement OAuth authentication...
|
|
173
|
+
|
|
174
|
+
### Requirements
|
|
175
|
+
- Support multiple auth providers
|
|
176
|
+
- Handle token refresh
|
|
177
|
+
- Secure token storage
|
|
178
|
+
|
|
179
|
+
## Comments (2)
|
|
180
|
+
|
|
181
|
+
### John Doe - Jan 07, 2026 11:00 AM
|
|
182
|
+
|
|
183
|
+
Started working on the OAuth flow.
|
|
184
|
+
|
|
185
|
+
### Jane Smith - Jan 07, 2026 01:30 PM
|
|
186
|
+
|
|
187
|
+
Looks good! Add tests when done.
|
|
188
|
+
|
|
189
|
+
## Attachments (1)
|
|
190
|
+
|
|
191
|
+
### design-mockup.png
|
|
192
|
+
- **Type:** image/png
|
|
193
|
+
- **Uploaded by:** Jane Smith
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Configuration
|
|
197
|
+
|
|
198
|
+
The CLI stores configuration at:
|
|
199
|
+
- **macOS/Linux:** `~/.config/janet-cli/config.json`
|
|
200
|
+
- **Windows:** `%APPDATA%\janet-cli\config.json`
|
|
201
|
+
|
|
202
|
+
Configuration includes authentication tokens and your selected organization.
|
|
203
|
+
|
|
204
|
+
## Requirements
|
|
205
|
+
|
|
206
|
+
- Python 3.8 or higher
|
|
207
|
+
- Janet AI account ([sign up](https://tryjanet.ai))
|
|
208
|
+
|
|
209
|
+
## License
|
|
210
|
+
|
|
211
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
212
|
+
|
|
213
|
+
## Acknowledgments
|
|
214
|
+
|
|
215
|
+
Built for [Janet AI](https://tryjanet.ai) - The AI-native project management platform backed by Y Combinator.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
**Current Version:** 0.2.0
|
|
220
|
+
**Status:** Production Ready ✅
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
janet/__init__.py,sha256=Bk05WAYOzsZs3TKPbv1UYe-sbc5J60ppx0B3iwuG5v4,82
|
|
2
|
+
janet/__main__.py,sha256=nxsNRykF1aXRRSYNcMvohre4QDfpUzyr5JMyHRHWrwI,130
|
|
3
|
+
janet/cli.py,sha256=AxjY76l5d7NnsaYEEvUP4dJ1LxXsY1Ya-uNaTGSfXd8,20391
|
|
4
|
+
janet/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
janet/api/client.py,sha256=fiIpCaQlvXBn_T2VGf0sT9jyQE83Xx7o_WJkCDnwykY,4399
|
|
6
|
+
janet/api/models.py,sha256=41or0kCcEJ3KJ2QCdV1xbrAoAcma_DteqqVlO0Ng18g,2002
|
|
7
|
+
janet/api/organizations.py,sha256=abaita6e2drm6RikTOfU-E1ohPeRPhiTYmWRFG0kqaQ,1539
|
|
8
|
+
janet/api/projects.py,sha256=Oxao4vvXMuXWMfUwZUuBrhkSUtC8t57FNc2d6Qzd5ms,1488
|
|
9
|
+
janet/api/tickets.py,sha256=k8EKrShdRVmevNbZahchJI_0iiHosP1QLCWfyFsXGxo,3346
|
|
10
|
+
janet/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
11
|
+
janet/auth/callback_server.py,sha256=mLkkQMMN6PnNUFf4mlQyY3eKOgK1W6_9O9u90xsLMhY,12499
|
|
12
|
+
janet/auth/oauth_flow.py,sha256=YaLQVRXyhAvZ3IWkd3AvjQlCkQgRRjhPEU9fXfZBgko,9133
|
|
13
|
+
janet/auth/token_manager.py,sha256=YxqSmIRiueGYmDxvPeRt--dLpXSfeFd61qCW91FTujU,2721
|
|
14
|
+
janet/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
+
janet/config/manager.py,sha256=Bs5YjHIzWPR-KuAFJyQL47ntU_JN87bGhROaYP0B3r4,3216
|
|
16
|
+
janet/config/models.py,sha256=2ZLAgM5CwuwQF0C0mZGjxrJO_ECgDGCQ6rnOg68sBp0,1741
|
|
17
|
+
janet/markdown/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
+
janet/markdown/generator.py,sha256=CgjvCjkna7XsigsrurdSnAXVPYajLQjlP8puuKkSTVM,9168
|
|
19
|
+
janet/markdown/yjs_converter.py,sha256=omoT6dZ0K3UIoSun2fczTw56vbTrHomz64no3U0YUwo,8482
|
|
20
|
+
janet/sync/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
+
janet/sync/file_manager.py,sha256=fwV0VYP-0ZpwTAyDVqlVUPn3MB2wK6TvFQq450Lhr0I,5839
|
|
22
|
+
janet/sync/readme_generator.py,sha256=RHfqlr-3oyGIy5zRbMcloAo1rrwy5aSqAvleC49QZME,6847
|
|
23
|
+
janet/sync/sync_engine.py,sha256=4WEQ6wmcwTWg1cZurQCZTcSBZhKkUtw4eBKUsAcL6WY,9779
|
|
24
|
+
janet/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
|
+
janet/utils/console.py,sha256=zMhX4HUXSco-or9KpqBJmYCzmfH_GWtvq-n2Sy6Dfgc,927
|
|
26
|
+
janet/utils/errors.py,sha256=yxoVDF7ovMT7ooJA-8cvxJK8_3nWumGv7s1n8povi-4,783
|
|
27
|
+
janet/utils/paths.py,sha256=JYp5gcSEjIbYNJaUcAwdpz6rmta9m0JzoBARC6_AWmM,1706
|
|
28
|
+
janet_cli-0.2.2.dist-info/licenses/LICENSE,sha256=wNChlibp2El7r-zfLH8QhOg2oLPAvGwP7ETnVWyNRio,1065
|
|
29
|
+
janet_cli-0.2.2.dist-info/METADATA,sha256=8121OXbTb0ZXUbkZ5h0jrNYbCxK8i3I_EvKy3onIgq0,5941
|
|
30
|
+
janet_cli-0.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
31
|
+
janet_cli-0.2.2.dist-info/entry_points.txt,sha256=MeYUkStK_xcqW3AylPNpQh_H5zmfojB1-d8WMhifkvw,40
|
|
32
|
+
janet_cli-0.2.2.dist-info/top_level.txt,sha256=Ux5zWeRoPO3Tu87toTRoiwMkIQNQylV9aRO2g7KqNW4,6
|
|
33
|
+
janet_cli-0.2.2.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Janet AI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
janet
|