aigency 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/README.md +12 -13
  4. data/lib/aigency/aigent/current_time.rb +33 -0
  5. data/lib/aigency/aigent/shell.rb +108 -0
  6. data/lib/aigency/aigent.rb +117 -65
  7. data/lib/aigency/delegator.rb +11 -0
  8. data/lib/aigency/plugin/shell.rb +11 -0
  9. data/lib/aigency/plugin.rb +39 -0
  10. data/lib/aigency/rake.rb +13 -0
  11. data/lib/aigency/sandbox/exec.rb +21 -0
  12. data/lib/aigency/sandbox.rb +22 -0
  13. data/lib/aigency/shell.rb +5 -5
  14. data/lib/aigency/tempdir/helpers.rb +15 -0
  15. data/lib/aigency/tempdir/list.rb +17 -0
  16. data/lib/aigency/tempdir/read.rb +32 -0
  17. data/lib/aigency/tempdir/size.rb +27 -0
  18. data/lib/aigency/tempdir/write.rb +28 -0
  19. data/lib/aigency/tempdir.rb +19 -0
  20. data/lib/aigency/tool.rb +5 -0
  21. data/lib/aigency/usability.rb +1 -0
  22. data/lib/aigency/version.rb +1 -1
  23. data/lib/aigency/workspace/cat.rb +11 -0
  24. data/lib/aigency/workspace/cmd.rb +59 -0
  25. data/lib/aigency/workspace/copy_tempdir_file.rb +28 -0
  26. data/lib/aigency/workspace/cp.rb +11 -0
  27. data/lib/aigency/workspace/diff.rb +11 -0
  28. data/lib/aigency/workspace/grep.rb +15 -0
  29. data/lib/aigency/workspace/head.rb +11 -0
  30. data/lib/aigency/workspace/helpers.rb +40 -3
  31. data/lib/aigency/workspace/ls.rb +11 -0
  32. data/lib/aigency/workspace/mkdir.rb +11 -0
  33. data/lib/aigency/workspace/mv.rb +11 -0
  34. data/lib/aigency/workspace/rm.rb +11 -0
  35. data/lib/aigency/workspace/tail.rb +11 -0
  36. data/lib/aigency/workspace/wc.rb +13 -0
  37. data/lib/aigency/workspace/write.rb +36 -0
  38. data/lib/aigency/workspace.rb +20 -7
  39. data/lib/aigency.rb +16 -13
  40. data/scaffold/{Rakefile → aigent/aigent.rake} +2 -11
  41. data/scaffold/enlist/.env.example +4 -0
  42. data/scaffold/{.gitignore → enlist/.gitignore} +1 -0
  43. data/scaffold/{Gemfile → enlist/Gemfile} +1 -1
  44. data/scaffold/enlist/README.md +90 -0
  45. data/scaffold/enlist/Rakefile +9 -0
  46. data/scaffold/enlist/bin/aigent +11 -0
  47. data/scaffold/{config → enlist/config}/schedule.rb +5 -0
  48. data/scaffold/sandbox/Dockerfile +37 -0
  49. data/scaffold/sandbox/docker-compose.yml +37 -0
  50. data/scaffold/sandbox/squid.conf +25 -0
  51. data/scaffold/sandbox/ssh_config +2 -0
  52. metadata +114 -16
  53. data/lib/aigency/tools.rb +0 -55
  54. data/lib/aigency/workspace/directory_deleter.rb +0 -23
  55. data/lib/aigency/workspace/directory_reader.rb +0 -33
  56. data/lib/aigency/workspace/file_deleter.rb +0 -22
  57. data/lib/aigency/workspace/file_reader.rb +0 -27
  58. data/lib/aigency/workspace/file_writer.rb +0 -26
  59. data/scaffold/README.md +0 -74
  60. data/scaffold/config/aigent.yml +0 -6
  61. /data/scaffold/{IDENTITY.md → enlist/IDENTITY.md} +0 -0
@@ -0,0 +1,90 @@
1
+ # Your Aigent
2
+
3
+ An aigent (AI agent) is an intelligent assistant powered by language models through OpenAI-compatible APIs. It can read and write files in its private workspace and perform scheduled tasks on your behalf.
4
+
5
+ ## Configuration
6
+
7
+ ### 1. Install dependencies
8
+
9
+ ```bash
10
+ bundle install
11
+ ```
12
+
13
+ ### 2. Configure OpenAI API Connection
14
+
15
+ Copy the example env file:
16
+
17
+ ```bash
18
+ cp .env.example .env
19
+ ```
20
+
21
+ Modify the `OPENAI_API_BASE` and `OPENAI_API_KEY` as needed. If you're using a local AI server or any other provider that is compatible with OpenAI, you can set the OPENAI_API_BASE config option to point there instead (e.g., `http://localhost:8080/v1`).
22
+
23
+ ### 3. Define the Aigent's Personality
24
+
25
+ Edit `IDENTITY.md` to define how your aigent should behave:
26
+
27
+ ```markdown
28
+ You are a professional assistant named Alex. You respond in a friendly but concise manner.
29
+ ```
30
+
31
+ This file sets the foundation for all the aigent's responses.
32
+
33
+ ### 4. Configure Plugins
34
+
35
+ Aigency ships with two plugins: `workspace` and `sandbox`. The `workspace` plugin is enabled by default. It's recommended that you use one or the other, but not both.
36
+
37
+ The `workspace` plugin gives your aigent a directory where it can manage its own files.
38
+
39
+ The `sandbox` plugin provides a container where the aigent can not only manage files, but also run commands and scripts.
40
+
41
+ The `workspace` plugin is sufficient for many aigents. Switch to `sandbox` if you need your aigent to perform software development or other complex tasks.
42
+
43
+ ### 5. Run setup
44
+
45
+ ```bash
46
+ rake setup
47
+ ```
48
+
49
+ ## Usage
50
+
51
+ ### Interactive Mode
52
+
53
+ Talk to your aigent using the `say` command:
54
+
55
+ ```bash
56
+ bin/aigent say "How many fibers are intertwined in a shredded wheat biscuit?"
57
+ ```
58
+
59
+ ### Scheduling Tasks
60
+
61
+ Aigents use the `whenever` gem for scheduling. Example of a scheduled task:
62
+
63
+ ```ruby
64
+ # config/schedule.rb
65
+
66
+ # Every day at 9am, the aigent will run the prompt in the DAILY_TASKS.md file
67
+ every 1.day, at: '9am' do
68
+ rake 'load[DAILY_TASKS.md]'
69
+ end
70
+ ```
71
+
72
+ Add the scheduled tasks to your crontab:
73
+
74
+ ```bash
75
+ bundle exec whenever --update-crontab
76
+ ```
77
+
78
+ (Note: the `whenever` gem does not work on Windows.)
79
+
80
+ ### Using the Sandbox
81
+
82
+ If you enable the `sandbox` plugin, you'll need to start the container:
83
+
84
+ ```bash
85
+ docker compose up -d
86
+ ```
87
+
88
+ The sandbox app is initialized with an egress that only allows network access to domains that are whitelisted in `squid.conf`. See the `http_targets` and `ssh_targets` ACLs.
89
+
90
+ Manage the sandbox user's SSH configuration in `data/sandbox_ssh`.
@@ -0,0 +1,9 @@
1
+ require "bundler/setup"
2
+ require 'dotenv/load'
3
+ Bundler.require(:default)
4
+
5
+ Aigency::Rake.define('.')
6
+
7
+ # Run `rake --tasks` for a list of tasks provided by aigent plugins.
8
+
9
+ # Custom rake tasks can be added below.
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # turn off warning diagnostics from Ruby
5
+ $VERBOSE=nil
6
+
7
+ require "bundler/setup"
8
+ require 'dotenv/load'
9
+ Bundler.require(:default)
10
+
11
+ Aigency::Aigent::Shell.start(ARGV)
@@ -19,6 +19,11 @@
19
19
 
20
20
  # Learn more: http://github.com/javan/whenever
21
21
 
22
+ job_type :rake, "cd :path && :environment_variable=:environment :bundle_command rake :task :output"
23
+
24
+ set :output, File.join(Dir.pwd, 'data', 'log', 'cron.log')
25
+
26
+ # Example job: run a prompt from a file named `DAILY.md` once a day
22
27
  # every 1.day do
23
28
  # rake "load[DAILY.md]"
24
29
  # end
@@ -0,0 +1,37 @@
1
+ FROM alpine:latest
2
+
3
+ RUN apk update && apk upgrade && apk add --no-cache \
4
+ autoconf \
5
+ bash \
6
+ bison \
7
+ build-base \
8
+ curl \
9
+ git \
10
+ libffi-dev \
11
+ linux-headers \
12
+ mise \
13
+ musl-dev \
14
+ netcat-openbsd \
15
+ nodejs \
16
+ openssh \
17
+ openssl \
18
+ openssl-dev \
19
+ perl \
20
+ pkgconf \
21
+ python3 \
22
+ tzdata \
23
+ xz \
24
+ yaml-dev \
25
+ zlib-dev
26
+
27
+ RUN adduser -D -h /sandbox user \
28
+ && mkdir -p /opt/mise \
29
+ && chown -R user:user /opt/mise
30
+ USER user
31
+ ENV MISE_DATA_DIR=/opt/mise \
32
+ MISE_CONFIG_DIR=/opt/mise/config \
33
+ MISE_TRUSTED_CONFIG_PATHS=/sandbox \
34
+ PATH=/opt/mise/shims:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
35
+ RUN mise use -g ruby@3.4 && mise install --yes
36
+
37
+ CMD ["sleep", "infinity"]
@@ -0,0 +1,37 @@
1
+ services:
2
+ app:
3
+ build:
4
+ context: .
5
+ dockerfile: ./sandbox/Dockerfile
6
+ networks: [sandbox]
7
+ restart: unless-stopped
8
+ depends_on:
9
+ - egress
10
+ volumes:
11
+ - ./data/sandbox:/sandbox
12
+ - ./data/sandbox_ssh:/sandbox/.ssh
13
+ working_dir: /sandbox
14
+ environment:
15
+ - http_proxy=http://egress:3128
16
+ - https_proxy=http://egress:3128
17
+ - HTTP_PROXY=http://egress:3128
18
+ - HTTPS_PROXY=http://egress:3128
19
+ - no_proxy=localhost,127.0.0.1,::1
20
+ - NO_PROXY=localhost,127.0.0.1,::1
21
+ command: ["sleep", "infinity"]
22
+
23
+ egress:
24
+ image: ubuntu/squid
25
+ networks: [sandbox, outside]
26
+ volumes:
27
+ - ./sandbox/squid.conf:/etc/squid/squid.conf:ro
28
+
29
+ networks:
30
+ sandbox:
31
+ internal: true
32
+ driver: bridge
33
+ driver_opts:
34
+ com.docker.network.bridge.gateway_mode_ipv4: isolated
35
+ com.docker.network.bridge.gateway_mode_ipv6: isolated
36
+ outside:
37
+ driver: bridge
@@ -0,0 +1,25 @@
1
+ # Allowlist-only forward proxy.
2
+ # NOTE: this file deliberately does NOT `include /etc/squid/conf.d/*`, so the
3
+ # rules Ubuntu ships in the image can't silently widen the allowlist.
4
+
5
+ http_port 3128
6
+ visible_hostname egress
7
+ cache deny all # forward proxy only, nothing to disk
8
+ access_log daemon:/var/log/squid/access.log
9
+ logfile_rotate 0
10
+ forwarded_for off # don't leak the container's IP downstream
11
+
12
+ acl SSL_ports port 443
13
+ acl Safe_ports port 80 443
14
+ acl http_targets dstdomain \
15
+ www.example.com
16
+
17
+ acl SSH_ports port 22
18
+ acl ssh_targets dstdomain \
19
+ ssh.example.com
20
+
21
+ http_access allow CONNECT ssh_targets SSH_ports
22
+ http_access deny !Safe_ports
23
+ http_access deny CONNECT !SSL_ports
24
+ http_access allow http_targets
25
+ http_access deny all
@@ -0,0 +1,2 @@
1
+ Host *
2
+ ProxyCommand nc -X connect -x egress:3128 %h %p
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aigency
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fred Snyder
@@ -9,6 +9,34 @@ bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: dotenv
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '3.2'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '3.2'
26
+ - !ruby/object:Gem::Dependency
27
+ name: faraday
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '2.15'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '2.15'
12
40
  - !ruby/object:Gem::Dependency
13
41
  name: fileutils
14
42
  requirement: !ruby/object:Gem::Requirement
@@ -29,14 +57,14 @@ dependencies:
29
57
  requirements:
30
58
  - - "~>"
31
59
  - !ruby/object:Gem::Version
32
- version: '1.15'
60
+ version: '2.1'
33
61
  type: :runtime
34
62
  prerelease: false
35
63
  version_requirements: !ruby/object:Gem::Requirement
36
64
  requirements:
37
65
  - - "~>"
38
66
  - !ruby/object:Gem::Version
39
- version: '1.15'
67
+ version: '2.1'
40
68
  - !ruby/object:Gem::Dependency
41
69
  name: thor
42
70
  requirement: !ruby/object:Gem::Requirement
@@ -51,6 +79,48 @@ dependencies:
51
79
  - - "~>"
52
80
  - !ruby/object:Gem::Version
53
81
  version: '1.5'
82
+ - !ruby/object:Gem::Dependency
83
+ name: rake
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '13.0'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '13.0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: rspec
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '3.0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '3.0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: simplecov
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '0.21'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '0.21'
54
124
  email:
55
125
  - fsnyder@castwide.com
56
126
  executables:
@@ -64,25 +134,53 @@ files:
64
134
  - exe/aigency
65
135
  - lib/aigency.rb
66
136
  - lib/aigency/aigent.rb
137
+ - lib/aigency/aigent/current_time.rb
138
+ - lib/aigency/aigent/shell.rb
139
+ - lib/aigency/delegator.rb
140
+ - lib/aigency/plugin.rb
141
+ - lib/aigency/plugin/shell.rb
142
+ - lib/aigency/rake.rb
143
+ - lib/aigency/sandbox.rb
144
+ - lib/aigency/sandbox/exec.rb
67
145
  - lib/aigency/shell.rb
146
+ - lib/aigency/tempdir.rb
147
+ - lib/aigency/tempdir/helpers.rb
148
+ - lib/aigency/tempdir/list.rb
149
+ - lib/aigency/tempdir/read.rb
150
+ - lib/aigency/tempdir/size.rb
151
+ - lib/aigency/tempdir/write.rb
68
152
  - lib/aigency/tool.rb
69
- - lib/aigency/tools.rb
70
153
  - lib/aigency/usability.rb
71
154
  - lib/aigency/version.rb
72
155
  - lib/aigency/workspace.rb
73
- - lib/aigency/workspace/directory_deleter.rb
74
- - lib/aigency/workspace/directory_reader.rb
75
- - lib/aigency/workspace/file_deleter.rb
76
- - lib/aigency/workspace/file_reader.rb
77
- - lib/aigency/workspace/file_writer.rb
156
+ - lib/aigency/workspace/cat.rb
157
+ - lib/aigency/workspace/cmd.rb
158
+ - lib/aigency/workspace/copy_tempdir_file.rb
159
+ - lib/aigency/workspace/cp.rb
160
+ - lib/aigency/workspace/diff.rb
161
+ - lib/aigency/workspace/grep.rb
162
+ - lib/aigency/workspace/head.rb
78
163
  - lib/aigency/workspace/helpers.rb
79
- - scaffold/.gitignore
80
- - scaffold/Gemfile
81
- - scaffold/IDENTITY.md
82
- - scaffold/README.md
83
- - scaffold/Rakefile
84
- - scaffold/config/aigent.yml
85
- - scaffold/config/schedule.rb
164
+ - lib/aigency/workspace/ls.rb
165
+ - lib/aigency/workspace/mkdir.rb
166
+ - lib/aigency/workspace/mv.rb
167
+ - lib/aigency/workspace/rm.rb
168
+ - lib/aigency/workspace/tail.rb
169
+ - lib/aigency/workspace/wc.rb
170
+ - lib/aigency/workspace/write.rb
171
+ - scaffold/aigent/aigent.rake
172
+ - scaffold/enlist/.env.example
173
+ - scaffold/enlist/.gitignore
174
+ - scaffold/enlist/Gemfile
175
+ - scaffold/enlist/IDENTITY.md
176
+ - scaffold/enlist/README.md
177
+ - scaffold/enlist/Rakefile
178
+ - scaffold/enlist/bin/aigent
179
+ - scaffold/enlist/config/schedule.rb
180
+ - scaffold/sandbox/Dockerfile
181
+ - scaffold/sandbox/docker-compose.yml
182
+ - scaffold/sandbox/squid.conf
183
+ - scaffold/sandbox/ssh_config
86
184
  - sig/aigency.rbs
87
185
  licenses: []
88
186
  metadata: {}
data/lib/aigency/tools.rb DELETED
@@ -1,55 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Aigency
4
- module Tools
5
- # @return [Array<Class<Tool>>]
6
- def self.registry
7
- @registry ||= []
8
- end
9
-
10
- # @return [Hash{String => String}]
11
- def self.config_map
12
- @configs ||= {}
13
- end
14
-
15
- # @return [Array<String>]
16
- def self.directories
17
- @directories ||= []
18
- end
19
-
20
- # Register a tool.
21
- #
22
- # @param klass [Class<Tool>]
23
- # @return [void]
24
- def self.register klass
25
- registry.push klass
26
- end
27
-
28
- # Define a default configuration.
29
- #
30
- # @param name [String] The name of the config section
31
- # @param text [String] YAML-formatted config data
32
- # @return [void]
33
- def self.configure name, text
34
- config_map[name] = text
35
- end
36
-
37
- # Define directories to be created relative to an aigent's root.
38
- #
39
- def self.mkdir_p *paths
40
- directories.concat paths
41
- end
42
- end
43
-
44
- Tools.configure 'aigent', <<~EOF
45
- name: an Aigent
46
- openai_api_base: https://api.openai.com/v1
47
- openai_api_key: CHANGE_ME
48
- require:
49
- - aigency/email
50
- - aigency/wikipedia
51
- - aigency/workspace
52
- EOF
53
-
54
- Tools.mkdir_p 'data/chats', 'data/log'
55
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Aigency
4
- module Workspace
5
- class DirectoryDeleter < Tool
6
- include Helpers
7
-
8
- desc "Delete a directory and all of its contents from your private workspace"
9
-
10
- def execute(directory_name:)
11
- aigent.log.puts "[Workspace::DirectoryDeleter] #{directory_name}"
12
-
13
- resolved = expand_to_workspace(directory_name)
14
- FileUtils.rm_rf(resolved)
15
- { dirname: directory_name, success: true }
16
- rescue StandardError => e
17
- { success: false, error: "[#{e.class}] #{e.message}"}
18
- end
19
- end
20
- end
21
- end
22
-
23
- Aigency::Tools.register Aigency::Workspace::DirectoryDeleter
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Aigency
4
- module Workspace
5
- class DirectoryReader < Tool
6
- include Helpers
7
-
8
- desc "Get the contents of a directory from your private workspace"
9
-
10
- def execute(directory_name:)
11
- aigent.log.puts "[Workspace::DirectoryReader] Reading #{directory_name}"
12
- resolved = expand_to_workspace(directory_name)
13
- if File.directory?(resolved)
14
- {
15
- directory: directory_name,
16
- success: true,
17
- entries: Dir.entries(resolved)[2..]
18
- }
19
- else
20
- {
21
- directory: directory_name,
22
- success: false,
23
- error: "Not a directory"
24
- }
25
- end
26
- rescue StandardError => e
27
- { success: false, error: "[#{e.class}] #{e.message}" }
28
- end
29
- end
30
- end
31
- end
32
-
33
- Aigency::Tools.register Aigency::Workspace::DirectoryReader
@@ -1,22 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Aigency
4
- module Workspace
5
- class FileDeleter < Tool
6
- include Helpers
7
-
8
- desc "Delete a file from your private workspace"
9
-
10
- def execute(filename:)
11
- aigent.log.puts "[Workspace::FileDeleter] Deleting file #{filename}"
12
- resolved = expand_to_workspace(filename)
13
- File.delete resolved
14
- { filename: filename, success: true }
15
- rescue StandardError => e
16
- { success: false, error: "[#{e.class}] #{e.message}" }
17
- end
18
- end
19
- end
20
- end
21
-
22
- Aigency::Tools.register Aigency::Workspace::FileDeleter
@@ -1,27 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Aigency
4
- module Workspace
5
- class FileReader < Tool
6
- include Helpers
7
-
8
- desc "Read a file from your private workspace"
9
-
10
- def execute(filename:)
11
- aigent.log.puts "[Workspace::FileReader] Reading #{filename}"
12
-
13
- resolved = expand_to_workspace(filename)
14
-
15
- {
16
- success: true,
17
- filename: filename,
18
- content: File.read(resolved)
19
- }
20
- rescue StandardError => e
21
- { success: false, error: "[#{e.class}] #{e.message}"}
22
- end
23
- end
24
- end
25
- end
26
-
27
- Aigency::Tools.register Aigency::Workspace::FileReader
@@ -1,26 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'fileutils'
4
-
5
- module Aigency
6
- module Workspace
7
- class FileWriter < Tool
8
- include Helpers
9
-
10
- desc "Write a file to your private workspace"
11
-
12
- def execute(filename:, content:)
13
- aigent.log.puts "[Workspace::FileWriter] Writing #{filename}"
14
-
15
- resolved = expand_to_workspace(filename)
16
- FileUtils.mkdir_p File.dirname(resolved)
17
- File.write resolved, content
18
- return { filename: filename, success: true }
19
- rescue StandardError => e
20
- { success: false, error: "[#{e.class}] #{e.message}" }
21
- end
22
- end
23
- end
24
- end
25
-
26
- Aigency::Tools.register Aigency::Workspace::FileWriter
data/scaffold/README.md DELETED
@@ -1,74 +0,0 @@
1
- # Your Aigent
2
-
3
- An aigent (AI agent) is an intelligent assistant powered by language models through OpenAI-compatible APIs. It can read and write files in its private workspace and perform scheduled tasks on your behalf.
4
-
5
- ## Configuration
6
-
7
- ### Install dependencies
8
-
9
- ```bash
10
- bundle install
11
- ```
12
-
13
- ### Initial setup
14
-
15
- ```bash
16
- rake setup
17
- ```
18
-
19
- ### 1. Configure the Aigent
20
-
21
- Configure the aigent's settings in `config/aigent.yml`.
22
-
23
- #### OpenAI-Compatible Providers
24
-
25
- If you're using a local AI server or any other provider that is compatible with OpenAI, you can set the OPENAI_API_BASE config option to point there instead (e.g., `http://localhost:8080/v1`).
26
-
27
- ### 2. Define the Aigent's Personality
28
-
29
- Edit `IDENTITY.md` to define how your aigent should behave:
30
-
31
- ```markdown
32
- You are a professional assistant named Alex. You respond in a friendly but concise manner.
33
- ```
34
-
35
- This file sets the foundation for all the aigent's responses.
36
-
37
- ## Usage
38
-
39
- ### Interactive Mode
40
-
41
- Talk to your aigent using the Rake task:
42
-
43
- ```bash
44
- rake say["Tell me about project progress"]
45
- ```
46
-
47
- ### The Workspace
48
-
49
- Your aigent has read/write access to everything in the `data/workspace` directory.
50
-
51
- ### Scheduling Tasks
52
-
53
- The project includes the `whenever` gem for scheduling. Example of a scheduled task:
54
-
55
- ```ruby
56
- # config/schedule.rb
57
-
58
- # Every day at 9am, the aigent will run the prompt in the DAILY_TASKS.md file
59
- every 1.day, at: '9am' do
60
- rake 'load[DAILY_TASKS.md]'
61
- end
62
- ```
63
-
64
- Add the scheduled tasks to your crontab:
65
-
66
- ```bash
67
- bundle exec whenever --update-crontab
68
- ```
69
-
70
- (Note: the `whenever` gem does not work on Windows.)
71
-
72
- ## Aigent Tools
73
-
74
- You can give your aigent more functionality by installing additional tools. It ships with the `Workspace` tool, which gives it full read/write access to the `data/workspace` directory.
@@ -1,6 +0,0 @@
1
- name: an Aigent
2
- openai_api_base: https://api.openai.com/v1
3
- openai_api_key: CHANGE_ME
4
- # max_tokens: 65536
5
- # require:
6
- # - aigency-example
File without changes