mirror of
https://github.com/danielmiessler/Fabric.git
synced 2026-01-09 22:38:10 -05:00
Compare commits
476 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
832fd2f718 | ||
|
|
dd0935fb70 | ||
|
|
e64bdd849c | ||
|
|
be82b4b013 | ||
|
|
6e2f00090c | ||
|
|
2c2b374664 | ||
|
|
b884c529bd | ||
|
|
137aff2268 | ||
|
|
42d3f45c57 | ||
|
|
f8ada0b148 | ||
|
|
cb5fa50f68 | ||
|
|
921d12a153 | ||
|
|
725c6f9327 | ||
|
|
9a64238f18 | ||
|
|
af318aca17 | ||
|
|
4d7bc7deb8 | ||
|
|
da1336e8cb | ||
|
|
81adb3b050 | ||
|
|
ebc59ee82a | ||
|
|
e242e0fc52 | ||
|
|
4004c51b9e | ||
|
|
6d67223a4b | ||
|
|
265f2b807e | ||
|
|
dc63e0d1cc | ||
|
|
75842d8610 | ||
|
|
bcd4c6caea | ||
|
|
a6a63698e1 | ||
|
|
0528556b5c | ||
|
|
47cf24e19d | ||
|
|
3f07afbef4 | ||
|
|
38d714dccd | ||
|
|
d0b5c95d61 | ||
|
|
f8f80ca206 | ||
|
|
0af458872f | ||
|
|
24e46a6f37 | ||
|
|
d6a31e68b0 | ||
|
|
b1013ca61b | ||
|
|
6b4ce946a5 | ||
|
|
2d2830e9c8 | ||
|
|
115327fdab | ||
|
|
e672f9b73f | ||
|
|
ef4364a1aa | ||
|
|
cb3f8ed43d | ||
|
|
4c1803cb6d | ||
|
|
d1c614d44e | ||
|
|
dbaa0b9754 | ||
|
|
4cfe2375ab | ||
|
|
2b371b69c7 | ||
|
|
6222a613e4 | ||
|
|
0882c43532 | ||
|
|
f0e1a1b77f | ||
|
|
a774f991ab | ||
|
|
a40bacaf34 | ||
|
|
969b85380c | ||
|
|
e8fe4434db | ||
|
|
7c7ceca264 | ||
|
|
c19d7ccd9d | ||
|
|
bd0c5f730e | ||
|
|
5900dac58f | ||
|
|
237219c3cc | ||
|
|
26fd700098 | ||
|
|
6bd926dd0f | ||
|
|
16ac519415 | ||
|
|
a32cc5fa01 | ||
|
|
26b5bb2e9e | ||
|
|
b751d323b1 | ||
|
|
d081fd269c | ||
|
|
369a0a850d | ||
|
|
8dc5343ee6 | ||
|
|
eda552dac5 | ||
|
|
f13a56685b | ||
|
|
2f9afe0247 | ||
|
|
1ec525ad97 | ||
|
|
b7dc6748e0 | ||
|
|
f1b612d828 | ||
|
|
eac5a104f2 | ||
|
|
4bff88fae3 | ||
|
|
acf1be71ce | ||
|
|
236a3c5f38 | ||
|
|
b2418984f8 | ||
|
|
152d74d160 | ||
|
|
4e16bbccd8 | ||
|
|
60174f41a4 | ||
|
|
ad4683952e | ||
|
|
86a044735b | ||
|
|
58583114cb | ||
|
|
36524cd2e4 | ||
|
|
e59156ac2b | ||
|
|
1eac026e92 | ||
|
|
17d863fd57 | ||
|
|
7c9dbfd343 | ||
|
|
d9260bdf26 | ||
|
|
63a0cfeb1e | ||
|
|
12fc6e2000 | ||
|
|
fe5900a5dc | ||
|
|
1b6b8e3d72 | ||
|
|
c85301cb1f | ||
|
|
7cc8226339 | ||
|
|
fc8c4babf8 | ||
|
|
bd809a1f94 | ||
|
|
50aec6291b | ||
|
|
f927fdf40f | ||
|
|
918862ef57 | ||
|
|
d9b8bc3233 | ||
|
|
da29b8e388 | ||
|
|
5e6d4110fa | ||
|
|
4bb090694b | ||
|
|
d232222787 | ||
|
|
a43f267a69 | ||
|
|
c78fe41ebc | ||
|
|
cab246bc74 | ||
|
|
50c05e2d5c | ||
|
|
095890a556 | ||
|
|
64c1fe18ef | ||
|
|
1cea32a677 | ||
|
|
49658a3214 | ||
|
|
f236cab276 | ||
|
|
5e0aaa1f93 | ||
|
|
eb16806931 | ||
|
|
474dd786a4 | ||
|
|
edad63df19 | ||
|
|
c7eb7439ef | ||
|
|
23d678d62f | ||
|
|
de5260a661 | ||
|
|
baeadc2270 | ||
|
|
5b4cec81c3 | ||
|
|
eda5531087 | ||
|
|
66925d188a | ||
|
|
6179742e79 | ||
|
|
d8fc6940f0 | ||
|
|
44f7e8dfef | ||
|
|
c5ada714ff | ||
|
|
80c4807f7e | ||
|
|
b4126b6798 | ||
|
|
f2ffa64af9 | ||
|
|
09e01eddf4 | ||
|
|
aa028a4a57 | ||
|
|
d8d157404c | ||
|
|
d0602c9653 | ||
|
|
35155496a4 | ||
|
|
eef16b89f2 | ||
|
|
7f66097577 | ||
|
|
2012f22a9c | ||
|
|
08695c9e24 | ||
|
|
d8cc9b5eef | ||
|
|
9dbe20cf7b | ||
|
|
64763e1303 | ||
|
|
126a9ff406 | ||
|
|
e906425138 | ||
|
|
df4a560302 | ||
|
|
34cf669bd4 | ||
|
|
0dbe1bbb4e | ||
|
|
e29ed908e6 | ||
|
|
3d049a435a | ||
|
|
1a335b3fb9 | ||
|
|
e2430b6c75 | ||
|
|
2497f10eca | ||
|
|
f62d2198f9 | ||
|
|
816e4072f4 | ||
|
|
85ee6196bd | ||
|
|
e15645c1bc | ||
|
|
fada6bb044 | ||
|
|
4ad14bb752 | ||
|
|
97fc9b0d58 | ||
|
|
ad0df37d10 | ||
|
|
666302c3c1 | ||
|
|
71e20cf251 | ||
|
|
b591666366 | ||
|
|
155d9f0a76 | ||
|
|
6a7cca65b4 | ||
|
|
94020dbde0 | ||
|
|
f949391098 | ||
|
|
64c3c69a70 | ||
|
|
4a830394be | ||
|
|
9f8a2d3b59 | ||
|
|
4353bc9f7f | ||
|
|
7a8024ee79 | ||
|
|
b5bf75ad2e | ||
|
|
1ae847f397 | ||
|
|
3fd923f6b8 | ||
|
|
eb251139b8 | ||
|
|
0b5d3cfc30 | ||
|
|
14a3c11930 | ||
|
|
c8cf6da0cc | ||
|
|
a2c954ba50 | ||
|
|
730d0adc86 | ||
|
|
dc9168ab6f | ||
|
|
e500a5916e | ||
|
|
6ddf46a379 | ||
|
|
e8aa358b15 | ||
|
|
62f373c2b4 | ||
|
|
fcf826f3de | ||
|
|
bd2db29cee | ||
|
|
c6d612ee9a | ||
|
|
d613c25974 | ||
|
|
c0abea7c66 | ||
|
|
496bd2812a | ||
|
|
70fccaf2fb | ||
|
|
9a71f7c96d | ||
|
|
5da3db383d | ||
|
|
19438cbd20 | ||
|
|
a0b71ee365 | ||
|
|
034513ece5 | ||
|
|
0affb9bab1 | ||
|
|
3305df8fb2 | ||
|
|
892c229076 | ||
|
|
599c5f2b9f | ||
|
|
19e5d8dbe0 | ||
|
|
b772127738 | ||
|
|
5dd61abe2a | ||
|
|
f45e140126 | ||
|
|
752a66cb48 | ||
|
|
da28d91d65 | ||
|
|
5a66ca1c5a | ||
|
|
98f3da610b | ||
|
|
73ce92ccd9 | ||
|
|
7f3f1d641f | ||
|
|
44b5c46beb | ||
|
|
8d37c9d6b9 | ||
|
|
1138d0b60e | ||
|
|
b78217088d | ||
|
|
76b889733d | ||
|
|
3911fd9f5d | ||
|
|
b06e29f8a8 | ||
|
|
11a7e542e1 | ||
|
|
6681078259 | ||
|
|
be1edf7b1d | ||
|
|
8ce748a1b1 | ||
|
|
96070f6f39 | ||
|
|
ca3e89a889 | ||
|
|
47d799d7ae | ||
|
|
4899ce56a5 | ||
|
|
4a7b7becec | ||
|
|
80fdccbe89 | ||
|
|
d9d8f7bf96 | ||
|
|
a96ddbeef0 | ||
|
|
d32a1d6a5a | ||
|
|
201474791d | ||
|
|
6d09137fee | ||
|
|
680febbe66 | ||
|
|
f59e5081f3 | ||
|
|
6a504c7422 | ||
|
|
89a0abcbe4 | ||
|
|
2dfd78ef0b | ||
|
|
2200b6ea08 | ||
|
|
82f9ebaf99 | ||
|
|
704ad3067a | ||
|
|
6f7e3c04d7 | ||
|
|
79f763456e | ||
|
|
9d4f7f1571 | ||
|
|
8e7373b308 | ||
|
|
7a39742507 | ||
|
|
cea218e61e | ||
|
|
02ac68834d | ||
|
|
f673f424da | ||
|
|
0ae41116aa | ||
|
|
2b11f3e48e | ||
|
|
ed77cc2320 | ||
|
|
29f19fce51 | ||
|
|
62ed5d2b9a | ||
|
|
836e4c4fab | ||
|
|
946c1af42d | ||
|
|
a74585cb14 | ||
|
|
5ffd458aa0 | ||
|
|
9786721037 | ||
|
|
ffb31985e8 | ||
|
|
eeee37a7cc | ||
|
|
bd89a8d776 | ||
|
|
2311e7e7a1 | ||
|
|
09b79283e9 | ||
|
|
7fbb5e0935 | ||
|
|
984d9d03f5 | ||
|
|
c47502fa8c | ||
|
|
1fe02bdf22 | ||
|
|
d550385a5e | ||
|
|
1e81da5f42 | ||
|
|
5b318dc402 | ||
|
|
4027305345 | ||
|
|
63879d5cf7 | ||
|
|
9539441496 | ||
|
|
352ade34c8 | ||
|
|
9abc69c1a9 | ||
|
|
93f6f2f0c4 | ||
|
|
1f5d3db3fb | ||
|
|
4446b456ba | ||
|
|
870941090a | ||
|
|
5fc004805e | ||
|
|
ce47018fc3 | ||
|
|
a09131ea72 | ||
|
|
36eb321059 | ||
|
|
47bf9600d6 | ||
|
|
be674841e7 | ||
|
|
39a8b67438 | ||
|
|
0a4950dd08 | ||
|
|
593c1558c0 | ||
|
|
c8f9a39a40 | ||
|
|
50ec02546f | ||
|
|
881085d0fe | ||
|
|
2d75052e57 | ||
|
|
fee604682b | ||
|
|
941ccabd92 | ||
|
|
57cd563963 | ||
|
|
274b6eada6 | ||
|
|
bc27f9d685 | ||
|
|
1291b35b63 | ||
|
|
9862564c45 | ||
|
|
bbc183f276 | ||
|
|
9c4445d7bd | ||
|
|
920620d771 | ||
|
|
d734e25e0d | ||
|
|
a31b2d5e41 | ||
|
|
8e7e4aa169 | ||
|
|
ea57a64afa | ||
|
|
da1a9dab56 | ||
|
|
068f111986 | ||
|
|
dd0be51726 | ||
|
|
43a1e66cc8 | ||
|
|
430a272e1d | ||
|
|
0e892f38e4 | ||
|
|
aa0fe90258 | ||
|
|
c59c7553b3 | ||
|
|
703756d0b0 | ||
|
|
50d22f8e77 | ||
|
|
fde2efd4ce | ||
|
|
0150c3a37d | ||
|
|
2a0216b9aa | ||
|
|
a6d14d86b8 | ||
|
|
a9374c128b | ||
|
|
f32b9f81da | ||
|
|
bf3af8e98e | ||
|
|
095c295ee5 | ||
|
|
93ecc9cfea | ||
|
|
e7aaa23fc2 | ||
|
|
197d3454f8 | ||
|
|
50a4f8b491 | ||
|
|
894b4967dd | ||
|
|
9837bd6664 | ||
|
|
6ca1b5dac4 | ||
|
|
c85135c04e | ||
|
|
31e4e42a94 | ||
|
|
196db04fc2 | ||
|
|
b3b1b5a471 | ||
|
|
892439a177 | ||
|
|
ba2e178e03 | ||
|
|
ed298bcedd | ||
|
|
6b04e6e674 | ||
|
|
04c0f6a0a5 | ||
|
|
486ff42b59 | ||
|
|
f7ab484510 | ||
|
|
f50a14305a | ||
|
|
d5f0cd7616 | ||
|
|
67c658f5b4 | ||
|
|
ef3bc03343 | ||
|
|
e31cb2b46a | ||
|
|
6ca7142ea4 | ||
|
|
8b2174897a | ||
|
|
ac5eab0563 | ||
|
|
65414dcc1c | ||
|
|
5db352f5be | ||
|
|
9e7830ff77 | ||
|
|
5945c0e16b | ||
|
|
29ee141822 | ||
|
|
8a69621e87 | ||
|
|
1645b0c4ea | ||
|
|
45205574d5 | ||
|
|
71a5e0394a | ||
|
|
f286936c23 | ||
|
|
9000f92a55 | ||
|
|
8c84d4b3c8 | ||
|
|
1d77afcc44 | ||
|
|
835bc6044b | ||
|
|
ef895a1ab9 | ||
|
|
82039cedaf | ||
|
|
973df61dfd | ||
|
|
661c85d7a6 | ||
|
|
4638f67fb7 | ||
|
|
ab71dbcd4f | ||
|
|
2abdabc100 | ||
|
|
9f78a2c8e1 | ||
|
|
76f78601f2 | ||
|
|
4eaba2dc56 | ||
|
|
2dcd9cb5f7 | ||
|
|
2943872bde | ||
|
|
b901542a48 | ||
|
|
c122ff8960 | ||
|
|
e128d818c4 | ||
|
|
5e9d6d0a91 | ||
|
|
70edf9cbe3 | ||
|
|
e61a0a9391 | ||
|
|
f8ddf98404 | ||
|
|
55219467f3 | ||
|
|
74d4be1ac6 | ||
|
|
9e57f8c6f1 | ||
|
|
3d2903cb47 | ||
|
|
13e9d22ec6 | ||
|
|
01d12c47cf | ||
|
|
c3258a2c3f | ||
|
|
746885e263 | ||
|
|
b25895c1d2 | ||
|
|
e40b1c1f66 | ||
|
|
ef2ec8bffe | ||
|
|
589991e6a6 | ||
|
|
965392ebbd | ||
|
|
6f615baf53 | ||
|
|
b60bad7799 | ||
|
|
234d1303ad | ||
|
|
cd74a96be2 | ||
|
|
ceaa90a7c7 | ||
|
|
15a2eeadc9 | ||
|
|
8d02f5b21d | ||
|
|
0f8f0b6b39 | ||
|
|
fd58b6d410 | ||
|
|
2579d37c16 | ||
|
|
4f28d85e96 | ||
|
|
f529b8bb80 | ||
|
|
71437605e1 | ||
|
|
cf5753a186 | ||
|
|
433c83fe2c | ||
|
|
01770cc6e3 | ||
|
|
55fda5e025 | ||
|
|
daad5f986e | ||
|
|
3785d0a5fa | ||
|
|
8a326e9cfb | ||
|
|
5f5822f1c6 | ||
|
|
111482e46e | ||
|
|
9b56e0e996 | ||
|
|
9b830f9801 | ||
|
|
dda73d3333 | ||
|
|
40c26d9c9e | ||
|
|
cdd86b0ed9 | ||
|
|
c2e84d6db9 | ||
|
|
4208a02191 | ||
|
|
943b26eeef | ||
|
|
d6ceae9efd | ||
|
|
f57dc6d681 | ||
|
|
4e4bfc9d5d | ||
|
|
ea137c1525 | ||
|
|
f0be1d4735 | ||
|
|
e3975b9364 | ||
|
|
cd48802ea0 | ||
|
|
dceccd8e72 | ||
|
|
0813ad9c39 | ||
|
|
e391132167 | ||
|
|
c7f86d3a0c | ||
|
|
f0d92f9424 | ||
|
|
4a9bdb1479 | ||
|
|
7eed80710e | ||
|
|
fbd62be47d | ||
|
|
85cc7b8a9d | ||
|
|
1fe8afd329 | ||
|
|
e89ccf5e97 | ||
|
|
0eee89140c | ||
|
|
5571e6fafd | ||
|
|
9a4e920618 | ||
|
|
6e479999b1 | ||
|
|
f65f2501b4 | ||
|
|
4b12bd2a61 | ||
|
|
d83a3beeeb | ||
|
|
7428c8017f | ||
|
|
008ed76d37 | ||
|
|
ce9d4ad831 | ||
|
|
657bcab48c | ||
|
|
cd11dcc7a9 | ||
|
|
22040a42f2 | ||
|
|
705ccd750b | ||
|
|
db7c2b70cb | ||
|
|
9dc9bfa1d5 | ||
|
|
6b93658191 | ||
|
|
ea7a425a26 | ||
|
|
9582978adb | ||
|
|
453d8e75e4 | ||
|
|
901a010efd | ||
|
|
b5c2d069f2 | ||
|
|
f744e25b39 | ||
|
|
096f40df68 | ||
|
|
a227e61952 |
59
.github/ISSUE_TEMPLATE/bug.yml
vendored
59
.github/ISSUE_TEMPLATE/bug.yml
vendored
@@ -7,29 +7,74 @@ body:
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report!
|
||||
Please provide as much detail as possible to help us understand and reproduce the issue.
|
||||
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Also tell us, what did you expect to happen?
|
||||
placeholder: Tell us what you see!
|
||||
value: "I was doing THIS, when THAT happened. I was expecting THAT_OTHER_THING to happen instead."
|
||||
value: "Please provide all the steps to reproduce the bug. I was doing THIS, when THAT happened. I was expecting THAT_OTHER_THING to happen instead."
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
|
||||
- type: dropdown
|
||||
id: os
|
||||
attributes:
|
||||
label: Operating System
|
||||
options:
|
||||
- macOS - Silicon (arm64)
|
||||
- macOS - Intel (amd64)
|
||||
- Linux - amd64
|
||||
- Linux - arm64
|
||||
- Windows
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: os-version
|
||||
attributes:
|
||||
label: OS Version
|
||||
description: Please provide details about your OS version by running one of the following commands.
|
||||
placeholder: |
|
||||
macOS: `sw_vers`
|
||||
Linux: `uname -a` or `cat /etc/os-release`
|
||||
Windows: `ver`
|
||||
render: shell
|
||||
|
||||
- type: dropdown
|
||||
id: installation
|
||||
attributes:
|
||||
label: How did you install Fabric?
|
||||
description: "Please select the method you used to install Fabric. You can find this information in the [Installation section of the README](https://github.com/ksylvan/fabric/blob/main/README.md#installation)."
|
||||
options:
|
||||
- Release Binary - Windows
|
||||
- Release Binary - macOS (arm64)
|
||||
- Release Binary - macOS (amd64)
|
||||
- Release Binary - Linux (amd64)
|
||||
- Release Binary - Linux (arm64)
|
||||
- Package Manager - Homebrew (macOS)
|
||||
- Package Manager - AUR (Arch Linux)
|
||||
- From Source
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: version
|
||||
attributes:
|
||||
label: Version check
|
||||
description: Please make sure you were using the latest version of this project available in the `main` branch.
|
||||
options:
|
||||
- label: Yes I was.
|
||||
required: true
|
||||
label: Version
|
||||
description: Please copy and paste the output of `fabric --version` (or `fabric-ai --version` if you installed it via brew) here.
|
||||
render: text
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
|
||||
- type: textarea
|
||||
id: screens
|
||||
attributes:
|
||||
|
||||
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
@@ -4,13 +4,13 @@ on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
paths-ignore:
|
||||
- 'patterns/**'
|
||||
- '**/*.md'
|
||||
- "data/patterns/**"
|
||||
- "**/*.md"
|
||||
pull_request:
|
||||
branches: ["main"]
|
||||
paths-ignore:
|
||||
- 'patterns/**'
|
||||
- '**/*.md'
|
||||
- "data/patterns/**"
|
||||
- "**/*.md"
|
||||
|
||||
jobs:
|
||||
test:
|
||||
|
||||
6
.github/workflows/patterns.yaml
vendored
6
.github/workflows/patterns.yaml
vendored
@@ -3,7 +3,7 @@ name: Patterns Artifact
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "patterns/**" # Trigger only on changes to files in the patterns folder
|
||||
- "data/patterns/**" # Trigger only on changes to files in the patterns folder
|
||||
|
||||
jobs:
|
||||
zip-and-upload:
|
||||
@@ -18,13 +18,13 @@ jobs:
|
||||
- name: Verify Changes in Patterns Folder
|
||||
run: |
|
||||
git fetch origin
|
||||
if git diff --quiet HEAD~1 -- patterns; then
|
||||
if git diff --quiet HEAD~1 -- data/patterns; then
|
||||
echo "No changes detected in patterns folder."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Zip the Patterns Folder
|
||||
run: zip -r patterns.zip patterns/
|
||||
run: zip -r patterns.zip data/patterns/
|
||||
|
||||
- name: Upload Patterns Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
13
.github/workflows/release.yml
vendored
13
.github/workflows/release.yml
vendored
@@ -2,7 +2,7 @@ name: Go Release
|
||||
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [ tag_created ]
|
||||
types: [tag_created]
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
@@ -69,7 +69,7 @@ jobs:
|
||||
GOOS: ${{ env.OS }}
|
||||
GOARCH: ${{ matrix.arch }}
|
||||
run: |
|
||||
go build -o fabric-${OS}-${{ matrix.arch }} .
|
||||
go build -o fabric-${OS}-${{ matrix.arch }} ./cmd/fabric
|
||||
|
||||
- name: Build binary on Windows
|
||||
if: matrix.os == 'windows-latest'
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
GOOS: windows
|
||||
GOARCH: ${{ matrix.arch }}
|
||||
run: |
|
||||
go build -o fabric-windows-${{ matrix.arch }}.exe .
|
||||
go build -o fabric-windows-${{ matrix.arch }}.exe ./cmd/fabric
|
||||
|
||||
- name: Upload build artifact
|
||||
if: matrix.os != 'windows-latest'
|
||||
@@ -108,10 +108,15 @@ jobs:
|
||||
Add-Content -Path $env:GITHUB_ENV -Value "latest_tag=$latest_tag"
|
||||
|
||||
- name: Create release if it doesn't exist
|
||||
shell: bash
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh release view ${{ env.latest_tag }} || gh release create ${{ env.latest_tag }} --title "Release ${{ env.latest_tag }}" --notes "Automated release for ${{ env.latest_tag }}"
|
||||
if ! gh release view ${{ env.latest_tag }} >/dev/null 2>&1; then
|
||||
gh release create ${{ env.latest_tag }} --title "Release ${{ env.latest_tag }}" --notes "Automated release for ${{ env.latest_tag }}"
|
||||
else
|
||||
echo "Release ${{ env.latest_tag }} already exists."
|
||||
fi
|
||||
|
||||
- name: Upload release artifact
|
||||
if: matrix.os == 'windows-latest'
|
||||
|
||||
@@ -3,13 +3,17 @@ name: Update Version File and Create Tag
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main # Monitor the main branch
|
||||
- main # Monitor the main branch
|
||||
paths-ignore:
|
||||
- 'patterns/**'
|
||||
- '**/*.md'
|
||||
- "data/patterns/**"
|
||||
- "**/*.md"
|
||||
|
||||
permissions:
|
||||
contents: write # Ensure the workflow has write permissions
|
||||
contents: write # Ensure the workflow has write permissions
|
||||
|
||||
concurrency:
|
||||
group: version-update
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
update-version:
|
||||
@@ -30,6 +34,11 @@ jobs:
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
- name: Pull latest main and tags
|
||||
run: |
|
||||
git pull --rebase origin main
|
||||
git fetch --tags
|
||||
|
||||
- name: Get the latest tag
|
||||
id: get_latest_tag
|
||||
run: |
|
||||
@@ -54,14 +63,14 @@ jobs:
|
||||
|
||||
- name: Update version.go file
|
||||
run: |
|
||||
echo "package main" > version.go
|
||||
echo "" >> version.go
|
||||
echo "var version = \"${{ env.new_tag }}\"" >> version.go
|
||||
echo "package main" > cmd/fabric/version.go
|
||||
echo "" >> cmd/fabric/version.go
|
||||
echo "var version = \"${{ env.new_tag }}\"" >> cmd/fabric/version.go
|
||||
|
||||
- name: Update version.nix file
|
||||
run: |
|
||||
echo "\"${{ env.new_version }}\"" > nix/pkgs/fabric/version.nix
|
||||
|
||||
|
||||
- name: Format source code
|
||||
run: |
|
||||
nix fmt
|
||||
@@ -72,7 +81,7 @@ jobs:
|
||||
|
||||
- name: Commit changes
|
||||
run: |
|
||||
git add version.go
|
||||
git add cmd/fabric/version.go
|
||||
git add nix/pkgs/fabric/version.nix
|
||||
git add nix/pkgs/fabric/gomod2nix.toml
|
||||
git add .
|
||||
@@ -84,7 +93,7 @@ jobs:
|
||||
|
||||
- name: Push changes
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Use GITHUB_TOKEN to authenticate the push
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Use GITHUB_TOKEN to authenticate the push
|
||||
run: |
|
||||
git push origin main # Push changes to the main branch
|
||||
|
||||
@@ -97,7 +106,7 @@ jobs:
|
||||
|
||||
- name: Dispatch event to trigger release workflow
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Use GITHUB_TOKEN to authenticate the dispatch
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Use GITHUB_TOKEN to authenticate the dispatch
|
||||
run: |
|
||||
curl -X POST \
|
||||
-H "Authorization: token $GITHUB_TOKEN" \
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -58,6 +58,7 @@ coverage.xml
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
coverage.out
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
||||
318
Alma.md
318
Alma.md
@@ -1,318 +0,0 @@
|
||||
# SPQA Policy and State for Alma Security
|
||||
|
||||
## Document Purpose
|
||||
|
||||
This document captures the SPQA policy and State for Alma Security, a security startup out of Redwood City, Ca.
|
||||
|
||||
This is part of the SPQA context that will be used to answer questions and create artifacts for the company, e.g., company strategy, security strategy, quarterly security reports (QSRs), project plans, recommendations on which projects to undertake, which investments to take and avoid, and other such decisions.
|
||||
|
||||
A major aspect of the SPQA system is the definition of the company's mission, goals, KPIs, and challenges. These shape everything within the company and thus should be used to shape the recommendations made when asked.
|
||||
|
||||
In addition to the clearly stated goals and other defining characteristics listed above, there will also be a streaming list of updates coming into this system using the Activity document.
|
||||
|
||||
Those will be changes, updates, or modifications to the direction of the company. For example, if Goal number 4 is to build a new datacenter in Boise, Idaho, but we see an update in the Activity section that says we've lost the ability to build in Boise, we should consider goal #4 out of the picture for prioritization and other decision purposes. In other words, the streaming activity log into this document should be considered updates to the core content.
|
||||
|
||||
## Company History
|
||||
|
||||
Alma Security was started by Chris Meyers, who was previously at Sigma Systems as CTO and HPE as a senior security engineer.
|
||||
|
||||
He started the company because, "I saw a gap in the authentication market, where companies were only looking at one or two aspects of one's identity to do authentication. They we're looking at the whole picture and turning that into a continuous authentication story."
|
||||
|
||||
## Company Mission
|
||||
|
||||
The mission of Alma Security is to ensure businesses can continuously authenticate their users using their whole selves.
|
||||
|
||||
## Company Goals (G1 means goal 1, G2 is goal 2, etc. Treat each item (goal/kpi/etc) as half as important as the one before it.)
|
||||
|
||||
NOTE: Some goals are things like project rollout which serve the higher goals. In that case they shouldn't always be considered so much lower priority because one is serving the other.
|
||||
|
||||
## Company Goals
|
||||
|
||||
- G1: Achieve 20% market share by January 2025
|
||||
- G2: Hit 10000 active customers by January 2025
|
||||
- G3: Hit a customer trust score of 90+% by January 2025
|
||||
- G4: Get churn below 5% by August 2024
|
||||
- G5: Launch in Europe by August 2024
|
||||
- G6: Launch in India by November 2024
|
||||
- G7: Launch Mood-monitor integration by February 2024
|
||||
- G8: Launch partnership with Apple Passkeys by June 2024
|
||||
|
||||
## Company KPIs
|
||||
|
||||
- K1: Current market share percentage
|
||||
- K2: Number of active customers
|
||||
- K3: Current churn percentage
|
||||
- K4: Launched_in_Europe (yes/no)
|
||||
- K4: Launched_in_India (yes/no)
|
||||
|
||||
-----------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
## Security Team Mission
|
||||
|
||||
- SM1: Protect Alma Security's customers and intellectual property from security and privacy incidents.
|
||||
|
||||
## Security Team Goals
|
||||
|
||||
- SG1: Secure all customer data -- especially biometric -- from security and privacy incidents.
|
||||
- SG2: Protect Alma Security's intellectual property from being captured by unauthorized parties.
|
||||
- SG3: Reach a time to detect malicious behavior of less than 4 minutes by January 2025
|
||||
- SG4: Ensure the public trusts our product, because it's an authentication product we can't survive if people don't trust us.
|
||||
- SG5: Reach a time to remediate critical vulnerabilities on crown jewel systems of less than 16 hours by August 2025
|
||||
- SG6: Reach a time to remediate critical vulnerabilities on all systems of less than 3 days by August 2025
|
||||
- SG5: Reach a time to remediate critical vulnerabilities on crown jewel systems of less than 16 hours by August 2025
|
||||
- SG6: Reach a time to remediate critical vulnerabilities on all systems of less than 3 days by August 2025
|
||||
- SG7: Complete audit of Apple Passkey integration by February 2025
|
||||
- SG8: Complete remediation of Apple Passkey vulnerabilities by February 2025
|
||||
|
||||
## Security Team KPIs (How we measure the team)
|
||||
|
||||
- SK1: TTD: Time to detect malicious behavior (Minutes)
|
||||
- SK1: TTI: Time to begin investigation of malicious behavior (Minutes)
|
||||
- SK3: TTR-CJC: Time to remediate critical vulnerabilities on crown jewel systems (Hours)
|
||||
- SK3: TTR-C: Time to remediate critical vulnerabilities on all systems (Hours)
|
||||
- SK4: PT: Public trust score (Complete, Significant, Moderate, Minimal, Distrust, N/A)
|
||||
|
||||
## Risk Register (The things we're most worried about)
|
||||
|
||||
- R1: Our infrastructure security team is understaffed by 50% after 5 key people left
|
||||
- R2: We are not currently monitoring our external perimeter for attack surface related vulnerabilities like open ports, listening applications, unknown hosts, unknown subdomains pointing to these things, etc. We only do scans once every couple of months and we don't really have anyone to look at the results
|
||||
- R3: It takes us multiple days to investigate potential malicious behavior on our systems.
|
||||
- R4: We lack a full list of our assets, including externally facing hosts, S3 buckets, etc., which make up our attack surface
|
||||
- R5: We have a low public trust score due to the events of 2022.
|
||||
|
||||
## Security Team Narrative
|
||||
|
||||
### Background
|
||||
|
||||
Alma hired a new security team starting in January of 2023 and we have been building out the program since then. The philosophy and approach for the security team is to explicitly articulate what we believe the highest risks are to Alma, to deploy targeted strategies to address those risks, and to use clear, transparent KPIs to show progress towards our goals over time.
|
||||
|
||||
### Current Risks
|
||||
|
||||
So our risk register looks like this:
|
||||
|
||||
1. We are understaffed by 50% after 5 key people left in 2022
|
||||
2. Our perimeter is not being monitored for attack surface related vulnerabilities
|
||||
3. It takes us too long to detect and start investigating malicious behavior on our systems
|
||||
4. We do not have a full list of our assets, which makes it difficult to know what we need to protect
|
||||
5. We have a low public trust score due to the events of 2022
|
||||
|
||||
### Strategies
|
||||
|
||||
As such, our strategies are as follows:
|
||||
|
||||
1. Hire 5 more A-tier security professionals
|
||||
2. Purchase and implement an attack surface management solution
|
||||
3. Invest in our detection and response capabilities
|
||||
4. Purchase an asset inventory system that integrates with our attack surface management tool
|
||||
5. Leverage PR to share as much of our progress as possible with the public to rebuild trust
|
||||
|
||||
### How We're Doing
|
||||
|
||||
We believe being transparent about our progress is key to everything, and for that reason we maintain a limited number of KPIs that we update every quarter. These metrics will not change often. They will remain consistent so that it's easy to track how we're spending our resources and the progress we're making.
|
||||
|
||||
Those KPIs are:
|
||||
|
||||
1. Time to detect malicious behavior
|
||||
2. Time to start investigating malicious behavior
|
||||
3. Time to remediate critical vulnerabilities on crown jewel systems
|
||||
4. Time to remediate critical vulnerabilities on all systems
|
||||
5. Our public trust score
|
||||
|
||||
As of $DATE$, our KPIs for these are currently:
|
||||
|
||||
$GIVE CURRENT KPIs from the Activity section below$
|
||||
|
||||
$INSERT GRAPHS OF KPI PROGRESS OVER TIME HERE$
|
||||
|
||||
## Security Team Strategies
|
||||
|
||||
- STS1: Hire 5 more A-tier security professionals
|
||||
- STS2: Purchase an attack surface management solution
|
||||
- STS3: Invest in our detection and response capabilities
|
||||
- STS4: Purchase an asset inventory system that integrates with our attack surface management tool
|
||||
|
||||
## Infrastructure Notes (a basic description of our tech stack and various context around it)
|
||||
|
||||
- We currently have no WAF protecting our main web app but we're considering adding one
|
||||
- We have had some issues with S3 buckets becoming public, or being set up as public, which has lead to some close calls with customer data almost being exposed.
|
||||
- alma.amazon-domain.com is our primary S3 bucket that contains everything, but it's not public readable or listable
|
||||
- We have a root account for our AWS account that doesn't yet have 2FA on it, but we're working on fixing that within a few weeks (but it's been open for a few months)
|
||||
- We also use Postgres for all our databases.
|
||||
- Developers have root access to the all kubernetes nodes via SSH on port 45,001 using a shared developer key issued during laptop provisioning.
|
||||
- We're a kubernetes shop and do everything through AWS
|
||||
- We're logging most stuff to Cloudtrail and we kind of use Amazon Guarduty, but we don't have a 24/7 team to monitor alerts and logs. We should add that to our list of challenges next time we update our overall policy
|
||||
- We also have a Windows infrastructure because some key personnel came from Microsoft. The DC is hosted in our head office which is in Redwood City, and anyone who works in that office (most of the 300 employees) uses that to log in when they start work. The domain is ALMA.
|
||||
- There's a domain-joined fileserver running Windows 2012 that most people use to upload new ideas and plans for new products. It uses Windows authentication from the domain.
|
||||
- We use a Palo Alto Networks firewall with 2fa using windows authenticator tied to SSO.
|
||||
- The name of the AI system doing all this context creation using SPQA is Alma, which is also the name of the company.
|
||||
- We use Workday for HR stuff. Slack for realtime communications. Outlook 365 as a service. Sentinel One on the workstations and laptops. Servers in AWS are mostly Amazon Linux 2 with a few Ubuntu boxes that are a few years old.
|
||||
- We also primarily use Postgres for all of our systems.
|
||||
|
||||
## Team
|
||||
|
||||
TEAM MEMBER | TEAM ASSIGNED | SKILLS | PAY LEVEL | LOCATION | PROJECTS
|
||||
|
||||
Nadia Khan | Detection and Response | D&R (Expert), AWS (Strong), Python (Expert), Kubernetes (Basic), Postgres (Basic) | $249K | Redwood City
|
||||
Chris Magann | Vulnerability Management | VM (Expert), AWS (Strong), Python (Basic), Postgres (Basic) | $212K | Redwood City
|
||||
Tigan Wang | Vulnerability Management | VM (Expert), AWS (Strong), Python (Basic), Postgres (Basic) | $217K | Redwood City
|
||||
|
||||
## Projects
|
||||
|
||||
PROJECT NAME | PROJECT DESCRIPTION | PROJECT PRIORITY | PROJECT MEMBERS | START DATE | END DATE | STATUS | PROJECT COST
|
||||
|
||||
WAF Install | Install a WAF in front of our main web app | Critical | Nadia Khan | 2024-01-01 - Ongoing | In Progress | $112K one-time, $9K/month
|
||||
|
||||
Multi-Factor Authentication (MFA) Rollout | Implement MFA across all internal and external systems | Critical | Chris Magann | 2024-01-15 | 2024-05-01 | Planned | $80K one-time, $5K/month
|
||||
|
||||
Procure and Implement ASM | Implement continuous monitoring for attack surface vulnerabilities | High | Tigan Wang | 2024-02-15 | 2024-06-15 | Not Started | $75K one-time, $6K/month
|
||||
|
||||
Data Encryption Upgrade | Upgrade encryption protocols for all sensitive data | Medium | Nadia Khan | 2024-04-01 | 2024-08-01 | Planned | $95K one-time
|
||||
|
||||
Incident Response Enhancement | Develop and implement a 24/7 incident response team | High | Nadia Khan | 2024-03-01 | 2024-07-01 | In Progress | $150K one-time, $10K/month
|
||||
|
||||
Cloud Security Optimization | Optimize AWS cloud security configurations and practices | Medium | Tigan Wang | 2024-02-01 | 2024-06-01 | In Progress | $100K one-time, $8K/month
|
||||
|
||||
S3 Bucket Security | Review and secure all S3 buckets to prevent data breaches | High | Chris Magann | 2024-01-10 | 2024-04-10 | In Progress | $70K one-time, $5K/month
|
||||
|
||||
SQL Injection Mitigation | Implement measures to eliminate SQL injection vulnerabilities | High | Tigan Wang | 2024-01-20 | 2024-05-20 | Not Started | $60K one-time
|
||||
|
||||
## SECURITY POSTURE (To be referenced for compliance questions and security questionnaires)
|
||||
|
||||
July 2019
|
||||
Admin accounts still not required to use 2FA.
|
||||
Company laptops distributed to employees, no MDM yet for device management.
|
||||
AWS IAM roles created for engineers, but root access still frequently used.
|
||||
Started basic vulnerability scanning using open-source tools.
|
||||
December 2019
|
||||
|
||||
MFA enforced for all Google Workspace accounts after a phishing attempt.
|
||||
Introduced ClamAV for basic endpoint protection on corporate laptops.
|
||||
AWS GuardDuty enabled for threat detection, but no formal incident response team.
|
||||
First incident response plan table-top exercise conducted, but findings not fully documented.
|
||||
April 2020
|
||||
|
||||
Migrated from Google Workspace to Office 365, with MFA enabled for all users.
|
||||
Rolled out SentinelOne for endpoint protection on 50% of company laptops.
|
||||
Implemented least-privilege access control for AWS IAM roles.
|
||||
First formal vendor risk management review completed for major SaaS providers.
|
||||
August 2020
|
||||
|
||||
Completed full deployment of SentinelOne across all endpoints.
|
||||
Implemented AWS CloudWatch for real-time alerts; however, logs still not monitored 24/7.
|
||||
Began encrypting all AWS S3 buckets at rest using server-side encryption.
|
||||
First internal review of data retention policies, started drafting data disposal policy.
|
||||
January 2021
|
||||
|
||||
Rolled out Jamf MDM for centralized management of macOS devices, enforcing encryption (FileVault) on all laptops.
|
||||
Strengthened Office 365 security by implementing phishing-resistant MFA using authenticator apps.
|
||||
AWS KMS introduced for managing encryption keys; manual key rotation policy documented.
|
||||
Introduced formal onboarding and offboarding processes for employee account management.
|
||||
July 2021
|
||||
|
||||
Conditional access policies introduced for Office 365, restricting access based on geography (US-only).
|
||||
Conducted company-wide security awareness training for the first time, focusing on phishing threats.
|
||||
Completed first backup and disaster recovery (DR) drill with AWS, documenting recovery times.
|
||||
AWS Config deployed to monitor and enforce encryption and access control policies across accounts.
|
||||
December 2021
|
||||
|
||||
Full migration to AWS for all production systems completed.
|
||||
Incident response playbook finalized and shared with the security team; still no 24/7 monitoring.
|
||||
Documented data classification policies for handling sensitive customer data in preparation for SOC 2 audit.
|
||||
First third-party penetration test conducted, critical vulnerabilities identified and remediated within 30 days.
|
||||
March 2022
|
||||
|
||||
Rolled out company-wide 2FA for all critical systems, including Office 365, AWS, GitHub, and Slack.
|
||||
Introduced AWS Secrets Manager for managing sensitive credentials, eliminating hardcoded API keys.
|
||||
Updated all documentation for identity and access management in preparation for SOC 2 Type 1 audit.
|
||||
First external vulnerability scan completed using Qualys, with remediation SLAs established.
|
||||
April 2022
|
||||
|
||||
Updated and consolidated all security policies (incident response, access control, data retention) in preparation for SOC 2 audit.
|
||||
Conducted tabletop exercise for ransomware response, documenting gaps in the incident response process.
|
||||
Implemented Just-In-Time (JIT) access for administrative privileges in AWS, reducing unnecessary persistent access.
|
||||
October 2022
|
||||
|
||||
Passed SOC 2 Type 1 audit, with recommendations to improve monitoring and asset management.
|
||||
Launched quarterly phishing simulations to raise employee awareness and track training effectiveness.
|
||||
Fully enforced encryption for all customer data in transit and at rest using AWS KMS.
|
||||
Extended GuardDuty to cover all AWS regions; started monitoring alerts daily.
|
||||
January 2023
|
||||
|
||||
Hired a dedicated CISO and expanded security team by 30%.
|
||||
Integrated continuous vulnerability scanning across all externally facing assets using Qualys.
|
||||
Conducted first third-party vendor risk assessment to ensure alignment with SOC 2 and internal security standards.
|
||||
Implemented automated patch management for all AWS EC2 instances, reducing time to deploy critical patches.
|
||||
July 2023
|
||||
|
||||
Rolled out continuous attack surface monitoring (ASM) to identify and remediate external vulnerabilities.
|
||||
Performed annual data retention review, ensuring compliance with SOC 2 and GDPR requirements.
|
||||
Conducted a disaster recovery drill for AWS workloads, achieving a recovery time objective (RTO) of under 4 hours.
|
||||
Completed SOC 2 Type 2 readiness assessment, with focus on improving incident response times.
|
||||
November 2023
|
||||
|
||||
Updated incident response documentation and assigned 24/7 monitoring to a third-party SOC provider.
|
||||
Rolled out zero-trust network architecture across the organization, removing reliance on VPN for remote access.
|
||||
Passed SOC 2 Type 2 audit with no major findings; recommendations included improved asset inventory tracking.
|
||||
Conducted full audit of access control policies and JIT access implementation in preparation for ISO 27001 certification.
|
||||
April 2024
|
||||
|
||||
Implemented AI-driven threat detection to reduce time to detect security incidents from 10 hours to under 2 hours.
|
||||
Completed full encryption audit across all databases, ensuring compliance with GDPR, HIPAA, and other privacy regulations.
|
||||
Updated employee training programs to include privacy regulations (GDPR, CCPA) and data handling best practices.
|
||||
Completed internal review and audit of vendor access to critical systems as part of SOC 2 compliance effort.
|
||||
Completed move of all AWS services to us-west-2 and us-east-1 regions for 100% us-based cloud services.
|
||||
October 2024
|
||||
|
||||
Conducted organization-wide review of data retention and disposal policies, implementing automated data deletion for expired data.
|
||||
Implemented continuous compliance monitoring for SOC 2, with automated alerts for deviations in access controls and encryption settings.
|
||||
Finalized implementation of AI-based monitoring and response systems, significantly reducing time to remediate critical vulnerabilities.
|
||||
Passed SOC 2 Type 2 and ISO 27001 audits with zero non-conformities, achieving full compliance across all control areas.March 2018
|
||||
|
||||
Personal Gmail accounts used for internal and external communication.
|
||||
No 2FA enabled on any accounts.
|
||||
AWS accounts shared with engineers, no IAM roles or formal access control policies.
|
||||
No centralized endpoint protection; employees use personal laptops with no security controls.
|
||||
No documented security policies or incident response plan.
|
||||
September 2018
|
||||
|
||||
Initiated migration from personal Gmail to Google Workspace (G Suite) for business email.
|
||||
Password complexity requirements introduced (minimum 8 characters).
|
||||
AWS root credentials still shared among team members, no MFA enabled.
|
||||
No formal logging or monitoring in place for AWS activity.
|
||||
February 2019
|
||||
|
||||
Completed migration to Google Workspace; no email encryption yet.
|
||||
Introduced a basic password manager (LastPass) but no enforcement policy.
|
||||
AWS CloudTrail enabled for logging, but no one is reviewing logs.
|
||||
First draft of the incident response plan created, but not tested.
|
||||
June 2019
|
||||
|
||||
Enforced MFA for Google Workspace admin accounts; standard user
|
||||
|
||||
## CURRENT STATE (KPIs, Metrics, Project Activity Updates, etc.)
|
||||
|
||||
- October 2022: Current time to detect malicious behavior is 81 hours
|
||||
- October 2022: Current time to start investigating malicious behavior is 82 hours
|
||||
- October 2022: Current time to remediate critical vulnerabilities on crown jewel systems is 21 days
|
||||
- October 2022: Current time to remediate critical vulnerabilities on all systems is 51 days
|
||||
- January 2023: Current time to detect malicious behavior is 62 hours
|
||||
- January 2023: Current time to start investigating malicious behavior is 72 hours
|
||||
- January 2023: Current time to remediate critical vulnerabilities on crown jewel systems is 17 days
|
||||
- January 2023: Current time to remediate critical vulnerabilities on all systems is 43 days
|
||||
- July 2023: Current time to detect malicious behavior is 29 hours
|
||||
- July 2023: Current time to start investigating malicious behavior is 41 hours
|
||||
- July 2023: Current time to remediate critical vulnerabilities on crown jewel systems is 12 days
|
||||
- July 2023: Current time to remediate critical vulnerabilities on all systems is 29 days
|
||||
- November 2023: Current time to start detect malicious behavior is 12 hours
|
||||
- November 2023: Current time to start investigating malicious behavior is 16 hours
|
||||
- November 2023: Current time to remediate critical vulnerabilities on crown jewel systems is 9 days
|
||||
- November 2023: Current time to remediate critical vulnerabilities on all systems is 17 days
|
||||
- February 2024: Started attack surface management vendor selection process
|
||||
- January 2024: Current time to start detect malicious behavior is 9 hours
|
||||
- January 2024: Current time to start investigating malicious behavior is 14 hours
|
||||
- January 2024: Current time to remediate critical vulnerabilities on crown jewel systems is 8 days
|
||||
- January 2024: Current time to remediate critical vulnerabilities on all systems is 12 days
|
||||
- March 2024: We're now remediating critical vulnerabilities on crown jewels in less than 6 days
|
||||
- April 2024: We're now remediating all critical vulnerabilities within 11 days
|
||||
- July 2024: critical vulnerabilities are now being fixed in 9 days
|
||||
- On August 5 we got remediation of critical vulnerabilities down to 7 days
|
||||
449
README.md
449
README.md
@@ -1,4 +1,7 @@
|
||||
<div align="center">
|
||||
Fabric is graciously supported by…
|
||||
|
||||
[](https://warp.dev/fabric)
|
||||
|
||||
<img src="./images/fabric-logo-gif.gif" alt="fabriclogo" width="400" height="400"/>
|
||||
|
||||
@@ -9,16 +12,17 @@
|
||||

|
||||

|
||||
[](https://opensource.org/licenses/MIT)
|
||||
[](https://deepwiki.com/danielmiessler/fabric)
|
||||
|
||||
<p class="align center">
|
||||
<div align="center">
|
||||
<h4><code>fabric</code> is an open-source framework for augmenting humans using AI.</h4>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
[Updates](#updates) •
|
||||
[What and Why](#whatandwhy) •
|
||||
[What and Why](#what-and-why) •
|
||||
[Philosophy](#philosophy) •
|
||||
[Installation](#Installation) •
|
||||
[Usage](#Usage) •
|
||||
[Installation](#installation) •
|
||||
[Usage](#usage) •
|
||||
[Examples](#examples) •
|
||||
[Just Use the Patterns](#just-use-the-patterns) •
|
||||
[Custom Patterns](#custom-patterns) •
|
||||
@@ -29,18 +33,49 @@
|
||||
|
||||
</div>
|
||||
|
||||
## What and why
|
||||
|
||||
Since the start of modern AI in late 2022 we've seen an **_extraordinary_** number of AI applications for accomplishing tasks. There are thousands of websites, chat-bots, mobile apps, and other interfaces for using all the different AI out there.
|
||||
|
||||
It's all really exciting and powerful, but _it's not easy to integrate this functionality into our lives._
|
||||
|
||||
<div class="align center">
|
||||
<h4>In other words, AI doesn't have a capabilities problem—it has an <em>integration</em> problem.</h4>
|
||||
</div>
|
||||
|
||||
**Fabric was created to address this by creating and organizing the fundamental units of AI—the prompts themselves!**
|
||||
|
||||
Fabric organizes prompts by real-world task, allowing people to create, collect, and organize their most important AI solutions in a single place for use in their favorite tools. And if you're command-line focused, you can use Fabric itself as the interface!
|
||||
|
||||
## Intro videos
|
||||
|
||||
Keep in mind that many of these were recorded when Fabric was Python-based, so remember to use the current [install instructions](#installation) below.
|
||||
|
||||
- [Network Chuck](https://www.youtube.com/watch?v=UbDyjIIGaxQ)
|
||||
- [David Bombal](https://www.youtube.com/watch?v=vF-MQmVxnCs)
|
||||
- [My Own Intro to the Tool](https://www.youtube.com/watch?v=wPEyyigh10g)
|
||||
- [More Fabric YouTube Videos](https://www.youtube.com/results?search_query=fabric+ai)
|
||||
|
||||
## Navigation
|
||||
|
||||
- [`fabric`](#fabric)
|
||||
- [What and why](#what-and-why)
|
||||
- [Intro videos](#intro-videos)
|
||||
- [Navigation](#navigation)
|
||||
- [Updates](#updates)
|
||||
- [Intro videos](#intro-videos)
|
||||
- [What and why](#what-and-why)
|
||||
- [Philosophy](#philosophy)
|
||||
- [Breaking problems into components](#breaking-problems-into-components)
|
||||
- [Too many prompts](#too-many-prompts)
|
||||
- [Installation](#installation)
|
||||
- [Get Latest Release Binaries](#get-latest-release-binaries)
|
||||
- [Windows](#windows)
|
||||
- [macOS (arm64)](#macos-arm64)
|
||||
- [macOS (amd64)](#macos-amd64)
|
||||
- [Linux (amd64)](#linux-amd64)
|
||||
- [Linux (arm64)](#linux-arm64)
|
||||
- [Using package managers](#using-package-managers)
|
||||
- [macOS (Homebrew)](#macos-homebrew)
|
||||
- [Arch Linux (AUR)](#arch-linux-aur)
|
||||
- [From Source](#from-source)
|
||||
- [Environment Variables](#environment-variables)
|
||||
- [Setup](#setup)
|
||||
@@ -48,46 +83,60 @@
|
||||
- [Save your files in markdown using aliases](#save-your-files-in-markdown-using-aliases)
|
||||
- [Migration](#migration)
|
||||
- [Upgrading](#upgrading)
|
||||
- [Shell Completions](#shell-completions)
|
||||
- [Zsh Completion](#zsh-completion)
|
||||
- [Bash Completion](#bash-completion)
|
||||
- [Fish Completion](#fish-completion)
|
||||
- [Usage](#usage)
|
||||
- [Our approach to prompting](#our-approach-to-prompting)
|
||||
- [Examples](#examples)
|
||||
- [Just use the Patterns](#just-use-the-patterns)
|
||||
- [Prompt Strategies](#prompt-strategies)
|
||||
- [Custom Patterns](#custom-patterns)
|
||||
- [Setting Up Custom Patterns](#setting-up-custom-patterns)
|
||||
- [Using Custom Patterns](#using-custom-patterns)
|
||||
- [How It Works](#how-it-works)
|
||||
- [Helper Apps](#helper-apps)
|
||||
- [`to_pdf`](#to_pdf)
|
||||
- [`to_pdf` Installation](#to_pdf-installation)
|
||||
- [`code_helper`](#code_helper)
|
||||
- [pbpaste](#pbpaste)
|
||||
- [Web Interface](#Web_Interface)
|
||||
- [Web Interface](#web-interface)
|
||||
- [Installing](#installing)
|
||||
- [Streamlit UI](#streamlit-ui)
|
||||
- [Clipboard Support](#clipboard-support)
|
||||
- [Meta](#meta)
|
||||
- [Primary contributors](#primary-contributors)
|
||||
- [Contributors](#contributors)
|
||||
|
||||
<br />
|
||||
|
||||
## Updates
|
||||
|
||||
> [!NOTE]
|
||||
> February 24, 2025
|
||||
>
|
||||
> - Fabric now supports Sonnet 3.7! Update and use `-S` to select it as your default if you want, or just use the shortcut `-m claude-3-7-sonnet-latest`. Enjoy!
|
||||
|
||||
## What and why
|
||||
|
||||
Since the start of 2023 and GenAI we've seen a massive number of AI applications for accomplishing tasks. It's powerful, but _it's not easy to integrate this functionality into our lives._
|
||||
|
||||
<div align="center">
|
||||
<h4>In other words, AI doesn't have a capabilities problem—it has an <em>integration</em> problem.</h4>
|
||||
</div>
|
||||
|
||||
Fabric was created to address this by enabling everyone to granularly apply AI to everyday challenges.
|
||||
|
||||
## Intro videos
|
||||
|
||||
Keep in mind that many of these were recorded when Fabric was Python-based, so remember to use the current [install instructions](#Installation) below.
|
||||
|
||||
- [Network Chuck](https://www.youtube.com/watch?v=UbDyjIIGaxQ)
|
||||
- [David Bombal](https://www.youtube.com/watch?v=vF-MQmVxnCs)
|
||||
- [My Own Intro to the Tool](https://www.youtube.com/watch?v=wPEyyigh10g)
|
||||
- [More Fabric YouTube Videos](https://www.youtube.com/results?search_query=fabric+ai)
|
||||
> July 4, 2025
|
||||
>
|
||||
> - **Web Search**: Fabric now supports web search for Anthropic and OpenAI models using the `--search` and `--search-location` flags. This replaces the previous plugin-based search, so you may want to remove the old `ANTHROPIC_WEB_SEARCH_TOOL_*` variables from your `~/.config/fabric/.env` file.
|
||||
> - **Image Generation**: Fabric now has powerful image generation capabilities with OpenAI.
|
||||
> - Generate images from text prompts and save them using `--image-file`.
|
||||
> - Edit existing images by providing an input image with `--attachment`.
|
||||
> - Control image `size`, `quality`, `compression`, and `background` with the new `--image-*` flags.
|
||||
>
|
||||
>June 17, 2025
|
||||
>
|
||||
>- Fabric now supports Perplexity AI. Configure it by using `fabric -S` to add your Perplexity AI API Key,
|
||||
> and then try:
|
||||
>
|
||||
> ```bash
|
||||
> fabric -m sonar-pro "What is the latest world news?"
|
||||
> ```
|
||||
>
|
||||
>June 11, 2025
|
||||
>
|
||||
>- Fabric's YouTube transcription now needs `yt-dlp` to be installed. Make sure to install the latest
|
||||
> version (2025.06.09 as of this note). The YouTube API key is only needed for comments (the `--comments` flag)
|
||||
> and metadata extraction (the `--metadata` flag).
|
||||
|
||||
## Philosophy
|
||||
|
||||
@@ -105,7 +154,7 @@ Our approach is to break problems into individual pieces (see below) and then ap
|
||||
|
||||
Prompts are good for this, but the biggest challenge I faced in 2023——which still exists today—is **the sheer number of AI prompts out there**. We all have prompts that are useful, but it's hard to discover new ones, know if they are good or not, _and manage different versions of the ones we like_.
|
||||
|
||||
One of <code>fabric</code>'s primary features is helping people collect and integrate prompts, which we call _Patterns_, into various parts of their lives.
|
||||
One of `fabric`'s primary features is helping people collect and integrate prompts, which we call _Patterns_, into various parts of their lives.
|
||||
|
||||
Fabric has Patterns for all sorts of life and work activities, including:
|
||||
|
||||
@@ -126,28 +175,50 @@ To install Fabric, you can use the latest release binaries or install it from th
|
||||
|
||||
### Get Latest Release Binaries
|
||||
|
||||
#### Windows:
|
||||
#### Windows
|
||||
|
||||
`https://github.com/danielmiessler/fabric/releases/latest/download/fabric-windows-amd64.exe`
|
||||
|
||||
#### MacOS (arm64):
|
||||
#### macOS (arm64)
|
||||
|
||||
`curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-darwin-arm64 > fabric && chmod +x fabric && ./fabric --version`
|
||||
|
||||
#### MacOS (amd64):
|
||||
#### macOS (amd64)
|
||||
|
||||
`curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-darwin-amd64 > fabric && chmod +x fabric && ./fabric --version`
|
||||
|
||||
#### Linux (amd64):
|
||||
#### Linux (amd64)
|
||||
|
||||
`curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-linux-amd64 > fabric && chmod +x fabric && ./fabric --version`
|
||||
|
||||
#### Linux (arm64):
|
||||
#### Linux (arm64)
|
||||
|
||||
`curl -L https://github.com/danielmiessler/fabric/releases/latest/download/fabric-linux-arm64 > fabric && chmod +x fabric && ./fabric --version`
|
||||
|
||||
### Using package managers
|
||||
|
||||
**NOTE:** using Homebrew or the Arch Linux package managers makes `fabric` available as `fabric-ai`, so add
|
||||
the following alias to your shell startup files to account for this:
|
||||
|
||||
```bash
|
||||
alias fabric='fabric-ai'
|
||||
```
|
||||
|
||||
#### macOS (Homebrew)
|
||||
|
||||
`brew install fabric-ai`
|
||||
|
||||
#### Arch Linux (AUR)
|
||||
|
||||
`yay -S fabric-ai`
|
||||
|
||||
### From Source
|
||||
|
||||
To install Fabric, [make sure Go is installed](https://go.dev/doc/install), and then run the following command.
|
||||
|
||||
```bash
|
||||
# Install Fabric directly from the repo
|
||||
go install github.com/danielmiessler/fabric@latest
|
||||
go install github.com/danielmiessler/fabric/cmd/fabric@latest
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
@@ -309,7 +380,7 @@ This also creates a `yt` alias that allows you to use `yt https://www.youtube.co
|
||||
|
||||
#### Save your files in markdown using aliases
|
||||
|
||||
If in addition to the above aliases you would like to have the option to save the output to your favourite markdown note vault like Obsidian then instead of the above add the following to your `.zshrc` or `.bashrc` file:
|
||||
If in addition to the above aliases you would like to have the option to save the output to your favorite markdown note vault like Obsidian then instead of the above add the following to your `.zshrc` or `.bashrc` file:
|
||||
|
||||
```bash
|
||||
# Define the base directory for Obsidian notes
|
||||
@@ -320,7 +391,7 @@ for pattern_file in ~/.config/fabric/patterns/*; do
|
||||
# Get the base name of the file (i.e., remove the directory path)
|
||||
pattern_name=$(basename "$pattern_file")
|
||||
|
||||
# Unalias any existing alias with the same name
|
||||
# Remove any existing alias with the same name
|
||||
unalias "$pattern_name" 2>/dev/null
|
||||
|
||||
# Define a function dynamically for each pattern
|
||||
@@ -341,11 +412,6 @@ for pattern_file in ~/.config/fabric/patterns/*; do
|
||||
}
|
||||
"
|
||||
done
|
||||
|
||||
yt() {
|
||||
local video_link="$1"
|
||||
fabric -y "$video_link" --transcript
|
||||
}
|
||||
```
|
||||
|
||||
This will allow you to use the patterns as aliases like in the above for example `summarize` instead of `fabric --pattern summarize --stream`, however if you pass in an extra argument like this `summarize "my_article_title"` your output will be saved in the destination that you set in `obsidian_base="/path/to/obsidian"` in the following format `YYYY-MM-DD-my_article_title.md` where the date gets autogenerated for you.
|
||||
@@ -362,19 +428,61 @@ pipx uninstall fabric
|
||||
# Clear any old Fabric aliases
|
||||
(check your .bashrc, .zshrc, etc.)
|
||||
# Install the Go version
|
||||
go install github.com/danielmiessler/fabric@latest
|
||||
go install github.com/danielmiessler/fabric/cmd/fabric@latest
|
||||
# Run setup for the new version. Important because things have changed
|
||||
fabric --setup
|
||||
```
|
||||
|
||||
Then [set your environmental variables](#environmental-variables) as shown above.
|
||||
Then [set your environmental variables](#environment-variables) as shown above.
|
||||
|
||||
### Upgrading
|
||||
|
||||
The great thing about Go is that it's super easy to upgrade. Just run the same command you used to install it in the first place and you'll always get the latest version.
|
||||
|
||||
```bash
|
||||
go install github.com/danielmiessler/fabric@latest
|
||||
go install github.com/danielmiessler/fabric/cmd/fabric@latest
|
||||
```
|
||||
|
||||
### Shell Completions
|
||||
|
||||
Fabric provides shell completion scripts for Zsh, Bash, and Fish
|
||||
shells, making it easier to use the CLI by providing tab completion
|
||||
for commands and options.
|
||||
|
||||
#### Zsh Completion
|
||||
|
||||
To enable Zsh completion:
|
||||
|
||||
```bash
|
||||
# Copy the completion file to a directory in your $fpath
|
||||
mkdir -p ~/.zsh/completions
|
||||
cp completions/_fabric ~/.zsh/completions/
|
||||
|
||||
# Add the directory to fpath in your .zshrc before compinit
|
||||
echo 'fpath=(~/.zsh/completions $fpath)' >> ~/.zshrc
|
||||
echo 'autoload -Uz compinit && compinit' >> ~/.zshrc
|
||||
```
|
||||
|
||||
#### Bash Completion
|
||||
|
||||
To enable Bash completion:
|
||||
|
||||
```bash
|
||||
# Source the completion script in your .bashrc
|
||||
echo 'source /path/to/fabric/completions/fabric.bash' >> ~/.bashrc
|
||||
|
||||
# Or copy to the system-wide bash completion directory
|
||||
sudo cp completions/fabric.bash /etc/bash_completion.d/
|
||||
```
|
||||
|
||||
#### Fish Completion
|
||||
|
||||
To enable Fish completion:
|
||||
|
||||
```bash
|
||||
# Copy the completion file to the fish completions directory
|
||||
mkdir -p ~/.config/fish/completions
|
||||
cp completions/fabric.fish ~/.config/fish/completions/
|
||||
```
|
||||
|
||||
## Usage
|
||||
@@ -385,54 +493,81 @@ Once you have it all set up, here's how to use it.
|
||||
fabric -h
|
||||
```
|
||||
|
||||
```bash
|
||||
|
||||
```plaintext
|
||||
Usage:
|
||||
fabric [OPTIONS]
|
||||
|
||||
Application Options:
|
||||
-p, --pattern= Choose a pattern from the available patterns
|
||||
-v, --variable= Values for pattern variables, e.g. -v=#role:expert -v=#points:30"
|
||||
-C, --context= Choose a context from the available contexts
|
||||
--session= Choose a session from the available sessions
|
||||
-a, --attachment= Attachment path or URL (e.g. for OpenAI image recognition messages)
|
||||
-S, --setup Run setup for all reconfigurable parts of fabric
|
||||
-t, --temperature= Set temperature (default: 0.7)
|
||||
-T, --topp= Set top P (default: 0.9)
|
||||
-s, --stream Stream
|
||||
-P, --presencepenalty= Set presence penalty (default: 0.0)
|
||||
-r, --raw Use the defaults of the model without sending chat options (like temperature etc.) and use the user role instead of the system role for patterns.
|
||||
-F, --frequencypenalty= Set frequency penalty (default: 0.0)
|
||||
-l, --listpatterns List all patterns
|
||||
-L, --listmodels List all available models
|
||||
-x, --listcontexts List all contexts
|
||||
-X, --listsessions List all sessions
|
||||
-U, --updatepatterns Update patterns
|
||||
-c, --copy Copy to clipboard
|
||||
-m, --model= Choose model
|
||||
-o, --output= Output to file
|
||||
--output-session Output the entire session (also a temporary one) to the output file
|
||||
-n, --latest= Number of latest patterns to list (default: 0)
|
||||
-d, --changeDefaultModel Change default model
|
||||
-y, --youtube= YouTube video "URL" to grab transcript, comments from it and send to chat
|
||||
--transcript Grab transcript from YouTube video and send to chat (it used per default).
|
||||
--comments Grab comments from YouTube video and send to chat
|
||||
--metadata Grab metadata from YouTube video and send to chat
|
||||
-g, --language= Specify the Language Code for the chat, e.g. -g=en -g=zh
|
||||
-u, --scrape_url= Scrape website URL to markdown using Jina AI
|
||||
-q, --scrape_question= Search question using Jina AI
|
||||
-e, --seed= Seed to be used for LMM generation
|
||||
-w, --wipecontext= Wipe context
|
||||
-W, --wipesession= Wipe session
|
||||
--printcontext= Print context
|
||||
--printsession= Print session
|
||||
--readability Convert HTML input into a clean, readable view
|
||||
--serve Initiate the API server
|
||||
--dry-run Show what would be sent to the model without actually sending it
|
||||
--version Print current version
|
||||
-p, --pattern= Choose a pattern from the available patterns
|
||||
-v, --variable= Values for pattern variables, e.g. -v=#role:expert -v=#points:30
|
||||
-C, --context= Choose a context from the available contexts
|
||||
--session= Choose a session from the available sessions
|
||||
-a, --attachment= Attachment path or URL (e.g. for OpenAI image recognition messages)
|
||||
-S, --setup Run setup for all reconfigurable parts of fabric
|
||||
-t, --temperature= Set temperature (default: 0.7)
|
||||
-T, --topp= Set top P (default: 0.9)
|
||||
-s, --stream Stream
|
||||
-P, --presencepenalty= Set presence penalty (default: 0.0)
|
||||
-r, --raw Use the defaults of the model without sending chat options (like
|
||||
temperature etc.) and use the user role instead of the system role for
|
||||
patterns.
|
||||
-F, --frequencypenalty= Set frequency penalty (default: 0.0)
|
||||
-l, --listpatterns List all patterns
|
||||
-L, --listmodels List all available models
|
||||
-x, --listcontexts List all contexts
|
||||
-X, --listsessions List all sessions
|
||||
-U, --updatepatterns Update patterns
|
||||
-c, --copy Copy to clipboard
|
||||
-m, --model= Choose model
|
||||
--modelContextLength= Model context length (only affects ollama)
|
||||
-o, --output= Output to file
|
||||
--output-session Output the entire session (also a temporary one) to the output file
|
||||
-n, --latest= Number of latest patterns to list (default: 0)
|
||||
-d, --changeDefaultModel Change default model
|
||||
-y, --youtube= YouTube video or play list "URL" to grab transcript, comments from it
|
||||
and send to chat or print it put to the console and store it in the
|
||||
output file
|
||||
--playlist Prefer playlist over video if both ids are present in the URL
|
||||
--transcript Grab transcript from YouTube video and send to chat (it is used per
|
||||
default).
|
||||
--transcript-with-timestamps Grab transcript from YouTube video with timestamps and send to chat
|
||||
--comments Grab comments from YouTube video and send to chat
|
||||
--metadata Output video metadata
|
||||
-g, --language= Specify the Language Code for the chat, e.g. -g=en -g=zh
|
||||
-u, --scrape_url= Scrape website URL to markdown using Jina AI
|
||||
-q, --scrape_question= Search question using Jina AI
|
||||
-e, --seed= Seed to be used for LMM generation
|
||||
-w, --wipecontext= Wipe context
|
||||
-W, --wipesession= Wipe session
|
||||
--printcontext= Print context
|
||||
--printsession= Print session
|
||||
--readability Convert HTML input into a clean, readable view
|
||||
--input-has-vars Apply variables to user input
|
||||
--dry-run Show what would be sent to the model without actually sending it
|
||||
--serve Serve the Fabric Rest API
|
||||
--serveOllama Serve the Fabric Rest API with ollama endpoints
|
||||
--address= The address to bind the REST API (default: :8080)
|
||||
--api-key= API key used to secure server routes
|
||||
--config= Path to YAML config file
|
||||
--version Print current version
|
||||
--listextensions List all registered extensions
|
||||
--addextension= Register a new extension from config file path
|
||||
--rmextension= Remove a registered extension by name
|
||||
--strategy= Choose a strategy from the available strategies
|
||||
--liststrategies List all strategies
|
||||
--listvendors List all vendors
|
||||
--shell-complete-list Output raw list without headers/formatting (for shell completion)
|
||||
--search Enable web search tool for supported models (Anthropic, OpenAI)
|
||||
--search-location= Set location for web search results (e.g., 'America/Los_Angeles')
|
||||
--image-file= Save generated image to specified file path (e.g., 'output.png')
|
||||
--image-size= Image dimensions: 1024x1024, 1536x1024, 1024x1536, auto (default: auto)
|
||||
--image-quality= Image quality: low, medium, high, auto (default: auto)
|
||||
--image-compression= Compression level 0-100 for JPEG/WebP formats (default: not set)
|
||||
--image-background= Background type: opaque, transparent (default: opaque, only for
|
||||
PNG/WebP)
|
||||
|
||||
Help Options:
|
||||
-h, --help Show this help message
|
||||
-h, --help Show this help message
|
||||
|
||||
```
|
||||
|
||||
@@ -462,31 +597,29 @@ Now let's look at some things you can do with Fabric.
|
||||
|
||||
1. Run the `summarize` Pattern based on input from `stdin`. In this case, the body of an article.
|
||||
|
||||
```bash
|
||||
pbpaste | fabric --pattern summarize
|
||||
```
|
||||
```bash
|
||||
pbpaste | fabric --pattern summarize
|
||||
```
|
||||
|
||||
2. Run the `analyze_claims` Pattern with the `--stream` option to get immediate and streaming results.
|
||||
|
||||
```bash
|
||||
pbpaste | fabric --stream --pattern analyze_claims
|
||||
```
|
||||
```bash
|
||||
pbpaste | fabric --stream --pattern analyze_claims
|
||||
```
|
||||
|
||||
3. Run the `extract_wisdom` Pattern with the `--stream` option to get immediate and streaming results from any Youtube video (much like in the original introduction video).
|
||||
|
||||
```bash
|
||||
fabric -y "https://youtube.com/watch?v=uXs-zPc63kM" --stream --pattern extract_wisdom
|
||||
```
|
||||
3. Run the `extract_wisdom` Pattern with the `--stream` option to get immediate and streaming results from any Youtube video (much like in the original introduction video).
|
||||
|
||||
```bash
|
||||
fabric -y "https://youtube.com/watch?v=uXs-zPc63kM" --stream --pattern extract_wisdom
|
||||
```
|
||||
|
||||
4. Create patterns- you must create a .md file with the pattern and save it to `~/.config/fabric/patterns/[yourpatternname]`.
|
||||
|
||||
|
||||
5. Run a `analyze_claims` pattern on a website. Fabric uses Jina AI to scrape the URL into markdown format before sending it to the model.
|
||||
|
||||
```bash
|
||||
fabric -u https://github.com/danielmiessler/fabric/ -p analyze_claims
|
||||
```
|
||||
```bash
|
||||
fabric -u https://github.com/danielmiessler/fabric/ -p analyze_claims
|
||||
```
|
||||
|
||||
## Just use the Patterns
|
||||
|
||||
@@ -503,20 +636,67 @@ You can use any of the Patterns you see there in any AI application that you hav
|
||||
|
||||
The wisdom of crowds for the win.
|
||||
|
||||
### Prompt Strategies
|
||||
|
||||
Fabric also implements prompt strategies like "Chain of Thought" or "Chain of Draft" which can
|
||||
be used in addition to the basic patterns.
|
||||
|
||||
See the [Thinking Faster by Writing Less](https://arxiv.org/pdf/2502.18600) paper and
|
||||
the [Thought Generation section of Learn Prompting](https://learnprompting.org/docs/advanced/thought_generation/introduction) for examples of prompt strategies.
|
||||
|
||||
Each strategy is available as a small `json` file in the [`/strategies`](https://github.com/danielmiessler/fabric/tree/main/strategies) directory.
|
||||
|
||||
The prompt modification of the strategy is applied to the system prompt and passed on to the
|
||||
LLM in the chat session.
|
||||
|
||||
Use `fabric -S` and select the option to install the strategies in your `~/.config/fabric` directory.
|
||||
|
||||
## Custom Patterns
|
||||
|
||||
You may want to use Fabric to create your own custom Patterns—but not share them with others. No problem!
|
||||
|
||||
Just make a directory in `~/.config/custompatterns/` (or wherever) and put your `.md` files in there.
|
||||
Fabric now supports a dedicated custom patterns directory that keeps your personal patterns separate from the built-in ones. This means your custom patterns won't be overwritten when you update Fabric's built-in patterns.
|
||||
|
||||
When you're ready to use them, copy them into:
|
||||
### Setting Up Custom Patterns
|
||||
|
||||
```
|
||||
~/.config/fabric/patterns/
|
||||
```
|
||||
1. Run the Fabric setup:
|
||||
|
||||
You can then use them like any other Patterns, but they won't be public unless you explicitly submit them as Pull Requests to the Fabric project. So don't worry—they're private to you.
|
||||
```bash
|
||||
fabric --setup
|
||||
```
|
||||
|
||||
2. Select the "Custom Patterns" option from the Tools menu and enter your desired directory path (e.g., `~/my-custom-patterns`)
|
||||
|
||||
3. Fabric will automatically create the directory if it does not exist.
|
||||
|
||||
### Using Custom Patterns
|
||||
|
||||
1. Create your custom pattern directory structure:
|
||||
|
||||
```bash
|
||||
mkdir -p ~/my-custom-patterns/my-analyzer
|
||||
```
|
||||
|
||||
2. Create your pattern file
|
||||
|
||||
```bash
|
||||
echo "You are an expert analyzer of ..." > ~/my-custom-patterns/my-analyzer/system.md
|
||||
```
|
||||
|
||||
3. **Use your custom pattern:**
|
||||
|
||||
```bash
|
||||
fabric --pattern my-analyzer "analyze this text"
|
||||
```
|
||||
|
||||
### How It Works
|
||||
|
||||
- **Priority System**: Custom patterns take precedence over built-in patterns with the same name
|
||||
- **Seamless Integration**: Custom patterns appear in `fabric --listpatterns` alongside built-in ones
|
||||
- **Update Safe**: Your custom patterns are never affected by `fabric --updatepatterns`
|
||||
- **Private by Default**: Custom patterns remain private unless you explicitly share them
|
||||
|
||||
Your custom patterns are completely private and won't be affected by Fabric updates!
|
||||
|
||||
## Helper Apps
|
||||
|
||||
@@ -545,11 +725,25 @@ This will create a PDF file named `output.pdf` in the current directory.
|
||||
To install `to_pdf`, install it the same way as you install Fabric, just with a different repo name.
|
||||
|
||||
```bash
|
||||
go install github.com/danielmiessler/fabric/plugins/tools/to_pdf@latest
|
||||
go install github.com/danielmiessler/fabric/cmd/to_pdf@latest
|
||||
```
|
||||
|
||||
Make sure you have a LaTeX distribution (like TeX Live or MiKTeX) installed on your system, as `to_pdf` requires `pdflatex` to be available in your system's PATH.
|
||||
|
||||
### `code_helper`
|
||||
|
||||
`code_helper` is used in conjunction with the `create_coding_feature` pattern.
|
||||
It generates a `json` representation of a directory of code that can be fed into an AI model
|
||||
with instructions to create a new feature or edit the code in a specified way.
|
||||
|
||||
See [the Create Coding Feature Pattern README](./patterns/create_coding_feature/README.md) for details.
|
||||
|
||||
Install it first using:
|
||||
|
||||
```bash
|
||||
go install github.com/danielmiessler/fabric/cmd/code_helper@latest
|
||||
```
|
||||
|
||||
## pbpaste
|
||||
|
||||
The [examples](#examples) use the macOS program `pbpaste` to paste content from the clipboard to pipe into `fabric` as the input. `pbpaste` is not available on Windows or Linux, but there are alternatives.
|
||||
@@ -575,16 +769,16 @@ alias pbpaste='xclip -selection clipboard -o'
|
||||
|
||||
## Web Interface
|
||||
|
||||
Fabric now includes a built-in web interface that provides a GUI alternative to the command-line interface and an out-of-the-box website for those who want to get started with web development or blogging.
|
||||
Fabric now includes a built-in web interface that provides a GUI alternative to the command-line interface and an out-of-the-box website for those who want to get started with web development or blogging.
|
||||
You can use this app as a GUI interface for Fabric, a ready to go blog-site, or a website template for your own projects.
|
||||
|
||||
The `web/src/lib/content` directory includes starter `.obsidian/` and `templates/` directories, allowing you to open up the `web/src/lib/content/` directory as an [Obsidian.md](https://obsidian.md) vault. You can place your posts in the posts directory when you're ready to publish.
|
||||
|
||||
### Installing
|
||||
|
||||
The GUI can be installed by navigating to the `web` directory and using `npm install`, `pnpm install`, or your favorite package manager. Then simply run the development server to start the app.
|
||||
The GUI can be installed by navigating to the `web` directory and using `npm install`, `pnpm install`, or your favorite package manager. Then simply run the development server to start the app.
|
||||
|
||||
_You will need to run fabric in a separate terminal with the `fabric --serve` command._
|
||||
_You will need to run fabric in a separate terminal with the `fabric --serve` command._
|
||||
|
||||
**From the fabric project `web/` directory:**
|
||||
|
||||
@@ -604,7 +798,10 @@ To run the Streamlit user interface:
|
||||
|
||||
```bash
|
||||
# Install required dependencies
|
||||
pip install streamlit pandas matplotlib seaborn numpy python-dotenv
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Or manually install dependencies
|
||||
pip install streamlit pandas matplotlib seaborn numpy python-dotenv pyperclip
|
||||
|
||||
# Run the Streamlit app
|
||||
streamlit run streamlit.py
|
||||
@@ -617,6 +814,14 @@ The Streamlit UI provides a user-friendly interface for:
|
||||
- Creating and editing patterns
|
||||
- Analyzing pattern results
|
||||
|
||||
#### Clipboard Support
|
||||
|
||||
The Streamlit UI supports clipboard operations across different platforms:
|
||||
|
||||
- **macOS**: Uses `pbcopy` and `pbpaste` (built-in)
|
||||
- **Windows**: Uses `pyperclip` library (install with `pip install pyperclip`)
|
||||
- **Linux**: Uses `xclip` (install with `sudo apt-get install xclip` or equivalent for your Linux distribution)
|
||||
|
||||
## Meta
|
||||
|
||||
> [!NOTE]
|
||||
@@ -633,10 +838,18 @@ The Streamlit UI provides a user-friendly interface for:
|
||||
|
||||
### Primary contributors
|
||||
|
||||
<a href="https://github.com/danielmiessler"><img src="https://avatars.githubusercontent.com/u/50654?v=4" title="Daniel Miessler" width="50" height="50"></a>
|
||||
<a href="https://github.com/xssdoctor"><img src="https://avatars.githubusercontent.com/u/9218431?v=4" title="Jonathan Dunn" width="50" height="50"></a>
|
||||
<a href="https://github.com/sbehrens"><img src="https://avatars.githubusercontent.com/u/688589?v=4" title="Scott Behrens" width="50" height="50"></a>
|
||||
<a href="https://github.com/agu3rra"><img src="https://avatars.githubusercontent.com/u/10410523?v=4" title="Andre Guerra" width="50" height="50"></a>
|
||||
<a href="https://github.com/danielmiessler"><img src="https://avatars.githubusercontent.com/u/50654?v=4" title="Daniel Miessler" width="50" height="50" alt="Daniel Miessler"></a>
|
||||
<a href="https://github.com/xssdoctor"><img src="https://avatars.githubusercontent.com/u/9218431?v=4" title="Jonathan Dunn" width="50" height="50" alt="Jonathan Dunn"></a>
|
||||
<a href="https://github.com/sbehrens"><img src="https://avatars.githubusercontent.com/u/688589?v=4" title="Scott Behrens" width="50" height="50" alt="Scott Behrens"></a>
|
||||
<a href="https://github.com/agu3rra"><img src="https://avatars.githubusercontent.com/u/10410523?v=4" title="Andre Guerra" width="50" height="50" alt="Andre Guerra"></a>
|
||||
|
||||
### Contributors
|
||||
|
||||
<a href="https://github.com/danielmiessler/fabric/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=danielmiessler/fabric" alt="contrib.rocks" />
|
||||
</a>
|
||||
|
||||
Made with [contrib.rocks](https://contrib.rocks).
|
||||
|
||||
`fabric` was created by <a href="https://danielmiessler.com/subscribe" target="_blank">Daniel Miessler</a> in January of 2024.
|
||||
<br /><br />
|
||||
|
||||
@@ -1,295 +0,0 @@
|
||||
This Cummulative PR adds several Web UI and functionality improvements to make pattern selection more intuitive with the addition of pattern descriptions, ability to save favorite patterns, a Pattern TAG system, powerful multilingual capabilities, PDF-to-markdown functionnalities, a help reference section, more robust Youtube processing and a variety of other ui improvements.
|
||||
|
||||
## 🎥 Demo Video
|
||||
https://youtu.be/XMzjgqvdltM
|
||||
|
||||
|
||||
|
||||
## 🌟 Key Features
|
||||
|
||||
### 1. Web UI and Pattern Selection Improvements
|
||||
- Pattern Descriptions
|
||||
- Pattern Tags
|
||||
- Pattern Favourites
|
||||
- Pattern Search bar
|
||||
- PDF to markdown (pdf as pattern input)
|
||||
- Better handling of Youtube url
|
||||
- Multilingual Support
|
||||
- Web UI refinements for clearer interaction
|
||||
- Help section via modal
|
||||
|
||||
### 2. Multilingual Support System
|
||||
- Seamless language switching via UI dropdown
|
||||
- Persistent language state management
|
||||
- Pattern processing now use the selected language seamlessly
|
||||
|
||||
### 3. YouTube Integration Enhancement
|
||||
- Robust language handling for YouTube transcript processing
|
||||
- Chunk-based language maintenance for long transcripts
|
||||
- Consistent language output throughout transcript analysis
|
||||
|
||||
### 4. Enhanced Tag Management Integration
|
||||
|
||||
The tag filtering system has been deeply integrated into the Pattern Selection interface through several UI enhancements:
|
||||
|
||||
1. **Dual-Position Tag Panel**
|
||||
- Sliding panel positioned to the right of pattern modal
|
||||
- Dynamic toggle button that adapts position and text based on panel state
|
||||
- Smooth transitions for opening/closing animations
|
||||
|
||||
2. **Tag Selection Visibility**
|
||||
- New dedicated tag display section in pattern modal
|
||||
- Visual separation through subtle background styling
|
||||
- Immediate feedback showing selected tags with comma separation
|
||||
- Inline reset capability for quick tag clearing
|
||||
|
||||
3. **Improved User Experience**
|
||||
- Clear visual hierarchy between pattern list and tag filtering
|
||||
- Multiple ways to manage tags (panel or quick reset)
|
||||
- Consistent styling with existing design language
|
||||
- Space-efficient tag brick layout in 3-column grid
|
||||
|
||||
4. **Technical Implementation**
|
||||
- Reactive tag state management
|
||||
- Efficient tag filtering logic
|
||||
- Proper event dispatching between components
|
||||
- Maintained accessibility standards
|
||||
- Responsive design considerations
|
||||
|
||||
|
||||
5. **PDF to Markdown conversion functionality for the web interface**
|
||||
- Automatic detection and processing of PDF files in chat
|
||||
- Conversion to markdown format for LLM processing
|
||||
- Installation instructions from the pdf-to-markdown repository
|
||||
|
||||
The PDF conversion module has been integrated in the svelte web browser interface. Once installed, it will automatically detect pdf files in the chat interface and convert them to markdown
|
||||
|
||||
|
||||
## HOW TO INSTALL PDF-TO-MARKDOWN
|
||||
If you need to update the web component follow the instructions in "Web Interface MOD Readme Files/WEB V2 Install Guide.md".
|
||||
|
||||
Assuming your web install is up to date and web svelte config complete, you can simply follow these steps to add Pdf-to-mardown.
|
||||
|
||||
# FROM FABRIC ROOT DIRECTORY
|
||||
cd .. web
|
||||
|
||||
# Install in this sequence:
|
||||
# Step 1
|
||||
npm install -D patch-package
|
||||
# Step 2
|
||||
npm install -D pdfjs-dist@2.5.207
|
||||
# Step 3
|
||||
npm install -D github:jzillmann/pdf-to-markdown#modularize
|
||||
|
||||
These enhancements create a more intuitive and efficient pattern discovery experience, allowing users to quickly filter and find relevant patterns while maintaining a clean, modern interface.
|
||||
|
||||
|
||||
## 🛠 Technical Implementation
|
||||
|
||||
### Language Support Architecture
|
||||
```typescript
|
||||
// Language state management
|
||||
export const languageStore = writable<string>('');
|
||||
|
||||
// Chat input language detection
|
||||
if (qualifier === 'fr') {
|
||||
languageStore.set('fr');
|
||||
userInput = userInput.replace(/--fr\s*/, '');
|
||||
}
|
||||
|
||||
// Service layer integration
|
||||
const language = get(languageStore) || 'en';
|
||||
const languageInstruction = language !== 'en'
|
||||
? `. Please use the language '${language}' for the output.`
|
||||
: '';
|
||||
```
|
||||
|
||||
### YouTube Processing Enhancement
|
||||
```typescript
|
||||
// Process stream with language instruction per chunk
|
||||
await chatService.processStream(
|
||||
stream,
|
||||
(content: string, response?: StreamResponse) => {
|
||||
if (currentLanguage !== 'en') {
|
||||
content = `${content}. Please use the language '${currentLanguage}' for the output.`;
|
||||
}
|
||||
// Update messages...
|
||||
}
|
||||
);
|
||||
```
|
||||
# Pattern Descriptions and Tags Management
|
||||
|
||||
This document explains the complete workflow for managing pattern descriptions and tags, including how to process new patterns and maintain metadata.
|
||||
|
||||
## System Overview
|
||||
|
||||
The pattern system follows this hierarchy:
|
||||
1. `~/.config/fabric/patterns/` directory: The source of truth for available patterns
|
||||
2. `pattern_extracts.json`: Contains first 500 words of each pattern for reference
|
||||
3. `pattern_descriptions.json`: Stores pattern metadata (descriptions and tags)
|
||||
4. `web/static/data/pattern_descriptions.json`: Web-accessible copy for the interface
|
||||
|
||||
## Pattern Processing Workflow
|
||||
|
||||
### 1. Adding New Patterns
|
||||
- Add patterns to `~/.config/fabric/patterns/`
|
||||
- Run extract_patterns.py to process new additions:
|
||||
```bash
|
||||
python extract_patterns.py
|
||||
|
||||
The Python Script automatically:
|
||||
- Creates pattern extracts for reference
|
||||
- Adds placeholder entries in descriptions file
|
||||
- Syncs to web interface
|
||||
|
||||
### 2. Pattern Extract Creation
|
||||
The script extracts first 500 words from each pattern's system.md file to:
|
||||
|
||||
- Provide context for writing descriptions
|
||||
- Maintain reference material
|
||||
- Aid in pattern categorization
|
||||
|
||||
### 3. Description and Tag Management
|
||||
Pattern descriptions and tags are managed in pattern_descriptions.json:
|
||||
|
||||
|
||||
{
|
||||
"patterns": [
|
||||
{
|
||||
"patternName": "pattern_name",
|
||||
"description": "[Description pending]",
|
||||
"tags": []
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
## Completing Pattern Metadata
|
||||
|
||||
### Writing Descriptions
|
||||
1. Check pattern_descriptions.json for "[Description pending]" entries
|
||||
2. Reference pattern_extracts.json for context
|
||||
|
||||
3. How to update Pattern short descriptions (one sentence).
|
||||
|
||||
You can update your descriptions in pattern_descriptions.json manually or using LLM assistance (prefered approach).
|
||||
|
||||
Tell AI to look for "Description pending" entries in this file and write a short description based on the extract info in the pattern_extracts.json file. You can also ask your LLM to add tags for those newly added patterns, using other patterns tag assignments as example.
|
||||
|
||||
### Managing Tags
|
||||
1. Add appropriate tags to new patterns
|
||||
2. Update existing tags as needed
|
||||
3. Tags are stored as arrays: ["TAG1", "TAG2"]
|
||||
4. Edit pattern_descriptions.json directly to modify tags
|
||||
5. Make tags your own. You can delete, replace, amend existing tags.
|
||||
|
||||
## File Synchronization
|
||||
|
||||
The script maintains synchronization between:
|
||||
- Local pattern_descriptions.json
|
||||
- Web interface copy in static/data/
|
||||
- No manual file copying needed
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. Run extract_patterns.py when:
|
||||
- Adding new patterns
|
||||
- Updating existing patterns
|
||||
- Modifying pattern structure
|
||||
|
||||
2. Description Writing:
|
||||
- Use pattern extracts for context
|
||||
- Keep descriptions clear and concise
|
||||
- Focus on pattern purpose and usage
|
||||
|
||||
3. Tag Management:
|
||||
- Use consistent tag categories
|
||||
- Apply multiple tags when relevant
|
||||
- Update tags to reflect pattern evolution
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If patterns are not showing in the web interface:
|
||||
1. Verify pattern_descriptions.json format
|
||||
2. Check web static copy exists
|
||||
3. Ensure proper file permissions
|
||||
4. Run extract_patterns.py to resync
|
||||
|
||||
## File Structure
|
||||
|
||||
fabric/
|
||||
├── patterns/ # Pattern source files
|
||||
├── PATTERN_DESCRIPTIONS/
|
||||
│ ├── extract_patterns.py # Pattern processing script
|
||||
│ ├── pattern_extracts.json # Pattern content references
|
||||
│ └── pattern_descriptions.json # Pattern metadata
|
||||
└── web/
|
||||
└── static/
|
||||
└── data/
|
||||
└── pattern_descriptions.json # Web interface copy
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## 🎯 Usage Examples
|
||||
|
||||
### 1. Using Language Qualifiers
|
||||
```
|
||||
User: What is the weather?
|
||||
AI: The weather information...
|
||||
|
||||
User: --fr What is the weather?
|
||||
AI: Voici les informations météo...
|
||||
```
|
||||
|
||||
### 2. Global Settings
|
||||
1. Select language from dropdown
|
||||
2. All interactions use selected language
|
||||
3. Automatic reset to English after each message
|
||||
|
||||
### 3. YouTube Analysis
|
||||
```
|
||||
User: Analyze this YouTube video --fr
|
||||
AI: [Provides analysis in French, maintaining language throughout the transcript]
|
||||
```
|
||||
|
||||
## 💡 Key Benefits
|
||||
|
||||
1. **Enhanced User Experience**
|
||||
- Intuitive language switching
|
||||
- Consistent language handling
|
||||
- Seamless integration with existing features
|
||||
|
||||
2. **Robust Implementation**
|
||||
- Simple yet powerful design
|
||||
- No complex language detection needed
|
||||
- Direct AI instruction approach
|
||||
|
||||
3. **Maintainable Architecture**
|
||||
- Clean separation of concerns
|
||||
- Stateful language management
|
||||
- Easy to extend for new languages
|
||||
|
||||
4. **YouTube Integration**
|
||||
- Handles long transcripts effectively
|
||||
- Maintains language consistency
|
||||
- Robust chunk processing
|
||||
|
||||
## 🔄 Implementation Notes
|
||||
|
||||
1. **State Management**
|
||||
- Language persists until changed
|
||||
- Resets to English after each message
|
||||
- Handles UI state updates efficiently
|
||||
|
||||
2. **Error Handling**
|
||||
- Invalid qualifiers are ignored
|
||||
- Unknown languages default to English
|
||||
- Proper store reset on errors
|
||||
|
||||
3. **Best Practices**
|
||||
- Clear language instructions
|
||||
- Consistent state management
|
||||
- Robust error handling
|
||||
|
||||
341
cli/cli.go
341
cli/cli.go
@@ -1,341 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/danielmiessler/fabric/plugins/tools/youtube"
|
||||
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
"github.com/danielmiessler/fabric/core"
|
||||
"github.com/danielmiessler/fabric/plugins/ai"
|
||||
"github.com/danielmiessler/fabric/plugins/db/fsdb"
|
||||
"github.com/danielmiessler/fabric/plugins/tools/converter"
|
||||
"github.com/danielmiessler/fabric/restapi"
|
||||
)
|
||||
|
||||
// Cli Controls the cli. It takes in the flags and runs the appropriate functions
|
||||
func Cli(version string) (err error) {
|
||||
var currentFlags *Flags
|
||||
if currentFlags, err = Init(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.Version {
|
||||
fmt.Println(version)
|
||||
return
|
||||
}
|
||||
|
||||
var homedir string
|
||||
if homedir, err = os.UserHomeDir(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fabricDb := fsdb.NewDb(filepath.Join(homedir, ".config/fabric"))
|
||||
|
||||
if err = fabricDb.Configure(); err != nil {
|
||||
if !currentFlags.Setup {
|
||||
println(err.Error())
|
||||
currentFlags.Setup = true
|
||||
}
|
||||
}
|
||||
|
||||
var registry *core.PluginRegistry
|
||||
if registry, err = core.NewPluginRegistry(fabricDb); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// if the setup flag is set, run the setup function
|
||||
if currentFlags.Setup {
|
||||
err = registry.Setup()
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.Serve {
|
||||
registry.ConfigureVendors()
|
||||
err = restapi.Serve(registry, currentFlags.ServeAddress)
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.ServeOllama {
|
||||
registry.ConfigureVendors()
|
||||
err = restapi.ServeOllama(registry, currentFlags.ServeAddress, version)
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.UpdatePatterns {
|
||||
err = registry.PatternsLoader.PopulateDB()
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.ChangeDefaultModel {
|
||||
err = registry.Defaults.Setup()
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.LatestPatterns != "0" {
|
||||
var parsedToInt int
|
||||
if parsedToInt, err = strconv.Atoi(currentFlags.LatestPatterns); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = fabricDb.Patterns.PrintLatestPatterns(parsedToInt); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.ListPatterns {
|
||||
err = fabricDb.Patterns.ListNames()
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.ListAllModels {
|
||||
var models *ai.VendorsModels
|
||||
if models, err = registry.VendorManager.GetModels(); err != nil {
|
||||
return
|
||||
}
|
||||
models.Print()
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.ListAllContexts {
|
||||
err = fabricDb.Contexts.ListNames()
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.ListAllSessions {
|
||||
err = fabricDb.Sessions.ListNames()
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.WipeContext != "" {
|
||||
err = fabricDb.Contexts.Delete(currentFlags.WipeContext)
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.WipeSession != "" {
|
||||
err = fabricDb.Sessions.Delete(currentFlags.WipeSession)
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.PrintSession != "" {
|
||||
err = fabricDb.Sessions.PrintSession(currentFlags.PrintSession)
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.PrintContext != "" {
|
||||
err = fabricDb.Contexts.PrintContext(currentFlags.PrintContext)
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.HtmlReadability {
|
||||
if msg, cleanErr := converter.HtmlReadability(currentFlags.Message); cleanErr != nil {
|
||||
fmt.Println("use original input, because can't apply html readability", err)
|
||||
} else {
|
||||
currentFlags.Message = msg
|
||||
}
|
||||
}
|
||||
|
||||
if currentFlags.ListExtensions {
|
||||
err = registry.TemplateExtensions.ListExtensions()
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.AddExtension != "" {
|
||||
err = registry.TemplateExtensions.RegisterExtension(currentFlags.AddExtension)
|
||||
return
|
||||
}
|
||||
|
||||
if currentFlags.RemoveExtension != "" {
|
||||
err = registry.TemplateExtensions.RemoveExtension(currentFlags.RemoveExtension)
|
||||
return
|
||||
}
|
||||
|
||||
// if the interactive flag is set, run the interactive function
|
||||
// if currentFlags.Interactive {
|
||||
// interactive.Interactive()
|
||||
// }
|
||||
|
||||
// if none of the above currentFlags are set, run the initiate chat function
|
||||
|
||||
var messageTools string
|
||||
|
||||
if currentFlags.YouTube != "" {
|
||||
if registry.YouTube.IsConfigured() == false {
|
||||
err = fmt.Errorf("YouTube is not configured, please run the setup procedure")
|
||||
return
|
||||
}
|
||||
|
||||
var videoId string
|
||||
var playlistId string
|
||||
if videoId, playlistId, err = registry.YouTube.GetVideoOrPlaylistId(currentFlags.YouTube); err != nil {
|
||||
return
|
||||
} else if (videoId == "" || currentFlags.YouTubePlaylist) && playlistId != "" {
|
||||
if currentFlags.Output != "" {
|
||||
err = registry.YouTube.FetchAndSavePlaylist(playlistId, currentFlags.Output)
|
||||
} else {
|
||||
var videos []*youtube.VideoMeta
|
||||
if videos, err = registry.YouTube.FetchPlaylistVideos(playlistId); err != nil {
|
||||
err = fmt.Errorf("error fetching playlist videos: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, video := range videos {
|
||||
var message string
|
||||
if message, err = processYoutubeVideo(currentFlags, registry, video.Id); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !currentFlags.IsChatRequest() {
|
||||
if err = WriteOutput(message, fmt.Sprintf("%v.md", video.TitleNormalized)); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
messageTools = AppendMessage(messageTools, message)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
messageTools, err = processYoutubeVideo(currentFlags, registry, videoId)
|
||||
if !currentFlags.IsChatRequest() {
|
||||
err = currentFlags.WriteOutput(messageTools)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (currentFlags.ScrapeURL != "" || currentFlags.ScrapeQuestion != "") && registry.Jina.IsConfigured() {
|
||||
// Check if the scrape_url flag is set and call ScrapeURL
|
||||
if currentFlags.ScrapeURL != "" {
|
||||
var website string
|
||||
if website, err = registry.Jina.ScrapeURL(currentFlags.ScrapeURL); err != nil {
|
||||
return
|
||||
}
|
||||
messageTools = AppendMessage(messageTools, website)
|
||||
}
|
||||
|
||||
// Check if the scrape_question flag is set and call ScrapeQuestion
|
||||
if currentFlags.ScrapeQuestion != "" {
|
||||
var website string
|
||||
if website, err = registry.Jina.ScrapeQuestion(currentFlags.ScrapeQuestion); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
messageTools = AppendMessage(messageTools, website)
|
||||
}
|
||||
|
||||
if !currentFlags.IsChatRequest() {
|
||||
err = currentFlags.WriteOutput(messageTools)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if messageTools != "" {
|
||||
currentFlags.AppendMessage(messageTools)
|
||||
}
|
||||
|
||||
var chatter *core.Chatter
|
||||
if chatter, err = registry.GetChatter(currentFlags.Model, currentFlags.ModelContextLength, currentFlags.Stream, currentFlags.DryRun); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var session *fsdb.Session
|
||||
var chatReq *common.ChatRequest
|
||||
if chatReq, err = currentFlags.BuildChatRequest(strings.Join(os.Args[1:], " ")); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if chatReq.Language == "" {
|
||||
chatReq.Language = registry.Language.DefaultLanguage.Value
|
||||
}
|
||||
if session, err = chatter.Send(chatReq, currentFlags.BuildChatOptions()); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
result := session.GetLastMessage().Content
|
||||
|
||||
if !currentFlags.Stream {
|
||||
// print the result if it was not streamed already
|
||||
fmt.Println(result)
|
||||
}
|
||||
|
||||
// if the copy flag is set, copy the message to the clipboard
|
||||
if currentFlags.Copy {
|
||||
if err = CopyToClipboard(result); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// if the output flag is set, create an output file
|
||||
if currentFlags.Output != "" {
|
||||
if currentFlags.OutputSession {
|
||||
sessionAsString := session.String()
|
||||
err = CreateOutputFile(sessionAsString, currentFlags.Output)
|
||||
} else {
|
||||
err = CreateOutputFile(result, currentFlags.Output)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func processYoutubeVideo(
|
||||
flags *Flags, registry *core.PluginRegistry, videoId string) (message string, err error) {
|
||||
|
||||
if (!flags.YouTubeComments && !flags.YouTubeMetadata) || flags.YouTubeTranscript || flags.YouTubeTranscriptWithTimestamps {
|
||||
var transcript string
|
||||
var language = "en"
|
||||
if flags.Language != "" || registry.Language.DefaultLanguage.Value != "" {
|
||||
if flags.Language != "" {
|
||||
language = flags.Language
|
||||
} else {
|
||||
language = registry.Language.DefaultLanguage.Value
|
||||
}
|
||||
}
|
||||
if flags.YouTubeTranscriptWithTimestamps {
|
||||
if transcript, err = registry.YouTube.GrabTranscriptWithTimestamps(videoId, language); err != nil {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if transcript, err = registry.YouTube.GrabTranscript(videoId, language); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
message = AppendMessage(message, transcript)
|
||||
}
|
||||
|
||||
if flags.YouTubeComments {
|
||||
var comments []string
|
||||
if comments, err = registry.YouTube.GrabComments(videoId); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
commentsString := strings.Join(comments, "\n")
|
||||
|
||||
message = AppendMessage(message, commentsString)
|
||||
}
|
||||
|
||||
if flags.YouTubeMetadata {
|
||||
var metadata *youtube.VideoMetadata
|
||||
if metadata, err = registry.YouTube.GrabMetadata(videoId); err != nil {
|
||||
return
|
||||
}
|
||||
metadataJson, _ := json.MarshalIndent(metadata, "", " ")
|
||||
message = AppendMessage(message, string(metadataJson))
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func WriteOutput(message string, outputFile string) (err error) {
|
||||
fmt.Println(message)
|
||||
if outputFile != "" {
|
||||
err = CreateOutputFile(message, outputFile)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestInit(t *testing.T) {
|
||||
args := []string{"--copy"}
|
||||
expectedFlags := &Flags{Copy: true}
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
os.Args = append([]string{"cmd"}, args...)
|
||||
|
||||
flags, err := Init()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expectedFlags.Copy, flags.Copy)
|
||||
}
|
||||
|
||||
func TestReadStdin(t *testing.T) {
|
||||
input := "test input"
|
||||
stdin := io.NopCloser(strings.NewReader(input))
|
||||
// No need to cast stdin to *os.File, pass it as io.ReadCloser directly
|
||||
content, err := ReadStdin(stdin)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if content != input {
|
||||
t.Fatalf("expected %q, got %q", input, content)
|
||||
}
|
||||
}
|
||||
|
||||
// ReadStdin function assuming it's part of `cli` package
|
||||
func ReadStdin(reader io.ReadCloser) (string, error) {
|
||||
defer reader.Close()
|
||||
buf := new(bytes.Buffer)
|
||||
_, err := buf.ReadFrom(reader)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
func TestBuildChatOptions(t *testing.T) {
|
||||
flags := &Flags{
|
||||
Temperature: 0.8,
|
||||
TopP: 0.9,
|
||||
PresencePenalty: 0.1,
|
||||
FrequencyPenalty: 0.2,
|
||||
Seed: 1,
|
||||
}
|
||||
|
||||
expectedOptions := &common.ChatOptions{
|
||||
Temperature: 0.8,
|
||||
TopP: 0.9,
|
||||
PresencePenalty: 0.1,
|
||||
FrequencyPenalty: 0.2,
|
||||
Raw: false,
|
||||
Seed: 1,
|
||||
}
|
||||
options := flags.BuildChatOptions()
|
||||
assert.Equal(t, expectedOptions, options)
|
||||
}
|
||||
|
||||
func TestBuildChatOptionsDefaultSeed(t *testing.T) {
|
||||
flags := &Flags{
|
||||
Temperature: 0.8,
|
||||
TopP: 0.9,
|
||||
PresencePenalty: 0.1,
|
||||
FrequencyPenalty: 0.2,
|
||||
}
|
||||
|
||||
expectedOptions := &common.ChatOptions{
|
||||
Temperature: 0.8,
|
||||
TopP: 0.9,
|
||||
PresencePenalty: 0.1,
|
||||
FrequencyPenalty: 0.2,
|
||||
Raw: false,
|
||||
Seed: 0,
|
||||
}
|
||||
options := flags.BuildChatOptions()
|
||||
assert.Equal(t, expectedOptions, options)
|
||||
}
|
||||
|
||||
func TestInitWithYAMLConfig(t *testing.T) {
|
||||
// Create a temporary YAML config file
|
||||
configContent := `
|
||||
temperature: 0.9
|
||||
model: gpt-4
|
||||
pattern: analyze
|
||||
stream: true
|
||||
`
|
||||
tmpfile, err := os.CreateTemp("", "config.*.yaml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(tmpfile.Name())
|
||||
|
||||
if _, err := tmpfile.Write([]byte(configContent)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := tmpfile.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Test 1: Basic YAML loading
|
||||
t.Run("Load YAML config", func(t *testing.T) {
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
os.Args = []string{"cmd", "--config", tmpfile.Name()}
|
||||
|
||||
flags, err := Init()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0.9, flags.Temperature)
|
||||
assert.Equal(t, "gpt-4", flags.Model)
|
||||
assert.Equal(t, "analyze", flags.Pattern)
|
||||
assert.True(t, flags.Stream)
|
||||
})
|
||||
|
||||
// Test 2: CLI overrides YAML
|
||||
t.Run("CLI overrides YAML", func(t *testing.T) {
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
os.Args = []string{"cmd", "--config", tmpfile.Name(), "--temperature", "0.7", "--model", "gpt-3.5-turbo"}
|
||||
|
||||
flags, err := Init()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, 0.7, flags.Temperature)
|
||||
assert.Equal(t, "gpt-3.5-turbo", flags.Model)
|
||||
assert.Equal(t, "analyze", flags.Pattern) // unchanged from YAML
|
||||
assert.True(t, flags.Stream) // unchanged from YAML
|
||||
})
|
||||
|
||||
// Test 3: Invalid YAML config
|
||||
t.Run("Invalid YAML config", func(t *testing.T) {
|
||||
badConfig := `
|
||||
temperature: "not a float"
|
||||
model: 123 # should be string
|
||||
`
|
||||
badfile, err := os.CreateTemp("", "bad-config.*.yaml")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer os.Remove(badfile.Name())
|
||||
|
||||
if _, err := badfile.Write([]byte(badConfig)); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := badfile.Close(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
oldArgs := os.Args
|
||||
defer func() { os.Args = oldArgs }()
|
||||
os.Args = []string{"cmd", "--config", badfile.Name()}
|
||||
|
||||
_, err = Init()
|
||||
assert.Error(t, err)
|
||||
})
|
||||
}
|
||||
181
cmd/code_helper/code.go
Normal file
181
cmd/code_helper/code.go
Normal file
@@ -0,0 +1,181 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// FileItem represents a file in the project
|
||||
type FileItem struct {
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Content string `json:"content,omitempty"`
|
||||
Contents []FileItem `json:"contents,omitempty"`
|
||||
}
|
||||
|
||||
// ProjectData represents the entire project structure with instructions
|
||||
type ProjectData struct {
|
||||
Files []FileItem `json:"files"`
|
||||
Instructions struct {
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
Details string `json:"details"`
|
||||
} `json:"instructions"`
|
||||
Report struct {
|
||||
Type string `json:"type"`
|
||||
Directories int `json:"directories"`
|
||||
Files int `json:"files"`
|
||||
} `json:"report"`
|
||||
}
|
||||
|
||||
// ScanDirectory scans a directory and returns a JSON representation of its structure
|
||||
func ScanDirectory(rootDir string, maxDepth int, instructions string, ignoreList []string) ([]byte, error) {
|
||||
// Count totals for report
|
||||
dirCount := 1
|
||||
fileCount := 0
|
||||
|
||||
// Create root directory item
|
||||
rootItem := FileItem{
|
||||
Type: "directory",
|
||||
Name: rootDir,
|
||||
Contents: []FileItem{},
|
||||
}
|
||||
|
||||
// Walk through the directory
|
||||
err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Skip .git directory
|
||||
if strings.Contains(path, ".git") {
|
||||
if info.IsDir() {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Check if path matches any ignore pattern
|
||||
relPath, err := filepath.Rel(rootDir, path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, pattern := range ignoreList {
|
||||
if strings.Contains(relPath, pattern) {
|
||||
if info.IsDir() {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if relPath == "." {
|
||||
return nil
|
||||
}
|
||||
|
||||
depth := len(strings.Split(relPath, string(filepath.Separator)))
|
||||
if depth > maxDepth {
|
||||
if info.IsDir() {
|
||||
return filepath.SkipDir
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create directory structure
|
||||
if info.IsDir() {
|
||||
dirCount++
|
||||
} else {
|
||||
fileCount++
|
||||
|
||||
// Read file content
|
||||
content, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error reading file %s: %v", path, err)
|
||||
}
|
||||
|
||||
// Add file to appropriate parent directory
|
||||
addFileToDirectory(&rootItem, relPath, string(content), rootDir)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Create final data structure
|
||||
var data []interface{}
|
||||
data = append(data, rootItem)
|
||||
|
||||
// Add report
|
||||
reportItem := map[string]interface{}{
|
||||
"type": "report",
|
||||
"directories": dirCount,
|
||||
"files": fileCount,
|
||||
}
|
||||
data = append(data, reportItem)
|
||||
|
||||
// Add instructions
|
||||
instructionsItem := map[string]interface{}{
|
||||
"type": "instructions",
|
||||
"name": "code_change_instructions",
|
||||
"details": instructions,
|
||||
}
|
||||
data = append(data, instructionsItem)
|
||||
|
||||
return json.MarshalIndent(data, "", " ")
|
||||
}
|
||||
|
||||
// addFileToDirectory adds a file to the correct directory in the structure
|
||||
func addFileToDirectory(root *FileItem, path, content, rootDir string) {
|
||||
parts := strings.Split(path, string(filepath.Separator))
|
||||
|
||||
// If this is a file at the root level
|
||||
if len(parts) == 1 {
|
||||
root.Contents = append(root.Contents, FileItem{
|
||||
Type: "file",
|
||||
Name: parts[0],
|
||||
Content: content,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// Otherwise, find or create the directory path
|
||||
current := root
|
||||
for i := 0; i < len(parts)-1; i++ {
|
||||
dirName := parts[i]
|
||||
found := false
|
||||
|
||||
// Look for existing directory
|
||||
for j, item := range current.Contents {
|
||||
if item.Type == "directory" && item.Name == dirName {
|
||||
current = ¤t.Contents[j]
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Create directory if not found
|
||||
if !found {
|
||||
newDir := FileItem{
|
||||
Type: "directory",
|
||||
Name: dirName,
|
||||
Contents: []FileItem{},
|
||||
}
|
||||
current.Contents = append(current.Contents, newDir)
|
||||
current = ¤t.Contents[len(current.Contents)-1]
|
||||
}
|
||||
}
|
||||
|
||||
// Add the file to the current directory
|
||||
current.Contents = append(current.Contents, FileItem{
|
||||
Type: "file",
|
||||
Name: parts[len(parts)-1],
|
||||
Content: content,
|
||||
})
|
||||
}
|
||||
65
cmd/code_helper/main.go
Normal file
65
cmd/code_helper/main.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Command line flags
|
||||
maxDepth := flag.Int("depth", 3, "Maximum directory depth to scan")
|
||||
ignorePatterns := flag.String("ignore", ".git,node_modules,vendor", "Comma-separated patterns to ignore")
|
||||
outputFile := flag.String("out", "", "Output file (default: stdout)")
|
||||
flag.Usage = printUsage
|
||||
flag.Parse()
|
||||
|
||||
// Require exactly two positional arguments: directory and instructions
|
||||
if flag.NArg() != 2 {
|
||||
printUsage()
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
directory := flag.Arg(0)
|
||||
instructions := flag.Arg(1)
|
||||
|
||||
// Validate directory
|
||||
if info, err := os.Stat(directory); err != nil || !info.IsDir() {
|
||||
fmt.Fprintf(os.Stderr, "Error: Directory '%s' does not exist or is not a directory\n", directory)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Parse ignore patterns and scan directory
|
||||
jsonData, err := ScanDirectory(directory, *maxDepth, instructions, strings.Split(*ignorePatterns, ","))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error scanning directory: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Output result
|
||||
if *outputFile != "" {
|
||||
if err := os.WriteFile(*outputFile, jsonData, 0644); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error writing file: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
fmt.Print(string(jsonData))
|
||||
}
|
||||
}
|
||||
|
||||
func printUsage() {
|
||||
fmt.Fprintf(os.Stderr, `code_helper - Code project scanner for use with Fabric AI
|
||||
|
||||
Usage:
|
||||
code_helper [options] <directory> <instructions>
|
||||
|
||||
Examples:
|
||||
code_helper . "Add input validation to all user inputs"
|
||||
code_helper -depth 4 ./my-project "Implement error handling"
|
||||
code_helper -out project.json ./src "Fix security issues"
|
||||
|
||||
Options:
|
||||
`)
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
|
||||
"github.com/jessevdk/go-flags"
|
||||
|
||||
"github.com/danielmiessler/fabric/cli"
|
||||
"github.com/danielmiessler/fabric/internal/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
3
cmd/fabric/version.go
Normal file
3
cmd/fabric/version.go
Normal file
@@ -0,0 +1,3 @@
|
||||
package main
|
||||
|
||||
var version = "v1.4.243"
|
||||
@@ -1,27 +0,0 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
goopenai "github.com/sashabaranov/go-openai"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNormalizeMessages(t *testing.T) {
|
||||
msgs := []*goopenai.ChatCompletionMessage{
|
||||
{Role: goopenai.ChatMessageRoleUser, Content: "Hello"},
|
||||
{Role: goopenai.ChatMessageRoleAssistant, Content: "Hi there!"},
|
||||
{Role: goopenai.ChatMessageRoleUser, Content: ""},
|
||||
{Role: goopenai.ChatMessageRoleUser, Content: ""},
|
||||
{Role: goopenai.ChatMessageRoleUser, Content: "How are you?"},
|
||||
}
|
||||
|
||||
expected := []*goopenai.ChatCompletionMessage{
|
||||
{Role: goopenai.ChatMessageRoleUser, Content: "Hello"},
|
||||
{Role: goopenai.ChatMessageRoleAssistant, Content: "Hi there!"},
|
||||
{Role: goopenai.ChatMessageRoleUser, Content: "How are you?"},
|
||||
}
|
||||
|
||||
actual := NormalizeMessages(msgs, "default")
|
||||
assert.Equal(t, expected, actual)
|
||||
}
|
||||
118
completions/_fabric
Normal file
118
completions/_fabric
Normal file
@@ -0,0 +1,118 @@
|
||||
#compdef fabric
|
||||
|
||||
# Zsh completion for fabric CLI
|
||||
# Place this file in a directory in your $fpath (e.g. /usr/local/share/zsh/site-functions)
|
||||
|
||||
_fabric_patterns() {
|
||||
local -a patterns
|
||||
patterns=(${(f)"$(fabric --listpatterns --shell-complete-list 2>/dev/null)"})
|
||||
compadd -X "Patterns:" ${patterns}
|
||||
}
|
||||
|
||||
_fabric_models() {
|
||||
local -a models
|
||||
models=(${(f)"$(fabric --listmodels --shell-complete-list 2>/dev/null)"})
|
||||
compadd -X "Models:" ${models}
|
||||
}
|
||||
_fabric_contexts() {
|
||||
local -a contexts
|
||||
contexts=(${(f)"$(fabric --listcontexts --shell-complete-list 2>/dev/null)"})
|
||||
compadd -X "Contexts:" ${contexts}
|
||||
}
|
||||
_fabric_sessions() {
|
||||
local -a sessions
|
||||
sessions=(${(f)"$(fabric --listsessions --shell-complete-list 2>/dev/null)"})
|
||||
compadd -X "Sessions:" ${sessions}
|
||||
}
|
||||
_fabric_strategies() {
|
||||
local -a strategies
|
||||
strategies=(${(f)"$(fabric --liststrategies --shell-complete-list 2>/dev/null)"})
|
||||
compadd -X "Strategies:" ${strategies}
|
||||
}
|
||||
|
||||
_fabric_extensions() {
|
||||
local -a extensions
|
||||
extensions=(${(f)"$(fabric --listextensions --shell-complete-list 2>/dev/null)"})
|
||||
compadd -X "Extensions:" ${extensions}
|
||||
'(-L --listmodels)'{-L,--listmodels}'[List all available models]:list models:_fabric_models' \
|
||||
'(-x --listcontexts)'{-x,--listcontexts}'[List all contexts]:list contexts:_fabric_contexts' \
|
||||
'(-X --listsessions)'{-X,--listsessions}'[List all sessions]:list sessions:_fabric_sessions' \
|
||||
'(--listextensions)--listextensions[List all registered extensions]' \
|
||||
'(--liststrategies)--liststrategies[List all strategies]:list strategies:_fabric_strategies' \
|
||||
'(--listvendors)--listvendors[List all vendors]' \
|
||||
vendors=(${(f)"$(fabric --listvendors 2>/dev/null)"})
|
||||
compadd -X "Vendors:" ${vendors}
|
||||
}
|
||||
|
||||
_fabric() {
|
||||
local curcontext="$curcontext" state line
|
||||
typeset -A opt_args
|
||||
|
||||
_arguments -C \
|
||||
'(-p --pattern)'{-p,--pattern}'[Choose a pattern from the available patterns]:pattern:_fabric_patterns' \
|
||||
'(-v --variable)'{-v,--variable}'[Values for pattern variables, e.g. -v=#role:expert -v=#points:30]:variable:' \
|
||||
'(-C --context)'{-C,--context}'[Choose a context from the available contexts]:context:_fabric_contexts' \
|
||||
'(--session)--session[Choose a session from the available sessions]:session:_fabric_sessions' \
|
||||
'(-a --attachment)'{-a,--attachment}'[Attachment path or URL (e.g. for OpenAI image recognition messages)]:file:_files' \
|
||||
'(-S --setup)'{-S,--setup}'[Run setup for all reconfigurable parts of fabric]' \
|
||||
'(-t --temperature)'{-t,--temperature}'[Set temperature (default: 0.7)]:temperature:' \
|
||||
'(-T --topp)'{-T,--topp}'[Set top P (default: 0.9)]:topp:' \
|
||||
'(-s --stream)'{-s,--stream}'[Stream]' \
|
||||
'(-P --presencepenalty)'{-P,--presencepenalty}'[Set presence penalty (default: 0.0)]:presence penalty:' \
|
||||
'(-r --raw)'{-r,--raw}'[Use the defaults of the model without sending chat options]' \
|
||||
'(-F --frequencypenalty)'{-F,--frequencypenalty}'[Set frequency penalty (default: 0.0)]:frequency penalty:' \
|
||||
'(-l --listpatterns)'{-l,--listpatterns}'[List all patterns]' \
|
||||
'(-L --listmodels)'{-L,--listmodels}'[List all available models]' \
|
||||
'(-x --listcontexts)'{-x,--listcontexts}'[List all contexts]' \
|
||||
'(-X --listsessions)'{-X,--listsessions}'[List all sessions]' \
|
||||
'(-U --updatepatterns)'{-U,--updatepatterns}'[Update patterns]' \
|
||||
'(-c --copy)'{-c,--copy}'[Copy to clipboard]' \
|
||||
'(-m --model)'{-m,--model}'[Choose model]:model:_fabric_models' \
|
||||
'(--modelContextLength)--modelContextLength[Model context length (only affects ollama)]:length:' \
|
||||
'(-o --output)'{-o,--output}'[Output to file]:file:_files' \
|
||||
'(--output-session)--output-session[Output the entire session to the output file]' \
|
||||
'(-n --latest)'{-n,--latest}'[Number of latest patterns to list (default: 0)]:number:' \
|
||||
'(-d --changeDefaultModel)'{-d,--changeDefaultModel}'[Change default model]' \
|
||||
'(-y --youtube)'{-y,--youtube}'[YouTube video or play list URL]:youtube url:' \
|
||||
'(--playlist)--playlist[Prefer playlist over video if both ids are present in the URL]' \
|
||||
'(--transcript)--transcript[Grab transcript from YouTube video and send to chat]' \
|
||||
'(--transcript-with-timestamps)--transcript-with-timestamps[Grab transcript from YouTube video with timestamps]' \
|
||||
'(--comments)--comments[Grab comments from YouTube video and send to chat]' \
|
||||
'(--metadata)--metadata[Output video metadata]' \
|
||||
'(-g --language)'{-g,--language}'[Specify the Language Code for the chat, e.g. -g=en -g=zh]:language:' \
|
||||
'(-u --scrape_url)'{-u,--scrape_url}'[Scrape website URL to markdown using Jina AI]:url:' \
|
||||
'(-q --scrape_question)'{-q,--scrape_question}'[Search question using Jina AI]:question:' \
|
||||
'(-e --seed)'{-e,--seed}'[Seed to be used for LMM generation]:seed:' \
|
||||
'(-w --wipecontext)'{-w,--wipecontext}'[Wipe context]:context:_fabric_contexts' \
|
||||
'(-W --wipesession)'{-W,--wipesession}'[Wipe session]:session:_fabric_sessions' \
|
||||
'(--printcontext)--printcontext[Print context]:context:_fabric_contexts' \
|
||||
'(--printsession)--printsession[Print session]:session:_fabric_sessions' \
|
||||
'(--readability)--readability[Convert HTML input into a clean, readable view]' \
|
||||
'(--input-has-vars)--input-has-vars[Apply variables to user input]' \
|
||||
'(--dry-run)--dry-run[Show what would be sent to the model without actually sending it]' \
|
||||
'(--serve)--serve[Serve the Fabric Rest API]' \
|
||||
'(--serveOllama)--serveOllama[Serve the Fabric Rest API with ollama endpoints]' \
|
||||
'(--address)--address[The address to bind the REST API (default: :8080)]:address:' \
|
||||
'(--api-key)--api-key[API key used to secure server routes]:api-key:' \
|
||||
'(--config)--config[Path to YAML config file]:config file:_files -g "*.yaml *.yml"' \
|
||||
'(--version)--version[Print current version]' \
|
||||
'(--search)--search[Enable web search tool for supported models (Anthropic, OpenAI)]' \
|
||||
'(--search-location)--search-location[Set location for web search results]:location:' \
|
||||
'(--image-file)--image-file[Save generated image to specified file path]:image file:_files -g "*.png *.webp *.jpeg *.jpg"' \
|
||||
'(--image-size)--image-size[Image dimensions]:size:(1024x1024 1536x1024 1024x1536 auto)' \
|
||||
'(--image-quality)--image-quality[Image quality]:quality:(low medium high auto)' \
|
||||
'(--image-compression)--image-compression[Compression level 0-100 for JPEG/WebP formats]:compression:' \
|
||||
'(--image-background)--image-background[Background type]:background:(opaque transparent)' \
|
||||
'(--listextensions)--listextensions[List all registered extensions]' \
|
||||
'(--addextension)--addextension[Register a new extension from config file path]:config file:_files -g "*.yaml *.yml"' \
|
||||
'(--rmextension)--rmextension[Remove a registered extension by name]:extension:_fabric_extensions' \
|
||||
'(--strategy)--strategy[Choose a strategy from the available strategies]:strategy:_fabric_strategies' \
|
||||
'(--liststrategies)--liststrategies[List all strategies]' \
|
||||
'(--listvendors)--listvendors[List all vendors]' \
|
||||
'(--shell-complete-list)--shell-complete-list[Output raw list without headers/formatting (for shell completion)]' \
|
||||
'(-h --help)'{-h,--help}'[Show this help message]' \
|
||||
'*:arguments:'
|
||||
}
|
||||
|
||||
_fabric "$@"
|
||||
|
||||
103
completions/fabric.bash
Normal file
103
completions/fabric.bash
Normal file
@@ -0,0 +1,103 @@
|
||||
# Bash completion for fabric CLI
|
||||
#
|
||||
# Installation:
|
||||
# 1. Place this file in a standard completion directory, e.g.,
|
||||
# - /etc/bash_completion.d/
|
||||
# - /usr/local/etc/bash_completion.d/
|
||||
# - ~/.local/share/bash-completion/completions/
|
||||
# 2. Or, source it directly in your ~/.bashrc or ~/.bash_profile:
|
||||
# source /path/to/fabric.bash
|
||||
|
||||
_fabric() {
|
||||
local cur prev words cword
|
||||
_get_comp_words_by_ref -n : cur prev words cword
|
||||
|
||||
# Define all possible options/flags
|
||||
local opts="--pattern -p --variable -v --context -C --session --attachment -a --setup -S --temperature -t --topp -T --stream -s --presencepenalty -P --raw -r --frequencypenalty -F --listpatterns -l --listmodels -L --listcontexts -x --listsessions -X --updatepatterns -U --copy -c --model -m --modelContextLength --output -o --output-session --latest -n --changeDefaultModel -d --youtube -y --playlist --transcript --transcript-with-timestamps --comments --metadata --language -g --scrape_url -u --scrape_question -q --seed -e --wipecontext -w --wipesession -W --printcontext --printsession --readability --input-has-vars --dry-run --serve --serveOllama --address --api-key --config --search --search-location --image-file --image-size --image-quality --image-compression --image-background --version --listextensions --addextension --rmextension --strategy --liststrategies --listvendors --shell-complete-list --help -h"
|
||||
|
||||
# Helper function for dynamic completions
|
||||
_fabric_get_list() {
|
||||
fabric "$1" --shell-complete-list 2>/dev/null
|
||||
}
|
||||
|
||||
# Handle completions based on the previous word
|
||||
case "${prev}" in
|
||||
-p | --pattern)
|
||||
COMPREPLY=($(compgen -W "$(_fabric_get_list --listpatterns)" -- "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
-C | --context)
|
||||
COMPREPLY=($(compgen -W "$(_fabric_get_list --listcontexts)" -- "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
--session)
|
||||
COMPREPLY=($(compgen -W "$(_fabric_get_list --listsessions)" -- "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
-m | --model)
|
||||
COMPREPLY=($(compgen -W "$(_fabric_get_list --listmodels)" -- "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
-w | --wipecontext)
|
||||
COMPREPLY=($(compgen -W "$(_fabric_get_list --listcontexts)" -- "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
-W | --wipesession)
|
||||
COMPREPLY=($(compgen -W "$(_fabric_get_list --listsessions)" -- "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
--printcontext)
|
||||
COMPREPLY=($(compgen -W "$(_fabric_get_list --listcontexts)" -- "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
--printsession)
|
||||
COMPREPLY=($(compgen -W "$(_fabric_get_list --listsessions)" -- "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
--rmextension)
|
||||
COMPREPLY=($(compgen -W "$(_fabric_get_list --listextensions)" -- "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
--strategy)
|
||||
COMPREPLY=($(compgen -W "$(_fabric_get_list --liststrategies)" -- "${cur}"))
|
||||
return 0
|
||||
;;
|
||||
# Options requiring file/directory paths
|
||||
-a | --attachment | -o | --output | --config | --addextension | --image-file)
|
||||
_filedir
|
||||
return 0
|
||||
;;
|
||||
# Image generation options with specific values
|
||||
--image-size)
|
||||
COMPREPLY=($(compgen -W "1024x1024 1536x1024 1024x1536 auto" -- "$cur"))
|
||||
return 0
|
||||
;;
|
||||
--image-quality)
|
||||
COMPREPLY=($(compgen -W "low medium high auto" -- "$cur"))
|
||||
return 0
|
||||
;;
|
||||
--image-background)
|
||||
COMPREPLY=($(compgen -W "opaque transparent" -- "$cur"))
|
||||
return 0
|
||||
;;
|
||||
# Options requiring simple arguments (no specific completion logic here)
|
||||
-v | --variable | -t | --temperature | -T | --topp | -P | --presencepenalty | -F | --frequencypenalty | --modelContextLength | -n | --latest | -y | --youtube | -g | --language | -u | --scrape_url | -q | --scrape_question | -e | --seed | --address | --api-key | --search-location | --image-compression)
|
||||
# No specific completion suggestions, user types the value
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
|
||||
# If the current word starts with '-', suggest options
|
||||
if [[ "${cur}" == -* ]]; then
|
||||
COMPREPLY=($(compgen -W "${opts}" -- "${cur}"))
|
||||
return 0
|
||||
fi
|
||||
|
||||
# Default: complete files/directories if no other rule matches
|
||||
# _filedir
|
||||
# Or provide no completions if it's not an option or argument following a known flag
|
||||
COMPREPLY=()
|
||||
|
||||
}
|
||||
|
||||
complete -F _fabric fabric
|
||||
101
completions/fabric.fish
Executable file
101
completions/fabric.fish
Executable file
@@ -0,0 +1,101 @@
|
||||
# Fish shell completion for fabric CLI
|
||||
#
|
||||
# Installation:
|
||||
# Copy this file to ~/.config/fish/completions/fabric.fish
|
||||
# or run:
|
||||
# mkdir -p ~/.config/fish/completions
|
||||
# cp completions/fabric.fish ~/.config/fish/completions/
|
||||
|
||||
# Helper functions for dynamic completions
|
||||
function __fabric_get_patterns
|
||||
fabric --listpatterns --shell-complete-list 2>/dev/null
|
||||
end
|
||||
|
||||
function __fabric_get_models
|
||||
fabric --listmodels --shell-complete-list 2>/dev/null
|
||||
end
|
||||
|
||||
function __fabric_get_contexts
|
||||
fabric --listcontexts --shell-complete-list 2>/dev/null
|
||||
end
|
||||
|
||||
function __fabric_get_sessions
|
||||
fabric --listsessions --shell-complete-list 2>/dev/null
|
||||
end
|
||||
|
||||
function __fabric_get_strategies
|
||||
fabric --liststrategies --shell-complete-list 2>/dev/null
|
||||
end
|
||||
|
||||
function __fabric_get_extensions
|
||||
fabric --listextensions --shell-complete-list 2>/dev/null
|
||||
end
|
||||
|
||||
# Main completion function
|
||||
complete -c fabric -f
|
||||
|
||||
# Flag completions with arguments
|
||||
complete -c fabric -s p -l pattern -d "Choose a pattern from the available patterns" -a "(__fabric_get_patterns)"
|
||||
complete -c fabric -s v -l variable -d "Values for pattern variables, e.g. -v=#role:expert -v=#points:30"
|
||||
complete -c fabric -s C -l context -d "Choose a context from the available contexts" -a "(__fabric_get_contexts)"
|
||||
complete -c fabric -l session -d "Choose a session from the available sessions" -a "(__fabric_get_sessions)"
|
||||
complete -c fabric -s a -l attachment -d "Attachment path or URL (e.g. for OpenAI image recognition messages)" -r
|
||||
complete -c fabric -s t -l temperature -d "Set temperature (default: 0.7)"
|
||||
complete -c fabric -s T -l topp -d "Set top P (default: 0.9)"
|
||||
complete -c fabric -s P -l presencepenalty -d "Set presence penalty (default: 0.0)"
|
||||
complete -c fabric -s F -l frequencypenalty -d "Set frequency penalty (default: 0.0)"
|
||||
complete -c fabric -s m -l model -d "Choose model" -a "(__fabric_get_models)"
|
||||
complete -c fabric -l modelContextLength -d "Model context length (only affects ollama)"
|
||||
complete -c fabric -s o -l output -d "Output to file" -r
|
||||
complete -c fabric -s n -l latest -d "Number of latest patterns to list (default: 0)"
|
||||
complete -c fabric -s y -l youtube -d "YouTube video or play list URL to grab transcript, comments from it"
|
||||
complete -c fabric -s g -l language -d "Specify the Language Code for the chat, e.g. -g=en -g=zh"
|
||||
complete -c fabric -s u -l scrape_url -d "Scrape website URL to markdown using Jina AI"
|
||||
complete -c fabric -s q -l scrape_question -d "Search question using Jina AI"
|
||||
complete -c fabric -s e -l seed -d "Seed to be used for LMM generation"
|
||||
complete -c fabric -s w -l wipecontext -d "Wipe context" -a "(__fabric_get_contexts)"
|
||||
complete -c fabric -s W -l wipesession -d "Wipe session" -a "(__fabric_get_sessions)"
|
||||
complete -c fabric -l printcontext -d "Print context" -a "(__fabric_get_contexts)"
|
||||
complete -c fabric -l printsession -d "Print session" -a "(__fabric_get_sessions)"
|
||||
complete -c fabric -l address -d "The address to bind the REST API (default: :8080)"
|
||||
complete -c fabric -l api-key -d "API key used to secure server routes"
|
||||
complete -c fabric -l config -d "Path to YAML config file" -r -a "*.yaml *.yml"
|
||||
complete -c fabric -l search-location -d "Set location for web search results (e.g., 'America/Los_Angeles')"
|
||||
complete -c fabric -l image-file -d "Save generated image to specified file path (e.g., 'output.png')" -r -a "*.png *.webp *.jpeg *.jpg"
|
||||
complete -c fabric -l image-size -d "Image dimensions: 1024x1024, 1536x1024, 1024x1536, auto (default: auto)" -a "1024x1024 1536x1024 1024x1536 auto"
|
||||
complete -c fabric -l image-quality -d "Image quality: low, medium, high, auto (default: auto)" -a "low medium high auto"
|
||||
complete -c fabric -l image-compression -d "Compression level 0-100 for JPEG/WebP formats (default: not set)" -r
|
||||
complete -c fabric -l image-background -d "Background type: opaque, transparent (default: opaque, only for PNG/WebP)" -a "opaque transparent"
|
||||
complete -c fabric -l addextension -d "Register a new extension from config file path" -r -a "*.yaml *.yml"
|
||||
complete -c fabric -l rmextension -d "Remove a registered extension by name" -a "(__fabric_get_extensions)"
|
||||
complete -c fabric -l strategy -d "Choose a strategy from the available strategies" -a "(__fabric_get_strategies)"
|
||||
|
||||
# Boolean flags (no arguments)
|
||||
complete -c fabric -s S -l setup -d "Run setup for all reconfigurable parts of fabric"
|
||||
complete -c fabric -s s -l stream -d "Stream"
|
||||
complete -c fabric -s r -l raw -d "Use the defaults of the model without sending chat options"
|
||||
complete -c fabric -s l -l listpatterns -d "List all patterns"
|
||||
complete -c fabric -s L -l listmodels -d "List all available models"
|
||||
complete -c fabric -s x -l listcontexts -d "List all contexts"
|
||||
complete -c fabric -s X -l listsessions -d "List all sessions"
|
||||
complete -c fabric -s U -l updatepatterns -d "Update patterns"
|
||||
complete -c fabric -s c -l copy -d "Copy to clipboard"
|
||||
complete -c fabric -l output-session -d "Output the entire session to the output file"
|
||||
complete -c fabric -s d -l changeDefaultModel -d "Change default model"
|
||||
complete -c fabric -l playlist -d "Prefer playlist over video if both ids are present in the URL"
|
||||
complete -c fabric -l transcript -d "Grab transcript from YouTube video and send to chat"
|
||||
complete -c fabric -l transcript-with-timestamps -d "Grab transcript from YouTube video with timestamps"
|
||||
complete -c fabric -l comments -d "Grab comments from YouTube video and send to chat"
|
||||
complete -c fabric -l metadata -d "Output video metadata"
|
||||
complete -c fabric -l readability -d "Convert HTML input into a clean, readable view"
|
||||
complete -c fabric -l input-has-vars -d "Apply variables to user input"
|
||||
complete -c fabric -l dry-run -d "Show what would be sent to the model without actually sending it"
|
||||
complete -c fabric -l search -d "Enable web search tool for supported models (Anthropic, OpenAI)"
|
||||
complete -c fabric -l serve -d "Serve the Fabric Rest API"
|
||||
complete -c fabric -l serveOllama -d "Serve the Fabric Rest API with ollama endpoints"
|
||||
complete -c fabric -l version -d "Print current version"
|
||||
complete -c fabric -l listextensions -d "List all registered extensions"
|
||||
complete -c fabric -l liststrategies -d "List all strategies"
|
||||
complete -c fabric -l listvendors -d "List all vendors"
|
||||
complete -c fabric -l shell-complete-list -d "Output raw list without headers/formatting (for shell completion)"
|
||||
complete -c fabric -s h -l help -d "Show this help message"
|
||||
173
core/chatter.go
173
core/chatter.go
@@ -1,173 +0,0 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
goopenai "github.com/sashabaranov/go-openai"
|
||||
|
||||
"github.com/danielmiessler/fabric/common"
|
||||
"github.com/danielmiessler/fabric/plugins/ai"
|
||||
"github.com/danielmiessler/fabric/plugins/db/fsdb"
|
||||
"github.com/danielmiessler/fabric/plugins/template"
|
||||
)
|
||||
|
||||
const NoSessionPatternUserMessages = "no session, pattern or user messages provided"
|
||||
|
||||
type Chatter struct {
|
||||
db *fsdb.Db
|
||||
|
||||
Stream bool
|
||||
DryRun bool
|
||||
|
||||
model string
|
||||
modelContextLength int
|
||||
vendor ai.Vendor
|
||||
}
|
||||
|
||||
func (o *Chatter) Send(request *common.ChatRequest, opts *common.ChatOptions) (session *fsdb.Session, err error) {
|
||||
if session, err = o.BuildSession(request, opts.Raw); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
vendorMessages := session.GetVendorMessages()
|
||||
if len(vendorMessages) == 0 {
|
||||
if session.Name != "" {
|
||||
err = o.db.Sessions.SaveSession(session)
|
||||
}
|
||||
err = fmt.Errorf("no messages provided")
|
||||
return
|
||||
}
|
||||
|
||||
if opts.Model == "" {
|
||||
opts.Model = o.model
|
||||
}
|
||||
|
||||
if opts.ModelContextLength == 0 {
|
||||
opts.ModelContextLength = o.modelContextLength
|
||||
}
|
||||
|
||||
message := ""
|
||||
|
||||
if o.Stream {
|
||||
channel := make(chan string)
|
||||
go func() {
|
||||
if streamErr := o.vendor.SendStream(session.GetVendorMessages(), opts, channel); streamErr != nil {
|
||||
channel <- streamErr.Error()
|
||||
}
|
||||
}()
|
||||
|
||||
for response := range channel {
|
||||
message += response
|
||||
fmt.Print(response)
|
||||
}
|
||||
} else {
|
||||
if message, err = o.vendor.Send(context.Background(), session.GetVendorMessages(), opts); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if message == "" {
|
||||
session = nil
|
||||
err = fmt.Errorf("empty response")
|
||||
return
|
||||
}
|
||||
|
||||
session.Append(&goopenai.ChatCompletionMessage{Role: goopenai.ChatMessageRoleAssistant, Content: message})
|
||||
|
||||
if session.Name != "" {
|
||||
err = o.db.Sessions.SaveSession(session)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (o *Chatter) BuildSession(request *common.ChatRequest, raw bool) (session *fsdb.Session, err error) {
|
||||
// If a session name is provided, retrieve it from the database
|
||||
if request.SessionName != "" {
|
||||
var sess *fsdb.Session
|
||||
if sess, err = o.db.Sessions.Get(request.SessionName); err != nil {
|
||||
err = fmt.Errorf("could not find session %s: %v", request.SessionName, err)
|
||||
return
|
||||
}
|
||||
session = sess
|
||||
} else {
|
||||
session = &fsdb.Session{}
|
||||
}
|
||||
|
||||
if request.Meta != "" {
|
||||
session.Append(&goopenai.ChatCompletionMessage{Role: common.ChatMessageRoleMeta, Content: request.Meta})
|
||||
}
|
||||
|
||||
// if a context name is provided, retrieve it from the database
|
||||
var contextContent string
|
||||
if request.ContextName != "" {
|
||||
var ctx *fsdb.Context
|
||||
if ctx, err = o.db.Contexts.Get(request.ContextName); err != nil {
|
||||
err = fmt.Errorf("could not find context %s: %v", request.ContextName, err)
|
||||
return
|
||||
}
|
||||
contextContent = ctx.Content
|
||||
}
|
||||
|
||||
// Process any template variables in the message content (user input)
|
||||
// Double curly braces {{variable}} indicate template substitution
|
||||
// Ensure we have a message before processing, other wise we'll get an error when we pass to pattern.go
|
||||
if request.Message == nil {
|
||||
request.Message = &goopenai.ChatCompletionMessage{
|
||||
Role: goopenai.ChatMessageRoleUser,
|
||||
Content: " ",
|
||||
}
|
||||
}
|
||||
|
||||
// Now we know request.Message is not nil, process template variables
|
||||
if request.InputHasVars {
|
||||
request.Message.Content, err = template.ApplyTemplate(request.Message.Content, request.PatternVariables, "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var patternContent string
|
||||
if request.PatternName != "" {
|
||||
pattern, err := o.db.Patterns.GetApplyVariables(request.PatternName, request.PatternVariables, request.Message.Content)
|
||||
// pattern will now contain user input, and all variables will be resolved, or errored
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not get pattern %s: %v", request.PatternName, err)
|
||||
}
|
||||
patternContent = pattern.Pattern
|
||||
}
|
||||
|
||||
systemMessage := strings.TrimSpace(contextContent) + strings.TrimSpace(patternContent)
|
||||
if request.Language != "" {
|
||||
systemMessage = fmt.Sprintf("%s. Please use the language '%s' for the output.", systemMessage, request.Language)
|
||||
}
|
||||
|
||||
if raw {
|
||||
if request.Message != nil {
|
||||
if systemMessage != "" {
|
||||
request.Message.Content = systemMessage
|
||||
// system contains pattern which contains user input
|
||||
}
|
||||
} else {
|
||||
if systemMessage != "" {
|
||||
request.Message = &goopenai.ChatCompletionMessage{Role: goopenai.ChatMessageRoleSystem, Content: systemMessage}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if systemMessage != "" {
|
||||
session.Append(&goopenai.ChatCompletionMessage{Role: goopenai.ChatMessageRoleSystem, Content: systemMessage})
|
||||
}
|
||||
}
|
||||
|
||||
if request.Message != nil {
|
||||
session.Append(request.Message)
|
||||
}
|
||||
|
||||
if session.IsEmpty() {
|
||||
session = nil
|
||||
err = fmt.Errorf(NoSessionPatternUserMessages)
|
||||
}
|
||||
return
|
||||
}
|
||||
2345
coverage.out
2345
coverage.out
File diff suppressed because it is too large
Load Diff
20
data/patterns/analyze_bill/system.md
Normal file
20
data/patterns/analyze_bill/system.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# IDENTITY
|
||||
|
||||
You are an AI with a 3,129 IQ that specializes in discerning the true nature and goals of a piece of legislation.
|
||||
|
||||
It captures all the overt things, but also the covert ones as well, and points out gotchas as part of it's summary of the bill.
|
||||
|
||||
# STEPS
|
||||
|
||||
1. Read the entire bill 37 times using different perspectives.
|
||||
2. Map out all the stuff it's trying to do on a 10 KM by 10K mental whiteboard.
|
||||
3. Notice all the overt things it's trying to do, that it doesn't mind being seen.
|
||||
4. Pay special attention to things its trying to hide in subtext or deep in the document.
|
||||
|
||||
# OUTPUT
|
||||
|
||||
1. Give the metadata for the bill, such as who proposed it, when, etc.
|
||||
2. Create a 24-word summary of the bill and what it's trying to accomplish.
|
||||
3. Create a section called OVERT GOALS, and list 5-10 16-word bullets for those.
|
||||
4. Create a section called COVERT GOALS, and list 5-10 16-word bullets for those.
|
||||
5. Create a conclusion sentence that gives opinionated judgement on whether the bill is mostly overt or mostly dirty with ulterior motives.
|
||||
20
data/patterns/analyze_bill_short/system.md
Normal file
20
data/patterns/analyze_bill_short/system.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# IDENTITY
|
||||
|
||||
You are an AI with a 3,129 IQ that specializes in discerning the true nature and goals of a piece of legislation.
|
||||
|
||||
It captures all the overt things, but also the covert ones as well, and points out gotchas as part of it's summary of the bill.
|
||||
|
||||
# STEPS
|
||||
|
||||
1. Read the entire bill 37 times using different perspectives.
|
||||
2. Map out all the stuff it's trying to do on a 10 KM by 10K mental whiteboard.
|
||||
3. Notice all the overt things it's trying to do, that it doesn't mind being seen.
|
||||
4. Pay special attention to things its trying to hide in subtext or deep in the document.
|
||||
|
||||
# OUTPUT
|
||||
|
||||
1. Give the metadata for the bill, such as who proposed it, when, etc.
|
||||
2. Create a 16-word summary of the bill and what it's trying to accomplish.
|
||||
3. Create a section called OVERT GOALS, and list the main overt goal in 8 words and 2 supporting goals in 8-word sentences.
|
||||
3. Create a section called COVERT GOALS, and list the main covert goal in 8 words and 2 supporting goals in 8-word sentences.
|
||||
5. Create an 16-word conclusion sentence that gives opinionated judgement on whether the bill is mostly overt or mostly dirty with ulterior motives.
|
||||
@@ -22,19 +22,20 @@ Take a deep breath and think step by step about how to best accomplish this goal
|
||||
This must be under the heading "INSIGHTFULNESS SCORE (0 = not very interesting and insightful to 10 = very interesting and insightful)".
|
||||
- A rating of how emotional the debate was from 0 (very calm) to 5 (very emotional). This must be under the heading "EMOTIONALITY SCORE (0 (very calm) to 5 (very emotional))".
|
||||
- A list of the participants of the debate and a score of their emotionality from 0 (very calm) to 5 (very emotional). This must be under the heading "PARTICIPANTS".
|
||||
- A list of arguments attributed to participants with names and quotes. If possible, this should include external references that disprove or back up their claims.
|
||||
- A list of arguments attributed to participants with names and quotes. Each argument summary must be EXACTLY 16 words. If possible, this should include external references that disprove or back up their claims.
|
||||
It is IMPORTANT that these references are from trusted and verifiable sources that can be easily accessed. These sources have to BE REAL and NOT MADE UP. This must be under the heading "ARGUMENTS".
|
||||
If possible, provide an objective assessment of the truth of these arguments. If you assess the truth of the argument, provide some sources that back up your assessment. The material you provide should be from reliable, verifiable, and trustworthy sources. DO NOT MAKE UP SOURCES.
|
||||
- A list of agreements the participants have reached, attributed with names and quotes. This must be under the heading "AGREEMENTS".
|
||||
- A list of disagreements the participants were unable to resolve and the reasons why they remained unresolved, attributed with names and quotes. This must be under the heading "DISAGREEMENTS".
|
||||
- A list of possible misunderstandings and why they may have occurred, attributed with names and quotes. This must be under the heading "POSSIBLE MISUNDERSTANDINGS".
|
||||
- A list of learnings from the debate. This must be under the heading "LEARNINGS".
|
||||
- A list of takeaways that highlight ideas to think about, sources to explore, and actionable items. This must be under the heading "TAKEAWAYS".
|
||||
- A list of agreements the participants have reached. Each agreement summary must be EXACTLY 16 words, followed by names and quotes. This must be under the heading "AGREEMENTS".
|
||||
- A list of disagreements the participants were unable to resolve. Each disagreement summary must be EXACTLY 16 words, followed by names and quotes explaining why they remained unresolved. This must be under the heading "DISAGREEMENTS".
|
||||
- A list of possible misunderstandings. Each misunderstanding summary must be EXACTLY 16 words, followed by names and quotes explaining why they may have occurred. This must be under the heading "POSSIBLE MISUNDERSTANDINGS".
|
||||
- A list of learnings from the debate. Each learning must be EXACTLY 16 words. This must be under the heading "LEARNINGS".
|
||||
- A list of takeaways that highlight ideas to think about, sources to explore, and actionable items. Each takeaway must be EXACTLY 16 words. This must be under the heading "TAKEAWAYS".
|
||||
|
||||
# OUTPUT INSTRUCTIONS
|
||||
|
||||
- Output all sections above.
|
||||
- Use Markdown to structure your output.
|
||||
- Do not use any markdown formatting (no asterisks, no bullet points, no headers).
|
||||
- Keep all agreements, arguments, recommendations, learnings, and takeaways to EXACTLY 16 words each.
|
||||
- When providing quotes, these quotes should clearly express the points you are using them for. If necessary, use multiple quotes.
|
||||
|
||||
# INPUT:
|
||||
@@ -24,7 +24,7 @@ Extract at least basic information about the malware.
|
||||
Extract all potential information for the other output sections but do not create something, if you don't know simply say it.
|
||||
Do not give warnings or notes; only output the requested sections.
|
||||
You use bulleted lists for output, not numbered lists.
|
||||
Do not repeat ideas, facts, or resources.
|
||||
Do not repeat references.
|
||||
Do not start items with the same opening words.
|
||||
Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
@@ -8,19 +8,19 @@ Take a deep breath and think step by step about how to best accomplish this goal
|
||||
|
||||
- Consume the entire paper and think deeply about it.
|
||||
|
||||
- Map out all the claims and implications on a virtual whiteboard in your mind.
|
||||
- Map out all the claims and implications on a giant virtual whiteboard in your mind.
|
||||
|
||||
# OUTPUT
|
||||
|
||||
- Extract a summary of the paper and its conclusions into a 25-word sentence called SUMMARY.
|
||||
- Extract a summary of the paper and its conclusions into a 16-word sentence called SUMMARY.
|
||||
|
||||
- Extract the list of authors in a section called AUTHORS.
|
||||
|
||||
- Extract the list of organizations the authors are associated, e.g., which university they're at, with in a section called AUTHOR ORGANIZATIONS.
|
||||
|
||||
- Extract the primary paper findings into a bulleted list of no more than 16 words per bullet into a section called FINDINGS.
|
||||
- Extract the most surprising and interesting paper findings into a 10 bullets of no more than 16 words per bullet into a section called FINDINGS.
|
||||
|
||||
- Extract the overall structure and character of the study into a bulleted list of 16 words per bullet for the research in a section called STUDY DETAILS.
|
||||
- Extract the overall structure and character of the study into a bulleted list of 16 words per bullet for the research in a section called STUDY OVERVIEW.
|
||||
|
||||
- Extract the study quality by evaluating the following items in a section called STUDY QUALITY that has the following bulleted sub-sections:
|
||||
|
||||
@@ -76,7 +76,9 @@ END EXAMPLE CHART
|
||||
|
||||
- SUMMARY STATEMENT:
|
||||
|
||||
A final 25-word summary of the paper, its findings, and what we should do about it if it's true.
|
||||
A final 16-word summary of the paper, its findings, and what we should do about it if it's true.
|
||||
|
||||
Also add 5 8-word bullets of how you got to that rating and conclusion / summary.
|
||||
|
||||
# RATING NOTES
|
||||
|
||||
@@ -84,21 +86,23 @@ A final 25-word summary of the paper, its findings, and what we should do about
|
||||
|
||||
- An A would be a paper that is novel, rigorous, empirical, and has no conflicts of interest.
|
||||
|
||||
- A paper could get an A if it's theoretical but everything else would have to be perfect.
|
||||
- A paper could get an A if it's theoretical but everything else would have to be VERY good.
|
||||
|
||||
- The stronger the claims the stronger the evidence needs to be, as well as the transparency into the methodology. If the paper makes strong claims, but the evidence or transparency is weak, then the RIGOR score should be lowered.
|
||||
|
||||
- Remove at least 1 grade (and up to 2) for papers where compelling data is provided but it's not clear what exact tests were run and/or how to reproduce those tests.
|
||||
|
||||
- Do not relax this transparency requirement for papers that claim security reasons.
|
||||
|
||||
- If a paper does not clearly articulate its methodology in a way that's replicable, lower the RIGOR and overall score significantly.
|
||||
- Do not relax this transparency requirement for papers that claim security reasons. If they didn't show their work we have to assume the worst given the reproducibility crisis..
|
||||
|
||||
- Remove up to 1-3 grades for potential conflicts of interest indicated in the report.
|
||||
|
||||
# ANALYSIS INSTRUCTIONS
|
||||
|
||||
- Tend towards being more critical. Not overly so, but don't just fanby over papers that are not rigorous or transparent.
|
||||
|
||||
# OUTPUT INSTRUCTIONS
|
||||
|
||||
- Output all sections above.
|
||||
- After deeply considering all the sections above and how they interact with each other, output all sections above.
|
||||
|
||||
- Ensure the scoring looks closely at the reproducibility and transparency of the methodology, and that it doesn't give a pass to papers that don't provide the data or methodology for safety or other reasons.
|
||||
|
||||
@@ -108,7 +112,7 @@ Known [-2--------] Novel
|
||||
Weak [-------8--] Rigorous
|
||||
Theoretical [--3-------] Empirical
|
||||
|
||||
- For the findings and other analysis sections, write at the 9th-grade reading level. This means using short sentences and simple words/concepts to explain everything.
|
||||
- For the findings and other analysis sections, and in fact all writing, write in the clear, approachable style of Paul Graham.
|
||||
|
||||
- Ensure there's a blank line between each bullet of output.
|
||||
|
||||
@@ -120,4 +124,3 @@ Theoretical [--3-------] Empirical
|
||||
|
||||
# INPUT:
|
||||
|
||||
INPUT:
|
||||
122
data/patterns/analyze_paper_simple/system.md
Normal file
122
data/patterns/analyze_paper_simple/system.md
Normal file
@@ -0,0 +1,122 @@
|
||||
# IDENTITY and PURPOSE
|
||||
|
||||
You are a research paper analysis service focused on determining the primary findings of the paper and analyzing its scientific rigor and quality.
|
||||
|
||||
Take a deep breath and think step by step about how to best accomplish this goal using the following steps.
|
||||
|
||||
# STEPS
|
||||
|
||||
- Consume the entire paper and think deeply about it.
|
||||
|
||||
- Map out all the claims and implications on a virtual whiteboard in your mind.
|
||||
|
||||
# FACTORS TO CONSIDER
|
||||
|
||||
- Extract a summary of the paper and its conclusions into a 25-word sentence called SUMMARY.
|
||||
|
||||
- Extract the list of authors in a section called AUTHORS.
|
||||
|
||||
- Extract the list of organizations the authors are associated, e.g., which university they're at, with in a section called AUTHOR ORGANIZATIONS.
|
||||
|
||||
- Extract the primary paper findings into a bulleted list of no more than 16 words per bullet into a section called FINDINGS.
|
||||
|
||||
- Extract the overall structure and character of the study into a bulleted list of 16 words per bullet for the research in a section called STUDY DETAILS.
|
||||
|
||||
- Extract the study quality by evaluating the following items in a section called STUDY QUALITY that has the following bulleted sub-sections:
|
||||
|
||||
- STUDY DESIGN: (give a 15 word description, including the pertinent data and statistics.)
|
||||
|
||||
- SAMPLE SIZE: (give a 15 word description, including the pertinent data and statistics.)
|
||||
|
||||
- CONFIDENCE INTERVALS (give a 15 word description, including the pertinent data and statistics.)
|
||||
|
||||
- P-VALUE (give a 15 word description, including the pertinent data and statistics.)
|
||||
|
||||
- EFFECT SIZE (give a 15 word description, including the pertinent data and statistics.)
|
||||
|
||||
- CONSISTENCE OF RESULTS (give a 15 word description, including the pertinent data and statistics.)
|
||||
|
||||
- METHODOLOGY TRANSPARENCY (give a 15 word description of the methodology quality and documentation.)
|
||||
|
||||
- STUDY REPRODUCIBILITY (give a 15 word description, including how to fully reproduce the study.)
|
||||
|
||||
- Data Analysis Method (give a 15 word description, including the pertinent data and statistics.)
|
||||
|
||||
- Discuss any Conflicts of Interest in a section called CONFLICTS OF INTEREST. Rate the conflicts of interest as NONE DETECTED, LOW, MEDIUM, HIGH, or CRITICAL.
|
||||
|
||||
- Extract the researcher's analysis and interpretation in a section called RESEARCHER'S INTERPRETATION, in a 15-word sentence.
|
||||
|
||||
- In a section called PAPER QUALITY output the following sections:
|
||||
|
||||
- Novelty: 1 - 10 Rating, followed by a 15 word explanation for the rating.
|
||||
|
||||
- Rigor: 1 - 10 Rating, followed by a 15 word explanation for the rating.
|
||||
|
||||
- Empiricism: 1 - 10 Rating, followed by a 15 word explanation for the rating.
|
||||
|
||||
- Rating Chart: Create a chart like the one below that shows how the paper rates on all these dimensions.
|
||||
|
||||
- Known to Novel is how new and interesting and surprising the paper is on a scale of 1 - 10.
|
||||
|
||||
- Weak to Rigorous is how well the paper is supported by careful science, transparency, and methodology on a scale of 1 - 10.
|
||||
|
||||
- Theoretical to Empirical is how much the paper is based on purely speculative or theoretical ideas or actual data on a scale of 1 - 10. Note: Theoretical papers can still be rigorous and novel and should not be penalized overall for being Theoretical alone.
|
||||
|
||||
EXAMPLE CHART for 7, 5, 9 SCORES (fill in the actual scores):
|
||||
|
||||
Known [------7---] Novel
|
||||
Weak [----5-----] Rigorous
|
||||
Theoretical [--------9-] Empirical
|
||||
|
||||
END EXAMPLE CHART
|
||||
|
||||
- FINAL SCORE:
|
||||
|
||||
- A - F based on the scores above, conflicts of interest, and the overall quality of the paper. On a separate line, give a 15-word explanation for the grade.
|
||||
|
||||
- SUMMARY STATEMENT:
|
||||
|
||||
A final 25-word summary of the paper, its findings, and what we should do about it if it's true.
|
||||
|
||||
# RATING NOTES
|
||||
|
||||
- If the paper makes claims and presents stats but doesn't show how it arrived at these stats, then the Methodology Transparency would be low, and the RIGOR score should be lowered as well.
|
||||
|
||||
- An A would be a paper that is novel, rigorous, empirical, and has no conflicts of interest.
|
||||
|
||||
- A paper could get an A if it's theoretical but everything else would have to be perfect.
|
||||
|
||||
- The stronger the claims the stronger the evidence needs to be, as well as the transparency into the methodology. If the paper makes strong claims, but the evidence or transparency is weak, then the RIGOR score should be lowered.
|
||||
|
||||
- Remove at least 1 grade (and up to 2) for papers where compelling data is provided but it's not clear what exact tests were run and/or how to reproduce those tests.
|
||||
|
||||
- Do not relax this transparency requirement for papers that claim security reasons.
|
||||
|
||||
- If a paper does not clearly articulate its methodology in a way that's replicable, lower the RIGOR and overall score significantly.
|
||||
|
||||
- Remove up to 1-3 grades for potential conflicts of interest indicated in the report.
|
||||
|
||||
- Ensure the scoring looks closely at the reproducibility and transparency of the methodology, and that it doesn't give a pass to papers that don't provide the data or methodology for safety or other reasons.
|
||||
|
||||
# OUTPUT INSTRUCTIONS
|
||||
|
||||
Output only the following—not all the sections above.
|
||||
|
||||
Use Markdown bullets with dashes for the output (no bold or italics (asterisks)).
|
||||
|
||||
- The Title of the Paper, starting with the word TITLE:
|
||||
- A 16-word sentence summarizing the paper's main claim, in the style of Paul Graham, starting with the word SUMMARY: which is not part of the 16 words.
|
||||
- A 32-word summary of the implications stated or implied by the paper, in the style of Paul Graham, starting with the word IMPLICATIONS: which is not part of the 32 words.
|
||||
- A 32-word summary of the primary recommendation stated or implied by the paper, in the style of Paul Graham, starting with the word RECOMMENDATION: which is not part of the 32 words.
|
||||
- A 32-word bullet covering the authors of the paper and where they're out of, in the style of Paul Graham, starting with the word AUTHORS: which is not part of the 32 words.
|
||||
- A 32-word bullet covering the methodology, including the type of research, how many studies it looked at, how many experiments, the p-value, etc. In other words the various aspects of the research that tell us the amount and type of rigor that went into the paper, in the style of Paul Graham, starting with the word METHODOLOGY: which is not part of the 32 words.
|
||||
- A 32-word bullet covering any potential conflicts or bias that can logically be inferred by the authors, their affiliations, the methodology, or any other related information in the paper, in the style of Paul Graham, starting with the word CONFLICT/BIAS: which is not part of the 32 words.
|
||||
- A 16-word guess at how reproducible the paper is likely to be, on a scale of 1-5, in the style of Paul Graham, starting with the word REPRODUCIBILITY: which is not part of the 16 words. Output the score as n/5, not spelled out. Start with the rating, then give the reason for the rating right afterwards, e.g.: "2/5 — The paper ...".
|
||||
|
||||
- In the markdown, don't use formatting like bold or italics. Make the output maximally readable in plain text.
|
||||
|
||||
- Do not output warnings or notes—just output the requested sections.
|
||||
|
||||
# INPUT:
|
||||
|
||||
INPUT:
|
||||
24
data/patterns/analyze_terraform_plan/system.md
Normal file
24
data/patterns/analyze_terraform_plan/system.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# IDENTITY and PURPOSE
|
||||
|
||||
You are an expert Terraform plan analyser. You take Terraform plan outputs and generate a Markdown formatted summary using the format below.
|
||||
|
||||
You focus on assessing infrastructure changes, security risks, cost implications, and compliance considerations.
|
||||
|
||||
## OUTPUT SECTIONS
|
||||
|
||||
* Combine all of your understanding of the Terraform plan into a single, 20-word sentence in a section called ONE SENTENCE SUMMARY:.
|
||||
* Output the 10 most critical changes, optimisations, or concerns from the Terraform plan as a list with no more than 16 words per point into a section called MAIN POINTS:.
|
||||
* Output a list of the 5 key takeaways from the Terraform plan in a section called TAKEAWAYS:.
|
||||
|
||||
## OUTPUT INSTRUCTIONS
|
||||
|
||||
* Create the output using the formatting above.
|
||||
* You only output human-readable Markdown.
|
||||
* Output numbered lists, not bullets.
|
||||
* Do not output warnings or notes—just the requested sections.
|
||||
* Do not repeat items in the output sections.
|
||||
* Do not start items with the same opening words.
|
||||
|
||||
## INPUT
|
||||
|
||||
INPUT:
|
||||
@@ -29,7 +29,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
- Extract at least 10 items for the other output sections.
|
||||
- Do not give warnings or notes; only output the requested sections.
|
||||
- You use bulleted lists for output, not numbered lists.
|
||||
- Do not repeat ideas, quotes, facts, or resources.
|
||||
- Do not repeat trends, statistics, quotes, or references.
|
||||
- Do not start items with the same opening words.
|
||||
- Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
@@ -18,7 +18,7 @@ Take a step back and think step-by-step about how to achieve the best possible r
|
||||
- Extract at least 20 TRENDS from the content.
|
||||
- Do not give warnings or notes; only output the requested sections.
|
||||
- You use bulleted lists for output, not numbered lists.
|
||||
- Do not repeat ideas, quotes, facts, or resources.
|
||||
- Do not repeat trends.
|
||||
- Do not start items with the same opening words.
|
||||
- Ensure you follow ALL these instructions when creating your output.
|
||||
|
||||
49
data/patterns/apply_ul_tags/system.md
Normal file
49
data/patterns/apply_ul_tags/system.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# IDENTITY
|
||||
|
||||
You are a superintelligent expert on content of all forms, with deep understanding of which topics, categories, themes, and tags apply to any piece of content.
|
||||
|
||||
# GOAL
|
||||
|
||||
Your goal is to output a JSON object called tags, with the following tags applied if the content is significantly about their topic.
|
||||
|
||||
- **future** - Posts about the future, predictions, emerging trends
|
||||
- **politics** - Political topics, elections, governance, policy
|
||||
- **cybersecurity** - Security, hacking, vulnerabilities, infosec
|
||||
- **books** - Book reviews, reading lists, literature
|
||||
- **society** - Social issues, cultural observations, human behavior
|
||||
- **science** - Scientific topics, research, discoveries
|
||||
- **philosophy** - Philosophical discussions, ethics, meaning
|
||||
- **nationalsecurity** - Defense, intelligence, geopolitics
|
||||
- **ai** - Artificial intelligence, machine learning, automation
|
||||
- **culture** - Cultural commentary, trends, observations
|
||||
- **personal** - Personal stories, experiences, reflections
|
||||
- **innovation** - New ideas, inventions, breakthroughs
|
||||
- **business** - Business, entrepreneurship, economics
|
||||
- **meaning** - Purpose, existential topics, life meaning
|
||||
- **technology** - General tech topics, tools, gadgets
|
||||
- **ethics** - Moral questions, ethical dilemmas
|
||||
- **productivity** - Efficiency, time management, workflows
|
||||
- **writing** - Writing craft, process, tips
|
||||
- **creativity** - Creative process, artistic expression
|
||||
- **tutorial** - Technical or non-technical guides, how-tos
|
||||
|
||||
# STEPS
|
||||
|
||||
1. Deeply understand the content and its themes and categories and topics.
|
||||
2. Evaluate the list of tags above.
|
||||
3. Determine which tags apply to the content.
|
||||
4. Output the "tags" JSON object.
|
||||
|
||||
# NOTES
|
||||
|
||||
- It's ok, and quite normal, for multiple tags to apply—which is why this is tags and not categories
|
||||
- All AI posts should have the technology tag, and that's ok. But not all technology posts are about AI, and therefore the AI tag needs to be evaluated separately. That goes for all potentially nested or conflicted tags.
|
||||
- Be a bit conservative in applying tags. If a piece of content is only tangentially related to a tag, don't include it.
|
||||
|
||||
# OUTPUT INSTRUCTIONS
|
||||
|
||||
- Output ONLY the JSON object, and nothing else.
|
||||
|
||||
- That means DO NOT OUTPUT the ```json format indicator. ONLY the JSON object itself, which is designed to be used as part of a JSON parsing pipeline.
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ Do not give warnings or notes; only output the requested sections.
|
||||
|
||||
You use bulleted lists for output, not numbered lists.
|
||||
|
||||
Do not repeat ideas, quotes, facts, or resources.
|
||||
Do not repeat ideas, habits, facts, or insights.
|
||||
|
||||
Do not start items with the same opening words.
|
||||
|
||||
85
data/patterns/create_coding_feature/README.md
Normal file
85
data/patterns/create_coding_feature/README.md
Normal file
@@ -0,0 +1,85 @@
|
||||
# Create Coding Feature
|
||||
|
||||
Generate code changes to an existing coding project using AI.
|
||||
|
||||
## Installation
|
||||
|
||||
After installing the `code_helper` binary:
|
||||
|
||||
```bash
|
||||
go install github.com/danielmiessler/fabric/plugins/tools/code_helper@latest
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
The create_coding_feature allows you to apply AI-suggested code changes directly to your project files. Use it like this:
|
||||
|
||||
```bash
|
||||
code_helper [project_directory] "[instructions for code changes]" | fabric --pattern create_coding_feature
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
```bash
|
||||
code_helper . "Create a simple Hello World C program in file main.c" | fabric --pattern create_coding_feature
|
||||
```
|
||||
|
||||
## How It Works
|
||||
|
||||
1. `code_helper` scans your project directory and creates a JSON representation
|
||||
2. The AI model analyzes your project structure and instructions
|
||||
3. AI generates file changes in a standard format
|
||||
4. Fabric parses these changes and prompts you to confirm
|
||||
5. If confirmed, changes are applied to your project files
|
||||
|
||||
## Example Workflow
|
||||
|
||||
```bash
|
||||
# Request AI to create a Hello World program
|
||||
code_helper . "Create a simple Hello World C program in file main.c" | fabric --pattern create_coding_feature
|
||||
|
||||
# Review the changes made to your project
|
||||
git diff
|
||||
|
||||
# Run/test the code
|
||||
make check
|
||||
|
||||
# If satisfied, commit the changes
|
||||
git add <changed files>
|
||||
git commit -s -m "Add Hello World program"
|
||||
```
|
||||
|
||||
### Security Enhancement Example
|
||||
|
||||
```bash
|
||||
code_helper . "Ensure that all user input is validated and sanitized before being used in the program." | fabric --pattern create_coding_feature
|
||||
git diff
|
||||
make check
|
||||
git add <changed files>
|
||||
git commit -s -m "Security fixes: Input validation"
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
- **Always run from project root**: File changes are applied relative to your current directory
|
||||
- **Use with version control**: It's highly recommended to use this feature in a clean git repository so you can review and revert
|
||||
changes. You will *not* be asked to approve each change.
|
||||
|
||||
## Security Features
|
||||
|
||||
- Path validation to prevent directory traversal attempts
|
||||
- File size limits to prevent excessive file generation
|
||||
- Operation validation (only create/update operations allowed)
|
||||
- User confirmation required before applying changes
|
||||
|
||||
## Suggestions for Future Improvements
|
||||
|
||||
- Add a dry-run mode to show changes without applying them
|
||||
- Enhance reporting with detailed change summaries
|
||||
- Support for file deletions with safety checks
|
||||
- Add configuration options for project-specific rules
|
||||
- Provide rollback capability for applied changes
|
||||
- Add support for project-specific validation rules
|
||||
- Enhance script generation with conditional logic
|
||||
- Include detailed logging for API responses
|
||||
- Consider adding a GUI for ease of use
|
||||
117
data/patterns/create_coding_feature/system.md
Normal file
117
data/patterns/create_coding_feature/system.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# IDENTITY and PURPOSE
|
||||
|
||||
You are an elite programmer. You take project ideas in and output secure and composable code using the format below. You always use the latest technology and best practices.
|
||||
|
||||
Take a deep breath and think step by step about how to best accomplish this goal using the following steps.
|
||||
|
||||
Input is a JSON file with the following format:
|
||||
|
||||
Example input:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"type": "directory",
|
||||
"name": ".",
|
||||
"contents": [
|
||||
{
|
||||
"type": "file",
|
||||
"name": "README.md",
|
||||
"content": "This is the README.md file content"
|
||||
},
|
||||
{
|
||||
"type": "file",
|
||||
"name": "system.md",
|
||||
"content": "This is the system.md file contents"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "report",
|
||||
"directories": 1,
|
||||
"files": 5
|
||||
},
|
||||
{
|
||||
"type": "instructions",
|
||||
"name": "code_change_instructions",
|
||||
"details": "Update README and refactor main.py"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
The object with `"type": "instructions"`, and field `"details"` contains the
|
||||
for the instructions for the suggested code changes. The `"name"` field is always
|
||||
`"code_change_instructions"`
|
||||
|
||||
The `"details"` field above, with type `"instructions"` contains the instructions for the suggested code changes.
|
||||
|
||||
## File Management Interface Instructions
|
||||
|
||||
You have access to a powerful file management system with the following capabilities:
|
||||
|
||||
### File Creation and Modification
|
||||
|
||||
- Use the **EXACT** JSON format below to define files that you want to be changed
|
||||
- If the file listed does not exist, it will be created
|
||||
- If a directory listed does not exist, it will be created
|
||||
- If the file already exists, it will be overwritten
|
||||
- It is **not possible** to delete files
|
||||
|
||||
```plaintext
|
||||
__CREATE_CODING_FEATURE_FILE_CHANGES__
|
||||
[
|
||||
{
|
||||
"operation": "create",
|
||||
"path": "README.md",
|
||||
"content": "This is the new README.md file content"
|
||||
},
|
||||
{
|
||||
"operation": "update",
|
||||
"path": "src/main.c",
|
||||
"content": "int main(){return 0;}"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### Important Guidelines
|
||||
|
||||
- Always use relative paths from the project root
|
||||
- Provide complete, functional code when creating or modifying files
|
||||
- Be precise and concise in your file operations
|
||||
- Never create files outside of the project root
|
||||
|
||||
### Constraints
|
||||
|
||||
- Do not attempt to read or modify files outside the project root directory.
|
||||
- Ensure code follows best practices and is production-ready.
|
||||
- Handle potential errors gracefully in your code suggestions.
|
||||
- Do not trust external input to applications, assume users are malicious.
|
||||
|
||||
### Workflow
|
||||
|
||||
1. Analyze the user's request
|
||||
2. Determine necessary file operations
|
||||
3. Provide clear, executable file creation/modification instructions
|
||||
4. Explain the purpose and functionality of proposed changes
|
||||
|
||||
## Output Sections
|
||||
|
||||
- Output a summary of the file changes
|
||||
- Output directory and file changes according to File Management Interface Instructions, in a json array marked by `__CREATE_CODING_FEATURE_FILE_CHANGES__`
|
||||
- Be exact in the `__CREATE_CODING_FEATURE_FILE_CHANGES__` section, and do not deviate from the proposed JSON format.
|
||||
- **never** omit the `__CREATE_CODING_FEATURE_FILE_CHANGES__` section.
|
||||
- If the proposed changes change how the project is built and installed, document these changes in the projects README.md
|
||||
- Implement build configurations changes if needed, prefer ninja if nothing already exists in the project, or is otherwise specified.
|
||||
- Document new dependencies according to best practices for the language used in the project.
|
||||
- Do not output sections that were not explicitly requested.
|
||||
|
||||
## Output Instructions
|
||||
|
||||
- Create the output using the formatting above
|
||||
- Do not output warnings or notes—just the requested sections.
|
||||
- Do not repeat items in the output sections
|
||||
- Be open to suggestions and output file system changes according to the JSON API described above
|
||||
- Output code that has comments for every step
|
||||
- Do not use deprecated features
|
||||
|
||||
## INPUT
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user